Bug 1418793 - stop trying to get per-tab previews to work prior to session restore, r=florian
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 14 Aug 2018 13:40:11 +0000
changeset 432335 3d64c00c695a519b83b3644ab46f38b8a8add753
parent 432334 9648d9afdd2a37674616bed74dbd51a82f6c6060
child 432351 1ba33950cff38b7e7baaf5d96431a11814de83df
child 432352 b8918cd29dde0375996ab3d0a377c72b1239ff3d
push id34473
push usershindli@mozilla.com
push dateMon, 20 Aug 2018 16:30:57 +0000
treeherdermozilla-central@3d64c00c695a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian
bugs1418793
milestone63.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 1418793 - stop trying to get per-tab previews to work prior to session restore, r=florian Initialize WindowsPreviewPerTab later, and make its favicon update code more efficient. Differential Revision: https://phabricator.services.mozilla.com/D2679
browser/base/content/browser.js
browser/modules/WindowsPreviewPerTab.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -218,20 +218,24 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
 
   const WINTASKBAR_CONTRACTID = "@mozilla.org/windows-taskbar;1";
   if (WINTASKBAR_CONTRACTID in Cc &&
       Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar).available) {
     let AeroPeek = ChromeUtils.import("resource:///modules/WindowsPreviewPerTab.jsm", {}).AeroPeek;
     return {
       onOpenWindow() {
         AeroPeek.onOpenWindow(window);
+        this.handledOpening = true;
       },
       onCloseWindow() {
-        AeroPeek.onCloseWindow(window);
-      }
+        if (this.handledOpening) {
+          AeroPeek.onCloseWindow(window);
+        }
+      },
+      handledOpening: false,
     };
   }
   return null;
 });
 
 var gBrowser;
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
@@ -1502,19 +1506,16 @@ var gBrowserInit = {
       updateEditUIVisibility();
       let placesContext = document.getElementById("placesContext");
       placesContext.addEventListener("popupshowing", updateEditUIVisibility);
       placesContext.addEventListener("popuphiding", updateEditUIVisibility);
     }
 
     LightWeightThemeWebInstaller.init();
 
-    if (Win7Features)
-      Win7Features.onOpenWindow();
-
     FullScreen.init();
     PointerLock.init();
 
     if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
       MenuTouchModeObserver.init();
     }
 
     if (AppConstants.MOZ_DATA_REPORTING)
@@ -1765,16 +1766,20 @@ var gBrowserInit = {
         DownloadsCommon.initializeAllDataLinks();
         ChromeUtils.import("resource:///modules/DownloadsTaskbar.jsm", {})
           .DownloadsTaskbar.registerIndicator(window);
       } catch (ex) {
         Cu.reportError(ex);
       }
     }, {timeout: 10000});
 
+    if (Win7Features) {
+      scheduleIdleTask(() => Win7Features.onOpenWindow());
+    }
+
     // This should always go last, since the idle tasks (except for the ones with
     // timeouts) should execute in order. Note that this observer notification is
     // not guaranteed to fire, since the window could close before we get here.
     scheduleIdleTask(() => {
       this.idleTasksFinished = true;
       Services.obs.notifyObservers(window, "browser-idle-startup-tasks-finished");
     });
   },
@@ -1890,19 +1895,16 @@ var gBrowserInit = {
 
     BrowserSearch.uninit();
 
     // Now either cancel delayedStartup, or clean up the services initialized from
     // it.
     if (this._boundDelayedStartup) {
       this._cancelDelayedStartup();
     } else {
-      if (Win7Features)
-        Win7Features.onCloseWindow();
-
       Services.prefs.removeObserver(ctrlTab.prefName, ctrlTab);
       ctrlTab.uninit();
       gBrowserThumbnails.uninit();
       FullZoom.destroy();
 
       Services.obs.removeObserver(gIdentityHandler, "perm-changed");
       Services.obs.removeObserver(gRemoteControl, "remote-active");
       Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -427,19 +427,19 @@ TabWindow.prototype = {
     // Now that we've updated this.previews, it will resolve successfully.
     controller.updateTitleAndTooltip();
   },
 
   createTabPreview(controller) {
     let docShell = this.win.docShell;
     let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller);
     preview.visible = AeroPeek.enabled;
-    preview.active = this.tabbrowser.selectedTab == controller.tab;
-    this.onLinkIconAvailable(controller.tab.linkedBrowser,
-                             controller.tab.getAttribute("image"));
+    let {tab} = controller;
+    preview.active = this.tabbrowser.selectedTab == tab;
+    this.updateFavicon(tab, tab.getAttribute("image"));
     return preview;
   },
 
   // Invoked when the given tab is closed
   removeTab(tab) {
     let preview = this.previewFromTab(tab);
     preview.active = false;
     preview.visible = false;
@@ -580,16 +580,20 @@ TabWindow.prototype = {
       this.invalidateTabPreview(aBrowser);
     }
   },
 
   directRequestProtocols: new Set([
     "file", "chrome", "resource", "about"
   ]),
   onLinkIconAvailable(aBrowser, aIconURL) {
+    let tab = this.win.gBrowser.getTabForBrowser(aBrowser);
+    this.updateFavicon(tab, aIconURL);
+  },
+  updateFavicon(aTab, aIconURL) {
     let requestURL = null;
     if (aIconURL) {
       let shouldRequestFaviconURL = true;
       try {
         let urlObject = NetUtil.newURI(aIconURL);
         shouldRequestFaviconURL =
           !this.directRequestProtocols.has(urlObject.scheme);
       } catch (ex) {}
@@ -598,27 +602,32 @@ TabWindow.prototype = {
         "moz-anno:favicon:" + aIconURL :
         aIconURL;
     }
     let isDefaultFavicon = !requestURL;
     getFaviconAsImage(
       requestURL,
       PrivateBrowsingUtils.isWindowPrivate(this.win),
       img => {
-        let index = this.tabbrowser.browsers.indexOf(aBrowser);
-        // Only add it if we've found the index and the URI is still the same.
         // The tab could have closed, and there's no guarantee the icons
         // will have finished fetching 'in order'.
-        if (index != -1) {
-          let tab = this.tabbrowser.tabs[index];
-          let preview = this.previews.get(tab);
-          if (tab.getAttribute("image") == aIconURL ||
-              (!preview.icon && isDefaultFavicon)) {
-            preview.icon = img;
-          }
+        if (this.win.closed || aTab.closing || !aTab.linkedBrowser) {
+          return;
+        }
+        // Note that bizarrely, we can get to updateFavicon via a sync codepath
+        // where the new preview controller hasn't yet been added to the
+        // window's map of previews. So `preview` would be null here - except
+        // getFaviconAsImage is async so that should never happen, as we add
+        // the controller to the preview collection straight after creating it.
+        // However, if any of this code ever tries to access this
+        // synchronously, that won't work.
+        let preview = this.previews.get(aTab);
+        if (aTab.getAttribute("image") == aIconURL ||
+            (!preview.icon && isDefaultFavicon)) {
+          preview.icon = img;
         }
       }
     );
   }
 };
 
 // AeroPeek
 
@@ -819,17 +828,17 @@ var AeroPeek = {
   onDeleteURI() {},
   onClearHistory() {},
   onDeleteVisits() {},
   onPageChanged(uri, changedConst, newValue) {
     if (this.enabled && changedConst == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
       for (let win of this.windows) {
         for (let [tab, ] of win.previews) {
           if (tab.getAttribute("image") == newValue) {
-            win.onLinkIconAvailable(tab.linkedBrowser, newValue);
+            win.updateFavicon(tab, newValue);
           }
         }
       }
     }
   },
 
   QueryInterface: ChromeUtils.generateQI([
     Ci.nsISupportsWeakReference,