2017-11-09 08:19:59 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "ClientManager.h"
|
|
|
|
|
2017-11-09 08:20:00 +03:00
|
|
|
#include "ClientHandle.h"
|
2017-11-09 08:19:59 +03:00
|
|
|
#include "ClientManagerChild.h"
|
|
|
|
#include "ClientManagerOpChild.h"
|
2017-11-14 22:36:45 +03:00
|
|
|
#include "ClientPrefs.h"
|
2017-11-09 08:19:59 +03:00
|
|
|
#include "ClientSource.h"
|
2017-11-09 08:19:59 +03:00
|
|
|
#include "mozilla/dom/WorkerPrivate.h"
|
|
|
|
#include "mozilla/dom/workers/bindings/WorkerHolderToken.h"
|
|
|
|
#include "mozilla/ipc/BackgroundChild.h"
|
|
|
|
#include "mozilla/ipc/PBackgroundChild.h"
|
|
|
|
#include "prthread.h"
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
using mozilla::ipc::BackgroundChild;
|
|
|
|
using mozilla::ipc::PBackgroundChild;
|
2017-11-09 08:19:59 +03:00
|
|
|
using mozilla::ipc::PrincipalInfo;
|
2017-11-09 08:19:59 +03:00
|
|
|
using mozilla::dom::workers::Closing;
|
|
|
|
using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
|
|
|
|
using mozilla::dom::workers::WorkerHolderToken;
|
|
|
|
using mozilla::dom::workers::WorkerPrivate;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
uint32_t kBadThreadLocalIndex = -1;
|
|
|
|
uint32_t sClientManagerThreadLocalIndex = kBadThreadLocalIndex;
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
ClientManager::ClientManager()
|
|
|
|
{
|
|
|
|
PBackgroundChild* parentActor = BackgroundChild::GetOrCreateForCurrentThread();
|
|
|
|
if (NS_WARN_IF(!parentActor)) {
|
|
|
|
Shutdown();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<WorkerHolderToken> workerHolderToken;
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
|
|
|
|
|
|
|
|
workerHolderToken =
|
|
|
|
WorkerHolderToken::Create(workerPrivate, Closing,
|
|
|
|
WorkerHolderToken::AllowIdleShutdownStart);
|
|
|
|
if (NS_WARN_IF(!workerHolderToken)) {
|
|
|
|
Shutdown();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientManagerChild* actor = new ClientManagerChild(workerHolderToken);
|
|
|
|
PClientManagerChild *sentActor =
|
|
|
|
parentActor->SendPClientManagerConstructor(actor);
|
|
|
|
if (NS_WARN_IF(!sentActor)) {
|
|
|
|
Shutdown();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(sentActor == actor);
|
|
|
|
|
|
|
|
ActivateThing(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientManager::~ClientManager()
|
|
|
|
{
|
|
|
|
NS_ASSERT_OWNINGTHREAD(ClientManager);
|
|
|
|
|
|
|
|
Shutdown();
|
|
|
|
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(this == PR_GetThreadPrivate(sClientManagerThreadLocalIndex));
|
2017-11-10 11:21:26 +03:00
|
|
|
|
|
|
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
2017-11-09 08:19:59 +03:00
|
|
|
PRStatus status =
|
2017-11-10 11:21:26 +03:00
|
|
|
#endif
|
2017-11-09 08:19:59 +03:00
|
|
|
PR_SetThreadPrivate(sClientManagerThreadLocalIndex, nullptr);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ClientManager::Shutdown()
|
|
|
|
{
|
|
|
|
NS_ASSERT_OWNINGTHREAD(ClientManager);
|
|
|
|
|
|
|
|
if (IsShutdown()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShutdownThing();
|
|
|
|
}
|
|
|
|
|
2017-11-09 08:19:59 +03:00
|
|
|
UniquePtr<ClientSource>
|
|
|
|
ClientManager::CreateSourceInternal(ClientType aType,
|
2017-11-16 21:15:10 +03:00
|
|
|
nsISerialEventTarget* aEventTarget,
|
2017-11-09 08:19:59 +03:00
|
|
|
const PrincipalInfo& aPrincipal)
|
|
|
|
{
|
|
|
|
NS_ASSERT_OWNINGTHREAD(ClientManager);
|
|
|
|
|
|
|
|
if (IsShutdown()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsID id;
|
|
|
|
nsresult rv = nsContentUtils::GenerateUUIDInPlace(id);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
|
2017-11-16 21:15:10 +03:00
|
|
|
UniquePtr<ClientSource> source(new ClientSource(this, aEventTarget, args));
|
2017-11-09 08:19:59 +03:00
|
|
|
source->Activate(GetActor());
|
|
|
|
|
|
|
|
return Move(source);
|
|
|
|
}
|
|
|
|
|
2017-11-09 08:20:00 +03:00
|
|
|
already_AddRefed<ClientHandle>
|
|
|
|
ClientManager::CreateHandleInternal(const ClientInfo& aClientInfo,
|
|
|
|
nsISerialEventTarget* aSerialEventTarget)
|
|
|
|
{
|
|
|
|
NS_ASSERT_OWNINGTHREAD(ClientManager);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(aSerialEventTarget);
|
|
|
|
|
|
|
|
if (IsShutdown()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ClientHandle> handle = new ClientHandle(this, aSerialEventTarget,
|
|
|
|
aClientInfo);
|
|
|
|
handle->Activate(GetActor());
|
|
|
|
|
|
|
|
return handle.forget();
|
|
|
|
}
|
|
|
|
|
2017-11-09 08:19:59 +03:00
|
|
|
already_AddRefed<ClientOpPromise>
|
|
|
|
ClientManager::StartOp(const ClientOpConstructorArgs& aArgs,
|
|
|
|
nsISerialEventTarget* aSerialEventTarget)
|
|
|
|
{
|
|
|
|
RefPtr<ClientOpPromise::Private> promise =
|
|
|
|
new ClientOpPromise::Private(__func__);
|
|
|
|
|
|
|
|
// Hold a ref to the client until the remote operation completes. Otherwise
|
|
|
|
// the ClientHandle might get de-refed and teardown the actor before we
|
|
|
|
// get an answer.
|
|
|
|
RefPtr<ClientManager> kungFuGrip = this;
|
|
|
|
promise->Then(aSerialEventTarget, __func__,
|
|
|
|
[kungFuGrip] (const ClientOpResult&) { },
|
|
|
|
[kungFuGrip] (nsresult) { });
|
|
|
|
|
|
|
|
MaybeExecute([aArgs, promise] (ClientManagerChild* aActor) {
|
|
|
|
ClientManagerOpChild* actor = new ClientManagerOpChild(aArgs, promise);
|
|
|
|
if (!aActor->SendPClientManagerOpConstructor(actor, aArgs)) {
|
|
|
|
// Constructor failure will reject promise via ActorDestroy()
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
RefPtr<ClientOpPromise> ref = promise.get();
|
|
|
|
return ref.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
already_AddRefed<ClientManager>
|
|
|
|
ClientManager::GetOrCreateForCurrentThread()
|
|
|
|
{
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(sClientManagerThreadLocalIndex != kBadThreadLocalIndex);
|
|
|
|
RefPtr<ClientManager> cm =
|
|
|
|
static_cast<ClientManager*>(PR_GetThreadPrivate(sClientManagerThreadLocalIndex));
|
|
|
|
|
|
|
|
if (!cm) {
|
|
|
|
cm = new ClientManager();
|
|
|
|
|
2017-11-10 11:21:26 +03:00
|
|
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
2017-11-09 08:19:59 +03:00
|
|
|
PRStatus status =
|
2017-11-10 11:21:26 +03:00
|
|
|
#endif
|
2017-11-09 08:19:59 +03:00
|
|
|
PR_SetThreadPrivate(sClientManagerThreadLocalIndex, cm.get());
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(cm);
|
|
|
|
return cm.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
WorkerPrivate*
|
|
|
|
ClientManager::GetWorkerPrivate() const
|
|
|
|
{
|
|
|
|
NS_ASSERT_OWNINGTHREAD(ClientManager);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(GetActor());
|
|
|
|
return GetActor()->GetWorkerPrivate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
|
|
|
ClientManager::Startup()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-11-10 11:21:26 +03:00
|
|
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
2017-11-09 08:19:59 +03:00
|
|
|
PRStatus status =
|
2017-11-10 11:21:26 +03:00
|
|
|
#endif
|
2017-11-09 08:19:59 +03:00
|
|
|
PR_NewThreadPrivateIndex(&sClientManagerThreadLocalIndex, nullptr);
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
|
2017-11-14 22:36:45 +03:00
|
|
|
|
|
|
|
ClientPrefsInit();
|
2017-11-09 08:19:59 +03:00
|
|
|
}
|
|
|
|
|
2017-11-09 08:19:59 +03:00
|
|
|
// static
|
|
|
|
UniquePtr<ClientSource>
|
2017-11-16 21:15:10 +03:00
|
|
|
ClientManager::CreateSource(ClientType aType, nsISerialEventTarget* aEventTarget,
|
|
|
|
nsIPrincipal* aPrincipal)
|
2017-11-09 08:19:59 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
|
|
|
|
PrincipalInfo principalInfo;
|
|
|
|
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
2017-11-16 21:15:10 +03:00
|
|
|
return mgr->CreateSourceInternal(aType, aEventTarget, principalInfo);
|
2017-11-09 08:19:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
UniquePtr<ClientSource>
|
2017-11-16 21:15:10 +03:00
|
|
|
ClientManager::CreateSource(ClientType aType, nsISerialEventTarget* aEventTarget,
|
|
|
|
const PrincipalInfo& aPrincipal)
|
2017-11-09 08:19:59 +03:00
|
|
|
{
|
|
|
|
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
2017-11-16 21:15:10 +03:00
|
|
|
return mgr->CreateSourceInternal(aType, aEventTarget, aPrincipal);
|
2017-11-09 08:19:59 +03:00
|
|
|
}
|
|
|
|
|
2017-11-09 08:20:00 +03:00
|
|
|
// static
|
|
|
|
already_AddRefed<ClientHandle>
|
|
|
|
ClientManager::CreateHandle(const ClientInfo& aClientInfo,
|
|
|
|
nsISerialEventTarget* aSerialEventTarget)
|
|
|
|
{
|
|
|
|
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
|
|
|
return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
|
|
|
|
}
|
|
|
|
|
2017-11-09 08:19:59 +03:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|