mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1424338 P1 Implement ClientManager::MatchAll() to support clients.matchAll() WebAPI. r=baku
This commit is contained in:
parent
491e62af53
commit
783e26e13e
@ -67,6 +67,19 @@ struct ClientControlledArgs
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
};
|
||||
|
||||
union ClientEndPoint
|
||||
{
|
||||
IPCClientInfo;
|
||||
IPCServiceWorkerDescriptor;
|
||||
};
|
||||
|
||||
struct ClientMatchAllArgs
|
||||
{
|
||||
ClientEndPoint endpoint;
|
||||
ClientType type;
|
||||
bool includeUncontrolled;
|
||||
};
|
||||
|
||||
struct ClientGetInfoAndStateArgs
|
||||
{
|
||||
nsID id;
|
||||
@ -80,9 +93,15 @@ struct ClientOpenWindowArgs
|
||||
union ClientOpConstructorArgs
|
||||
{
|
||||
ClientControlledArgs;
|
||||
ClientMatchAllArgs;
|
||||
ClientGetInfoAndStateArgs;
|
||||
};
|
||||
|
||||
struct ClientList
|
||||
{
|
||||
ClientInfoAndState[] values;
|
||||
};
|
||||
|
||||
struct ClientNavigateOpConstructorArgs
|
||||
{
|
||||
};
|
||||
@ -91,6 +110,7 @@ union ClientOpResult
|
||||
{
|
||||
nsresult;
|
||||
ClientInfoAndState;
|
||||
ClientList;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -257,6 +257,15 @@ ClientManager::CreateHandle(const ClientInfo& aClientInfo,
|
||||
return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::MatchAll(const ClientMatchAllArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
|
@ -22,6 +22,7 @@ class ClientGetInfoAndStateArgs;
|
||||
class ClientHandle;
|
||||
class ClientInfo;
|
||||
class ClientManagerChild;
|
||||
class ClientMatchAllArgs;
|
||||
class ClientOpConstructorArgs;
|
||||
class ClientSource;
|
||||
enum class ClientType : uint8_t;
|
||||
@ -94,6 +95,9 @@ public:
|
||||
CreateHandle(const ClientInfo& aClientInfo,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
MatchAll(const ClientMatchAllArgs& aArgs, nsISerialEventTarget* aTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
@ -48,6 +48,12 @@ void
|
||||
ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
switch (aArgs.type()) {
|
||||
case ClientOpConstructorArgs::TClientMatchAllArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::MatchAll,
|
||||
aArgs.get_ClientMatchAllArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::GetInfoAndState,
|
||||
|
@ -302,6 +302,151 @@ ClientManagerService::RemoveManager(ClientManagerParent* aManager)
|
||||
MOZ_ASSERT(removed);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class PromiseListHolder final
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> mResultPromise;
|
||||
nsTArray<RefPtr<ClientOpPromise>> mPromiseList;
|
||||
nsTArray<ClientInfoAndState> mResultList;
|
||||
uint32_t mOutstandingPromiseCount;
|
||||
|
||||
void
|
||||
ProcessSuccess(const ClientInfoAndState& aResult)
|
||||
{
|
||||
mResultList.AppendElement(aResult);
|
||||
ProcessCompletion();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessCompletion()
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOutstandingPromiseCount > 0);
|
||||
mOutstandingPromiseCount -= 1;
|
||||
MaybeFinish();
|
||||
}
|
||||
|
||||
~PromiseListHolder() = default;
|
||||
public:
|
||||
PromiseListHolder()
|
||||
: mResultPromise(new ClientOpPromise::Private(__func__))
|
||||
, mOutstandingPromiseCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<ClientOpPromise>
|
||||
GetResultPromise()
|
||||
{
|
||||
RefPtr<PromiseListHolder> kungFuDeathGrip = this;
|
||||
mResultPromise->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[kungFuDeathGrip] (const ClientOpResult& aResult) { },
|
||||
[kungFuDeathGrip] (nsresult aResult) { });
|
||||
|
||||
RefPtr<ClientOpPromise> ref = mResultPromise;
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
AddPromise(RefPtr<ClientOpPromise>&& aPromise)
|
||||
{
|
||||
mPromiseList.AppendElement(Move(aPromise));
|
||||
MOZ_DIAGNOSTIC_ASSERT(mPromiseList.LastElement());
|
||||
mOutstandingPromiseCount += 1;
|
||||
|
||||
RefPtr<PromiseListHolder> self(this);
|
||||
mPromiseList.LastElement()->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self] (const ClientOpResult& aResult) {
|
||||
// TODO: This is pretty clunky. Try to figure out a better
|
||||
// wait for MatchAll() and Claim() to share this code
|
||||
// even though they expect different return values.
|
||||
if (aResult.type() == ClientOpResult::TClientInfoAndState) {
|
||||
self->ProcessSuccess(aResult.get_ClientInfoAndState());
|
||||
} else {
|
||||
self->ProcessCompletion();
|
||||
}
|
||||
}, [self] (nsresult aResult) {
|
||||
self->ProcessCompletion();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
MaybeFinish()
|
||||
{
|
||||
if (!mOutstandingPromiseCount) {
|
||||
mResultPromise->Resolve(mResultList, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(PromiseListHolder)
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::MatchAll(const ClientMatchAllArgs& aArgs)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
const ClientEndPoint& endpoint = aArgs.endpoint();
|
||||
|
||||
const PrincipalInfo& principalInfo =
|
||||
endpoint.type() == ClientEndPoint::TIPCClientInfo
|
||||
? endpoint.get_IPCClientInfo().principalInfo()
|
||||
: endpoint.get_IPCServiceWorkerDescriptor().principalInfo();
|
||||
|
||||
RefPtr<PromiseListHolder> promiseList = new PromiseListHolder();
|
||||
|
||||
for (auto iter = mSourceTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
ClientSourceParent* source = iter.UserData();
|
||||
MOZ_DIAGNOSTIC_ASSERT(source);
|
||||
|
||||
if (source->IsFrozen() || !source->ExecutionReady()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aArgs.type() != ClientType::All &&
|
||||
source->Info().Type() != aArgs.type()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), principalInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aArgs.includeUncontrolled()) {
|
||||
if (endpoint.type() != ClientEndPoint::TIPCServiceWorkerDescriptor) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>& controller =
|
||||
source->GetController();
|
||||
if (controller.isNothing()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const IPCServiceWorkerDescriptor& serviceWorker =
|
||||
endpoint.get_IPCServiceWorkerDescriptor();
|
||||
|
||||
if(controller.ref().Id() != serviceWorker.id() ||
|
||||
controller.ref().Scope() != serviceWorker.scope()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
promiseList->AddPromise(
|
||||
source->StartOp(Move(ClientGetInfoAndStateArgs(source->Info().Id(),
|
||||
source->Info().PrincipalInfo()))));
|
||||
}
|
||||
|
||||
// Maybe finish the promise now in case we didn't find any matching clients.
|
||||
promiseList->MaybeFinish();
|
||||
|
||||
return promiseList->GetResultPromise();
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
|
@ -59,6 +59,9 @@ public:
|
||||
void
|
||||
RemoveManager(ClientManagerParent* aManager);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
MatchAll(const ClientMatchAllArgs& aArgs);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs);
|
||||
|
||||
|
@ -225,6 +225,12 @@ ClientSourceParent::ExecutionReady() const
|
||||
return mExecutionReady;
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
ClientSourceParent::GetController() const
|
||||
{
|
||||
return mController;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
|
||||
{
|
||||
|
@ -70,6 +70,9 @@ public:
|
||||
bool
|
||||
ExecutionReady() const;
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
void
|
||||
AttachHandle(ClientHandleParent* aClientSource);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user