Bug 1529684 - Part 3: Create BrowsingContext for remote iframes in embedder, r=farre
☠☠ backed out by 1b825b6f3869 ☠ ☠
authorNika Layzell <nika@thelayzells.com>
Tue, 05 Mar 2019 17:33:29 +0000
changeset 520306 9f3e65f6b1dda22a6e35db2c4c8e8b46377a9b93
parent 520305 257d45117af301a610832d9d4b6f43ba55ecb9c4
child 520307 289c2b4126c9953fb4af4d7c085cf2dcedcc0504
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfarre
bugs1529684
milestone67.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 1529684 - Part 3: Create BrowsingContext for remote iframes in embedder, r=farre Depends on D21096 Differential Revision: https://phabricator.services.mozilla.com/D21097
dom/base/nsFrameLoader.cpp
dom/ipc/PBrowser.ipdl
dom/ipc/RemoteFrameChild.cpp
dom/ipc/RemoteFrameChild.h
dom/ipc/RemoteFrameParent.cpp
dom/ipc/RemoteFrameParent.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1843,16 +1843,30 @@ static already_AddRefed<BrowsingContext>
   }
 
   BrowsingContext::Type type = aIsContent ? BrowsingContext::Type::Content
                                           : BrowsingContext::Type::Chrome;
 
   return BrowsingContext::Create(aParentContext, aOpenerContext, aName, type);
 }
 
+static void GetFrameName(Element* aOwnerContent, nsAString& aFrameName) {
+  int32_t namespaceID = aOwnerContent->GetNameSpaceID();
+  if (namespaceID == kNameSpaceID_XHTML && !aOwnerContent->IsInHTMLDocument()) {
+    aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
+  } else {
+    aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, aFrameName);
+    // XXX if no NAME then use ID, after a transition period this will be
+    // changed so that XUL only uses ID too (bug 254284).
+    if (aFrameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
+      aOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aFrameName);
+    }
+  }
+}
+
 nsresult nsFrameLoader::MaybeCreateDocShell() {
   if (mDocShell) {
     return NS_OK;
   }
   if (IsRemoteFrame()) {
     return NS_OK;
   }
   NS_ENSURE_STATE(!mDestroyCalled);
@@ -1884,28 +1898,17 @@ nsresult nsFrameLoader::MaybeCreateDocSh
     return NS_ERROR_UNEXPECTED;
   }
 
   RefPtr<BrowsingContext> parentBC = parentDocShell->GetBrowsingContext();
   MOZ_ASSERT(parentBC, "docShell must have BrowsingContext");
 
   // Determine the frame name for the new browsing context.
   nsAutoString frameName;
-
-  int32_t namespaceID = mOwnerContent->GetNameSpaceID();
-  if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
-    mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
-  } else {
-    mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
-    // XXX if no NAME then use ID, after a transition period this will be
-    // changed so that XUL only uses ID too (bug 254284).
-    if (frameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
-      mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
-    }
-  }
+  GetFrameName(mOwnerContent, frameName);
 
   // Check if our new context is chrome or content
   bool isContent = parentBC->IsContent() ||
                    mOwnerContent->AttrValueIs(kNameSpaceID_None, TypeAttrName(),
                                               nsGkAtoms::content, eIgnoreCase);
 
   // Force mozbrowser frames to always be content, even if the mozbrowser
   // interfaces are disabled.
@@ -2528,18 +2531,27 @@ bool nsFrameLoader::TryRemoteBrowser() {
       Unused << window->GetNextTabParentId(&nextTabParentId);
     }
   }
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
 
   // If we're in a content process, create a RemoteFrameChild actor.
   if (XRE_IsContentProcess()) {
+    // Determine the frame name for the new browsing context.
+    nsAutoString frameName;
+    GetFrameName(mOwnerContent, frameName);
+
+    // XXX(nika): due to limitations with Browsing Context Groups and multiple
+    // processes, we can't link up aParent yet! (Bug 1532661)
+    RefPtr<BrowsingContext> browsingContext =
+        CreateBrowsingContext(nullptr, nullptr, frameName, true);
+
     mRemoteFrameChild = RemoteFrameChild::Create(
-        this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
+        this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), browsingContext);
     return !!mRemoteFrameChild;
   }
 
   mRemoteBrowser =
       ContentParent::CreateBrowser(context, ownerElement, openerContentParent,
                                    sameTabGroupAs, nextTabParentId);
   if (!mRemoteBrowser) {
     return false;
@@ -3060,28 +3072,38 @@ already_AddRefed<mozilla::dom::Promise> 
 }
 
 already_AddRefed<nsITabParent> nsFrameLoader::GetTabParent() {
   return do_AddRef(mRemoteBrowser);
 }
 
 already_AddRefed<nsILoadContext> nsFrameLoader::LoadContext() {
   nsCOMPtr<nsILoadContext> loadContext;
-  if (IsRemoteFrame() && (mRemoteBrowser || TryRemoteBrowser())) {
-    loadContext = mRemoteBrowser->GetLoadContext();
+  if (IsRemoteFrame() &&
+      (mRemoteBrowser || mRemoteFrameChild || TryRemoteBrowser())) {
+    if (mRemoteBrowser) {
+      loadContext = mRemoteBrowser->GetLoadContext();
+    } else {
+      loadContext = mRemoteFrameChild->GetLoadContext();
+    }
   } else {
     loadContext = do_GetInterface(ToSupports(GetDocShell(IgnoreErrors())));
   }
   return loadContext.forget();
 }
 
 already_AddRefed<BrowsingContext> nsFrameLoader::GetBrowsingContext() {
   RefPtr<BrowsingContext> browsingContext;
-  if (IsRemoteFrame() && (mRemoteBrowser || TryRemoteBrowser())) {
-    browsingContext = mRemoteBrowser->GetBrowsingContext();
+  if (IsRemoteFrame() &&
+      (mRemoteBrowser || mRemoteFrameChild || TryRemoteBrowser())) {
+    if (mRemoteBrowser) {
+      browsingContext = mRemoteBrowser->GetBrowsingContext();
+    } else {
+      browsingContext = mRemoteFrameChild->GetBrowsingContext();
+    }
   } else if (GetDocShell(IgnoreErrors())) {
     browsingContext = nsDocShell::Cast(mDocShell)->GetBrowsingContext();
   }
   return browsingContext.forget();
 }
 
 void nsFrameLoader::InitializeBrowserAPI() {
   if (!OwnerIsMozBrowserFrame()) {
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -173,17 +173,18 @@ parent:
      * Construct a new WindowGlobal actor for a window global in the given
      * BrowsingContext and with the given principal.
      */
     async PWindowGlobal(WindowGlobalInit init);
 
     /**
      * Construct a new Remote iframe actor.
      */
-    async PRemoteFrame(nsString aPresentationURL, nsString aRemoteType);
+    async PRemoteFrame(nsString aPresentationURL, nsString aRemoteType,
+                       BrowsingContext aBrowsingContext);
 
     /**
      * Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the
      * widget's shareable window on the chrome side. Only used on Windows.
      */
     async SetNativeChildOfShareableWindow(uintptr_t childWindow);
 
     /**
--- a/dom/ipc/RemoteFrameChild.cpp
+++ b/dom/ipc/RemoteFrameChild.cpp
@@ -1,46 +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/. */
 
 #include "mozilla/dom/RemoteFrameChild.h"
+#include "mozilla/dom/BrowsingContext.h"
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace dom {
 
-RemoteFrameChild::RemoteFrameChild(nsFrameLoader* aFrameLoader)
-    : mLayersId{0}, mIPCOpen(true), mFrameLoader(aFrameLoader) {}
+RemoteFrameChild::RemoteFrameChild(nsFrameLoader* aFrameLoader,
+                                   BrowsingContext* aBrowsingContext)
+    : mLayersId{0},
+      mIPCOpen(true),
+      mFrameLoader(aFrameLoader),
+      mBrowsingContext(aBrowsingContext) {}
 
 RemoteFrameChild::~RemoteFrameChild() {}
 
 already_AddRefed<RemoteFrameChild> RemoteFrameChild::Create(
     nsFrameLoader* aFrameLoader, const TabContext& aContext,
-    const nsString& aRemoteType) {
+    const nsString& aRemoteType, BrowsingContext* aBrowsingContext) {
   MOZ_ASSERT(XRE_IsContentProcess());
 
   // Determine our embedder's TabChild actor.
   RefPtr<Element> owner = aFrameLoader->GetOwnerContent();
   MOZ_DIAGNOSTIC_ASSERT(owner);
 
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(owner->GetOwnerGlobal());
   MOZ_DIAGNOSTIC_ASSERT(docShell);
 
   RefPtr<TabChild> tabChild = TabChild::GetFrom(docShell);
   MOZ_DIAGNOSTIC_ASSERT(tabChild);
 
-  RefPtr<RemoteFrameChild> remoteFrame = new RemoteFrameChild(aFrameLoader);
+  RefPtr<RemoteFrameChild> remoteFrame =
+      new RemoteFrameChild(aFrameLoader, aBrowsingContext);
+
   // Reference is freed in TabChild::DeallocPRemoteFrameChild.
   tabChild->SendPRemoteFrameConstructor(
       do_AddRef(remoteFrame).take(),
-      PromiseFlatString(aContext.PresentationURL()), aRemoteType);
+      PromiseFlatString(aContext.PresentationURL()), aRemoteType,
+      aBrowsingContext);
   remoteFrame->mIPCOpen = true;
 
   return remoteFrame.forget();
 }
 
 void RemoteFrameChild::UpdateDimensions(const nsIntRect& aRect,
                                         const mozilla::ScreenIntSize& aSize) {
   MOZ_DIAGNOSTIC_ASSERT(mIPCOpen);
--- a/dom/ipc/RemoteFrameChild.h
+++ b/dom/ipc/RemoteFrameChild.h
@@ -7,51 +7,59 @@
 #ifndef mozilla_dom_RemoteFrameChild_h
 #define mozilla_dom_RemoteFrameChild_h
 
 #include "mozilla/dom/PRemoteFrameChild.h"
 #include "mozilla/dom/TabChild.h"
 
 namespace mozilla {
 namespace dom {
+class BrowsingContext;
 
 /**
  * Child side for a remote frame.
  */
 class RemoteFrameChild : public PRemoteFrameChild {
  public:
   NS_INLINE_DECL_REFCOUNTING(RemoteFrameChild);
 
   TabChild* Manager() {
     MOZ_ASSERT(mIPCOpen);
     return static_cast<TabChild*>(PRemoteFrameChild::Manager());
   }
 
   mozilla::layers::LayersId GetLayersId() { return mLayersId; }
 
-  static already_AddRefed<RemoteFrameChild> Create(nsFrameLoader* aFrameLoader,
-                                                   const TabContext& aContext,
-                                                   const nsString& aRemoteType);
+  BrowsingContext* GetBrowsingContext() { return mBrowsingContext; }
+
+  // XXX(nika): We should have a load context here. (bug 1532664)
+  nsILoadContext* GetLoadContext() { return nullptr; }
+
+  static already_AddRefed<RemoteFrameChild> Create(
+      nsFrameLoader* aFrameLoader, const TabContext& aContext,
+      const nsString& aRemoteType, BrowsingContext* aBrowsingContext);
 
   void UpdateDimensions(const nsIntRect& aRect,
                         const mozilla::ScreenIntSize& aSize);
 
  protected:
   friend class PRemoteFrameChild;
 
   mozilla::ipc::IPCResult RecvSetLayersId(
       const mozilla::layers::LayersId& aLayersId);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
  private:
-  explicit RemoteFrameChild(nsFrameLoader* aFrameLoader);
+  explicit RemoteFrameChild(nsFrameLoader* aFrameLoader,
+                            BrowsingContext* aBrowsingContext);
   ~RemoteFrameChild();
 
   mozilla::layers::LayersId mLayersId;
   bool mIPCOpen;
   RefPtr<nsFrameLoader> mFrameLoader;
+  RefPtr<BrowsingContext> mBrowsingContext;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // !defined(mozilla_dom_RemoteFrameParent_h)
--- a/dom/ipc/RemoteFrameParent.cpp
+++ b/dom/ipc/RemoteFrameParent.cpp
@@ -16,17 +16,18 @@ using namespace mozilla::layout;
 namespace mozilla {
 namespace dom {
 
 RemoteFrameParent::RemoteFrameParent() : mIPCOpen(false) {}
 
 RemoteFrameParent::~RemoteFrameParent() {}
 
 nsresult RemoteFrameParent::Init(const nsString& aPresentationURL,
-                                 const nsString& aRemoteType) {
+                                 const nsString& aRemoteType,
+                                 CanonicalBrowsingContext* aBrowsingContext) {
   mIPCOpen = true;
 
   // FIXME: This should actually use a non-bogus TabContext, probably inherited
   // from our Manager().
   OriginAttributes attrs;
   attrs.mInIsolatedMozBrowser = false;
   attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID;
   attrs.SyncAttributesWithPrivateBrowsing(false);
@@ -40,42 +41,36 @@ nsresult RemoteFrameParent::Init(const n
   RefPtr<ContentParent> constructorSender =
       ContentParent::GetNewOrUsedBrowserProcess(
           nullptr, aRemoteType, initialPriority, nullptr, false);
   if (NS_WARN_IF(!constructorSender)) {
     MOZ_ASSERT(false, "Unable to allocate content process!");
     return NS_ERROR_FAILURE;
   }
 
-  // FIXME: This BrowsingContext should be provided by our embedder!
-  RefPtr<CanonicalBrowsingContext> browsingContext =
-      BrowsingContext::Create(nullptr, nullptr, EmptyString(),
-                              BrowsingContext::Type::Content)
-          .downcast<CanonicalBrowsingContext>();
-
   // Ensure that our content process is subscribed to our newly created
   // BrowsingContextGroup.
-  browsingContext->Group()->EnsureSubscribed(constructorSender);
-  browsingContext->SetOwnerProcessId(constructorSender->ChildID());
+  aBrowsingContext->Group()->EnsureSubscribed(constructorSender);
+  aBrowsingContext->SetOwnerProcessId(constructorSender->ChildID());
 
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
   TabId tabId(nsContentUtils::GenerateTabId());
   cpm->RegisterRemoteFrame(tabId, ContentParentId(0), TabId(0),
                            tabContext.AsIPCTabContext(),
                            constructorSender->ChildID());
 
   // Construct the TabParent object for our subframe.
   uint32_t chromeFlags = 0;
   RefPtr<TabParent> tabParent = new TabParent(
-      constructorSender, tabId, tabContext, browsingContext, chromeFlags);
+      constructorSender, tabId, tabContext, aBrowsingContext, chromeFlags);
 
   PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
       // DeallocPBrowserParent() releases this ref.
       tabParent.forget().take(), tabId, TabId(0), tabContext.AsIPCTabContext(),
-      chromeFlags, constructorSender->ChildID(), browsingContext,
+      chromeFlags, constructorSender->ChildID(), aBrowsingContext,
       constructorSender->IsForBrowser());
   if (NS_WARN_IF(!browser)) {
     MOZ_ASSERT(false, "Browser Constructor Failed");
     return NS_ERROR_FAILURE;
   }
 
   // Set our TabParent object to the newly created browser.
   mTabParent = TabParent::GetFrom(browser);
--- a/dom/ipc/RemoteFrameParent.h
+++ b/dom/ipc/RemoteFrameParent.h
@@ -15,20 +15,25 @@ namespace dom {
 
 class RemoteFrameParent : public PRemoteFrameParent {
  public:
   NS_INLINE_DECL_REFCOUNTING(RemoteFrameParent);
 
   RemoteFrameParent();
 
   // Initialize this actor after performing startup.
-  nsresult Init(const nsString& aPresentationURL, const nsString& aRemoteType);
+  nsresult Init(const nsString& aPresentationURL, const nsString& aRemoteType,
+                CanonicalBrowsingContext* aBrowsingContext);
 
   TabParent* GetTabParent() { return mTabParent; }
 
+  CanonicalBrowsingContext* GetBrowsingContext() {
+    return mTabParent->GetBrowsingContext();
+  }
+
   // Get our manager actor.
   TabParent* Manager() {
     MOZ_ASSERT(mIPCOpen);
     return static_cast<TabParent*>(PRemoteFrameParent::Manager());
   }
 
  protected:
   friend class PRemoteFrameParent;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3175,17 +3175,18 @@ PWindowGlobalChild* TabChild::AllocPWind
 
 bool TabChild::DeallocPWindowGlobalChild(PWindowGlobalChild* aActor) {
   // This reference was added in WindowGlobalChild::Create.
   static_cast<WindowGlobalChild*>(aActor)->Release();
   return true;
 }
 
 PRemoteFrameChild* TabChild::AllocPRemoteFrameChild(const nsString&,
-                                                    const nsString&) {
+                                                    const nsString&,
+                                                    BrowsingContext*) {
   MOZ_CRASH("We should never be manually allocating PRemoteFrameChild actors");
   return nullptr;
 }
 
 bool TabChild::DeallocPRemoteFrameChild(PRemoteFrameChild* aActor) {
   // This reference was added in RemoteFrameChild::Create.
   static_cast<RemoteFrameChild*>(aActor)->Release();
   return true;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -668,17 +668,18 @@ class TabChild final : public TabChildBa
   virtual ~TabChild();
 
   virtual PWindowGlobalChild* AllocPWindowGlobalChild(
       const WindowGlobalInit& aInit) override;
 
   virtual bool DeallocPWindowGlobalChild(PWindowGlobalChild* aActor) override;
 
   virtual PRemoteFrameChild* AllocPRemoteFrameChild(
-      const nsString& aName, const nsString& aRemoteType) override;
+      const nsString& aName, const nsString& aRemoteType,
+      BrowsingContext* aBrowsingContext) override;
 
   virtual bool DeallocPRemoteFrameChild(PRemoteFrameChild* aActor) override;
 
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
 
   virtual mozilla::ipc::IPCResult RecvSetDocShellIsActive(
       const bool& aIsActive) override;
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -996,25 +996,27 @@ PWindowGlobalParent* TabParent::AllocPWi
 }
 
 bool TabParent::DeallocPWindowGlobalParent(PWindowGlobalParent* aActor) {
   // Free reference from AllocPWindowGlobalParent.
   static_cast<WindowGlobalParent*>(aActor)->Release();
   return true;
 }
 
-IPCResult TabParent::RecvPRemoteFrameConstructor(PRemoteFrameParent* aActor,
-                                                 const nsString& aName,
-                                                 const nsString& aRemoteType) {
-  static_cast<RemoteFrameParent*>(aActor)->Init(aName, aRemoteType);
+IPCResult TabParent::RecvPRemoteFrameConstructor(
+    PRemoteFrameParent* aActor, const nsString& aName,
+    const nsString& aRemoteType, BrowsingContext* aBrowsingContext) {
+  static_cast<RemoteFrameParent*>(aActor)->Init(
+      aName, aRemoteType, CanonicalBrowsingContext::Cast(aBrowsingContext));
   return IPC_OK();
 }
 
 PRemoteFrameParent* TabParent::AllocPRemoteFrameParent(
-    const nsString& aName, const nsString& aRemoteType) {
+    const nsString& aName, const nsString& aRemoteType,
+    BrowsingContext* aBrowsingContext) {
   // Reference freed in DeallocPRemoteFrameParent.
   return do_AddRef(new RemoteFrameParent()).take();
 }
 
 bool TabParent::DeallocPRemoteFrameParent(PRemoteFrameParent* aActor) {
   // Free reference from AllocPRemoteFrameParent.
   static_cast<RemoteFrameParent*>(aActor)->Release();
   return true;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -311,24 +311,25 @@ class TabParent final : public PBrowserP
 
   PWindowGlobalParent* AllocPWindowGlobalParent(const WindowGlobalInit& aInit);
 
   bool DeallocPWindowGlobalParent(PWindowGlobalParent* aActor);
 
   virtual mozilla::ipc::IPCResult RecvPWindowGlobalConstructor(
       PWindowGlobalParent* aActor, const WindowGlobalInit& aInit) override;
 
-  PRemoteFrameParent* AllocPRemoteFrameParent(const nsString& aPresentationURL,
-                                              const nsString& aRemoteType);
+  PRemoteFrameParent* AllocPRemoteFrameParent(
+      const nsString& aPresentationURL, const nsString& aRemoteType,
+      BrowsingContext* aBrowsingContext);
 
   bool DeallocPRemoteFrameParent(PRemoteFrameParent* aActor);
 
   virtual mozilla::ipc::IPCResult RecvPRemoteFrameConstructor(
       PRemoteFrameParent* aActor, const nsString& aPresentationURL,
-      const nsString& aRemoteType) override;
+      const nsString& aRemoteType, BrowsingContext* aBrowsingContext) override;
 
   void LoadURL(nsIURI* aURI);
 
   void InitRendering();
   void MaybeShowFrame();
 
   // XXX/cjones: it's not clear what we gain by hiding these
   // message-sending functions under a layer of indirection and