зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset daecd36223c9 (bug 1584007) for ClientManagerService.cpp failures CLOSED TREE
This commit is contained in:
Родитель
846d70ee89
Коммит
e2c099719a
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()) {}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,9 +32,6 @@ parent:
|
|||
async PClientManagerOp(ClientOpConstructorArgs aArgs);
|
||||
async PClientSource(ClientSourceConstructorArgs aArgs);
|
||||
|
||||
async ExpectOrForgetFutureClientSource(bool aExpect,
|
||||
IPCClientInfo aClientInfo);
|
||||
|
||||
child:
|
||||
async PClientNavigateOp(ClientNavigateOpConstructorArgs aArgs);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче