mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1584007 - allow ClientManager to register "future" ClientSources r=dom-workers-and-storage-reviewers,asuth
Differential Revision: https://phabricator.services.mozilla.com/D66520
This commit is contained in:
parent
2ed195d384
commit
9ca5730156
@ -226,6 +226,36 @@ 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<ClientManager> 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());
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "mozilla/dom/ClientOpPromise.h"
|
||||
#include "mozilla/dom/ClientThing.h"
|
||||
#include "mozilla/dom/PClientManagerChild.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
@ -73,7 +74,29 @@ class ClientManager final : public ClientThing<ClientManagerChild> {
|
||||
// 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.
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "ClientManagerOpParent.h"
|
||||
#include "ClientManagerService.h"
|
||||
#include "ClientSourceParent.h"
|
||||
#include "ClientValidation.h"
|
||||
#include "mozilla/dom/PClientNavigateOpParent.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
@ -106,4 +107,27 @@ 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<ClientManagerService> 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<ClientManagerService> cms = ClientManagerService::GetInstance();
|
||||
cms->ForgetFutureSource(aClientInfo);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -52,6 +52,12 @@ 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();
|
||||
|
@ -294,6 +294,50 @@ bool ClientManagerService::RemoveSource(ClientSourceParent* aSource) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientManagerService::ExpectFutureSource(
|
||||
const IPCClientInfo& aClientInfo) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (!mSourceTable.WithEntryHandle(
|
||||
aClientInfo.id(), [&aClientInfo](auto&& entry) {
|
||||
// Prevent overwrites.
|
||||
if (entry.HasEntry()) {
|
||||
return false;
|
||||
}
|
||||
entry.Insert(SourceTableEntry(
|
||||
VariantIndex<0>(), FutureClientSourceParent(aClientInfo)));
|
||||
return true;
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientManagerService::ForgetFutureSource(
|
||||
const IPCClientInfo& aClientInfo) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
auto entry = mSourceTable.Lookup(aClientInfo.id());
|
||||
|
||||
if (entry) {
|
||||
if (entry.Data().is<ClientSourceParent*>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!XRE_IsE10sParentProcess() &&
|
||||
entry.Data().as<FutureClientSourceParent>().IsAssociated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CopyableErrorResult rv;
|
||||
rv.ThrowInvalidStateError("Client creation aborted.");
|
||||
entry.Data().as<FutureClientSourceParent>().RejectPromiseIfExists(rv);
|
||||
|
||||
entry.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<SourcePromise> ClientManagerService::FindSource(
|
||||
const nsID& aID, const PrincipalInfo& aPrincipalInfo) {
|
||||
AssertIsOnBackgroundThread();
|
||||
@ -306,6 +350,7 @@ RefPtr<SourcePromise> ClientManagerService::FindSource(
|
||||
}
|
||||
|
||||
if (entry.Data().is<FutureClientSourceParent>()) {
|
||||
entry.Data().as<FutureClientSourceParent>().SetAsAssociated();
|
||||
return entry.Data().as<FutureClientSourceParent>().Promise();
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,13 @@ 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<SourcePromise> FindSource(
|
||||
const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
|
||||
|
||||
|
@ -32,6 +32,9 @@ parent:
|
||||
async PClientManagerOp(ClientOpConstructorArgs aArgs);
|
||||
async PClientSource(ClientSourceConstructorArgs aArgs);
|
||||
|
||||
async ExpectFutureClientSource(IPCClientInfo aClientInfo);
|
||||
async ForgetFutureClientSource(IPCClientInfo aClientInfo);
|
||||
|
||||
child:
|
||||
async PClientNavigateOp(ClientNavigateOpConstructorArgs aArgs);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user