Bug 1335281 - Use frame loader for same process browsers. r=mrbkap draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Tue, 14 Feb 2017 14:12:35 -0600
changeset 484169 34eeb289f59e030e626cf9ea3181eb9e9d302ab1
parent 483640 fc9f6f7e8e86f00af60ff1ecc72eaf854a6b1ddd
child 545723 4abc2c9186842985a8f998ab2632dee7e2ee70bb
push id45405
push userbmo:jryans@gmail.com
push dateTue, 14 Feb 2017 21:43:41 +0000
reviewersmrbkap
bugs1335281
milestone54.0a1
Bug 1335281 - Use frame loader for same process browsers. r=mrbkap This changes the `relatedBrowser` property which held a <xul:browser> to the more explicit `sameProcessAsFrameLoader` which takes an nsIFrameLoader. This clarifies the purpose of the property and also (by switching to the frame loader) makes it easier to set in some contexts. MozReview-Commit-ID: LnEvSP8zkto
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
dom/base/nsFrameLoader.cpp
dom/interfaces/base/nsIBrowser.idl
toolkit/components/passwordmgr/test/browser/browser_hasInsecureLoginForms_streamConverter.js
toolkit/components/viewsource/ViewSourceBrowser.jsm
toolkit/components/viewsource/content/viewSource.js
toolkit/content/widgets/browser.xml
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2362,17 +2362,17 @@ function BrowserViewSourceOfDocument(aAr
       // descriptor for the tab (when possible) or fallback to the network if
       // that fails.  Either way, the view source module will manage the tab's
       // location, so use "about:blank" here to avoid unnecessary redundant
       // requests.
       let tab = tabBrowser.loadOneTab("about:blank", {
         relatedToCurrent: true,
         inBackground: false,
         preferredRemoteType,
-        relatedBrowser: args.browser
+        sameProcessAsFrameLoader: args.browser ? args.browser.frameLoader : null
       });
       args.viewSourceBrowser = tabBrowser.getBrowserForTab(tab);
       top.gViewSourceUtils.viewSourceInBrowser(args);
     } else {
       top.gViewSourceUtils.viewSource(args);
     }
   }
 
@@ -3342,29 +3342,31 @@ var PrintPreviewListener = {
   _tabBeforePrintPreview: null,
   _simplifyPageTab: null,
 
   getPrintPreviewBrowser() {
     if (!this._printPreviewTab) {
       let browser = gBrowser.selectedBrowser;
       let preferredRemoteType = browser.remoteType;
       this._tabBeforePrintPreview = gBrowser.selectedTab;
-      this._printPreviewTab = gBrowser.loadOneTab("about:blank",
-                                                  { inBackground: false,
-                                                    preferredRemoteType,
-                                                    relatedBrowser: browser });
+      this._printPreviewTab = gBrowser.loadOneTab("about:blank", {
+        inBackground: false,
+        preferredRemoteType,
+        sameProcessAsFrameLoader: browser.frameLoader
+      });
       gBrowser.selectedTab = this._printPreviewTab;
     }
     return gBrowser.getBrowserForTab(this._printPreviewTab);
   },
   createSimplifiedBrowser() {
     let browser = this._tabBeforePrintPreview.linkedBrowser;
-    this._simplifyPageTab = gBrowser.loadOneTab("about:blank",
-                                                { inBackground: true,
-                                                  relatedBrowser: browser });
+    this._simplifyPageTab = gBrowser.loadOneTab("about:blank", {
+      inBackground: true,
+      sameProcessAsFrameLoader: browser.frameLoader
+     });
     return this.getSimplifiedSourceBrowser();
   },
   getSourceBrowser() {
     return this._tabBeforePrintPreview ?
       this._tabBeforePrintPreview.linkedBrowser : gBrowser.selectedBrowser;
   },
   getSimplifiedSourceBrowser() {
     return this._simplifyPageTab ?
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1506,42 +1506,42 @@
             var aFromExternal;
             var aRelatedToCurrent;
             var aAllowMixedContent;
             var aSkipAnimation;
             var aForceNotRemote;
             var aPreferredRemoteType;
             var aNoReferrer;
             var aUserContextId;
-            var aRelatedBrowser;
+            var aSameProcessAsFrameLoader;
             var aOriginPrincipal;
             var aOpener;
             if (arguments.length == 2 &&
                 typeof arguments[1] == "object" &&
                 !(arguments[1] instanceof Ci.nsIURI)) {
               let params = arguments[1];
-              aTriggeringPrincipal  = params.triggeringPrincipal
-              aReferrerURI          = params.referrerURI;
-              aReferrerPolicy       = params.referrerPolicy;
-              aCharset              = params.charset;
-              aPostData             = params.postData;
-              aLoadInBackground     = params.inBackground;
-              aAllowThirdPartyFixup = params.allowThirdPartyFixup;
-              aFromExternal         = params.fromExternal;
-              aRelatedToCurrent     = params.relatedToCurrent;
-              aAllowMixedContent    = params.allowMixedContent;
-              aSkipAnimation        = params.skipAnimation;
-              aForceNotRemote       = params.forceNotRemote;
-              aPreferredRemoteType  = params.preferredRemoteType;
-              aNoReferrer           = params.noReferrer;
-              aUserContextId        = params.userContextId;
-              aRelatedBrowser       = params.relatedBrowser;
-              aOriginPrincipal      = params.originPrincipal;
-              aOpener               = params.opener;
-              aIsPrerendered        = params.isPrerendered;
+              aTriggeringPrincipal      = params.triggeringPrincipal
+              aReferrerURI              = params.referrerURI;
+              aReferrerPolicy           = params.referrerPolicy;
+              aCharset                  = params.charset;
+              aPostData                 = params.postData;
+              aLoadInBackground         = params.inBackground;
+              aAllowThirdPartyFixup     = params.allowThirdPartyFixup;
+              aFromExternal             = params.fromExternal;
+              aRelatedToCurrent         = params.relatedToCurrent;
+              aAllowMixedContent        = params.allowMixedContent;
+              aSkipAnimation            = params.skipAnimation;
+              aForceNotRemote           = params.forceNotRemote;
+              aPreferredRemoteType      = params.preferredRemoteType;
+              aNoReferrer               = params.noReferrer;
+              aUserContextId            = params.userContextId;
+              aSameProcessAsFrameLoader = params.sameProcessAsFrameLoader;
+              aOriginPrincipal          = params.originPrincipal;
+              aOpener                   = params.opener;
+              aIsPrerendered            = params.isPrerendered;
             }
 
             var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
                          Services.prefs.getBoolPref("browser.tabs.loadInBackground");
             var owner = bgLoad ? null : this.selectedTab;
 
             var tab = this.addTab(aURI, {
                                   triggeringPrincipal: aTriggeringPrincipal,
@@ -1555,17 +1555,17 @@
                                   relatedToCurrent: aRelatedToCurrent,
                                   skipAnimation: aSkipAnimation,
                                   allowMixedContent: aAllowMixedContent,
                                   forceNotRemote: aForceNotRemote,
                                   preferredRemoteType: aPreferredRemoteType,
                                   noReferrer: aNoReferrer,
                                   userContextId: aUserContextId,
                                   originPrincipal: aOriginPrincipal,
-                                  relatedBrowser: aRelatedBrowser,
+                                  sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
                                   opener: aOpener,
                                   isPrerendered: aIsPrerendered });
             if (!bgLoad)
               this.selectedTab = tab;
 
             return tab;
          ]]>
         </body>
@@ -1731,19 +1731,19 @@
 
             let oldUserTypedValue = aBrowser.userTypedValue;
             let hadStartedLoad = aBrowser.didStartLoadSinceLastUserTyping();
 
             // Make sure the browser is destroyed so it unregisters from observer notifications
             aBrowser.destroy();
 
             // Make sure to restore the original droppedLinkHandler and
-            // relatedBrowser.
+            // sameProcessAsFrameLoader.
             let droppedLinkHandler = aBrowser.droppedLinkHandler;
-            let relatedBrowser = aBrowser.relatedBrowser;
+            let sameProcessAsFrameLoader = aBrowser.sameProcessAsFrameLoader;
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
             parent.removeChild(aBrowser);
             if (aShouldBeRemote) {
               aBrowser.setAttribute("remote", "true");
               aBrowser.setAttribute("remoteType", aOptions.remoteType);
             } else {
@@ -1751,17 +1751,17 @@
               aBrowser.removeAttribute("remoteType");
             }
 
             // NB: This works with the hack in the browser constructor that
             // turns this normal property into a field. When switching remote
             // type copying related browser would stop the switch and the
             // previously related browser will no longer be relevant.
             if (!aShouldBeRemote || currentRemoteType == aOptions.remoteType) {
-              aBrowser.relatedBrowser = relatedBrowser;
+              aBrowser.sameProcessAsFrameLoader = sameProcessAsFrameLoader;
             }
 
             if (aOptions.opener) {
               // Set the opener window on the browser, such that when the frame
               // loader is created the opener is set correctly.
               aBrowser.presetOpenerWindow(aOptions.opener);
             }
 
@@ -1991,18 +1991,18 @@
               b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
 
             if (this.hasAttribute("datetimepicker")) {
               b.setAttribute("datetimepicker", this.getAttribute("datetimepicker"));
             }
 
             b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
 
-            if (aParams.relatedBrowser) {
-              b.relatedBrowser = aParams.relatedBrowser;
+            if (aParams.sameProcessAsFrameLoader) {
+              b.sameProcessAsFrameLoader = aParams.sameProcessAsFrameLoader;
             }
 
             // Create the browserStack container
             var stack = document.createElementNS(NS_XUL, "stack");
             stack.className = "browserStack";
             stack.appendChild(b);
             stack.setAttribute("flex", "1");
 
@@ -2073,17 +2073,17 @@
             }
 
             if (!browser) {
               // No preloaded browser found, create one.
               browser = this._createBrowser({permanentKey: aTab.permanentKey,
                                              remoteType,
                                              uriIsAboutBlank,
                                              userContextId: aParams.userContextId,
-                                             relatedBrowser: aParams.relatedBrowser,
+                                             sameProcessAsFrameLoader: aParams.sameProcessAsFrameLoader,
                                              opener: aParams.opener,
                                              isPrerendered: aParams.isPrerendered});
             }
 
             let notificationbox = this.getNotificationBox(browser);
             let uniqueId = this._generateUniquePanelID();
             notificationbox.id = uniqueId;
             aTab.linkedPanel = uniqueId;
@@ -2152,17 +2152,17 @@
             var aRelatedToCurrent;
             var aSkipAnimation;
             var aAllowMixedContent;
             var aForceNotRemote;
             var aPreferredRemoteType;
             var aNoReferrer;
             var aUserContextId;
             var aEventDetail;
-            var aRelatedBrowser;
+            var aSameProcessAsFrameLoader;
             var aOriginPrincipal;
             var aDisallowInheritPrincipal;
             var aOpener;
             if (arguments.length == 2 &&
                 typeof arguments[1] == "object" &&
                 !(arguments[1] instanceof Ci.nsIURI)) {
               let params = arguments[1];
               aTriggeringPrincipal      = params.triggeringPrincipal;
@@ -2176,17 +2176,17 @@
               aRelatedToCurrent         = params.relatedToCurrent;
               aSkipAnimation            = params.skipAnimation;
               aAllowMixedContent        = params.allowMixedContent;
               aForceNotRemote           = params.forceNotRemote;
               aPreferredRemoteType      = params.preferredRemoteType;
               aNoReferrer               = params.noReferrer;
               aUserContextId            = params.userContextId;
               aEventDetail              = params.eventDetail;
-              aRelatedBrowser           = params.relatedBrowser;
+              aSameProcessAsFrameLoader = params.sameProcessAsFrameLoader;
               aOriginPrincipal          = params.originPrincipal;
               aDisallowInheritPrincipal = params.disallowInheritPrincipal;
               aOpener                   = params.opener;
               aIsPrerendered            = params.isPrerendered;
             }
 
             // if we're adding tabs, we're past interrupt mode, ditch the owner
             if (this.mCurrentTab.owner)
@@ -2268,17 +2268,17 @@
             // state to be exploited for startup optimization.  Note that for
             // now this must occur before "TabOpen" event is fired, as that will
             // trigger SessionStore.jsm to run code that expects the existence
             // of tab.linkedBrowser.
             let browserParams = {
               forceNotRemote: aForceNotRemote,
               preferredRemoteType: aPreferredRemoteType,
               userContextId:  aUserContextId,
-              relatedBrowser: aRelatedBrowser,
+              sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
               opener: aOpener,
               isPrerendered: aIsPrerendered,
             };
             let { usingPreloadedContent } = this._linkBrowserToTab(t, aURI, browserParams);
             let b = t.linkedBrowser;
 
             // Dispatch a new tab notification.  We do this once we're
             // entirely done, so that things are in a consistent state
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2819,25 +2819,22 @@ static
 ContentParent*
 GetContentParent(Element* aBrowser)
 {
   nsCOMPtr<nsIBrowser> browser = do_QueryInterface(aBrowser);
   if (!browser) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIDOMElement> related;
-  browser->GetRelatedBrowser(getter_AddRefs(related));
-
-  nsCOMPtr<nsIFrameLoaderOwner> otherOwner = do_QueryInterface(related);
-  if (!otherOwner) {
+  nsCOMPtr<nsIFrameLoader> otherLoader;
+  browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoader));
+  if (!otherLoader) {
     return nullptr;
   }
 
-  nsCOMPtr<nsIFrameLoader> otherLoader = otherOwner->GetFrameLoader();
   TabParent* tabParent = TabParent::GetFrom(otherLoader);
   if (tabParent &&
       tabParent->Manager() &&
       tabParent->Manager()->IsContentParent()) {
     return tabParent->Manager()->AsContentParent();
   }
 
   return nullptr;
--- a/dom/interfaces/base/nsIBrowser.idl
+++ b/dom/interfaces/base/nsIBrowser.idl
@@ -1,24 +1,26 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMElement;
+interface nsIFrameLoader;
 
 [scriptable, uuid(14e5a0cb-e223-4202-95e8-fe53275193ea)]
 interface nsIBrowser : nsISupports
 {
   /**
-   * Gets a related browser for a given browser (if any). If this exists, then
-   * we should attempt to use the same content parent as its frameLoader
-   * for any new tab parents.
+   * Gets an optional frame loader that is "related" to this browser.
+   * If this exists, then we should attempt to use the same content parent as
+   * this frame loader for any new tab parents.  For example, view source
+   * browsers set this to the frame loader for the original content to ensure
+   * they are loaded in the same process as the content.
    */
-  readonly attribute nsIDOMElement relatedBrowser;
+  readonly attribute nsIFrameLoader sameProcessAsFrameLoader;
 
   /*
    * Called by the child to inform the parent that links are dropped into
    * content area.
    *
    * @param linksCount length of links
    * @param links a flat array of url, name, and type for each link
    */
--- a/toolkit/components/passwordmgr/test/browser/browser_hasInsecureLoginForms_streamConverter.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_hasInsecureLoginForms_streamConverter.js
@@ -78,17 +78,17 @@ function waitForInsecureLoginFormsStateC
  */
 add_task(function* test_streamConverter() {
   let originalBrowser = gBrowser.selectedTab.linkedBrowser;
 
   yield ContentTask.spawn(originalBrowser, null, registerConverter);
 
   let tab = gBrowser.addTab("http://example.com/browser/toolkit/components/" +
                             "passwordmgr/test/browser/streamConverter_content.sjs",
-                            { relatedBrowser: originalBrowser });
+                            { sameProcessAsFrameLoader: originalBrowser.frameLoader });
   let browser = tab.linkedBrowser;
   yield Promise.all([
     BrowserTestUtils.switchTab(gBrowser, tab),
     BrowserTestUtils.browserLoaded(browser),
     // One event is triggered by pageshow and one by DOMFormHasPassword.
     waitForInsecureLoginFormsStateChange(browser, 2),
   ]);
 
--- a/toolkit/components/viewsource/ViewSourceBrowser.jsm
+++ b/toolkit/components/viewsource/ViewSourceBrowser.jsm
@@ -181,17 +181,17 @@ ViewSourceBrowser.prototype = {
    *     The line number to focus on once the source is loaded.
    */
   loadViewSource({ URL, browser, outerWindowID, lineNumber }) {
     if (!URL) {
       throw new Error("Must supply a URL when opening view source.");
     }
 
     if (browser) {
-      this.browser.relatedBrowser = browser;
+      this.browser.sameProcessAsFrameLoader = browser.frameLoader;
 
       // If we're dealing with a remote browser, then the browser
       // for view source needs to be remote as well.
       this.updateBrowserRemoteness(browser.isRemoteBrowser, browser.remoteType);
     } else if (outerWindowID) {
       throw new Error("Must supply the browser if passing the outerWindowID");
     }
 
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -673,33 +673,33 @@ ViewSourceChrome.prototype = {
     if (this.browser.isRemoteBrowser == shouldBeRemote &&
         this.browser.remoteType == remoteType) {
       return;
     }
 
     let parentNode = this.browser.parentNode;
     let nextSibling = this.browser.nextSibling;
 
-    // XX Removing and re-adding the browser from and to the DOM strips its
-    // XBL properties. Save and restore relatedBrowser. Note that when we
-    // restore relatedBrowser, there won't yet be a binding or setter. This
-    // works in conjunction with the hack in <xul:browser>'s constructor to
-    // re-get the weak reference to it.
-    let relatedBrowser = this.browser.relatedBrowser;
+    // Removing and re-adding the browser from and to the DOM strips its XBL
+    // properties. Save and restore sameProcessAsFrameLoader. Note that when we
+    // restore sameProcessAsFrameLoader, there won't yet be a binding or
+    // setter. This works in conjunction with the hack in <xul:browser>'s
+    // constructor to re-get the weak reference to it.
+    let sameProcessAsFrameLoader = this.browser.sameProcessAsFrameLoader;
 
     this.browser.remove();
     if (shouldBeRemote) {
       this.browser.setAttribute("remote", "true");
       this.browser.setAttribute("remoteType", remoteType);
     } else {
       this.browser.removeAttribute("remote");
       this.browser.removeAttribute("remoteType");
     }
 
-    this.browser.relatedBrowser = relatedBrowser;
+    this.browser.sameProcessAsFrameLoader = sameProcessAsFrameLoader;
 
     // If nextSibling was null, this will put the browser at
     // the end of the list.
     parentNode.insertBefore(this.browser, nextSibling);
 
     if (shouldBeRemote) {
       // We're going to send a message down to the remote browser
       // to load the source content - however, in order for the
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -231,26 +231,27 @@
                 onget="return this.contentDocument ? this.contentDocument.contentType : null;"
                 readonly="true"/>
 
       <property name="preferences"
                 onget="return this.mPrefs.QueryInterface(Components.interfaces.nsIPrefService);"
                 readonly="true"/>
 
       <!--
-        Weak reference to the related browser (see
-        nsIBrowser.getRelatedBrowser).
+        Weak reference to an optional frame loader that can be used to influence
+        process selection for this browser.
+        See nsIBrowser.sameProcessAsFrameLoader.
       -->
-      <field name="_relatedBrowser">null</field>
-      <property name="relatedBrowser">
+      <field name="_sameProcessAsFrameLoader">null</field>
+      <property name="sameProcessAsFrameLoader">
         <getter><![CDATA[
-          return this._relatedBrowser && this._relatedBrowser.get();
+          return this._sameProcessAsFrameLoader && this._sameProcessAsFrameLoader.get();
         ]]></getter>
         <setter><![CDATA[
-          this._relatedBrowser = Cu.getWeakReference(val);
+          this._sameProcessAsFrameLoader = Cu.getWeakReference(val);
         ]]></setter>
       </property>
 
       <field name="_docShell">null</field>
 
       <property name="docShell" readonly="true">
         <getter><![CDATA[
           if (this._docShell)
@@ -942,24 +943,24 @@
             Components.utils.reportError(e);
           }
           try {
             // Ensures the securityUI is initialized.
             var securityUI = this.securityUI; // eslint-disable-line no-unused-vars
           } catch (e) {
           }
 
-          // XXX tabbrowser.xml sets "relatedBrowser" as a direct property on
-          // some browsers before they are put into a DOM (and get a binding).
-          // This hack makes sure that we hold a weak reference to the other
-          // browser (and go through the proper getter and setter).
-          if (this.hasOwnProperty("relatedBrowser")) {
-            var relatedBrowser = this.relatedBrowser;
-            delete this.relatedBrowser;
-            this.relatedBrowser = relatedBrowser;
+          // tabbrowser.xml sets "sameProcessAsFrameLoader" as a direct property
+          // on some browsers before they are put into a DOM (and get a
+          // binding).  This hack makes sure that we hold a weak reference to
+          // the other browser (and go through the proper getter and setter).
+          if (this.hasOwnProperty("sameProcessAsFrameLoader")) {
+            var sameProcessAsFrameLoader = this.sameProcessAsFrameLoader;
+            delete this.sameProcessAsFrameLoader;
+            this.sameProcessAsFrameLoader = sameProcessAsFrameLoader;
           }
 
           if (!this.isRemoteBrowser) {
             this.addEventListener("pagehide", this.onPageHide, true);
           }
 
           if (this.messageManager) {
             this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);