Backed out changeset daecd36223c9 (bug 1584007) for ClientManagerService.cpp failures CLOSED TREE

This commit is contained in:
Bogdan Tara 2019-10-02 14:36:27 +03:00
parent 846d70ee89
commit e2c099719a
10 changed files with 106 additions and 352 deletions

View File

@ -9,8 +9,6 @@
#include "ClientManager.h"
#include "ClientSource.h"
#include "MainThreadUtils.h"
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsContentUtils.h"
@ -141,17 +139,10 @@ class ClientChannelHelper final : public nsIInterfaceRequestor,
// create a ClientSource when the final channel propagates back
// to the child.
if (mMode == Mode::Mode_Parent) {
const Maybe<ClientInfo>& oldReservedInfo =
oldLoadInfo->GetReservedClientInfo();
if (oldReservedInfo) {
MOZ_TRY(ClientManager::ForgetFutureClientSource(*oldReservedInfo));
}
Maybe<ClientInfo> newReservedInfo =
Maybe<ClientInfo> reservedInfo =
ClientManager::CreateInfo(ClientType::Window, principal);
if (newReservedInfo) {
MOZ_TRY(ClientManager::ExpectFutureClientSource(*newReservedInfo));
newLoadInfo->SetReservedClientInfo(*newReservedInfo);
if (reservedInfo) {
newLoadInfo->SetReservedClientInfo(*reservedInfo);
}
} else {
reservedClient.reset();

View File

@ -8,7 +8,6 @@
#include "ClientHandleOpParent.h"
#include "ClientManagerService.h"
#include "ClientPrincipalUtils.h"
#include "ClientSourceParent.h"
#include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/Unused.h"
@ -28,10 +27,12 @@ void ClientHandleParent::ActorDestroy(ActorDestroyReason aReason) {
mSource->DetachHandle(this);
mSource = nullptr;
} else {
mSourcePromiseRequestHolder.DisconnectIfExists();
mService->StopWaitingForSource(this, mClientId);
}
mSourcePromiseHolder.RejectIfExists(NS_ERROR_FAILURE, __func__);
if (mSourcePromise) {
mSourcePromise->Reject(NS_ERROR_FAILURE, __func__);
}
}
PClientHandleOpParent* ClientHandleParent::AllocPClientHandleOpParent(
@ -60,22 +61,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;
}
// Capturing `this` is okay because the callbacks are disconnected from the
// promise returned by `FindSource` in `ActorDestroy`, so the dangling
// pointers will never be used.
mService->FindSource(aClientInfo.id(), aClientInfo.principalInfo())
->Then(
GetCurrentThreadSerialEventTarget(), __func__,
[this](ClientSourceParent* aSource) {
mSourcePromiseRequestHolder.Complete();
FoundSource(aSource);
},
[this](nsresult) {
mSourcePromiseRequestHolder.Complete();
Unused << Send__delete__(this);
})
->Track(mSourcePromiseRequestHolder);
mSource->AttachHandle(this);
}
ClientSourceParent* ClientHandleParent::GetSource() const { return mSource; }
@ -85,20 +77,28 @@ RefPtr<SourcePromise> 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 (mSourcePromise) {
mSourcePromise->Reject(NS_ERROR_FAILURE, __func__);
}
Unused << Send__delete__(this);
return;
}
mSource = aSource;
mSource->AttachHandle(this);
mSourcePromiseHolder.ResolveIfExists(aSource, __func__);
if (mSourcePromise) {
mSourcePromise->Resolve(aSource, __func__);
}
}
} // namespace dom

View File

@ -6,26 +6,20 @@
#ifndef _mozilla_dom_ClientHandleParent_h
#define _mozilla_dom_ClientHandleParent_h
#include "ClientManagerService.h"
#include "mozilla/MozPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/PClientHandleOpParent.h"
#include "mozilla/dom/PClientHandleParent.h"
namespace mozilla {
namespace dom {
class ClientManagerService;
class ClientSourceParent;
typedef MozPromise<ClientSourceParent*, nsresult, /* IsExclusive = */ false>
SourcePromise;
class ClientHandleParent final : public PClientHandleParent {
RefPtr<ClientManagerService> mService;
// `mSource` and (`mSourcePromiseHolder`, `mSourcePromiseRequestHolder`) are
// mutually exclusive, so they could be combined in a `mozilla::Variant`.
ClientSourceParent* mSource;
MozPromiseHolder<SourcePromise> mSourcePromiseHolder;
MozPromiseRequestHolder<SourcePromise> mSourcePromiseRequestHolder;
nsID mClientId;
PrincipalInfo mPrincipalInfo;

View File

@ -280,37 +280,6 @@ UniquePtr<ClientSource> ClientManager::CreateSourceFromInfo(
return mgr->CreateSourceInternal(aClientInfo, aEventTarget);
}
// static
nsresult ClientManager::ExpectOrForgetFutureClientSource(
bool aExpect, const ClientInfo& aClientInfo) {
nsresult rv = NS_OK;
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
mgr->MaybeExecute(
[&](ClientManagerChild* aActor) {
if (!aActor->SendExpectOrForgetFutureClientSource(
aExpect, aClientInfo.ToIPC())) {
rv = NS_ERROR_DOM_INVALID_STATE_ERR;
}
},
[&] { rv = NS_ERROR_DOM_INVALID_STATE_ERR; });
return rv;
}
// static
nsresult ClientManager::ExpectFutureClientSource(
const ClientInfo& aClientInfo) {
return ExpectOrForgetFutureClientSource(true, aClientInfo);
}
// static
nsresult ClientManager::ForgetFutureClientSource(
const ClientInfo& aClientInfo) {
return ExpectOrForgetFutureClientSource(false, aClientInfo);
}
// static
Maybe<ClientInfo> ClientManager::CreateInfo(ClientType aType,
nsIPrincipal* aPrincipal) {
MOZ_ASSERT(NS_IsMainThread());

View File

@ -29,7 +29,6 @@ class ClientOpConstructorArgs;
class ClientOpenWindowArgs;
class ClientSource;
enum class ClientType : uint8_t;
class PClientManagerChild;
class WorkerPrivate;
// The ClientManager provides a per-thread singleton interface workering
@ -74,9 +73,6 @@ class ClientManager final : public ClientThing<ClientManagerChild> {
// Private methods called by ClientSource
mozilla::dom::WorkerPrivate* GetWorkerPrivate() const;
static nsresult ExpectOrForgetFutureClientSource(
bool aExpect, const ClientInfo& aClientInfo);
public:
// Initialize the ClientManager at process start. This
// does book-keeping like creating a TLS identifier, etc.
@ -96,28 +92,9 @@ class ClientManager final : public ClientThing<ClientManagerChild> {
static UniquePtr<ClientSource> CreateSourceFromInfo(
const ClientInfo& aClientInfo, nsISerialEventTarget* aSerialEventTarget);
// Asynchronously declare that a `ClientSource` will _possibly_ be constructed
// from an equivalent `ClientInfo` in the future. This must be called _before_
// any `ClientHandle`s are created with the `ClientInfo` to avoid race
// conditions when `ClientHandle`s 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, `ForgetFutureClientSource` _must_ be called.
static nsresult ExpectFutureClientSource(const ClientInfo& aClientInfo);
// Negates a prior call to `ExpectFutureClientSource`.
static nsresult ForgetFutureClientSource(const ClientInfo& aClientInfo);
// Allocate a new ClientInfo and id without creating a ClientSource. Used
// when we have a redirect that isn't exposed to the process that owns
// the global/ClientSource.
//
// NOTE: callers should consider whether a call to `ExpectFutureClientSource`
// should be made when calling this method.
static Maybe<ClientInfo> CreateInfo(ClientType aType,
nsIPrincipal* aPrincipal);

View File

@ -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"
@ -100,25 +99,6 @@ IPCResult ClientManagerParent::RecvPClientSourceConstructor(
return IPC_OK();
}
mozilla::ipc::IPCResult
ClientManagerParent::RecvExpectOrForgetFutureClientSource(
const bool& aExpect, const IPCClientInfo& aClientInfo) {
if (NS_WARN_IF(!ClientIsValidPrincipalInfo(aClientInfo.principalInfo()))) {
return IPC_FAIL(this, "Invalid PrincipalInfo.");
}
RefPtr<ClientManagerService> svc =
ClientManagerService::GetOrCreateInstance();
if (aExpect) {
svc->ExpectFutureSource(aClientInfo);
} else {
svc->ForgetFutureSource(aClientInfo);
}
return IPC_OK();
}
ClientManagerParent::ClientManagerParent()
: mService(ClientManagerService::GetOrCreateInstance()) {}

View File

@ -52,9 +52,6 @@ class ClientManagerParent final : public PClientManagerParent {
PClientSourceParent* aActor,
const ClientSourceConstructorArgs& aArgs) override;
mozilla::ipc::IPCResult RecvExpectOrForgetFutureClientSource(
const bool& aExpect, const IPCClientInfo& aClientInfo) override;
public:
ClientManagerParent();
~ClientManagerParent();

View File

@ -12,7 +12,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"
@ -138,7 +137,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);
@ -189,155 +188,52 @@ already_AddRefed<ClientManagerService> ClientManagerService::GetInstance() {
return ref.forget();
}
ClientManagerService::FutureClientSourceParent::FutureClientSourceParent(
const IPCClientInfo& aClientInfo)
: mPrincipalInfo(aClientInfo.principalInfo()) {}
// static
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<ClientSourceParent*>())) {
return false;
}
{
FutureClientSourceParent& placeHolder =
entry.as<FutureClientSourceParent>();
if (NS_WARN_IF(!ClientMatchPrincipalInfo(
placeHolder.PrincipalInfo(), aSource->Info().PrincipalInfo()))) {
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) ||
NS_WARN_IF(entryPtr->value().is<FutureClientSourceParent>())) {
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) {
ClientSourceParent* ClientManagerService::FindSource(
const nsID& aID, const PrincipalInfo& aPrincipalInfo) {
AssertIsOnBackgroundThread();
const nsID& id = aClientInfo.id();
auto entryPtr = mSourceTable.lookupForAdd(id);
// Prevent overwrites.
if (NS_WARN_IF(static_cast<bool>(entryPtr))) {
return false;
auto entry = mSourceTable.Lookup(aID);
if (!entry) {
return nullptr;
}
return mSourceTable.add(
entryPtr, id,
SourceTableEntry(VariantIndex<0>(),
FutureClientSourceParent(aClientInfo)));
}
bool ClientManagerService::ForgetFutureSource(
const IPCClientInfo& aClientInfo) {
AssertIsOnBackgroundThread();
auto entryPtr = mSourceTable.lookup(aClientInfo.id());
if (entryPtr) {
SourceTableEntry& entry = entryPtr->value();
if (NS_WARN_IF(entry.is<ClientSourceParent*>())) {
return false;
}
entry.as<FutureClientSourceParent>().RejectPromiseIfExists(
NS_ERROR_NOT_AVAILABLE);
}
mSourceTable.remove(entryPtr);
return true;
}
RefPtr<SourcePromise> ClientManagerService::FindSource(
const nsID& aID, const PrincipalInfo& aPrincipalInfo) const {
AssertIsOnBackgroundThread();
auto entryPtr = mSourceTable.lookup(aID);
if (!entryPtr) {
return SourcePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
}
SourceTableEntry& entry = entryPtr->value();
if (entry.is<FutureClientSourceParent>()) {
return entry.as<FutureClientSourceParent>().Promise();
}
ClientSourceParent* source = entry.as<ClientSourceParent*>();
MOZ_DIAGNOSTIC_ASSERT(source);
ClientSourceParent* source = entry.Data();
if (source->IsFrozen() ||
NS_WARN_IF(!ClientMatchPrincipalInfo(source->Info().PrincipalInfo(),
aPrincipalInfo))) {
return SourcePromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
__func__);
}
return SourcePromise::CreateAndResolve(source, __func__);
}
inline ClientSourceParent* MaybeUnwrapAsExistingSource(
const ClientManagerService::SourceTableEntry& aEntry) {
AssertIsOnBackgroundThread();
if (aEntry.is<ClientManagerService::FutureClientSourceParent>()) {
return nullptr;
}
MOZ_DIAGNOSTIC_ASSERT(aEntry.as<ClientSourceParent*>());
return aEntry.as<ClientSourceParent*>();
}
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() ||
!ClientMatchPrincipalInfo(source->Info().PrincipalInfo(),
aPrincipalInfo)) {
return nullptr;
@ -346,6 +242,20 @@ ClientSourceParent* ClientManagerService::FindExistingSource(
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) {
AssertIsOnBackgroundThread();
MOZ_DIAGNOSTIC_ASSERT(aManager);
@ -368,7 +278,7 @@ void ClientManagerService::RemoveManager(ClientManagerParent* aManager) {
RefPtr<ClientOpPromise> ClientManagerService::Navigate(
const ClientNavigateArgs& aArgs) {
ClientSourceParent* source =
FindExistingSource(aArgs.target().id(), aArgs.target().principalInfo());
FindSource(aArgs.target().id(), aArgs.target().principalInfo());
if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
@ -475,11 +385,11 @@ RefPtr<ClientOpPromise> ClientManagerService::MatchAll(
RefPtr<PromiseListHolder> 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;
}
@ -557,11 +467,11 @@ RefPtr<ClientOpPromise> ClientManagerService::Claim(
RefPtr<PromiseListHolder> 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;
}
@ -603,8 +513,7 @@ RefPtr<ClientOpPromise> ClientManagerService::Claim(
RefPtr<ClientOpPromise> ClientManagerService::GetInfoAndState(
const ClientGetInfoAndStateArgs& aArgs) {
ClientSourceParent* source =
FindExistingSource(aArgs.id(), aArgs.principalInfo());
ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo());
if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
@ -616,10 +525,9 @@ RefPtr<ClientOpPromise> ClientManagerService::GetInfoAndState(
// rejection ultimately converted to `undefined` in Clients::Get
return source->ExecutionReadyPromise()->Then(
GetCurrentThreadSerialEventTarget(), __func__,
[self = std::move(self), aArgs] {
// Execution ready implies the source had registered itself.
[self, aArgs]() -> RefPtr<ClientOpPromise> {
ClientSourceParent* source =
self->FindExistingSource(aArgs.id(), aArgs.principalInfo());
self->FindSource(aArgs.id(), aArgs.principalInfo());
if (!source) {
return ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
@ -732,7 +640,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;
}

View File

@ -7,11 +7,6 @@
#define _mozilla_dom_ClientManagerService_h
#include "ClientOpPromise.h"
#include "mozilla/HashTable.h"
#include "mozilla/MozPromise.h"
#include "mozilla/Variant.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsDataHashtable.h"
namespace mozilla {
@ -27,14 +22,29 @@ namespace dom {
class ClientManagerParent;
class ClientSourceParent;
class ClientHandleParent;
typedef MozPromise<ClientSourceParent*, nsresult, /* IsExclusive = */ false>
SourcePromise;
class ContentParent;
// Define a singleton service to manage client activity throughout the
// browser. This service runs on the PBackground thread. To interact
// it with it please use the ClientManager and ClientHandle classes.
class ClientManagerService final {
// Store the ClientSourceParent objects in a hash table. We want to
// optimize for insertion, removal, and lookup by UUID.
nsDataHashtable<nsIDHashKey, ClientSourceParent*> mSourceTable;
// The set of handles waiting for their corresponding ClientSourceParent
// to be created.
nsDataHashtable<nsIDHashKey, nsTArray<ClientHandleParent*>> mPendingHandles;
nsTArray<ClientManagerParent*> mManagerList;
bool mShutdown;
ClientManagerService();
~ClientManagerService();
void Shutdown();
public:
static already_AddRefed<ClientManagerService> GetOrCreateInstance();
@ -45,18 +55,14 @@ class ClientManagerService final {
bool RemoveSource(ClientSourceParent* aSource);
bool ExpectFutureSource(const IPCClientInfo& aClientInfo);
ClientSourceParent* FindSource(
const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
bool ForgetFutureSource(const IPCClientInfo& aClientInfo);
// The returned promise rejects if:
// - the corresponding `ClientSourceParent` has already removed itself from
// the `ClientManagerService` (i.e. the corresponding `ClientSource` has been
// detroyed) or if
// - it's known that the corresponding `ClientSourceParent` will not exist
// (i.e. the corresponding `ClientSource` will not be created).
RefPtr<SourcePromise> FindSource(
const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo) const;
// 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);
@ -80,71 +86,6 @@ class ClientManagerService final {
const nsID& aClientId);
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService)
private:
ClientManagerService();
~ClientManagerService();
void Shutdown();
// Returns `nullptr` if the `ClientSourceParent*` doesn't exist.
ClientSourceParent* FindExistingSource(
const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo) const;
// Represents a `ClientSourceParent` that may possibly be created and add
// itself in the future.
class FutureClientSourceParent {
public:
explicit FutureClientSourceParent(const IPCClientInfo& aClientInfo);
const mozilla::ipc::PrincipalInfo& PrincipalInfo() const {
return mPrincipalInfo;
}
already_AddRefed<SourcePromise> Promise() {
return mPromiseHolder.Ensure(__func__);
}
void ResolvePromiseIfExists(ClientSourceParent* aSource) {
mPromiseHolder.ResolveIfExists(aSource, __func__);
}
void RejectPromiseIfExists(nsresult aRv) {
mPromiseHolder.RejectIfExists(aRv, __func__);
}
private:
const mozilla::ipc::PrincipalInfo mPrincipalInfo;
MozPromiseHolder<SourcePromise> mPromiseHolder;
};
using SourceTableEntry =
Variant<FutureClientSourceParent, ClientSourceParent*>;
// Returns `nullptr` if `aEntry` isn't a `ClientSourceParent*`.
friend inline ClientSourceParent* MaybeUnwrapAsExistingSource(
const SourceTableEntry& aEntry);
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
// optimize for insertion, removal, and lookup by UUID.
HashMap<nsID, SourceTableEntry, nsIDHasher> mSourceTable;
nsTArray<ClientManagerParent*> mManagerList;
bool mShutdown;
};
} // namespace dom

View File

@ -32,9 +32,6 @@ parent:
async PClientManagerOp(ClientOpConstructorArgs aArgs);
async PClientSource(ClientSourceConstructorArgs aArgs);
async ExpectOrForgetFutureClientSource(bool aExpect,
IPCClientInfo aClientInfo);
child:
async PClientNavigateOp(ClientNavigateOpConstructorArgs aArgs);