Bug 1142034 - Don't show 'Restore All Crashed Tabs' when only one tab has crashed. r=mconley
authorUrsula <usarracini@mozilla.com>
Thu, 23 Jul 2015 14:47:35 -0400
changeset 286860 ec8ea44bdb05ee4b0efcb8d55fb888b206a179b5
parent 286859 60a0b1f2e41c695a1b618bffc26d68ae8de82574
child 286861 c69643cd3502c2b24987890954959594bb7ad0e9
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1142034
milestone42.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 1142034 - Don't show 'Restore All Crashed Tabs' when only one tab has crashed. r=mconley
browser/base/content/browser.js
browser/components/sessionstore/SessionStore.jsm
browser/modules/ContentCrashReporters.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1134,17 +1134,19 @@ var gBrowserInit = {
     mm.addMessageListener("PageVisibility:Show", function(message) {
       if (message.target == gBrowser.selectedBrowser) {
         setTimeout(pageShowEventHandlers, 0, message.data.persisted);
       }
     });
 
     gBrowser.addEventListener("AboutTabCrashedLoad", function(event) {
 #ifdef MOZ_CRASHREPORTER
-      TabCrashReporter.onAboutTabCrashedLoad(gBrowser.getBrowserForDocument(event.target));
+      TabCrashReporter.onAboutTabCrashedLoad(gBrowser.getBrowserForDocument(event.target), {
+        crashedTabCount: SessionStore.crashedTabCount,
+      });
 #endif
     }, false, true);
 
     gBrowser.addEventListener("AboutTabCrashedMessage", function(event) {
       let ownerDoc = event.originalTarget;
 
       if (!ownerDoc.documentURI.startsWith("about:tabcrashed")) {
         return;
@@ -1166,21 +1168,17 @@ var gBrowserInit = {
       switch (event.detail.message) {
       case "closeTab":
         gBrowser.removeTab(tab, { animate: true });
         break;
       case "restoreTab":
         SessionStore.reviveCrashedTab(tab);
         break;
       case "restoreAll":
-        for (let browserWin of browserWindows()) {
-          for (let tab of browserWin.gBrowser.tabs) {
-            SessionStore.reviveCrashedTab(tab);
-          }
-        }
+        SessionStore.reviveAllCrashedTabs();
         break;
       }
     }, false, true);
 
     let uriToLoad = this._getUriToLoad();
     if (uriToLoad && uriToLoad != "about:blank") {
       if (uriToLoad instanceof Ci.nsISupportsArray) {
         let count = uriToLoad.Count();
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -177,16 +177,20 @@ this.SessionStore = {
   get promiseInitialized() {
     return SessionStoreInternal.promiseInitialized;
   },
 
   get canRestoreLastSession() {
     return SessionStoreInternal.canRestoreLastSession;
   },
 
+  get crashedTabCount() {
+    return SessionStoreInternal._crashedBrowsersCount;
+  },
+
   set canRestoreLastSession(val) {
     SessionStoreInternal.canRestoreLastSession = val;
   },
 
   init: function ss_init() {
     SessionStoreInternal.init();
   },
 
@@ -297,16 +301,20 @@ this.SessionStore = {
   getCurrentState: function (aUpdateAll) {
     return SessionStoreInternal.getCurrentState(aUpdateAll);
   },
 
   reviveCrashedTab(aTab) {
     return SessionStoreInternal.reviveCrashedTab(aTab);
   },
 
+  reviveAllCrashedTabs() {
+    return SessionStoreInternal.reviveAllCrashedTabs();
+  },
+
   navigateAndRestore(tab, loadArguments, historyIndex) {
     return SessionStoreInternal.navigateAndRestore(tab, loadArguments, historyIndex);
   }
 };
 
 // Freeze the SessionStore object. We don't want anyone to modify it.
 Object.freeze(SessionStore);
 
@@ -326,16 +334,19 @@ let SessionStoreInternal = {
   // For each <browser> element, records the current epoch.
   _browserEpochs: new WeakMap(),
 
   // Any browsers that fires the oop-browser-crashed event gets stored in
   // here - that way we know which browsers to ignore messages from (until
   // they get restored).
   _crashedBrowsers: new WeakSet(),
 
+  // The number of crashed browsers.
+  _crashedBrowsersCount: 0,
+
   // A map (xul:browser -> nsIFrameLoader) that maps a browser to the last
   // associated frameLoader we heard about.
   _lastKnownFrameLoader: new WeakMap(),
 
   // A map (xul:browser -> object) that maps a browser associated with a
   // recently closed tab to all its necessary state information we need to
   // properly handle final update message.
   _closedTabs: new WeakMap(),
@@ -1403,16 +1414,20 @@ let SessionStoreInternal = {
 
     if (browser.frameLoader) {
       this._lastKnownFrameLoader.set(browser.permanentKey, browser.frameLoader);
     }
 
     if (!aNoNotification) {
       this.saveStateDelayed(aWindow);
     }
+
+    if (this._crashedBrowsers.has(browser.permanentKey)) {
+      this._crashedBrowsersCount++;
+    }
   },
 
   /**
    * remove listeners for a tab
    * @param aWindow
    *        Window reference
    * @param aTab
    *        Tab reference
@@ -1432,16 +1447,20 @@ let SessionStoreInternal = {
       this._resetTabRestoringState(aTab);
       if (previousState == TAB_STATE_RESTORING)
         this.restoreNextTab();
     }
 
     if (!aNoNotification) {
       this.saveStateDelayed(aWindow);
     }
+
+    if (this._crashedBrowsers.has(browser.permanentKey)) {
+      this._crashedBrowsersCount--;
+    }
   },
 
   /**
    * When a tab closes, collect its properties
    * @param aWindow
    *        Window reference
    * @param aTab
    *        Tab reference
@@ -1611,16 +1630,17 @@ let SessionStoreInternal = {
    *
    * @param aWindow
    *        The window that the crashed browser belongs to.
    * @param aBrowser
    *        The <xul:browser> that is now in the crashed state.
    */
   onBrowserCrashed: function(aWindow, aBrowser) {
     this._crashedBrowsers.add(aBrowser.permanentKey);
+    this._crashedBrowsersCount++;
     // If we never got around to restoring this tab, clear its state so
     // that we don't try restoring if the user switches to it before
     // reviving the crashed browser. This is throwing away the information
     // that the tab was in a pending state when the browser crashed, which
     // is an explicit choice. For now, when restoring all crashed tabs, based
     // on a user preference we'll either restore all of them at once, or only
     // restore the selected tab and lazily restore the rest. We'll make no
     // efforts at this time to be smart and restore all of the tabs that had
@@ -2166,16 +2186,33 @@ let SessionStoreInternal = {
     // at this point.
     if (browser.isRemoteBrowser) {
       throw new Error("SessionStore.reviveCrashedTab: " +
                       "Somehow a crashed browser is still remote.")
     }
 
     let data = TabState.collect(aTab);
     this.restoreTab(aTab, data);
+
+    this._crashedBrowsersCount--;
+  },
+
+  /**
+   * Revive all crashed tabs and reset the crashed tabs count to 0.
+   */
+  reviveAllCrashedTabs() {
+    let windowsEnum = Services.wm.getEnumerator("navigator:browser");
+    while (windowsEnum.hasMoreElements()) {
+      let window = windowsEnum.getNext();
+      for (let tab of window.gBrowser.tabs) {
+        this.reviveCrashedTab(tab);
+      }
+    }
+
+    this._crashedBrowsersCount = 0;
   },
 
   /**
    * Navigate the given |tab| by first collecting its current state and then
    * either changing only the index of the currently shown shistory entry,
    * or restoring the exact same state again and passing the new URL to load
    * in |loadArguments|. Use this method to seamlessly switch between pages
    * loaded in the parent and pages loaded in the child process.
--- a/browser/modules/ContentCrashReporters.jsm
+++ b/browser/modules/ContentCrashReporters.jsm
@@ -83,25 +83,35 @@ this.TabCrashReporter = {
           this.browserMap.delete(browser);
           browser.contentDocument.documentElement.classList.remove("crashDumpAvailable");
           browser.contentDocument.documentElement.classList.add("crashDumpSubmitted");
         }
       }
     }
   },
 
-  onAboutTabCrashedLoad: function (aBrowser) {
+  onAboutTabCrashedLoad: function (aBrowser, aParams) {
+    // If there was only one tab open that crashed, do not show the "restore all tabs" button
+    if (aParams.crashedTabCount == 1) {
+      this.hideRestoreAllButton(aBrowser);
+    }
+
     if (!this.childMap)
       return;
 
     let dumpID = this.childMap.get(this.browserMap.get(aBrowser));
     if (!dumpID)
       return;
 
     aBrowser.contentDocument.documentElement.classList.add("crashDumpAvailable");
+  },
+
+  hideRestoreAllButton: function (aBrowser) {
+    aBrowser.contentDocument.getElementById("restoreAll").setAttribute("hidden", true);
+    aBrowser.contentDocument.getElementById("restoreTab").setAttribute("class", "primary");
   }
 }
 
 this.PluginCrashReporter = {
   /**
    * Makes the PluginCrashReporter ready to hear about and
    * submit crash reports.
    */