forked from Floorp-Projects/Floorp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1487249 - Part 2: Add a new PInProcess actor to manage intra-thre…
…ad actors, r=mccr8 This will be useful as a basis for asynchronous actors which would like to exist both when crossing the process boundary (managed by PContent), and when displaying an in-process window. Differential Revision: https://phabricator.services.mozilla.com/D4622
- Loading branch information
Showing
7 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* -*- 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 "mozilla/ipc/InProcessChild.h" | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
} // namespace ipc | ||
} // namespace mozilla |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* -*- 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_ipc_InProcessChild_h | ||
#define mozilla_ipc_InProcessChild_h | ||
|
||
#include "mozilla/ipc/PInProcessChild.h" | ||
#include "mozilla/StaticPtr.h" | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
class InProcessParent; | ||
|
||
/** | ||
* The `InProcessChild` class represents the child half of a main-thread to | ||
* main-thread actor. | ||
* | ||
* The `PInProcess` actor should be used as an alternate manager to `PContent` | ||
* for async actors which want to communicate uniformly between Content->Chrome | ||
* and Chrome->Chrome situations. | ||
*/ | ||
class InProcessChild : public PInProcessChild | ||
{ | ||
public: | ||
friend class InProcessParent; | ||
|
||
NS_INLINE_DECL_REFCOUNTING(InProcessChild) | ||
|
||
// Get the singleton instance of this actor. | ||
static InProcessChild* Singleton(); | ||
|
||
// Get the parent side of the in-process child actor |aActor|. If |aActor| is | ||
// not an in-process actor, or is not connected, this method will return | ||
// |nullptr|. | ||
static IProtocol* ParentActorFor(IProtocol* aActor); | ||
|
||
private: | ||
// NOTE: PInProcess lifecycle management is declared as staic methods and | ||
// state on InProcessParent, and implemented in InProcessImpl.cpp. | ||
virtual void ActorDestroy(ActorDestroyReason aWhy) override; | ||
virtual void DeallocPInProcessChild() override; | ||
~InProcessChild() = default; | ||
|
||
static StaticRefPtr<InProcessChild> sSingleton; | ||
}; | ||
|
||
} // namespace ipc | ||
} // namespace mozilla | ||
|
||
#endif // defined(mozilla_ipc_InProcessChild_h) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/* -*- 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 "mozilla/ipc/InProcessParent.h" | ||
#include "mozilla/ipc/InProcessChild.h" | ||
|
||
// This file contains the implementation of core InProcess lifecycle management | ||
// facilities. | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
StaticRefPtr<InProcessParent> InProcessParent::sSingleton; | ||
StaticRefPtr<InProcessChild> InProcessChild::sSingleton; | ||
bool InProcessParent::sShutdown = false; | ||
|
||
|
||
////////////////////////////////////////// | ||
// InProcess actor lifecycle management // | ||
////////////////////////////////////////// | ||
|
||
/* static */ InProcessChild* | ||
InProcessChild::Singleton() { | ||
MOZ_ASSERT(NS_IsMainThread()); | ||
|
||
if (!sSingleton) { | ||
InProcessParent::Startup(); | ||
} | ||
return sSingleton; | ||
} | ||
|
||
/* static */ InProcessParent* | ||
InProcessParent::Singleton() { | ||
MOZ_ASSERT(NS_IsMainThread()); | ||
|
||
if (!sSingleton) { | ||
InProcessParent::Startup(); | ||
} | ||
return sSingleton; | ||
} | ||
|
||
/* static */ void | ||
InProcessParent::Startup() | ||
{ | ||
MOZ_ASSERT(NS_IsMainThread()); | ||
|
||
if (sShutdown) { | ||
NS_WARNING("Could not get in-process actor while shutting down!"); | ||
return; | ||
} | ||
|
||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); | ||
if (!obs) { | ||
sShutdown = true; | ||
NS_WARNING("Failed to get nsIObserverService for in-process actor"); | ||
return; | ||
} | ||
|
||
RefPtr<InProcessParent> parent = new InProcessParent(); | ||
RefPtr<InProcessChild> child = new InProcessChild(); | ||
|
||
// Observe the shutdown event to close & clean up after ourselves. | ||
nsresult rv = obs->AddObserver(parent, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); | ||
if (NS_WARN_IF(NS_FAILED(rv))) { | ||
return; | ||
} | ||
|
||
// Link the two actors | ||
if (!child->OpenOnSameThread(parent->GetIPCChannel(), ChildSide)) { | ||
MOZ_CRASH("Failed to open InProcessChild!"); | ||
} | ||
|
||
parent->SetOtherProcessId(base::GetCurrentProcId()); | ||
|
||
// Create references held by the IPC layer which will be freed in | ||
// DeallocPInProcess{Parent,Child}. | ||
parent.get()->AddRef(); | ||
child.get()->AddRef(); | ||
|
||
// Stash global references to fetch the other side of the reference. | ||
InProcessParent::sSingleton = parent.forget(); | ||
InProcessChild::sSingleton = child.forget(); | ||
} | ||
|
||
|
||
/* static */ void | ||
InProcessParent::Shutdown() | ||
{ | ||
MOZ_ASSERT(NS_IsMainThread()); | ||
|
||
if (!sSingleton || sShutdown) { | ||
return; | ||
} | ||
|
||
sShutdown = true; | ||
|
||
RefPtr<InProcessParent> parent = sSingleton; | ||
InProcessParent::sSingleton = nullptr; | ||
InProcessChild::sSingleton = nullptr; | ||
|
||
// Calling `Close` on the actor will cause the `Dealloc` methods to be called, | ||
// freeing the remaining references. | ||
parent->Close(); | ||
} | ||
|
||
NS_IMETHODIMP | ||
InProcessParent::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) | ||
{ | ||
MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)); | ||
InProcessParent::Shutdown(); | ||
return NS_OK; | ||
} | ||
|
||
void | ||
InProcessParent::ActorDestroy(ActorDestroyReason aWhy) | ||
{ | ||
InProcessParent::Shutdown(); | ||
} | ||
|
||
void | ||
InProcessChild::ActorDestroy(ActorDestroyReason aWhy) | ||
{ | ||
InProcessParent::Shutdown(); | ||
} | ||
|
||
void | ||
InProcessParent::DeallocPInProcessParent() | ||
{ | ||
MOZ_ASSERT(!InProcessParent::sSingleton); | ||
Release(); // Release the reference taken in InProcessParent::Startup. | ||
} | ||
|
||
void | ||
InProcessChild::DeallocPInProcessChild() | ||
{ | ||
MOZ_ASSERT(!InProcessChild::sSingleton); | ||
Release(); // Release the reference taken in InProcessParent::Startup. | ||
} | ||
|
||
//////////////////////////////// | ||
// In-Process Actor Utilities // | ||
//////////////////////////////// | ||
|
||
// Helper method for implementing ParentActorFor and ChildActorFor. | ||
static IProtocol* | ||
GetOtherInProcessActor(IProtocol* aActor) | ||
{ | ||
MOZ_ASSERT(aActor->GetSide() != UnknownSide, "bad unknown side"); | ||
|
||
// Discover the manager of aActor which is PInProcess. | ||
IProtocol* current = aActor; | ||
while (current) { | ||
if (current->GetProtocolTypeId() == PInProcessMsgStart) { | ||
break; // Found the correct actor. | ||
} | ||
current = current->Manager(); | ||
} | ||
if (!current) { | ||
return nullptr; // Not a PInProcess actor, return |nullptr| | ||
} | ||
|
||
MOZ_ASSERT(current->GetSide() == aActor->GetSide(), "side changed?"); | ||
MOZ_ASSERT_IF(aActor->GetSide() == ParentSide, | ||
current == InProcessParent::Singleton()); | ||
MOZ_ASSERT_IF(aActor->GetSide() == ChildSide, | ||
current == InProcessChild::Singleton()); | ||
|
||
// Check whether this is InProcessParent or InProcessChild, and get the other | ||
// side's toplevel actor. | ||
IProtocol* otherRoot = nullptr; | ||
if (aActor->GetSide() == ParentSide) { | ||
otherRoot = InProcessChild::Singleton(); | ||
} else { | ||
otherRoot = InProcessParent::Singleton(); | ||
} | ||
if (NS_WARN_IF(!otherRoot)) { | ||
return nullptr; | ||
} | ||
|
||
// Look up the actor on the other side, and return it. | ||
IProtocol* otherActor = otherRoot->Lookup(aActor->Id()); | ||
if (otherActor) { | ||
MOZ_ASSERT(otherActor->GetSide() != UnknownSide, "bad unknown side"); | ||
MOZ_ASSERT(otherActor->GetSide() != aActor->GetSide(), "Wrong side!"); | ||
MOZ_ASSERT(otherActor->GetProtocolTypeId() == aActor->GetProtocolTypeId(), | ||
"Wrong type of protocol!"); | ||
} | ||
|
||
return otherActor; | ||
} | ||
|
||
/* static */ IProtocol* | ||
InProcessParent::ChildActorFor(IProtocol* aActor) | ||
{ | ||
MOZ_ASSERT(aActor && aActor->GetSide() == ParentSide); | ||
return GetOtherInProcessActor(aActor); | ||
} | ||
|
||
/* static */ IProtocol* | ||
InProcessChild::ParentActorFor(IProtocol* aActor) | ||
{ | ||
MOZ_ASSERT(aActor && aActor->GetSide() == ChildSide); | ||
return GetOtherInProcessActor(aActor); | ||
} | ||
|
||
} // namespace ipc | ||
} // namespace mozilla |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* -*- 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 "mozilla/ipc/InProcessParent.h" | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
NS_IMPL_ISUPPORTS(InProcessParent, nsIObserver) | ||
|
||
} // namespace ipc | ||
} // namespace mozilla |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* -*- 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_ipc_InProcessParent_h | ||
#define mozilla_ipc_InProcessParent_h | ||
|
||
#include "mozilla/ipc/PInProcessParent.h" | ||
#include "mozilla/StaticPtr.h" | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
class InProcessChild; | ||
|
||
/** | ||
* The `InProcessParent` class represents the parent half of a main-thread to | ||
* main-thread actor. | ||
* | ||
* The `PInProcess` actor should be used as an alternate manager to `PContent` | ||
* for async actors which want to communicate uniformly between Content->Chrome | ||
* and Chrome->Chrome situations. | ||
*/ | ||
class InProcessParent : public nsIObserver | ||
, public PInProcessParent | ||
{ | ||
public: | ||
friend class InProcessChild; | ||
|
||
NS_DECL_ISUPPORTS | ||
NS_DECL_NSIOBSERVER | ||
|
||
// Get the singleton instance of this actor. | ||
static InProcessParent* Singleton(); | ||
|
||
// Get the child side of the in-process child actor |aActor|. If |aActor| is | ||
// not an in-process actor, or is not connected, this method will return | ||
// |nullptr|. | ||
static IProtocol* ChildActorFor(IProtocol* aActor); | ||
|
||
private: | ||
// Lifecycle management is implemented in InProcessImpl.cpp | ||
virtual void ActorDestroy(ActorDestroyReason aWhy) override; | ||
virtual void DeallocPInProcessParent() override; | ||
~InProcessParent() = default; | ||
|
||
static void Startup(); | ||
static void Shutdown(); | ||
|
||
static StaticRefPtr<InProcessParent> sSingleton; | ||
static bool sShutdown; | ||
}; | ||
|
||
|
||
} // namespace ipc | ||
} // namespace mozilla | ||
|
||
#endif // defined(mozilla_ipc_InProcessParent_h) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ | ||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ | ||
/* 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/. */ | ||
|
||
namespace mozilla { | ||
namespace ipc { | ||
|
||
/** | ||
* PInProcess is intended for use as an alternative actor manager to PContent | ||
* for async actors which want to be used uniformly in both Content->Chrome and | ||
* Chrome->Chrome circumstances. | ||
* | ||
* `mozilla::ipc::InProcess{Parent, Child}::Singleton()` should be used to get | ||
* an instance of this actor. | ||
*/ | ||
async protocol PInProcess | ||
{ | ||
}; | ||
|
||
} // namespace ipc | ||
} // namespace mozilla |
Oops, something went wrong.