diff --git a/dom/clients/manager/ClientManagerService.cpp b/dom/clients/manager/ClientManagerService.cpp index 5c36340c9e9f..709ecf0ee367 100644 --- a/dom/clients/manager/ClientManagerService.cpp +++ b/dom/clients/manager/ClientManagerService.cpp @@ -107,6 +107,10 @@ RefPtr OnShutdown() { } // anonymous namespace +ClientManagerService::FutureClientSourceParent::FutureClientSourceParent( + const IPCClientInfo& aClientInfo) + : mPrincipalInfo(aClientInfo.principalInfo()) {} + ClientManagerService::ClientManagerService() : mShutdown(false) { AssertIsOnBackgroundThread(); diff --git a/dom/clients/manager/ClientManagerService.h b/dom/clients/manager/ClientManagerService.h index 9f247b667427..eed2cb26c207 100644 --- a/dom/clients/manager/ClientManagerService.h +++ b/dom/clients/manager/ClientManagerService.h @@ -6,7 +6,12 @@ #ifndef _mozilla_dom_ClientManagerService_h #define _mozilla_dom_ClientManagerService_h +#include "ClientHandleParent.h" #include "ClientOpPromise.h" +#include "mozilla/Assertions.h" +#include "mozilla/HashTable.h" +#include "mozilla/MozPromise.h" +#include "mozilla/Variant.h" #include "nsDataHashtable.h" namespace mozilla { @@ -28,6 +33,55 @@ class ContentParent; // browser. This service runs on the PBackground thread. To interact // it with it please use the ClientManager and ClientHandle classes. class ClientManagerService final { + // Placeholder type that represents a ClientSourceParent that may be created + // in the future (e.g. while a redirect chain is being resolved). + // + // Each FutureClientSourceParent has a promise that callbacks may be chained + // to; the promise will be resolved when the associated ClientSourceParent is + // created or rejected when it's known that it'll never be created. + class FutureClientSourceParent { + public: + explicit FutureClientSourceParent(const IPCClientInfo& aClientInfo); + + const mozilla::ipc::PrincipalInfo& PrincipalInfo() const { + return mPrincipalInfo; + } + + already_AddRefed Promise() { + return mPromiseHolder.Ensure(__func__); + } + + void ResolvePromiseIfExists(ClientSourceParent* aSource) { + MOZ_ASSERT(aSource); + mPromiseHolder.ResolveIfExists(aSource, __func__); + } + + void RejectPromiseIfExists(const CopyableErrorResult& aRv) { + MOZ_ASSERT(aRv.Failed()); + mPromiseHolder.RejectIfExists(aRv, __func__); + } + + private: + const mozilla::ipc::PrincipalInfo mPrincipalInfo; + MozPromiseHolder mPromiseHolder; + }; + + using SourceTableEntry = + Variant; + + struct nsIDHasher { + using Key = nsID; + using Lookup = Key; + + static HashNumber hash(const Lookup& aLookup) { + return HashBytes(&aLookup, sizeof(Lookup)); + } + + static bool match(const Key& aKey, const Lookup& aLookup) { + return aKey.Equals(aLookup); + } + }; + // Store the ClientSourceParent objects in a hash table. We want to // optimize for insertion, removal, and lookup by UUID. nsDataHashtable mSourceTable; diff --git a/dom/clients/manager/moz.build b/dom/clients/manager/moz.build index e2be201898f4..1dde94fc4b39 100644 --- a/dom/clients/manager/moz.build +++ b/dom/clients/manager/moz.build @@ -7,6 +7,7 @@ EXPORTS.mozilla.dom += [ 'ClientChannelHelper.h', 'ClientHandle.h', + 'ClientHandleParent.h', 'ClientInfo.h', 'ClientIPCUtils.h', 'ClientManager.h',