mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 977762 - 'Provide a mechanism to get the PContentParent associated with a PBackgroundParent'. r=mrbkap.
This commit is contained in:
parent
85bbd9301e
commit
f90d07c4fd
@ -35,6 +35,12 @@
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "prthread.h"
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
#define THREADSAFETY_ASSERT MOZ_ASSERT
|
||||
#else
|
||||
#define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT
|
||||
#endif
|
||||
|
||||
#define CRASH_IN_CHILD_PROCESS(_msg) \
|
||||
do { \
|
||||
if (IsMainProcess()) { \
|
||||
@ -86,7 +92,7 @@ AssertIsInChildProcess()
|
||||
void
|
||||
AssertIsOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
THREADSAFETY_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -174,10 +180,18 @@ private:
|
||||
// deleting it on the wrong thread. Only non-null for other-process actors.
|
||||
Transport* mTransport;
|
||||
|
||||
// Set when the actor is opened successfully and used to handle shutdown
|
||||
// hangs. Only touched on the background thread.
|
||||
nsTArray<ParentImpl*>* mLiveActorArray;
|
||||
|
||||
// Used to assert things in DEBUG builds.
|
||||
DebugOnly<bool> mIsOtherProcessActorDEBUG;
|
||||
// Set at construction to indicate whether this parent actor corresponds to a
|
||||
// child actor in another process or to a child actor from a different thread
|
||||
// in the same process.
|
||||
const bool mIsOtherProcessActor;
|
||||
|
||||
// Set after ActorDestroy has been called. Only touched on the background
|
||||
// thread.
|
||||
bool mActorDestroyed;
|
||||
|
||||
public:
|
||||
static bool
|
||||
@ -192,7 +206,7 @@ public:
|
||||
static void
|
||||
AssertIsOnBackgroundThread()
|
||||
{
|
||||
MOZ_ASSERT(IsOnBackgroundThread());
|
||||
THREADSAFETY_ASSERT(IsOnBackgroundThread());
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ParentImpl)
|
||||
@ -201,6 +215,14 @@ public:
|
||||
Destroy();
|
||||
|
||||
private:
|
||||
// Forwarded from BackgroundParent.
|
||||
static bool
|
||||
IsOtherProcessActor(PBackgroundParent* aBackgroundActor);
|
||||
|
||||
// Forwarded from BackgroundParent.
|
||||
static already_AddRefed<ContentParent>
|
||||
GetContentParent(PBackgroundParent* aBackgroundActor);
|
||||
|
||||
// Forwarded from BackgroundParent.
|
||||
static PBackgroundParent*
|
||||
Alloc(ContentParent* aContent,
|
||||
@ -218,8 +240,8 @@ private:
|
||||
|
||||
// For same-process actors.
|
||||
ParentImpl()
|
||||
: mTransport(nullptr), mLiveActorArray(nullptr),
|
||||
mIsOtherProcessActorDEBUG(false)
|
||||
: mTransport(nullptr), mLiveActorArray(nullptr), mIsOtherProcessActor(false),
|
||||
mActorDestroyed(false)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnMainThread();
|
||||
@ -230,7 +252,7 @@ private:
|
||||
// For other-process actors.
|
||||
ParentImpl(ContentParent* aContent, Transport* aTransport)
|
||||
: mContent(aContent), mTransport(aTransport), mLiveActorArray(nullptr),
|
||||
mIsOtherProcessActorDEBUG(true)
|
||||
mIsOtherProcessActor(true), mActorDestroyed(false)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnMainThread();
|
||||
@ -257,7 +279,7 @@ private:
|
||||
MOZ_ASSERT(aLiveActorArray);
|
||||
MOZ_ASSERT(!aLiveActorArray->Contains(this));
|
||||
MOZ_ASSERT(!mLiveActorArray);
|
||||
MOZ_ASSERT(mIsOtherProcessActorDEBUG);
|
||||
MOZ_ASSERT(mIsOtherProcessActor);
|
||||
|
||||
mLiveActorArray = aLiveActorArray;
|
||||
mLiveActorArray->AppendElement(this);
|
||||
@ -318,7 +340,11 @@ class ChildImpl MOZ_FINAL : public BackgroundChildImpl
|
||||
// create the background thread after application shutdown has started.
|
||||
static bool sShutdownHasStarted;
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
DebugOnly<nsIThread*> mBoundThread;
|
||||
#else
|
||||
nsIThread* mBoundThread;
|
||||
#endif
|
||||
|
||||
public:
|
||||
static bool
|
||||
@ -330,15 +356,18 @@ public:
|
||||
void
|
||||
AssertIsOnBoundThread()
|
||||
{
|
||||
MOZ_ASSERT(mBoundThread);
|
||||
THREADSAFETY_ASSERT(mBoundThread);
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
DebugOnly<bool> current;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(mBoundThread->IsOnCurrentThread(¤t)));
|
||||
|
||||
MOZ_ASSERT(current);
|
||||
#else
|
||||
bool current;
|
||||
#endif
|
||||
THREADSAFETY_ASSERT(
|
||||
NS_SUCCEEDED(mBoundThread->IsOnCurrentThread(¤t)));
|
||||
THREADSAFETY_ASSERT(current);
|
||||
}
|
||||
|
||||
|
||||
ChildImpl()
|
||||
: mBoundThread(nullptr)
|
||||
{
|
||||
@ -387,11 +416,13 @@ private:
|
||||
void
|
||||
SetBoundThread()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!mBoundThread);
|
||||
THREADSAFETY_ASSERT(!mBoundThread);
|
||||
|
||||
#if defined(DEBUG) || !defined(RELEASE_BUILD)
|
||||
mBoundThread = NS_GetCurrentThread();
|
||||
MOZ_ASSERT(mBoundThread);
|
||||
#endif
|
||||
|
||||
THREADSAFETY_ASSERT(mBoundThread);
|
||||
}
|
||||
|
||||
// Only called by IPDL.
|
||||
@ -740,6 +771,20 @@ AssertIsOnBackgroundThread()
|
||||
// BackgroundParent Public Methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
bool
|
||||
BackgroundParent::IsOtherProcessActor(PBackgroundParent* aBackgroundActor)
|
||||
{
|
||||
return ParentImpl::IsOtherProcessActor(aBackgroundActor);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<ContentParent>
|
||||
BackgroundParent::GetContentParent(PBackgroundParent* aBackgroundActor)
|
||||
{
|
||||
return ParentImpl::GetContentParent(aBackgroundActor);
|
||||
}
|
||||
|
||||
// static
|
||||
PBackgroundParent*
|
||||
BackgroundParent::Alloc(ContentParent* aContent,
|
||||
@ -826,6 +871,46 @@ bool ChildImpl::sShutdownHasStarted = false;
|
||||
// ParentImpl Implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
bool
|
||||
ParentImpl::IsOtherProcessActor(PBackgroundParent* aBackgroundActor)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aBackgroundActor);
|
||||
|
||||
return static_cast<ParentImpl*>(aBackgroundActor)->mIsOtherProcessActor;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<ContentParent>
|
||||
ParentImpl::GetContentParent(PBackgroundParent* aBackgroundActor)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aBackgroundActor);
|
||||
|
||||
auto actor = static_cast<ParentImpl*>(aBackgroundActor);
|
||||
if (actor->mActorDestroyed) {
|
||||
MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (actor->mContent) {
|
||||
// We need to hand out a reference to our ContentParent but we also need to
|
||||
// keep the one we have. We can't call AddRef here because ContentParent is
|
||||
// not threadsafe so instead we dispatch a runnable to the main thread to do
|
||||
// it for us. This is safe since we are guaranteed that our AddRef runnable
|
||||
// will run before the reference we hand out can be released, and the
|
||||
// ContentParent can't die as long as the existing reference is maintained.
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewNonOwningRunnableMethod(actor->mContent, &ContentParent::AddRef);
|
||||
MOZ_ASSERT(runnable);
|
||||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
||||
}
|
||||
|
||||
return actor->mContent.get();
|
||||
}
|
||||
|
||||
// static
|
||||
PBackgroundParent*
|
||||
ParentImpl::Alloc(ContentParent* aContent,
|
||||
@ -1095,10 +1180,10 @@ ParentImpl::MainThreadActorDestroy()
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActorDEBUG, mContent);
|
||||
MOZ_ASSERT_IF(!mIsOtherProcessActorDEBUG, !mContent);
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActorDEBUG, mTransport);
|
||||
MOZ_ASSERT_IF(!mIsOtherProcessActorDEBUG, !mTransport);
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActor, mContent);
|
||||
MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent);
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActor, mTransport);
|
||||
MOZ_ASSERT_IF(!mIsOtherProcessActor, !mTransport);
|
||||
|
||||
if (mTransport) {
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
@ -1167,10 +1252,13 @@ ParentImpl::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActorDEBUG, mLiveActorArray);
|
||||
MOZ_ASSERT(!mActorDestroyed);
|
||||
MOZ_ASSERT_IF(mIsOtherProcessActor, mLiveActorArray);
|
||||
|
||||
BackgroundParentImpl::ActorDestroy(aWhy);
|
||||
|
||||
mActorDestroyed = true;
|
||||
|
||||
if (mLiveActorArray) {
|
||||
MOZ_ALWAYS_TRUE(mLiveActorArray->RemoveElement(this));
|
||||
mLiveActorArray = nullptr;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
template <class> class already_AddRefed;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -20,8 +22,8 @@ namespace ipc {
|
||||
|
||||
class PBackgroundParent;
|
||||
|
||||
// This class is not designed for public consumption. It must only be used by
|
||||
// ContentParent.
|
||||
// This class is not designed for public consumption beyond the few static
|
||||
// member functions.
|
||||
class BackgroundParent MOZ_FINAL
|
||||
{
|
||||
friend class mozilla::dom::ContentParent;
|
||||
@ -30,6 +32,25 @@ class BackgroundParent MOZ_FINAL
|
||||
typedef mozilla::dom::ContentParent ContentParent;
|
||||
typedef mozilla::ipc::Transport Transport;
|
||||
|
||||
public:
|
||||
// This function allows the caller to determine if the given parent actor
|
||||
// corresponds to a child actor from another process or a child actor from a
|
||||
// different thread in the same process.
|
||||
// This function may only be called on the background thread.
|
||||
static bool
|
||||
IsOtherProcessActor(PBackgroundParent* aBackgroundActor);
|
||||
|
||||
// This function returns the ContentParent associated with the parent actor if
|
||||
// the parent actor corresponds to a child actor from another process. If the
|
||||
// parent actor corresponds to a child actor from a different thread in the
|
||||
// same process then this function returns null.
|
||||
// This function may only be called on the background thread. However,
|
||||
// ContentParent is not threadsafe and the returned pointer may not be used on
|
||||
// any thread other than the main thread. Callers must take care to use (and
|
||||
// release) the returned pointer appropriately.
|
||||
static already_AddRefed<ContentParent>
|
||||
GetContentParent(PBackgroundParent* aBackgroundActor);
|
||||
|
||||
private:
|
||||
// Only called by ContentParent for cross-process actors.
|
||||
static PBackgroundParent*
|
||||
|
Loading…
Reference in New Issue
Block a user