Bug 1528744 - Port browser_urlbar_search.js and browser_urlbar_keyed_search.js to QuantumBar. r=Standard8,mconley
☠☠ backed out by 1977f2af5469 ☠ ☠
authorDrew Willcoxon <adw@mozilla.com>
Thu, 28 Feb 2019 00:32:08 +0000
changeset 519449 71dd92230a54beb5037cf8ddef92b0f227653f93
parent 519448 20c54f8dd7fa7ad7390330856a1a7f666bbcbf12
child 519450 67213a91036c5830a6f830bc48ccb55c424d34ca
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, mconley
bugs1528744
milestone67.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 1528744 - Port browser_urlbar_search.js and browser_urlbar_keyed_search.js to QuantumBar. r=Standard8,mconley Differential Revision: https://phabricator.services.mozilla.com/D21242
browser/base/content/test/performance/browser.ini
browser/base/content/test/performance/browser_urlbar_keyed_search.js
browser/base/content/test/performance/browser_urlbar_keyed_search_legacy.js
browser/base/content/test/performance/browser_urlbar_search.js
browser/base/content/test/performance/browser_urlbar_search_legacy.js
browser/base/content/test/performance/head.js
browser/base/content/test/performance/legacyurlbar/browser.ini
browser/base/moz.build
--- a/browser/base/content/test/performance/browser.ini
+++ b/browser/base/content/test/performance/browser.ini
@@ -3,16 +3,17 @@
 # do almost nothing unless browser.startup.record is true.
 # gfx.canvas.willReadFrequently.enable is just an optimization, but needs to be
 # set during early startup to have an impact as a canvas will be used by
 # startupRecorder.js
 prefs =
   # Skip migration work in BG__migrateUI for browser_startup.js since it isn't
   # representative of common startup.
   browser.migration.version=9999999
+  browser.urlbar.quantumbar=true
   browser.startup.record=true
   gfx.canvas.willReadFrequently.enable=true
   # The form autofill framescript is only used in certain locales if this
   # pref is set to 'detect', which is the default value on non-Nightly.
   extensions.formautofill.available='on'
 support-files =
   head.js
 [browser_appmenu.js]
@@ -31,14 +32,12 @@ skip-if = (os == 'win' && bits == 32) # 
 [browser_tabopen.js]
 skip-if = (verify && (os == 'mac'))
 [browser_tabopen_squeeze.js]
 [browser_tabstrip_overflow_underflow.js]
 skip-if = (verify && !debug && (os == 'win')) || (!debug && (os == 'win') && (bits == 32)) # Bug 1502255
 [browser_tabswitch.js]
 [browser_toolbariconcolor_restyles.js]
 [browser_urlbar_keyed_search.js]
-skip-if = (os == 'linux') || (os == 'win' && debug) || (os == 'win' && bits == 32) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320. Disabled on Win32 because of intermittent OOM failures (bug 1448241).
 [browser_urlbar_search.js]
-skip-if = (debug || ccov) && (os == 'linux' || os == 'win') || (os == 'win' && bits == 32) # Disabled on Linux and Windows debug and ccov due to intermittent timeouts. Bug 1414126, bug 1426611. Disabled on Win32 because of intermittent OOM failures (bug 1448241)
 [browser_window_resize.js]
 [browser_windowclose.js]
 [browser_windowopen.js]
--- a/browser/base/content/test/performance/browser_urlbar_keyed_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_keyed_search.js
@@ -1,199 +1,53 @@
 "use strict";
 
-// There are a _lot_ of reflows in this test, and processing them takes
-// time. On slower builds, we need to boost our allowed test time.
-requestLongerTimeout(5);
+// This tests searching in the urlbar (a.k.a. the quantumbar).
 
 /**
  * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
  * is a whitelist that should slowly go away as we improve the performance of
  * the front-end. Instead of adding more reflows to the whitelist, you should
  * be modifying your code to avoid the reflow.
  *
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 
-/* These reflows happen only the first time the awesomebar panel opens. */
-const EXPECTED_REFLOWS_FIRST_OPEN = [];
-if (AppConstants.platform != "macosx" &&
-    (AppConstants.DEBUG ||
-     AppConstants.platform == "win")) {
-  EXPECTED_REFLOWS_FIRST_OPEN.push({
+/* These reflows happen only the first time the panel opens. */
+const EXPECTED_REFLOWS_FIRST_OPEN = [
+  // This is the this.panel.openPopup() call in UrlbarView._openPanel.  See bug
+  // 1359989, which was filed against the legacy awesomebar but applies here too
+  // because it seems to be caused by platform code.
+  {
+    stack: [
+      "_openPanel@resource:///modules/UrlbarView.jsm",
+      "onQueryResults@resource:///modules/UrlbarView.jsm",
+      "_notify@resource:///modules/UrlbarController.jsm",
+      "receiveResults@resource:///modules/UrlbarController.jsm",
+      "notifyResults@resource:///modules/UrlbarProvidersManager.jsm",
+      "add@resource:///modules/UrlbarProvidersManager.jsm",
+      "onSearchResult@resource:///modules/UrlbarProviderUnifiedComplete.jsm",
+    ],
+  },
+  {
     stack: [
       "__rebuild@chrome://browser/content/search/search-one-offs.js",
       /* This is limited to a one-line stack, because the next item is an async
          function and as such not supported on all trees, according to bug 1501761.
-      "async*set popup@chrome://browser/content/search/search-one-offs.js",
-      "_syncOneOffSearchesEnabled@chrome://browser/content/urlbarBindings.xml",
-      "toggleOneOffSearches@chrome://browser/content/urlbarBindings.xml",
-      "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
-      "@chrome://browser/content/urlbarBindings.xml",
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",*/
+      "async*_rebuild@chrome://browser/content/search/search-one-offs.js",
+      "async*_on_popupshowing@chrome://browser/content/search/search-one-offs.js",
+      "handleEvent@chrome://browser/content/search/search-one-offs.js",
+      "_openPanel@resource:///modules/UrlbarView.jsm",
+      "onQueryResults@resource:///modules/UrlbarView.jsm",
+      "_notify@resource:///modules/UrlbarController.jsm",
+      "receiveResults@resource:///modules/UrlbarController.jsm",
+      "notifyResults@resource:///modules/UrlbarProvidersManager.jsm",
+      "add@resource:///modules/UrlbarProvidersManager.jsm",
+      "onSearchResult@resource:///modules/UrlbarProviderUnifiedComplete.jsm",
+      */
     ],
-  });
-}
-EXPECTED_REFLOWS_FIRST_OPEN.push(
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
-      "_invalidate@chrome://global/content/bindings/autocomplete.xml",
-      "invalidate@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 60, // This number should only ever go down - never up.
-  },
-
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 6, // This number should only ever go down - never up.
   },
-
-  // Bug 1359989
-  {
-    stack: [
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
-    ],
-  }
-);
-
-// These extra reflows happen on beta/release as one of the default bookmarks in
-// bookmarks.html.in has a long URL.
-if (AppConstants.RELEASE_OR_BETA) {
-  EXPECTED_REFLOWS_FIRST_OPEN.push({
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_onUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "MozAutocompleteRichlistitem/<@chrome://global/content/elements/autocomplete-richlistitem.js",
-    ],
-    maxCount: 6,
-  },
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_onOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "MozAutocompleteRichlistitem/<@chrome://global/content/elements/autocomplete-richlistitem.js",
-    ],
-    maxCount: 6,
-  },
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_adjustAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
-      "_invalidate@chrome://global/content/bindings/autocomplete.xml",
-      "invalidate@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 12,
-  });
-}
+];
 
-/**
- * Returns a Promise that resolves once the AwesomeBar popup for a particular
- * window has appeared after having done a search for its input text.
- *
- * @param win (browser window)
- *        The window to do the search in.
- * @returns Promise
- */
-async function promiseSearchComplete(win) {
-  let URLBar = win.gURLBar;
-  if (URLBar.popup.state != "open") {
-    await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
-  }
-  await BrowserTestUtils.waitForCondition(() => {
-    return URLBar.controller.searchStatus >=
-      Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
-  });
-
-  // There are several setTimeout(fn, 0); calls inside autocomplete.xml
-  // that we need to wait for. Since those have higher priority than
-  // idle callbacks, we can be sure they will have run once this
-  // idle callback is called. The timeout seems to be required in
-  // automation - presumably because the machines can be pretty busy
-  // especially if it's GC'ing from previous tests.
-  await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
-}
-
-add_task(async function setup() {
-  await addDummyHistoryEntries();
+add_task(async function quantumbar() {
+  await runUrlbarTest(false, true, EXPECTED_REFLOWS_FIRST_OPEN);
 });
-
-/**
- * This test ensures that there are no unexpected uninterruptible reflows when
- * typing into the URL bar with the default values in Places.
- */
-add_task(async function() {
-  let win = await prepareSettledWindow();
-
-  let URLBar = win.gURLBar;
-  let popup = URLBar.popup;
-
-  URLBar.focus();
-  URLBar.value = "";
-
-  let dropmarkerRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "historydropmarker").getBoundingClientRect();
-  let textBoxRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "moz-input-box").getBoundingClientRect();
-
-  await withPerfObserver(async function() {
-    let oldInvalidate = popup.invalidate.bind(popup);
-    let oldResultsAdded = popup.onResultsAdded.bind(popup);
-
-    // We need to invalidate the frame tree outside of the normal
-    // mechanism since invalidations and result additions to the
-    // URL bar occur without firing JS events (which is how we
-    // normally know to dirty the frame tree).
-    popup.invalidate = (reason) => {
-      dirtyFrame(win);
-      oldInvalidate(reason);
-    };
-
-    popup.onResultsAdded = () => {
-      dirtyFrame(win);
-      oldResultsAdded();
-    };
-
-    // Only keying in 6 characters because the number of reflows triggered
-    // is so high that we risk timing out the test if we key in any more.
-    const SEARCH_TERM = "ows-10";
-    for (let i = 0; i < SEARCH_TERM.length; ++i) {
-      let char = SEARCH_TERM[i];
-      EventUtils.synthesizeKey(char, {}, win);
-      await promiseSearchComplete(win);
-    }
-
-    let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
-    await hiddenPromise;
-  }, {expectedReflows: EXPECTED_REFLOWS_FIRST_OPEN,
-      frames: {filter: rects => rects.filter(r => !(
-        // We put text into the urlbar so expect its textbox to change.
-        (r.x1 >= textBoxRect.left && r.x2 <= textBoxRect.right &&
-         r.y1 >= textBoxRect.top && r.y2 <= textBoxRect.bottom) ||
-        // The dropmarker is replaced with the go arrow during the test.
-        // dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
-        (r.x1 >= dropmarkerRect.left - 1 && r.x2 <= dropmarkerRect.right + 1 &&
-         r.y1 >= dropmarkerRect.top && r.y2 <= dropmarkerRect.bottom)
-        // XXX For some reason the awesomebar panel isn't in our screenshots,
-        // but that's where we actually expect many changes.
-      ))}}, win);
-
-  await BrowserTestUtils.closeWindow(win);
-});
copy from browser/base/content/test/performance/browser_urlbar_keyed_search.js
copy to browser/base/content/test/performance/browser_urlbar_keyed_search_legacy.js
--- a/browser/base/content/test/performance/browser_urlbar_keyed_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_keyed_search_legacy.js
@@ -1,10 +1,13 @@
 "use strict";
 
+// This tests searching in the legacy urlbar implementation (a.k.a. the
+// awesomebar).
+
 // There are a _lot_ of reflows in this test, and processing them takes
 // time. On slower builds, we need to boost our allowed test time.
 requestLongerTimeout(5);
 
 /**
  * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
  * is a whitelist that should slowly go away as we improve the performance of
  * the front-end. Instead of adding more reflows to the whitelist, you should
@@ -98,102 +101,11 @@ if (AppConstants.RELEASE_OR_BETA) {
       "_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
       "_invalidate@chrome://global/content/bindings/autocomplete.xml",
       "invalidate@chrome://global/content/bindings/autocomplete.xml",
     ],
     maxCount: 12,
   });
 }
 
-/**
- * Returns a Promise that resolves once the AwesomeBar popup for a particular
- * window has appeared after having done a search for its input text.
- *
- * @param win (browser window)
- *        The window to do the search in.
- * @returns Promise
- */
-async function promiseSearchComplete(win) {
-  let URLBar = win.gURLBar;
-  if (URLBar.popup.state != "open") {
-    await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
-  }
-  await BrowserTestUtils.waitForCondition(() => {
-    return URLBar.controller.searchStatus >=
-      Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
-  });
-
-  // There are several setTimeout(fn, 0); calls inside autocomplete.xml
-  // that we need to wait for. Since those have higher priority than
-  // idle callbacks, we can be sure they will have run once this
-  // idle callback is called. The timeout seems to be required in
-  // automation - presumably because the machines can be pretty busy
-  // especially if it's GC'ing from previous tests.
-  await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
-}
-
-add_task(async function setup() {
-  await addDummyHistoryEntries();
+add_task(async function awesomebar() {
+  await runUrlbarTest(true, true, EXPECTED_REFLOWS_FIRST_OPEN);
 });
-
-/**
- * This test ensures that there are no unexpected uninterruptible reflows when
- * typing into the URL bar with the default values in Places.
- */
-add_task(async function() {
-  let win = await prepareSettledWindow();
-
-  let URLBar = win.gURLBar;
-  let popup = URLBar.popup;
-
-  URLBar.focus();
-  URLBar.value = "";
-
-  let dropmarkerRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "historydropmarker").getBoundingClientRect();
-  let textBoxRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "moz-input-box").getBoundingClientRect();
-
-  await withPerfObserver(async function() {
-    let oldInvalidate = popup.invalidate.bind(popup);
-    let oldResultsAdded = popup.onResultsAdded.bind(popup);
-
-    // We need to invalidate the frame tree outside of the normal
-    // mechanism since invalidations and result additions to the
-    // URL bar occur without firing JS events (which is how we
-    // normally know to dirty the frame tree).
-    popup.invalidate = (reason) => {
-      dirtyFrame(win);
-      oldInvalidate(reason);
-    };
-
-    popup.onResultsAdded = () => {
-      dirtyFrame(win);
-      oldResultsAdded();
-    };
-
-    // Only keying in 6 characters because the number of reflows triggered
-    // is so high that we risk timing out the test if we key in any more.
-    const SEARCH_TERM = "ows-10";
-    for (let i = 0; i < SEARCH_TERM.length; ++i) {
-      let char = SEARCH_TERM[i];
-      EventUtils.synthesizeKey(char, {}, win);
-      await promiseSearchComplete(win);
-    }
-
-    let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
-    await hiddenPromise;
-  }, {expectedReflows: EXPECTED_REFLOWS_FIRST_OPEN,
-      frames: {filter: rects => rects.filter(r => !(
-        // We put text into the urlbar so expect its textbox to change.
-        (r.x1 >= textBoxRect.left && r.x2 <= textBoxRect.right &&
-         r.y1 >= textBoxRect.top && r.y2 <= textBoxRect.bottom) ||
-        // The dropmarker is replaced with the go arrow during the test.
-        // dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
-        (r.x1 >= dropmarkerRect.left - 1 && r.x2 <= dropmarkerRect.right + 1 &&
-         r.y1 >= dropmarkerRect.top && r.y2 <= dropmarkerRect.bottom)
-        // XXX For some reason the awesomebar panel isn't in our screenshots,
-        // but that's where we actually expect many changes.
-      ))}}, win);
-
-  await BrowserTestUtils.closeWindow(win);
-});
--- a/browser/base/content/test/performance/browser_urlbar_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_search.js
@@ -1,198 +1,69 @@
 "use strict";
 
-// There are a _lot_ of reflows in this test, and processing them takes
-// time. On slower builds, we need to boost our allowed test time.
-requestLongerTimeout(5);
+// This tests searching in the urlbar (a.k.a. the quantumbar).
 
 /**
  * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
  * is a whitelist that should slowly go away as we improve the performance of
  * the front-end. Instead of adding more reflows to the whitelist, you should
  * be modifying your code to avoid the reflow.
  *
  * See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
  * for tips on how to do that.
  */
 
-/* These reflows happen only the first time the awesomebar panel opens. */
-const EXPECTED_REFLOWS_FIRST_OPEN = [];
-if (AppConstants.platform != "macosx" &&
-    (AppConstants.DEBUG ||
-     AppConstants.platform == "linux" ||
-     AppConstants.isPlatformAndVersionAtLeast("win", "10"))) {
-  EXPECTED_REFLOWS_FIRST_OPEN.push({
+/* These reflows happen only the first time the panel opens. */
+const EXPECTED_REFLOWS_FIRST_OPEN = [
+  {
+    stack: [
+      "_openPanel@resource:///modules/UrlbarView.jsm",
+      "onQueryResults@resource:///modules/UrlbarView.jsm",
+      "_notify@resource:///modules/UrlbarController.jsm",
+      "receiveResults@resource:///modules/UrlbarController.jsm",
+      "notifyResults@resource:///modules/UrlbarProvidersManager.jsm",
+      "add@resource:///modules/UrlbarProvidersManager.jsm",
+      "onSearchResult@resource:///modules/UrlbarProviderUnifiedComplete.jsm",
+    ],
+  },
+  {
     stack: [
       "__rebuild@chrome://browser/content/search/search-one-offs.js",
       /* This is limited to a one-line stack, because the next item is an async
          function and as such not supported on all trees, according to bug 1501761.
-      "async*set popup@chrome://browser/content/search/search-one-offs.js",
-      "_syncOneOffSearchesEnabled@chrome://browser/content/urlbarBindings.xml",
-      "toggleOneOffSearches@chrome://browser/content/urlbarBindings.xml",
-      "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml",
-      "@chrome://browser/content/urlbarBindings.xml",
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",*/
-    ],
-  });
-}
-EXPECTED_REFLOWS_FIRST_OPEN.push(
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
-      "_invalidate@chrome://global/content/bindings/autocomplete.xml",
-      "invalidate@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 36, // This number should only ever go down - never up.
-  },
-
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 6, // This number should only ever go down - never up.
-  },
-
-  // Bug 1359989
-  {
-    stack: [
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
-    ],
-  }
-);
-
-/* These reflows happen everytime the awesomebar panel opens. */
-const EXPECTED_REFLOWS_SECOND_OPEN = [
-  {
-    stack: [
-      "_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
-      "_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
-      "_invalidate@chrome://global/content/bindings/autocomplete.xml",
-      "invalidate@chrome://global/content/bindings/autocomplete.xml",
-    ],
-    maxCount: 24, // This number should only ever go down - never up.
-  },
-
-  // Bug 1359989
-  {
-    stack: [
-      "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
-      "openPopup@chrome://global/content/bindings/autocomplete.xml",
-      "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
+      "async*_rebuild@chrome://browser/content/search/search-one-offs.js",
+      "async*_on_popupshowing@chrome://browser/content/search/search-one-offs.js",
+      "handleEvent@chrome://browser/content/search/search-one-offs.js",
+      "_openPanel@resource:///modules/UrlbarView.jsm",
+      "onQueryResults@resource:///modules/UrlbarView.jsm",
+      "_notify@resource:///modules/UrlbarController.jsm",
+      "receiveResults@resource:///modules/UrlbarController.jsm",
+      "notifyResults@resource:///modules/UrlbarProvidersManager.jsm",
+      "add@resource:///modules/UrlbarProvidersManager.jsm",
+      "onSearchResult@resource:///modules/UrlbarProviderUnifiedComplete.jsm",
+      */
     ],
   },
 ];
 
-const SEARCH_TERM = "urlbar-reflows-" + Date.now();
-
-add_task(async function setup() {
-  await addDummyHistoryEntries(SEARCH_TERM);
-});
-
-/**
- * This test ensures that there are no unexpected
- * uninterruptible reflows when typing into the URL bar
- * with the default values in Places.
- */
-add_task(async function() {
-  let win = await prepareSettledWindow();
-
-  let URLBar = win.gURLBar;
-  let popup = URLBar.popup;
-
-  URLBar.focus();
-  URLBar.value = SEARCH_TERM;
-  let testFn = async function() {
-    let oldInvalidate = popup.invalidate.bind(popup);
-    let oldResultsAdded = popup.onResultsAdded.bind(popup);
-    let oldSetTimeout = win.setTimeout;
-
-    // We need to invalidate the frame tree outside of the normal
-    // mechanism since invalidations and result additions to the
-    // URL bar occur without firing JS events (which is how we
-    // normally know to dirty the frame tree).
-    popup.invalidate = (reason) => {
-      dirtyFrame(win);
-      oldInvalidate(reason);
-    };
-
-    popup.onResultsAdded = () => {
-      dirtyFrame(win);
-      oldResultsAdded();
-    };
-
-    win.setTimeout = (fn, ms) => {
-      return oldSetTimeout(() => {
-        dirtyFrame(win);
-        fn();
-      }, ms);
-    };
+/* These reflows happen every time the panel opens. */
+const EXPECTED_REFLOWS_SECOND_OPEN = [
+  // This is the this.panel.openPopup() call in UrlbarView._openPanel.  See bug
+  // 1359989, which was filed against the legacy awesomebar but applies here too
+  // because it seems to be caused by platform code.
+  {
+    stack: [
+      "_openPanel@resource:///modules/UrlbarView.jsm",
+      "onQueryResults@resource:///modules/UrlbarView.jsm",
+      "_notify@resource:///modules/UrlbarController.jsm",
+      "receiveResults@resource:///modules/UrlbarController.jsm",
+      "notifyResults@resource:///modules/UrlbarProvidersManager.jsm",
+      "add@resource:///modules/UrlbarProvidersManager.jsm",
+      "onSearchResult@resource:///modules/UrlbarProviderUnifiedComplete.jsm",
+    ],
+  },
+];
 
-    URLBar.controller.startSearch(URLBar.value);
-    await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
-    await BrowserTestUtils.waitForCondition(() => {
-      return URLBar.controller.searchStatus >=
-        Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
-    });
-    let matchCount = URLBar.popup.matchCount;
-    await BrowserTestUtils.waitForCondition(() => {
-      return URLBar.popup.richlistbox.children.length == matchCount;
-    });
-
-    URLBar.controller.stopSearch();
-    // There are several setTimeout(fn, 0); calls inside autocomplete.xml
-    // that we need to wait for. Since those have higher priority than
-    // idle callbacks, we can be sure they will have run once this
-    // idle callback is called. The timeout seems to be required in
-    // automation - presumably because the machines can be pretty busy
-    // especially if it's GC'ing from previous tests.
-    await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
-
-    let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
-    await hiddenPromise;
-  };
-
-  let dropmarkerRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "historydropmarker").getBoundingClientRect();
-  let textBoxRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "moz-input-box").getBoundingClientRect();
-  let expectedRects = {
-    filter: rects => rects.filter(r => !(
-      // We put text into the urlbar so expect its textbox to change.
-      (r.x1 >= textBoxRect.left && r.x2 <= textBoxRect.right &&
-       r.y1 >= textBoxRect.top && r.y2 <= textBoxRect.bottom) ||
-      // The dropmarker is displayed as active during some of the test.
-      // dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
-      (r.x1 >= dropmarkerRect.left - 1 && r.x2 <= dropmarkerRect.right + 1 &&
-       r.y1 >= dropmarkerRect.top && r.y2 <= dropmarkerRect.bottom)
-      // XXX For some reason the awesomebar panel isn't in our screenshots,
-      // but that's where we actually expect many changes.
-    )),
-  };
-
-  info("First opening");
-  await withPerfObserver(testFn, {expectedReflows: EXPECTED_REFLOWS_FIRST_OPEN,
-                                  frames: expectedRects}, win);
-
-  info("Second opening");
-  await withPerfObserver(testFn, {expectedReflows: EXPECTED_REFLOWS_SECOND_OPEN,
-                                  frames: expectedRects}, win);
-
-  await BrowserTestUtils.closeWindow(win);
+add_task(async function quantumbar() {
+  await runUrlbarTest(false, false, EXPECTED_REFLOWS_FIRST_OPEN,
+                      EXPECTED_REFLOWS_SECOND_OPEN);
 });
copy from browser/base/content/test/performance/browser_urlbar_search.js
copy to browser/base/content/test/performance/browser_urlbar_search_legacy.js
--- a/browser/base/content/test/performance/browser_urlbar_search.js
+++ b/browser/base/content/test/performance/browser_urlbar_search_legacy.js
@@ -1,10 +1,13 @@
 "use strict";
 
+// This tests searching in the legacy urlbar implementation (a.k.a. the
+// awesomebar).
+
 // There are a _lot_ of reflows in this test, and processing them takes
 // time. On slower builds, we need to boost our allowed test time.
 requestLongerTimeout(5);
 
 /**
  * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
  * is a whitelist that should slowly go away as we improve the performance of
  * the front-end. Instead of adding more reflows to the whitelist, you should
@@ -93,106 +96,12 @@ const EXPECTED_REFLOWS_SECOND_OPEN = [
       "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
       "openPopup@chrome://global/content/bindings/autocomplete.xml",
       "set_popupOpen@chrome://global/content/bindings/autocomplete.xml",
     ],
   },
 ];
 
-const SEARCH_TERM = "urlbar-reflows-" + Date.now();
-
-add_task(async function setup() {
-  await addDummyHistoryEntries(SEARCH_TERM);
+add_task(async function awesomebar() {
+  await runUrlbarTest(true, false, EXPECTED_REFLOWS_FIRST_OPEN,
+                      EXPECTED_REFLOWS_SECOND_OPEN);
 });
-
-/**
- * This test ensures that there are no unexpected
- * uninterruptible reflows when typing into the URL bar
- * with the default values in Places.
- */
-add_task(async function() {
-  let win = await prepareSettledWindow();
-
-  let URLBar = win.gURLBar;
-  let popup = URLBar.popup;
-
-  URLBar.focus();
-  URLBar.value = SEARCH_TERM;
-  let testFn = async function() {
-    let oldInvalidate = popup.invalidate.bind(popup);
-    let oldResultsAdded = popup.onResultsAdded.bind(popup);
-    let oldSetTimeout = win.setTimeout;
-
-    // We need to invalidate the frame tree outside of the normal
-    // mechanism since invalidations and result additions to the
-    // URL bar occur without firing JS events (which is how we
-    // normally know to dirty the frame tree).
-    popup.invalidate = (reason) => {
-      dirtyFrame(win);
-      oldInvalidate(reason);
-    };
-
-    popup.onResultsAdded = () => {
-      dirtyFrame(win);
-      oldResultsAdded();
-    };
-
-    win.setTimeout = (fn, ms) => {
-      return oldSetTimeout(() => {
-        dirtyFrame(win);
-        fn();
-      }, ms);
-    };
-
-    URLBar.controller.startSearch(URLBar.value);
-    await BrowserTestUtils.waitForEvent(URLBar.popup, "popupshown");
-    await BrowserTestUtils.waitForCondition(() => {
-      return URLBar.controller.searchStatus >=
-        Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH;
-    });
-    let matchCount = URLBar.popup.matchCount;
-    await BrowserTestUtils.waitForCondition(() => {
-      return URLBar.popup.richlistbox.children.length == matchCount;
-    });
-
-    URLBar.controller.stopSearch();
-    // There are several setTimeout(fn, 0); calls inside autocomplete.xml
-    // that we need to wait for. Since those have higher priority than
-    // idle callbacks, we can be sure they will have run once this
-    // idle callback is called. The timeout seems to be required in
-    // automation - presumably because the machines can be pretty busy
-    // especially if it's GC'ing from previous tests.
-    await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
-
-    let hiddenPromise = BrowserTestUtils.waitForEvent(URLBar.popup, "popuphidden");
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
-    await hiddenPromise;
-  };
-
-  let dropmarkerRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "historydropmarker").getBoundingClientRect();
-  let textBoxRect = document.getAnonymousElementByAttribute(gURLBar,
-    "anonid", "moz-input-box").getBoundingClientRect();
-  let expectedRects = {
-    filter: rects => rects.filter(r => !(
-      // We put text into the urlbar so expect its textbox to change.
-      (r.x1 >= textBoxRect.left && r.x2 <= textBoxRect.right &&
-       r.y1 >= textBoxRect.top && r.y2 <= textBoxRect.bottom) ||
-      // The dropmarker is displayed as active during some of the test.
-      // dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
-      (r.x1 >= dropmarkerRect.left - 1 && r.x2 <= dropmarkerRect.right + 1 &&
-       r.y1 >= dropmarkerRect.top && r.y2 <= dropmarkerRect.bottom)
-      // XXX For some reason the awesomebar panel isn't in our screenshots,
-      // but that's where we actually expect many changes.
-    )),
-  };
-
-  info("First opening");
-  await withPerfObserver(testFn, {expectedReflows: EXPECTED_REFLOWS_FIRST_OPEN,
-                                  frames: expectedRects}, win);
-
-  info("Second opening");
-  await withPerfObserver(testFn, {expectedReflows: EXPECTED_REFLOWS_SECOND_OPEN,
-                                  frames: expectedRects}, win);
-
-  await BrowserTestUtils.closeWindow(win);
-});
--- a/browser/base/content/test/performance/head.js
+++ b/browser/base/content/test/performance/head.js
@@ -1,15 +1,15 @@
 "use strict";
 
-ChromeUtils.defineModuleGetter(this, "PlacesUtils",
-  "resource://gre/modules/PlacesUtils.jsm");
-ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
-  "resource://testing-common/PlacesTestUtils.jsm");
-
+XPCOMUtils.defineLazyModuleGetters(this, {
+  PlacesTestUtils: "resource://testing-common/PlacesTestUtils.jsm",
+  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
+  UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.jsm",
+});
 
 /**
  * This function can be called if the test needs to trigger frame dirtying
  * outside of the normal mechanism.
  *
  * @param win (dom window)
  *        The window in which the frame tree needs to be marked as dirty.
  */
@@ -634,8 +634,126 @@ async function withPerfObserver(testFn, 
   await promiseTestDone;
 
   let reflows = await promiseReflows;
   reportUnexpectedReflows(reflows, exceptions.expectedReflows);
 
   let frames = await promiseFrames;
   reportUnexpectedFlicker(frames, exceptions.frames);
 }
+
+/**
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when typing into the URL bar
+ * with the default values in Places.
+ *
+ * @param {bool} useAwesomebar
+ *        Pass true if the legacy awesomebar is enabled.  Pass false if the
+ *        quantumbar is enabled.
+ * @param {bool} keyed
+ *        Pass true to synthesize typing the search string one key at a time.
+ * @param {array} expectedReflowsFirstOpen
+ *        The array of expected reflow stacks when the panel is first opened.
+ * @param {array} [expectedReflowsSecondOpen]
+ *        The array of expected reflow stacks when the panel is subsequently
+ *        opened, if you're testing opening the panel twice.
+ */
+async function runUrlbarTest(useAwesomebar,
+                             keyed,
+                             expectedReflowsFirstOpen,
+                             expectedReflowsSecondOpen = null) {
+  const SEARCH_TERM = keyed ? "" : "urlbar-reflows-" + Date.now();
+  await addDummyHistoryEntries(SEARCH_TERM);
+
+  let win = await prepareSettledWindow();
+
+  let URLBar = win.gURLBar;
+
+  URLBar.focus();
+  URLBar.value = SEARCH_TERM;
+  let testFn = async function() {
+    if (useAwesomebar) {
+      let popup = URLBar.popup;
+      let oldInvalidate = popup.invalidate.bind(popup);
+      let oldResultsAdded = popup.onResultsAdded.bind(popup);
+      let oldSetTimeout = win.setTimeout;
+
+      // We need to invalidate the frame tree outside of the normal
+      // mechanism since invalidations and result additions to the
+      // URL bar occur without firing JS events (which is how we
+      // normally know to dirty the frame tree).
+      popup.invalidate = (reason) => {
+        dirtyFrame(win);
+        oldInvalidate(reason);
+      };
+
+      popup.onResultsAdded = () => {
+        dirtyFrame(win);
+        oldResultsAdded();
+      };
+
+      win.setTimeout = (fn, ms) => {
+        return oldSetTimeout(() => {
+          dirtyFrame(win);
+          fn();
+        }, ms);
+      };
+    }
+
+    let waitExtra = async () => {
+      // There are several setTimeout(fn, 0); calls inside autocomplete.xml
+      // that we need to wait for. Since those have higher priority than
+      // idle callbacks, we can be sure they will have run once this
+      // idle callback is called. The timeout seems to be required in
+      // automation - presumably because the machines can be pretty busy
+      // especially if it's GC'ing from previous tests.
+      await new Promise(resolve => win.requestIdleCallback(resolve, { timeout: 1000 }));
+    };
+
+    if (keyed) {
+      // Only keying in 6 characters because the number of reflows triggered
+      // is so high that we risk timing out the test if we key in any more.
+      let searchTerm = "ows-10";
+      for (let i = 0; i < searchTerm.length; ++i) {
+        let char = searchTerm[i];
+        EventUtils.synthesizeKey(char, {}, win);
+        await UrlbarTestUtils.promiseSearchComplete(win);
+        await waitExtra();
+      }
+    } else {
+      await UrlbarTestUtils.promiseAutocompleteResultPopup(win, URLBar.value,
+                                                           SimpleTest.waitForFocus);
+      await waitExtra();
+    }
+
+    await UrlbarTestUtils.promisePopupClose(win);
+  };
+
+  let dropmarkerRect = win.document.getAnonymousElementByAttribute(URLBar.textbox,
+    "anonid", "historydropmarker").getBoundingClientRect();
+  let textBoxRect = win.document.getAnonymousElementByAttribute(URLBar.textbox,
+    "anonid", "moz-input-box").getBoundingClientRect();
+  let expectedRects = {
+    filter: rects => rects.filter(r => !(
+      // We put text into the urlbar so expect its textbox to change.
+      (r.x1 >= textBoxRect.left && r.x2 <= textBoxRect.right &&
+       r.y1 >= textBoxRect.top && r.y2 <= textBoxRect.bottom) ||
+      // The dropmarker is displayed as active during some of the test.
+      // dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
+      (r.x1 >= dropmarkerRect.left - 1 && r.x2 <= dropmarkerRect.right + 1 &&
+       r.y1 >= dropmarkerRect.top && r.y2 <= dropmarkerRect.bottom)
+      // XXX For some reason the awesomebar panel isn't in our screenshots,
+      // but that's where we actually expect many changes.
+    )),
+  };
+
+  info(`First opening, useAwesomebar=${useAwesomebar}`);
+  await withPerfObserver(testFn, {expectedReflows: expectedReflowsFirstOpen,
+                                  frames: expectedRects}, win);
+
+  if (expectedReflowsSecondOpen) {
+    info(`Second opening, useAwesomebar=${useAwesomebar}`);
+    await withPerfObserver(testFn, {expectedReflows: expectedReflowsSecondOpen,
+                                    frames: expectedRects}, win);
+  }
+
+  await BrowserTestUtils.closeWindow(win);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/performance/legacyurlbar/browser.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+prefs =
+  browser.urlbar.quantumbar=false
+
+[../browser_urlbar_keyed_search_legacy.js]
+skip-if = (os == 'linux') || (os == 'win' && debug) || (os == 'win' && bits == 32) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320. Disabled on Win32 because of intermittent OOM failures (bug 1448241).
+[../browser_urlbar_search_legacy.js]
+skip-if = (debug || ccov) && (os == 'linux' || os == 'win') || (os == 'win' && bits == 32) # Disabled on Linux and Windows debug and ccov due to intermittent timeouts. Bug 1414126, bug 1426611. Disabled on Win32 because of intermittent OOM failures (bug 1448241)
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -31,16 +31,17 @@ BROWSER_CHROME_MANIFESTS += [
     'content/test/general/browser.ini',
     'content/test/historySwipeAnimation/browser.ini',
     'content/test/keyboard/browser.ini',
     'content/test/metaTags/browser.ini',
     'content/test/pageActions/browser.ini',
     'content/test/pageinfo/browser.ini',
     'content/test/performance/browser.ini',
     'content/test/performance/hidpi/browser.ini',
+    'content/test/performance/legacyurlbar/browser.ini',
     'content/test/performance/lowdpi/browser.ini',
     'content/test/permissions/browser.ini',
     'content/test/plugins/browser.ini',
     'content/test/popupNotifications/browser.ini',
     'content/test/popups/browser.ini',
     'content/test/referrer/browser.ini',
     'content/test/sanitize/browser.ini',
     'content/test/sidebar/browser.ini',