Bug 1578583 - Add support for a resultSpan property on results. r=adw
authorharry <htwyford@mozilla.com>
Wed, 18 Sep 2019 15:18:55 +0000
changeset 493841 96fecf5a0833f92b546f54435b4e7e538c132719
parent 493840 a632aaff50eb0195bcc59f3b814e739d4b97e4a1
child 493842 2b4d285d8caa26da661d3100c9f9db8a19ea3dc7
push id95712
push userhtwyford@mozilla.com
push dateWed, 18 Sep 2019 15:20:31 +0000
treeherderautoland@96fecf5a0833 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw
bugs1578583
milestone71.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 1578583 - Add support for a resultSpan property on results. r=adw Differential Revision: https://phabricator.services.mozilla.com/D46220
browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm
browser/components/urlbar/UrlbarUtils.jsm
browser/components/urlbar/tests/browser/browser.ini
browser/components/urlbar/tests/browser/browser_urlbar_resultSpan.js
--- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm
+++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm
@@ -82,20 +82,22 @@ class MuxerUnifiedComplete extends Urlba
         // Handle the heuristic result.
         if (
           group == UrlbarUtils.RESULT_GROUP.HEURISTIC &&
           match == heuristicMatch &&
           context.preselected
         ) {
           sortedMatches.unshift(match);
           handled.add(match);
+          context.maxResults -= UrlbarUtils.getSpanForResult(match) - 1;
           count--;
         } else if (group == RESULT_TYPE_TO_GROUP.get(match.type)) {
           sortedMatches.push(match);
           handled.add(match);
+          context.maxResults -= UrlbarUtils.getSpanForResult(match) - 1;
           count--;
         } else if (!RESULT_TYPE_TO_GROUP.has(match.type)) {
           let errorMsg = `Result type ${
             match.type
           } is not mapped to a match group.`;
           logger.error(errorMsg);
           Cu.reportError(errorMsg);
         }
--- a/browser/components/urlbar/UrlbarUtils.jsm
+++ b/browser/components/urlbar/UrlbarUtils.jsm
@@ -368,16 +368,40 @@ var UrlbarUtils = {
    *    post data (object).
    */
   getSearchQueryUrl(engine, query) {
     let submission = engine.getSubmission(query, null, "keyword");
     return [submission.uri.spec, submission.postData];
   },
 
   /**
+   * Get the number of rows a result should span in the autocomplete dropdown.
+   *
+   * @param {UrlbarResult} result The result being created.
+   * @returns {number}
+   *          The number of rows the result should span in the autocomplete
+   *          dropdown.
+   */
+  getSpanForResult(result) {
+    switch (result.type) {
+      case UrlbarUtils.RESULT_TYPE.URL:
+      case UrlbarUtils.RESULT_TYPE.BOOKMARKS:
+      case UrlbarUtils.RESULT_TYPE.REMOTE_TAB:
+      case UrlbarUtils.RESULT_TYPE.TAB_SWITCH:
+      case UrlbarUtils.RESULT_TYPE.KEYWORD:
+      case UrlbarUtils.RESULT_TYPE.SEARCH:
+      case UrlbarUtils.RESULT_TYPE.OMNIBOX:
+        return 1;
+      case UrlbarUtils.RESULT_TYPE.TIP:
+        return 3;
+    }
+    return 1;
+  },
+
+  /**
    * Tries to initiate a speculative connection to a given url.
    * @param {nsISearchEngine|nsIURI|URL|string} urlOrEngine entity to initiate
    *        a speculative connection for.
    * @param {window} window the window from where the connection is initialized.
    * @note This is not infallible, if a speculative connection cannot be
    *       initialized, it will be a no-op.
    */
   setupSpeculativeConnection(urlOrEngine, window) {
--- a/browser/components/urlbar/tests/browser/browser.ini
+++ b/browser/components/urlbar/tests/browser/browser.ini
@@ -127,16 +127,17 @@ support-files =
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
 [browser_urlbar_locationchange_urlbar_edit_dos.js]
 support-files =
   file_urlbar_edit_dos.html
 [browser_urlbar_remoteness_switch.js]
 run-if = e10s
 [browser_urlbar_remove_match.js]
+[browser_urlbar_resultSpan.js]
 [browser_urlbar_searchsettings.js]
 [browser_urlbar_selection.js]
 skip-if = (os == 'mac') # bug 1570474
 [browser_urlbar_speculative_connect.js]
 support-files =
   searchSuggestionEngine2.xml
   searchSuggestionEngine.sjs
 [browser_urlbar_speculative_connect_not_with_client_cert.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/urlbar/tests/browser/browser_urlbar_resultSpan.js
@@ -0,0 +1,129 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  UrlbarProvider: "resource:///modules/UrlbarUtils.jsm",
+  UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.jsm",
+  UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
+});
+
+// Tests that displaying results with resultSpan > 1 limits other results in
+// the view.
+add_task(async function oneTip() {
+  let tipMatches = Array.from(matches);
+  for (let i = 2; i < 15; i++) {
+    tipMatches.push(
+      new UrlbarResult(
+        UrlbarUtils.RESULT_TYPE.URL,
+        UrlbarUtils.RESULT_SOURCE.HISTORY,
+        { url: `http://mozilla.org/${i}` }
+      )
+    );
+  }
+
+  let provider = new TipTestProvider(tipMatches);
+  UrlbarProvidersManager.registerProvider(provider);
+
+  gURLBar.search("test");
+  await promiseSearchComplete();
+
+  Assert.equal(
+    UrlbarTestUtils.getResultCount(window),
+    8,
+    "There should be 8 results in the view."
+  );
+
+  UrlbarProvidersManager.unregisterProvider(provider);
+  gURLBar.view.close();
+});
+
+add_task(async function threeTips() {
+  let tipMatches = Array.from(matches);
+  for (let i = 1; i < 3; i++) {
+    tipMatches.push(
+      new UrlbarResult(
+        UrlbarUtils.RESULT_TYPE.TIP,
+        UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
+        {
+          text: "This is a test intervention.",
+          buttonText: "Done",
+          data: "test",
+          helpUrl: `about:about#${i}`,
+        }
+      )
+    );
+  }
+  for (let i = 2; i < 15; i++) {
+    tipMatches.push(
+      new UrlbarResult(
+        UrlbarUtils.RESULT_TYPE.URL,
+        UrlbarUtils.RESULT_SOURCE.HISTORY,
+        { url: `http://mozilla.org/${i}` }
+      )
+    );
+  }
+
+  let provider = new TipTestProvider(tipMatches);
+  UrlbarProvidersManager.registerProvider(provider);
+
+  gURLBar.search("test");
+  await promiseSearchComplete();
+  Assert.equal(
+    UrlbarTestUtils.getResultCount(window),
+    4,
+    "There should be 4 results in the view."
+  );
+
+  UrlbarProvidersManager.unregisterProvider(provider);
+  gURLBar.view.close();
+});
+
+/**
+ * A test provider.
+ */
+class TipTestProvider extends UrlbarProvider {
+  constructor(matches) {
+    super();
+    this._matches = matches;
+  }
+  get name() {
+    return "TipTestProvider";
+  }
+  get type() {
+    return UrlbarUtils.PROVIDER_TYPE.PROFILE;
+  }
+  isActive(context) {
+    return true;
+  }
+  isRestricting(context) {
+    return true;
+  }
+  async startQuery(context, addCallback) {
+    Assert.ok(true, "Tip provider was invoked");
+    this._context = context;
+    for (const match of this._matches) {
+      addCallback(this, match);
+    }
+  }
+  cancelQuery(context) {}
+}
+
+const matches = [
+  new UrlbarResult(
+    UrlbarUtils.RESULT_TYPE.URL,
+    UrlbarUtils.RESULT_SOURCE.HISTORY,
+    { url: "http://mozilla.org/1" }
+  ),
+  new UrlbarResult(
+    UrlbarUtils.RESULT_TYPE.TIP,
+    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
+    {
+      text: "This is a test intervention.",
+      buttonText: "Done",
+      data: "test",
+      helpUrl: "about:about",
+    }
+  ),
+];