Bug 1318767 - Part 1: When performing SessionRestore on a GroupedSHistory tab, ensure that it reverts to a complete SHistory state before restoring, r=mikedeboer
authorMichael Layzell <michael@thelayzells.com>
Thu, 24 Nov 2016 10:45:00 +0800
changeset 325862 a9d879cfa0f7a7af35a85e118ac51f7b237f583a
parent 325861 5dbec5fef561e38b38b9efa0d744f04e3f81640e
child 325863 447db63f9b10e75fd48a42a38ce9298ddd839930
push idunknown
push userunknown
push dateunknown
reviewersmikedeboer
bugs1318767
milestone53.0a1
Bug 1318767 - Part 1: When performing SessionRestore on a GroupedSHistory tab, ensure that it reverts to a complete SHistory state before restoring, r=mikedeboer MozReview-Commit-ID: 2zNXDtkx3bs
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/components/sessionstore/SessionStore.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1142,17 +1142,17 @@ var gBrowserInit = {
           gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
         }
 
         try {
           // Make sure selectedBrowser has the same remote settings as the one
           // we are swapping in.
           gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser,
                                            tabToOpen.linkedBrowser.isRemoteBrowser,
-                                           tabToOpen.linkedBrowser.remoteType);
+                                           { remoteType: tabToOpen.linkedBrowser.remoteType });
           gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToOpen);
         } catch (e) {
           Cu.reportError(e);
         }
       }
       // window.arguments[2]: referrer (nsIURI | string)
       //                 [3]: postData (nsIInputStream)
       //                 [4]: allowThirdPartyFixup (bool)
@@ -4249,23 +4249,23 @@ var XULBrowserWindow = {
 
   setJSStatus: function() {
     // unsupported
   },
 
   forceInitialBrowserRemote: function(aRemoteType) {
     let initBrowser =
       document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-    gBrowser.updateBrowserRemoteness(initBrowser, true, aRemoteType, null);
+    gBrowser.updateBrowserRemoteness(initBrowser, true, { remoteType: aRemoteType });
   },
 
   forceInitialBrowserNonRemote: function(aOpener) {
     let initBrowser =
       document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-    gBrowser.updateBrowserRemoteness(initBrowser, false, E10SUtils.NOT_REMOTE, aOpener);
+    gBrowser.updateBrowserRemoteness(initBrowser, false, { opener: aOpener });
   },
 
   setDefaultStatus: function(status) {
     this.defaultStatus = status;
     this.updateStatusField();
   },
 
   setOverLink: function(url, anchorElt) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1664,48 +1664,47 @@
               this.selectedBrowser.focus();
           }
         ]]></body>
       </method>
 
       <method name="updateBrowserRemoteness">
         <parameter name="aBrowser"/>
         <parameter name="aShouldBeRemote"/>
-        <parameter name="aNewRemoteType"/>
-        <parameter name="aOpener"/>
-        <parameter name="aFreshProcess"/>
+        <parameter name="aOptions"/>
         <body>
           <![CDATA[
+            aOptions = aOptions || {};
+            let isRemote = aBrowser.getAttribute("remote") == "true";
+
             if (!gMultiProcessBrowser && aShouldBeRemote) {
               throw new Error("Cannot switch to remote browser in a window " +
                               "without the remote tabs load context.");
             }
 
-            let isRemote = aBrowser.getAttribute("remote") == "true";
-
-            // If going remote and no aNewRemoteType then use default.
-            if (aShouldBeRemote && !aNewRemoteType) {
-              aNewRemoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
+            // Default values for remoteType
+            if (!aOptions.remoteType) {
+              aOptions.remoteType = aShouldBeRemote ? E10SUtils.DEFAULT_REMOTE_TYPE : E10SUtils.NOT_REMOTE;
             }
 
             // If we are passed an opener, we must be making the browser non-remote, and
             // if the browser is _currently_ non-remote, we need the openers to match,
             // because it is already too late to change it.
-            if (aOpener) {
+            if (aOptions.opener) {
               if (aShouldBeRemote) {
                 throw new Error("Cannot set an opener on a browser which should be remote!");
               }
-              if (!isRemote && aBrowser.contentWindow.opener != aOpener) {
+              if (!isRemote && aBrowser.contentWindow.opener != aOptions.opener) {
                 throw new Error("Cannot change opener on an already non-remote browser!");
               }
             }
 
             // Abort if we're not going to change anything
-            if (isRemote == aShouldBeRemote && !aFreshProcess &&
-                (!isRemote || aBrowser.getAttribute("remoteType") == aNewRemoteType)) {
+            if (isRemote == aShouldBeRemote && !aOptions.newFrameloader && !aOptions.freshProcess &&
+                (!isRemote || aBrowser.getAttribute("remoteType") == aOptions.remoteType)) {
               return false;
             }
 
             let tab = this.getTabForBrowser(aBrowser);
             let evt = document.createEvent("Events");
             evt.initEvent("BeforeTabRemotenessChange", true, false);
             tab.dispatchEvent(evt);
 
@@ -1734,33 +1733,35 @@
             let droppedLinkHandler = aBrowser.droppedLinkHandler;
             let relatedBrowser = aBrowser.relatedBrowser;
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
             parent.removeChild(aBrowser);
             if (aShouldBeRemote) {
               aBrowser.setAttribute("remote", "true");
-              aBrowser.setAttribute("remoteType", aNewRemoteType);
+              aBrowser.setAttribute("remoteType", aOptions.remoteType);
             } else {
               aBrowser.setAttribute("remote", "false");
               aBrowser.removeAttribute("remoteType");
             }
 
             // NB: This works with the hack in the browser constructor that
             // turns this normal property into a field.
             aBrowser.relatedBrowser = relatedBrowser;
 
-            // Set the opener window on the browser, such that when the frame
-            // loader is created the opener is set correctly.
-            aBrowser.presetOpenerWindow(aOpener);
+            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);
+            }
 
             // Set the freshProcess attribute so that the frameloader knows to
             // create a new process
-            if (aFreshProcess) {
+            if (aOptions.freshProcess) {
               aBrowser.setAttribute("freshProcess", "true");
             }
 
             parent.appendChild(aBrowser);
 
             // Remove the freshProcess attribute if we set it, as we don't
             // want it to apply for the next time the frameloader is created
             aBrowser.removeAttribute("freshProcess");
@@ -1825,34 +1826,34 @@
             return true;
           ]]>
         </body>
       </method>
 
       <method name="updateBrowserRemotenessByURL">
         <parameter name="aBrowser"/>
         <parameter name="aURL"/>
-        <parameter name="aFreshProcess"/>
+        <parameter name="aOptions"/>
         <body>
           <![CDATA[
+            aOptions = aOptions || {};
+
             if (!gMultiProcessBrowser)
               return this.updateBrowserRemoteness(aBrowser, false);
 
             // If this URL can't load in the current browser then flip it to the
             // correct type.
             let currentRemoteType = aBrowser.remoteType;
-            let requiredRemoteType =
+            aOptions.remoteType =
               E10SUtils.getRemoteTypeForURI(aURL, gMultiProcessBrowser,
                                             currentRemoteType);
-            if (currentRemoteType != requiredRemoteType || aFreshProcess) {
-              return this.updateBrowserRemoteness(aBrowser,
-                                                  !!requiredRemoteType,
-                                                  requiredRemoteType,
-                                                  /* aOpener */ null,
-                                                  aFreshProcess);
+            if (currentRemoteType != aOptions.remoteType ||
+                aOptions.freshProcess || aOptions.newFrameloader) {
+              let remote = aOptions.remoteType != E10SUtils.NOT_REMOTE;
+              return this.updateBrowserRemoteness(aBrowser, remote, aOptions);
             }
 
             return false;
           ]]>
         </body>
       </method>
 
       <field name="_preloadedBrowser">null</field>
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -3606,18 +3606,27 @@ var SessionStoreInternal = {
     }
 
     // We have to mark this tab as restoring first, otherwise
     // the "pending" attribute will be applied to the linked
     // browser, which removes it from the display list. We cannot
     // flip the remoteness of any browser that is not being displayed.
     this.markTabAsRestoring(aTab);
 
+    // We need a new frameloader either if we are reloading into a fresh
+    // process, or we have a browser with a grouped session history (as we don't
+    // support restoring into browsers with grouped session histories directly).
+    let newFrameloader =
+      aReloadInFreshProcess || !!browser.frameLoader.groupedSessionHistory;
     let isRemotenessUpdate =
-      tabbrowser.updateBrowserRemotenessByURL(browser, uri, aReloadInFreshProcess);
+      tabbrowser.updateBrowserRemotenessByURL(browser, uri, {
+        freshProcess: aReloadInFreshProcess,
+        newFrameloader: newFrameloader,
+      });
+
     if (isRemotenessUpdate) {
       // We updated the remoteness, so we need to send the history down again.
       //
       // Start a new epoch to discard all frame script messages relating to a
       // previous epoch. All async messages that are still on their way to chrome
       // will be ignored and don't override any tab data set when restoring.
       let epoch = this.startNextEpoch(browser);