Bug 1501417 - Part 2 - Don't wait for the Enter key in the new "about:config" search field. r=bgrins
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Tue, 15 Jan 2019 14:37:30 +0000
changeset 514022 ecd71a7f46f828e30200d50c06326fdc6eb90d2d
parent 514021 963484091d53cc5b77ce0530cea042270c184a85
child 514023 c20f8b989a2fc405d2cdbf74ac78031e8f67af5c
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1501417
milestone66.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 1501417 - Part 2 - Don't wait for the Enter key in the new "about:config" search field. r=bgrins Differential Revision: https://phabricator.services.mozilla.com/D16310
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,16 +1,20 @@
 /* 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/. */
 
+ChromeUtils.import("resource://gre/modules/DeferredTask.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 
+const SEARCH_TIMEOUT_MS = 500;
+
 let gDefaultBranch = Services.prefs.getDefaultBranch("");
+let gFilterPrefsTask = new DeferredTask(() => filterPrefs(), SEARCH_TIMEOUT_MS);
 
 /**
  * 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();
@@ -284,22 +288,33 @@ function loadPrefs() {
   let prefs = document.createElement("table");
   prefs.id = "prefs";
   document.body.appendChild(prefs);
 
   for (let name of Services.prefs.getChildList("")) {
     new PrefRow(name);
   }
 
-  search.addEventListener("keypress", e => {
-    if (e.key == "Enter") {
-      filterPrefs();
+  search.addEventListener("keypress", event => {
+    switch (event.key) {
+      case "Escape":
+        search.value = "";
+        // Fall through.
+      case "Enter":
+        gFilterPrefsTask.disarm();
+        filterPrefs();
     }
   });
 
+  search.addEventListener("input", () => {
+    // We call "disarm" to restart the timer at every input.
+    gFilterPrefsTask.disarm();
+    gFilterPrefsTask.arm();
+  });
+
   prefs.addEventListener("click", event => {
     if (event.target.localName != "button") {
       return;
     }
     let pref = gElementToPrefMap.get(event.target.closest("tr"));
     let button = event.target.closest("button");
     if (button.classList.contains("button-add")) {
       Preferences.set(pref.name, pref.value);
--- a/browser/components/aboutconfig/test/browser/browser_search.js
+++ b/browser/components/aboutconfig/test/browser/browser_search.js
@@ -54,8 +54,36 @@ add_task(async function test_search() {
     Assert.equal(this.rows.length, 2);
 
     // When searching case insensitively, there is an additional row to add a
     // new preference with the same name but a different case.
     this.search("TEST.aboutconfig.a");
     Assert.equal(this.rows.length, 3);
   });
 });
+
+add_task(async function test_search_delayed() {
+  await AboutConfigTest.withNewTab(async function() {
+    let prefs = this.document.getElementById("prefs");
+
+    // Prepare the table and the search field for the 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 the children are updated.
+    let prefsTableChanged = new Promise(resolve => {
+      let observer = new MutationObserver(() => {
+        observer.disconnect();
+        resolve();
+      });
+      observer.observe(prefs, { childList: true });
+    });
+
+    // Add a character and test that the table is not updated immediately.
+    EventUtils.synthesizeKey("b");
+    Assert.equal(this.rows.length, 2);
+
+    // The table will eventually be updated after a delay.
+    await prefsTableChanged;
+    Assert.equal(this.rows.length, 1);
+  });
+});