diff --git a/dom/base/nsFrameLoaderOwner.cpp b/dom/base/nsFrameLoaderOwner.cpp index 3cd4342cb0ca..3be4e5f31c17 100644 --- a/dom/base/nsFrameLoaderOwner.cpp +++ b/dom/base/nsFrameLoaderOwner.cpp @@ -182,9 +182,8 @@ void nsFrameLoaderOwner::ChangeRemoteness( aOptions.mRemoteType, frameLoaderInit, rv); } -void nsFrameLoaderOwner::ChangeRemotenessWithBridge( - mozilla::ipc::ManagedEndpoint aEndpoint, - uint64_t aTabId, mozilla::ErrorResult& rv) { +void nsFrameLoaderOwner::ChangeRemotenessWithBridge(BrowserBridgeChild* aBridge, + mozilla::ErrorResult& rv) { MOZ_ASSERT(XRE_IsContentProcess()); if (NS_WARN_IF(!mFrameLoader)) { rv.Throw(NS_ERROR_UNEXPECTED); @@ -192,24 +191,9 @@ void nsFrameLoaderOwner::ChangeRemotenessWithBridge( } std::function frameLoaderInit = [&] { - RefPtr browsingContext = mFrameLoader->mBrowsingContext; - RefPtr bridge = - new BrowserBridgeChild(mFrameLoader, browsingContext, TabId(aTabId)); - Document* ownerDoc = mFrameLoader->GetOwnerDoc(); - if (NS_WARN_IF(!ownerDoc)) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - RefPtr browser = - BrowserChild::GetFrom(ownerDoc->GetDocShell()); - if (!browser->BindPBrowserBridgeEndpoint(std::move(aEndpoint), bridge)) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - RefPtr host = bridge->FinishInit(); - browsingContext->SetEmbedderElement(mFrameLoader->GetOwnerContent()); + RefPtr host = aBridge->FinishInit(mFrameLoader); + mFrameLoader->mBrowsingContext->SetEmbedderElement( + mFrameLoader->GetOwnerContent()); mFrameLoader->mRemoteBrowser = host; }; diff --git a/dom/base/nsFrameLoaderOwner.h b/dom/base/nsFrameLoaderOwner.h index b1ad6a4f6194..6c7c8cda48cb 100644 --- a/dom/base/nsFrameLoaderOwner.h +++ b/dom/base/nsFrameLoaderOwner.h @@ -14,13 +14,9 @@ namespace mozilla { class ErrorResult; namespace dom { class BrowsingContext; -class PBrowserBridgeChild; +class BrowserBridgeChild; struct RemotenessOptions; } // namespace dom -namespace ipc { -template -class ManagedEndpoint; -} // namespace ipc } // namespace mozilla // IID for the FrameLoaderOwner interface @@ -57,10 +53,8 @@ class nsFrameLoaderOwner : public nsISupports { void ChangeRemoteness(const mozilla::dom::RemotenessOptions& aOptions, mozilla::ErrorResult& rv); - void ChangeRemotenessWithBridge( - mozilla::ipc::ManagedEndpoint - aEndpoint, - uint64_t aTabId, mozilla::ErrorResult& rv); + void ChangeRemotenessWithBridge(mozilla::dom::BrowserBridgeChild* aBridge, + mozilla::ErrorResult& rv); private: bool UseRemoteSubframes(); diff --git a/dom/ipc/BrowserBridgeChild.cpp b/dom/ipc/BrowserBridgeChild.cpp index 2c1e063a3e2c..63c42d6e1bb4 100644 --- a/dom/ipc/BrowserBridgeChild.cpp +++ b/dom/ipc/BrowserBridgeChild.cpp @@ -30,13 +30,9 @@ using namespace mozilla::ipc; namespace mozilla { namespace dom { -BrowserBridgeChild::BrowserBridgeChild(nsFrameLoader* aFrameLoader, - BrowsingContext* aBrowsingContext, +BrowserBridgeChild::BrowserBridgeChild(BrowsingContext* aBrowsingContext, TabId aId) - : mId{aId}, - mLayersId{0}, - mFrameLoader(aFrameLoader), - mBrowsingContext(aBrowsingContext) {} + : mId{aId}, mLayersId{0}, mBrowsingContext(aBrowsingContext) {} BrowserBridgeChild::~BrowserBridgeChild() { #if defined(ACCESSIBILITY) && defined(XP_WIN) @@ -46,7 +42,11 @@ BrowserBridgeChild::~BrowserBridgeChild() { #endif } -already_AddRefed BrowserBridgeChild::FinishInit() { +already_AddRefed BrowserBridgeChild::FinishInit( + nsFrameLoader* aFrameLoader) { + MOZ_DIAGNOSTIC_ASSERT(!mFrameLoader); + mFrameLoader = aFrameLoader; + RefPtr owner = mFrameLoader->GetOwnerContent(); nsCOMPtr docShell = do_GetInterface(owner->GetOwnerGlobal()); MOZ_DIAGNOSTIC_ASSERT(docShell); diff --git a/dom/ipc/BrowserBridgeChild.h b/dom/ipc/BrowserBridgeChild.h index 47b21f7445eb..de0b5bccaf41 100644 --- a/dom/ipc/BrowserBridgeChild.h +++ b/dom/ipc/BrowserBridgeChild.h @@ -56,7 +56,7 @@ class BrowserBridgeChild : public PBrowserBridgeChild { void SetIsUnderHiddenEmbedderElement(bool aIsUnderHiddenEmbedderElement); - already_AddRefed FinishInit(); + already_AddRefed FinishInit(nsFrameLoader* aFrameLoader); #if defined(ACCESSIBILITY) && defined(XP_WIN) a11y::RemoteIframeDocProxyAccessibleWrap* GetEmbeddedDocAccessible() { @@ -68,8 +68,7 @@ class BrowserBridgeChild : public PBrowserBridgeChild { static BrowserBridgeChild* GetFrom(nsIContent* aContent); - BrowserBridgeChild(nsFrameLoader* aFrameLoader, - BrowsingContext* aBrowsingContext, TabId aId); + BrowserBridgeChild(BrowsingContext* aBrowsingContext, TabId aId); protected: friend class ContentChild; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 393fb53c02ee..1cb3c79a6d42 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2127,13 +2127,13 @@ already_AddRefed ContentChild::CreateBrowser( TabId tabId(nsContentUtils::GenerateTabId()); RefPtr browserBridge = - new BrowserBridgeChild(aFrameLoader, aBrowsingContext, tabId); + new BrowserBridgeChild(aBrowsingContext, tabId); browserChild->SendPBrowserBridgeConstructor( browserBridge, PromiseFlatString(aContext.PresentationURL()), aRemoteType, aBrowsingContext, chromeFlags, tabId); - return browserBridge->FinishInit(); + return browserBridge->FinishInit(aFrameLoader); } PScriptCacheChild* ContentChild::AllocPScriptCacheChild( diff --git a/dom/ipc/WindowGlobalChild.cpp b/dom/ipc/WindowGlobalChild.cpp index 61601b622db0..85a4cfd9781a 100644 --- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -281,11 +281,11 @@ mozilla::ipc::IPCResult WindowGlobalChild::RecvMakeFrameLocal( RefPtr embedderElt = aFrameContext->GetEmbedderElement(); if (NS_WARN_IF(!embedderElt)) { - return IPC_FAIL(this, "No embedder element in this process"); + return IPC_OK(); } if (NS_WARN_IF(embedderElt->GetOwnerGlobal() != WindowGlobal())) { - return IPC_FAIL(this, "Wrong actor"); + return IPC_OK(); } RefPtr flo = do_QueryObject(embedderElt); @@ -311,20 +311,38 @@ mozilla::ipc::IPCResult WindowGlobalChild::RecvMakeFrameRemote( // Immediately resolve the promise, acknowledging the request. aResolve(true); + // Immediately construct the BrowserBridgeChild so we can destroy it cleanly + // if the process switch fails. + RefPtr bridge = + new BrowserBridgeChild(aFrameContext, aTabId); + RefPtr manager = GetBrowserChild(); + if (NS_WARN_IF( + !manager->BindPBrowserBridgeEndpoint(std::move(aEndpoint), bridge))) { + return IPC_OK(); + } + RefPtr embedderElt = aFrameContext->GetEmbedderElement(); if (NS_WARN_IF(!embedderElt)) { - return IPC_FAIL(this, "No embedder element in this process"); + BrowserBridgeChild::Send__delete__(bridge); + return IPC_OK(); } if (NS_WARN_IF(embedderElt->GetOwnerGlobal() != WindowGlobal())) { - return IPC_FAIL(this, "Wrong actor"); + BrowserBridgeChild::Send__delete__(bridge); + return IPC_OK(); } RefPtr flo = do_QueryObject(embedderElt); MOZ_DIAGNOSTIC_ASSERT(flo, "Embedder must be a nsFrameLoaderOwner"); // Trgger a process switch into the specified process. - flo->ChangeRemotenessWithBridge(std::move(aEndpoint), aTabId, IgnoreErrors()); + IgnoredErrorResult rv; + flo->ChangeRemotenessWithBridge(bridge, rv); + if (NS_WARN_IF(rv.Failed())) { + BrowserBridgeChild::Send__delete__(bridge); + return IPC_OK(); + } + return IPC_OK(); }