Bug 1538353 - Part 2: Create PBrowser actors using ManagedEndpoint instead of IPDL Ctors, r=bzbarsky

Depends on D24566

Differential Revision: https://phabricator.services.mozilla.com/D24567

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nika Layzell 2019-04-17 00:51:38 +00:00
Родитель c20d338fe9
Коммит 7f4ecdea61
7 изменённых файлов: 182 добавлений и 182 удалений

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

@ -68,18 +68,27 @@ nsresult BrowserBridgeParent::Init(const nsString& aPresentationURL,
tabContext, aBrowsingContext,
aChromeFlags, this));
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
// DeallocPBrowserParent() releases this ref.
tabParent.forget().take(), tabId, TabId(0), tabContext.AsIPCTabContext(),
aChromeFlags, constructorSender->ChildID(), aBrowsingContext,
// Open a remote endpoint for our PBrowser actor. DeallocPBrowserParent
// releases the ref taken.
ManagedEndpoint<PBrowserChild> childEp =
constructorSender->OpenPBrowserEndpoint(do_AddRef(tabParent).take());
if (NS_WARN_IF(!childEp.IsValid())) {
MOZ_ASSERT(false, "Browser Open Endpoint Failed");
return NS_ERROR_FAILURE;
}
// Tell the content process to set up its PBrowserChild.
bool ok = constructorSender->SendConstructBrowser(
std::move(childEp), tabId, TabId(0), tabContext.AsIPCTabContext(),
aBrowsingContext, aChromeFlags, constructorSender->ChildID(),
constructorSender->IsForBrowser());
if (NS_WARN_IF(!browser)) {
if (NS_WARN_IF(!ok)) {
MOZ_ASSERT(false, "Browser Constructor Failed");
return NS_ERROR_FAILURE;
}
// Set our TabParent object to the newly created browser.
mTabParent = TabParent::GetFrom(browser);
mTabParent = tabParent.forget();
mTabParent->SetOwnerElement(Manager()->GetOwnerElement());
mTabParent->InitRendering();

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

@ -960,10 +960,24 @@ nsresult ContentChild::ProvideWindowCommon(
tabGroup->EventTargetFor(TaskCategory::Other);
SetEventTargetForActor(newChild, target);
Unused << SendPBrowserConstructor(
// We release this ref in DeallocPBrowserChild
RefPtr<TabChild>(newChild).forget().take(), tabId, TabId(0), *ipcContext,
aChromeFlags, GetID(), browsingContext, IsForBrowser());
if (IsShuttingDown()) {
return NS_ERROR_ABORT;
}
// Open a remote endpoint for our PBrowser actor. DeallocPBrowserChild
// releases the ref taken.
ManagedEndpoint<PBrowserParent> parentEp =
OpenPBrowserEndpoint(do_AddRef(newChild).take());
if (NS_WARN_IF(!parentEp.IsValid())) {
return NS_ERROR_ABORT;
}
// Tell the parent process to set up its PBrowserParent.
if (NS_WARN_IF(!SendConstructPopupBrowser(std::move(parentEp), tabId,
*ipcContext, browsingContext,
aChromeFlags))) {
return NS_ERROR_ABORT;
}
// Now that |newChild| has had its IPC link established, call |Init| to set it
// up.
@ -1764,51 +1778,11 @@ bool ContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) {
return true;
}
PBrowserChild* ContentChild::AllocPBrowserChild(
const TabId& aTabId, const TabId& aSameTabGroupAs,
const IPCTabContext& aContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser) {
// We'll happily accept any kind of IPCTabContext here; we don't need to
// check that it's of a certain type for security purposes, because we
// believe whatever the parent process tells us.
MaybeInvalidTabContext tc(aContext);
if (!tc.IsValid()) {
NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
"the parent process. (%s) Crashing...",
tc.GetInvalidReason())
.get());
MOZ_CRASH("Invalid TabContext received from the parent process.");
}
RefPtr<TabChild> child = TabChild::Create(
static_cast<ContentChild*>(this), aTabId, aSameTabGroupAs,
tc.GetTabContext(), aBrowsingContext, aChromeFlags);
// The ref here is released in DeallocPBrowserChild.
return child.forget().take();
}
bool ContentChild::SendPBrowserConstructor(
PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
const IPCTabContext& aContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser) {
if (IsShuttingDown()) {
return false;
}
return PContentChild::SendPBrowserConstructor(
aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID,
aBrowsingContext, aIsForBrowser);
}
mozilla::ipc::IPCResult ContentChild::RecvPBrowserConstructor(
PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
const IPCTabContext& aContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser) {
mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp, const TabId& aTabId,
const TabId& aSameTabGroupAs, const IPCTabContext& aContext,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, const bool& aIsForBrowser) {
MOZ_ASSERT(!IsShuttingDown());
static bool hasRunOnce = false;
@ -1825,7 +1799,29 @@ mozilla::ipc::IPCResult ContentChild::RecvPBrowserConstructor(
}
}
auto tabChild = static_cast<TabChild*>(aActor);
// We'll happily accept any kind of IPCTabContext here; we don't need to
// check that it's of a certain type for security purposes, because we
// believe whatever the parent process tells us.
MaybeInvalidTabContext tc(aContext);
if (!tc.IsValid()) {
NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
"the parent process. (%s) Crashing...",
tc.GetInvalidReason())
.get());
MOZ_CRASH("Invalid TabContext received from the parent process.");
}
RefPtr<TabChild> tabChild =
TabChild::Create(this, aTabId, aSameTabGroupAs, tc.GetTabContext(),
aBrowsingContext, aChromeFlags);
// Bind the created TabChild to IPC to actually link the actor. The ref here
// is released in DeallocPBrowserChild.
if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp),
do_AddRef(tabChild).take()))) {
return IPC_FAIL(this, "BindPBrowserEndpoint failed");
}
if (!tabChild->mTabGroup) {
tabChild->mTabGroup = TabGroup::GetFromActor(tabChild);
@ -3395,49 +3391,6 @@ bool ContentChild::DeallocPSessionStorageObserverChild(
return true;
}
// The IPC code will call this method asking us to assign an event target to new
// actors created by the ContentParent.
already_AddRefed<nsIEventTarget> ContentChild::GetConstructedEventTarget(
const Message& aMsg) {
// Currently we only set targets for PBrowser.
if (aMsg.type() != PContent::Msg_PBrowserConstructor__ID) {
return nullptr;
}
ActorHandle handle;
TabId tabId, sameTabGroupAs;
PickleIterator iter(aMsg);
if (!IPC::ReadParam(&aMsg, &iter, &handle)) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (!IPC::ReadParam(&aMsg, &iter, &tabId)) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs)) {
return nullptr;
}
// If sameTabGroupAs is non-zero, then the new tab will be in the same
// TabGroup as a previously created tab. Rather than try to find the
// previously created tab (whose constructor message may not even have been
// processed yet, in theory) and look up its event target, we just use the
// default event target. This means that runnables for this tab will not be
// labeled. However, this path is only taken for print preview and view
// source, which are not performance-sensitive.
if (sameTabGroupAs) {
return nullptr;
}
// If the request for a new TabChild is coming from the parent process, then
// there is no opener. Therefore, we create a fresh TabGroup.
RefPtr<TabGroup> tabGroup = new TabGroup();
nsCOMPtr<nsIEventTarget> target =
tabGroup->EventTargetFor(TaskCategory::Other);
return target.forget();
}
void ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
const nsAString& aFullPath,
const nsAString& aType,
@ -3721,6 +3674,55 @@ already_AddRefed<nsIEventTarget> ContentChild::GetSpecificMessageEventTarget(
return do_AddRef(SystemGroup::EventTargetFor(TaskCategory::Other));
// PBrowserChild Construction
case PContent::Msg_ConstructBrowser__ID: {
// Deserialize the arguments for this message to get the endpoint and
// `sameTabGroupAs`. The endpoint is needed to set up the event target for
// our newly created actor, and sameTabGroupAs is needed to determine if
// we're going to join an existing TabGroup.
ManagedEndpoint<PBrowserChild> endpoint;
TabId tabId, sameTabGroupAs;
PickleIterator iter(aMsg);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &endpoint))) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &tabId))) {
return nullptr;
}
aMsg.IgnoreSentinel(&iter);
if (NS_WARN_IF(!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs))) {
return nullptr;
}
// If sameTabGroupAs is non-zero, then the new tab will be in the same
// TabGroup as a previously created tab. Rather than try to find the
// previously created tab (whose constructor message may not even have been
// processed yet, in theory) and look up its event target, we just use the
// default event target. This means that runnables for this tab will not be
// labeled. However, this path is only taken for print preview and view
// source, which are not performance-sensitive.
if (sameTabGroupAs) {
return nullptr;
}
if (NS_WARN_IF(!endpoint.IsValid())) {
return nullptr;
}
// If the request for a new TabChild is coming from the parent process,
// then there is no opener. Therefore, we create a fresh TabGroup.
RefPtr<TabGroup> tabGroup = new TabGroup();
nsCOMPtr<nsIEventTarget> target =
tabGroup->EventTargetFor(TaskCategory::Other);
// Set this event target for our newly created entry, and use it for this
// message.
SetEventTargetForRoute(*endpoint.ActorId(), target);
return target.forget();
}
default:
return nullptr;
}

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

@ -197,14 +197,6 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvSetProcessSandbox(
const Maybe<FileDescriptor>& aBroker);
PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
const TabId& aSameTabGroupAs,
const IPCTabContext& aContext,
const uint32_t& aChromeFlags,
const ContentParentId& aCpID,
BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser);
bool DeallocPBrowserChild(PBrowserChild*);
PIPCBlobInputStreamChild* AllocPIPCBlobInputStreamChild(
@ -518,19 +510,11 @@ class ContentChild final : public PContentChild,
bool DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*);
bool SendPBrowserConstructor(PBrowserChild* actor, const TabId& aTabId,
const TabId& aSameTabGroupAs,
const IPCTabContext& context,
const uint32_t& chromeFlags,
const ContentParentId& aCpID,
BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser);
virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
PBrowserChild* aCctor, const TabId& aTabId, const TabId& aSameTabGroupAs,
const IPCTabContext& aContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser) override;
mozilla::ipc::IPCResult RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp, const TabId& aTabId,
const TabId& aSameTabGroupAs, const IPCTabContext& aContext,
BrowsingContext* aBrowsingContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpID, const bool& aIsForBrowser);
FORWARD_SHMEM_ALLOCATOR_TO(PContentChild)
@ -717,9 +701,6 @@ class ContentChild final : public PContentChild,
virtual void ProcessingError(Result aCode, const char* aReason) override;
virtual already_AddRefed<nsIEventTarget> GetConstructedEventTarget(
const Message& aMsg) override;
virtual already_AddRefed<nsIEventTarget> GetSpecificMessageEventTarget(
const Message& aMsg) override;

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

@ -1182,31 +1182,39 @@ TabParent* ContentParent::CreateBrowser(const TabContext& aContext,
if (tabId == 0) {
return nullptr;
}
RefPtr<TabParent> tp =
new TabParent(constructorSender, tabId, aContext,
aBrowsingContext->Canonical(), chromeFlags);
aBrowsingContext->Canonical()->SetOwnerProcessId(
constructorSender->ChildID());
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
// DeallocPBrowserParent() releases this ref.
tp.forget().take(), tabId,
RefPtr<TabParent> tabParent = new TabParent(
constructorSender, tabId, aContext, aBrowsingContext->Canonical(), chromeFlags);
// Open a remote endpoint for our PBrowser actor. DeallocPBrowserParent
// releases the ref taken.
ManagedEndpoint<PBrowserChild> childEp =
constructorSender->OpenPBrowserEndpoint(do_AddRef(tabParent).take());
if (NS_WARN_IF(!childEp.IsValid())) {
return nullptr;
}
// Tell the content process to set up its PBrowserChild.
bool ok = constructorSender->SendConstructBrowser(
std::move(childEp), tabId,
aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0),
aContext.AsIPCTabContext(), chromeFlags, constructorSender->ChildID(),
aBrowsingContext, constructorSender->IsForBrowser());
aContext.AsIPCTabContext(), aBrowsingContext, chromeFlags,
constructorSender->ChildID(), constructorSender->IsForBrowser());
if (NS_WARN_IF(!ok)) {
return nullptr;
}
if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
// Tell the TabChild object that it was created due to a Large-Allocation
// request.
Unused << browser->SendAwaitLargeAlloc();
Unused << tabParent->SendAwaitLargeAlloc();
}
if (browser) {
RefPtr<TabParent> constructedTabParent = TabParent::GetFrom(browser);
constructedTabParent->SetOwnerElement(aFrameElement);
return constructedTabParent;
}
tabParent->SetOwnerElement(aFrameElement);
return tabParent;
}
return nullptr;
}
@ -3199,18 +3207,18 @@ bool ContentParent::CanOpenBrowser(const IPCTabContext& aContext) {
return true;
}
PBrowserParent* ContentParent::AllocPBrowserParent(
const TabId& aTabId, const TabId& aSameTabGroupAs,
const IPCTabContext& aContext, const uint32_t& aChromeFlags,
const ContentParentId& aCpId, BrowsingContext* aBrowsingContext,
const bool& aIsForBrowser) {
MOZ_ASSERT(!aSameTabGroupAs);
Unused << aCpId;
Unused << aIsForBrowser;
bool ContentParent::DeallocPBrowserParent(PBrowserParent* frame) {
TabParent* parent = TabParent::GetFrom(frame);
NS_RELEASE(parent);
return true;
}
mozilla::ipc::IPCResult ContentParent::RecvConstructPopupBrowser(
ManagedEndpoint<PBrowserParent>&& aBrowserEp, const TabId& aTabId,
const IPCTabContext& aContext, BrowsingContext* aBrowsingContext,
const uint32_t& aChromeFlags) {
if (!CanOpenBrowser(aContext)) {
return nullptr;
return IPC_FAIL(this, "CanOpenBrowser Failed");
}
uint32_t chromeFlags = aChromeFlags;
@ -3230,7 +3238,7 @@ PBrowserParent* ContentParent::AllocPBrowserParent(
// match those of the opener.
nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
if (!loadContext) {
return nullptr;
return IPC_FAIL(this, "Missing Opener LoadContext");
}
bool isPrivate;
@ -3244,7 +3252,7 @@ PBrowserParent* ContentParent::AllocPBrowserParent(
aContext.type() == IPCTabContext::TUnsafeIPCTabContext) {
MOZ_ASSERT(XRE_IsParentProcess());
if (!XRE_IsParentProcess()) {
return nullptr;
return IPC_FAIL(this, "Not in Parent Process");
}
// The creation of PBrowser was triggered from content process through
@ -3252,8 +3260,8 @@ PBrowserParent* ContentParent::AllocPBrowserParent(
// We need to register remote frame with the child generated tab id.
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
if (!cpm->RegisterRemoteFrame(aTabId, openerCpId, openerTabId, aContext,
aCpId)) {
return nullptr;
ChildID())) {
return IPC_FAIL(this, "RegisterRemoteFrame Failed");
}
}
@ -3264,32 +3272,21 @@ PBrowserParent* ContentParent::AllocPBrowserParent(
CanonicalBrowsingContext* browsingContext =
CanonicalBrowsingContext::Cast(aBrowsingContext);
if (NS_WARN_IF(!browsingContext->IsOwnedByProcess(ChildID()))) {
MOZ_ASSERT(false, "BrowsingContext not owned by the correct process!");
return nullptr;
return IPC_FAIL(this, "BrowsingContext Owned by Incorrect Process!");
}
MaybeInvalidTabContext tc(aContext);
MOZ_ASSERT(tc.IsValid());
TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(),
browsingContext, chromeFlags);
RefPtr<TabParent> parent = new TabParent(this, aTabId, tc.GetTabContext(),
browsingContext, chromeFlags);
// We release this ref in DeallocPBrowserParent()
NS_ADDREF(parent);
return parent;
}
// Bind the created TabParent to IPC to actually link the actor. The ref here
// is released in DeallocPBrowserParent.
if (NS_WARN_IF(!BindPBrowserEndpoint(std::move(aBrowserEp),
do_AddRef(parent).take()))) {
return IPC_FAIL(this, "BindPBrowserEndpoint failed");
}
bool ContentParent::DeallocPBrowserParent(PBrowserParent* frame) {
TabParent* parent = TabParent::GetFrom(frame);
NS_RELEASE(parent);
return true;
}
mozilla::ipc::IPCResult ContentParent::RecvPBrowserConstructor(
PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
const IPCTabContext& context, const uint32_t& chromeFlags,
const ContentParentId& cpId, BrowsingContext* aBrowsingContext,
const bool& isForBrowser) {
TabParent* parent = TabParent::GetFrom(actor);
// When enabling input event prioritization, input events may preempt other
// normal priority IPC messages. To prevent the input events preempt
// PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to

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

@ -820,11 +820,10 @@ class ContentParent final : public PContentParent,
bool DeallocPBrowserParent(PBrowserParent* frame);
virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
const IPCTabContext& context, const uint32_t& chromeFlags,
const ContentParentId& cpId, BrowsingContext* aBrowsingContext,
const bool& isForBrowser) override;
mozilla::ipc::IPCResult RecvConstructPopupBrowser(
ManagedEndpoint<PBrowserParent>&& actor, const TabId& tabId,
const IPCTabContext& context, BrowsingContext* aBrowsingContext,
const uint32_t& chromeFlags);
PIPCBlobInputStreamParent* AllocPIPCBlobInputStreamParent(
const nsID& aID, const uint64_t& aSize);

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

@ -369,7 +369,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PLoginReputation;
manages PSessionStorageObserver;
both:
// Depending on exactly how the new browser is being created, it might be
// created from either the child or parent process!
//
@ -391,12 +390,25 @@ both:
// TabGroup as |sameTabGroupAs|. This parameter should always be zero
// for PBrowser messages sent from the child to the parent.
//
// Separate messages are used for the parent and child side constructors due
// to the differences in data and actor setup required.
//
// Keep the last 3 attributes in sync with GetProcessAttributes!
async PBrowser(TabId tabId, TabId sameTabGroupAs,
IPCTabContext context, uint32_t chromeFlags,
ContentParentId cpId, BrowsingContext browsingContext,
bool isForBrowser);
parent:
async ConstructPopupBrowser(ManagedEndpoint<PBrowserParent> browserEp,
TabId tabId, IPCTabContext context,
BrowsingContext browsingContext,
uint32_t chromeFlags);
child:
async ConstructBrowser(ManagedEndpoint<PBrowserChild> browserEp,
TabId tabId, TabId sameTabGroupAs,
IPCTabContext context,
BrowsingContext browsingContext,
uint32_t chromeFlags, ContentParentId cpId,
bool isForBrowser);
both:
async PFileDescriptorSet(FileDescriptor fd);
// For parent->child, aBrowser must be non-null; aOuterWindowID can

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

@ -35,7 +35,7 @@ static bool HandleMessageInMiddleman(ipc::Side aSide,
// Handle messages that should be sent to both the middleman and the
// child process.
if ( // Initialization that must be performed in both processes.
type == dom::PContent::Msg_PBrowserConstructor__ID ||
type == dom::PContent::Msg_ConstructBrowser__ID ||
type == dom::PContent::Msg_RegisterBrowsingContextGroup__ID ||
type == dom::PContent::Msg_RegisterChrome__ID ||
type == dom::PContent::Msg_SetXPCOMProcessAttributes__ID ||