Bug 1256472 - Add a reason to the restoreTabContent function and message. r?mikedeboer, Gijs draft
authorMike Conley <mconley@mozilla.com>
Tue, 14 Mar 2017 09:55:54 -0400
changeset 502319 2726b471ca698cd5b5b149266085b10c6e69c3b3
parent 501522 8d967436d696d1f8e3fb33cf7e3d32a72457ffa6
child 502320 bf2797cfe906d10480f65feab82eb1cdc35d6b92
push id50256
push usermconley@mozilla.com
push dateTue, 21 Mar 2017 17:20:57 +0000
reviewersmikedeboer, Gijs
bugs1256472
milestone55.0a1
Bug 1256472 - Add a reason to the restoreTabContent function and message. r?mikedeboer, Gijs This helps differentiate restorations that were caused by navigateAndRestore, as opposed to SessionStore having set state via setBrowserState, setWindowState, or setTabState. MozReview-Commit-ID: DEEbKLh7f7p
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/content/content-sessionStore.js
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -127,16 +127,36 @@ const CLOSED_MESSAGES = new Set([
 // These are tab events that we listen to.
 const TAB_EVENTS = [
   "TabOpen", "TabBrowserInserted", "TabClose", "TabSelect", "TabShow", "TabHide", "TabPinned",
   "TabUnpinned"
 ];
 
 const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
+/**
+ * When calling restoreTabContent, we can supply a reason why
+ * the content is being restored. These are those reasons.
+ */
+const RESTORE_TAB_CONTENT_REASON = {
+  /**
+   * SET_STATE:
+   * We're restoring this tab's content because we're setting
+   * state inside this browser tab, probably because the user
+   * has asked us to restore a tab (or window, or entire session).
+   */
+  SET_STATE: 0,
+  /**
+   * NAVIGATE_AND_RESTORE:
+   * We're restoring this tab's content because a navigation caused
+   * us to do a remoteness-flip.
+   */
+  NAVIGATE_AND_RESTORE: 1,
+};
+
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
 Cu.import("resource://gre/modules/Promise.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/Task.jsm", this);
 Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
 Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
 Cu.import("resource://gre/modules/Timer.jsm", this);
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
@@ -901,21 +921,25 @@ var SessionStoreInternal = {
         tab.dispatchEvent(event);
         break;
       }
       case "SessionStore:restoreTabContentStarted":
         if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
           // If a load not initiated by sessionstore was started in a
           // previously pending tab. Mark the tab as no longer pending.
           this.markTabAsRestoring(tab);
-        } else if (!data.isRemotenessUpdate) {
+        } else if (data.reason != RESTORE_TAB_CONTENT_REASON.NAVIGATE_AND_RESTORE) {
           // If the user was typing into the URL bar when we crashed, but hadn't hit
           // enter yet, then we just need to write that value to the URL bar without
           // loading anything. This must happen after the load, as the load will clear
           // userTypedValue.
+          //
+          // Note that we only want to do that if we're restoring state for reasons
+          // _other_ than a navigateAndRestore remoteness-flip, as such a flip
+          // implies that the user was navigating.
           let tabData = TabState.collect(tab);
           if (tabData.userTypedValue && !tabData.userTypedClear && !browser.userTypedValue) {
             browser.userTypedValue = tabData.userTypedValue;
             win.URLBarSetURI();
           }
 
           // Remove state we don't need any longer.
           TabStateCache.update(browser, {
@@ -2792,16 +2816,19 @@ var SessionStoreInternal = {
 
       let tabState = TabState.clone(tab);
       let options = {
         restoreImmediately: true,
         // We want to make sure that this information is passed to restoreTab
         // whether or not a historyIndex is passed in. Thus, we extract it from
         // the loadArguments.
         reloadInFreshProcess: !!recentLoadArguments.reloadInFreshProcess,
+        // Make sure that SessionStore knows that this restoration is due
+        // to a navigation, as opposed to us restoring a closed window or tab.
+        restoreContentReason: RESTORE_TAB_CONTENT_REASON.NAVIGATE_AND_RESTORE,
       };
 
       if (historyIndex >= 0) {
         tabState.index = historyIndex + 1;
         tabState.index = Math.max(1, Math.min(tabState.index, tabState.entries.length));
       } else {
         options.loadArguments = recentLoadArguments;
       }
@@ -3453,16 +3480,17 @@ var SessionStoreInternal = {
 
     let restoreImmediately = options.restoreImmediately;
     let loadArguments = options.loadArguments;
     let browser = tab.linkedBrowser;
     let window = tab.ownerGlobal;
     let tabbrowser = window.gBrowser;
     let forceOnDemand = options.forceOnDemand;
     let reloadInFreshProcess = options.reloadInFreshProcess;
+    let restoreContentReason = options.restoreContentReason;
 
     let willRestoreImmediately = restoreImmediately ||
                                  tabbrowser.selectedBrowser == browser ||
                                  loadArguments;
 
     if (!willRestoreImmediately && !forceOnDemand) {
       TabRestoreQueue.add(tab);
     }
@@ -3577,17 +3605,18 @@ var SessionStoreInternal = {
     // Restore tab attributes.
     if ("attributes" in tabData) {
       TabAttributes.set(tab, tabData.attributes);
     }
 
     // This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but
     // it ensures each window will have its selected tab loaded.
     if (willRestoreImmediately) {
-      this.restoreTabContent(tab, loadArguments, reloadInFreshProcess);
+      this.restoreTabContent(tab, loadArguments, reloadInFreshProcess,
+                             restoreContentReason);
     } else if (!forceOnDemand) {
       this.restoreNextTab();
     }
 
     // Decrease the busy state counter after we're done.
     this._setWindowStateReady(window);
   },
 
@@ -3595,18 +3624,23 @@ var SessionStoreInternal = {
    * Kicks off restoring the given tab.
    *
    * @param aTab
    *        the tab to restore
    * @param aLoadArguments
    *        optional load arguments used for loadURI()
    * @param aReloadInFreshProcess
    *        true if we want to reload into a fresh process
+   * @param aReason
+   *        The reason for why this tab content is being restored.
+   *        Should be one of the values within RESTORE_TAB_CONTENT_REASON.
+   *        Defaults to RESTORE_TAB_CONTENT_REASON.SET_STATE.
    */
-  restoreTabContent(aTab, aLoadArguments = null, aReloadInFreshProcess = false) {
+  restoreTabContent(aTab, aLoadArguments = null, aReloadInFreshProcess = false,
+                    aReason = RESTORE_TAB_CONTENT_REASON.SET_STATE) {
     if (aTab.hasAttribute("customizemode") && !aLoadArguments) {
       return;
     }
 
     let browser = aTab.linkedBrowser;
     let window = aTab.ownerGlobal;
     let tabbrowser = window.gBrowser;
     let tabData = TabState.clone(aTab);
@@ -3656,17 +3690,18 @@ var SessionStoreInternal = {
 
     // If the restored browser wants to show view source content, start up a
     // view source browser that will load the required frame script.
     if (uri && ViewSourceBrowser.isViewSource(uri)) {
       new ViewSourceBrowser(browser);
     }
 
     browser.messageManager.sendAsyncMessage("SessionStore:restoreTabContent",
-      {loadArguments: aLoadArguments, isRemotenessUpdate});
+      {loadArguments: aLoadArguments, isRemotenessUpdate,
+       reason: aReason});
   },
 
   /**
    * Marks a given pending tab as restoring.
    *
    * @param aTab
    *        the pending tab to mark as restoring
    */
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -193,27 +193,29 @@ var MessageListener = {
     // SessionStore.jsm so that it can run SSTabRestoring. Users of
     // SSTabRestoring seem to get confused if chrome and content are out of
     // sync about the state of the restore (particularly regarding
     // docShell.currentURI). Using a synchronous message is the easiest way
     // to temporarily synchronize them.
     sendSyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
   },
 
-  restoreTabContent({loadArguments, isRemotenessUpdate}) {
+  restoreTabContent({loadArguments, isRemotenessUpdate, reason}) {
     let epoch = gCurrentEpoch;
 
     // We need to pass the value of didStartLoad back to SessionStore.jsm.
     let didStartLoad = gContentRestore.restoreTabContent(loadArguments, isRemotenessUpdate, () => {
       // Tell SessionStore.jsm that it may want to restore some more tabs,
       // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
       sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
     });
 
-    sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch, isRemotenessUpdate});
+    sendAsyncMessage("SessionStore:restoreTabContentStarted", {
+      epoch, isRemotenessUpdate, reason,
+    });
 
     if (!didStartLoad) {
       // Pretend that the load succeeded so that event handlers fire correctly.
       sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
     }
   },
 
   flush({id}) {