Merge inbound to mozilla-central a=merge

This commit is contained in:
dluca 2017-11-09 15:56:43 +02:00
Родитель c748db6076 1911626bf9
Коммит 30ead7d1ae
26 изменённых файлов: 946 добавлений и 26 удалений

Просмотреть файл

@ -0,0 +1,99 @@
/* -*- 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 "ClientHandle.h"
#include "ClientHandleChild.h"
#include "ClientHandleOpChild.h"
#include "ClientManager.h"
#include "mozilla/dom/PClientManagerChild.h"
namespace mozilla {
namespace dom {
ClientHandle::~ClientHandle()
{
Shutdown();
}
void
ClientHandle::Shutdown()
{
NS_ASSERT_OWNINGTHREAD(ClientSource);
if (IsShutdown()) {
return;
}
ShutdownThing();
mManager = nullptr;
}
already_AddRefed<ClientOpPromise>
ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs)
{
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<ClientHandle> kungFuGrip = this;
promise->Then(mSerialEventTarget, __func__,
[kungFuGrip] (const ClientOpResult &) { },
[kungFuGrip] (nsresult) { });
MaybeExecute([aArgs, promise] (ClientHandleChild* aActor) {
ClientHandleOpChild* actor = new ClientHandleOpChild(aArgs, promise);
if (!aActor->SendPClientHandleOpConstructor(actor, aArgs)) {
// Constructor failure will reject promise via ActorDestroy()
return;
}
});
RefPtr<ClientOpPromise> ref = promise.get();
return ref.forget();
}
ClientHandle::ClientHandle(ClientManager* aManager,
nsISerialEventTarget* aSerialEventTarget,
const ClientInfo& aClientInfo)
: mManager(aManager)
, mSerialEventTarget(aSerialEventTarget)
, mClientInfo(aClientInfo)
{
MOZ_DIAGNOSTIC_ASSERT(mManager);
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
MOZ_ASSERT(mSerialEventTarget->IsOnCurrentThread());
}
void
ClientHandle::Activate(PClientManagerChild* aActor)
{
NS_ASSERT_OWNINGTHREAD(ClientHandle);
if (IsShutdown()) {
return;
}
PClientHandleChild* actor =
aActor->SendPClientHandleConstructor(mClientInfo.ToIPC());
if (!actor) {
Shutdown();
return;
}
ActivateThing(static_cast<ClientHandleChild*>(actor));
}
const ClientInfo&
ClientHandle::Info() const
{
return mClientInfo;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,66 @@
/* -*- 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/. */
#ifndef _mozilla_dom_ClientHandle_h
#define _mozilla_dom_ClientHandle_h
#include "mozilla/dom/ClientInfo.h"
#include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/ClientThing.h"
#ifdef XP_WIN
#undef PostMessage
#endif
namespace mozilla {
namespace dom {
class ClientManager;
class ClientHandleChild;
class ClientOpConstructorArgs;
class PClientManagerChild;
// The ClientHandle allows code to take a simple ClientInfo struct and
// convert it into a live actor-backed object attached to a particular
// ClientSource somewhere in the browser. If the ClientSource is
// destroyed then the ClientHandle will simply begin to reject operations.
// We do not currently provide a way to be notified when the ClientSource
// is destroyed, but this could be added in the future.
class ClientHandle final : public ClientThing<ClientHandleChild>
{
friend class ClientManager;
RefPtr<ClientManager> mManager;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
ClientInfo mClientInfo;
~ClientHandle();
void
Shutdown();
already_AddRefed<ClientOpPromise>
StartOp(const ClientOpConstructorArgs& aArgs);
// Private methods called by ClientManager
ClientHandle(ClientManager* aManager,
nsISerialEventTarget* aSerialEventTarget,
const ClientInfo& aClientInfo);
void
Activate(PClientManagerChild* aActor);
public:
const ClientInfo&
Info() const;
NS_INLINE_DECL_REFCOUNTING(ClientHandle);
};
} // namespace dom
} // namespace mozilla
#endif // _mozilla_dom_ClientHandle_h

Просмотреть файл

@ -7,6 +7,7 @@
#include "ClientHandleParent.h" #include "ClientHandleParent.h"
#include "ClientHandleOpParent.h" #include "ClientHandleOpParent.h"
#include "ClientManagerService.h"
#include "ClientSourceParent.h" #include "ClientSourceParent.h"
#include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -26,6 +27,10 @@ ClientHandleParent::RecvTeardown()
void void
ClientHandleParent::ActorDestroy(ActorDestroyReason aReason) ClientHandleParent::ActorDestroy(ActorDestroyReason aReason)
{ {
if (mSource) {
mSource->DetachHandle(this);
mSource = nullptr;
}
} }
PClientHandleOpParent* PClientHandleOpParent*
@ -51,16 +56,32 @@ ClientHandleParent::RecvPClientHandleOpConstructor(PClientHandleOpParent* aActor
} }
ClientHandleParent::ClientHandleParent() ClientHandleParent::ClientHandleParent()
: mService(ClientManagerService::GetOrCreateInstance())
, mSource(nullptr)
{ {
} }
ClientHandleParent::~ClientHandleParent() ClientHandleParent::~ClientHandleParent()
{ {
MOZ_DIAGNOSTIC_ASSERT(!mSource);
} }
void void
ClientHandleParent::Init(const IPCClientInfo& aClientInfo) ClientHandleParent::Init(const IPCClientInfo& aClientInfo)
{ {
mSource = mService->FindSource(aClientInfo.id(), aClientInfo.principalInfo());
if (!mSource) {
Unused << Send__delete__(this);
return;
}
mSource->AttachHandle(this);
}
ClientSourceParent*
ClientHandleParent::GetSource() const
{
return mSource;
} }
} // namespace dom } // namespace dom

Просмотреть файл

@ -11,8 +11,14 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class ClientManagerService;
class ClientSourceParent;
class ClientHandleParent final : public PClientHandleParent class ClientHandleParent final : public PClientHandleParent
{ {
RefPtr<ClientManagerService> mService;
ClientSourceParent* mSource;
// PClientHandleParent interface // PClientHandleParent interface
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
RecvTeardown() override; RecvTeardown() override;
@ -36,6 +42,9 @@ public:
void void
Init(const IPCClientInfo& aClientInfo); Init(const IPCClientInfo& aClientInfo);
ClientSourceParent*
GetSource() const;
}; };
} // namespace dom } // namespace dom

Просмотреть файл

@ -17,6 +17,10 @@ namespace dom {
struct ClientSourceConstructorArgs struct ClientSourceConstructorArgs
{ {
nsID id;
ClientType type;
PrincipalInfo principalInfo;
TimeStamp creationTime;
}; };
struct IPCClientInfo struct IPCClientInfo

Просмотреть файл

@ -0,0 +1,236 @@
/* -*- 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"
#include "ClientHandle.h"
#include "ClientManagerChild.h"
#include "ClientManagerOpChild.h"
#include "ClientSource.h"
#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;
using mozilla::ipc::PrincipalInfo;
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));
PRStatus status =
PR_SetThreadPrivate(sClientManagerThreadLocalIndex, nullptr);
MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
}
void
ClientManager::Shutdown()
{
NS_ASSERT_OWNINGTHREAD(ClientManager);
if (IsShutdown()) {
return;
}
ShutdownThing();
}
UniquePtr<ClientSource>
ClientManager::CreateSourceInternal(ClientType aType,
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());
UniquePtr<ClientSource> source(new ClientSource(this, args));
source->Activate(GetActor());
return Move(source);
}
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();
}
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();
PRStatus status =
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());
PRStatus status =
PR_NewThreadPrivateIndex(&sClientManagerThreadLocalIndex, nullptr);
MOZ_DIAGNOSTIC_ASSERT(status == PR_SUCCESS);
}
// static
UniquePtr<ClientSource>
ClientManager::CreateSource(ClientType aType, nsIPrincipal* aPrincipal)
{
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();
return mgr->CreateSourceInternal(aType, principalInfo);
}
// static
UniquePtr<ClientSource>
ClientManager::CreateSource(ClientType aType, const PrincipalInfo& aPrincipal)
{
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
return mgr->CreateSourceInternal(aType, aPrincipal);
}
// static
already_AddRefed<ClientHandle>
ClientManager::CreateHandle(const ClientInfo& aClientInfo,
nsISerialEventTarget* aSerialEventTarget)
{
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,95 @@
/* -*- 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/. */
#ifndef _mozilla_dom_ClientManager_h
#define _mozilla_dom_ClientManager_h
#include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/ClientThing.h"
namespace mozilla {
namespace ipc {
class PBackgroundChild;
} // namespace ipc
namespace dom {
class ClientHandle;
class ClientInfo;
class ClientManagerChild;
class ClientOpConstructorArgs;
class ClientSource;
enum class ClientType : uint8_t;
namespace workers {
class WorkerPrivate;
} // workers namespace
// The ClientManager provides a per-thread singleton interface workering
// with the client subsystem. It allows globals to create ClientSource
// objects. It allows other parts of the system to attach to this globals
// by creating ClientHandle objects. The ClientManager also provides
// methods for querying the list of clients active in the system.
class ClientManager final : public ClientThing<ClientManagerChild>
{
friend class ClientManagerChild;
ClientManager();
~ClientManager();
// Utility method to trigger a shutdown of the ClientManager. This
// is called in various error conditions or when the last reference
// is dropped.
void
Shutdown();
UniquePtr<ClientSource>
CreateSourceInternal(ClientType aType,
const mozilla::ipc::PrincipalInfo& aPrincipal);
already_AddRefed<ClientHandle>
CreateHandleInternal(const ClientInfo& aClientInfo,
nsISerialEventTarget* aSerialEventTarget);
// Utility method to perform an IPC operation. This will create a
// PClientManagerOp actor tied to a MozPromise. The promise will
// resolve or reject with the result of the remote operation.
already_AddRefed<ClientOpPromise>
StartOp(const ClientOpConstructorArgs& aArgs,
nsISerialEventTarget* aSerialEventTarget);
// Get or create the TLS singleton. Currently this is only used
// internally and external code indirectly calls it by invoking
// static methods.
static already_AddRefed<ClientManager>
GetOrCreateForCurrentThread();
// Private methods called by ClientSource
mozilla::dom::workers::WorkerPrivate*
GetWorkerPrivate() const;
public:
// 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.
static void
Startup();
static UniquePtr<ClientSource>
CreateSource(ClientType aType, nsIPrincipal* aPrincipal);
static UniquePtr<ClientSource>
CreateSource(ClientType aType, const mozilla::ipc::PrincipalInfo& aPrincipal);
static already_AddRefed<ClientHandle>
CreateHandle(const ClientInfo& aClientInfo,
nsISerialEventTarget* aSerialEventTarget);
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManager)
};
} // namespace dom
} // namespace mozilla
#endif // _mozilla_dom_ClientManager_h

Просмотреть файл

@ -14,6 +14,12 @@ ClientManagerOpParent::ActorDestroy(ActorDestroyReason aReason)
{ {
} }
ClientManagerOpParent::ClientManagerOpParent(ClientManagerService* aService)
: mService(aService)
{
MOZ_DIAGNOSTIC_ASSERT(mService);
}
void void
ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs) ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs)
{ {

Просмотреть файл

@ -15,12 +15,14 @@ class ClientManagerService;
class ClientManagerOpParent final : public PClientManagerOpParent class ClientManagerOpParent final : public PClientManagerOpParent
{ {
RefPtr<ClientManagerService> mService;
// PClientManagerOpParent interface // PClientManagerOpParent interface
void void
ActorDestroy(ActorDestroyReason aReason) override; ActorDestroy(ActorDestroyReason aReason) override;
public: public:
ClientManagerOpParent() = default; explicit ClientManagerOpParent(ClientManagerService* aService);
~ClientManagerOpParent() = default; ~ClientManagerOpParent() = default;
void void

Просмотреть файл

@ -8,6 +8,7 @@
#include "ClientHandleParent.h" #include "ClientHandleParent.h"
#include "ClientManagerOpParent.h" #include "ClientManagerOpParent.h"
#include "ClientManagerService.h"
#include "ClientSourceParent.h" #include "ClientSourceParent.h"
#include "mozilla/dom/PClientNavigateOpParent.h" #include "mozilla/dom/PClientNavigateOpParent.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -54,7 +55,7 @@ ClientManagerParent::RecvPClientHandleConstructor(PClientHandleParent* aActor,
PClientManagerOpParent* PClientManagerOpParent*
ClientManagerParent::AllocPClientManagerOpParent(const ClientOpConstructorArgs& aArgs) ClientManagerParent::AllocPClientManagerOpParent(const ClientOpConstructorArgs& aArgs)
{ {
return new ClientManagerOpParent(); return new ClientManagerOpParent(mService);
} }
bool bool
@ -101,6 +102,7 @@ ClientManagerParent::DeallocPClientSourceParent(PClientSourceParent* aActor)
} }
ClientManagerParent::ClientManagerParent() ClientManagerParent::ClientManagerParent()
: mService(ClientManagerService::GetOrCreateInstance())
{ {
} }

Просмотреть файл

@ -11,8 +11,12 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class ClientManagerService;
class ClientManagerParent final : public PClientManagerParent class ClientManagerParent final : public PClientManagerParent
{ {
RefPtr<ClientManagerService> mService;
// PClientManagerParent interface // PClientManagerParent interface
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
RecvTeardown() override; RecvTeardown() override;

Просмотреть файл

@ -0,0 +1,125 @@
/* -*- 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 "ClientManagerService.h"
#include "mozilla/ipc/BackgroundParent.h"
namespace mozilla {
namespace dom {
using mozilla::ipc::AssertIsOnBackgroundThread;
using mozilla::ipc::ContentPrincipalInfo;
namespace {
ClientManagerService* sClientManagerServiceInstance = nullptr;
bool
MatchPrincipalInfo(const PrincipalInfo& aLeft, const PrincipalInfo& aRight)
{
if (aLeft.type() != aRight.type()) {
return false;
}
switch (aLeft.type()) {
case PrincipalInfo::TContentPrincipalInfo:
{
const ContentPrincipalInfo& leftContent = aLeft.get_ContentPrincipalInfo();
const ContentPrincipalInfo& rightContent = aRight.get_ContentPrincipalInfo();
return leftContent.attrs() == rightContent.attrs() &&
leftContent.originNoSuffix() == rightContent.originNoSuffix();
}
case PrincipalInfo::TSystemPrincipalInfo:
{
// system principal always matches
return true;
}
case PrincipalInfo::TNullPrincipalInfo:
{
// null principal never matches
return false;
}
default:
{
break;
}
}
// Clients (windows/workers) should never have an expanded principal type.
MOZ_CRASH("unexpected principal type!");
}
} // anonymous namespace
ClientManagerService::ClientManagerService()
{
AssertIsOnBackgroundThread();
}
ClientManagerService::~ClientManagerService()
{
AssertIsOnBackgroundThread();
MOZ_DIAGNOSTIC_ASSERT(mSourceTable.Count() == 0);
MOZ_DIAGNOSTIC_ASSERT(sClientManagerServiceInstance == this);
sClientManagerServiceInstance = nullptr;
}
// static
already_AddRefed<ClientManagerService>
ClientManagerService::GetOrCreateInstance()
{
AssertIsOnBackgroundThread();
if (!sClientManagerServiceInstance) {
sClientManagerServiceInstance = new ClientManagerService();
}
RefPtr<ClientManagerService> ref(sClientManagerServiceInstance);
return ref.forget();
}
void
ClientManagerService::AddSource(ClientSourceParent* aSource)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aSource);
auto entry = mSourceTable.LookupForAdd(aSource->Info().Id());
MOZ_DIAGNOSTIC_ASSERT(!entry);
entry.OrInsert([&] { return aSource; });
}
void
ClientManagerService::RemoveSource(ClientSourceParent* aSource)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aSource);
auto entry = mSourceTable.Lookup(aSource->Info().Id());
MOZ_DIAGNOSTIC_ASSERT(entry);
entry.Remove();
}
ClientSourceParent*
ClientManagerService::FindSource(const nsID& aID, const PrincipalInfo& aPrincipalInfo)
{
AssertIsOnBackgroundThread();
auto entry = mSourceTable.Lookup(aID);
if (!entry) {
return nullptr;
}
ClientSourceParent* source = entry.Data();
if (!MatchPrincipalInfo(source->Info().PrincipalInfo(), aPrincipalInfo)) {
return nullptr;
}
return source;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,49 @@
/* -*- 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/. */
#ifndef _mozilla_dom_ClientManagerService_h
#define _mozilla_dom_ClientManagerService_h
#include "nsDataHashtable.h"
namespace mozilla {
namespace dom {
class ClientSourceParent;
// 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;
ClientManagerService();
~ClientManagerService();
public:
static already_AddRefed<ClientManagerService>
GetOrCreateInstance();
void
AddSource(ClientSourceParent* aSource);
void
RemoveSource(ClientSourceParent* aSource);
ClientSourceParent*
FindSource(const nsID& aID,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService)
};
} // namespace dom
} // namespace mozilla
#endif // _mozilla_dom_ClientManagerService_h

Просмотреть файл

@ -0,0 +1,68 @@
/* -*- 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 "ClientSource.h"
#include "ClientManager.h"
#include "ClientManagerChild.h"
#include "ClientSourceChild.h"
#include "mozilla/dom/ClientIPCTypes.h"
namespace mozilla {
namespace dom {
using mozilla::ipc::PrincipalInfo;
void
ClientSource::Shutdown()
{
NS_ASSERT_OWNINGTHREAD(ClientSource);
if (IsShutdown()) {
return;
}
ShutdownThing();
mManager = nullptr;
}
ClientSource::ClientSource(ClientManager* aManager,
const ClientSourceConstructorArgs& aArgs)
: mManager(aManager)
, mClientInfo(aArgs.id(), aArgs.type(), aArgs.principalInfo(), aArgs.creationTime())
{
MOZ_ASSERT(mManager);
}
void
ClientSource::Activate(PClientManagerChild* aActor)
{
NS_ASSERT_OWNINGTHREAD(ClientSource);
MOZ_ASSERT(!GetActor());
if (IsShutdown()) {
return;
}
ClientSourceConstructorArgs args(mClientInfo.Id(), mClientInfo.Type(),
mClientInfo.PrincipalInfo(),
mClientInfo.CreationTime());
PClientSourceChild* actor = aActor->SendPClientSourceConstructor(args);
if (!actor) {
Shutdown();
return;
}
ActivateThing(static_cast<ClientSourceChild*>(actor));
}
ClientSource::~ClientSource()
{
Shutdown();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- 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/. */
#ifndef _mozilla_dom_ClientSource_h
#define _mozilla_dom_ClientSource_h
#include "mozilla/dom/ClientInfo.h"
#include "mozilla/dom/ClientThing.h"
namespace mozilla {
namespace dom {
class ClientManager;
class ClientSourceChild;
class ClientSourceConstructorArgs;
class PClientManagerChild;
namespace workers {
class WorkerPrivate;
} // workers namespace
// ClientSource is an RAII style class that is designed to be held via
// a UniquePtr<>. When created ClientSource will register the existence
// of a client in the cross-process ClientManagerService. When the
// ClientSource is destroyed then client entry will be removed. Code
// that represents globals or browsing environments, such as nsGlobalWindow
// or WorkerPrivate, should use ClientManager to create a ClientSource.
class ClientSource final : public ClientThing<ClientSourceChild>
{
friend class ClientManager;
NS_DECL_OWNINGTHREAD
RefPtr<ClientManager> mManager;
ClientInfo mClientInfo;
void
Shutdown();
// Private methods called by ClientManager
ClientSource(ClientManager* aManager,
const ClientSourceConstructorArgs& aArgs);
void
Activate(PClientManagerChild* aActor);
public:
~ClientSource();
};
} // namespace dom
} // namespace mozilla
#endif // _mozilla_dom_ClientSource_h

Просмотреть файл

@ -7,6 +7,7 @@
#include "ClientSourceChild.h" #include "ClientSourceChild.h"
#include "ClientSourceOpChild.h" #include "ClientSourceOpChild.h"
#include "ClientThing.h"
#include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"

Просмотреть файл

@ -7,6 +7,7 @@
#include "ClientSourceParent.h" #include "ClientSourceParent.h"
#include "ClientHandleParent.h" #include "ClientHandleParent.h"
#include "ClientManagerService.h"
#include "ClientSourceOpParent.h" #include "ClientSourceOpParent.h"
#include "mozilla/dom/ClientIPCTypes.h" #include "mozilla/dom/ClientIPCTypes.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -27,6 +28,15 @@ ClientSourceParent::RecvTeardown()
void void
ClientSourceParent::ActorDestroy(ActorDestroyReason aReason) ClientSourceParent::ActorDestroy(ActorDestroyReason aReason)
{ {
mService->RemoveSource(this);
nsTArray<ClientHandleParent*> handleList(mHandleList);
for (ClientHandleParent* handle : handleList) {
// This should trigger DetachHandle() to be called removing
// the entry from the mHandleList.
Unused << ClientHandleParent::Send__delete__(handle);
}
MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
} }
PClientSourceOpParent* PClientSourceOpParent*
@ -44,11 +54,37 @@ ClientSourceParent::DeallocPClientSourceOpParent(PClientSourceOpParent* aActor)
} }
ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs) ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs)
: mClientInfo(aArgs.id(), aArgs.type(), aArgs.principalInfo(), aArgs.creationTime())
, mService(ClientManagerService::GetOrCreateInstance())
{ {
mService->AddSource(this);
} }
ClientSourceParent::~ClientSourceParent() ClientSourceParent::~ClientSourceParent()
{ {
MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
}
const ClientInfo&
ClientSourceParent::Info() const
{
return mClientInfo;
}
void
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
{
MOZ_DIAGNOSTIC_ASSERT(aClientHandle);
MOZ_ASSERT(!mHandleList.Contains(aClientHandle));
mHandleList.AppendElement(aClientHandle);
}
void
ClientSourceParent::DetachHandle(ClientHandleParent* aClientHandle)
{
MOZ_DIAGNOSTIC_ASSERT(aClientHandle);
MOZ_ASSERT(mHandleList.Contains(aClientHandle));
mHandleList.RemoveElement(aClientHandle);
} }
} // namespace dom } // namespace dom

Просмотреть файл

@ -6,13 +6,21 @@
#ifndef _mozilla_dom_ClientSourceParent_h #ifndef _mozilla_dom_ClientSourceParent_h
#define _mozilla_dom_ClientSourceParent_h #define _mozilla_dom_ClientSourceParent_h
#include "ClientInfo.h"
#include "mozilla/dom/PClientSourceParent.h" #include "mozilla/dom/PClientSourceParent.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class ClientHandleParent;
class ClientManagerService;
class ClientSourceParent final : public PClientSourceParent class ClientSourceParent final : public PClientSourceParent
{ {
ClientInfo mClientInfo;
RefPtr<ClientManagerService> mService;
nsTArray<ClientHandleParent*> mHandleList;
// PClientSourceParent // PClientSourceParent
IPCResult IPCResult
RecvTeardown() override; RecvTeardown() override;
@ -29,6 +37,15 @@ class ClientSourceParent final : public PClientSourceParent
public: public:
explicit ClientSourceParent(const ClientSourceConstructorArgs& aArgs); explicit ClientSourceParent(const ClientSourceConstructorArgs& aArgs);
~ClientSourceParent(); ~ClientSourceParent();
const ClientInfo&
Info() const;
void
AttachHandle(ClientHandleParent* aClientSource);
void
DetachHandle(ClientHandleParent* aClientSource);
}; };
} // namespace dom } // namespace dom

Просмотреть файл

@ -99,6 +99,11 @@ public:
MOZ_DIAGNOSTIC_ASSERT(mActor == aActor); MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
mActor->RevokeOwner(this); mActor->RevokeOwner(this);
mActor = nullptr; mActor = nullptr;
// Also consider the ClientThing shutdown. We simply set the flag
// instead of calling ShutdownThing() to avoid calling MaybeStartTeardown()
// on the destroyed actor.
mShutdown = true;
} }
}; };

Просмотреть файл

@ -5,31 +5,38 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [ EXPORTS.mozilla.dom += [
'ClientHandle.h',
'ClientInfo.h', 'ClientInfo.h',
'ClientIPCUtils.h', 'ClientIPCUtils.h',
'ClientManager.h',
'ClientManagerActors.h', 'ClientManagerActors.h',
'ClientOpenWindowOpActors.h', 'ClientOpenWindowOpActors.h',
'ClientOpPromise.h', 'ClientOpPromise.h',
'ClientSource.h',
'ClientState.h', 'ClientState.h',
'ClientThing.h', 'ClientThing.h',
] ]
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'ClientHandle.cpp',
'ClientHandleChild.cpp', 'ClientHandleChild.cpp',
'ClientHandleOpChild.cpp', 'ClientHandleOpChild.cpp',
'ClientHandleOpParent.cpp', 'ClientHandleOpParent.cpp',
'ClientHandleParent.cpp', 'ClientHandleParent.cpp',
'ClientInfo.cpp', 'ClientInfo.cpp',
'ClientManager.cpp',
'ClientManagerActors.cpp', 'ClientManagerActors.cpp',
'ClientManagerChild.cpp', 'ClientManagerChild.cpp',
'ClientManagerOpChild.cpp', 'ClientManagerOpChild.cpp',
'ClientManagerOpParent.cpp', 'ClientManagerOpParent.cpp',
'ClientManagerParent.cpp', 'ClientManagerParent.cpp',
'ClientManagerService.cpp',
'ClientNavigateOpChild.cpp', 'ClientNavigateOpChild.cpp',
'ClientNavigateOpParent.cpp', 'ClientNavigateOpParent.cpp',
'ClientOpenWindowOpActors.cpp', 'ClientOpenWindowOpActors.cpp',
'ClientOpenWindowOpChild.cpp', 'ClientOpenWindowOpChild.cpp',
'ClientOpenWindowOpParent.cpp', 'ClientOpenWindowOpParent.cpp',
'ClientSource.cpp',
'ClientSourceChild.cpp', 'ClientSourceChild.cpp',
'ClientSourceOpChild.cpp', 'ClientSourceOpChild.cpp',
'ClientSourceOpParent.cpp', 'ClientSourceOpParent.cpp',
@ -52,6 +59,7 @@ IPDL_SOURCES += [
include('/ipc/chromium/chromium-config.mozbuild') include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'/dom/workers',
] ]
FINAL_LIBRARY = 'xul' FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/TelemetryIPC.h" #include "mozilla/TelemetryIPC.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h" #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
#include "mozilla/docshell/OfflineCacheUpdateChild.h" #include "mozilla/docshell/OfflineCacheUpdateChild.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h" #include "mozilla/dom/ClientOpenWindowOpActors.h"
#include "mozilla/dom/ContentBridgeChild.h" #include "mozilla/dom/ContentBridgeChild.h"
#include "mozilla/dom/ContentBridgeParent.h" #include "mozilla/dom/ContentBridgeParent.h"
@ -1154,6 +1155,8 @@ ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit,
return; return;
} }
ClientManager::Startup();
nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (!svc) { if (!svc) {
NS_WARNING("Couldn't acquire console service"); NS_WARNING("Couldn't acquire console service");

Просмотреть файл

@ -34,6 +34,7 @@
#include "mozilla/DataStorage.h" #include "mozilla/DataStorage.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h" #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h" #include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h" #include "mozilla/dom/ClientOpenWindowOpActors.h"
#include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
@ -628,6 +629,7 @@ ContentParent::StartUp()
mozilla::dom::time::InitializeDateCacheCleaner(); mozilla::dom::time::InitializeDateCacheCleaner();
BackgroundChild::Startup(); BackgroundChild::Startup();
ClientManager::Startup();
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS"); sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");

Просмотреть файл

@ -0,0 +1,12 @@
try {
WebAssembly.compileStreaming();
} catch (err) {
assertEq(String(err).indexOf("not supported with --no-threads") !== -1, true);
quit();
}
if (!this.oomAfterAllocations)
quit();
oomAfterAllocations(1, 2);
var x = wasmTextToBinary('(module (func (export "run") (result i32) i32.const 42))');
WebAssembly.compileStreaming(x);
drainJobQueue();

Просмотреть файл

@ -135,8 +135,7 @@ js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleOb
RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncFunction, length, RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncFunction, length,
JSFunction::NATIVE_FUN, nullptr, JSFunction::NATIVE_FUN, nullptr,
funName, proto, funName, proto,
AllocKind::FUNCTION_EXTENDED, AllocKind::FUNCTION_EXTENDED));
TenuredObject));
if (!wrapped) if (!wrapped)
return nullptr; return nullptr;

Просмотреть файл

@ -80,8 +80,7 @@ js::WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleO
RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncGenerator, length, RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncGenerator, length,
JSFunction::NATIVE_FUN, nullptr, JSFunction::NATIVE_FUN, nullptr,
funName, proto, funName, proto,
AllocKind::FUNCTION_EXTENDED, AllocKind::FUNCTION_EXTENDED));
TenuredObject));
if (!wrapped) if (!wrapped)
return nullptr; return nullptr;

Просмотреть файл

@ -1851,17 +1851,25 @@ WebAssembly_toSource(JSContext* cx, unsigned argc, Value* vp)
} }
#endif #endif
static bool
RejectWithPendingException(JSContext* cx, Handle<PromiseObject*> promise)
{
if (!cx->isExceptionPending())
return false;
RootedValue rejectionValue(cx);
if (!GetAndClearException(cx, &rejectionValue))
return false;
return PromiseObject::reject(cx, promise, rejectionValue);
}
static bool static bool
Reject(JSContext* cx, const CompileArgs& args, UniqueChars error, Handle<PromiseObject*> promise) Reject(JSContext* cx, const CompileArgs& args, UniqueChars error, Handle<PromiseObject*> promise)
{ {
if (!error) { if (!error) {
ReportOutOfMemory(cx); ReportOutOfMemory(cx);
return RejectWithPendingException(cx, promise);
RootedValue rejectionValue(cx);
if (!cx->getPendingException(&rejectionValue))
return false;
return PromiseObject::reject(cx, promise, rejectionValue);
} }
RootedObject stack(cx, promise->allocationSite()); RootedObject stack(cx, promise->allocationSite());
@ -1892,19 +1900,6 @@ Reject(JSContext* cx, const CompileArgs& args, UniqueChars error, Handle<Promise
return PromiseObject::reject(cx, promise, rejectionValue); return PromiseObject::reject(cx, promise, rejectionValue);
} }
static bool
RejectWithPendingException(JSContext* cx, Handle<PromiseObject*> promise)
{
if (!cx->isExceptionPending())
return false;
RootedValue rejectionValue(cx);
if (!GetAndClearException(cx, &rejectionValue))
return false;
return PromiseObject::reject(cx, promise, rejectionValue);
}
static bool static bool
Resolve(JSContext* cx, Module& module, const CompileArgs& compileArgs, Resolve(JSContext* cx, Module& module, const CompileArgs& compileArgs,
Handle<PromiseObject*> promise, bool instantiate, HandleObject importObj) Handle<PromiseObject*> promise, bool instantiate, HandleObject importObj)
@ -2522,7 +2517,7 @@ ResolveResponse(JSContext* cx, CallArgs callArgs, Handle<PromiseObject*> promise
RootedFunction onRejected(cx, NewNativeFunction(cx, ResolveResponse_OnRejected, 1, nullptr, RootedFunction onRejected(cx, NewNativeFunction(cx, ResolveResponse_OnRejected, 1, nullptr,
gc::AllocKind::FUNCTION_EXTENDED)); gc::AllocKind::FUNCTION_EXTENDED));
if (!onResolved) if (!onRejected)
return false; return false;
onResolved->setExtendedSlot(0, ObjectValue(*closure)); onResolved->setExtendedSlot(0, ObjectValue(*closure));