Bug 1544419 - Work around devtools mutating BrowsingContext parent, r=qdot
authorNika Layzell <nika@thelayzells.com>
Wed, 17 Apr 2019 00:53:24 +0000
changeset 469831 59f0c7c6226621e567e311cf47482a97c05543c7
parent 469830 31afeed0ac1d708b6705b457f40229ac5061066a
child 469832 2846ae7210336f4e8c72076edaab027e7027ac8f
push id35883
push userbtara@mozilla.com
push dateWed, 17 Apr 2019 21:47:29 +0000
treeherdermozilla-central@02b89c29412b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1544419
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1544419 - Work around devtools mutating BrowsingContext parent, r=qdot Differential Revision: https://phabricator.services.mozilla.com/D27517
docshell/base/BrowsingContext.cpp
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -200,34 +200,63 @@ void BrowsingContext::SetDocShell(nsIDoc
   // XXX(nika): We should communicate that we are now an active BrowsingContext
   // process to the parent & do other validation here.
   MOZ_RELEASE_ASSERT(nsDocShell::Cast(aDocShell)->GetBrowsingContext() == this);
   mDocShell = aDocShell;
   mIsInProcess = true;
 }
 
 void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
-  mEmbedderElement = aEmbedder;
-
   // Notify the parent process of the embedding status. We don't need to do
   // this when clearing our embedder, as we're being destroyed either way.
-  if (mEmbedderElement) {
-    nsCOMPtr<nsPIDOMWindowInner> embedderGlobal =
-        do_QueryInterface(mEmbedderElement->GetOwnerGlobal());
-    RefPtr<WindowGlobalChild> wgc = embedderGlobal->GetWindowGlobalChild();
+  if (aEmbedder) {
+    nsCOMPtr<nsIDocShell> container =
+        do_QueryInterface(aEmbedder->OwnerDoc()->GetContainer());
+
+    // If our embedder element is being mutated to a different embedder, and we
+    // have a parent edge, bad things might be happening!
+    //
+    // XXX: This is a workaround to some parent edges not being immutable in the
+    // parent process. It can be fixed once bug 1539979 has been fixed.
+    if (mParent && mEmbedderElement && mEmbedderElement != aEmbedder) {
+      NS_WARNING("Non root content frameLoader swap! This will crash soon!");
+
+      MOZ_DIAGNOSTIC_ASSERT(mType == Type::Chrome, "must be chrome");
+      MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "must be in parent");
+      MOZ_DIAGNOSTIC_ASSERT(
+          !sCachedBrowsingContexts || !sCachedBrowsingContexts->has(Id()),
+          "cannot be in bfcache");
 
-    // If we're in-process, synchronously perform the update to ensure we don't
-    // get out of sync.
-    // XXX(nika): This is super gross, and I don't like it one bit.
-    if (RefPtr<WindowGlobalParent> wgp = wgc->GetParentActor()) {
-      Canonical()->SetEmbedderWindowGlobal(wgp);
-    } else {
-      wgc->SendDidEmbedBrowsingContext(this);
+      RefPtr<BrowsingContext> kungFuDeathGrip(this);
+      RefPtr<BrowsingContext> newParent;
+      container->GetBrowsingContext(getter_AddRefs(newParent));
+      mParent->mChildren.RemoveElement(this);
+      if (newParent) {
+        newParent->mChildren.AppendElement(this);
+      }
+      mParent = newParent;
+    }
+
+    nsCOMPtr<nsPIDOMWindowInner> inner =
+        do_QueryInterface(aEmbedder->GetOwnerGlobal());
+    if (inner) {
+      RefPtr<WindowGlobalChild> wgc = inner->GetWindowGlobalChild();
+
+      // If we're in-process, synchronously perform the update to ensure we
+      // don't get out of sync.
+      // XXX(nika): This is super gross, and I don't like it one bit.
+      if (RefPtr<WindowGlobalParent> wgp = wgc->GetParentActor()) {
+        Canonical()->SetEmbedderWindowGlobal(wgp);
+      } else {
+        wgc->SendDidEmbedBrowsingContext(this);
+      }
     }
   }
+
+  mEmbedderElement = aEmbedder;
 }
 
 void BrowsingContext::Attach(bool aFromIPC) {
   MOZ_LOG(GetLog(), LogLevel::Debug,
           ("%s: %s 0x%08" PRIx64 " to 0x%08" PRIx64,
            XRE_IsParentProcess() ? "Parent" : "Child",
            sCachedBrowsingContexts->has(Id()) ? "Re-connecting" : "Connecting",
            Id(), mParent ? mParent->Id() : 0));