Merge inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Fri, 16 Feb 2018 12:15:38 +0200
changeset 404143 f01d1def46fb53a6523768c6e9188e66b89e664e
parent 404133 9eaebbcc33fd3824876db1b8b33750e997c02f7b (current diff)
parent 404061 0adb6b91b758fc7e45bd0476a2fbadc913adeee0 (diff)
child 404144 941681a0ddc64f46dda9c2e69ea36a78bc307dee
child 404204 c76cfa405b0e4b96e290d440cecdae8691f077de
push id99942
push usernbeleuzu@mozilla.com
push dateFri, 16 Feb 2018 11:16:06 +0000
treeherdermozilla-inbound@8cf35a5cc077 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
f01d1def46fb / 60.0a1 / 20180216104033 / files
nightly linux64
f01d1def46fb / 60.0a1 / 20180216104033 / files
nightly mac
f01d1def46fb / 60.0a1 / 20180216104033 / files
nightly win32
f01d1def46fb / 60.0a1 / 20180216104033 / files
nightly win64
f01d1def46fb / 60.0a1 / 20180216104033 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/base/content/browser.xul
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1249,28 +1249,16 @@ var gBrowserInit = {
       remoteType, sameProcessAsFrameLoader
     });
 
     gUIDensity.init();
 
     if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
       gDragSpaceObserver.init();
     }
-
-    // Hack to ensure that the about:home favicon is loaded
-    // instantaneously, to avoid flickering and improve perceived performance.
-    this._callWithURIToLoad(uriToLoad => {
-      if (uriToLoad == "about:home") {
-        gBrowser.setIcon(gBrowser.selectedTab, "chrome://branding/content/icon32.png");
-      } else if (uriToLoad == "about:privatebrowsing") {
-        gBrowser.setIcon(gBrowser.selectedTab, "chrome://browser/skin/privatebrowsing/favicon.svg");
-      }
-    });
-
-    this._setInitialFocus();
   },
 
   onLoad() {
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver);
 
     Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
 
     window.addEventListener("AppCommand", HandleAppCommandEvent, true);
@@ -1361,16 +1349,28 @@ var gBrowserInit = {
 
       try {
         gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToOpen);
       } catch (e) {
         Cu.reportError(e);
       }
     }
 
+    this._setInitialFocus();
+
+    // Hack to ensure that the about:home favicon is loaded
+    // instantaneously, to avoid flickering and improve perceived performance.
+    this._uriToLoadPromise.then(uriToLoad => {
+      if (uriToLoad == "about:home") {
+        gBrowser.setIcon(gBrowser.selectedTab, "chrome://branding/content/icon32.png");
+      } else if (uriToLoad == "about:privatebrowsing") {
+        gBrowser.setIcon(gBrowser.selectedTab, "chrome://browser/skin/privatebrowsing/favicon.svg");
+      }
+    });
+
     // Wait until chrome is painted before executing code not critical to making the window visible
     this._boundDelayedStartup = this._delayedStartup.bind(this);
     window.addEventListener("MozAfterPaint", this._boundDelayedStartup);
 
     this._loadHandled = true;
   },
 
   _cancelDelayedStartup() {
@@ -1587,25 +1587,19 @@ var gBrowserInit = {
 
     let initialBrowser = gBrowser.selectedBrowser;
     mm.addMessageListener("Browser:FirstNonBlankPaint",
                           function onFirstNonBlankPaint() {
       mm.removeMessageListener("Browser:FirstNonBlankPaint", onFirstNonBlankPaint);
       initialBrowser.removeAttribute("blank");
     });
 
-    // To prevent flickering of the urlbar-history-dropmarker in the general
-    // case, the urlbar has the 'focused' attribute set by default.
-    // If we are not fully sure the urlbar will be focused in this window,
-    // we should remove the attribute before first paint.
-    let shouldRemoveFocusedAttribute = true;
-    this._callWithURIToLoad(uriToLoad => {
+    this._uriToLoadPromise.then(uriToLoad => {
       if ((isBlankPageURL(uriToLoad) || uriToLoad == "about:privatebrowsing") &&
           focusAndSelectUrlBar()) {
-        shouldRemoveFocusedAttribute = false;
         return;
       }
 
       if (gBrowser.selectedBrowser.isRemoteBrowser) {
         // If the initial browser is remote, in order to optimize for first paint,
         // we'll defer switching focus to that browser until it has painted.
         firstBrowserPaintDeferred.promise.then(() => {
           // If focus didn't move while we were waiting for first paint, we're okay
@@ -1615,22 +1609,20 @@ var gBrowserInit = {
           }
         });
       } else {
         // If the initial browser is not remote, we can focus the browser
         // immediately with no paint performance impact.
         gBrowser.selectedBrowser.focus();
       }
     });
-    if (shouldRemoveFocusedAttribute)
-      gURLBar.removeAttribute("focused");
   },
 
   _handleURIToLoad() {
-    this._callWithURIToLoad(uriToLoad => {
+    this._uriToLoadPromise.then(uriToLoad => {
       if (!uriToLoad || uriToLoad == "about:blank") {
         return;
       }
 
       // We don't check if uriToLoad is a XULElement because this case has
       // already been handled before first paint, and the argument cleared.
       if (uriToLoad instanceof Ci.nsIArray) {
         let count = uriToLoad.length;
@@ -1739,59 +1731,47 @@ var gBrowserInit = {
         ChromeUtils.import("resource:///modules/DownloadsTaskbar.jsm", {})
           .DownloadsTaskbar.registerIndicator(window);
       } catch (ex) {
         Cu.reportError(ex);
       }
     }, {timeout: 10000});
   },
 
-  // Returns the URI(s) to load at startup if it is immediately known, or a
-  // promise resolving to the URI to load.
+  // Returns the URI(s) to load at startup.
   get _uriToLoadPromise() {
     delete this._uriToLoadPromise;
-    return this._uriToLoadPromise = function() {
+    return this._uriToLoadPromise = new Promise(resolve => {
       // window.arguments[0]: URI to load (string), or an nsIArray of
       //                      nsISupportsStrings to load, or a xul:tab of
       //                      a tabbrowser, which will be replaced by this
       //                      window (for this case, all other arguments are
       //                      ignored).
       if (!window.arguments || !window.arguments[0]) {
-        return null;
+        resolve(null);
+        return;
       }
 
       let uri = window.arguments[0];
       let defaultArgs = Cc["@mozilla.org/browser/clh;1"]
                           .getService(Ci.nsIBrowserHandler)
                           .defaultArgs;
 
       // If the given URI is different from the homepage, we want to load it.
       if (uri != defaultArgs) {
-        return uri;
+        resolve(uri);
+        return;
       }
 
       // The URI appears to be the the homepage. We want to load it only if
       // session restore isn't about to override the homepage.
-      let willOverride = SessionStartup.willOverrideHomepage;
-      if (!(willOverride instanceof Promise)) {
-        return willOverride ? null : uri;
-      }
-      return willOverride.then(willOverrideHomepage =>
-                                 willOverrideHomepage ? null : uri);
-    }();
-  },
-
-  // Calls the given callback with the URI to load at startup.
-  // Synchronously if possible, or after _uriToLoadPromise resolves otherwise.
-  _callWithURIToLoad(callback) {
-    let uriToLoad = this._uriToLoadPromise;
-    if (uriToLoad instanceof Promise)
-      uriToLoad.then(callback);
-    else
-      callback(uriToLoad);
+      SessionStartup.willOverrideHomepagePromise.then(willOverrideHomepage => {
+        resolve(willOverrideHomepage ? null : uri);
+      });
+    });
   },
 
   onUnload() {
     gUIDensity.uninit();
 
     if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
       gDragSpaceObserver.uninit();
     }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -768,17 +768,16 @@
                        cui-areatype="toolbar"
                        aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
         <toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
         <toolbaritem id="urlbar-container" flex="400" persist="width"
                      removable="false"
                      class="chromeclass-location" overflows="false">
             <textbox id="urlbar" flex="1"
                      placeholder="&urlbar.placeholder2;"
-                     focused="true"
                      type="autocomplete"
                      autocompletesearch="unifiedcomplete"
                      autocompletesearchparam="enable-actions"
                      autocompletepopup="PopupAutoCompleteRichResult"
                      completeselectedindex="true"
                      shrinkdelay="250"
                      tabscrolling="true"
                      newlines="stripsurroundingwhitespace"
--- a/browser/base/content/test/performance/browser_startup_flicker.js
+++ b/browser/base/content/test/performance/browser_startup_flicker.js
@@ -31,22 +31,35 @@ add_task(async function() {
       alreadyFocused = true;
       // This is likely an issue caused by the test harness, but log it anyway.
       todo(false,
            "the window should be focused at first paint, " + rects.toSource());
       continue;
     }
 
     rects = rects.filter(rect => {
+      let inRange = (val, min, max) => min <= val && val <= max;
       let width = frame.width;
 
       let exceptions = [
-        /**
-         * Nothing here! Please don't add anything new!
-         */
+        {name: "bug 1403648 - urlbar down arrow shouldn't flicker",
+         condition: r => // 5x9px area, sometimes less at the end of the opacity transition
+                         inRange(r.h, 3, 5) && inRange(r.w, 7, 9) &&
+                         inRange(r.y1, 40, 80) && // in the toolbar
+                         // at ~80% of the window width
+                         inRange(r.x1, width * .75, width * .9)
+        },
+
+        {name: "bug 1403648 - urlbar should be focused at first paint",
+         condition: r => inRange(r.y2, 60, 80) && // in the toolbar
+                         // taking 50% to 75% of the window width
+                         inRange(r.w, width * .5, width * .75) &&
+                         // starting at 15 to 25% of the window width
+                         inRange(r.x1, width * .15, width * .25)
+        },
       ];
 
       let rectText = `${rect.toSource()}, window width: ${width}`;
       for (let e of exceptions) {
         if (e.condition(rect)) {
           todo(false, e.name + ", " + rectText);
           return false;
         }
--- a/browser/base/content/test/performance/browser_windowopen_flicker.js
+++ b/browser/base/content/test/performance/browser_windowopen_flicker.js
@@ -80,26 +80,54 @@ add_task(async function() {
       continue;
     }
 
     ignoreTinyPaint = false;
     let rects = compareFrames(frame, previousFrame).filter(rect => {
       let inRange = (val, min, max) => min <= val && val <= max;
       let width = frame.width;
 
+      const spaceBeforeFirstTab = AppConstants.platform == "macosx" ? 100 : 0;
+      let inFirstTab = r =>
+        inRange(r.x1, spaceBeforeFirstTab, spaceBeforeFirstTab + 50) && r.y1 < 30;
+
       let exceptions = [
+        {name: "bug 1403648 - urlbar down arrow shouldn't flicker",
+         condition: r => // 5x9px area, sometimes less at the end of the opacity transition
+                         inRange(r.h, 3, 5) && inRange(r.w, 7, 9) &&
+                         inRange(r.y1, 40, 80) && // in the toolbar
+                         // at ~80% of the window width
+                         inRange(r.x1, width * .75, width * .9)
+        },
+
+        {name: "bug 1403648 - urlbar should be focused at first paint",
+         condition: r => inRange(r.y2, 60, 80) && // in the toolbar
+                         // taking 50% to 75% of the window width
+                         inRange(r.w, width * .5, width * .75) &&
+                         // starting at 15 to 25% of the window width
+                         inRange(r.x1, width * .15, width * .25)
+        },
+
         {name: "bug 1421463 - reload toolbar icon shouldn't flicker",
          condition: r => r.h == 13 && inRange(r.w, 14, 16) && // icon size
                          inRange(r.y1, 40, 80) && // in the toolbar
                          // near the left side of the screen
                          // The reload icon is shifted on devedition builds
                          // where there's an additional devtools toolbar icon.
                          AppConstants.MOZ_DEV_EDITION ? inRange(r.x1, 100, 120) :
                                                         inRange(r.x1, 65, 100)
         },
+
+        {name: "bug 1401955 - about:home favicon should be visible at first paint",
+         condition: r => inFirstTab(r) && inRange(r.h, 14, 15) && inRange(r.w, 14, 15)
+        },
+
+        {name: "bug 1401955 - space for about:home favicon should be there at first paint",
+         condition: r => inFirstTab(r) && inRange(r.w, 60, 80) && inRange(r.h, 8, 15)
+        },
       ];
 
       let rectText = `${rect.toSource()}, window width: ${width}`;
       for (let e of exceptions) {
         if (e.condition(rect)) {
           todo(false, e.name + ", " + rectText);
           return false;
         }
--- a/browser/base/content/test/performance/browser_windowopen_reflows.js
+++ b/browser/base/content/test/performance/browser_windowopen_reflows.js
@@ -31,16 +31,22 @@ if (Services.appinfo.OS == "WINNT") {
     },
   );
 }
 
 if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
   EXPECTED_REFLOWS.push(
     {
       stack: [
+        "select@chrome://global/content/bindings/textbox.xml",
+        "focusAndSelectUrlBar@chrome://browser/content/browser.js",
+      ],
+    },
+    {
+      stack: [
         "rect@chrome://browser/content/browser-tabsintitlebar.js",
         "_update@chrome://browser/content/browser-tabsintitlebar.js",
         "init@chrome://browser/content/browser-tabsintitlebar.js",
         "handleEvent@chrome://browser/content/tabbrowser.xml",
       ],
       // These numbers should only ever go down - never up.
       times: Services.appinfo.OS == "WINNT" ? 5 : 4,
     },
--- a/browser/components/sessionstore/nsISessionStartup.idl
+++ b/browser/components/sessionstore/nsISessionStartup.idl
@@ -31,24 +31,23 @@ interface nsISessionStartup: nsISupports
   /**
    * Determines whether automatic session restoration is enabled for this
    * launch of the browser. This does not include crash restoration, and will
    * return false if restoration will only be caused by a crash.
    */
   boolean isAutomaticRestoreEnabled();
 
   /**
-   * Returns a boolean or a promise that resolves to a boolean, indicating
-   * whether we will restore a session that ends up replacing the homepage.
-   * True guarantees that we'll restore a session; false means that we
-   * /probably/ won't do so.
+   * Returns a promise that resolves to a boolean, indicating whether we will
+   * restore a session that ends up replacing the homepage. True guarantees
+   * that we'll restore a session; false means that we /probably/ won't do so.
    * The browser uses this to avoid unnecessarily loading the homepage when
    * restoring a session.
    */
-  readonly attribute jsval willOverrideHomepage;
+  readonly attribute jsval willOverrideHomepagePromise;
 
   /**
    * What type of session we're restoring.
    * NO_SESSION       There is no data available from the previous session
    * RECOVER_SESSION  The last session crashed. It will either be restored or
    *                  about:sessionrestore will be shown.
    * RESUME_SESSION   The previous session should be restored at startup
    * DEFER_SESSION    The previous session is fine, but it shouldn't be restored
--- a/browser/components/sessionstore/nsSessionStartup.js
+++ b/browser/components/sessionstore/nsSessionStartup.js
@@ -305,31 +305,30 @@ SessionStartup.prototype = {
    * @returns bool
    */
   _willRestore() {
     return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
            this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
   },
 
   /**
-   * Returns a boolean or a promise that resolves to a boolean, indicating
-   * whether we will restore a session that ends up replacing the homepage.
-   * True guarantees that we'll restore a session; false means that we
-   * /probably/ won't do so.
+   * Returns a promise that resolves to a boolean, indicating whether we will
+   * restore a session that ends up replacing the homepage. True guarantees
+   * that we'll restore a session; false means that we /probably/ won't do so.
    * The browser uses this to avoid unnecessarily loading the homepage when
    * restoring a session.
    */
-  get willOverrideHomepage() {
+  get willOverrideHomepagePromise() {
     // If the session file hasn't been read yet and resuming the session isn't
     // enabled via prefs, go ahead and load the homepage. We may still replace
     // it when recovering from a crash, which we'll only know after reading the
     // session file, but waiting for that would delay loading the homepage in
     // the non-crash case.
     if (!this._initialState && !this._resumeSessionEnabled) {
-      return false;
+      return Promise.resolve(false);
     }
 
     return new Promise(resolve => {
       this.onceInitialized.then(() => {
         // If there are valid windows with not only pinned tabs, signal that we
         // will override the default homepage by restoring a session.
         resolve(this._willRestore() &&
                 this._initialState &&