зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1415779
P4 Add ClientHandle class and make it attach to the correct ClientSource. r=baku
This commit is contained in:
Родитель
a973dff21c
Коммит
d7eca2ba76
|
@ -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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче