diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp index 149a64f9f542..6e4997d2a46a 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -58,20 +58,6 @@ static void Register(BrowsingContext* aBrowsingContext) { aBrowsingContext->Group()->Register(aBrowsingContext); } -static void Sync(BrowsingContext* aBrowsingContext) { - if (!XRE_IsContentProcess()) { - return; - } - - auto cc = ContentChild::GetSingleton(); - MOZ_DIAGNOSTIC_ASSERT(cc); - RefPtr parent = aBrowsingContext->GetParent(); - BrowsingContext* opener = aBrowsingContext->GetOpener(); - cc->SendAttachBrowsingContext(parent, opener, - BrowsingContextId(aBrowsingContext->Id()), - aBrowsingContext->Name()); -} - BrowsingContext* BrowsingContext::TopLevelBrowsingContext() { BrowsingContext* bc = this; while (bc->mParent) { @@ -161,7 +147,7 @@ already_AddRefed BrowsingContext::CreateFromIPC( Register(context); - context->Attach(); + // Caller handles attaching us to the tree. return context.forget(); } @@ -197,7 +183,7 @@ void BrowsingContext::SetDocShell(nsIDocShell* aDocShell) { mDocShell = aDocShell; } -void BrowsingContext::Attach() { +void BrowsingContext::Attach(bool aFromIPC) { MOZ_LOG(GetLog(), LogLevel::Debug, ("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64, XRE_IsParentProcess() ? "Parent" : "Child", @@ -211,10 +197,16 @@ void BrowsingContext::Attach() { children->AppendElement(this); - Sync(this); + // Send attach to our parent if we need to. + if (!aFromIPC && XRE_IsContentProcess()) { + auto cc = ContentChild::GetSingleton(); + MOZ_DIAGNOSTIC_ASSERT(cc); + cc->SendAttachBrowsingContext( + mParent, mOpener, BrowsingContextId(mBrowsingContextId), Name()); + } } -void BrowsingContext::Detach() { +void BrowsingContext::Detach(bool aFromIPC) { MOZ_LOG(GetLog(), LogLevel::Debug, ("%s: Detaching 0x%08" PRIx64 " from 0x%08" PRIx64, XRE_IsParentProcess() ? "Parent" : "Child", Id(), @@ -242,16 +234,14 @@ void BrowsingContext::Detach() { Group()->Unregister(this); - if (!XRE_IsContentProcess()) { - return; + if (!aFromIPC && XRE_IsContentProcess()) { + auto cc = ContentChild::GetSingleton(); + MOZ_DIAGNOSTIC_ASSERT(cc); + cc->SendDetachBrowsingContext(this, false /* aMoveToBFCache */); } - - auto cc = ContentChild::GetSingleton(); - MOZ_DIAGNOSTIC_ASSERT(cc); - cc->SendDetachBrowsingContext(this, false /* aMoveToBFCache */); } -void BrowsingContext::CacheChildren() { +void BrowsingContext::CacheChildren(bool aFromIPC) { if (mChildren.IsEmpty()) { return; } @@ -267,13 +257,11 @@ void BrowsingContext::CacheChildren() { } mChildren.Clear(); - if (!XRE_IsContentProcess()) { - return; + if (!aFromIPC && XRE_IsContentProcess()) { + auto cc = ContentChild::GetSingleton(); + MOZ_DIAGNOSTIC_ASSERT(cc); + cc->SendDetachBrowsingContext(this, true /* aMoveToBFCache */); } - - auto cc = ContentChild::GetSingleton(); - MOZ_DIAGNOSTIC_ASSERT(cc); - cc->SendDetachBrowsingContext(this, true /* aMoveToBFCache */); } bool BrowsingContext::IsCached() { return sCachedBrowsingContexts->has(Id()); } diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h index eab646528e9b..3a9fd8a6ed66 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h @@ -178,15 +178,15 @@ class BrowsingContext : public nsWrapperCache, // parent process. BrowsingContext objects are created attached by default, so // this method need only be called when restoring cached BrowsingContext // objects. - void Attach(); + void Attach(bool aFromIPC = false); // Detach the current BrowsingContext from its parent, in both the // child and the parent process. - void Detach(); + void Detach(bool aFromIPC = false); // Remove all children from the current BrowsingContext and cache // them to allow them to be attached again. - void CacheChildren(); + void CacheChildren(bool aFromIPC = false); // Determine if the current BrowsingContext was 'cached' by the logic in // CacheChildren. diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index bc18ab257631..dbc7fa37bce2 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -3679,6 +3679,35 @@ PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg, return result; } +mozilla::ipc::IPCResult ContentChild::RecvAttachBrowsingContext( + BrowsingContext* aParent, BrowsingContext* aOpener, + BrowsingContextId aChildId, const nsString& aName) { + RefPtr child = BrowsingContext::Get(aChildId); + MOZ_RELEASE_ASSERT(!child || child->IsCached()); + + if (!child) { + child = BrowsingContext::CreateFromIPC(aParent, aOpener, aName, + (uint64_t)aChildId, nullptr); + } + + child->Attach(/* aFromIPC */ true); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult ContentChild::RecvDetachBrowsingContext( + BrowsingContext* aContext, bool aMoveToBFCache) { + MOZ_RELEASE_ASSERT(aContext); + + if (aMoveToBFCache) { + aContext->CacheChildren(/* aFromIPC */ true); + } else { + aContext->Detach(/* aFromIPC */ true); + } + + return IPC_OK(); +} + mozilla::ipc::IPCResult ContentChild::RecvWindowClose(BrowsingContext* aContext, bool aTrustedCaller) { if (!aContext) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 91cdb3202dd1..1265a233168e 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -712,6 +712,13 @@ class ContentChild final : public PContentChild, virtual void OnChannelReceivedMessage(const Message& aMsg) override; + mozilla::ipc::IPCResult RecvAttachBrowsingContext( + BrowsingContext* aParentContext, BrowsingContext* aOpener, + BrowsingContextId aContextId, const nsString& aName); + + mozilla::ipc::IPCResult RecvDetachBrowsingContext(BrowsingContext* aContext, + bool aMoveToBFCache); + mozilla::ipc::IPCResult RecvWindowClose(BrowsingContext* aContext, bool aTrustedCaller); mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index e5bb8b74a6a0..f2b3eed0c261 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -5708,6 +5708,8 @@ mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext( (uint64_t)aChildId, this); } + child->Attach(/* aFromIPC */ true); + return IPC_OK(); } @@ -5734,9 +5736,9 @@ mozilla::ipc::IPCResult ContentParent::RecvDetachBrowsingContext( } if (aMoveToBFCache) { - aContext->CacheChildren(); + aContext->CacheChildren(/* aFromIPC */ true); } else { - aContext->Detach(); + aContext->Detach(/* aFromIPC */ true); } return IPC_OK(); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index ab799a427505..b9b99b118fe6 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -1227,34 +1227,6 @@ parent: async StoreUserInteractionAsPermission(Principal aPrincipal); - /** - * Sync the BrowsingContext with id 'aContextId' and name 'aName' to the - * parent, and attach it to the BrowsingContext 'aParentContext'. If - * 'aParentContext' is 'nullptr' the BrowsingContext is a root in the - * BrowsingContext tree. AttachBrowsingContext must only be called at most - * once for any child BrowsingContext, and only for BrowsingContexts where - * the parent and the child context contains their nsDocShell. - */ - async AttachBrowsingContext(BrowsingContext aParentContext, - BrowsingContext aOpener, - BrowsingContextId aContextId, - nsString aName); - - /** - * Remove the synced BrowsingContext 'aContext' from the parent. - * DetachBrowsingContext is only needed to be called once for any - * BrowsingContext, since detaching a node in the BrowsingContext detaches - * the entire sub-tree rooted at that node. Calling DetachBrowsingContext - * with an already detached BrowsingContext effectively does nothing. Note - * that it is not an error to call DetachBrowsingContext on a - * BrowsingContext belonging to an already detached subtree. The - * 'aMoveToBFCache' paramater controls if detaching a BrowsingContext - * should move it to the bfcache allowing it to be re-attached if navigated - * to. - */ - async DetachBrowsingContext(BrowsingContext aContext, - bool aMoveToBFCache); - /** * Set the opener of browsing context 'aContext' to the browsing context * with id 'aOpenerId'. @@ -1288,6 +1260,34 @@ both: async PushError(nsCString scope, Principal principal, nsString message, uint32_t flags); + /** + * Sync the BrowsingContext with id 'aContextId' and name 'aName' to the + * parent, and attach it to the BrowsingContext 'aParentContext'. If + * 'aParentContext' is 'nullptr' the BrowsingContext is a root in the + * BrowsingContext tree. AttachBrowsingContext must only be called at most + * once for any child BrowsingContext, and only for BrowsingContexts where + * the parent and the child context contains their nsDocShell. + */ + async AttachBrowsingContext(BrowsingContext aParentContext, + BrowsingContext aOpener, + BrowsingContextId aContextId, + nsString aName); + + /** + * Remove the synced BrowsingContext 'aContext' from the parent. + * DetachBrowsingContext is only needed to be called once for any + * BrowsingContext, since detaching a node in the BrowsingContext detaches + * the entire sub-tree rooted at that node. Calling DetachBrowsingContext + * with an already detached BrowsingContext effectively does nothing. Note + * that it is not an error to call DetachBrowsingContext on a + * BrowsingContext belonging to an already detached subtree. The + * 'aMoveToBFCache' paramater controls if detaching a BrowsingContext + * should move it to the bfcache allowing it to be re-attached if navigated + * to. + */ + async DetachBrowsingContext(BrowsingContext aContext, + bool aMoveToBFCache); + async WindowClose(BrowsingContext aContext, bool aTrustedCaller); async WindowFocus(BrowsingContext aContext); async WindowBlur(BrowsingContext aContext);