Bug 1365541 - Re-implement reusing the selected tab when restoring a window to fix FX_SESSION_RESTORE_RESTORE_WINDOW_MS regression. r=mikedeboer, a=lizzard
authorDão Gottwald <dao@mozilla.com>
Mon, 19 Jun 2017 12:57:09 +0200
changeset 414104 ceb3cb73a8b1c6c80fac90e10dcdc62e60a3980b
parent 414103 c1683cb4df4583171c88b00e3a26e035959e5b1f
child 414105 9a93656f44a26de617a0ab458f9cef3ca5328e72
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer, lizzard
bugs1365541
milestone55.0
Bug 1365541 - Re-implement reusing the selected tab when restoring a window to fix FX_SESSION_RESTORE_RESTORE_WINDOW_MS regression. r=mikedeboer, a=lizzard MozReview-Commit-ID: CFxrJ8NjlER
browser/components/sessionstore/SessionStore.jsm
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -3250,95 +3250,109 @@ var SessionStoreInternal = {
     let selectTab = 0;
     if (overwriteTabs) {
       selectTab = parseInt(winData.selected || 1, 10);
       selectTab = Math.max(selectTab, 1);
       selectTab = Math.min(selectTab, winData.tabs.length);
     }
 
     let tabbrowser = aWindow.gBrowser;
-    let tabsToRemove = overwriteTabs ? tabbrowser.browsers.length : 0;
     let newTabCount = winData.tabs.length;
     var tabs = [];
 
     // disable smooth scrolling while adding, moving, removing and selecting tabs
     let tabstrip = tabbrowser.tabContainer.mTabstrip;
     let smoothScroll = tabstrip.smoothScroll;
     tabstrip.smoothScroll = false;
 
     // We need to keep track of the initially open tabs so that they
     // can be moved to the end of the restored tabs.
-    let initialTabs = [];
+    let initialTabs;
     if (!overwriteTabs && firstWindow) {
       initialTabs = Array.slice(tabbrowser.tabs);
     }
 
+    // Get rid of tabs that aren't needed anymore.
+    if (overwriteTabs) {
+      for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
+        if (!tabbrowser.tabs[i].selected) {
+          tabbrowser.removeTab(tabbrowser.tabs[i]);
+        }
+      }
+    }
+
     let restoreTabsLazily = this._prefBranch.getBoolPref("sessionstore.restore_tabs_lazily") &&
       this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
 
     for (var t = 0; t < newTabCount; t++) {
       let tabData = winData.tabs[t];
 
       let userContextId = tabData.userContextId;
       let select = t == selectTab - 1;
-      let createLazyBrowser = restoreTabsLazily && !select && !tabData.pinned;
-
-      let url = "about:blank";
-      if (createLazyBrowser && tabData.entries && tabData.entries.length) {
-        // Let tabbrowser know the future URI because progress listeners won't
-        // get onLocationChange notification before the browser is inserted.
-        let activeIndex = (tabData.index || tabData.entries.length) - 1;
-        // Ensure the index is in bounds.
-        activeIndex = Math.min(activeIndex, tabData.entries.length - 1);
-        activeIndex = Math.max(activeIndex, 0);
-        url = tabData.entries[activeIndex].url;
+      let tab;
+
+      // Re-use existing selected tab if possible to avoid the overhead of
+      // selecting a new tab.
+      if (select &&
+          tabbrowser.selectedTab.userContextId == userContextId) {
+        tab = tabbrowser.selectedTab;
+        if (!tabData.pinned) {
+          tabbrowser.unpinTab(tab);
+        }
+        tabbrowser.moveTabToEnd();
+        if (aWindow.gMultiProcessBrowser && !tab.linkedBrowser.isRemoteBrowser) {
+          tabbrowser.updateBrowserRemoteness(tab.linkedBrowser, true);
+        }
       }
 
-      // Setting noInitialLabel is a perf optimization. Rendering tab labels
-      // would make resizing the tabs more expensive as we're adding them.
-      // Each tab will get its initial label set in restoreTab.
-      let tab = tabbrowser.addTab(url,
-                                  { createLazyBrowser,
-                                    skipAnimation: true,
-                                    noInitialLabel: true,
-                                    userContextId,
-                                    skipBackgroundNotify: true });
-
-      if (select) {
-        // Select a new tab first to prevent the removeTab loop from changing
-        // the selected tab over and over again.
-        tabbrowser.selectedTab = tab;
-
-        // Remove superfluous tabs.
-        for (let i = 0; i < tabsToRemove; i++) {
-          tabbrowser.removeTab(tabbrowser.tabs[0]);
+      // Add a new tab if needed.
+      if (!tab) {
+        let createLazyBrowser = restoreTabsLazily && !select && !tabData.pinned;
+
+        let url = "about:blank";
+        if (createLazyBrowser && tabData.entries && tabData.entries.length) {
+          // Let tabbrowser know the future URI because progress listeners won't
+          // get onLocationChange notification before the browser is inserted.
+          let activeIndex = (tabData.index || tabData.entries.length) - 1;
+          // Ensure the index is in bounds.
+          activeIndex = Math.min(activeIndex, tabData.entries.length - 1);
+          activeIndex = Math.max(activeIndex, 0);
+          url = tabData.entries[activeIndex].url;
         }
-        tabsToRemove = 0;
+
+        // Setting noInitialLabel is a perf optimization. Rendering tab labels
+        // would make resizing the tabs more expensive as we're adding them.
+        // Each tab will get its initial label set in restoreTab.
+        tab = tabbrowser.addTab(url,
+                                { createLazyBrowser,
+                                  skipAnimation: true,
+                                  noInitialLabel: true,
+                                  userContextId,
+                                  skipBackgroundNotify: true });
+
+        if (select) {
+          let leftoverTab = tabbrowser.selectedTab;
+          tabbrowser.selectedTab = tab;
+          tabbrowser.removeTab(leftoverTab);
+        }
       }
 
       tabs.push(tab);
 
       if (tabData.hidden) {
-        tabbrowser.hideTab(tabs[t]);
+        tabbrowser.hideTab(tab);
+      }
+
+      if (tabData.pinned) {
+        tabbrowser.pinTab(tab);
       }
     }
 
-    for (let i = 0; i < newTabCount; ++i) {
-      if (winData.tabs[i].pinned) {
-        tabbrowser.pinTab(tabs[i]);
-      } else {
-        // Pinned tabs are clustered at the start of the tab strip. As
-        // soon as we reach a tab that isn't pinned, we know there aren't
-        // any more for this window.
-        break;
-      }
-    }
-
-    if (!overwriteTabs && firstWindow) {
-      // Move the originally open tabs to the end
+    // Move the originally open tabs to the end.
+    if (initialTabs) {
       let endPosition = tabbrowser.tabs.length - 1;
       for (let i = 0; i < initialTabs.length; i++) {
         tabbrowser.unpinTab(initialTabs[i]);
         tabbrowser.moveTabTo(initialTabs[i], endPosition);
       }
     }
 
     // We want to correlate the window with data from the last session, so