From 5012cc0f5df2e56c03f95324871683afabc8b140 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 30 Mar 2020 14:53:46 -0400 Subject: [PATCH] Backed out 6 changesets (bug 1584007) for causing bug 1625227. Backed out changeset c626a363823e (bug 1584007) Backed out changeset 0d130a64b0f5 (bug 1584007) Backed out changeset 8ca43f80bdd2 (bug 1584007) Backed out changeset 00eda7b39a13 (bug 1584007) Backed out changeset ac2765b4b4ec (bug 1584007) Backed out changeset 24deb3d46783 (bug 1584007) --HG-- extra : amend_source : 9431aa82b4a472f0c60dcf1368817fe7c658bcf5 --- dom/clients/manager/ClientChannelHelper.cpp | 46 +--- dom/clients/manager/ClientHandleParent.cpp | 44 ++-- dom/clients/manager/ClientHandleParent.h | 14 +- dom/clients/manager/ClientManager.cpp | 30 --- dom/clients/manager/ClientManager.h | 23 -- dom/clients/manager/ClientManagerParent.cpp | 24 -- dom/clients/manager/ClientManagerParent.h | 6 - dom/clients/manager/ClientManagerService.cpp | 225 +++++-------------- dom/clients/manager/ClientManagerService.h | 88 ++------ dom/clients/manager/PClientManager.ipdl | 3 - dom/clients/manager/moz.build | 1 - 11 files changed, 107 insertions(+), 397 deletions(-) diff --git a/dom/clients/manager/ClientChannelHelper.cpp b/dom/clients/manager/ClientChannelHelper.cpp index 3f8a25e4cbce..b6dace1fde29 100644 --- a/dom/clients/manager/ClientChannelHelper.cpp +++ b/dom/clients/manager/ClientChannelHelper.cpp @@ -163,9 +163,9 @@ class ClientChannelHelper : public nsIInterfaceRequestor, NS_DECL_ISUPPORTS - virtual void CreateClientForPrincipal(nsILoadInfo* aLoadInfo, - nsIPrincipal* aPrincipal, - nsISerialEventTarget* aEventTarget) { + static void CreateClientForPrincipal(nsILoadInfo* aLoadInfo, + nsIPrincipal* aPrincipal, + nsISerialEventTarget* aEventTarget) { // Create the new ClientSource. This should only happen for window // Clients since support cross-origin redirects are blocked by the // same-origin security policy. @@ -181,41 +181,16 @@ NS_IMPL_ISUPPORTS(ClientChannelHelper, nsIInterfaceRequestor, nsIChannelEventSink); class ClientChannelHelperParent final : public ClientChannelHelper { - ~ClientChannelHelperParent() { - // This requires that if a load completes, the associated ClientSource is - // created and registers itself before this ClientChannelHelperParent is - // destroyed. Otherwise, we may incorrectly "forget" a future ClientSource - // which will actually be created. - SetFutureSourceInfo(Nothing()); - } + ~ClientChannelHelperParent() = default; void CreateClient(nsILoadInfo* aLoadInfo, nsIPrincipal* aPrincipal) override { CreateClientForPrincipal(aLoadInfo, aPrincipal, mEventTarget); } - void SetFutureSourceInfo(Maybe&& aClientInfo) { - if (mRecentFutureSourceInfo) { - // No-op if the corresponding ClientSource has alrady been created, but - // it's not known if that's the case here. - ClientManager::ForgetFutureSource(*mRecentFutureSourceInfo); - } - - if (aClientInfo) { - Unused << NS_WARN_IF(!ClientManager::ExpectFutureSource(*aClientInfo)); - } - - mRecentFutureSourceInfo = std::move(aClientInfo); - } - - // Keep track of the most recent ClientInfo created which isn't backed by a - // ClientSource, which is used to notify ClientManagerService that the - // ClientSource won't ever actually be constructed. - Maybe mRecentFutureSourceInfo; - public: - void CreateClientForPrincipal(nsILoadInfo* aLoadInfo, - nsIPrincipal* aPrincipal, - nsISerialEventTarget* aEventTarget) override { + static void CreateClientForPrincipal(nsILoadInfo* aLoadInfo, + nsIPrincipal* aPrincipal, + nsISerialEventTarget* aEventTarget) { // If we're managing redirects in the parent, then we don't want // to create a new ClientSource (since those need to live with // the global), so just allocate a new ClientInfo/id and we can @@ -225,7 +200,6 @@ class ClientChannelHelperParent final : public ClientChannelHelper { ClientManager::CreateInfo(ClientType::Window, aPrincipal); if (reservedInfo) { aLoadInfo->SetReservedClientInfo(*reservedInfo); - SetFutureSourceInfo(std::move(reservedInfo)); } } ClientChannelHelperParent(nsIInterfaceRequestor* aOuter, @@ -320,12 +294,12 @@ nsresult AddClientChannelHelperInternal(nsIChannel* aChannel, rv = aChannel->GetNotificationCallbacks(getter_AddRefs(outerCallbacks)); NS_ENSURE_SUCCESS(rv, rv); - RefPtr helper = new T(outerCallbacks, aEventTarget); - if (initialClientInfo.isNothing() && reservedClientInfo.isNothing()) { - helper->CreateClientForPrincipal(loadInfo, channelPrincipal, aEventTarget); + T::CreateClientForPrincipal(loadInfo, channelPrincipal, aEventTarget); } + RefPtr helper = new T(outerCallbacks, aEventTarget); + // Only set the callbacks helper if we are able to reserve the client // successfully. rv = aChannel->SetNotificationCallbacks(helper); diff --git a/dom/clients/manager/ClientHandleParent.cpp b/dom/clients/manager/ClientHandleParent.cpp index 4325eead48f1..f46a2b169d91 100644 --- a/dom/clients/manager/ClientHandleParent.cpp +++ b/dom/clients/manager/ClientHandleParent.cpp @@ -27,13 +27,13 @@ void ClientHandleParent::ActorDestroy(ActorDestroyReason aReason) { mSource->DetachHandle(this); mSource = nullptr; } else { - if (!mSourcePromiseHolder.IsEmpty()) { - CopyableErrorResult rv; - rv.ThrowAbortError("Client aborted"); - mSourcePromiseHolder.Reject(rv, __func__); - } + mService->StopWaitingForSource(this, mClientId); + } - mSourcePromiseRequestHolder.DisconnectIfExists(); + if (mSourcePromise) { + CopyableErrorResult rv; + rv.ThrowAbortError("Client aborted"); + mSourcePromise->Reject(rv, __func__); } } @@ -63,20 +63,13 @@ ClientHandleParent::~ClientHandleParent() { MOZ_DIAGNOSTIC_ASSERT(!mSource); } void ClientHandleParent::Init(const IPCClientInfo& aClientInfo) { mClientId = aClientInfo.id(); mPrincipalInfo = aClientInfo.principalInfo(); + mSource = mService->FindSource(aClientInfo.id(), aClientInfo.principalInfo()); + if (!mSource) { + mService->WaitForSource(this, aClientInfo.id()); + return; + } - // Callbacks are disconnected in ActorDestroy, so capturing `this` is safe. - mService->FindSource(aClientInfo.id(), aClientInfo.principalInfo()) - ->Then( - GetCurrentThreadSerialEventTarget(), __func__, - [this](ClientSourceParent* aSource) { - mSourcePromiseRequestHolder.Complete(); - FoundSource(aSource); - }, - [this](const CopyableErrorResult&) { - mSourcePromiseRequestHolder.Complete(); - Unused << Send__delete__(this); - }) - ->Track(mSourcePromiseRequestHolder); + mSource->AttachHandle(this); } ClientSourceParent* ClientHandleParent::GetSource() const { return mSource; } @@ -86,17 +79,20 @@ RefPtr ClientHandleParent::EnsureSource() { return SourcePromise::CreateAndResolve(mSource, __func__); } - return mSourcePromiseHolder.Ensure(__func__); + if (!mSourcePromise) { + mSourcePromise = new SourcePromise::Private(__func__); + } + return mSourcePromise; } void ClientHandleParent::FoundSource(ClientSourceParent* aSource) { MOZ_ASSERT(aSource->Info().Id() == mClientId); if (!ClientMatchPrincipalInfo(aSource->Info().PrincipalInfo(), mPrincipalInfo)) { - if (!mSourcePromiseHolder.IsEmpty()) { + if (mSourcePromise) { CopyableErrorResult rv; rv.ThrowAbortError("Client aborted"); - mSourcePromiseHolder.Reject(rv, __func__); + mSourcePromise->Reject(rv, __func__); } Unused << Send__delete__(this); return; @@ -104,7 +100,9 @@ void ClientHandleParent::FoundSource(ClientSourceParent* aSource) { mSource = aSource; mSource->AttachHandle(this); - mSourcePromiseHolder.ResolveIfExists(aSource, __func__); + if (mSourcePromise) { + mSourcePromise->Resolve(aSource, __func__); + } } } // namespace dom diff --git a/dom/clients/manager/ClientHandleParent.h b/dom/clients/manager/ClientHandleParent.h index 720a69fa90d7..5f2a7e842b03 100644 --- a/dom/clients/manager/ClientHandleParent.h +++ b/dom/clients/manager/ClientHandleParent.h @@ -6,8 +6,6 @@ #ifndef _mozilla_dom_ClientHandleParent_h #define _mozilla_dom_ClientHandleParent_h -#include "mozilla/MozPromise.h" -#include "mozilla/RefPtr.h" #include "mozilla/dom/PClientHandleParent.h" #include "mozilla/ErrorResult.h" @@ -23,18 +21,16 @@ typedef MozPromise mService; - - // mSource and mSourcePromiseHolder are mutually exclusive. ClientSourceParent* mSource; - // Operations will wait on this promise while mSource is null. - MozPromiseHolder mSourcePromiseHolder; - - MozPromiseRequestHolder mSourcePromiseRequestHolder; - nsID mClientId; PrincipalInfo mPrincipalInfo; + // A promise for HandleOps that want to access our ClientSourceParent. + // Resolved once FoundSource is called and we have a ClientSourceParent + // available. + RefPtr mSourcePromise; + // PClientHandleParent interface mozilla::ipc::IPCResult RecvTeardown() override; diff --git a/dom/clients/manager/ClientManager.cpp b/dom/clients/manager/ClientManager.cpp index 277a76c61966..9bd3cd3334cb 100644 --- a/dom/clients/manager/ClientManager.cpp +++ b/dom/clients/manager/ClientManager.cpp @@ -227,36 +227,6 @@ WorkerPrivate* ClientManager::GetWorkerPrivate() const { return GetActor()->GetWorkerPrivate(); } -// Used to share logic between ExpectFutureSource and ForgetFutureSource. -/* static */ bool ClientManager::ExpectOrForgetFutureSource( - const ClientInfo& aClientInfo, - bool (PClientManagerChild::*aMethod)(const IPCClientInfo&)) { - bool rv = true; - - RefPtr mgr = ClientManager::GetOrCreateForCurrentThread(); - mgr->MaybeExecute( - [&](ClientManagerChild* aActor) { - if (!(aActor->*aMethod)(aClientInfo.ToIPC())) { - rv = false; - } - }, - [&] { rv = false; }); - - return rv; -} - -/* static */ bool ClientManager::ExpectFutureSource( - const ClientInfo& aClientInfo) { - return ExpectOrForgetFutureSource( - aClientInfo, &PClientManagerChild::SendExpectFutureClientSource); -} - -/* static */ bool ClientManager::ForgetFutureSource( - const ClientInfo& aClientInfo) { - return ExpectOrForgetFutureSource( - aClientInfo, &PClientManagerChild::SendForgetFutureClientSource); -} - // static void ClientManager::Startup() { MOZ_ASSERT(NS_IsMainThread()); diff --git a/dom/clients/manager/ClientManager.h b/dom/clients/manager/ClientManager.h index 93ecd4379b8b..cb8c4ccf0270 100644 --- a/dom/clients/manager/ClientManager.h +++ b/dom/clients/manager/ClientManager.h @@ -8,7 +8,6 @@ #include "mozilla/dom/ClientOpPromise.h" #include "mozilla/dom/ClientThing.h" -#include "mozilla/dom/PClientManagerChild.h" class nsIPrincipal; @@ -74,29 +73,7 @@ class ClientManager final : public ClientThing { // Private methods called by ClientSource mozilla::dom::WorkerPrivate* GetWorkerPrivate() const; - // Don't use - use {Expect,Forget}FutureSource instead. - static bool ExpectOrForgetFutureSource( - const ClientInfo& aClientInfo, - bool (PClientManagerChild::*aMethod)(const IPCClientInfo&)); - public: - // Asynchronously declare that a ClientSource will possibly be constructed - // from an equivalent ClientInfo in the future. This must be called before any - // any ClientHandles are created with the ClientInfo to avoid race conditions - // when ClientHandles query the ClientManagerService. - // - // This method exists so that the ClientManagerService can determine if a - // particular ClientSource can be expected to exist in the future or has - // already existed and been destroyed. - // - // If it's later known that the expected ClientSource will not be - // constructed, ForgetFutureSource must be called. - static bool ExpectFutureSource(const ClientInfo& aClientInfo); - - // May also be called even when the "future" source has become a "real" - // source, in which case this is a no-op. - static bool ForgetFutureSource(const ClientInfo& aClientInfo); - // Initialize the ClientManager at process start. This // does book-keeping like creating a TLS identifier, etc. // This should only be called by process startup code. diff --git a/dom/clients/manager/ClientManagerParent.cpp b/dom/clients/manager/ClientManagerParent.cpp index ed415334ddc2..93f4ab968d20 100644 --- a/dom/clients/manager/ClientManagerParent.cpp +++ b/dom/clients/manager/ClientManagerParent.cpp @@ -10,7 +10,6 @@ #include "ClientManagerOpParent.h" #include "ClientManagerService.h" #include "ClientSourceParent.h" -#include "ClientValidation.h" #include "mozilla/dom/PClientNavigateOpParent.h" #include "mozilla/Unused.h" @@ -107,28 +106,5 @@ ClientManagerParent::~ClientManagerParent() { mService->RemoveManager(this); } void ClientManagerParent::Init() { mService->AddManager(this); } -IPCResult ClientManagerParent::RecvExpectFutureClientSource( - const IPCClientInfo& aClientInfo) { - if (NS_WARN_IF(!ClientIsValidPrincipalInfo(aClientInfo.principalInfo()))) { - return IPC_FAIL(this, "Invalid PrincipalInfo."); - } - - RefPtr cms = - ClientManagerService::GetOrCreateInstance(); - Unused << NS_WARN_IF(cms->ExpectFutureSource(aClientInfo)); - return IPC_OK(); -} - -IPCResult ClientManagerParent::RecvForgetFutureClientSource( - const IPCClientInfo& aClientInfo) { - if (NS_WARN_IF(!ClientIsValidPrincipalInfo(aClientInfo.principalInfo()))) { - return IPC_FAIL(this, "Invalid PrincipalInfo."); - } - - RefPtr cms = ClientManagerService::GetInstance(); - cms->ForgetFutureSource(aClientInfo); - return IPC_OK(); -} - } // namespace dom } // namespace mozilla diff --git a/dom/clients/manager/ClientManagerParent.h b/dom/clients/manager/ClientManagerParent.h index b27f3b6835c7..edc060402148 100644 --- a/dom/clients/manager/ClientManagerParent.h +++ b/dom/clients/manager/ClientManagerParent.h @@ -52,12 +52,6 @@ class ClientManagerParent final : public PClientManagerParent { PClientSourceParent* aActor, const ClientSourceConstructorArgs& aArgs) override; - mozilla::ipc::IPCResult RecvExpectFutureClientSource( - const IPCClientInfo& aClientInfo) override; - - mozilla::ipc::IPCResult RecvForgetFutureClientSource( - const IPCClientInfo& aClientInfo) override; - public: ClientManagerParent(); ~ClientManagerParent(); diff --git a/dom/clients/manager/ClientManagerService.cpp b/dom/clients/manager/ClientManagerService.cpp index 2bd17659b6de..5c36340c9e9f 100644 --- a/dom/clients/manager/ClientManagerService.cpp +++ b/dom/clients/manager/ClientManagerService.cpp @@ -11,7 +11,6 @@ #include "ClientOpenWindowUtils.h" #include "ClientPrincipalUtils.h" #include "ClientSourceParent.h" -#include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ServiceWorkerManager.h" #include "mozilla/dom/ServiceWorkerUtils.h" @@ -108,10 +107,6 @@ RefPtr OnShutdown() { } // anonymous namespace -ClientManagerService::FutureClientSourceParent::FutureClientSourceParent( - const IPCClientInfo& aClientInfo) - : mPrincipalInfo(aClientInfo.principalInfo()) {} - ClientManagerService::ClientManagerService() : mShutdown(false) { AssertIsOnBackgroundThread(); @@ -141,7 +136,7 @@ ClientManagerService::ClientManagerService() : mShutdown(false) { ClientManagerService::~ClientManagerService() { AssertIsOnBackgroundThread(); - MOZ_DIAGNOSTIC_ASSERT(mSourceTable.count() == 0); + MOZ_DIAGNOSTIC_ASSERT(mSourceTable.Count() == 0); MOZ_DIAGNOSTIC_ASSERT(mManagerList.IsEmpty()); MOZ_DIAGNOSTIC_ASSERT(sClientManagerServiceInstance == this); @@ -167,38 +162,6 @@ void ClientManagerService::Shutdown() { } } -ClientSourceParent* ClientManagerService::MaybeUnwrapAsExistingSource( - const SourceTableEntry& aEntry) const { - AssertIsOnBackgroundThread(); - - if (aEntry.is()) { - return nullptr; - } - - return aEntry.as(); -} - -ClientSourceParent* ClientManagerService::FindExistingSource( - const nsID& aID, const PrincipalInfo& aPrincipalInfo) const { - AssertIsOnBackgroundThread(); - - auto entryPtr = mSourceTable.lookup(aID); - - if (!entryPtr) { - return nullptr; - } - - ClientSourceParent* source = MaybeUnwrapAsExistingSource(entryPtr->value()); - - if (!source || source->IsFrozen() || - NS_WARN_IF(!ClientMatchPrincipalInfo(source->Info().PrincipalInfo(), - aPrincipalInfo))) { - return nullptr; - } - - return source; -} - // static already_AddRefed ClientManagerService::GetOrCreateInstance() { @@ -224,143 +187,72 @@ already_AddRefed ClientManagerService::GetInstance() { return ref.forget(); } -namespace { - -bool IsNullPrincipalInfo(const PrincipalInfo& aPrincipalInfo) { - return aPrincipalInfo.type() == PrincipalInfo::TNullPrincipalInfo; -} - -bool AreBothNullPrincipals(const PrincipalInfo& aPrincipalInfo1, - const PrincipalInfo& aPrincipalInfo2) { - return IsNullPrincipalInfo(aPrincipalInfo1) && - IsNullPrincipalInfo(aPrincipalInfo2); -} - -} // anonymous namespace - bool ClientManagerService::AddSource(ClientSourceParent* aSource) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aSource); - - const nsID& id = aSource->Info().Id(); - auto entryPtr = mSourceTable.lookupForAdd(id); - - if (entryPtr) { - SourceTableEntry& entry = entryPtr->value(); - - // Do not permit overwriting an existing ClientSource with the same - // UUID. This would allow a spoofed ClientParentSource actor to - // intercept postMessage() intended for the real actor. - if (NS_WARN_IF(entry.is())) { - return false; - } - - FutureClientSourceParent& placeHolder = - entry.as(); - - const PrincipalInfo& placeHolderPrincipalInfo = placeHolder.PrincipalInfo(); - const PrincipalInfo& sourcePrincipalInfo = aSource->Info().PrincipalInfo(); - - // The placeholder FutureClientSourceParent's PrincipalInfo must match the - // real ClientSourceParent's PrincipalInfo. The only exception is if both - // are null principals (two null principals are considered unequal). - if (!AreBothNullPrincipals(placeHolderPrincipalInfo, sourcePrincipalInfo) && - NS_WARN_IF(!ClientMatchPrincipalInfo(placeHolderPrincipalInfo, - sourcePrincipalInfo))) { - return false; - } - - placeHolder.ResolvePromiseIfExists(aSource); - - entry = AsVariant(aSource); - return true; + auto entry = mSourceTable.LookupForAdd(aSource->Info().Id()); + // Do not permit overwriting an existing ClientSource with the same + // UUID. This would allow a spoofed ClientParentSource actor to + // intercept postMessage() intended for the real actor. + if (NS_WARN_IF(!!entry)) { + return false; } + entry.OrInsert([&] { return aSource; }); - return mSourceTable.add(entryPtr, id, AsVariant(aSource)); + // Now that we've been created, notify any handles that were + // waiting on us. + auto* handles = mPendingHandles.GetValue(aSource->Info().Id()); + if (handles) { + for (auto handle : *handles) { + handle->FoundSource(aSource); + } + } + mPendingHandles.Remove(aSource->Info().Id()); + return true; } bool ClientManagerService::RemoveSource(ClientSourceParent* aSource) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aSource); - - auto entryPtr = mSourceTable.lookup(aSource->Info().Id()); - - if (NS_WARN_IF(!entryPtr)) { + auto entry = mSourceTable.Lookup(aSource->Info().Id()); + if (NS_WARN_IF(!entry)) { return false; } - - mSourceTable.remove(entryPtr); + entry.Remove(); return true; } -bool ClientManagerService::ExpectFutureSource( - const IPCClientInfo& aClientInfo) { - AssertIsOnBackgroundThread(); - - const nsID& id = aClientInfo.id(); - auto entryPtr = mSourceTable.lookupForAdd(id); - - // Prevent overwrites. - if (NS_WARN_IF(static_cast(entryPtr))) { - return false; - } - - return mSourceTable.add( - entryPtr, id, - SourceTableEntry(VariantIndex<0>(), - FutureClientSourceParent(aClientInfo))); -} - -void ClientManagerService::ForgetFutureSource( - const IPCClientInfo& aClientInfo) { - AssertIsOnBackgroundThread(); - - auto entryPtr = mSourceTable.lookup(aClientInfo.id()); - - if (entryPtr) { - SourceTableEntry& entry = entryPtr->value(); - - if (entry.is()) { - return; - } - - CopyableErrorResult rv; - rv.ThrowInvalidStateError("Client creation aborted."); - entry.as().RejectPromiseIfExists(rv); - - mSourceTable.remove(entryPtr); - } -} - -RefPtr ClientManagerService::FindSource( +ClientSourceParent* ClientManagerService::FindSource( const nsID& aID, const PrincipalInfo& aPrincipalInfo) { AssertIsOnBackgroundThread(); - auto entryPtr = mSourceTable.lookup(aID); - - if (!entryPtr) { - CopyableErrorResult rv; - rv.ThrowInvalidStateError("Unknown client."); - return SourcePromise::CreateAndReject(rv, __func__); + auto entry = mSourceTable.Lookup(aID); + if (!entry) { + return nullptr; } - SourceTableEntry& entry = entryPtr->value(); - - if (entry.is()) { - return entry.as().Promise(); - } - - ClientSourceParent* source = entry.as(); - + ClientSourceParent* source = entry.Data(); if (source->IsFrozen() || - NS_WARN_IF(!ClientMatchPrincipalInfo(source->Info().PrincipalInfo(), - aPrincipalInfo))) { - CopyableErrorResult rv; - rv.ThrowInvalidStateError("Unknown client."); - return SourcePromise::CreateAndReject(rv, __func__); + !ClientMatchPrincipalInfo(source->Info().PrincipalInfo(), + aPrincipalInfo)) { + return nullptr; } - return SourcePromise::CreateAndResolve(source, __func__); + return source; +} + +void ClientManagerService::WaitForSource(ClientHandleParent* aHandle, + const nsID& aID) { + auto& entry = mPendingHandles.GetOrInsert(aID); + entry.AppendElement(aHandle); +} + +void ClientManagerService::StopWaitingForSource(ClientHandleParent* aHandle, + const nsID& aID) { + auto* entry = mPendingHandles.GetValue(aID); + if (entry) { + entry->RemoveElement(aHandle); + } } void ClientManagerService::AddManager(ClientManagerParent* aManager) { @@ -385,7 +277,7 @@ void ClientManagerService::RemoveManager(ClientManagerParent* aManager) { RefPtr ClientManagerService::Navigate( const ClientNavigateArgs& aArgs) { ClientSourceParent* source = - FindExistingSource(aArgs.target().id(), aArgs.target().principalInfo()); + FindSource(aArgs.target().id(), aArgs.target().principalInfo()); if (!source) { CopyableErrorResult rv; rv.ThrowInvalidStateError("Unknown client"); @@ -511,11 +403,11 @@ RefPtr ClientManagerService::MatchAll( RefPtr promiseList = new PromiseListHolder(); - for (auto iter = mSourceTable.iter(); !iter.done(); iter.next()) { - ClientSourceParent* source = - MaybeUnwrapAsExistingSource(iter.get().value()); + for (auto iter = mSourceTable.Iter(); !iter.Done(); iter.Next()) { + ClientSourceParent* source = iter.UserData(); + MOZ_DIAGNOSTIC_ASSERT(source); - if (!source || source->IsFrozen() || !source->ExecutionReady()) { + if (source->IsFrozen() || !source->ExecutionReady()) { continue; } @@ -606,11 +498,11 @@ RefPtr ClientManagerService::Claim( RefPtr promiseList = new PromiseListHolder(); - for (auto iter = mSourceTable.iter(); !iter.done(); iter.next()) { - ClientSourceParent* source = - MaybeUnwrapAsExistingSource(iter.get().value()); + for (auto iter = mSourceTable.Iter(); !iter.Done(); iter.Next()) { + ClientSourceParent* source = iter.UserData(); + MOZ_DIAGNOSTIC_ASSERT(source); - if (!source || source->IsFrozen()) { + if (source->IsFrozen()) { continue; } @@ -652,8 +544,7 @@ RefPtr ClientManagerService::Claim( RefPtr ClientManagerService::GetInfoAndState( const ClientGetInfoAndStateArgs& aArgs) { - ClientSourceParent* source = - FindExistingSource(aArgs.id(), aArgs.principalInfo()); + ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo()); if (!source) { CopyableErrorResult rv; @@ -664,11 +555,12 @@ RefPtr ClientManagerService::GetInfoAndState( if (!source->ExecutionReady()) { RefPtr self = this; + // rejection ultimately converted to `undefined` in Clients::Get return source->ExecutionReadyPromise()->Then( GetCurrentThreadSerialEventTarget(), __func__, - [self = std::move(self), aArgs]() { + [self, aArgs]() -> RefPtr { ClientSourceParent* source = - self->FindExistingSource(aArgs.id(), aArgs.principalInfo()); + self->FindSource(aArgs.id(), aArgs.principalInfo()); if (!source) { CopyableErrorResult rv; @@ -694,8 +586,7 @@ bool ClientManagerService::HasWindow( const PrincipalInfo& aPrincipalInfo, const nsID& aClientId) { AssertIsOnBackgroundThread(); - ClientSourceParent* source = FindExistingSource(aClientId, aPrincipalInfo); - + ClientSourceParent* source = FindSource(aClientId, aPrincipalInfo); if (!source) { return false; } diff --git a/dom/clients/manager/ClientManagerService.h b/dom/clients/manager/ClientManagerService.h index 36afdb2af981..9f247b667427 100644 --- a/dom/clients/manager/ClientManagerService.h +++ b/dom/clients/manager/ClientManagerService.h @@ -6,12 +6,7 @@ #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 { @@ -33,59 +28,13 @@ 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; - RefPtr mService = ClientManagerService::GetInstance(); - }; - - 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 possible ClientSourceParent objects in a hash table. We want to + // Store the ClientSourceParent objects in a hash table. We want to // optimize for insertion, removal, and lookup by UUID. - HashMap mSourceTable; + nsDataHashtable mSourceTable; + + // The set of handles waiting for their corresponding ClientSourceParent + // to be created. + nsDataHashtable> mPendingHandles; nsTArray mManagerList; @@ -96,16 +45,6 @@ class ClientManagerService final { void Shutdown(); - // Returns nullptr if aEntry isn't a ClientSourceParent (i.e. it's a - // FutureClientSourceParent). - ClientSourceParent* MaybeUnwrapAsExistingSource( - const SourceTableEntry& aEntry) const; - - // Returns nullptr if the ClientSourceParent doesn't exist yet (i.e. it's a - // FutureClientSourceParent or has already been destroyed) or is frozen. - ClientSourceParent* FindExistingSource( - const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo) const; - public: static already_AddRefed GetOrCreateInstance(); @@ -116,16 +55,15 @@ class ClientManagerService final { bool RemoveSource(ClientSourceParent* aSource); - // Returns true when a FutureClientSourceParent is successfully added. - bool ExpectFutureSource(const IPCClientInfo& aClientInfo); - - // May still be called if it's possible that the FutureClientSourceParent - // no longer exists. - void ForgetFutureSource(const IPCClientInfo& aClientInfo); - - RefPtr FindSource( + ClientSourceParent* FindSource( const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo); + // Called when a ClientHandle is created before the corresponding + // ClientSource. Will call FoundSource on the ClientHandleParent when it + // becomes available. + void WaitForSource(ClientHandleParent* aHandle, const nsID& aID); + void StopWaitingForSource(ClientHandleParent* aHandle, const nsID& aID); + void AddManager(ClientManagerParent* aManager); void RemoveManager(ClientManagerParent* aManager); diff --git a/dom/clients/manager/PClientManager.ipdl b/dom/clients/manager/PClientManager.ipdl index 4291a3a18c5c..84646f46c83d 100644 --- a/dom/clients/manager/PClientManager.ipdl +++ b/dom/clients/manager/PClientManager.ipdl @@ -32,9 +32,6 @@ parent: async PClientManagerOp(ClientOpConstructorArgs aArgs); async PClientSource(ClientSourceConstructorArgs aArgs); - async ExpectFutureClientSource(IPCClientInfo aClientInfo); - async ForgetFutureClientSource(IPCClientInfo aClientInfo); - child: async PClientNavigateOp(ClientNavigateOpConstructorArgs aArgs); diff --git a/dom/clients/manager/moz.build b/dom/clients/manager/moz.build index 1dde94fc4b39..e2be201898f4 100644 --- a/dom/clients/manager/moz.build +++ b/dom/clients/manager/moz.build @@ -7,7 +7,6 @@ EXPORTS.mozilla.dom += [ 'ClientChannelHelper.h', 'ClientHandle.h', - 'ClientHandleParent.h', 'ClientInfo.h', 'ClientIPCUtils.h', 'ClientManager.h',