Bug 1517213 - Part 3 - Display the correct value when resetting a localized preference. r=bgrins
☠☠ backed out by 39d6e47b5bf4 ☠ ☠
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Wed, 02 Jan 2019 11:54:17 +0000
changeset 509538 798c09311606328e8c7374468b16859113ab883c
parent 509537 8dcd5d5e815ddea060c89a7cffd2d075aadf8ab2
child 509539 58633320257f3ee65956d44cfb10d501c65ea866
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1517213
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 1517213 - Part 3 - Display the correct value when resetting a localized preference. r=bgrins Differential Revision: https://phabricator.services.mozilla.com/D15567
browser/components/aboutconfig/content/aboutconfig.js
browser/components/aboutconfig/test/browser/browser_edit.js
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -5,16 +5,45 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 
 let gDefaultBranch = Services.prefs.getDefaultBranch("");
 let gPrefArray;
 let gPrefRowInEdit;
 let gPrefInEdit;
 
+class PrefRow {
+  constructor(name) {
+    this.name = name;
+    this.refreshValue();
+  }
+
+  refreshValue() {
+    this.hasUserValue = Services.prefs.prefHasUserValue(this.name);
+    this.hasDefaultValue = this.hasUserValue ? prefHasDefaultValue(this.name)
+                                             : true;
+    this.isLocked = Services.prefs.prefIsLocked(this.name);
+
+    try {
+      // This can throw for locked preferences without a default value.
+      this.value = Preferences.get(this.name);
+      // We don't know which preferences should be read using getComplexValue,
+      // so we use a heuristic to determine if this is a localized preference.
+      if (!this.hasUserValue &&
+          /^chrome:\/\/.+\/locale\/.+\.properties/.test(this.value)) {
+        // This can throw if there is no value in the localized files.
+        this.value = Services.prefs.getComplexValue(this.name,
+          Ci.nsIPrefLocalizedString).data;
+      }
+    } catch (ex) {
+      this.value = "";
+    }
+  }
+}
+
 function getPrefName(prefRow) {
   return prefRow.getAttribute("aria-label");
 }
 
 document.addEventListener("DOMContentLoaded", () => {
   if (!Preferences.get("browser.aboutConfig.showWarning")) {
     loadPrefs();
   }
@@ -33,38 +62,17 @@ function loadPrefs() {
   search.type = "text";
   search.id = "search";
   document.l10n.setAttributes(search, "about-config-search");
   document.body.appendChild(search);
   let prefs = document.createElement("table");
   prefs.id = "prefs";
   document.body.appendChild(prefs);
 
-  gPrefArray = Services.prefs.getChildList("").map(function(name) {
-    let hasUserValue = Services.prefs.prefHasUserValue(name);
-    let pref = {
-      name,
-      hasUserValue,
-      hasDefaultValue: hasUserValue ? prefHasDefaultValue(name) : true,
-      isLocked: Services.prefs.prefIsLocked(name),
-    };
-    // Try in case it's a localized string or locked user added pref
-    // If an execption is thrown the pref value is set to the empty string.
-    try {
-      // Throws an exception in case locked user added pref without default value
-      pref.value = Preferences.get(name);
-      // Throws an exception if there is no equivalent value in the localized files for the pref.
-      if (!pref.hasUserValue && /^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.value)) {
-        pref.value = Services.prefs.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
-      }
-    } catch (ex) {
-      pref.value = "";
-    }
-    return pref;
-  });
+  gPrefArray = Services.prefs.getChildList("").map(name => new PrefRow(name));
 
   gPrefArray.sort((a, b) => a.name > b.name);
 
   search.addEventListener("keypress", e => {
     if (e.key == "Enter") {
       filterPrefs();
     }
   });
@@ -75,18 +83,17 @@ function loadPrefs() {
     }
     let prefRow = event.target.closest("tr");
     let prefName = getPrefName(prefRow);
     let pref = gPrefArray.find(p => p.name == prefName);
     let button = event.target.closest("button");
     if (button.classList.contains("button-reset")) {
       // Reset pref and update gPrefArray.
       Services.prefs.clearUserPref(prefName);
-      pref.value = Preferences.get(prefName);
-      pref.hasUserValue = false;
+      pref.refreshValue();
       // Update UI.
       prefRow.textContent = "";
       prefRow.classList.remove("has-user-value");
       prefRow.appendChild(getPrefRow(pref));
       prefRow.querySelector("td.cell-edit").firstChild.focus();
     } else if (button.classList.contains("add-true")) {
       addNewPref(prefRow.firstChild.innerHTML, true);
     } else if (button.classList.contains("add-false")) {
@@ -97,18 +104,17 @@ function loadPrefs() {
         button.classList.contains("add-Number") ? 0 : "");
       prefRow = [...prefs.getElementsByTagName("tr")]
         .find(row => row.querySelector("td").textContent == prefName);
       startEditingPref(prefRow, gPrefArray.find(p => p.name == prefName));
       prefRow.querySelector("td.cell-value").firstChild.firstChild.focus();
     } else if (button.classList.contains("button-toggle")) {
       // Toggle the pref and update gPrefArray.
       Services.prefs.setBoolPref(prefName, !pref.value);
-      pref.value = !pref.value;
-      pref.hasUserValue = Services.prefs.prefHasUserValue(pref.name);
+      pref.refreshValue();
       // Update UI.
       prefRow.textContent = "";
       if (pref.hasUserValue) {
         prefRow.classList.add("has-user-value");
       } else {
         prefRow.classList.remove("has-user-value");
       }
       prefRow.appendChild(getPrefRow(pref));
@@ -291,18 +297,17 @@ function endEditingPref(row) {
     }
     newValue = numberValue;
     Services.prefs.setIntPref(name, newValue);
   } else {
     Services.prefs.setStringPref(name, newValue);
   }
 
   // Update gPrefArray.
-  gPrefInEdit.value = newValue;
-  gPrefInEdit.hasUserValue = Services.prefs.prefHasUserValue(name);
+  gPrefInEdit.refreshValue();
   // Update UI.
   row.textContent = "";
   if (gPrefInEdit.hasUserValue) {
     row.classList.add("has-user-value");
   } else {
     row.classList.remove("has-user-value");
   }
   row.appendChild(getPrefRow(gPrefInEdit));
@@ -322,17 +327,12 @@ function prefHasDefaultValue(name) {
         return true;
     }
   } catch (ex) {}
   return false;
 }
 
 function addNewPref(name, value) {
   Preferences.set(name, value);
-  gPrefArray.push({
-    name,
-    value,
-    hasUserValue: true,
-    hasDefaultValue: false,
-  });
+  gPrefArray.push(new PrefRow(name));
   gPrefArray.sort((a, b) => a.name > b.name);
   filterPrefs();
 }
--- a/browser/components/aboutconfig/test/browser/browser_edit.js
+++ b/browser/components/aboutconfig/test/browser/browser_edit.js
@@ -49,16 +49,17 @@ add_task(async function test_delete_user
     Assert.ok(!this.getRow("userAddedPref"));
   });
 });
 
 add_task(async function test_reset_user_pref() {
   await SpecialPowers.pushPrefEnv({
     "set": [
       [PREF_BOOLEAN_DEFAULT_TRUE, false],
+      [PREF_STRING_LOCALIZED_MISSING, "user-value"],
     ],
   });
 
   await AboutConfigTest.withNewTab(async function() {
     let testPref = "browser.autofocus";
     // Click reset.
     let row = this.getRow(PREF_BOOLEAN_DEFAULT_TRUE);
     row.resetColumnButton.click();
@@ -69,16 +70,26 @@ add_task(async function test_reset_user_
     Assert.equal(this.getRow(PREF_BOOLEAN_DEFAULT_TRUE).value, "true");
 
     // Search for nothing to test gPrefArray
     this.search();
     row = this.getRow(PREF_BOOLEAN_DEFAULT_TRUE);
     Assert.ok(!row.hasClass("has-user-value"));
     Assert.ok(!row.resetColumnButton);
     Assert.equal(this.getRow(PREF_BOOLEAN_DEFAULT_TRUE).value, "true");
+
+    // Clicking reset on a localized preference without a corresponding value.
+    row = this.getRow(PREF_STRING_LOCALIZED_MISSING);
+    Assert.equal(row.value, "user-value");
+    row.resetColumnButton.click();
+    // Check new layout and reset.
+    Assert.ok(!row.hasClass("has-user-value"));
+    Assert.ok(!row.resetColumnButton);
+    Assert.ok(!Services.prefs.prefHasUserValue(PREF_STRING_LOCALIZED_MISSING));
+    Assert.equal(this.getRow(PREF_STRING_LOCALIZED_MISSING).value, "");
   });
 });
 
 add_task(async function test_modify() {
   await AboutConfigTest.withNewTab(async function() {
     // Test toggle for boolean prefs.
     for (let nameOfBoolPref of [
       "test.aboutconfig.modify.boolean",