Bug 1415779 P4 Add ClientHandle class and make it attach to the correct ClientSource. r=baku

This commit is contained in:
Ben Kelly 2017-11-08 21:20:00 -08:00
Родитель a973dff21c
Коммит d7eca2ba76
10 изменённых файлов: 267 добавлений и 0 удалений

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

@ -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

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

@ -27,6 +27,10 @@ ClientHandleParent::RecvTeardown()
void
ClientHandleParent::ActorDestroy(ActorDestroyReason aReason)
{
if (mSource) {
mSource->DetachHandle(this);
mSource = nullptr;
}
}
PClientHandleOpParent*
@ -53,16 +57,31 @@ ClientHandleParent::RecvPClientHandleOpConstructor(PClientHandleOpParent* aActor
ClientHandleParent::ClientHandleParent()
: mService(ClientManagerService::GetOrCreateInstance())
, mSource(nullptr)
{
}
ClientHandleParent::~ClientHandleParent()
{
MOZ_DIAGNOSTIC_ASSERT(!mSource);
}
void
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

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

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

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

@ -6,6 +6,7 @@
#include "ClientManager.h"
#include "ClientHandle.h"
#include "ClientManagerChild.h"
#include "ClientManagerOpChild.h"
#include "ClientSource.h"
@ -114,6 +115,24 @@ ClientManager::CreateSourceInternal(ClientType aType,
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)
@ -204,5 +223,14 @@ ClientManager::CreateSource(ClientType aType, const PrincipalInfo& aPrincipal)
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

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

@ -15,6 +15,8 @@ class PBackgroundChild;
} // namespace ipc
namespace dom {
class ClientHandle;
class ClientInfo;
class ClientManagerChild;
class ClientOpConstructorArgs;
class ClientSource;
@ -46,6 +48,10 @@ class ClientManager final : public ClientThing<ClientManagerChild>
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.
@ -76,6 +82,10 @@ public:
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)
};

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

@ -29,6 +29,14 @@ void
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*
@ -54,6 +62,7 @@ ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs)
ClientSourceParent::~ClientSourceParent()
{
MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
}
const ClientInfo&
@ -62,5 +71,21 @@ 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 mozilla

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

@ -12,12 +12,14 @@
namespace mozilla {
namespace dom {
class ClientHandleParent;
class ClientManagerService;
class ClientSourceParent final : public PClientSourceParent
{
ClientInfo mClientInfo;
RefPtr<ClientManagerService> mService;
nsTArray<ClientHandleParent*> mHandleList;
// PClientSourceParent
IPCResult
@ -38,6 +40,12 @@ public:
const ClientInfo&
Info() const;
void
AttachHandle(ClientHandleParent* aClientSource);
void
DetachHandle(ClientHandleParent* aClientSource);
};
} // namespace dom

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

@ -99,6 +99,11 @@ public:
MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
mActor->RevokeOwner(this);
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,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
'ClientHandle.h',
'ClientInfo.h',
'ClientIPCUtils.h',
'ClientManager.h',
@ -17,6 +18,7 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'ClientHandle.cpp',
'ClientHandleChild.cpp',
'ClientHandleOpChild.cpp',
'ClientHandleOpParent.cpp',