Bug 1527395 - Reduce timeout and don't search automatically until enough characters have been typed. r=mconley
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Fri, 15 Feb 2019 15:19:56 +0000
changeset 459802 14f258320f909aa607964d18683373922090460f
parent 459801 329374773b81d379ada1d33abf01436310d35331
child 459803 6f42a0b6c8dea3a07850db4bfe5966f56c5a8a58
push id35573
push usercbrindusan@mozilla.com
push dateMon, 18 Feb 2019 21:45:58 +0000
treeherdermozilla-central@ca3d40c83ae7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1527395
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 1527395 - Reduce timeout and don't search automatically until enough characters have been typed. r=mconley Differential Revision: https://phabricator.services.mozilla.com/D19546
browser/components/aboutconfig/content/aboutconfig.js
browser/components/aboutconfig/test/browser/browser_search.js
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -1,32 +1,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const {DeferredTask} = ChromeUtils.import("resource://gre/modules/DeferredTask.jsm");
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 
-const SEARCH_TIMEOUT_MS = 500;
+const SEARCH_TIMEOUT_MS = 100;
+const SEARCH_AUTO_MIN_CRARACTERS = 3;
 
 const GETTERS_BY_PREF_TYPE = {
   [Ci.nsIPrefBranch.PREF_BOOL]: "getBoolPref",
   [Ci.nsIPrefBranch.PREF_INT]: "getIntPref",
   [Ci.nsIPrefBranch.PREF_STRING]: "getStringPref",
 };
 
 const STRINGS_ADD_BY_TYPE = {
   Boolean: "about-config-pref-add-type-boolean",
   Number: "about-config-pref-add-type-number",
   String: "about-config-pref-add-type-string",
 };
 
 let gDefaultBranch = Services.prefs.getDefaultBranch("");
-let gFilterPrefsTask = new DeferredTask(() => filterPrefs(), SEARCH_TIMEOUT_MS);
+let gFilterPrefsTask = new DeferredTask(() => filterPrefs(), SEARCH_TIMEOUT_MS, 0);
 
 /**
  * Maps the name of each preference in the back-end to its PrefRow object,
  * separating the preferences that actually exist. This is as an optimization to
  * avoid querying the preferences service each time the list is filtered.
  */
 let gExistingPrefs = new Map();
 let gDeletedPrefs = new Map();
@@ -376,31 +377,33 @@ function loadPrefs() {
   let showAll = document.getElementById("show-all");
   search.focus();
 
   for (let name of Services.prefs.getChildList("")) {
     new PrefRow(name);
   }
 
   search.addEventListener("keypress", event => {
-    switch (event.key) {
-      case "Escape":
-        search.value = "";
-        // Fall through.
-      case "Enter":
-        gFilterPrefsTask.disarm();
-        filterPrefs();
+    if (event.key == "Escape") {
+      // The ESC key returns immediately to the initial empty page.
+      search.value = "";
+      gFilterPrefsTask.disarm();
+      filterPrefs();
+    } else if (event.key == "Enter") {
+      // The Enter key filters immediately even if the search string is short.
+      gFilterPrefsTask.disarm();
+      filterPrefs({ shortString: true });
     }
   });
 
   search.addEventListener("input", () => {
     // We call "disarm" to restart the timer at every input.
     gFilterPrefsTask.disarm();
-    if (!search.value.trim().length) {
-      // Return immediately to the empty page if the search string is empty.
+    if (search.value.trim().length < SEARCH_AUTO_MIN_CRARACTERS) {
+      // Return immediately to the empty page if the search string is short.
       filterPrefs();
     } else {
       gFilterPrefsTask.arm();
     }
   });
 
   showAll.addEventListener("click", event => {
     search.focus();
@@ -437,16 +440,20 @@ function loadPrefs() {
 
 function filterPrefs(options = {}) {
   if (gPrefInEdit) {
     gPrefInEdit.endEdit();
   }
   gDeletedPrefs.clear();
 
   let searchName = gSearchInput.value.trim();
+  if (searchName.length < SEARCH_AUTO_MIN_CRARACTERS && !options.shortString) {
+    searchName = "";
+  }
+
   gFilterString = searchName.toLowerCase();
   gFilterShowAll = !!options.showAll;
 
   let showResults = gFilterString || gFilterShowAll;
   document.getElementById("show-all").classList.toggle("hidden", showResults);
 
   let prefArray = [];
   if (showResults) {
--- a/browser/components/aboutconfig/test/browser/browser_search.js
+++ b/browser/components/aboutconfig/test/browser/browser_search.js
@@ -71,17 +71,32 @@ add_task(async function test_search() {
     // Entering an empty string returns to the initial page.
     this.search("");
     Assert.equal(this.rows.length, 0);
   });
 });
 
 add_task(async function test_search_delayed() {
   await AboutConfigTest.withNewTab(async function() {
-    // Prepare the table and the search field for the test.
+    // Start with the initial empty page.
+    this.search("");
+
+    // We need to wait more than the search typing timeout to make sure that
+    // nothing happens when entering a short string.
+    EventUtils.synthesizeKey("t");
+    EventUtils.synthesizeKey("e");
+    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+    await new Promise(resolve => setTimeout(resolve, 500));
+    Assert.equal(this.rows.length, 0);
+
+    // Pressing Enter will force a search to occur anyways.
+    EventUtils.sendKey("return");
+    Assert.greater(this.rows.length, 0);
+
+    // Prepare the table and the search field for the next test.
     this.search("test.aboutconfig.a");
     Assert.equal(this.rows.length, 2);
 
     // The table is updated in a single microtask, so we don't need to wait for
     // specific mutations, we can just continue when any of the children or
     // their "hidden" attributes are updated.
     let prefsTableChanged = new Promise(resolve => {
       let observer = new MutationObserver(() => {