Bug 1379338 - scriptify preferences XBL; r=jaws
authorMyk Melez <myk@mykzilla.org>
Thu, 04 Jan 2018 21:37:47 -0800
changeset 397934 0adedb70b788
parent 397933 d760cf06ca40
child 397935 81362f7306fe
child 397988 de578768ff3b
push id33194
push usertoros@mozilla.com
push date2018-01-05 09:58 +0000
treeherdermozilla-central@81362f7306fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1379338
milestone59.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 1379338 - scriptify preferences XBL; r=jaws MozReview-Commit-ID: Egyzs2KxhzH
browser/base/content/sanitize.xul
browser/base/content/sanitizeDialog.js
browser/base/content/test/general/browser_sanitizeDialog.js
browser/base/content/utilityOverlay.js
browser/components/preferences/applicationManager.xul
browser/components/preferences/colors.js
browser/components/preferences/colors.xul
browser/components/preferences/connection.js
browser/components/preferences/connection.xul
browser/components/preferences/fonts.js
browser/components/preferences/fonts.xul
browser/components/preferences/in-content/containers.xul
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/main.xul
browser/components/preferences/in-content/preferences.js
browser/components/preferences/in-content/preferences.xul
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/privacy.xul
browser/components/preferences/in-content/search.js
browser/components/preferences/in-content/search.xul
browser/components/preferences/in-content/sync.js
browser/components/preferences/in-content/sync.xul
browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js
browser/components/preferences/in-content/tests/browser_bug731866.js
browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js
browser/components/preferences/in-content/tests/browser_connection.js
browser/components/preferences/in-content/tests/browser_connection_bug388287.js
browser/components/preferences/in-content/tests/browser_fluent.js
browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js
browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
browser/components/preferences/jar.mn
browser/components/preferences/languages.js
browser/components/preferences/languages.xul
browser/components/preferences/sanitize.js
browser/components/preferences/sanitize.xul
browser/extensions/shield-recipe-client/lib/ShieldPreferences.jsm
browser/themes/linux/preferences/preferences.css
browser/themes/linux/sanitizeDialog.css
browser/themes/osx/preferences/in-content/dialog.css
browser/themes/osx/preferences/preferences.css
browser/themes/osx/sanitizeDialog.css
browser/themes/shared/incontentprefs/dialog.inc.css
browser/themes/shared/incontentprefs/preferences.inc.css
browser/themes/windows/preferences/preferences.css
browser/themes/windows/sanitizeDialog.css
testing/marionette/harness/marionette_harness/tests/unit/test_anonymous_content.py
toolkit/content/jar.mn
toolkit/content/preferencesBindings.js
toolkit/content/resetProfile.xul
toolkit/content/tests/chrome/test_preferences.xul
toolkit/content/tests/chrome/test_preferences_beforeaccept.xul
toolkit/content/tests/chrome/test_preferences_onsyncfrompreference.xul
toolkit/content/tests/chrome/window_preferences.xul
toolkit/content/tests/chrome/window_preferences2.xul
toolkit/content/tests/chrome/window_preferences3.xul
toolkit/content/tests/chrome/window_preferences_beforeaccept.xul
toolkit/content/tests/chrome/window_preferences_commandretarget.xul
toolkit/content/tests/chrome/window_preferences_onsyncfrompreference.xul
toolkit/content/widgets/dialog.xml
toolkit/content/widgets/preferences.xml
toolkit/content/xul.css
toolkit/mozapps/preferences/fontbuilder.js
toolkit/themes/linux/global/global.css
toolkit/themes/linux/global/jar.mn
toolkit/themes/linux/global/preferences.css
toolkit/themes/mobile/jar.mn
toolkit/themes/osx/global/global.css
toolkit/themes/osx/global/icons/panebutton-active.png
toolkit/themes/osx/global/icons/panebutton-inactive.png
toolkit/themes/osx/global/jar.mn
toolkit/themes/osx/global/preferences.css
toolkit/themes/shared/in-content/common.inc.css
toolkit/themes/windows/global/global.css
toolkit/themes/windows/global/jar.mn
toolkit/themes/windows/global/preferences.css
--- a/browser/base/content/sanitize.xul
+++ b/browser/base/content/sanitize.xul
@@ -1,64 +1,58 @@
 <?xml version="1.0"?>
 
 <!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
 <!-- 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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/"?>
+<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
 <?xml-stylesheet href="chrome://browser/skin/sanitizeDialog.css"?>
 
 
 <?xml-stylesheet href="chrome://browser/content/sanitizeDialog.css"?>
 
-<!DOCTYPE prefwindow [
+<!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
   <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
   <!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
+  %preferencesDTD;
+  %globalKeysDTD;
   %brandDTD;
   %sanitizeDTD;
 ]>
 
-<prefwindow id="SanitizeDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            dlgbuttons="accept,cancel"
-            title="&sanitizeDialog2.title;"
-            noneverythingtitle="&sanitizeDialog2.title;"
-            style="width: &sanitizeDialog2.width;;"
-            ondialogaccept="return gSanitizePromptDialog.sanitize();">
+<dialog id="SanitizeDialog" class="prefwindow" type="child"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        buttons="accept,cancel"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        title="&sanitizeDialog2.title;"
+        noneverythingtitle="&sanitizeDialog2.title;"
+        style="width: &sanitizeDialog2.width;;"
+        onload="gSanitizePromptDialog.init();"
+        ondialogaccept="return gSanitizePromptDialog.sanitize();">
 
-  <prefpane id="SanitizeDialogPane" onpaneload="gSanitizePromptDialog.init();">
+  <vbox id="SanitizeDialogPane" class="prefpane">
     <stringbundle id="bundleBrowser"
                   src="chrome://browser/locale/browser.properties"/>
 
     <script type="application/javascript"
             src="chrome://browser/content/sanitize.js"/>
 
-
+    <script type="application/javascript"
+            src="chrome://global/content/preferencesBindings.js"/>
     <script type="application/javascript"
             src="chrome://browser/content/sanitizeDialog.js"/>
 
-    <preferences id="sanitizePreferences">
-      <preference id="privacy.cpd.history"               name="privacy.cpd.history"               type="bool"/>
-      <preference id="privacy.cpd.formdata"              name="privacy.cpd.formdata"              type="bool"/>
-      <preference id="privacy.cpd.downloads"             name="privacy.cpd.downloads"             type="bool" disabled="true"/>
-      <preference id="privacy.cpd.cookies"               name="privacy.cpd.cookies"               type="bool"/>
-      <preference id="privacy.cpd.cache"                 name="privacy.cpd.cache"                 type="bool"/>
-      <preference id="privacy.cpd.sessions"              name="privacy.cpd.sessions"              type="bool"/>
-      <preference id="privacy.cpd.offlineApps"           name="privacy.cpd.offlineApps"           type="bool"/>
-      <preference id="privacy.cpd.siteSettings"          name="privacy.cpd.siteSettings"          type="bool"/>
-    </preferences>
-    
-    <preferences id="nonItemPreferences">
-      <preference id="privacy.sanitize.timeSpan"
-                  name="privacy.sanitize.timeSpan"
-                  type="int"/>
-    </preferences>
-
     <hbox id="SanitizeDurationBox" align="center">
       <label value="&clearTimeDuration.label;"
              accesskey="&clearTimeDuration.accesskey;"
              control="sanitizeDurationChoice"
              id="sanitizeDurationLabel"/>
       <menulist id="sanitizeDurationChoice"
                 preference="privacy.sanitize.timeSpan"
                 onselect="gSanitizePromptDialog.selectByTimespan();"
@@ -139,10 +133,10 @@
       <listitem label="&itemSitePreferences.label;"
                 type="checkbox"
                 accesskey="&itemSitePreferences.accesskey;"
                 preference="privacy.cpd.siteSettings"
                 noduration="true"
                 onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
     </listbox>
 
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/browser/base/content/sanitizeDialog.js
+++ b/browser/base/content/sanitizeDialog.js
@@ -1,40 +1,46 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
+/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 
 var {Sanitizer} = Cu.import("resource:///modules/Sanitizer.jsm", {});
 
+Preferences.addAll([
+  { id: "privacy.cpd.history", type: "bool" },
+  { id: "privacy.cpd.formdata", type: "bool" },
+  { id: "privacy.cpd.downloads", type: "bool", disabled: true },
+  { id: "privacy.cpd.cookies", type: "bool" },
+  { id: "privacy.cpd.cache", type: "bool" },
+  { id: "privacy.cpd.sessions", type: "bool" },
+  { id: "privacy.cpd.offlineApps", type: "bool" },
+  { id: "privacy.cpd.siteSettings", type: "bool" },
+  { id: "privacy.sanitize.timeSpan", type: "int" },
+]);
+
 var gSanitizePromptDialog = {
 
   get bundleBrowser() {
     if (!this._bundleBrowser)
       this._bundleBrowser = document.getElementById("bundleBrowser");
     return this._bundleBrowser;
   },
 
   get selectedTimespan() {
     var durList = document.getElementById("sanitizeDurationChoice");
     return parseInt(durList.value);
   },
 
-  get sanitizePreferences() {
-    if (!this._sanitizePreferences) {
-      this._sanitizePreferences =
-        document.getElementById("sanitizePreferences");
-    }
-    return this._sanitizePreferences;
-  },
-
   get warningBox() {
     return document.getElementById("sanitizeEverythingWarningBox");
   },
 
   init() {
     // This is used by selectByTimespan() to determine if the window has loaded.
     this._inited = true;
 
@@ -136,73 +142,72 @@ var gSanitizePromptDialog = {
     }
 
     var warningDesc = document.getElementById("sanitizeEverythingWarning");
     warningDesc.textContent =
       this.bundleBrowser.getString(warningStringID);
   },
 
   /**
+   * Return the boolean prefs that enable/disable clearing of various kinds
+   * of history.  The only pref this excludes is privacy.sanitize.timeSpan.
+   */
+  _getItemPrefs() {
+    return Preferences.getAll().filter(p => p.id !== "privacy.sanitize.timeSpan");
+  },
+
+  /**
    * Called when the value of a preference element is synced from the actual
    * pref.  Enables or disables the OK button appropriately.
    */
   onReadGeneric() {
-    var found = false;
-
-    // Find any other pref that's checked and enabled.
-    var i = 0;
-    while (!found && i < this.sanitizePreferences.childNodes.length) {
-      var preference = this.sanitizePreferences.childNodes[i];
-
-      found = !!preference.value &&
-              !preference.disabled;
-      i++;
-    }
+    // Find any other pref that's checked and enabled (except for
+    // privacy.sanitize.timeSpan, which doesn't affect the button's status).
+    var found = this._getItemPrefs().some(pref => !!pref.value && !pref.disabled);
 
     try {
       document.documentElement.getButton("accept").disabled = !found;
     } catch (e) { }
 
     // Update the warning prompt if needed
     this.prepareWarning(true);
 
     return undefined;
   },
 
   /**
    * Sanitizer.prototype.sanitize() requires the prefs to be up-to-date.
    * Because the type of this prefwindow is "child" -- and that's needed because
    * without it the dialog has no OK and Cancel buttons -- the prefs are not
-   * updated on dialogaccept on platforms that don't support instant-apply
-   * (i.e., Windows).  We must therefore manually set the prefs from their
-   * corresponding preference elements.
+   * updated on dialogaccept.  We must therefore manually set the prefs
+   * from their corresponding preference elements.
    */
   updatePrefs() {
     Sanitizer.prefs.setIntPref("timeSpan", this.selectedTimespan);
 
     // Keep the pref for the download history in sync with the history pref.
-    document.getElementById("privacy.cpd.downloads").value =
-      document.getElementById("privacy.cpd.history").value;
+    Preferences.get("privacy.cpd.downloads").value =
+      Preferences.get("privacy.cpd.history").value;
 
     // Now manually set the prefs from their corresponding preference
     // elements.
-    var prefs = this.sanitizePreferences.rootBranch;
-    for (let i = 0; i < this.sanitizePreferences.childNodes.length; ++i) {
-      var p = this.sanitizePreferences.childNodes[i];
-      prefs.setBoolPref(p.name, p.value);
+    var prefs = this._getItemPrefs();
+    for (let i = 0; i < prefs.length; ++i) {
+      var p = prefs[i];
+      Services.prefs.setBoolPref(p.name, p.value);
     }
   },
 
   /**
    * Check if all of the history items have been selected like the default status.
    */
   hasNonSelectedItems() {
     let checkboxes = document.querySelectorAll("#itemList > [preference]");
     for (let i = 0; i < checkboxes.length; ++i) {
-      let pref = document.getElementById(checkboxes[i].getAttribute("preference"));
+      let pref = Preferences.get(checkboxes[i].getAttribute("preference"));
       if (!pref.value)
         return true;
     }
     return false;
   },
 
   /**
    * Show the history items list.
--- a/browser/base/content/test/general/browser_sanitizeDialog.js
+++ b/browser/base/content/test/general/browser_sanitizeDialog.js
@@ -710,17 +710,17 @@ WindowHelper.prototype = {
 
   /**
    * Makes sure all the checkboxes are checked.
    */
   _checkAllCheckboxesCustom(check) {
     var cb = this.win.document.querySelectorAll("#itemList > [preference]");
     ok(cb.length > 1, "found checkboxes for preferences");
     for (var i = 0; i < cb.length; ++i) {
-      var pref = this.win.document.getElementById(cb[i].getAttribute("preference"));
+      var pref = this.win.Preferences.get(cb[i].getAttribute("preference"));
       if (!!pref.value ^ check)
         cb[i].click();
     }
   },
 
   checkAllCheckboxes() {
     this._checkAllCheckboxesCustom(true);
   },
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -930,17 +930,17 @@ function openHelpLink(aHelpTopic, aCalle
   openUILinkIn(url, where);
 }
 
 function openPrefsHelp() {
   // non-instant apply prefwindows are usually modal, so we can't open in the topmost window,
   // since its probably behind the window.
   var instantApply = getBoolPref("browser.preferences.instantApply");
 
-  var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
+  var helpTopic = document.documentElement.getAttribute("helpTopic");
   openHelpLink(helpTopic, !instantApply);
 }
 
 function trimURL(aURL) {
   // This function must not modify the given URL such that calling
   // nsIURIFixup::createFixupURI with the result will produce a different URI.
 
   // remove single trailing slash for http/https/ftp URLs
--- a/browser/components/preferences/applicationManager.xul
+++ b/browser/components/preferences/applicationManager.xul
@@ -15,16 +15,18 @@
         ondialogcancel="gAppManagerDialog.onCancel();"
         title="&appManager.title;"
         style="&appManager.style;"
         persist="screenX screenY">
 
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"
+          src="chrome://global/content/preferencesBindings.js"/>
+  <script type="application/javascript"
           src="chrome://browser/content/preferences/applicationManager.js"/>
 
   <commandset id="appManagerCommandSet">
     <command id="cmd_remove"
              oncommand="gAppManagerDialog.remove();"
              disabled="true"/>
   </commandset>
 
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/colors.js
@@ -0,0 +1,15 @@
+/* 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/. */
+
+/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
+
+Preferences.addAll([
+  { id: "browser.display.document_color_use", type: "int" },
+  { id: "browser.anchor_color", type: "string" },
+  { id: "browser.visited_color", type: "string" },
+  { id: "browser.underline_anchors", type: "bool" },
+  { id: "browser.display.foreground_color", type: "string" },
+  { id: "browser.display.background_color", type: "string" },
+  { id: "browser.display.use_system_colors", type: "bool" },
+]);
--- a/browser/components/preferences/colors.xul
+++ b/browser/components/preferences/colors.xul
@@ -1,46 +1,51 @@
 <?xml version="1.0"?>
 
 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 # 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/.
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-#ifdef XP_MACOSX
 <?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
 
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/colors.dtd" >
+<!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  %preferencesDTD;
+  <!ENTITY % colorsDTD SYSTEM "chrome://browser/locale/preferences/colors.dtd">
+  %colorsDTD;
+]>
 
-<prefwindow id="ColorsDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="&colorsDialog.title;"
-            dlgbuttons="accept,cancel,help"
-            ondialoghelp="openPrefsHelp()"
+<dialog id="ColorsDialog" type="child" class="prefwindow"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="&colorsDialog.title;"
+        buttons="accept,cancel,help"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        helpTopic="prefs-fonts-and-colors"
+        ondialoghelp="openPrefsHelp()"
 #ifdef XP_MACOSX
-            style="width: &window.macWidth; !important;">
+        style="width: &window.macWidth; !important;">
 #else
-            style="width: &window.width; !important;">
+        style="width: &window.width; !important;">
 #endif
 
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-  <prefpane id="ColorsDialogPane"
-            helpTopic="prefs-fonts-and-colors">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
 
-    <preferences>
-      <preference id="browser.display.document_color_use"   name="browser.display.document_color_use"   type="int"/>
-      <preference id="browser.anchor_color"                 name="browser.anchor_color"                 type="string"/>
-      <preference id="browser.visited_color"                name="browser.visited_color"                type="string"/>
-      <preference id="browser.underline_anchors"            name="browser.underline_anchors"            type="bool"/>
-      <preference id="browser.display.foreground_color"     name="browser.display.foreground_color"     type="string"/>
-      <preference id="browser.display.background_color"     name="browser.display.background_color"     type="string"/>
-      <preference id="browser.display.use_system_colors"    name="browser.display.use_system_colors"    type="bool"/>
-    </preferences>
+  <keyset>
+    <key key="&windowClose.key;" modifiers="accel" oncommand="Preferences.close(event)"/>
+  </keyset>
+
+  <vbox id="ColorsDialogPane" class="prefpane">
+
+    <script type="application/javascript" src="chrome://browser/content/preferences/colors.js"/>
 
     <hbox>
       <groupbox flex="1">
         <caption><label>&color;</label></caption>
         <hbox align="center">
           <label accesskey="&textColor2.accesskey;" control="foregroundtextmenu">&textColor2.label;</label>
           <spacer flex="1"/>
           <colorpicker type="button" id="foregroundtextmenu" palettename="standard"
@@ -95,10 +100,10 @@
             <menuitem label="&overrideDefaultPageColors.auto.label;"
                       value="0" id="documentColorAutomatic"/>
             <menuitem label="&overrideDefaultPageColors.never.label;"
                       value="1" id="documentColorNever"/>
           </menupopup>
         </menulist>
       </hbox>
     </vbox>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/browser/components/preferences/connection.js
+++ b/browser/components/preferences/connection.js
@@ -1,51 +1,84 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
 /* 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/. */
 
 /* import-globals-from ../../base/content/utilityOverlay.js */
+/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
+
+Preferences.addAll([
+  { id: "network.proxy.type", type: "int" },
+  { id: "network.proxy.http", type: "string" },
+  { id: "network.proxy.http_port", type: "int" },
+  { id: "network.proxy.ftp", type: "string" },
+  { id: "network.proxy.ftp_port", type: "int" },
+  { id: "network.proxy.ssl", type: "string" },
+  { id: "network.proxy.ssl_port", type: "int" },
+  { id: "network.proxy.socks", type: "string" },
+  { id: "network.proxy.socks_port", type: "int" },
+  { id: "network.proxy.socks_version", type: "int" },
+  { id: "network.proxy.socks_remote_dns", type: "bool" },
+  { id: "network.proxy.no_proxies_on", type: "string" },
+  { id: "network.proxy.autoconfig_url", type: "string" },
+  { id: "network.proxy.share_proxy_settings", type: "bool" },
+  { id: "signon.autologin.proxy", type: "bool" },
+  { id: "pref.advanced.proxies.disable_button.reload", type: "bool" },
+  { id: "network.proxy.backup.ftp", type: "string" },
+  { id: "network.proxy.backup.ftp_port", type: "int" },
+  { id: "network.proxy.backup.ssl", type: "string" },
+  { id: "network.proxy.backup.ssl_port", type: "int" },
+  { id: "network.proxy.backup.socks", type: "string" },
+  { id: "network.proxy.backup.socks_port", type: "int" },
+]);
+
+window.addEventListener("DOMContentLoaded", () => {
+  Preferences.get("network.proxy.type").on("change",
+    gConnectionsDialog.proxyTypeChanged.bind(gConnectionsDialog));
+  Preferences.get("network.proxy.socks_version").on("change",
+    gConnectionsDialog.updateDNSPref.bind(gConnectionsDialog));
+}, { once: true, capture: true });
 
 var gConnectionsDialog = {
   beforeAccept() {
-    var proxyTypePref = document.getElementById("network.proxy.type");
+    var proxyTypePref = Preferences.get("network.proxy.type");
     if (proxyTypePref.value == 2) {
       this.doAutoconfigURLFixup();
       return true;
     }
 
     if (proxyTypePref.value != 1)
       return true;
 
-    var httpProxyURLPref = document.getElementById("network.proxy.http");
-    var httpProxyPortPref = document.getElementById("network.proxy.http_port");
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var httpProxyURLPref = Preferences.get("network.proxy.http");
+    var httpProxyPortPref = Preferences.get("network.proxy.http_port");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
 
     // If the port is 0 and the proxy server is specified, focus on the port and cancel submission.
     for (let prefName of ["http", "ssl", "ftp", "socks"]) {
-      let proxyPortPref = document.getElementById("network.proxy." + prefName + "_port");
-      let proxyPref = document.getElementById("network.proxy." + prefName);
+      let proxyPortPref = Preferences.get("network.proxy." + prefName + "_port");
+      let proxyPref = Preferences.get("network.proxy." + prefName);
       // Only worry about ports which are currently active. If the share option is on, then ignore
       // all ports except the HTTP port
       if (proxyPref.value != "" && proxyPortPref.value == 0 &&
             (prefName == "http" || !shareProxiesPref.value)) {
         document.getElementById("networkProxy" + prefName.toUpperCase() + "_Port").focus();
         return false;
       }
     }
 
     // In the case of a shared proxy preference, backup the current values and update with the HTTP value
     if (shareProxiesPref.value) {
       var proxyPrefs = ["ssl", "ftp", "socks"];
       for (var i = 0; i < proxyPrefs.length; ++i) {
-        var proxyServerURLPref = document.getElementById("network.proxy." + proxyPrefs[i]);
-        var proxyPortPref = document.getElementById("network.proxy." + proxyPrefs[i] + "_port");
-        var backupServerURLPref = document.getElementById("network.proxy.backup." + proxyPrefs[i]);
-        var backupPortPref = document.getElementById("network.proxy.backup." + proxyPrefs[i] + "_port");
+        var proxyServerURLPref = Preferences.get("network.proxy." + proxyPrefs[i]);
+        var proxyPortPref = Preferences.get("network.proxy." + proxyPrefs[i] + "_port");
+        var backupServerURLPref = Preferences.get("network.proxy.backup." + proxyPrefs[i]);
+        var backupPortPref = Preferences.get("network.proxy.backup." + proxyPrefs[i] + "_port");
         backupServerURLPref.value = backupServerURLPref.value || proxyServerURLPref.value;
         backupPortPref.value = backupPortPref.value || proxyPortPref.value;
         proxyServerURLPref.value = httpProxyURLPref.value;
         proxyPortPref.value = httpProxyPortPref.value;
       }
     }
 
     this.sanitizeNoProxiesPref();
@@ -54,145 +87,145 @@ var gConnectionsDialog = {
   },
 
   checkForSystemProxy() {
     if ("@mozilla.org/system-proxy-settings;1" in Components.classes)
       document.getElementById("systemPref").removeAttribute("hidden");
   },
 
   proxyTypeChanged() {
-    var proxyTypePref = document.getElementById("network.proxy.type");
+    var proxyTypePref = Preferences.get("network.proxy.type");
 
     // Update http
-    var httpProxyURLPref = document.getElementById("network.proxy.http");
+    var httpProxyURLPref = Preferences.get("network.proxy.http");
     httpProxyURLPref.disabled = proxyTypePref.value != 1;
-    var httpProxyPortPref = document.getElementById("network.proxy.http_port");
+    var httpProxyPortPref = Preferences.get("network.proxy.http_port");
     httpProxyPortPref.disabled = proxyTypePref.value != 1;
 
     // Now update the other protocols
     this.updateProtocolPrefs();
 
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
     shareProxiesPref.disabled = proxyTypePref.value != 1;
-    var autologinProxyPref = document.getElementById("signon.autologin.proxy");
+    var autologinProxyPref = Preferences.get("signon.autologin.proxy");
     autologinProxyPref.disabled = proxyTypePref.value == 0;
-    var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
+    var noProxiesPref = Preferences.get("network.proxy.no_proxies_on");
     noProxiesPref.disabled = proxyTypePref.value != 1;
 
-    var autoconfigURLPref = document.getElementById("network.proxy.autoconfig_url");
+    var autoconfigURLPref = Preferences.get("network.proxy.autoconfig_url");
     autoconfigURLPref.disabled = proxyTypePref.value != 2;
 
     this.updateReloadButton();
   },
 
   updateDNSPref() {
-    var socksVersionPref = document.getElementById("network.proxy.socks_version");
-    var socksDNSPref = document.getElementById("network.proxy.socks_remote_dns");
-    var proxyTypePref = document.getElementById("network.proxy.type");
+    var socksVersionPref = Preferences.get("network.proxy.socks_version");
+    var socksDNSPref = Preferences.get("network.proxy.socks_remote_dns");
+    var proxyTypePref = Preferences.get("network.proxy.type");
     var isDefinitelySocks4 = !socksVersionPref.disabled && socksVersionPref.value == 4;
     socksDNSPref.disabled = (isDefinitelySocks4 || proxyTypePref.value == 0);
     return undefined;
   },
 
   updateReloadButton() {
     // Disable the "Reload PAC" button if the selected proxy type is not PAC or
     // if the current value of the PAC textbox does not match the value stored
     // in prefs.  Likewise, disable the reload button if PAC is not configured
     // in prefs.
 
     var typedURL = document.getElementById("networkProxyAutoconfigURL").value;
-    var proxyTypeCur = document.getElementById("network.proxy.type").value;
+    var proxyTypeCur = Preferences.get("network.proxy.type").value;
 
     var pacURL = Services.prefs.getCharPref("network.proxy.autoconfig_url");
     var proxyType = Services.prefs.getIntPref("network.proxy.type");
 
     var disableReloadPref =
-        document.getElementById("pref.advanced.proxies.disable_button.reload");
+        Preferences.get("pref.advanced.proxies.disable_button.reload");
     disableReloadPref.disabled =
         (proxyTypeCur != 2 || proxyType != 2 || typedURL != pacURL);
   },
 
   readProxyType() {
     this.proxyTypeChanged();
     return undefined;
   },
 
   updateProtocolPrefs() {
-    var proxyTypePref = document.getElementById("network.proxy.type");
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var proxyTypePref = Preferences.get("network.proxy.type");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
     var proxyPrefs = ["ssl", "ftp", "socks"];
     for (var i = 0; i < proxyPrefs.length; ++i) {
-      var proxyServerURLPref = document.getElementById("network.proxy." + proxyPrefs[i]);
-      var proxyPortPref = document.getElementById("network.proxy." + proxyPrefs[i] + "_port");
+      var proxyServerURLPref = Preferences.get("network.proxy." + proxyPrefs[i]);
+      var proxyPortPref = Preferences.get("network.proxy." + proxyPrefs[i] + "_port");
 
       // Restore previous per-proxy custom settings, if present.
       if (!shareProxiesPref.value) {
-        var backupServerURLPref = document.getElementById("network.proxy.backup." + proxyPrefs[i]);
-        var backupPortPref = document.getElementById("network.proxy.backup." + proxyPrefs[i] + "_port");
+        var backupServerURLPref = Preferences.get("network.proxy.backup." + proxyPrefs[i]);
+        var backupPortPref = Preferences.get("network.proxy.backup." + proxyPrefs[i] + "_port");
         if (backupServerURLPref.hasUserValue) {
           proxyServerURLPref.value = backupServerURLPref.value;
           backupServerURLPref.reset();
         }
         if (backupPortPref.hasUserValue) {
           proxyPortPref.value = backupPortPref.value;
           backupPortPref.reset();
         }
       }
 
       proxyServerURLPref.updateElements();
       proxyPortPref.updateElements();
       proxyServerURLPref.disabled = proxyTypePref.value != 1 || shareProxiesPref.value;
       proxyPortPref.disabled = proxyServerURLPref.disabled;
     }
-    var socksVersionPref = document.getElementById("network.proxy.socks_version");
+    var socksVersionPref = Preferences.get("network.proxy.socks_version");
     socksVersionPref.disabled = proxyTypePref.value != 1 || shareProxiesPref.value;
     this.updateDNSPref();
     return undefined;
   },
 
   readProxyProtocolPref(aProtocol, aIsPort) {
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
     if (shareProxiesPref.value) {
-      var pref = document.getElementById("network.proxy.http" + (aIsPort ? "_port" : ""));
+      var pref = Preferences.get("network.proxy.http" + (aIsPort ? "_port" : ""));
       return pref.value;
     }
 
-    var backupPref = document.getElementById("network.proxy.backup." + aProtocol + (aIsPort ? "_port" : ""));
+    var backupPref = Preferences.get("network.proxy.backup." + aProtocol + (aIsPort ? "_port" : ""));
     return backupPref.hasUserValue ? backupPref.value : undefined;
   },
 
   reloadPAC() {
     Components.classes["@mozilla.org/network/protocol-proxy-service;1"].
         getService().reloadPAC();
   },
 
   doAutoconfigURLFixup() {
     var autoURL = document.getElementById("networkProxyAutoconfigURL");
-    var autoURLPref = document.getElementById("network.proxy.autoconfig_url");
+    var autoURLPref = Preferences.get("network.proxy.autoconfig_url");
     try {
       autoURLPref.value = autoURL.value =
         Services.uriFixup.createFixupURI(autoURL.value, 0).spec;
     } catch (ex) {}
   },
 
   sanitizeNoProxiesPref() {
-    var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
+    var noProxiesPref = Preferences.get("network.proxy.no_proxies_on");
     // replace substrings of ; and \n with commas if they're neither immediately
     // preceded nor followed by a valid separator character
     noProxiesPref.value = noProxiesPref.value.replace(/([^, \n;])[;\n]+(?![,\n;])/g, "$1,");
     // replace any remaining ; and \n since some may follow commas, etc.
     noProxiesPref.value = noProxiesPref.value.replace(/[;\n]/g, "");
   },
 
   readHTTPProxyServer() {
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
     if (shareProxiesPref.value)
       this.updateProtocolPrefs();
     return undefined;
   },
 
   readHTTPProxyPort() {
-    var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
+    var shareProxiesPref = Preferences.get("network.proxy.share_proxy_settings");
     if (shareProxiesPref.value)
       this.updateProtocolPrefs();
     return undefined;
   }
 };
--- a/browser/components/preferences/connection.xul
+++ b/browser/components/preferences/connection.xul
@@ -1,73 +1,54 @@
 <?xml version="1.0"?>
 
 <!-- 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/. -->
 
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/connection.dtd">
+<!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  %preferencesDTD;
+  <!ENTITY % connectionDTD SYSTEM "chrome://browser/locale/preferences/connection.dtd">
+  %connectionDTD;
+]>
 
 <?xml-stylesheet href="chrome://global/skin/"?>
+<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
 
-<prefwindow id="ConnectionsDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="&connectionsDialog.title;"
-            dlgbuttons="accept,cancel,help"
-            onbeforeaccept="return gConnectionsDialog.beforeAccept();"
-            onload="gConnectionsDialog.checkForSystemProxy();"
-            ondialoghelp="openPrefsHelp()"
+<dialog id="ConnectionsDialog" type="child" class="prefwindow"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="&connectionsDialog.title;"
+        buttons="accept,cancel,help"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        onbeforeaccept="return gConnectionsDialog.beforeAccept();"
+        onload="gConnectionsDialog.checkForSystemProxy();"
+        helpTopic="prefs-connection-settings"
+        ondialoghelp="openPrefsHelp()"
+
 #ifdef XP_MACOSX
-            style="width: &window.macWidth2; !important;">
+        style="width: &window.macWidth2; !important;">
 #else
-            style="width: &window.width2; !important;">
+        style="width: &window.width2; !important;">
 #endif
 
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
-  <prefpane id="ConnectionsDialogPane"
-            class="largeDialogContainer"
-            helpTopic="prefs-connection-settings">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
 
-    <preferences>
-      <preference id="network.proxy.type"         name="network.proxy.type"         type="int" onchange="gConnectionsDialog.proxyTypeChanged();"/>
-      <preference id="network.proxy.http"         name="network.proxy.http"         type="string"/>
-      <preference id="network.proxy.http_port"    name="network.proxy.http_port"    type="int"/>
-      <preference id="network.proxy.ftp"          name="network.proxy.ftp"          type="string"/>
-      <preference id="network.proxy.ftp_port"     name="network.proxy.ftp_port"     type="int"/>
-      <preference id="network.proxy.ssl"          name="network.proxy.ssl"          type="string"/>
-      <preference id="network.proxy.ssl_port"     name="network.proxy.ssl_port"     type="int"/>
-      <preference id="network.proxy.socks"        name="network.proxy.socks"        type="string"/>
-      <preference id="network.proxy.socks_port"   name="network.proxy.socks_port"   type="int"/>
-      <preference id="network.proxy.socks_version"  name="network.proxy.socks_version"  type="int" onchange="gConnectionsDialog.updateDNSPref();"/>
-      <preference id="network.proxy.socks_remote_dns"  name="network.proxy.socks_remote_dns"  type="bool"/>
-      <preference id="network.proxy.no_proxies_on"  name="network.proxy.no_proxies_on"  type="string"/>
-      <preference id="network.proxy.autoconfig_url" name="network.proxy.autoconfig_url" type="string"/>
-      <preference id="network.proxy.share_proxy_settings"
-                  name="network.proxy.share_proxy_settings"
-                  type="bool"/>
-      <preference id="signon.autologin.proxy"
-                  name="signon.autologin.proxy"
-                  type="bool"/>
+  <keyset>
+    <key key="&windowClose.key;" modifiers="accel" oncommand="Preferences.close(event)"/>
+  </keyset>
 
-      <preference id="pref.advanced.proxies.disable_button.reload"
-                  name="pref.advanced.proxies.disable_button.reload"
-                  type="bool"/>
-
-      <preference id="network.proxy.backup.ftp"          name="network.proxy.backup.ftp"          type="string"/>
-      <preference id="network.proxy.backup.ftp_port"     name="network.proxy.backup.ftp_port"     type="int"/>
-      <preference id="network.proxy.backup.ssl"          name="network.proxy.backup.ssl"          type="string"/>
-      <preference id="network.proxy.backup.ssl_port"     name="network.proxy.backup.ssl_port"     type="int"/>
-      <preference id="network.proxy.backup.socks"        name="network.proxy.backup.socks"        type="string"/>
-      <preference id="network.proxy.backup.socks_port"   name="network.proxy.backup.socks_port"   type="int"/>
-    </preferences>
-
-    <script type="application/javascript" src="chrome://browser/content/preferences/connection.js"/>
+  <vbox id="ConnectionsDialogPane" class="prefpane largeDialogContainer">
 
     <stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
+    <script type="application/javascript" src="chrome://browser/content/preferences/connection.js"/>
 
     <groupbox>
       <caption><label>&proxyTitle.label;</label></caption>
 
       <radiogroup id="networkProxyType" preference="network.proxy.type"
                   onsyncfrompreference="return gConnectionsDialog.readProxyType();">
         <radio value="0" label="&noProxyTypeRadio.label;" accesskey="&noProxyTypeRadio.accesskey;"/>
         <radio value="4" label="&WPADTypeRadio.label;" accesskey="&WPADTypeRadio.accesskey;"/>
@@ -164,10 +145,10 @@
     <separator class="thin"/>
     <checkbox id="autologinProxy"
               label="&autologinproxy.label;"
               accesskey="&autologinproxy.accesskey;"
               preference="signon.autologin.proxy"
               tooltiptext="&autologinproxy.tooltip;"/>
     <checkbox id="networkProxySOCKSRemoteDNS"  preference="network.proxy.socks_remote_dns" label="&socksRemoteDNS.label2;" accesskey="&socksRemoteDNS.accesskey;" />
     <separator/>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/browser/components/preferences/fonts.js
+++ b/browser/components/preferences/fonts.js
@@ -13,16 +13,22 @@ const kFontNameFmtSansSerif     = "font.
 const kFontNameFmtMonospace     = "font.name.monospace.%LANG%";
 const kFontNameListFmtSerif     = "font.name-list.serif.%LANG%";
 const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%";
 const kFontNameListFmtMonospace = "font.name-list.monospace.%LANG%";
 const kFontSizeFmtVariable      = "font.size.variable.%LANG%";
 const kFontSizeFmtFixed         = "font.size.fixed.%LANG%";
 const kFontMinSizeFmt           = "font.minimum-size.%LANG%";
 
+Preferences.addAll([
+  { id: "font.language.group", type: "wstring" },
+  { id: "browser.display.use_document_fonts", type: "int" },
+  { id: "intl.charset.fallback.override", type: "string" },
+]);
+
 var gFontsDialog = {
   _selectLanguageGroupPromise: Promise.resolve(),
 
   _selectLanguageGroup(aLanguageGroup) {
     this._selectLanguageGroupPromise = (async () => {
       // Avoid overlapping language group selections by awaiting the resolution
       // of the previous one.  We do this because this function is re-entrant,
       // as inserting <preference> elements into the DOM sometimes triggers a call
@@ -39,26 +45,21 @@ var gFontsDialog = {
         { format: kFontNameFmtMonospace,     type: "fontname", element: "monospace",  fonttype: "monospace"   },
         { format: kFontNameListFmtSerif,     type: "unichar",  element: null,         fonttype: "serif"       },
         { format: kFontNameListFmtSansSerif, type: "unichar",  element: null,         fonttype: "sans-serif"  },
         { format: kFontNameListFmtMonospace, type: "unichar",  element: null,         fonttype: "monospace"   },
         { format: kFontSizeFmtVariable,      type: "int",      element: "sizeVar",    fonttype: null          },
         { format: kFontSizeFmtFixed,         type: "int",      element: "sizeMono",   fonttype: null          },
         { format: kFontMinSizeFmt,           type: "int",      element: "minSize",    fonttype: null          }
       ];
-      var preferences = document.getElementById("fontPreferences");
       for (var i = 0; i < prefs.length; ++i) {
-        var preference = document.getElementById(prefs[i].format.replace(/%LANG%/, aLanguageGroup));
+        var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
+        var preference = Preferences.get(name);
         if (!preference) {
-          preference = document.createElement("preference");
-          var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
-          preference.id = name;
-          preference.setAttribute("name", name);
-          preference.setAttribute("type", prefs[i].type);
-          preferences.appendChild(preference);
+          preference = Preferences.add({ id: name, type: prefs[i].type });
         }
 
         if (!prefs[i].element)
           continue;
 
         var element = document.getElementById(prefs[i].element);
         if (element) {
           element.setAttribute("preference", preference.id);
@@ -69,39 +70,38 @@ var gFontsDialog = {
           preference.setElementValue(element);
         }
       }
     })()
       .catch(Components.utils.reportError);
   },
 
   readFontLanguageGroup() {
-    var languagePref = document.getElementById("font.language.group");
+    var languagePref = Preferences.get("font.language.group");
     this._selectLanguageGroup(languagePref.value);
     return undefined;
   },
 
   readUseDocumentFonts() {
-    var preference = document.getElementById("browser.display.use_document_fonts");
+    var preference = Preferences.get("browser.display.use_document_fonts");
     return preference.value == 1;
   },
 
   writeUseDocumentFonts() {
     var useDocumentFonts = document.getElementById("useDocumentFonts");
     return useDocumentFonts.checked ? 1 : 0;
   },
 
   onBeforeAccept() {
-    let preferences = document.querySelectorAll("preference[id*='font.minimum-size']");
     // It would be good if we could avoid touching languages the pref pages won't use, but
     // unfortunately the language group APIs (deducing language groups from language codes)
     // are C++ - only. So we just check all the things the user touched:
     // Don't care about anything up to 24px, or if this value is the same as set previously:
-    preferences = Array.filter(preferences, prefEl => {
-      return prefEl.value > 24 && prefEl.value != prefEl.valueFromPreferences;
+    let preferences = Preferences.getAll().filter(pref => {
+      return pref.id.includes("font.minimum-size") && pref.value > 24 && pref.value != pref.valueFromPreferences;
     });
     if (!preferences.length) {
       return true;
     }
 
     let strings = document.getElementById("bundlePreferences");
     let title = strings.getString("veryLargeMinimumFontTitle");
     let confirmLabel = strings.getString("acceptVeryLargeMinimumFont");
--- a/browser/components/preferences/fonts.xul
+++ b/browser/components/preferences/fonts.xul
@@ -1,43 +1,45 @@
 <?xml version="1.0"?>
 
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# 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/.
+<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
+<!-- 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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-#ifdef XP_MACOSX
 <?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
 
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/fonts.dtd" >
+<!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  %preferencesDTD;
+  <!ENTITY % fontsDTD SYSTEM "chrome://browser/locale/preferences/fonts.dtd">
+  %fontsDTD;
+]>
 
-<prefwindow id="FontsDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="&fontsDialog.title;"
-            dlgbuttons="accept,cancel,help"
-            ondialoghelp="openPrefsHelp()"
-            onbeforeaccept="return gFontsDialog.onBeforeAccept();"
-            style="">
+<dialog id="FontsDialog" type="child" class="prefwindow"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="&fontsDialog.title;"
+        buttons="accept,cancel,help"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        helpTopic="prefs-fonts-and-colors"
+        ondialoghelp="openPrefsHelp()"
+        onbeforeaccept="return gFontsDialog.onBeforeAccept();">
 
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
-  <prefpane id="FontsDialogPane"
-            class="largeDialogContainer"
-            helpTopic="prefs-fonts-and-colors">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
 
-    <preferences id="fontPreferences">
-      <preference id="font.language.group"  name="font.language.group"  type="wstring"/>
-      <preference id="browser.display.use_document_fonts"
-                  name="browser.display.use_document_fonts"
-                  type="int"/>
-      <preference id="intl.charset.fallback.override" name="intl.charset.fallback.override" type="string"/>
-    </preferences>
+  <keyset>
+    <key key="&windowClose.key;" modifiers="accel" oncommand="Preferences.close(event)"/>
+  </keyset>
+
+  <vbox id="FontsDialogPane" class="prefpane largeDialogContainer">
 
     <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
     <script type="application/javascript" src="chrome://mozapps/content/preferences/fontbuilder.js"/>
     <script type="application/javascript" src="chrome://browser/content/preferences/fonts.js"/>
 
     <!-- Fonts for: [ Language ] -->
     <groupbox>
       <caption>
@@ -292,10 +294,10 @@
               <menuitem label="&languages.customize.Fallback.turkish;"     value="windows-1254"/>
               <menuitem label="&languages.customize.Fallback.vietnamese;"  value="windows-1258"/>
               <menuitem label="&languages.customize.Fallback.other;"       value="windows-1252"/>
             </menupopup>
           </menulist>
         </hbox>
       </hbox>
     </groupbox>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/browser/components/preferences/in-content/containers.xul
+++ b/browser/components/preferences/in-content/containers.xul
@@ -2,24 +2,16 @@
 # 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/.
 
 <!-- Containers panel -->
 
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content/containers.js"/>
 
-<preferences id="containerPreferences" hidden="true" data-category="paneContainer">
-  <!-- Containers -->
-  <preference id="privacy.userContext.enabled"
-              name="privacy.userContext.enabled"
-              type="bool"/>
-
-</preferences>
-
 <hbox hidden="true"
       class="container-header-links"
       data-category="paneContainers">
   <label class="text-link" id="backContainersLink">&backLink2.label;</label>
 </hbox>
 
 <hbox id="header-containers"
       class="header"
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -98,16 +98,154 @@ const APP_ICON_ATTR_NAME = "appHandlerIc
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
   "resource://gre/modules/osfile.jsm");
 
 if (AppConstants.MOZ_DEV_EDITION) {
   XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
     "resource://gre/modules/FxAccounts.jsm");
 }
 
+Preferences.addAll([
+  // Startup
+  { id: "browser.startup.page", type: "int" },
+  { id: "browser.startup.homepage", type: "wstring" },
+
+  { id: "pref.browser.homepage.disable_button.current_page", type: "bool" },
+  { id: "pref.browser.homepage.disable_button.bookmark_page", type: "bool" },
+  { id: "pref.browser.homepage.disable_button.restore_default", type: "bool" },
+
+  { id: "browser.privatebrowsing.autostart", type: "bool" },
+
+  // Downloads
+  { id: "browser.download.useDownloadDir", type: "bool" },
+  { id: "browser.download.folderList", type: "int" },
+  { id: "browser.download.dir", type: "file" },
+
+  /* Tab preferences
+  Preferences:
+
+  browser.link.open_newwindow
+      1 opens such links in the most recent window or tab,
+      2 opens such links in a new window,
+      3 opens such links in a new tab
+  browser.tabs.loadInBackground
+  - true if display should switch to a new tab which has been opened from a
+    link, false if display shouldn't switch
+  browser.tabs.warnOnClose
+  - true if when closing a window with multiple tabs the user is warned and
+    allowed to cancel the action, false to just close the window
+  browser.tabs.warnOnOpen
+  - true if the user should be warned if he attempts to open a lot of tabs at
+    once (e.g. a large folder of bookmarks), false otherwise
+  browser.taskbar.previews.enable
+  - true if tabs are to be shown in the Windows 7 taskbar
+  */
+
+  { id: "browser.link.open_newwindow", type: "int" },
+  { id: "browser.tabs.loadInBackground", type: "bool", inverted: true },
+  { id: "browser.tabs.warnOnClose", type: "bool" },
+  { id: "browser.tabs.warnOnOpen", type: "bool" },
+  { id: "browser.sessionstore.restore_on_demand", type: "bool" },
+  { id: "browser.ctrlTab.previews", type: "bool" },
+
+  // Fonts
+  { id: "font.language.group", type: "wstring" },
+
+  // Languages
+  { id: "browser.translation.detectLanguage", type: "bool" },
+
+  // General tab
+
+  /* Accessibility
+   * accessibility.browsewithcaret
+     - true enables keyboard navigation and selection within web pages using a
+       visible caret, false uses normal keyboard navigation with no caret
+   * accessibility.typeaheadfind
+     - when set to true, typing outside text areas and input boxes will
+       automatically start searching for what's typed within the current
+       document; when set to false, no search action happens */
+  { id: "accessibility.browsewithcaret", type: "bool" },
+  { id: "accessibility.typeaheadfind", type: "bool" },
+  { id: "accessibility.blockautorefresh", type: "bool" },
+
+  /* Browsing
+   * general.autoScroll
+     - when set to true, clicking the scroll wheel on the mouse activates a
+       mouse mode where moving the mouse down scrolls the document downward with
+       speed correlated with the distance of the cursor from the original
+       position at which the click occurred (and likewise with movement upward);
+       if false, this behavior is disabled
+   * general.smoothScroll
+     - set to true to enable finer page scrolling than line-by-line on page-up,
+       page-down, and other such page movements */
+  { id: "general.autoScroll", type: "bool" },
+  { id: "general.smoothScroll", type: "bool" },
+  { id: "layout.spellcheckDefault", type: "int" },
+
+  { id: "browser.preferences.defaultPerformanceSettings.enabled", type: "bool" },
+  { id: "dom.ipc.processCount", type: "int" },
+  { id: "dom.ipc.processCount.web", type: "int" },
+  { id: "layers.acceleration.disabled", type: "bool", inverted: true },
+
+  // Files and Applications
+  { id: "browser.feeds.handler", type: "string" },
+  { id: "browser.feeds.handler.default", type: "string" },
+  { id: "browser.feeds.handlers.application", type: "file" },
+  { id: "browser.feeds.handlers.webservice", type: "string" },
+
+  { id: "browser.videoFeeds.handler", type: "string" },
+  { id: "browser.videoFeeds.handler.default", type: "string" },
+  { id: "browser.videoFeeds.handlers.application", type: "file" },
+  { id: "browser.videoFeeds.handlers.webservice", type: "string" },
+
+  { id: "browser.audioFeeds.handler", type: "string" },
+  { id: "browser.audioFeeds.handler.default", type: "string" },
+  { id: "browser.audioFeeds.handlers.application", type: "file" },
+  { id: "browser.audioFeeds.handlers.webservice", type: "string" },
+
+  { id: "pref.downloads.disable_button.edit_actions", type: "bool" },
+
+  // DRM content
+  { id: "media.eme.enabled", type: "bool" },
+
+  // Update
+  { id: "browser.preferences.advanced.selectedTabIndex", type: "int" },
+  { id: "browser.search.update", type: "bool" },
+
+  { id: "privacy.userContext.enabled", type: "bool" },
+]);
+
+if (AppConstants.HAVE_SHELL_SERVICE) {
+  Preferences.addAll([
+    { id: "browser.shell.checkDefaultBrowser", type: "bool" },
+    { id: "pref.general.disable_button.default_browser", type: "bool" },
+  ]);
+}
+
+if (AppConstants.platform === "win") {
+  Preferences.addAll([
+    { id: "browser.taskbar.previews.enable", type: "bool" },
+    { id: "ui.osk.enabled", type: "bool" },
+  ]);
+}
+
+if (AppConstants.MOZ_UPDATER) {
+  Preferences.addAll([
+    { id: "app.update.enabled", type: "bool" },
+    { id: "app.update.auto", type: "bool" },
+    { id: "app.update.disable_button.showUpdateHistory", type: "bool" },
+  ]);
+
+  if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
+    Preferences.addAll([
+      { id: "app.update.service.enabled", type: "bool" },
+    ]);
+  }
+}
+
 // A promise that resolves when the list of application handlers is loaded.
 // We store this in a global so tests can await it.
 var promiseLoadHandlersList;
 
 var gMainPane = {
   // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
   // objects, indexed by type.
   _handledTypes: {},
@@ -203,18 +341,18 @@ var gMainPane = {
 
     let performanceSettingsLink = document.getElementById("performanceSettingsLearnMore");
     let performanceSettingsUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "performance";
     performanceSettingsLink.setAttribute("href", performanceSettingsUrl);
 
     this.updateDefaultPerformanceSettingsPref();
 
     let defaultPerformancePref =
-      document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
-    defaultPerformancePref.addEventListener("change", () => {
+      Preferences.get("browser.preferences.defaultPerformanceSettings.enabled");
+    defaultPerformancePref.on("change", () => {
       this.updatePerformanceSettingsBox({ duringChangeEvent: true });
     });
     this.updatePerformanceSettingsBox({ duringChangeEvent: false });
 
     // set up the "use current page" label-changing listener
     this._updateUseCurrentButton();
     window.addEventListener("focus", this._updateUseCurrentButton.bind(this));
 
@@ -244,18 +382,18 @@ var gMainPane = {
     // &brandShortName;" warnings provide options for not showing these
     // warnings again. When the user disabled them, we provide checkboxes to
     // re-enable the warnings.
     if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnClose"))
       document.getElementById("warnCloseMultiple").hidden = true;
     if (!TransientPrefs.prefShouldBeVisible("browser.tabs.warnOnOpen"))
       document.getElementById("warnOpenMany").hidden = true;
 
-    setEventListener("browser.privatebrowsing.autostart", "change",
-      gMainPane.updateBrowserStartupLastSession);
+    Preferences.get("browser.privatebrowsing.autostart").on("change",
+      gMainPane.updateBrowserStartupLastSession.bind(gMainPane));
     if (AppConstants.HAVE_SHELL_SERVICE) {
       setEventListener("setDefaultButton", "command",
         gMainPane.setDefaultBrowser);
     }
     setEventListener("useCurrent", "command",
       gMainPane.setHomePageToCurrent);
     setEventListener("useBookmark", "command",
       gMainPane.setHomePageToBookmark);
@@ -268,24 +406,24 @@ var gMainPane = {
     setEventListener("disableNewTabExtension", "command",
                      makeDisableControllingExtension(URL_OVERRIDES_TYPE, NEW_TAB_KEY));
     setEventListener("chooseLanguage", "command",
       gMainPane.showLanguages);
     setEventListener("translationAttributionImage", "click",
       gMainPane.openTranslationProviderAttribution);
     setEventListener("translateButton", "command",
       gMainPane.showTranslationExceptions);
-    setEventListener("font.language.group", "change",
-      gMainPane._rebuildFonts);
+    Preferences.get("font.language.group").on("change",
+      gMainPane._rebuildFonts.bind(gMainPane));
     setEventListener("advancedFonts", "command",
       gMainPane.configureFonts);
     setEventListener("colors", "command",
       gMainPane.configureColors);
-    setEventListener("layers.acceleration.disabled", "change",
-      gMainPane.updateHardwareAcceleration);
+    Preferences.get("layers.acceleration.disabled").on("change",
+      gMainPane.updateHardwareAcceleration.bind(gMainPane));
     setEventListener("connectionSettings", "command",
       gMainPane.showConnections);
     setEventListener("browserContainersCheckbox", "command",
       gMainPane.checkBrowserContainers);
     setEventListener("browserContainersSettings", "command",
       gMainPane.showContainerSettings);
     setEventListener("browserHomePage", "input",
       gMainPane.onBrowserHomePageChange);
@@ -415,18 +553,18 @@ var gMainPane = {
     Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
 
     setEventListener("filter", "command", gMainPane.filter);
     setEventListener("handlersView", "select",
       gMainPane.onSelectionChanged);
     setEventListener("typeColumn", "click", gMainPane.sort);
     setEventListener("actionColumn", "click", gMainPane.sort);
     setEventListener("chooseFolder", "command", gMainPane.chooseFolder);
-    setEventListener("browser.download.dir", "change", gMainPane.displayDownloadDirPref);
-    setEventListener("saveWhere", "command", gMainPane.handleSaveToCommand);
+    Preferences.get("browser.download.dir").on("change",
+      gMainPane.displayDownloadDirPref.bind(gMainPane));
 
     // Listen for window unload so we can remove our preference observers.
     window.addEventListener("unload", this);
 
     // Figure out how we should be sorting the list.  We persist sort settings
     // across sessions, so we can't assume the default sort column/direction.
     // XXX should we be using the XUL sort service instead?
     if (document.getElementById("actionColumn").hasAttribute("sortDirection")) {
@@ -479,17 +617,17 @@ var gMainPane = {
    * privacy.userContext.enabled
    * - true if containers is enabled
    */
 
   /**
    * Enables/disables the Settings button used to configure containers
    */
   readBrowserContainersCheckbox() {
-    const pref = document.getElementById("privacy.userContext.enabled");
+    const pref = Preferences.get("privacy.userContext.enabled");
     const settings = document.getElementById("browserContainersSettings");
 
     settings.disabled = !pref.value;
     const containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
     const containersCheckbox = document.getElementById("browserContainersCheckbox");
     containersCheckbox.checked = containersEnabled;
     handleControllingExtension(PREF_SETTING_TYPE, CONTAINERS_KEY)
       .then((isControlled) => {
@@ -602,26 +740,26 @@ var gMainPane = {
    *     3: windows and tabs from the last session (a.k.a. session restore)
    *
    *   The deprecated option is not exposed in UI; however, if the user has it
    *   selected and doesn't change the UI for this preference, the deprecated
    *   option is preserved.
    */
 
   syncFromHomePref() {
-    let homePref = document.getElementById("browser.startup.homepage");
+    let homePref = Preferences.get("browser.startup.homepage");
 
     // Set the "Use Current Page(s)" button's text and enabled state.
     this._updateUseCurrentButton();
 
     function setInputDisabledStates(isControlled) {
       // Disable or enable the inputs based on if this is controlled by an extension.
       document.querySelectorAll("#browserHomePage, .homepage-button")
         .forEach((element) => {
-          let isLocked = document.getElementById(element.getAttribute("preference")).locked;
+          let isLocked = Preferences.get(element.getAttribute("preference")).locked;
           element.disabled = isLocked || isControlled;
         });
     }
 
     if (homePref.locked) {
       // An extension can't control these settings if they're locked.
       hideControllingExtension(HOMEPAGE_OVERRIDE_KEY);
       setInputDisabledStates(false);
@@ -663,17 +801,17 @@ var gMainPane = {
   },
 
   /**
    * Sets the home page to the current displayed page (or frontmost tab, if the
    * most recent browser window contains multiple tabs), updating preference
    * window UI to reflect this.
    */
   setHomePageToCurrent() {
-    let homePage = document.getElementById("browser.startup.homepage");
+    let homePage = Preferences.get("browser.startup.homepage");
     let tabs = this._getTabsForHomePage();
     function getTabURI(t) {
       return t.linkedBrowser.currentURI.spec;
     }
 
     // FIXME Bug 244192: using dangerous "|" joiner!
     if (tabs.length) {
       homePage.value = tabs.map(getTabURI).join("|");
@@ -710,17 +848,17 @@ var gMainPane = {
       }, 3000);
     }
   },
 
   _setHomePageToBookmarkClosed(rv, aEvent) {
     if (aEvent.detail.button != "accept")
       return;
     if (rv.urls && rv.names) {
-      var homePage = document.getElementById("browser.startup.homepage");
+      var homePage = Preferences.get("browser.startup.homepage");
 
       // XXX still using dangerous "|" joiner!
       homePage.value = rv.urls.join("|");
     }
   },
 
   /**
    * Switches the "Use Current Page" button between its singular and plural
@@ -738,17 +876,17 @@ var gMainPane = {
     // If the homepage is controlled by an extension then you can't use this.
     if (await getControllingExtensionInfo(PREF_SETTING_TYPE, HOMEPAGE_OVERRIDE_KEY)) {
       useCurrent.disabled = true;
       return;
     }
 
     // In this case, the button's disabled state is set by preferences.xml.
     let prefName = "pref.browser.homepage.disable_button.current_page";
-    if (document.getElementById(prefName).locked)
+    if (Preferences.get(prefName).locked)
       return;
 
     useCurrent.disabled = !tabs.length;
   },
 
   _getTabsForHomePage() {
     var win;
     var tabs = [];
@@ -773,38 +911,38 @@ var gMainPane = {
   isNotAboutPreferences(aElement, aIndex, aArray) {
     return !aElement.linkedBrowser.currentURI.spec.startsWith("about:preferences");
   },
 
   /**
    * Restores the default home page as the user's home page.
    */
   restoreDefaultHomePage() {
-    var homePage = document.getElementById("browser.startup.homepage");
+    var homePage = Preferences.get("browser.startup.homepage");
     homePage.value = homePage.defaultValue;
   },
 
   /**
    * Utility function to enable/disable the button specified by aButtonID based
    * on the value of the Boolean preference specified by aPreferenceID.
    */
   updateButtons(aButtonID, aPreferenceID) {
     var button = document.getElementById(aButtonID);
-    var preference = document.getElementById(aPreferenceID);
+    var preference = Preferences.get(aPreferenceID);
     button.disabled = preference.value != true;
     return undefined;
   },
 
   /**
    * Hide/show the "Show my windows and tabs from last time" option based
    * on the value of the browser.privatebrowsing.autostart pref.
    */
   updateBrowserStartupLastSession() {
-    let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
-    let startupPref = document.getElementById("browser.startup.page");
+    let pbAutoStartPref = Preferences.get("browser.privatebrowsing.autostart");
+    let startupPref = Preferences.get("browser.startup.page");
     let group = document.getElementById("browserStartupPage");
     let option = document.getElementById("browserStartupLastSession");
     if (pbAutoStartPref.value) {
       option.setAttribute("disabled", "true");
       if (option.selected) {
         group.selectedItem = document.getElementById("browserStartupHomePage");
       }
     } else {
@@ -839,17 +977,17 @@ var gMainPane = {
    */
 
   /**
    * Determines where a link which opens a new window will open.
    *
    * @returns |true| if such links should be opened in new tabs
    */
   readLinkTarget() {
-    var openNewWindow = document.getElementById("browser.link.open_newwindow");
+    var openNewWindow = Preferences.get("browser.link.open_newwindow");
     return openNewWindow.value != 2;
   },
 
   /**
    * Determines where a link which opens a new window will open.
    *
    * @returns 2 if such links should be opened in new windows,
    *          3 if such links should be opened in new tabs
@@ -887,17 +1025,17 @@ var gMainPane = {
     }
   },
 
   /**
    * Set browser as the operating system default browser.
    */
   setDefaultBrowser() {
     if (AppConstants.HAVE_SHELL_SERVICE) {
-      let alwaysCheckPref = document.getElementById("browser.shell.checkDefaultBrowser");
+      let alwaysCheckPref = Preferences.get("browser.shell.checkDefaultBrowser");
       alwaysCheckPref.value = true;
 
       // Reset exponential backoff delay time in order to do visual update in pollForDefaultBrowser.
       this._backoffIndex = 0;
 
       let shellSvc = getShellService();
       if (!shellSvc)
         return;
@@ -1019,41 +1157,32 @@ var gMainPane = {
   },
 
   // FONTS
 
   /**
    * Populates the default font list in UI.
    */
   _rebuildFonts() {
-    var preferences = document.getElementById("mainPreferences");
-    // Ensure preferences are "visible" to ensure bindings work.
-    preferences.hidden = false;
-    // Force flush:
-    preferences.clientHeight;
-    var langGroupPref = document.getElementById("font.language.group");
+    var langGroupPref = Preferences.get("font.language.group");
     var isSerif = this._readDefaultFontTypeForLanguage(langGroupPref.value) == "serif";
     this._selectDefaultLanguageGroup(langGroupPref.value, isSerif);
   },
 
   /**
    * Returns the type of the current default font for the language denoted by
    * aLanguageGroup.
    */
   _readDefaultFontTypeForLanguage(aLanguageGroup) {
     const kDefaultFontType = "font.default.%LANG%";
     var defaultFontTypePref = kDefaultFontType.replace(/%LANG%/, aLanguageGroup);
-    var preference = document.getElementById(defaultFontTypePref);
+    var preference = Preferences.get(defaultFontTypePref);
     if (!preference) {
-      preference = document.createElement("preference");
-      preference.id = defaultFontTypePref;
-      preference.setAttribute("name", defaultFontTypePref);
-      preference.setAttribute("type", "string");
-      preference.setAttribute("onchange", "gMainPane._rebuildFonts();");
-      document.getElementById("mainPreferences").appendChild(preference);
+      preference = Preferences.add({ id: defaultFontTypePref, type: "string" });
+      preference.on("change", gMainPane._rebuildFonts.bind(gMainPane));
     }
     return preference.value;
   },
 
   _selectDefaultLanguageGroupPromise: Promise.resolve(),
 
   _selectDefaultLanguageGroup(aLanguageGroup, aIsSerif) {
     this._selectDefaultLanguageGroupPromise = (async () => {
@@ -1067,17 +1196,16 @@ var gMainPane = {
       await this._selectDefaultLanguageGroupPromise;
 
       const kFontNameFmtSerif = "font.name.serif.%LANG%";
       const kFontNameFmtSansSerif = "font.name.sans-serif.%LANG%";
       const kFontNameListFmtSerif = "font.name-list.serif.%LANG%";
       const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%";
       const kFontSizeFmtVariable = "font.size.variable.%LANG%";
 
-      var preferences = document.getElementById("mainPreferences");
       var prefs = [{
         format: aIsSerif ? kFontNameFmtSerif : kFontNameFmtSansSerif,
         type: "fontname",
         element: "defaultFont",
         fonttype: aIsSerif ? "serif" : "sans-serif"
       },
       {
         format: aIsSerif ? kFontNameListFmtSerif : kFontNameListFmtSansSerif,
@@ -1087,24 +1215,20 @@ var gMainPane = {
       },
       {
         format: kFontSizeFmtVariable,
         type: "int",
         element: "defaultFontSize",
         fonttype: null
       }];
       for (var i = 0; i < prefs.length; ++i) {
-        var preference = document.getElementById(prefs[i].format.replace(/%LANG%/, aLanguageGroup));
+        var preference = Preferences.get(prefs[i].format.replace(/%LANG%/, aLanguageGroup));
         if (!preference) {
-          preference = document.createElement("preference");
           var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
-          preference.id = name;
-          preference.setAttribute("name", name);
-          preference.setAttribute("type", prefs[i].type);
-          preferences.appendChild(preference);
+          preference = Preferences.add({ id: name, type: prefs[i].type });
         }
 
         if (!prefs[i].element)
           continue;
 
         var element = document.getElementById(prefs[i].element);
         if (element) {
           element.setAttribute("preference", preference.id);
@@ -1132,17 +1256,17 @@ var gMainPane = {
    *
    * layout.spellcheckDefault
    * - an integer:
    *     0  disables spellchecking
    *     1  enables spellchecking, but only for multiline text fields
    *     2  enables spellchecking for all text fields
    */
   readCheckSpelling() {
-    var pref = document.getElementById("layout.spellcheckDefault");
+    var pref = Preferences.get("layout.spellcheckDefault");
     this._storedSpellCheck = pref.value;
 
     return (pref.value != 0);
   },
 
   /**
    * Returns the value of the spellchecking preference represented by UI,
    * preserving the preference's "hidden" value if the preference is
@@ -1156,44 +1280,44 @@ var gMainPane = {
       }
       return 1;
     }
     return 0;
   },
 
   updateDefaultPerformanceSettingsPref() {
     let defaultPerformancePref =
-      document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
-    let processCountPref = document.getElementById("dom.ipc.processCount");
-    let accelerationPref = document.getElementById("layers.acceleration.disabled");
+      Preferences.get("browser.preferences.defaultPerformanceSettings.enabled");
+    let processCountPref = Preferences.get("dom.ipc.processCount");
+    let accelerationPref = Preferences.get("layers.acceleration.disabled");
     if (processCountPref.value != processCountPref.defaultValue ||
       accelerationPref.value != accelerationPref.defaultValue) {
       defaultPerformancePref.value = false;
     }
   },
 
   updatePerformanceSettingsBox({ duringChangeEvent }) {
     let defaultPerformancePref =
-      document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
+      Preferences.get("browser.preferences.defaultPerformanceSettings.enabled");
     let performanceSettings = document.getElementById("performanceSettings");
-    let processCountPref = document.getElementById("dom.ipc.processCount");
+    let processCountPref = Preferences.get("dom.ipc.processCount");
     if (defaultPerformancePref.value) {
-      let accelerationPref = document.getElementById("layers.acceleration.disabled");
+      let accelerationPref = Preferences.get("layers.acceleration.disabled");
       // Unset the value so process count will be decided by the platform.
       processCountPref.value = processCountPref.defaultValue;
       accelerationPref.value = accelerationPref.defaultValue;
       performanceSettings.hidden = true;
     } else {
       performanceSettings.hidden = false;
     }
   },
 
   buildContentProcessCountMenuList() {
     if (Services.appinfo.browserTabsRemoteAutostart) {
-      let processCountPref = document.getElementById("dom.ipc.processCount");
+      let processCountPref = Preferences.get("dom.ipc.processCount");
       let defaultProcessCount = processCountPref.defaultValue;
       let bundlePreferences = document.getElementById("bundlePreferences");
 
       let contentProcessCount =
         document.querySelector(`#contentProcessCount > menupopup >
                                 menuitem[value="${defaultProcessCount}"]`);
 
       // New localization API experiment (October 2017).
@@ -1255,18 +1379,18 @@ var gMainPane = {
    * Element           pref  value  locked  disabled
    * radiogroup        i     t/f    f       false
    *                   i     t/f    *t*     *true*
    *                   ii    t/f    f       false
    *                   ii    t/f    *t*     *true*
    */
   updateReadPrefs() {
     if (AppConstants.MOZ_UPDATER) {
-      var enabledPref = document.getElementById("app.update.enabled");
-      var autoPref = document.getElementById("app.update.auto");
+      var enabledPref = Preferences.get("app.update.enabled");
+      var autoPref = Preferences.get("app.update.auto");
       var radiogroup = document.getElementById("updateRadioGroup");
 
       if (!enabledPref.value) // Don't care for autoPref.value in this case.
         radiogroup.value = "manual"; // 3. Never check for updates.
       else if (autoPref.value) // enabledPref.value && autoPref.value
         radiogroup.value = "auto"; // 1. Automatically install updates
       else // enabledPref.value && !autoPref.value
         radiogroup.value = "checkOnly"; // 2. Check, but let me choose
@@ -1300,18 +1424,18 @@ var gMainPane = {
     }
   },
 
   /**
    * Sets the pref values based on the selected item of the radiogroup.
    */
   updateWritePrefs() {
     if (AppConstants.MOZ_UPDATER) {
-      var enabledPref = document.getElementById("app.update.enabled");
-      var autoPref = document.getElementById("app.update.auto");
+      var enabledPref = Preferences.get("app.update.enabled");
+      var autoPref = Preferences.get("app.update.auto");
       var radiogroup = document.getElementById("updateRadioGroup");
       switch (radiogroup.value) {
         case "auto": // 1. Automatically install updates for Desktop only
           enabledPref.value = true;
           autoPref.value = true;
           break;
         case "checkOnly": // 2. Check, but let me choose
           enabledPref.value = true;
@@ -2365,17 +2489,17 @@ var gMainPane = {
 
   /**
    * Enables/disables the folder field and Browse button based on whether a
    * default download directory is being used.
    */
   readUseDownloadDir() {
     var downloadFolder = document.getElementById("downloadFolder");
     var chooseFolder = document.getElementById("chooseFolder");
-    var preference = document.getElementById("browser.download.useDownloadDir");
+    var preference = Preferences.get("browser.download.useDownloadDir");
     downloadFolder.disabled = !preference.value || preference.locked;
     chooseFolder.disabled = !preference.value || preference.locked;
 
     this.readCloudStorage().catch(Components.utils.reportError);
     // don't override the preference's value in UI
     return undefined;
   },
 
@@ -2393,18 +2517,18 @@ var gMainPane = {
     if (providerDisplayName) {
       // Show cloud storage radio button with provider name in label
       let saveToCloudRadio = document.getElementById("saveToCloud");
       let cloudStrings = Services.strings.createBundle("resource://cloudstorage/preferences.properties");
       saveToCloudRadio.label = cloudStrings.formatStringFromName("saveFilesToCloudStorage",
         [providerDisplayName], 1);
       saveToCloudRadio.hidden = false;
 
-      let useDownloadDirPref = document.getElementById("browser.download.useDownloadDir");
-      let folderListPref = document.getElementById("browser.download.folderList");
+      let useDownloadDirPref = Preferences.get("browser.download.useDownloadDir");
+      let folderListPref = Preferences.get("browser.download.folderList");
 
       // Check if useDownloadDir is true and folderListPref is set to Cloud Storage value 3
       // before selecting cloudStorageradio button. Disable folder field and Browse button if
       // 'Save to Cloud Storage Provider' radio option is selected
       if (useDownloadDirPref.value && folderListPref.value === 3) {
         document.getElementById("saveWhere").selectedItem = saveToCloudRadio;
         document.getElementById("downloadFolder").disabled = true;
         document.getElementById("chooseFolder").disabled = true;
@@ -2428,53 +2552,53 @@ var gMainPane = {
     // Check if Save To Cloud Storage Provider radio option is displayed in UI
     // before continuing.
     let saveToCloudRadio = document.getElementById("saveToCloud");
     if (!saveToCloudRadio.hidden) {
       // When switching between SaveTo and SaveToCloud radio button
       // with useDownloadDirPref value true, if selectedIndex is other than
       // SaveTo radio button disable downloadFolder filefield and chooseFolder button
       let saveWhere = document.getElementById("saveWhere");
-      let useDownloadDirPref = document.getElementById("browser.download.useDownloadDir");
+      let useDownloadDirPref = Preferences.get("browser.download.useDownloadDir");
       if (useDownloadDirPref.value) {
         let downloadFolder = document.getElementById("downloadFolder");
         let chooseFolder = document.getElementById("chooseFolder");
         downloadFolder.disabled = saveWhere.selectedIndex || useDownloadDirPref.locked;
         chooseFolder.disabled = saveWhere.selectedIndex || useDownloadDirPref.locked;
       }
 
       // Set folderListPref value depending on radio option
       // selected. folderListPref should be set to 3 if Save To Cloud Storage Provider
       // option is selected. If user switch back to 'Save To' custom path or system
       // default Downloads, check pref 'browser.download.dir' before setting respective
       // folderListPref value. If currentDirPref is unspecified folderList should
       // default to 1
-      let folderListPref = document.getElementById("browser.download.folderList");
+      let folderListPref = Preferences.get("browser.download.folderList");
       let saveTo = document.getElementById("saveTo");
       if (saveWhere.selectedItem == saveToCloudRadio) {
         folderListPref.value = 3;
       } else if (saveWhere.selectedItem == saveTo) {
-        let currentDirPref = document.getElementById("browser.download.dir");
+        let currentDirPref = Preferences.get("browser.download.dir");
         folderListPref.value = currentDirPref.value ? await this._folderToIndex(currentDirPref.value) : 1;
       }
     }
   },
 
   /**
    * Displays a file picker in which the user can choose the location where
    * downloads are automatically saved, updating preferences and UI in
    * response to the choice, if one is made.
    */
   chooseFolder() {
     return this.chooseFolderTask().catch(Components.utils.reportError);
   },
   async chooseFolderTask() {
     let bundlePreferences = document.getElementById("bundlePreferences");
     let title = bundlePreferences.getString("chooseDownloadFolderTitle");
-    let folderListPref = document.getElementById("browser.download.folderList");
+    let folderListPref = Preferences.get("browser.download.folderList");
     let currentDirPref = await this._indexToFolder(folderListPref.value);
     let defDownloads = await this._indexToFolder(1);
     let fp = Components.classes["@mozilla.org/filepicker;1"].
       createInstance(Components.interfaces.nsIFilePicker);
 
     fp.init(window, title, Components.interfaces.nsIFilePicker.modeGetFolder);
     fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
     // First try to open what's currently configured
@@ -2488,17 +2612,17 @@ var gMainPane = {
       fp.displayDirectory = await this._indexToFolder(0);
     }
 
     let result = await new Promise(resolve => fp.open(resolve));
     if (result != Components.interfaces.nsIFilePicker.returnOK) {
       return;
     }
 
-    let downloadDirPref = document.getElementById("browser.download.dir");
+    let downloadDirPref = Preferences.get("browser.download.dir");
     downloadDirPref.value = fp.file;
     folderListPref.value = await this._folderToIndex(fp.file);
     // Note, the real prefs will not be updated yet, so dnld manager's
     // userDownloadsDirectory may not return the right folder after
     // this code executes. displayDownloadDirPref will be called on
     // the assignment above to update the UI.
   },
 
@@ -2509,20 +2633,20 @@ var gMainPane = {
   displayDownloadDirPref() {
     this.displayDownloadDirPrefTask().catch(Components.utils.reportError);
 
     // don't override the preference's value in UI
     return undefined;
   },
 
   async displayDownloadDirPrefTask() {
-    var folderListPref = document.getElementById("browser.download.folderList");
+    var folderListPref = Preferences.get("browser.download.folderList");
     var bundlePreferences = document.getElementById("bundlePreferences");
     var downloadFolder = document.getElementById("downloadFolder");
-    var currentDirPref = document.getElementById("browser.download.dir");
+    var currentDirPref = Preferences.get("browser.download.dir");
 
     // Used in defining the correct path to the folder icon.
     var fph = Services.io.getProtocolHandler("file")
       .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
     var iconUrlSpec;
 
     let folderIndex = folderListPref.value;
     if (folderIndex == 3) {
@@ -2608,17 +2732,17 @@ var gMainPane = {
    */
   _indexToFolder(aIndex) {
     switch (aIndex) {
       case 0:
         return this._getDownloadsFolder("Desktop");
       case 1:
         return this._getDownloadsFolder("Downloads");
     }
-    var currentDirPref = document.getElementById("browser.download.dir");
+    var currentDirPref = Preferences.get("browser.download.dir");
     return currentDirPref.value;
   }
 };
 
 // Utilities
 
 function getFileDisplayName(file) {
   if (AppConstants.platform == "win") {
@@ -3011,46 +3135,46 @@ FeedHandlerInfo.prototype = {
 
   // nsIHandlerInfo
 
   get description() {
     return this.element("bundlePreferences").getString(this._appPrefLabel);
   },
 
   get preferredApplicationHandler() {
-    switch (this.element(this._prefSelectedReader).value) {
+    switch (Preferences.get(this._prefSelectedReader).value) {
       case "client":
-        var file = this.element(this._prefSelectedApp).value;
+        var file = Preferences.get(this._prefSelectedApp).value;
         if (file)
           return getLocalHandlerApp(file);
 
         return null;
 
       case "web":
-        var uri = this.element(this._prefSelectedWeb).value;
+        var uri = Preferences.get(this._prefSelectedWeb).value;
         if (!uri)
           return null;
         return this._converterSvc.getWebContentHandlerByURI(this.type, uri);
 
       case "bookmarks":
       default:
         // When the pref is set to bookmarks, we handle feeds internally,
         // we don't forward them to a local or web handler app, so there is
         // no preferred handler.
         return null;
     }
   },
 
   set preferredApplicationHandler(aNewValue) {
     if (aNewValue instanceof Ci.nsILocalHandlerApp) {
-      this.element(this._prefSelectedApp).value = aNewValue.executable;
-      this.element(this._prefSelectedReader).value = "client";
+      Preferences.get(this._prefSelectedApp).value = aNewValue.executable;
+      Preferences.get(this._prefSelectedReader).value = "client";
     } else if (aNewValue instanceof Ci.nsIWebContentHandlerInfo) {
-      this.element(this._prefSelectedWeb).value = aNewValue.uri;
-      this.element(this._prefSelectedReader).value = "web";
+      Preferences.get(this._prefSelectedWeb).value = aNewValue.uri;
+      Preferences.get(this._prefSelectedReader).value = "web";
       // Make the web handler be the new "auto handler" for feeds.
       // Note: we don't have to unregister the auto handler when the user picks
       // a non-web handler (local app, Live Bookmarks, etc.) because the service
       // only uses the "auto handler" when the selected reader is a web handler.
       // We also don't have to unregister it when the user turns on "always ask"
       // (i.e. preview in browser), since that also overrides the auto handler.
       this._converterSvc.setAutoHandler(this.type, aNewValue);
     }
@@ -3100,17 +3224,17 @@ FeedHandlerInfo.prototype = {
     };
 
     // Add the selected local app if it's different from the OS default handler.
     // Unlike for other types, we can store only one local app at a time for the
     // feed type, since we store it in a preference that historically stores
     // only a single path.  But we display all the local apps the user chooses
     // while the prefpane is open, only dropping the list when the user closes
     // the prefpane, for maximum usability and consistency with other types.
-    var preferredAppFile = this.element(this._prefSelectedApp).value;
+    var preferredAppFile = Preferences.get(this._prefSelectedApp).value;
     if (preferredAppFile) {
       let preferredApp = getLocalHandlerApp(preferredAppFile);
       let defaultApp = this._defaultApplicationHandler;
       if (!defaultApp || !defaultApp.equals(preferredApp))
         this._possibleApplicationHandlers.appendElement(preferredApp);
     }
 
     // Add the registered web handlers.  There can be any number of these.
@@ -3168,17 +3292,17 @@ FeedHandlerInfo.prototype = {
       return this._defaultApplicationHandler.name;
 
     // Should we instead return null?
     return "";
   },
 
   // What to do with content of this type.
   get preferredAction() {
-    switch (this.element(this._prefSelectedAction).value) {
+    switch (Preferences.get(this._prefSelectedAction).value) {
 
       case "bookmarks":
         return Ci.nsIHandlerInfo.handleInternally;
 
       case "reader": {
         let preferredApp = this.preferredApplicationHandler;
         let defaultApp = this._defaultApplicationHandler;
 
@@ -3206,41 +3330,41 @@ FeedHandlerInfo.prototype = {
         return Ci.nsIHandlerInfo.handleInternally;
     }
   },
 
   set preferredAction(aNewValue) {
     switch (aNewValue) {
 
       case Ci.nsIHandlerInfo.handleInternally:
-        this.element(this._prefSelectedReader).value = "bookmarks";
+        Preferences.get(this._prefSelectedReader).value = "bookmarks";
         break;
 
       case Ci.nsIHandlerInfo.useHelperApp:
-        this.element(this._prefSelectedAction).value = "reader";
+        Preferences.get(this._prefSelectedAction).value = "reader";
         // The controller has already set preferredApplicationHandler
         // to the new helper app.
         break;
 
       case Ci.nsIHandlerInfo.useSystemDefault:
-        this.element(this._prefSelectedAction).value = "reader";
+        Preferences.get(this._prefSelectedAction).value = "reader";
         this.preferredApplicationHandler = this._defaultApplicationHandler;
         break;
     }
   },
 
   get alwaysAskBeforeHandling() {
-    return this.element(this._prefSelectedAction).value == "ask";
+    return Preferences.get(this._prefSelectedAction).value == "ask";
   },
 
   set alwaysAskBeforeHandling(aNewValue) {
     if (aNewValue == true)
-      this.element(this._prefSelectedAction).value = "ask";
+      Preferences.get(this._prefSelectedAction).value = "ask";
     else
-      this.element(this._prefSelectedAction).value = "reader";
+      Preferences.get(this._prefSelectedAction).value = "reader";
   },
 
   // Whether or not we are currently storing the action selected by the user.
   // We use this to suppress notification-triggered updates to the list when
   // we make changes that may spawn such updates, specifically when we change
   // the action for the feed type, which results in feed preference updates,
   // which spawn "pref changed" notifications that would otherwise cause us
   // to rebuild the view unnecessarily.
@@ -3259,17 +3383,17 @@ FeedHandlerInfo.prototype = {
   // Changes to the preferred action and handler take effect immediately
   // (we write them out to the preferences right as they happen),
   // so we when the controller calls store() after modifying the handlers,
   // the only thing we need to store is the removal of possible handlers
   // XXX Should we hold off on making the changes until this method gets called?
   store() {
     for (let app of this._possibleApplicationHandlers._removed) {
       if (app instanceof Ci.nsILocalHandlerApp) {
-        let pref = this.element(PREF_FEED_SELECTED_APP);
+        let pref = Preferences.get(PREF_FEED_SELECTED_APP);
         var preferredAppFile = pref.value;
         if (preferredAppFile) {
           let preferredApp = getLocalHandlerApp(preferredAppFile);
           if (app.equals(preferredApp))
             pref.reset();
         }
       } else {
         app.QueryInterface(Ci.nsIWebContentHandlerInfo);
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -11,255 +11,16 @@
   <script type="application/javascript" src="chrome://browser/content/aboutDialog-appUpdater.js"/>
 #endif
 
 <script type="application/javascript"
         src="chrome://mozapps/content/preferences/fontbuilder.js"/>
 
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences.properties"/>
 
-<preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
-
-    <!-- Startup -->
-    <preference id="browser.startup.page"
-                name="browser.startup.page"
-                type="int"/>
-    <preference id="browser.startup.homepage"
-                name="browser.startup.homepage"
-                type="wstring"/>
-
-#ifdef HAVE_SHELL_SERVICE
-    <preference id="browser.shell.checkDefaultBrowser"
-                name="browser.shell.checkDefaultBrowser"
-                type="bool"/>
-
-    <preference id="pref.general.disable_button.default_browser"
-                name="pref.general.disable_button.default_browser"
-                type="bool"/>
-#endif
-
-    <preference id="pref.browser.homepage.disable_button.current_page"
-                name="pref.browser.homepage.disable_button.current_page"
-                type="bool"/>
-    <preference id="pref.browser.homepage.disable_button.bookmark_page"
-                name="pref.browser.homepage.disable_button.bookmark_page"
-                type="bool"/>
-    <preference id="pref.browser.homepage.disable_button.restore_default"
-                name="pref.browser.homepage.disable_button.restore_default"
-                type="bool"/>
-
-    <preference id="browser.privatebrowsing.autostart"
-                name="browser.privatebrowsing.autostart"
-                type="bool"/>
-
-    <!-- Downloads -->
-    <preference id="browser.download.useDownloadDir"
-                name="browser.download.useDownloadDir"
-                type="bool"/>
-
-    <preference id="browser.download.folderList"
-                name="browser.download.folderList"
-                type="int"/>
-    <preference id="browser.download.dir"
-                name="browser.download.dir"
-                type="file"/>
-    <!-- Tab preferences
-    Preferences:
-
-    browser.link.open_newwindow
-        1 opens such links in the most recent window or tab,
-        2 opens such links in a new window,
-        3 opens such links in a new tab
-    browser.tabs.loadInBackground
-    - true if display should switch to a new tab which has been opened from a
-      link, false if display shouldn't switch
-    browser.tabs.warnOnClose
-    - true if when closing a window with multiple tabs the user is warned and
-      allowed to cancel the action, false to just close the window
-    browser.tabs.warnOnOpen
-    - true if the user should be warned if he attempts to open a lot of tabs at
-      once (e.g. a large folder of bookmarks), false otherwise
-    browser.taskbar.previews.enable
-    - true if tabs are to be shown in the Windows 7 taskbar
-    -->
-
-    <preference id="browser.link.open_newwindow"
-                name="browser.link.open_newwindow"
-                type="int"/>
-    <preference id="browser.tabs.loadInBackground"
-                name="browser.tabs.loadInBackground"
-                type="bool"
-                inverted="true"/>
-    <preference id="browser.tabs.warnOnClose"
-                name="browser.tabs.warnOnClose"
-                type="bool"/>
-    <preference id="browser.tabs.warnOnOpen"
-                name="browser.tabs.warnOnOpen"
-                type="bool"/>
-    <preference id="browser.sessionstore.restore_on_demand"
-                name="browser.sessionstore.restore_on_demand"
-                type="bool"/>
-#ifdef XP_WIN
-    <preference id="browser.taskbar.previews.enable"
-                name="browser.taskbar.previews.enable"
-                type="bool"/>
-#endif
-    <preference id="browser.ctrlTab.previews"
-                name="browser.ctrlTab.previews"
-                type="bool"/>
-
-  <!-- Fonts -->
-  <preference id="font.language.group"
-              name="font.language.group"
-              type="wstring"/>
-
-  <!-- Languages -->
-  <preference id="browser.translation.detectLanguage"
-              name="browser.translation.detectLanguage"
-              type="bool"/>
-
-  <!-- General tab -->
-
-  <!-- Accessibility
-   * accessibility.browsewithcaret
-     - true enables keyboard navigation and selection within web pages using a
-       visible caret, false uses normal keyboard navigation with no caret
-   * accessibility.typeaheadfind
-     - when set to true, typing outside text areas and input boxes will
-       automatically start searching for what's typed within the current
-       document; when set to false, no search action happens -->
-  <preference id="accessibility.browsewithcaret"
-              name="accessibility.browsewithcaret"
-              type="bool"/>
-  <preference id="accessibility.typeaheadfind"
-              name="accessibility.typeaheadfind"
-              type="bool"/>
-  <preference id="accessibility.blockautorefresh"
-              name="accessibility.blockautorefresh"
-              type="bool"/>
-#ifdef XP_WIN
-  <preference id="ui.osk.enabled"
-              name="ui.osk.enabled"
-              type="bool"/>
-#endif
-  <!-- Browsing
-   * general.autoScroll
-     - when set to true, clicking the scroll wheel on the mouse activates a
-       mouse mode where moving the mouse down scrolls the document downward with
-       speed correlated with the distance of the cursor from the original
-       position at which the click occurred (and likewise with movement upward);
-       if false, this behavior is disabled
-   * general.smoothScroll
-     - set to true to enable finer page scrolling than line-by-line on page-up,
-       page-down, and other such page movements -->
-  <preference id="general.autoScroll"
-              name="general.autoScroll"
-              type="bool"/>
-  <preference id="general.smoothScroll"
-              name="general.smoothScroll"
-              type="bool"/>
-  <preference id="layout.spellcheckDefault"
-              name="layout.spellcheckDefault"
-              type="int"/>
-
-  <preference id="browser.preferences.defaultPerformanceSettings.enabled"
-              name="browser.preferences.defaultPerformanceSettings.enabled"
-              type="bool"/>
-
-  <preference id="dom.ipc.processCount"
-              name="dom.ipc.processCount"
-              type="int"/>
-
-  <preference id="dom.ipc.processCount.web"
-              name="dom.ipc.processCount.web"
-              type="int"/>
-
-  <preference id="layers.acceleration.disabled"
-              name="layers.acceleration.disabled"
-              type="bool"
-              inverted="true"/>
-
-  <!-- Files and Applications -->
-  <preference id="browser.feeds.handler"
-              name="browser.feeds.handler"
-              type="string"/>
-  <preference id="browser.feeds.handler.default"
-              name="browser.feeds.handler.default"
-              type="string"/>
-  <preference id="browser.feeds.handlers.application"
-              name="browser.feeds.handlers.application"
-              type="file"/>
-  <preference id="browser.feeds.handlers.webservice"
-              name="browser.feeds.handlers.webservice"
-              type="string"/>
-
-  <preference id="browser.videoFeeds.handler"
-              name="browser.videoFeeds.handler"
-              type="string"/>
-  <preference id="browser.videoFeeds.handler.default"
-              name="browser.videoFeeds.handler.default"
-              type="string"/>
-  <preference id="browser.videoFeeds.handlers.application"
-              name="browser.videoFeeds.handlers.application"
-              type="file"/>
-  <preference id="browser.videoFeeds.handlers.webservice"
-              name="browser.videoFeeds.handlers.webservice"
-              type="string"/>
-
-  <preference id="browser.audioFeeds.handler"
-              name="browser.audioFeeds.handler"
-              type="string"/>
-  <preference id="browser.audioFeeds.handler.default"
-              name="browser.audioFeeds.handler.default"
-              type="string"/>
-  <preference id="browser.audioFeeds.handlers.application"
-              name="browser.audioFeeds.handlers.application"
-              type="file"/>
-  <preference id="browser.audioFeeds.handlers.webservice"
-              name="browser.audioFeeds.handlers.webservice"
-              type="string"/>
-
-  <preference id="pref.downloads.disable_button.edit_actions"
-              name="pref.downloads.disable_button.edit_actions"
-              type="bool"/>
-
-  <!-- DRM content -->
-  <preference id="media.eme.enabled"
-              name="media.eme.enabled"
-              type="bool"/>
-
-  <!-- Update -->
-  <preference id="browser.preferences.advanced.selectedTabIndex"
-              name="browser.preferences.advanced.selectedTabIndex"
-              type="int"/>
-
-#ifdef MOZ_UPDATER
-  <preference id="app.update.enabled"
-              name="app.update.enabled"
-              type="bool"/>
-  <preference id="app.update.auto"
-              name="app.update.auto"
-              type="bool"/>
-
-  <preference id="app.update.disable_button.showUpdateHistory"
-              name="app.update.disable_button.showUpdateHistory"
-              type="bool"/>
-
-#ifdef MOZ_MAINTENANCE_SERVICE
-  <preference id="app.update.service.enabled"
-              name="app.update.service.enabled"
-              type="bool"/>
-#endif
-#endif
-
-  <preference id="browser.search.update"
-              name="browser.search.update"
-              type="bool"/>
-</preferences>
-
 <hbox id="generalCategory"
       class="subcategory"
       hidden="true"
       data-category="paneGeneral">
   <label class="header-name" flex="1">&paneGeneral.title;</label>
 </hbox>
 
 <!-- Startup -->
--- a/browser/components/preferences/in-content/preferences.js
+++ b/browser/components/preferences/in-content/preferences.js
@@ -6,16 +6,17 @@
 /* import-globals-from subdialogs.js */
 /* import-globals-from main.js */
 /* import-globals-from search.js */
 /* import-globals-from containers.js */
 /* import-globals-from privacy.js */
 /* import-globals-from sync.js */
 /* import-globals-from findInPage.js */
 /* import-globals-from ../../../base/content/utilityOverlay.js */
+/* import-globals-from ../../../../toolkit/content/preferencesBindings.js */
 
 "use strict";
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
@@ -52,17 +53,17 @@ function register_module(categoryName, c
       this.inited = true;
     }
   });
 }
 
 document.addEventListener("DOMContentLoaded", init_all, {once: true});
 
 function init_all() {
-  document.documentElement.instantApply = true;
+  Preferences.forceEnableInstantApply();
 
   gSubDialog.init();
   register_module("paneGeneral", gMainPane);
   register_module("paneSearch", gSearchPane);
   register_module("panePrivacy", gPrivacyPane);
   register_module("paneContainers", gContainersPane);
   register_module("paneSync", gSyncPane);
   register_module("paneSearchResults", gSearchResultsPane);
@@ -313,24 +314,16 @@ function scrollContentTo(element) {
   let mainContent = document.querySelector(".main-content");
   let top = element.getBoundingClientRect().top - SEARCH_CONTAINER_HEIGHT;
   mainContent.scroll({
     top,
     behavior: "smooth",
   });
 }
 
-function helpButtonCommand() {
-  let pane = history.state;
-  let categories = document.getElementById("categories");
-  let helpTopic = categories.querySelector(".category[value=" + pane + "]")
-                            .getAttribute("helpTopic");
-  openHelpLink(helpTopic);
-}
-
 function friendlyPrefCategoryNameToInternalName(aName) {
   if (aName.startsWith("pane"))
     return aName;
   return "pane" + aName.substring(0, 1).toUpperCase() + aName.substr(1);
 }
 
 // This function is duplicated inside of utilityOverlay.js's openPreferences.
 function internalPrefCategoryNameToFriendlyName(aName) {
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -100,16 +100,18 @@
   <script type="text/javascript" src="chrome://global/content/l10n.js"></script>
 
   <html:link rel="shortcut icon"
               href="chrome://browser/skin/settings.svg"/>
 
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"
+          src="chrome://global/content/preferencesBindings.js"/>
+  <script type="application/javascript"
           src="chrome://browser/content/preferences/in-content/preferences.js"/>
   <script src="chrome://browser/content/preferences/in-content/findInPage.js"/>
   <script src="chrome://browser/content/preferences/in-content/subdialogs.js"/>
 
   <stringbundle id="bundleBrand"
                 src="chrome://branding/locale/brand.properties"/>
   <stringbundle id="bundlePreferences"
                 src="chrome://browser/locale/preferences/preferences.properties"/>
@@ -191,24 +193,24 @@
       <key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand="gSearchResultsPane.searchInput.focus();"/>
     </keyset>
 
     <vbox class="main-content" flex="1" align="start">
       <vbox class="pane-container">
         <hbox class="search-container" pack="end">
           <textbox type="search" id="searchInput" style="width: &searchField.width;" hidden="true" clickSelectsAll="true"/>
         </hbox>
-        <prefpane id="mainPrefPane">
+        <vbox id="mainPrefPane" class="prefpane prefwindow">
 #include searchResults.xul
 #include main.xul
 #include search.xul
 #include privacy.xul
 #include containers.xul
 #include sync.xul
-        </prefpane>
+        </vbox>
       </vbox>
     </vbox>
   </hbox>
 
   <stack id="dialogStack" hidden="true"/>
   <vbox id="dialogTemplate" class="dialogOverlay" align="center" pack="center" topmost="true" hidden="true">
     <groupbox class="dialogBox"
               orient="vertical"
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -29,16 +29,97 @@ XPCOMUtils.defineLazyGetter(this, "Alert
     // This will throw if manualDoNotDisturb isn't implemented.
     alertsService.manualDoNotDisturb;
     return alertsService;
   } catch (ex) {
     return undefined;
   }
 });
 
+Preferences.addAll([
+  // Tracking
+  { id: "privacy.trackingprotection.enabled", type: "bool" },
+  { id: "privacy.trackingprotection.pbmode.enabled", type: "bool" },
+
+  // Button prefs
+  { id: "pref.privacy.disable_button.cookie_exceptions", type: "bool" },
+  { id: "pref.privacy.disable_button.view_cookies", type: "bool" },
+  { id: "pref.privacy.disable_button.change_blocklist", type: "bool" },
+  { id: "pref.privacy.disable_button.tracking_protection_exceptions", type: "bool" },
+
+  // Location Bar
+  { id: "browser.urlbar.autocomplete.enabled", type: "bool" },
+  { id: "browser.urlbar.suggest.bookmark", type: "bool" },
+  { id: "browser.urlbar.suggest.history", type: "bool" },
+  { id: "browser.urlbar.suggest.openpage", type: "bool" },
+
+  // History
+  { id: "places.history.enabled", type: "bool" },
+  { id: "browser.formfill.enable", type: "bool" },
+  { id: "privacy.history.custom", type: "bool" },
+  // Cookies
+  { id: "network.cookie.cookieBehavior", type: "int" },
+  { id: "network.cookie.lifetimePolicy", type: "int" },
+  { id: "network.cookie.blockFutureCookies", type: "bool" },
+  // Clear Private Data
+  { id: "privacy.sanitize.sanitizeOnShutdown", type: "bool" },
+  { id: "privacy.sanitize.timeSpan", type: "int" },
+  // Do not track
+  { id: "privacy.donottrackheader.enabled", type: "bool" },
+
+  // Popups
+  { id: "dom.disable_open_during_load", type: "bool" },
+  // Passwords
+  { id: "signon.rememberSignons", type: "bool" },
+
+  // Buttons
+  { id: "pref.privacy.disable_button.view_passwords", type: "bool" },
+  { id: "pref.privacy.disable_button.view_passwords_exceptions", type: "bool" },
+
+  /* Certificates tab
+   * security.default_personal_cert
+   *   - a string:
+   *       "Select Automatically"   select a certificate automatically when a site
+   *                                requests one
+   *       "Ask Every Time"         present a dialog to the user so he can select
+   *                                the certificate to use on a site which
+   *                                requests one
+   */
+  { id: "security.default_personal_cert", type: "string" },
+
+  { id: "security.disable_button.openCertManager", type: "bool" },
+
+  { id: "security.disable_button.openDeviceManager", type: "bool" },
+
+  { id: "security.OCSP.enabled", type: "int" },
+
+  // Add-ons, malware, phishing
+  { id: "xpinstall.whitelist.required", type: "bool" },
+
+  { id: "browser.safebrowsing.malware.enabled", type: "bool" },
+  { id: "browser.safebrowsing.phishing.enabled", type: "bool" },
+
+  { id: "browser.safebrowsing.downloads.enabled", type: "bool" },
+
+  { id: "urlclassifier.malwareTable", type: "string" },
+
+  { id: "browser.safebrowsing.downloads.remote.block_potentially_unwanted", type: "bool" },
+  { id: "browser.safebrowsing.downloads.remote.block_uncommon", type: "bool" },
+
+  // Network tab
+  { id: "browser.cache.disk.capacity", type: "int" },
+
+  { id: "browser.cache.disk.smart_size.enabled", type: "bool", inverted: "true" },
+]);
+
+// Data Choices tab
+if (AppConstants.MOZ_CRASHREPORTER) {
+  Preferences.add({ id: "browser.crashReports.unsubmittedCheck.autoSubmit2", type: "bool" });
+}
+
 var gPrivacyPane = {
   _pane: null,
 
   /**
    * Whether the use has selected the auto-start private browsing mode in the UI.
    */
   _autoStartPrivateBrowsing: false,
 
@@ -99,20 +180,20 @@ var gPrivacyPane = {
     this.initializeHistoryMode();
     this.updateHistoryModePane();
     this.updatePrivacyMicroControls();
     this.initAutoStartPrivateBrowsingReverter();
     this._initTrackingProtection();
     this._initTrackingProtectionPBM();
     this._initAutocomplete();
 
-    setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
-      gPrivacyPane._updateSanitizeSettingsButton);
-    setEventListener("browser.privatebrowsing.autostart", "change",
-      gPrivacyPane.updatePrivacyMicroControls);
+    Preferences.get("privacy.sanitize.sanitizeOnShutdown").on("change",
+      gPrivacyPane._updateSanitizeSettingsButton.bind(gPrivacyPane));
+    Preferences.get("browser.privatebrowsing.autostart").on("change",
+      gPrivacyPane.updatePrivacyMicroControls.bind(gPrivacyPane));
     setEventListener("historyMode", "command", function() {
       gPrivacyPane.updateHistoryModePane();
       gPrivacyPane.updateHistoryModePrefs();
       gPrivacyPane.updatePrivacyMicroControls();
       gPrivacyPane.updateAutostart();
     });
     setEventListener("historyRememberClear", "click", function(event) {
       if (event.button == 0) {
@@ -321,36 +402,36 @@ var gPrivacyPane = {
   },
 
   // TRACKING PROTECTION MODE
 
   /**
    * Selects the right item of the Tracking Protection radiogroup.
    */
   trackingProtectionReadPrefs() {
-    let enabledPref = document.getElementById("privacy.trackingprotection.enabled");
-    let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled");
+    let enabledPref = Preferences.get("privacy.trackingprotection.enabled");
+    let pbmPref = Preferences.get("privacy.trackingprotection.pbmode.enabled");
     let radiogroup = document.getElementById("trackingProtectionRadioGroup");
 
     // Global enable takes precedence over enabled in Private Browsing.
     if (enabledPref.value) {
       radiogroup.value = "always";
     } else if (pbmPref.value) {
       radiogroup.value = "private";
     } else {
       radiogroup.value = "never";
     }
   },
 
   /**
    * Sets the pref values based on the selected item of the radiogroup.
    */
   trackingProtectionWritePrefs() {
-    let enabledPref = document.getElementById("privacy.trackingprotection.enabled");
-    let pbmPref = document.getElementById("privacy.trackingprotection.pbmode.enabled");
+    let enabledPref = Preferences.get("privacy.trackingprotection.enabled");
+    let pbmPref = Preferences.get("privacy.trackingprotection.pbmode.enabled");
     let radiogroup = document.getElementById("trackingProtectionRadioGroup");
 
     switch (radiogroup.value) {
       case "always":
         enabledPref.value = true;
         pbmPref.value = true;
         break;
       case "private":
@@ -406,28 +487,28 @@ var gPrivacyPane = {
    * Check whether preferences values are set to keep history
    *
    * @param aPrefs an array of pref names to check for
    * @returns boolean true if all of the prefs are set to keep history,
    *                  false otherwise
    */
   _checkHistoryValues(aPrefs) {
     for (let pref of Object.keys(aPrefs)) {
-      if (document.getElementById(pref).value != aPrefs[pref])
+      if (Preferences.get(pref).value != aPrefs[pref])
         return false;
     }
     return true;
   },
 
   /**
    * Initialize the history mode menulist based on the privacy preferences
    */
   initializeHistoryMode() {
     let mode;
-    let getVal = aPref => document.getElementById(aPref).value;
+    let getVal = aPref => Preferences.get(aPref).value;
 
     if (getVal("privacy.history.custom"))
       mode = "custom";
     else if (this._checkHistoryValues(this.prefsForKeepingHistory)) {
       if (getVal("browser.privatebrowsing.autostart"))
         mode = "dontremember";
       else
         mode = "remember";
@@ -449,93 +530,93 @@ var gPrivacyPane = {
       case "dontremember":
         selectedIndex = 1;
         break;
       case "custom":
         selectedIndex = 2;
         break;
     }
     document.getElementById("historyPane").selectedIndex = selectedIndex;
-    document.getElementById("privacy.history.custom").value = selectedIndex == 2;
+    Preferences.get("privacy.history.custom").value = selectedIndex == 2;
   },
 
   /**
    * Update the private browsing auto-start pref and the history mode
    * micro-management prefs based on the history mode menulist
    */
   updateHistoryModePrefs() {
-    let pref = document.getElementById("browser.privatebrowsing.autostart");
+    let pref = Preferences.get("browser.privatebrowsing.autostart");
     switch (document.getElementById("historyMode").value) {
       case "remember":
         if (pref.value)
           pref.value = false;
 
         // select the remember history option if needed
-        document.getElementById("places.history.enabled").value = true;
+        Preferences.get("places.history.enabled").value = true;
 
         // select the remember forms history option
-        document.getElementById("browser.formfill.enable").value = true;
+        Preferences.get("browser.formfill.enable").value = true;
 
         // select the allow cookies option
-        document.getElementById("network.cookie.cookieBehavior").value = 0;
+        Preferences.get("network.cookie.cookieBehavior").value = 0;
         // select the cookie lifetime policy option
-        document.getElementById("network.cookie.lifetimePolicy").value = 0;
+        Preferences.get("network.cookie.lifetimePolicy").value = 0;
 
         // select the clear on close option
-        document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
+        Preferences.get("privacy.sanitize.sanitizeOnShutdown").value = false;
         break;
       case "dontremember":
         if (!pref.value)
           pref.value = true;
         break;
     }
   },
 
   /**
    * Update the privacy micro-management controls based on the
    * value of the private browsing auto-start checkbox.
    */
   updatePrivacyMicroControls() {
     if (document.getElementById("historyMode").value == "custom") {
       let disabled = this._autoStartPrivateBrowsing =
-        document.getElementById("browser.privatebrowsing.autostart").value;
+        Preferences.get("browser.privatebrowsing.autostart").value;
       this.dependentControls.forEach(function(aElement) {
         let control = document.getElementById(aElement);
         let preferenceId = control.getAttribute("preference");
         if (!preferenceId) {
           let dependentControlId = control.getAttribute("control");
           if (dependentControlId) {
             let dependentControl = document.getElementById(dependentControlId);
             preferenceId = dependentControl.getAttribute("preference");
           }
         }
 
-        let preference = preferenceId ? document.getElementById(preferenceId) : {};
+        let preference = preferenceId ? Preferences.get(preferenceId) : {};
         control.disabled = disabled || preference.locked;
       });
 
       // adjust the cookie controls status
       this.readAcceptCookies();
-      let lifetimePolicy = document.getElementById("network.cookie.lifetimePolicy").value;
+      let lifetimePolicy = Preferences.get("network.cookie.lifetimePolicy").value;
       if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY &&
         lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION &&
         lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) {
         lifetimePolicy = Ci.nsICookieService.ACCEPT_NORMALLY;
       }
       document.getElementById("keepCookiesUntil").value = disabled ? 2 : lifetimePolicy;
 
       // adjust the checked state of the sanitizeOnShutdown checkbox
       document.getElementById("alwaysClear").checked = disabled ? false :
-        document.getElementById("privacy.sanitize.sanitizeOnShutdown").value;
+        Preferences.get("privacy.sanitize.sanitizeOnShutdown").value;
 
       // adjust the checked state of the remember history checkboxes
       document.getElementById("rememberHistory").checked = disabled ? false :
-        document.getElementById("places.history.enabled").value;
+        Preferences.get("places.history.enabled").value;
       document.getElementById("rememberForms").checked = disabled ? false :
-        document.getElementById("browser.formfill.enable").value;
+        Preferences.get("browser.formfill.enable").value;
 
       if (!disabled) {
         // adjust the Settings button for sanitizeOnShutdown
         this._updateSanitizeSettingsButton();
       }
     }
   },
 
@@ -551,17 +632,17 @@ var gPrivacyPane = {
     this._lastCheckState = autoStart.hasAttribute("checked");
   },
 
   _lastMode: null,
   _lastCheckState: null,
   updateAutostart() {
     let mode = document.getElementById("historyMode");
     let autoStart = document.getElementById("privateBrowsingAutoStart");
-    let pref = document.getElementById("browser.privatebrowsing.autostart");
+    let pref = Preferences.get("browser.privatebrowsing.autostart");
     if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) ||
       (mode.value == "remember" && !this._lastCheckState) ||
       (mode.value == "dontremember" && this._lastCheckState)) {
       // These are all no-op changes, so we don't need to prompt.
       this._lastMode = mode.selectedIndex;
       this._lastCheckState = autoStart.hasAttribute("checked");
       return;
     }
@@ -655,17 +736,17 @@ var gPrivacyPane = {
    */
 
   /**
    * Reads the network.cookie.cookieBehavior preference value and
    * enables/disables the rest of the cookie UI accordingly, returning true
    * if cookies are enabled.
    */
   readAcceptCookies() {
-    var pref = document.getElementById("network.cookie.cookieBehavior");
+    var pref = Preferences.get("network.cookie.cookieBehavior");
     var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
     var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
     var keepUntil = document.getElementById("keepUntil");
     var menu = document.getElementById("keepCookiesUntil");
 
     // enable the rest of the UI for anything other than "disable all cookies"
     var acceptCookies = (pref.value != 2);
 
@@ -689,17 +770,17 @@ var gPrivacyPane = {
 
     return accept.checked ? 0 : 2;
   },
 
   /**
    * Converts between network.cookie.cookieBehavior and the third-party cookie UI
    */
   readAcceptThirdPartyCookies() {
-    var pref = document.getElementById("network.cookie.cookieBehavior");
+    var pref = Preferences.get("network.cookie.cookieBehavior");
     switch (pref.value) {
       case 0:
         return "always";
       case 1:
         return "never";
       case 2:
         return "never";
       case 3:
@@ -766,17 +847,17 @@ var gPrivacyPane = {
   },
 
 
   /**
    * Displays a dialog from which individual parts of private data may be
    * cleared.
    */
   clearPrivateDataNow(aClearEverything) {
-    var ts = document.getElementById("privacy.sanitize.timeSpan");
+    var ts = Preferences.get("privacy.sanitize.timeSpan");
     var timeSpanOrig = ts.value;
 
     if (aClearEverything) {
       ts.value = 0;
     }
 
     gSubDialog.open("chrome://browser/content/sanitize.xul", "resizable=no", null, () => {
       // reset the timeSpan pref
@@ -789,17 +870,17 @@ var gPrivacyPane = {
   },
 
   /**
    * Enables or disables the "Settings..." button depending
    * on the privacy.sanitize.sanitizeOnShutdown preference value
    */
   _updateSanitizeSettingsButton() {
     var settingsButton = document.getElementById("clearDataSettings");
-    var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
+    var sanitizeOnShutdownPref = Preferences.get("privacy.sanitize.sanitizeOnShutdown");
 
     settingsButton.disabled = !sanitizeOnShutdownPref.value;
   },
 
   toggleDoNotDisturbNotifications(event) {
     AlertsServiceDND.manualDoNotDisturb = event.target.checked;
   },
 
@@ -895,17 +976,17 @@ var gPrivacyPane = {
   // UTILITY FUNCTIONS
 
   /**
    * Utility function to enable/disable the button specified by aButtonID based
    * on the value of the Boolean preference specified by aPreferenceID.
    */
   updateButtons(aButtonID, aPreferenceID) {
     var button = document.getElementById(aButtonID);
-    var preference = document.getElementById(aPreferenceID);
+    var preference = Preferences.get(aPreferenceID);
     button.disabled = preference.value != true;
     return undefined;
   },
 
   // BEGIN UI CODE
 
   /*
    * Preferences:
@@ -1013,17 +1094,17 @@ var gPrivacyPane = {
   },
 
   /**
    * Enables/disables the Exceptions button used to configure sites where
    * passwords are never saved. When browser is set to start in Private
    * Browsing mode, the "Remember passwords" UI is useless, so we disable it.
    */
   readSavePasswords() {
-    var pref = document.getElementById("signon.rememberSignons");
+    var pref = Preferences.get("signon.rememberSignons");
     var excepts = document.getElementById("passwordExceptions");
 
     if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
       document.getElementById("savePasswords").disabled = true;
       excepts.disabled = true;
       return false;
     }
     excepts.disabled = !pref.value;
@@ -1031,38 +1112,38 @@ var gPrivacyPane = {
     return undefined;
   },
 
   /**
    * Enables/disables the add-ons Exceptions button depending on whether
    * or not add-on installation warnings are displayed.
    */
   readWarnAddonInstall() {
-    var warn = document.getElementById("xpinstall.whitelist.required");
+    var warn = Preferences.get("xpinstall.whitelist.required");
     var exceptions = document.getElementById("addonExceptions");
 
     exceptions.disabled = !warn.value;
 
     // don't override the preference value
     return undefined;
   },
 
   _initSafeBrowsing() {
     let enableSafeBrowsing = document.getElementById("enableSafeBrowsing");
     let blockDownloads = document.getElementById("blockDownloads");
     let blockUncommonUnwanted = document.getElementById("blockUncommonUnwanted");
 
-    let safeBrowsingPhishingPref = document.getElementById("browser.safebrowsing.phishing.enabled");
-    let safeBrowsingMalwarePref = document.getElementById("browser.safebrowsing.malware.enabled");
+    let safeBrowsingPhishingPref = Preferences.get("browser.safebrowsing.phishing.enabled");
+    let safeBrowsingMalwarePref = Preferences.get("browser.safebrowsing.malware.enabled");
 
-    let blockDownloadsPref = document.getElementById("browser.safebrowsing.downloads.enabled");
-    let malwareTable = document.getElementById("urlclassifier.malwareTable");
+    let blockDownloadsPref = Preferences.get("browser.safebrowsing.downloads.enabled");
+    let malwareTable = Preferences.get("urlclassifier.malwareTable");
 
-    let blockUnwantedPref = document.getElementById("browser.safebrowsing.downloads.remote.block_potentially_unwanted");
-    let blockUncommonPref = document.getElementById("browser.safebrowsing.downloads.remote.block_uncommon");
+    let blockUnwantedPref = Preferences.get("browser.safebrowsing.downloads.remote.block_potentially_unwanted");
+    let blockUncommonPref = Preferences.get("browser.safebrowsing.downloads.remote.block_uncommon");
 
     let learnMoreLink = document.getElementById("enableSafeBrowsingLearnMore");
     let phishingUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "phishing-malware";
     learnMoreLink.setAttribute("href", phishingUrl);
 
     enableSafeBrowsing.addEventListener("command", function() {
       safeBrowsingPhishingPref.value = enableSafeBrowsing.checked;
       safeBrowsingMalwarePref.value = enableSafeBrowsing.checked;
@@ -1186,17 +1267,17 @@ var gPrivacyPane = {
    * values for "security.OCSP.enabled" are:
    * 0: fetching is disabled
    * 1: fetch for all certificates
    * 2: fetch only for EV certificates
    * Hence, if "security.OCSP.enabled" is non-zero, the checkbox should be
    * checked. Otherwise, it should be unchecked.
    */
   readEnableOCSP() {
-    var preference = document.getElementById("security.OCSP.enabled");
+    var preference = Preferences.get("security.OCSP.enabled");
     // This is the case if the preference is the default value.
     if (preference.value === undefined) {
       return true;
     }
     return preference.value != 0;
   },
 
   /**
@@ -1299,47 +1380,47 @@ var gPrivacyPane = {
     document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
     document.getElementById("cacheSize").disabled = smartSizeEnabled;
     document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
   },
 
   readSmartSizeEnabled() {
     // The smart_size.enabled preference element is inverted="true", so its
     // value is the opposite of the actual pref value
-    var disabled = document.getElementById("browser.cache.disk.smart_size.enabled").value;
+    var disabled = Preferences.get("browser.cache.disk.smart_size.enabled").value;
     this.updateCacheSizeUI(!disabled);
   },
 
   /**
    * Converts the cache size from units of KB to units of MB and stores it in
    * the textbox element.
    *
    * Preferences:
    *
    * browser.cache.disk.capacity
    * - the size of the browser cache in KB
    * - Only used if browser.cache.disk.smart_size.enabled is disabled
    */
   updateCacheSizeInputField() {
     let cacheSizeElem = document.getElementById("cacheSize");
-    let cachePref = document.getElementById("browser.cache.disk.capacity");
+    let cachePref = Preferences.get("browser.cache.disk.capacity");
     cacheSizeElem.value = cachePref.value / 1024;
     if (cachePref.locked)
       cacheSizeElem.disabled = true;
   },
 
   /**
    * Updates the cache size preference once user enters a new value.
    * We intentionally do not set preference="browser.cache.disk.capacity"
    * onto the textbox directly, as that would update the pref at each keypress
    * not only after the final value is entered.
    */
   updateCacheSizePref() {
     let cacheSizeElem = document.getElementById("cacheSize");
-    let cachePref = document.getElementById("browser.cache.disk.capacity");
+    let cachePref = Preferences.get("browser.cache.disk.capacity");
     // Converts the cache size as specified in UI (in MB) to KB.
     let intValue = parseInt(cacheSizeElem.value, 10);
     cachePref.value = isNaN(intValue) ? 0 : intValue * 1024;
   },
 
   clearSiteData() {
     let flags =
       Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -1,175 +1,16 @@
 # 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/.
 
 <!-- Privacy panel -->
 
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content/privacy.js"/>
-
-<preferences id="privacyPreferences" hidden="true" data-category="panePrivacy">
-
-  <!-- Tracking -->
-  <preference id="privacy.trackingprotection.enabled"
-              name="privacy.trackingprotection.enabled"
-              type="bool"/>
-  <preference id="privacy.trackingprotection.pbmode.enabled"
-              name="privacy.trackingprotection.pbmode.enabled"
-              type="bool"/>
-
-  <!-- XXX button prefs -->
-  <preference id="pref.privacy.disable_button.cookie_exceptions"
-              name="pref.privacy.disable_button.cookie_exceptions"
-              type="bool"/>
-  <preference id="pref.privacy.disable_button.view_cookies"
-              name="pref.privacy.disable_button.view_cookies"
-              type="bool"/>
-  <preference id="pref.privacy.disable_button.change_blocklist"
-              name="pref.privacy.disable_button.change_blocklist"
-              type="bool"/>
-  <preference id="pref.privacy.disable_button.tracking_protection_exceptions"
-              name="pref.privacy.disable_button.tracking_protection_exceptions"
-              type="bool"/>
-
-  <!-- Location Bar -->
-  <preference id="browser.urlbar.autocomplete.enabled"
-              name="browser.urlbar.autocomplete.enabled"
-              type="bool"/>
-  <preference id="browser.urlbar.suggest.bookmark"
-              name="browser.urlbar.suggest.bookmark"
-              type="bool"/>
-  <preference id="browser.urlbar.suggest.history"
-              name="browser.urlbar.suggest.history"
-              type="bool"/>
-  <preference id="browser.urlbar.suggest.openpage"
-              name="browser.urlbar.suggest.openpage"
-              type="bool"/>
-
-  <!-- History -->
-  <preference id="places.history.enabled"
-              name="places.history.enabled"
-              type="bool"/>
-  <preference id="browser.formfill.enable"
-              name="browser.formfill.enable"
-              type="bool"/>
-  <preference id="privacy.history.custom"
-              name="privacy.history.custom"
-              type="bool"/>
-  <!-- Cookies -->
-  <preference id="network.cookie.cookieBehavior"
-              name="network.cookie.cookieBehavior"
-              type="int"/>
-  <preference id="network.cookie.lifetimePolicy"
-              name="network.cookie.lifetimePolicy"
-              type="int"/>
-  <preference id="network.cookie.blockFutureCookies"
-              name="network.cookie.blockFutureCookies"
-              type="bool"/>
-  <!-- Clear Private Data -->
-  <preference id="privacy.sanitize.sanitizeOnShutdown"
-              name="privacy.sanitize.sanitizeOnShutdown"
-              type="bool"/>
-  <preference id="privacy.sanitize.timeSpan"
-              name="privacy.sanitize.timeSpan"
-              type="int"/>
-  <!-- Private Browsing -->
-  <preference id="browser.privatebrowsing.autostart"
-              name="browser.privatebrowsing.autostart"
-              type="bool"/>
-  <!-- Do not track -->
-  <preference id="privacy.donottrackheader.enabled"
-              name="privacy.donottrackheader.enabled"
-              type="bool"/>
-  <!-- Popups -->
-  <preference id="dom.disable_open_during_load"
-              name="dom.disable_open_during_load"
-              type="bool"/>
-  <!-- Passwords -->
-  <preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
-
-  <!-- XXX buttons -->
-  <preference id="pref.privacy.disable_button.view_passwords"
-              name="pref.privacy.disable_button.view_passwords"
-              type="bool"/>
-  <preference id="pref.privacy.disable_button.view_passwords_exceptions"
-              name="pref.privacy.disable_button.view_passwords_exceptions"
-              type="bool"/>
-
-  <!-- Certificates tab
-   * security.default_personal_cert
-     - a string:
-         "Select Automatically"   select a certificate automatically when a site
-                                  requests one
-         "Ask Every Time"         present a dialog to the user so he can select
-                                  the certificate to use on a site which
-                                  requests one -->
-  <preference id="security.default_personal_cert"
-              name="security.default_personal_cert"
-              type="string"/>
-
-  <preference id="security.disable_button.openCertManager"
-              name="security.disable_button.openCertManager"
-              type="bool"/>
-
-  <preference id="security.disable_button.openDeviceManager"
-              name="security.disable_button.openDeviceManager"
-              type="bool"/>
-
-  <preference id="security.OCSP.enabled"
-              name="security.OCSP.enabled"
-              type="int"/>
-
-  <!-- Add-ons, malware, phishing -->
-  <preference id="xpinstall.whitelist.required"
-              name="xpinstall.whitelist.required"
-              type="bool"/>
-
-  <preference id="browser.safebrowsing.malware.enabled"
-              name="browser.safebrowsing.malware.enabled"
-              type="bool"/>
-  <preference id="browser.safebrowsing.phishing.enabled"
-              name="browser.safebrowsing.phishing.enabled"
-              type="bool"/>
-
-  <preference id="browser.safebrowsing.downloads.enabled"
-              name="browser.safebrowsing.downloads.enabled"
-              type="bool"/>
-
-  <preference id="urlclassifier.malwareTable"
-              name="urlclassifier.malwareTable"
-              type="string"/>
-
-  <preference id="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
-              name="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
-              type="bool"/>
-  <preference id="browser.safebrowsing.downloads.remote.block_uncommon"
-              name="browser.safebrowsing.downloads.remote.block_uncommon"
-              type="bool"/>
-
-  <!-- Network tab -->
-  <preference id="browser.cache.disk.capacity"
-              name="browser.cache.disk.capacity"
-              type="int"/>
-
-  <preference id="browser.cache.disk.smart_size.enabled"
-              name="browser.cache.disk.smart_size.enabled"
-              inverted="true"
-              type="bool"/>
-
-  <!-- Data Choices tab -->
-#ifdef MOZ_CRASHREPORTER
-  <preference id="browser.crashReports.unsubmittedCheck.autoSubmit2"
-              name="browser.crashReports.unsubmittedCheck.autoSubmit2"
-              type="bool"/>
-#endif
-
-</preferences>
-
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
 <stringbundle id="signonBundle" src="chrome://passwordmgr/locale/passwordmgr.properties"/>
 
 <hbox id="browserPrivacyCategory"
       class="subcategory"
       hidden="true"
       data-category="panePrivacy">
   <label class="header-name" flex="1">&browserPrivacy.label;</label>
--- a/browser/components/preferences/in-content/search.js
+++ b/browser/components/preferences/in-content/search.js
@@ -5,16 +5,23 @@
 /* import-globals-from preferences.js */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSettingsStore",
                                   "resource://gre/modules/ExtensionSettingsStore.jsm");
 
+Preferences.addAll([
+  { id: "browser.search.suggest.enabled", type: "bool" },
+  { id: "browser.urlbar.suggest.searches", type: "bool" },
+  { id: "browser.search.hiddenOneOffs", type: "unichar" },
+  { id: "browser.search.widget.inNavBar", type: "bool" },
+]);
+
 const ENGINE_FLAVOR = "text/x-moz-search-engine";
 const SEARCH_TYPE = "default_search";
 const SEARCH_KEY = "defaultSearch";
 
 var gEngineView = null;
 
 var gSearchPane = {
 
@@ -45,34 +52,29 @@ var gSearchPane = {
 
     Services.obs.addObserver(this, "browser-search-engine-modified");
     window.addEventListener("unload", () => {
       Services.obs.removeObserver(this, "browser-search-engine-modified");
     });
 
     this._initAutocomplete();
 
-    let suggestsPref =
-      document.getElementById("browser.search.suggest.enabled");
-    suggestsPref.addEventListener("change", () => {
-      this.updateSuggestsCheckbox();
-    });
+    let suggestsPref = Preferences.get("browser.search.suggest.enabled");
+    suggestsPref.on("change", this.updateSuggestsCheckbox.bind(this));
     this.updateSuggestsCheckbox();
   },
 
   updateSuggestsCheckbox() {
-    let suggestsPref =
-      document.getElementById("browser.search.suggest.enabled");
+    let suggestsPref = Preferences.get("browser.search.suggest.enabled");
     let permanentPB =
       Services.prefs.getBoolPref("browser.privatebrowsing.autostart");
     let urlbarSuggests = document.getElementById("urlBarSuggestion");
     urlbarSuggests.disabled = !suggestsPref.value || permanentPB;
 
-    let urlbarSuggestsPref =
-      document.getElementById("browser.urlbar.suggest.searches");
+    let urlbarSuggestsPref = Preferences.get("browser.urlbar.suggest.searches");
     urlbarSuggests.checked = urlbarSuggestsPref.value;
     if (urlbarSuggests.disabled) {
       urlbarSuggests.checked = false;
     }
 
     let permanentPBLabel =
       document.getElementById("urlBarSuggestionPermanentPBLabel");
     permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
@@ -310,17 +312,17 @@ var gSearchPane = {
   },
 
   saveOneClickEnginesList() {
     let hiddenList = [];
     for (let engine of gEngineView._engineStore.engines) {
       if (!engine.shown)
         hiddenList.push(engine.name);
     }
-    document.getElementById("browser.search.hiddenOneOffs").value =
+    Preferences.get("browser.search.hiddenOneOffs").value =
       hiddenList.join(",");
   },
 
   setDefaultEngine() {
     Services.search.currentEngine =
       document.getElementById("defaultEngine").selectedItem.engine;
     ExtensionSettingsStore.setByUser(SEARCH_TYPE, SEARCH_KEY);
   }
@@ -334,17 +336,17 @@ function onDragEngineStart(event) {
   if (selectedIndex >= 0 && !gEngineView.isCheckBox(row.value, col.value)) {
     event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
     event.dataTransfer.effectAllowed = "move";
   }
 }
 
 
 function EngineStore() {
-  let pref = document.getElementById("browser.search.hiddenOneOffs").value;
+  let pref = Preferences.get("browser.search.hiddenOneOffs").value;
   this.hiddenList = pref ? pref.split(",") : [];
 
   this._engines = Services.search.getVisibleEngines().map(this._cloneEngine, this);
   this._defaultEngines = Services.search.getDefaultEngines().map(this._cloneEngine, this);
 
   // check if we need to disable the restore defaults button
   var someHidden = this._defaultEngines.some(e => e.hidden);
   gSearchPane.showRestoreDefaults(someHidden);
--- a/browser/components/preferences/in-content/search.xul
+++ b/browser/components/preferences/in-content/search.xul
@@ -1,28 +1,8 @@
-    <preferences id="searchPreferences" hidden="true" data-category="paneSearch">
-
-      <preference id="browser.search.suggest.enabled"
-                  name="browser.search.suggest.enabled"
-                  type="bool"/>
-
-      <preference id="browser.urlbar.suggest.searches"
-                  name="browser.urlbar.suggest.searches"
-                  type="bool"/>
-
-      <preference id="browser.search.hiddenOneOffs"
-                  name="browser.search.hiddenOneOffs"
-                  type="unichar"/>
-
-      <preference id="browser.search.widget.inNavBar"
-                  name="browser.search.widget.inNavBar"
-                  type="bool"/>
-
-    </preferences>
-
     <script type="application/javascript"
             src="chrome://browser/content/preferences/in-content/search.js"/>
 
     <stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
 
     <hbox id="searchCategory"
           class="subcategory"
           hidden="true"
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -23,16 +23,27 @@ const FXA_PAGE_LOGGED_IN = 1;
 // Indexes into the "login status" deck.
 // We are in a successful verified state - everything should work!
 const FXA_LOGIN_VERIFIED = 0;
 // We have logged in to an unverified account.
 const FXA_LOGIN_UNVERIFIED = 1;
 // We are logged in locally, but the server rejected our credentials.
 const FXA_LOGIN_FAILED = 2;
 
+Preferences.addAll([
+  { id: "engine.addons", name: "services.sync.engine.addons", type: "bool" },
+  { id: "engine.bookmarks", name: "services.sync.engine.bookmarks", type: "bool" },
+  { id: "engine.history", name: "services.sync.engine.history", type: "bool" },
+  { id: "engine.tabs", name: "services.sync.engine.tabs", type: "bool" },
+  { id: "engine.prefs", name: "services.sync.engine.prefs", type: "bool" },
+  { id: "engine.passwords", name: "services.sync.engine.passwords", type: "bool" },
+  { id: "engine.addresses", name: "services.sync.engine.addresses", type: "bool" },
+  { id: "engine.creditcards", name: "services.sync.engine.creditcards", type: "bool" },
+]);
+
 var gSyncPane = {
   get page() {
     return document.getElementById("weavePrefsDeck").selectedIndex;
   },
 
   set page(val) {
     document.getElementById("weavePrefsDeck").selectedIndex = val;
   },
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -1,41 +1,14 @@
 # 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/.
 
 <!-- Sync panel -->
 
-<preferences id="syncEnginePrefs" hidden="true" data-category="paneSync">
-  <preference id="engine.addons"
-              name="services.sync.engine.addons"
-              type="bool"/>
-  <preference id="engine.bookmarks"
-              name="services.sync.engine.bookmarks"
-              type="bool"/>
-  <preference id="engine.history"
-              name="services.sync.engine.history"
-              type="bool"/>
-  <preference id="engine.tabs"
-              name="services.sync.engine.tabs"
-              type="bool"/>
-  <preference id="engine.prefs"
-              name="services.sync.engine.prefs"
-              type="bool"/>
-  <preference id="engine.passwords"
-              name="services.sync.engine.passwords"
-              type="bool"/>
-  <preference id="engine.addresses"
-              name="services.sync.engine.addresses"
-              type="bool"/>
-  <preference id="engine.creditcards"
-              name="services.sync.engine.creditcards"
-              type="bool"/>
-</preferences>
-
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content/sync.js"/>
 
 <hbox id="firefoxAccountCategory"
       class="subcategory"
       hidden="true"
       data-category="paneSync">
   <label class="header-name" flex="1">&paneSync1.title;</label>
--- a/browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js
+++ b/browser/components/preferences/in-content/tests/browser_basic_rebuild_fonts_test.js
@@ -5,18 +5,20 @@ registerCleanupFunction(function() {
 });
 
 add_task(async function() {
   await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
   // eslint-disable-next-line mozilla/no-cpows-in-tests
   await gBrowser.contentWindow.gMainPane._selectDefaultLanguageGroupPromise;
   // eslint-disable-next-line mozilla/no-cpows-in-tests
   let doc = gBrowser.contentDocument;
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
+  let contentWindow = gBrowser.contentWindow;
   var langGroup = Services.prefs.getComplexValue("font.language.group", Ci.nsIPrefLocalizedString).data;
-  is(doc.getElementById("font.language.group").value, langGroup,
+  is(contentWindow.Preferences.get("font.language.group").value, langGroup,
      "Language group should be set correctly.");
 
   let defaultFontType = Services.prefs.getCharPref("font.default." + langGroup);
   let fontFamily = Services.prefs.getCharPref("font.name." + defaultFontType + "." + langGroup);
   let fontFamilyField = doc.getElementById("defaultFont");
   is(fontFamilyField.value, fontFamily, "Font family should be set correctly.");
 
   let defaultFontSize = Services.prefs.getIntPref("font.size.variable." + langGroup);
@@ -39,17 +41,17 @@ add_task(async function() {
       return Promise.resolve(this._list);
     },
     getDefaultFont() { return this._defaultFont; },
     getStandardFamilyName(name) { return name; },
   };
   win.FontBuilder._allFonts = null;
   win.FontBuilder._langGroupSupported = false;
 
-  let langGroupElement = doc.getElementById("font.language.group");
+  let langGroupElement = win.Preferences.get("font.language.group");
   let selectLangsField = doc.getElementById("selectLangs");
   let serifField = doc.getElementById("serif");
   let armenian = "x-armn";
   let western = "x-western";
 
   // Await rebuilding of the font lists, which happens asynchronously in
   // gFontsDialog._selectLanguageGroup.  Testing code needs to call this
   // function and await its resolution after changing langGroupElement's value
@@ -58,17 +60,17 @@ add_task(async function() {
     return win.gFontsDialog._selectLanguageGroupPromise;
   }
 
   langGroupElement.value = armenian;
   await fontListsRebuilt();
   selectLangsField.value = armenian;
   is(serifField.value, "", "Font family should not be set.");
 
-  let armenianSerifElement = doc.getElementById("font.name.serif.x-armn");
+  let armenianSerifElement = win.Preferences.get("font.name.serif.x-armn");
 
   langGroupElement.value = western;
   await fontListsRebuilt();
   selectLangsField.value = western;
 
   // Simulate a font backend supporting language-specific enumeration.
   // NB: FontBuilder has cached the return value from EnumerateAllFonts(),
   // so _allFonts will always have 3 elements regardless of subsequent
--- a/browser/components/preferences/in-content/tests/browser_bug731866.js
+++ b/browser/components/preferences/in-content/tests/browser_bug731866.js
@@ -11,20 +11,19 @@ function test() {
   waitForExplicitFinish();
   open_preferences(runTest);
 }
 
 var gElements;
 
 function checkElements(expectedPane) {
   for (let element of gElements) {
-    // keyset and preferences elements fail is_element_visible checks because they are never visible.
+    // keyset elements fail is_element_visible checks because they are never visible.
     // special-case the drmGroup item because its visibility depends on pref + OS version
     if (element.nodeName == "keyset" ||
-        element.nodeName == "preferences" ||
         element.id === "drmGroup") {
       continue;
     }
     // The siteDataGroup in the Storage Management project is currently only pref-on on Nightly for testing purpose.
     // During the test and the transition period, we have to check the pref to see if the siteDataGroup
     // should be hidden always. This would be a bit bothersome, same as the offlineGroup as below.
     // However, this checking is necessary to make sure we don't leak the siteDataGroup into beta/release build
     if (element.id == "siteDataGroup" && storageManagerDisabled) {
--- a/browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js
+++ b/browser/components/preferences/in-content/tests/browser_bug795764_cachedisabled.js
@@ -29,19 +29,16 @@ function runTest(win) {
   is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
 
   let tab = win.document;
   let elements = tab.getElementById("mainPrefPane").children;
 
   // Test if privacy pane is opened correctly
   win.gotoPref("panePrivacy");
   for (let element of elements) {
-    if (element.nodeName == "preferences") {
-      continue;
-    }
     let attributeValue = element.getAttribute("data-category");
     if (attributeValue == "panePrivacy") {
       is_element_visible(element, `Privacy element of id=${element.id} should be visible`);
     } else {
       is_element_hidden(element, `Non-Privacy element of id=${element.id} should be hidden`);
     }
   }
 
--- a/browser/components/preferences/in-content/tests/browser_connection.js
+++ b/browser/components/preferences/in-content/tests/browser_connection.js
@@ -43,18 +43,18 @@ function test() {
     finish();
   });
 }
 
 // run a bunch of tests on the window containing connection.xul
 function runConnectionTests(win) {
   let doc = win.document;
   let networkProxyNone = doc.getElementById("networkProxyNone");
-  let networkProxyNonePref = doc.getElementById("network.proxy.no_proxies_on");
-  let networkProxyTypePref = doc.getElementById("network.proxy.type");
+  let networkProxyNonePref = win.Preferences.get("network.proxy.no_proxies_on");
+  let networkProxyTypePref = win.Preferences.get("network.proxy.type");
 
   // make sure the networkProxyNone textbox is formatted properly
   is(networkProxyNone.getAttribute("multiline"), "true",
      "networkProxyNone textbox is multiline");
   is(networkProxyNone.getAttribute("rows"), "2",
      "networkProxyNone textbox has two rows");
 
   // check if sanitizing the given input for the no_proxies_on pref results in
--- a/browser/components/preferences/in-content/tests/browser_connection_bug388287.js
+++ b/browser/components/preferences/in-content/tests/browser_connection_bug388287.js
@@ -48,22 +48,22 @@ function test() {
         finish();
         return;
       }
 
       dialog = await openAndLoadSubDialog(connectionURL);
       dialogClosingPromise = waitForEvent(dialog.document.documentElement, "dialogclosing");
 
       doc = dialog.document;
-      proxyTypePref = doc.getElementById("network.proxy.type");
-      sharePref = doc.getElementById("network.proxy.share_proxy_settings");
-      httpPref = doc.getElementById("network.proxy.http");
-      httpPortPref = doc.getElementById("network.proxy.http_port");
-      ftpPref = doc.getElementById("network.proxy.ftp");
-      ftpPortPref = doc.getElementById("network.proxy.ftp_port");
+      proxyTypePref = dialog.Preferences.get("network.proxy.type");
+      sharePref = dialog.Preferences.get("network.proxy.share_proxy_settings");
+      httpPref = dialog.Preferences.get("network.proxy.http");
+      httpPortPref = dialog.Preferences.get("network.proxy.http_port");
+      ftpPref = dialog.Preferences.get("network.proxy.ftp");
+      ftpPortPref = dialog.Preferences.get("network.proxy.ftp_port");
     }
 
     // This batch of tests should not close the dialog
     await setDoc();
 
     // Testing HTTP port 0 with share on
     proxyTypePref.value = 1;
     sharePref.value = true;
--- a/browser/components/preferences/in-content/tests/browser_fluent.js
+++ b/browser/components/preferences/in-content/tests/browser_fluent.js
@@ -20,19 +20,20 @@ add_task(async function() {
   }
 
   await Promise.all([
     openPreferencesViaOpenPreferencesAPI("general", {leaveOpen: true}),
     whenMainPaneLoadedFinished(),
   ]);
 
   let doc = gBrowser.contentDocument;
+  let win = gBrowser.contentWindow;
   await doc.l10n.ready;
 
-  let processCountPref = doc.getElementById("dom.ipc.processCount");
+  let processCountPref = win.Preferences.get("dom.ipc.processCount");
   let defaultProcessCount = processCountPref.defaultValue;
 
   let [ msg ] = await doc.l10n.formatMessages([
     ["default-content-process-count", { num: defaultProcessCount }]
   ]);
 
   let elem = doc.querySelector(
     `#contentProcessCount > menupopup > menuitem[value="${defaultProcessCount}"]`);
--- a/browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js
+++ b/browser/components/preferences/in-content/tests/browser_sanitizeOnShutdown_prefLocked.js
@@ -9,17 +9,17 @@ function switchToCustomHistoryMode(doc) 
 
 function testPrefStateMatchesLockedState() {
   // eslint-disable-next-line mozilla/no-cpows-in-tests
   let win = gBrowser.contentWindow;
   let doc = win.document;
   switchToCustomHistoryMode(doc);
 
   let checkbox = doc.getElementById("alwaysClear");
-  let preference = doc.getElementById("privacy.sanitize.sanitizeOnShutdown");
+  let preference = win.Preferences.get("privacy.sanitize.sanitizeOnShutdown");
   is(checkbox.disabled, preference.locked, "Always Clear checkbox should be enabled when preference is not locked.");
 
   Services.prefs.clearUserPref("privacy.history.custom");
   gBrowser.removeCurrentTab();
 }
 
 add_task(function setup() {
   registerCleanupFunction(function resetPreferences() {
--- a/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
+++ b/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
@@ -215,17 +215,17 @@ function test_dependent_prefs(win) {
   });
 
   let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
   ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
 
   function expect_checked(checked) {
     controls.forEach(function(control) {
       is(control.checked, checked,
-        control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
+        control.getAttribute("id") + " should " + (checked ? "" : "not ") + "be checked");
     });
 
     is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should " + (checked ? "not " : "") + "be limited");
   }
 
   // controls should be checked in remember mode
   historymode.value = "remember";
   controlChanged(historymode);
@@ -306,23 +306,23 @@ function test_locbar_suggestion_retentio
     is(Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled"), autocomplete,
        "browser.urlbar.autocomplete.enabled pref should be " + autocomplete);
   };
 }
 
 const gPrefCache = new Map();
 
 function cache_preferences(win) {
-  let prefs = win.document.querySelectorAll("#privacyPreferences > preference");
+  let prefs = win.Preferences.getAll();
   for (let pref of prefs)
     gPrefCache.set(pref.name, pref.value);
 }
 
 function reset_preferences(win) {
-  let prefs = win.document.querySelectorAll("#privacyPreferences > preference");
+  let prefs = win.Preferences.getAll();
   for (let pref of prefs)
     pref.value = gPrefCache.get(pref.name);
 }
 
 function run_test_subset(subset) {
   info("subset: " + Array.from(subset, x => x.name).join(",") + "\n");
   SpecialPowers.pushPrefEnv({"set": [["browser.preferences.instantApply", true]]});
 
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -3,25 +3,26 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 browser.jar:
     content/browser/preferences/applicationManager.xul
     content/browser/preferences/applicationManager.js
     content/browser/preferences/blocklists.xul
     content/browser/preferences/blocklists.js
 *   content/browser/preferences/colors.xul
+    content/browser/preferences/colors.js
 *   content/browser/preferences/cookies.xul
     content/browser/preferences/cookies.js
 *   content/browser/preferences/connection.xul
     content/browser/preferences/connection.js
-*   content/browser/preferences/fonts.xul
+    content/browser/preferences/fonts.xul
     content/browser/preferences/fonts.js
     content/browser/preferences/handlers.xml
     content/browser/preferences/handlers.css
-*   content/browser/preferences/languages.xul
+    content/browser/preferences/languages.xul
     content/browser/preferences/languages.js
     content/browser/preferences/permissions.xul
     content/browser/preferences/sitePermissions.xul
     content/browser/preferences/sitePermissions.js
     content/browser/preferences/sitePermissions.css
     content/browser/preferences/containers.xul
     content/browser/preferences/containers.js
     content/browser/preferences/permissions.js
--- a/browser/components/preferences/languages.js
+++ b/browser/components/preferences/languages.js
@@ -1,15 +1,25 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
 /* 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/. */
 
+/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
+
 Components.utils.import("resource://gre/modules/Services.jsm");
 
+Preferences.addAll([
+  { id: "intl.accept_languages", type: "wstring" },
+  { id: "pref.browser.language.disable_button.up", type: "bool" },
+  { id: "pref.browser.language.disable_button.down", type: "bool" },
+  { id: "pref.browser.language.disable_button.remove", type: "bool" },
+  { id: "privacy.spoof_english", type: "int" },
+]);
+
 var gLanguagesDialog = {
 
   _availableLanguagesList: [],
   _acceptLanguages: { },
 
   _selectedItemID: null,
 
   init() {
@@ -121,17 +131,17 @@ var gLanguagesDialog = {
     }
   },
 
   readAcceptLanguages() {
     while (this._activeLanguages.hasChildNodes())
       this._activeLanguages.firstChild.remove();
 
     var selectedIndex = 0;
-    var preference = document.getElementById("intl.accept_languages");
+    var preference = Preferences.get("intl.accept_languages");
     if (preference.value == "")
       return undefined;
     var languages = preference.value.toLowerCase().split(/\s*,\s*/);
     for (var i = 0; i < languages.length; ++i) {
       var name = this._getLanguageName(languages[i]);
       if (!name)
         name = "[" + languages[i] + "]";
       var listitem = document.createElement("listitem");
@@ -168,17 +178,17 @@ var gLanguagesDialog = {
     addButton.disabled = availableLanguages.disabled ||
                          availableLanguages.selectedIndex < 0;
 
     this._availableLanguages.removeAttribute("accesskey");
   },
 
   addLanguage() {
     var selectedID = this._availableLanguages.selectedItem.id;
-    var preference = document.getElementById("intl.accept_languages");
+    var preference = Preferences.get("intl.accept_languages");
     var arrayOfPrefs = preference.value.toLowerCase().split(/\s*,\s*/);
     for (var i = 0; i < arrayOfPrefs.length; ++i ) {
       if (arrayOfPrefs[i] == selectedID)
         return;
     }
 
     this._selectedItemID = selectedID;
 
@@ -214,17 +224,17 @@ var gLanguagesDialog = {
     var selection = this._activeLanguages.selectedItems;
     var lastSelected = selection[selection.length - 1];
     var selectItem = lastSelected.nextSibling || lastSelected.previousSibling;
     selectItem = selectItem ? selectItem.id : null;
 
     this._selectedItemID = selectItem;
 
     // Update the preference and force a UI rebuild
-    var preference = document.getElementById("intl.accept_languages");
+    var preference = Preferences.get("intl.accept_languages");
     preference.value = string;
 
     this._buildAvailableLanguageList();
   },
 
   _getLanguageName(aABCD) {
     if (!this._availableLanguagesList.length)
       this._loadAvailableLanguages();
@@ -249,17 +259,17 @@ var gLanguagesDialog = {
         string += previousItem.id;
       else
         string += item.id;
     }
 
     this._selectedItemID = selectedItem.id;
 
     // Update the preference and force a UI rebuild
-    var preference = document.getElementById("intl.accept_languages");
+    var preference = Preferences.get("intl.accept_languages");
     preference.value = string;
   },
 
   moveDown() {
     var selectedItem = this._activeLanguages.selectedItems[0];
     var nextItem = selectedItem.nextSibling;
 
     var string = "";
@@ -272,17 +282,17 @@ var gLanguagesDialog = {
         string += nextItem.id;
       else
         string += item.id;
     }
 
     this._selectedItemID = selectedItem.id;
 
     // Update the preference and force a UI rebuild
-    var preference = document.getElementById("intl.accept_languages");
+    var preference = Preferences.get("intl.accept_languages");
     preference.value = string;
   },
 
   onLanguageSelect() {
     var upButton = document.getElementById("up");
     var downButton = document.getElementById("down");
     var removeButton = document.getElementById("remove");
     switch (this._activeLanguages.selectedCount) {
@@ -330,9 +340,8 @@ var gLanguagesDialog = {
       return false;
     }
   },
 
   writeSpoofEnglish() {
     return document.getElementById("spoofEnglish").checked ? 2 : 1;
   }
 };
-
--- a/browser/components/preferences/languages.xul
+++ b/browser/components/preferences/languages.xul
@@ -1,56 +1,52 @@
 <?xml version="1.0"?>
 
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# 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/.
+<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
+<!-- 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/. -->
 
-<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/languages.dtd">
+<!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  %preferencesDTD;
+  <!ENTITY % languagesDTD SYSTEM "chrome://browser/locale/preferences/languages.dtd">
+  %languagesDTD;
+]>
 
 <?xml-stylesheet href="chrome://global/skin/"?>
-#ifdef XP_MACOSX
 <?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-#endif
 
-<prefwindow id="LanguagesDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="&languages.customize.Header;"
-            dlgbuttons="accept,cancel,help"
-            ondialoghelp="openPrefsHelp()"
-            style="width: &window.width;"
-# hack around XUL bug 1194844 by triggering extra reflow (see bug 1194346):
-            onfocus="gLanguagesDialog.forceReflow()"
-            onresize="gLanguagesDialog.forceReflow()">
+<dialog id="LanguagesDialog" type="child" class="prefwindow"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="&languages.customize.Header;"
+        buttons="accept,cancel,help"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        onload="gLanguagesDialog.init();"
+        helpTopic="prefs-languages"
+        ondialoghelp="openPrefsHelp()"
+        style="width: &window.width;"
+        onfocus="gLanguagesDialog.forceReflow()"
+        onresize="gLanguagesDialog.forceReflow()">
+
+<!-- The onfocus and onresize handlers above hack around XUL bug 1194844
+   - by triggering extra reflow (see bug 1194346). -->
 
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-
-  <prefpane id="LanguagesDialogPane"
-            class="largeDialogContainer"
-            onpaneload="gLanguagesDialog.init();"
-            helpTopic="prefs-languages">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
+  <script type="application/javascript" src="chrome://browser/content/preferences/languages.js"/>
 
-    <preferences>
-      <preference id="intl.accept_languages" name="intl.accept_languages" type="wstring"/>
-      <preference id="pref.browser.language.disable_button.up"
-                  name="pref.browser.language.disable_button.up"
-                  type="bool"/>
-      <preference id="pref.browser.language.disable_button.down"
-                  name="pref.browser.language.disable_button.down"
-                  type="bool"/>
-      <preference id="pref.browser.language.disable_button.remove"
-                  name="pref.browser.language.disable_button.remove"
-                  type="bool"/>
-      <preference id="privacy.spoof_english"
-                  name="privacy.spoof_english"
-                  type="int"/>
-    </preferences>
+  <keyset>
+    <key key="&windowClose.key;" modifiers="accel" oncommand="Preferences.close(event)"/>
+  </keyset>
 
-    <script type="application/javascript" src="chrome://browser/content/preferences/languages.js"/>
+  <vbox id="LanguagesDialogPane" class="prefpane largeDialogContainer">
 
     <stringbundleset id="languageSet">
       <stringbundle id="bundleRegions"      src="chrome://global/locale/regionNames.properties"/>
       <stringbundle id="bundleLanguages"    src="chrome://global/locale/languageNames.properties"/>
       <stringbundle id="bundlePreferences"  src="chrome://browser/locale/preferences/preferences.properties"/>
       <stringbundle id="bundleAccepted"     src="resource://gre/res/language.properties"/>
     </stringbundleset>
 
@@ -102,11 +98,10 @@
           <button id="addButton" oncommand="gLanguagesDialog.addLanguage();" disabled="true"
                   label="&languages.customize.addButton.label;"
                   accesskey="&languages.customize.addButton.accesskey;"/>
         </row>
       </rows>
     </grid>
     <separator/>
     <separator/>
-  </prefpane>
-</prefwindow>
-
+  </vbox>
+</dialog>
--- a/browser/components/preferences/sanitize.js
+++ b/browser/components/preferences/sanitize.js
@@ -1,16 +1,31 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
 /* 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/. */
 
+/* import-globals-from ../../../toolkit/content/preferencesBindings.js */
+
+Preferences.addAll([
+  { id: "privacy.clearOnShutdown.history", type: "bool" },
+  { id: "privacy.clearOnShutdown.formdata", type: "bool" },
+  { id: "privacy.clearOnShutdown.downloads", type: "bool" },
+  { id: "privacy.clearOnShutdown.cookies", type: "bool" },
+  { id: "privacy.clearOnShutdown.cache", type: "bool" },
+  { id: "privacy.clearOnShutdown.offlineApps", type: "bool" },
+  { id: "privacy.clearOnShutdown.sessions", type: "bool" },
+  { id: "privacy.clearOnShutdown.siteSettings", type: "bool" },
+]);
+
 var gSanitizeDialog = Object.freeze({
   init() {
     this.onClearHistoryChanged();
+
+    Preferences.get("privacy.clearOnShutdown.history").on("change", this.onClearHistoryChanged.bind(this));
   },
 
   onClearHistoryChanged() {
-    let downloadsPref = document.getElementById("privacy.clearOnShutdown.downloads");
-    let historyPref = document.getElementById("privacy.clearOnShutdown.history");
+    let downloadsPref = Preferences.get("privacy.clearOnShutdown.downloads");
+    let historyPref = Preferences.get("privacy.clearOnShutdown.history");
     downloadsPref.value = historyPref.value;
   }
 });
--- a/browser/components/preferences/sanitize.xul
+++ b/browser/components/preferences/sanitize.xul
@@ -1,50 +1,50 @@
 <?xml version="1.0"?>
 
 <!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
 <!-- 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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
 
 <!DOCTYPE dialog [
+  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
+  %preferencesDTD;
   <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  %brandDTD;
   <!ENTITY % sanitizeDTD SYSTEM "chrome://browser/locale/sanitize.dtd">
-  %brandDTD;
   %sanitizeDTD;
 ]>
 
-<prefwindow id="SanitizeDialog" type="child"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            dlgbuttons="accept,cancel,help"
-            ondialoghelp="openPrefsHelp()"
-            style="width: &sanitizePrefs2.modal.width;"
-            title="&sanitizePrefs2.title;"
-            onload="gSanitizeDialog.init();">
+<dialog id="SanitizeDialog" type="child" class="prefwindow"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        buttons="accept,cancel,help"
+        persist="lastSelected screenX screenY"
+        closebuttonlabel="&preferencesCloseButton.label;"
+        closebuttonaccesskey="&preferencesCloseButton.accesskey;"
+        role="dialog"
+        ondialoghelp="openPrefsHelp()"
+        style="width: &sanitizePrefs2.modal.width;"
+        title="&sanitizePrefs2.title;"
+        helpTopic="prefs-clear-private-data"
+        onload="gSanitizeDialog.init();">
 
   <script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
-  <script type="application/javascript" src="chrome://browser/content/preferences/sanitize.js"/>
-
-  <prefpane id="SanitizeDialogPane"
-            helpTopic="prefs-clear-private-data">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
 
-    <preferences>
-      <preference id="privacy.clearOnShutdown.history"               name="privacy.clearOnShutdown.history"               type="bool"
-                  onchange="return gSanitizeDialog.onClearHistoryChanged();"/>
-      <preference id="privacy.clearOnShutdown.formdata"              name="privacy.clearOnShutdown.formdata"              type="bool"/>
-      <preference id="privacy.clearOnShutdown.downloads"             name="privacy.clearOnShutdown.downloads"             type="bool"/>
-      <preference id="privacy.clearOnShutdown.cookies"               name="privacy.clearOnShutdown.cookies"               type="bool"/>
-      <preference id="privacy.clearOnShutdown.cache"                 name="privacy.clearOnShutdown.cache"                 type="bool"/>
-      <preference id="privacy.clearOnShutdown.offlineApps"           name="privacy.clearOnShutdown.offlineApps"           type="bool"/>
-      <preference id="privacy.clearOnShutdown.sessions"              name="privacy.clearOnShutdown.sessions"              type="bool"/>
-      <preference id="privacy.clearOnShutdown.siteSettings"          name="privacy.clearOnShutdown.siteSettings"          type="bool"/>
-    </preferences>
+  <keyset>
+    <key key="&windowClose.key;" modifiers="accel" oncommand="Preferences.close(event)"/>
+  </keyset>
+
+  <vbox id="SanitizeDialogPane" class="prefpane">
+
+    <script type="application/javascript" src="chrome://browser/content/preferences/sanitize.js"/>
 
     <description>&clearDataSettings3.label;</description>
 
     <groupbox orient="horizontal">
       <caption><label>&historySection.label;</label></caption>
       <grid flex="1">
         <columns>
           <column style="width: &sanitizePrefs2.column.width;"/>
@@ -89,10 +89,10 @@
                       preference="privacy.clearOnShutdown.siteSettings"/>
             <checkbox label="&itemOfflineApps.label;"
                       accesskey="&itemOfflineApps.accesskey;"
                       preference="privacy.clearOnShutdown.offlineApps"/>
           </row>
         </rows>
       </grid>
     </groupbox>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/browser/extensions/shield-recipe-client/lib/ShieldPreferences.jsm
+++ b/browser/extensions/shield-recipe-client/lib/ShieldPreferences.jsm
@@ -115,34 +115,29 @@ this.ShieldPreferences = {
     const viewStudies = doc.createElementNS(XUL_NS, "label");
     viewStudies.setAttribute("id", "viewShieldStudies");
     viewStudies.setAttribute("href", "about:studies");
     viewStudies.setAttribute("useoriginprincipal", true);
     viewStudies.textContent = "View Firefox Studies";
     viewStudies.classList.add("learnMore", "text-link");
     hContainer.appendChild(viewStudies);
 
-    // <prefrence> elements for prefs that we need to monitor while the page is open.
     const optOutPref = doc.createElementNS(XUL_NS, "preference");
     optOutPref.setAttribute("id", OPT_OUT_STUDIES_ENABLED_PREF);
     optOutPref.setAttribute("name", OPT_OUT_STUDIES_ENABLED_PREF);
     optOutPref.setAttribute("type", "bool");
 
+    // Preference instances for prefs that we need to monitor while the page is open.
+    doc.defaultView.Preferences.add({ id: OPT_OUT_STUDIES_ENABLED_PREF, type: "bool" });
+
     // Weirdly, FHR doesn't have a <preference> element on the page, so we create it.
-    const fhrPref = doc.createElementNS(XUL_NS, "preference");
-    fhrPref.setAttribute("id", FHR_UPLOAD_ENABLED_PREF);
-    fhrPref.setAttribute("name", FHR_UPLOAD_ENABLED_PREF);
-    fhrPref.setAttribute("type", "bool");
-    fhrPref.addEventListener("change", function(event) {
+    const fhrPref = doc.defaultView.Preferences.add({ id: FHR_UPLOAD_ENABLED_PREF, type: "bool" });
+    fhrPref.on("change", function(event) {
       // Avoid reference to the document directly, to avoid leaks.
       const eventTargetCheckbox = event.target.ownerDocument.getElementById("optOutStudiesEnabled");
       eventTargetCheckbox.disabled = !Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED_PREF);
     });
 
     // Actually inject the elements we've created.
     const parent = doc.getElementById("submitHealthReportBox").closest("vbox");
     parent.appendChild(container);
-
-    const preferences = doc.getElementById("privacyPreferences");
-    preferences.appendChild(optOutPref);
-    preferences.appendChild(fhrPref);
   },
 };
--- a/browser/themes/linux/preferences/preferences.css
+++ b/browser/themes/linux/preferences/preferences.css
@@ -1,15 +1,42 @@
 /*
 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 # 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/.
 */
 
+/* Pref Window & Pane */
+.prefwindow {
+  padding: 0px;
+}
+
+.prefwindow[type="child"] {
+  padding: 8px;
+}
+
+.prefpane {
+  padding: 8px;
+}
+
+.prefwindow[type="child"] > .prefpane {
+  padding: 0px;
+}
+
+.dialog-button-box {
+  padding-bottom: 8px;
+  padding-inline-start: 8px;
+  padding-inline-end: 8px;
+}
+
+.prefwindow[type="child"] .dialog-button-box {
+  padding: 0px;
+}
+
 /* General Pane */
 #useFirefoxSync,
 #getStarted {
   font-size: 90%;
 }
 
 #isNotDefaultLabel {
   font-weight: bold;
@@ -18,17 +45,17 @@
 /* Content Pane */
 #translationAttributionImage {
   width: 70px;
   cursor: pointer;
 }
 
 /* Modeless Window Dialogs */
 .windowDialog,
-.windowDialog prefpane {
+.windowDialog .prefpane {
   padding: 0px;
 }
 
 .contentPane {
   margin: 9px 8px 5px 8px;
 }
 
 .actionButtons {
--- a/browser/themes/linux/sanitizeDialog.css
+++ b/browser/themes/linux/sanitizeDialog.css
@@ -94,14 +94,14 @@
    attribute is set to the total number of listitems, as it is currently.  See
    bug 489958 comment 14 and bug 491788. */
 #itemList > listitem {
   padding: 1px 0;
 }
 
 
 /* Align the last dialog button with the end of the warning box */
-.prefWindow-dlgbuttons {
+.dialog-button-box {
   margin-inline-end: 0;
 }
 .dialog-button[dlgtype="accept"] {
   margin-inline-end: 0;
 }
--- a/browser/themes/osx/preferences/in-content/dialog.css
+++ b/browser/themes/osx/preferences/in-content/dialog.css
@@ -1,18 +1,14 @@
 /* - 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/. */
 
 %include ../../../shared/incontentprefs/dialog.inc.css
 
-prefwindow,
+.prefwindow,
 .windowDialog {
   font: message-box !important;
 }
 
 :root > * {
   font-size: 1.18em;
 }
-
-.prefWindow-dlgbuttons {
-  margin: 0;
-}
--- a/browser/themes/osx/preferences/preferences.css
+++ b/browser/themes/osx/preferences/preferences.css
@@ -7,22 +7,50 @@
 
 %include ../../../../toolkit/themes/osx/global/shared.inc
 
 .windowDialog {
   padding: 12px;
   font: -moz-dialog;
 }
 
-/* ----- APPLICATIONS PREFPANE ----- */
+.prefwindow {
+  padding: 0;
+  font: -moz-dialog !important;
+}
+
+.prefwindow[type="child"] {
+  padding-top: 18px;
+  padding-bottom: 15px;
+  padding-inline-start: 18px;
+  padding-inline-end: 20px;
+}
+
+.dialog-button-box {
+  margin: 0 12px 12px;
+  padding-top: 0 !important;
+}
+
 description {
   margin-bottom: 4px !important;
 }
 
-prefpane .groupbox-body {
+.prefpane {
+  padding-top: 12px;
+  padding-bottom: 12px;
+  padding-inline-start: 0;
+  padding-inline-end: 12px;
+}
+
+.prefwindow[type="child"] > .prefpane {
+  padding: 0;
+}
+
+.prefpane .groupbox-body,
+.prefpane .groupbox-body {
   -moz-appearance: none;
   padding: 8px 4px 4px 4px;
 }
 
 tabpanels {
   padding: 20px 7px 7px;
 }
 
--- a/browser/themes/osx/sanitizeDialog.css
+++ b/browser/themes/osx/sanitizeDialog.css
@@ -78,14 +78,14 @@
    attribute is set to the total number of listitems, as it is currently.  See
    bug 489958 comment 14 and bug 491788. */
 #itemList > listitem {
   padding: 1px 0;
 }
 
 
 /* Align the last dialog button with the end of the warning box */
-.prefWindow-dlgbuttons {
+.dialog-button-box {
   margin-inline-end: 0;
 }
 .dialog-button[dlgtype="accept"] {
   margin-inline-end: 0;
 }
--- a/browser/themes/shared/incontentprefs/dialog.inc.css
+++ b/browser/themes/shared/incontentprefs/dialog.inc.css
@@ -1,18 +1,17 @@
 %if 0
 /* - 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/. */
 %endif
 
 dialog,
 window,
-prefpane,
-prefwindow,
+.prefpane,
 .windowDialog {
   -moz-appearance: none;
   background-color: #fbfbfb;
   color: #424e5a;
   margin: 0;
   padding: 0;
 }
 
@@ -52,17 +51,17 @@ caption {
 groupbox {
   margin-top: 0;
   margin-right: 4px;
   margin-left: 4px;
   padding-top: 0;
   padding-bottom: 5px;
 }
 
-prefpane .groupbox-body {
+.prefpane .groupbox-body {
   padding: 0 0 5px;
 }
 
 groupbox description {
   margin-right: 0;
   margin-left: 0;
 }
 
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -23,17 +23,22 @@
   width: 664px;
 }
 
 #mainPrefPane {
   width: 100%;
   padding: 0;
 }
 
-prefpane > groupbox + groupbox {
+.prefwindow[type="child"] > .prefpane {
+  -moz-box-flex: 1;
+  overflow: -moz-hidden-unscrollable;
+}
+
+.prefpane > groupbox + groupbox {
   margin-top: 16px;
 }
 
 groupbox + groupbox > .groupbox-body,
 groupbox + vbox groupbox > .groupbox-body {
   margin-top: 4px;
 }
 
--- a/browser/themes/windows/preferences/preferences.css
+++ b/browser/themes/windows/preferences/preferences.css
@@ -1,15 +1,48 @@
 /*
 # -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 # 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/.
 */
 
+/* Pref Window & Pane */
+.prefwindow {
+  padding: 0px;
+}
+
+.prefwindow[type="child"] {
+  padding-top: 8px;
+  padding-bottom: 10px;
+  padding-inline-start: 8px;
+  padding-inline-end: 10px;
+}
+
+.prefpane {
+  padding-top: 8px;
+  padding-bottom: 10px;
+  padding-inline-start: 8px;
+  padding-inline-end: 10px;
+}
+
+.prefwindow[type="child"] > .prefpane {
+  padding: 0px;
+}
+
+.dialog-button-box {
+  padding-bottom: 10px;
+  padding-inline-start: 8px;
+  padding-inline-end: 10px;
+}
+
+.prefwindow[type="child"] .dialog-button-box {
+  padding: 0px;
+}
+
 /* General Pane */
 
 #useFirefoxSync,
 #getStarted {
   font-size: 90%;
 }
 
 #isNotDefaultLabel {
@@ -18,18 +51,17 @@
 
 /* Content Pane */
 #translationAttributionImage {
   width: 70px;
   cursor: pointer;
 }
 
 /* Modeless Window Dialogs */
-.windowDialog,
-.windowDialog prefpane {
+.windowDialog {
   padding: 0;
 }
 
 .contentPane {
   margin: 9px 8px 5px;
 }
 
 .actionButtons {
--- a/browser/themes/windows/sanitizeDialog.css
+++ b/browser/themes/windows/sanitizeDialog.css
@@ -80,14 +80,14 @@
 /* Make the item list the same width as the warning box */
 #itemList {
   margin-inline-start: 0;
   margin-inline-end: 0;
 }
 
 
 /* Align the last dialog button with the end of the warning box */
-.prefWindow-dlgbuttons {
+.dialog-button-box {
   margin-inline-end: 0;
 }
 .dialog-button[dlgtype="cancel"] {
   margin-inline-end: 0;
 }
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_anonymous_content.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_anonymous_content.py
@@ -77,14 +77,14 @@ class TestAnonymousNodes(WindowManagerMi
         self.assertListEqual([], start_node.find_elements(*not_existent))
 
         # By using the default start node
         self.assertListEqual(buttons, self.marionette.find_elements(*dialog_buttons))
         self.assertListEqual([], self.marionette.find_elements(*not_existent))
 
     def test_find_anonymous_children(self):
         self.assertEquals(HTMLElement, type(self.marionette.find_element(By.ANON, None)))
-        self.assertEquals(2, len(self.marionette.find_elements(By.ANON, None)))
+        self.assertEquals(3, len(self.marionette.find_elements(By.ANON, None)))
 
         frame = self.marionette.find_element(By.ID, "framebox")
         with self.assertRaises(NoSuchElementException):
             frame.find_element(By.ANON, None)
         self.assertListEqual([], frame.find_elements(By.ANON, None))
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -48,16 +48,17 @@ toolkit.jar:
    content/global/datepicker.xhtml
 #ifndef MOZ_FENNEC
    content/global/editMenuOverlay.js
 *  content/global/editMenuOverlay.xul
 #endif
    content/global/filepicker.properties
    content/global/globalOverlay.js
    content/global/mozilla.xhtml
+   content/global/preferencesBindings.js
    content/global/process-content.js
    content/global/resetProfile.css
    content/global/resetProfile.js
    content/global/resetProfile.xul
    content/global/resetProfileProgress.xul
    content/global/TopLevelVideoDocument.js
    content/global/timepicker.xhtml
    content/global/treeUtils.js
@@ -82,17 +83,16 @@ toolkit.jar:
    content/global/bindings/general.xml         (widgets/general.xml)
    content/global/bindings/groupbox.xml        (widgets/groupbox.xml)
    content/global/bindings/listbox.xml         (widgets/listbox.xml)
    content/global/bindings/menu.xml            (widgets/menu.xml)
    content/global/bindings/menulist.xml        (widgets/menulist.xml)
    content/global/bindings/notification.xml    (widgets/notification.xml)
    content/global/bindings/numberbox.xml       (widgets/numberbox.xml)
    content/global/bindings/popup.xml           (widgets/popup.xml)
-*  content/global/bindings/preferences.xml     (widgets/preferences.xml)
    content/global/bindings/progressmeter.xml   (widgets/progressmeter.xml)
    content/global/bindings/radio.xml           (widgets/radio.xml)
    content/global/bindings/remote-browser.xml  (widgets/remote-browser.xml)
    content/global/bindings/resizer.xml         (widgets/resizer.xml)
    content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
    content/global/bindings/scale.xml           (widgets/scale.xml)
    content/global/bindings/scrollbar.xml       (widgets/scrollbar.xml)
    content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
new file mode 100644
--- /dev/null
+++ b/toolkit/content/preferencesBindings.js
@@ -0,0 +1,615 @@
+/* - 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/. */
+
+"use strict";
+
+// We attach Preferences to the window object so other contexts (tests, JSMs)
+// have access to it.
+const Preferences = window.Preferences = (function() {
+  const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+
+  Cu.import("resource://gre/modules/EventEmitter.jsm");
+  Cu.import("resource://gre/modules/Services.jsm");
+  Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+  XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
+                                    "resource://gre/modules/DeferredTask.jsm");
+
+  function getElementsByAttribute(name, value) {
+    // If we needed to defend against arbitrary values, we would escape
+    // double quotes (") and escape characters (\) in them, i.e.:
+    //   ${value.replace(/["\\]/g, '\\$&')}
+    return value ? document.querySelectorAll(`[${name}="${value}"]`)
+                 : document.querySelectorAll(`[${name}]`);
+  }
+
+  const domContentLoadedPromise = new Promise(resolve => {
+    window.addEventListener("DOMContentLoaded", resolve, { capture: true, once: true });
+  });
+
+  const Preferences = {
+    _all: {},
+
+    _add(prefInfo) {
+      if (this._all[prefInfo.id]) {
+        throw new Error(`preference with id '${prefInfo.id}' already added`);
+      }
+      const pref = new Preference(prefInfo);
+      this._all[pref.id] = pref;
+      domContentLoadedPromise.then(() => { pref.updateElements(); });
+      return pref;
+    },
+
+    add(prefInfo) {
+      const pref = this._add(prefInfo);
+      return pref;
+    },
+
+    addAll(prefInfos) {
+      prefInfos.map(prefInfo => this._add(prefInfo));
+    },
+
+    get(id) {
+      return this._all[id] || null;
+    },
+
+    getAll() {
+      return Object.values(this._all);
+    },
+
+    defaultBranch: Services.prefs.getDefaultBranch(""),
+
+    get type() {
+      return document.documentElement.getAttribute("type") || "";
+    },
+
+    get instantApply() {
+      // The about:preferences page forces instantApply.
+      if (this._instantApplyForceEnabled) {
+        return true;
+      }
+
+      // Dialogs of type="child" are never instantApply.
+      if (this.type === "child") {
+        return false;
+      }
+
+      // All other pref windows observe the value of the instantApply
+      // preference.  Note that, as of this writing, the only such windows
+      // are in tests, so it should be possible to remove the pref
+      // (and forceEnableInstantApply) in favor of always applying in a parent
+      // and never applying in a child.
+      return Services.prefs.getBoolPref("browser.preferences.instantApply");
+    },
+
+    _instantApplyForceEnabled: false,
+
+    // Override the computed value of instantApply for this window.
+    forceEnableInstantApply() {
+      this._instantApplyForceEnabled = true;
+    },
+
+    observe(subject, topic, data) {
+      const pref = this._all[data];
+      if (pref) {
+        pref.value = pref.valueFromPreferences;
+      }
+    },
+
+    onDOMContentLoaded() {
+      // Iterate elements with a "preference" attribute and log an error
+      // if there isn't a corresponding Preference object in order to catch
+      // any cases of elements referencing preferences that haven't (yet?)
+      // been registered.
+      //
+      // TODO: remove this code once we determine that there are no such
+      // elements (or resolve any bugs that cause this behavior).
+      //
+      const elements = getElementsByAttribute("preference");
+      for (const element of elements) {
+        const id = element.getAttribute("preference");
+        const pref = this.get(id);
+        if (!pref) {
+          console.error(`Missing preference for ID ${id}`);
+        }
+      }
+    },
+
+    onUnload() {
+      Services.prefs.removeObserver("", this);
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([
+      Ci.nsITimerCallback,
+      Ci.nsIObserver,
+    ]),
+
+    _deferredValueUpdateElements: new Set(),
+
+    writePreferences(aFlushToDisk) {
+      // Write all values to preferences.
+      if (this._deferredValueUpdateElements.size) {
+        this._finalizeDeferredElements();
+      }
+
+      const preferences = Preferences.getAll();
+      for (const preference of preferences) {
+        preference.batching = true;
+        preference.valueFromPreferences = preference.value;
+        preference.batching = false;
+      }
+      if (aFlushToDisk) {
+        Services.prefs.savePrefFile(null);
+      }
+    },
+
+    getPreferenceElement(aStartElement) {
+      let temp = aStartElement;
+      while (temp && temp.nodeType == Node.ELEMENT_NODE &&
+             !temp.hasAttribute("preference"))
+        temp = temp.parentNode;
+      return temp && temp.nodeType == Node.ELEMENT_NODE ?
+             temp : aStartElement;
+    },
+
+    _deferredValueUpdate(aElement) {
+      delete aElement._deferredValueUpdateTask;
+      const prefID = aElement.getAttribute("preference");
+      const preference = Preferences.get(prefID);
+      const prefVal = preference.getElementValue(aElement);
+      preference.value = prefVal;
+      this._deferredValueUpdateElements.delete(aElement);
+    },
+
+    _finalizeDeferredElements() {
+      for (const el of this._deferredValueUpdateElements) {
+        if (el._deferredValueUpdateTask) {
+          el._deferredValueUpdateTask.finalize();
+        }
+      }
+    },
+
+    userChangedValue(aElement) {
+      const element = this.getPreferenceElement(aElement);
+      if (element.hasAttribute("preference")) {
+        if (element.getAttribute("delayprefsave") != "true") {
+          const preference = Preferences.get(element.getAttribute("preference"));
+          const prefVal = preference.getElementValue(element);
+          preference.value = prefVal;
+        } else {
+          if (!element._deferredValueUpdateTask) {
+            element._deferredValueUpdateTask =
+              new DeferredTask(this._deferredValueUpdate.bind(this, element), 1000);
+            this._deferredValueUpdateElements.add(element);
+          } else {
+            // Each time the preference is changed, restart the delay.
+            element._deferredValueUpdateTask.disarm();
+          }
+          element._deferredValueUpdateTask.arm();
+        }
+      }
+    },
+
+    onCommand(event) {
+      // This "command" event handler tracks changes made to preferences by
+      // the user in this window.
+      if (event.sourceEvent)
+        event = event.sourceEvent;
+      this.userChangedValue(event.target);
+    },
+
+    onSelect(event) {
+      // This "select" event handler tracks changes made to colorpicker
+      // preferences by the user in this window.
+      if (event.target.localName == "colorpicker")
+        this.userChangedValue(event.target);
+    },
+
+    onChange(event) {
+      // This "change" event handler tracks changes made to preferences by
+      // the user in this window.
+      this.userChangedValue(event.target);
+    },
+
+    onInput(event) {
+      // This "input" event handler tracks changes made to preferences by
+      // the user in this window.
+      this.userChangedValue(event.target);
+    },
+
+    _fireEvent(aEventName, aTarget) {
+      // Panel loaded, synthesize a load event.
+      try {
+        const event = document.createEvent("Events");
+        event.initEvent(aEventName, true, true);
+        let cancel = !aTarget.dispatchEvent(event);
+        if (aTarget.hasAttribute("on" + aEventName)) {
+          const fn = new Function("event", aTarget.getAttribute("on" + aEventName));
+          const rv = fn.call(aTarget, event);
+          if (rv == false)
+            cancel = true;
+        }
+        return !cancel;
+      } catch (e) {
+        Cu.reportError(e);
+      }
+      return false;
+    },
+
+    onDialogAccept(event) {
+      if (!this._fireEvent("beforeaccept", document.documentElement)) {
+        event.preventDefault();
+        return false;
+      }
+      this.writePreferences(true);
+      return true;
+    },
+
+    close(event) {
+      if (Preferences.instantApply)
+        window.close();
+      event.stopPropagation();
+      event.preventDefault();
+    },
+
+    handleEvent(event) {
+      switch (event.type) {
+        case "change": return this.onChange(event);
+        case "command": return this.onCommand(event);
+        case "dialogaccept": return this.onDialogAccept(event);
+        case "input": return this.onInput(event);
+        case "select": return this.onSelect(event);
+        case "unload": return this.onUnload(event);
+        default: return undefined;
+      }
+    },
+  };
+
+  Services.prefs.addObserver("", Preferences);
+  domContentLoadedPromise.then(result => Preferences.onDOMContentLoaded(result));
+  window.addEventListener("change", Preferences);
+  window.addEventListener("command", Preferences);
+  window.addEventListener("dialogaccept", Preferences);
+  window.addEventListener("input", Preferences);
+  window.addEventListener("select", Preferences);
+  window.addEventListener("unload", Preferences, { once: true });
+
+  class Preference extends EventEmitter {
+    constructor({ id, name, type, inverted, disabled }) {
+      super();
+      this.on("change", this.onChange.bind(this));
+
+      this._value = null;
+      this.readonly = false;
+      this._useDefault = false;
+      this.batching = false;
+
+      this.id = id;
+      this._name = name || this.id;
+      this.type = type;
+      this.inverted = !!inverted;
+      this._disabled = !!disabled;
+
+      // if the element has been inserted without the name attribute set,
+      // we have nothing to do here
+      if (!this.name) {
+        throw new Error(`preference with id '${id}' doesn't have name`);
+      }
+
+      // In non-instant apply mode, we must try and use the last saved state
+      // from any previous opens of a child dialog instead of the value from
+      // preferences, to pick up any edits a user may have made.
+
+      if (Preferences.type == "child" && window.opener &&
+          Services.scriptSecurityManager.isSystemPrincipal(window.opener.document.nodePrincipal)) {
+        // Try to find the preference in the parent window.
+        const preference = window.opener.Preferences.get(this.name);
+
+        // Don't use the value setter here, we don't want updateElements to be
+        // prematurely fired.
+        this._value = preference ? preference.value : this.valueFromPreferences;
+      } else
+        this._value = this.valueFromPreferences;
+    }
+
+    reset() {
+      // defer reset until preference update
+      this.value = undefined;
+    }
+
+    _reportUnknownType() {
+      const msg = `Preference with id=${this.id} and name=${this.name} has unknown type ${this.type}.`;
+      Services.console.logStringMessage(msg);
+    }
+
+    setElementValue(aElement) {
+      if (this.locked)
+        aElement.disabled = true;
+
+      if (!this.isElementEditable(aElement))
+        return;
+
+      let rv = undefined;
+      if (aElement.hasAttribute("onsyncfrompreference")) {
+        // Value changed, synthesize an event
+        try {
+          const event = document.createEvent("Events");
+          event.initEvent("syncfrompreference", true, true);
+          const f = new Function("event",
+                               aElement.getAttribute("onsyncfrompreference"));
+          rv = f.call(aElement, event);
+        } catch (e) {
+          Cu.reportError(e);
+        }
+      }
+      let val = rv;
+      if (val === undefined)
+        val = Preferences.instantApply ? this.valueFromPreferences : this.value;
+      // if the preference is marked for reset, show default value in UI
+      if (val === undefined)
+        val = this.defaultValue;
+
+      /**
+       * Initialize a UI element property with a value. Handles the case
+       * where an element has not yet had a XBL binding attached for it and
+       * the property setter does not yet exist by setting the same attribute
+       * on the XUL element using DOM apis and assuming the element's
+       * constructor or property getters appropriately handle this state.
+       */
+      function setValue(element, attribute, value) {
+        if (attribute in element)
+          element[attribute] = value;
+        else
+          element.setAttribute(attribute, value);
+      }
+      if (aElement.localName == "checkbox" ||
+          aElement.localName == "listitem")
+        setValue(aElement, "checked", val);
+      else if (aElement.localName == "colorpicker")
+        setValue(aElement, "color", val);
+      else if (aElement.localName == "textbox") {
+        // XXXmano Bug 303998: Avoid a caret placement issue if either the
+        // preference observer or its setter calls updateElements as a result
+        // of the input event handler.
+        if (aElement.value !== val)
+          setValue(aElement, "value", val);
+      } else
+        setValue(aElement, "value", val);
+    }
+
+    getElementValue(aElement) {
+      if (aElement.hasAttribute("onsynctopreference")) {
+        // Value changed, synthesize an event
+        try {
+          const event = document.createEvent("Events");
+          event.initEvent("synctopreference", true, true);
+          const f = new Function("event",
+                               aElement.getAttribute("onsynctopreference"));
+          const rv = f.call(aElement, event);
+          if (rv !== undefined)
+            return rv;
+        } catch (e) {
+          Cu.reportError(e);
+        }
+      }
+
+      /**
+       * Read the value of an attribute from an element, assuming the
+       * attribute is a property on the element's node API. If the property
+       * is not present in the API, then assume its value is contained in
+       * an attribute, as is the case before a binding has been attached.
+       */
+      function getValue(element, attribute) {
+        if (attribute in element)
+          return element[attribute];
+        return element.getAttribute(attribute);
+      }
+      let value;
+      if (aElement.localName == "checkbox" ||
+          aElement.localName == "listitem")
+        value = getValue(aElement, "checked");
+      else if (aElement.localName == "colorpicker")
+        value = getValue(aElement, "color");
+      else
+        value = getValue(aElement, "value");
+
+      switch (this.type) {
+      case "int":
+        return parseInt(value, 10) || 0;
+      case "bool":
+        return typeof(value) == "boolean" ? value : value == "true";
+      }
+      return value;
+    }
+
+    isElementEditable(aElement) {
+      switch (aElement.localName) {
+      case "checkbox":
+      case "colorpicker":
+      case "radiogroup":
+      case "textbox":
+      case "listitem":
+      case "listbox":
+      case "menulist":
+        return true;
+      }
+      return aElement.getAttribute("preference-editable") == "true";
+    }
+
+    updateElements() {
+      if (!this.id)
+        return;
+
+      // This "change" event handler tracks changes made to preferences by
+      // sources other than the user in this window.
+      const elements = getElementsByAttribute("preference", this.id);
+      for (const element of elements)
+        this.setElementValue(element);
+    }
+
+    onChange() {
+      this.updateElements();
+    }
+
+    get name() {
+      return this._name;
+    }
+
+    set name(val) {
+      if (val == this.name)
+        return val;
+
+      this._name = val;
+
+      return val;
+    }
+
+    get value() {
+      return this._value;
+    }
+
+    set value(val) {
+      if (this.value !== val) {
+        this._value = val;
+        if (Preferences.instantApply)
+          this.valueFromPreferences = val;
+        this.emit("change");
+      }
+      return val;
+    }
+
+    get locked() {
+      return Services.prefs.prefIsLocked(this.name);
+    }
+
+    get disabled() {
+      return this._disabled;
+    }
+
+    set disabled(val) {
+      this._disabled = !!val;
+
+      if (!this.id)
+        return val;
+
+      const elements = getElementsByAttribute("preference", this.id);
+      for (const element of elements) {
+        element.disabled = val;
+
+        const labels = getElementsByAttribute("control", element.id);
+        for (const label of labels)
+          label.disabled = val;
+      }
+
+      return val;
+    }
+
+    get hasUserValue() {
+      return Services.prefs.prefHasUserValue(this.name) &&
+             this.value !== undefined;
+    }
+
+    get defaultValue() {
+      this._useDefault = true;
+      const val = this.valueFromPreferences;
+      this._useDefault = false;
+      return val;
+    }
+
+    get _branch() {
+      return this._useDefault ? Preferences.defaultBranch : Services.prefs;
+    }
+
+    get valueFromPreferences() {
+      try {
+        // Force a resync of value with preferences.
+        switch (this.type) {
+        case "int":
+          return this._branch.getIntPref(this.name);
+        case "bool": {
+          const val = this._branch.getBoolPref(this.name);
+          return this.inverted ? !val : val;
+        }
+        case "wstring":
+          return this._branch
+                     .getComplexValue(this.name, Ci.nsIPrefLocalizedString)
+                     .data;
+        case "string":
+        case "unichar":
+          return this._branch.getStringPref(this.name);
+        case "fontname": {
+          const family = this._branch.getStringPref(this.name);
+          const fontEnumerator = Cc["@mozilla.org/gfx/fontenumerator;1"]
+                               .createInstance(Ci.nsIFontEnumerator);
+          return fontEnumerator.getStandardFamilyName(family);
+        }
+        case "file": {
+          const f = this._branch
+                      .getComplexValue(this.name, Ci.nsIFile);
+          return f;
+        }
+        default:
+          this._reportUnknownType();
+        }
+      } catch (e) { }
+      return null;
+    }
+
+    set valueFromPreferences(val) {
+      // Exit early if nothing to do.
+      if (this.readonly || this.valueFromPreferences == val)
+        return val;
+
+      // The special value undefined means 'reset preference to default'.
+      if (val === undefined) {
+        Services.prefs.clearUserPref(this.name);
+        return val;
+      }
+
+      // Force a resync of preferences with value.
+      switch (this.type) {
+      case "int":
+        Services.prefs.setIntPref(this.name, val);
+        break;
+      case "bool":
+        Services.prefs.setBoolPref(this.name, this.inverted ? !val : val);
+        break;
+      case "wstring": {
+        const pls = Cc["@mozilla.org/pref-localizedstring;1"]
+                  .createInstance(Ci.nsIPrefLocalizedString);
+        pls.data = val;
+        Services.prefs
+            .setComplexValue(this.name, Ci.nsIPrefLocalizedString, pls);
+        break;
+      }
+      case "string":
+      case "unichar":
+      case "fontname":
+        Services.prefs.setStringPref(this.name, val);
+        break;
+      case "file": {
+        let lf;
+        if (typeof(val) == "string") {
+          lf = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+          lf.persistentDescriptor = val;
+          if (!lf.exists())
+            lf.initWithPath(val);
+        } else
+          lf = val.QueryInterface(Ci.nsIFile);
+        Services.prefs
+            .setComplexValue(this.name, Ci.nsIFile, lf);
+        break;
+      }
+      default:
+        this._reportUnknownType();
+      }
+      if (!this.batching) {
+        Services.prefs.savePrefFile(null);
+      }
+      return val;
+    }
+  }
+
+  return Preferences;
+}.bind({})());
--- a/toolkit/content/resetProfile.xul
+++ b/toolkit/content/resetProfile.xul
@@ -1,15 +1,15 @@
 <?xml version="1.0"?>
 
 <!-- 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/. -->
 
-<!DOCTYPE prefwindow [
+<!DOCTYPE dialog [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
 %brandDTD;
 <!ENTITY % resetProfileDTD SYSTEM "chrome://global/locale/resetProfile.dtd" >
 %resetProfileDTD;
 ]>
 
 <?xml-stylesheet href="chrome://global/skin/"?>
 <?xml-stylesheet href="chrome://global/content/resetProfile.css"?>
--- a/toolkit/content/tests/chrome/test_preferences.xul
+++ b/toolkit/content/tests/chrome/test_preferences.xul
@@ -123,38 +123,43 @@
       return result;
     }
 
     function GetXULElement(aPrefWindow, aID)
     {
       return aPrefWindow.document.getElementById(aID);
     }
 
+    function GetPreference(aPrefWindow, aID)
+    {
+      return aPrefWindow.Preferences.get(aID);
+    }
+
     function WritePrefsToPreferences(aPrefWindow, aPrefValueSet)
     {
-      // write preference data into <preference>s
-      GetXULElement(aPrefWindow, "tests.static_preference_int"    ).value = aPrefValueSet.int;
-      GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).value = aPrefValueSet.bool;
-      GetXULElement(aPrefWindow, "tests.static_preference_string" ).value = aPrefValueSet.string;
-      GetXULElement(aPrefWindow, "tests.static_preference_unichar").value = aPrefValueSet.unichar;
-      GetXULElement(aPrefWindow, "tests.static_preference_wstring").value = aPrefValueSet.wstring_data;
-      GetXULElement(aPrefWindow, "tests.static_preference_file"   ).value = aPrefValueSet.file_data;
+      // write preference data into Preference instances
+      GetPreference(aPrefWindow, "tests.static_preference_int"    ).value = aPrefValueSet.int;
+      GetPreference(aPrefWindow, "tests.static_preference_bool"   ).value = aPrefValueSet.bool;
+      GetPreference(aPrefWindow, "tests.static_preference_string" ).value = aPrefValueSet.string;
+      GetPreference(aPrefWindow, "tests.static_preference_unichar").value = aPrefValueSet.unichar;
+      GetPreference(aPrefWindow, "tests.static_preference_wstring").value = aPrefValueSet.wstring_data;
+      GetPreference(aPrefWindow, "tests.static_preference_file"   ).value = aPrefValueSet.file_data;
     }
 
     function ReadPrefsFromPreferences(aPrefWindow)
     {
-      // read preference data from <preference>s
+      // read preference data from Preference instances
       var result =
       {
-        int:          GetXULElement(aPrefWindow, "tests.static_preference_int"    ).value,
-        bool:         GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).value,
-        string:       GetXULElement(aPrefWindow, "tests.static_preference_string" ).value,
-        unichar:      GetXULElement(aPrefWindow, "tests.static_preference_unichar").value,
-        wstring_data: GetXULElement(aPrefWindow, "tests.static_preference_wstring").value,
-        file_data:    GetXULElement(aPrefWindow, "tests.static_preference_file"   ).value,
+        int:          GetPreference(aPrefWindow, "tests.static_preference_int"    ).value,
+        bool:         GetPreference(aPrefWindow, "tests.static_preference_bool"   ).value,
+        string:       GetPreference(aPrefWindow, "tests.static_preference_string" ).value,
+        unichar:      GetPreference(aPrefWindow, "tests.static_preference_unichar").value,
+        wstring_data: GetPreference(aPrefWindow, "tests.static_preference_wstring").value,
+        file_data:    GetPreference(aPrefWindow, "tests.static_preference_file"   ).value,
         wstring: Components.classes["@mozilla.org/pref-localizedstring;1"]
                            .createInstance(Components.interfaces.nsIPrefLocalizedString),
         file:    Components.classes["@mozilla.org/file/local;1"]
                            .createInstance(Components.interfaces.nsIFile)
       }
       result.wstring.data = result.wstring_data;
       SafeFileInit(result.file, result.file_data);
       return result;
@@ -168,17 +173,17 @@
       GetXULElement(aPrefWindow, "static_element_string" ).value   = aPrefValueSet.string;
       GetXULElement(aPrefWindow, "static_element_unichar").value   = aPrefValueSet.unichar;
       GetXULElement(aPrefWindow, "static_element_wstring").value   = aPrefValueSet.wstring_data;
       GetXULElement(aPrefWindow, "static_element_file"   ).value   = aPrefValueSet.file_data;
     }
 
     function ReadPrefsFromUI(aPrefWindow)
     {
-      // read preference data from <preference>s
+      // read preference data from Preference instances
       var result =
       {
         int:          GetXULElement(aPrefWindow, "static_element_int"    ).value,
         bool:         GetXULElement(aPrefWindow, "static_element_bool"   ).checked,
         string:       GetXULElement(aPrefWindow, "static_element_string" ).value,
         unichar:      GetXULElement(aPrefWindow, "static_element_unichar").value,
         wstring_data: GetXULElement(aPrefWindow, "static_element_wstring").value,
         file_data:    GetXULElement(aPrefWindow, "static_element_file"   ).value,
@@ -192,17 +197,17 @@
       return result;
     }
 
 
     function RunInstantPrefTest(aPrefWindow)
     {
       // remark: there's currently no UI element binding for files
 
-      // were all <preferences> correctly initialized?
+      // were all Preference instances correctly initialized?
       var expected = kPrefValueSet1;
       var found    = ReadPrefsFromPreferences(aPrefWindow);
       ok(found.int          === expected.int,          "instant pref init int"    );
       ok(found.bool         === expected.bool,         "instant pref init bool"   );
       ok(found.string       === expected.string,       "instant pref init string" );
       ok(found.unichar      === expected.unichar,      "instant pref init unichar");
       ok(found.wstring_data === expected.wstring_data, "instant pref init wstring");
       todo(found.file_data  === expected.file_data,    "instant pref init file"   );
@@ -215,17 +220,17 @@
       ok(found.unichar      == expected.unichar,      "instant element init unichar");
       ok(found.wstring_data == expected.wstring_data, "instant element init wstring");
       todo(found.file_data  == expected.file_data,    "instant element init file"   );
 
       // do some changes in the UI
       expected = kPrefValueSet2;
       WritePrefsToUI(aPrefWindow, expected);
 
-      // UI changes should get passed to the <preference>s,
+      // UI changes should get passed to the Preference instances,
       // but currently they aren't if the changes are made programmatically
       // (the handlers preference.change/prefpane.input and prefpane.change
       //  are called for manual changes, though).
       found = ReadPrefsFromPreferences(aPrefWindow);
       todo(found.int          === expected.int,          "instant change pref int"    );
       todo(found.bool         === expected.bool,         "instant change pref bool"   );
       todo(found.string       === expected.string,       "instant change pref string" );
       todo(found.unichar      === expected.unichar,      "instant change pref unichar");
@@ -238,22 +243,22 @@
       todo(found.int          === expected.int,          "instant change element int"    );
       todo(found.bool         === expected.bool,         "instant change element bool"   );
       todo(found.string       === expected.string,       "instant change element string" );
       todo(found.unichar      === expected.unichar,      "instant change element unichar");
       todo(found.wstring_data === expected.wstring_data, "instant change element wstring");
       todo(found.file_data    === expected.file_data,    "instant change element file"   );
 
       // try resetting the prefs to default values (which should be empty here)
-      GetXULElement(aPrefWindow, "tests.static_preference_int"    ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_string" ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_unichar").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_wstring").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_file"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_int"    ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_bool"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_string" ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_unichar").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_wstring").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_file"   ).reset();
 
       // check system
       expected = CreateEmptyPrefValueSet();
       found    = ReadPrefsFromSystem();
       ok(found.int          === expected.int,          "instant reset system int"    );
       ok(found.bool         === expected.bool,         "instant reset system bool"   );
       ok(found.string       === expected.string,       "instant reset system string" );
       ok(found.unichar      === expected.unichar,      "instant reset system unichar");
@@ -278,35 +283,35 @@
       ok(found.int          === expected.int,          "instant reset element int"    );
       ok(found.bool         === expected.bool,         "instant reset element bool"   );
       ok(found.string       === expected.string,       "instant reset element string" );
       ok(found.unichar      === expected.unichar,      "instant reset element unichar");
       ok(found.wstring_data === expected.wstring_data, "instant reset element wstring");
 //      ok(found.file_data    === expected.file_data,    "instant reset element file"   );
 
       // check hasUserValue
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_int"    ).hasUserValue === false, "instant reset hasUserValue int"    );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).hasUserValue === false, "instant reset hasUserValue bool"   );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_string" ).hasUserValue === false, "instant reset hasUserValue string" );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_unichar").hasUserValue === false, "instant reset hasUserValue unichar");
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_wstring").hasUserValue === false, "instant reset hasUserValue wstring");
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_file"   ).hasUserValue === false, "instant reset hasUserValue file"   );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_int"    ).hasUserValue === false, "instant reset hasUserValue int"    );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_bool"   ).hasUserValue === false, "instant reset hasUserValue bool"   );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_string" ).hasUserValue === false, "instant reset hasUserValue string" );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_unichar").hasUserValue === false, "instant reset hasUserValue unichar");
+      ok(GetPreference(aPrefWindow, "tests.static_preference_wstring").hasUserValue === false, "instant reset hasUserValue wstring");
+      ok(GetPreference(aPrefWindow, "tests.static_preference_file"   ).hasUserValue === false, "instant reset hasUserValue file"   );
 
       // done with instant apply checks
     }
 
     function RunNonInstantPrefTestGeneral(aPrefWindow)
     {
       // Non-instant apply tests are harder: not only do we need to check that
       // fiddling with the values does *not* change the system settings, but
       // also that they *are* (not) set after closing (cancelling) the dialog...
 
       // remark: there's currently no UI element binding for files
 
-      // were all <preferences> correctly initialized?
+      // were all Preference instances correctly initialized?
       var expected = kPrefValueSet1;
       var found    = ReadPrefsFromPreferences(aPrefWindow);
       ok(found.int          === expected.int,          "non-instant pref init int"    );
       ok(found.bool         === expected.bool,         "non-instant pref init bool"   );
       ok(found.string       === expected.string,       "non-instant pref init string" );
       ok(found.unichar      === expected.unichar,      "non-instant pref init unichar");
       ok(found.wstring_data === expected.wstring_data, "non-instant pref init wstring");
       todo(found.file_data  === expected.file_data,    "non-instant pref init file"   );
@@ -319,17 +324,17 @@
       ok(found.unichar      == expected.unichar,      "non-instant element init unichar");
       ok(found.wstring_data == expected.wstring_data, "non-instant element init wstring");
       todo(found.file_data  == expected.file_data,    "non-instant element init file"   );
 
       // do some changes in the UI
       expected = kPrefValueSet2;
       WritePrefsToUI(aPrefWindow, expected);
 
-      // UI changes should get passed to the <preference>s,
+      // UI changes should get passed to the Preference instances,
       // but currently they aren't if the changes are made programmatically
       // (the handlers preference.change/prefpane.input and prefpane.change
       //  are called for manual changes, though).
       found = ReadPrefsFromPreferences(aPrefWindow);
       todo(found.int          === expected.int,          "non-instant change pref int"    );
       todo(found.bool         === expected.bool,         "non-instant change pref bool"   );
       todo(found.string       === expected.string,       "non-instant change pref string" );
       todo(found.unichar      === expected.unichar,      "non-instant change pref unichar");
@@ -343,22 +348,22 @@
       ok(found.int          === expected.int,          "non-instant change element int"    );
       ok(found.bool         === expected.bool,         "non-instant change element bool"   );
       ok(found.string       === expected.string,       "non-instant change element string" );
       ok(found.unichar      === expected.unichar,      "non-instant change element unichar");
       ok(found.wstring_data === expected.wstring_data, "non-instant change element wstring");
       todo(found.file_data  === expected.file_data,    "non-instant change element file"   );
 
       // try resetting the prefs to default values (which should be empty here)
-      GetXULElement(aPrefWindow, "tests.static_preference_int"    ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_string" ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_unichar").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_wstring").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_file"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_int"    ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_bool"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_string" ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_unichar").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_wstring").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_file"   ).reset();
 
       // check system: the current values *MUST NOT* change
       expected = kPrefValueSet1;
       found    = ReadPrefsFromSystem();
       ok(found.int          === expected.int,          "non-instant reset system int"    );
       ok(found.bool         === expected.bool,         "non-instant reset system bool"   );
       ok(found.string       === expected.string,       "non-instant reset system string" );
       ok(found.unichar      === expected.unichar,      "non-instant reset system unichar");
@@ -383,46 +388,46 @@
       ok(found.int          === expected.int,          "non-instant reset element int"    );
       ok(found.bool         === expected.bool,         "non-instant reset element bool"   );
       ok(found.string       === expected.string,       "non-instant reset element string" );
       ok(found.unichar      === expected.unichar,      "non-instant reset element unichar");
       ok(found.wstring_data === expected.wstring_data, "non-instant reset element wstring");
 //      ok(found.file_data    === expected.file_data,    "non-instant reset element file"   );
 
       // check hasUserValue
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_int"    ).hasUserValue === false, "non-instant reset hasUserValue int"    );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).hasUserValue === false, "non-instant reset hasUserValue bool"   );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_string" ).hasUserValue === false, "non-instant reset hasUserValue string" );
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_unichar").hasUserValue === false, "non-instant reset hasUserValue unichar");
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_wstring").hasUserValue === false, "non-instant reset hasUserValue wstring");
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_file"   ).hasUserValue === false, "non-instant reset hasUserValue file"   );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_int"    ).hasUserValue === false, "non-instant reset hasUserValue int"    );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_bool"   ).hasUserValue === false, "non-instant reset hasUserValue bool"   );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_string" ).hasUserValue === false, "non-instant reset hasUserValue string" );
+      ok(GetPreference(aPrefWindow, "tests.static_preference_unichar").hasUserValue === false, "non-instant reset hasUserValue unichar");
+      ok(GetPreference(aPrefWindow, "tests.static_preference_wstring").hasUserValue === false, "non-instant reset hasUserValue wstring");
+      ok(GetPreference(aPrefWindow, "tests.static_preference_file"   ).hasUserValue === false, "non-instant reset hasUserValue file"   );
     }
 
     function RunNonInstantPrefTestClose(aPrefWindow)
     {
       WritePrefsToPreferences(aPrefWindow, kPrefValueSet2);
     }
 
     function RunCheckCommandRedirect(aPrefWindow)
     {
       GetXULElement(aPrefWindow, "checkbox").click();
-      ok(GetXULElement(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
+      ok(GetPreference(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
       GetXULElement(aPrefWindow, "checkbox").click();
-      ok(!GetXULElement(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
+      ok(!GetPreference(aPrefWindow, "tests.static_preference_bool").value, "redirected command bool");
     }
 
     function RunResetPrefTest(aPrefWindow)
     {
       // try resetting the prefs to default values
-      GetXULElement(aPrefWindow, "tests.static_preference_int"    ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_bool"   ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_string" ).reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_unichar").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_wstring").reset();
-      GetXULElement(aPrefWindow, "tests.static_preference_file"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_int"    ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_bool"   ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_string" ).reset();
+      GetPreference(aPrefWindow, "tests.static_preference_unichar").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_wstring").reset();
+      GetPreference(aPrefWindow, "tests.static_preference_file"   ).reset();
     }
 
     function InitTestPrefs(aInstantApply)
     {
       // set instant apply mode and init prefs to set 1
       kPref.setBoolPref("browser.preferences.instantApply", aInstantApply);
       WritePrefsToSystem(kPrefValueSet1);
     }
--- a/toolkit/content/tests/chrome/test_preferences_beforeaccept.xul
+++ b/toolkit/content/tests/chrome/test_preferences_beforeaccept.xul
@@ -12,18 +12,18 @@
   <![CDATA[
     SimpleTest.waitForExplicitFinish();
     SpecialPowers.pushPrefEnv({"set":[["browser.preferences.instantApply", false]]}, function() {
 
     // No instant-apply for this test
     var prefWindow = openDialog("window_preferences_beforeaccept.xul", "", "", windowOnload);
 
     function windowOnload() {
-      var dialogShown = prefWindow.document.getElementById("tests.beforeaccept.dialogShown");
-      var called = prefWindow.document.getElementById("tests.beforeaccept.called");
+      var dialogShown = prefWindow.Preferences.get("tests.beforeaccept.dialogShown");
+      var called = prefWindow.Preferences.get("tests.beforeaccept.called");
       is(dialogShown.value, true, "dialog opened, shown pref set");
       is(dialogShown.valueFromPreferences, null, "shown pref not committed");
       is(called.value, null, "beforeaccept not yet called");
       is(called.valueFromPreferences, null, "beforeaccept not yet called, pref not committed");
 
       // try to accept the dialog, should fail the first time
       prefWindow.document.documentElement.acceptDialog();
       is(prefWindow.closed, false, "window not closed");
--- a/toolkit/content/tests/chrome/test_preferences_onsyncfrompreference.xul
+++ b/toolkit/content/tests/chrome/test_preferences_onsyncfrompreference.xul
@@ -32,17 +32,17 @@
       prefWindow.close();
     });
 
     // Onsyncfrompreference handler for the prefs
     function onSync() {
       for (let pref of PREFS) {
         // The `value` field of each <preference> element should be initialized by now.
 
-        is(SpecialPowers.getIntPref(pref), prefWindow.document.getElementById(pref).value,
+        is(SpecialPowers.getIntPref(pref), prefWindow.Preferences.get(pref).value,
            "Pref constructor was called correctly")
       }
 
       counter++;
 
       if (counter == PREFS.length) {
         SimpleTest.finish();
       }
--- a/toolkit/content/tests/chrome/window_preferences.xul
+++ b/toolkit/content/tests/chrome/window_preferences.xul
@@ -1,53 +1,44 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <!--
   XUL Widget Test for preferences window
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            windowtype="test:preferences"
-            buttons="accept,cancel"
-            onload="RunTest(window.arguments)"
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        windowtype="test:preferences"
+        buttons="accept,cancel"
+        onload="RunTest(window.arguments)"
 >
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
   <script type="application/javascript">
   <![CDATA[
     function RunTest(aArgs)
     {
       // run test
       aArgs[0](this);
       // close dialog
       document.documentElement[aArgs[1] ? "acceptDialog" : "cancelDialog"]();
     }
+
+    Preferences.addAll([
+      // one of each type known to Preference.valueFromPreferences
+      { id: "tests.static_preference_int", type: "int" },
+      { id: "tests.static_preference_bool", type: "bool" },
+      { id: "tests.static_preference_string", type: "string" },
+      { id: "tests.static_preference_wstring", type: "wstring" },
+      { id: "tests.static_preference_unichar", type: "unichar" },
+      { id: "tests.static_preference_file", type: "file" },
+    ]);
   ]]>
   </script>
 
-  <prefpane id="sample_pane" label="Sample Prefpane">
-    <preferences id="sample_preferences">
-      <!-- one of each type known to <preferences>.valueFromPreferences -->
-      <preference id  ="tests.static_preference_int"
-                  name="tests.static_preference_int"
-                  type="int"/>
-      <preference id  ="tests.static_preference_bool"
-                  name="tests.static_preference_bool"
-                  type="bool"/>
-      <preference id  ="tests.static_preference_string"
-                  name="tests.static_preference_string"
-                  type="string"/>
-      <preference id  ="tests.static_preference_wstring"
-                  name="tests.static_preference_wstring"
-                  type="wstring"/>
-      <preference id  ="tests.static_preference_unichar"
-                  name="tests.static_preference_unichar"
-                  type="unichar"/>
-      <preference id  ="tests.static_preference_file"
-                  name="tests.static_preference_file"
-                  type="file"/>
-    </preferences>
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane">
 
     <!-- one element for each preference type above -->
     <hbox>
       <label flex="1" value="int"/>
       <textbox id="static_element_int"     preference="tests.static_preference_int"/>
     </hbox>
     <hbox>
       <label flex="1" value="bool"/>
@@ -64,10 +55,10 @@
     <hbox>
       <label flex="1" value="unichar"/>
       <textbox id="static_element_unichar" preference="tests.static_preference_unichar"/>
     </hbox>
     <hbox>
       <label flex="1" value="file"/>
       <textbox id="static_element_file"    preference="tests.static_preference_file"/>
     </hbox>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/toolkit/content/tests/chrome/window_preferences2.xul
+++ b/toolkit/content/tests/chrome/window_preferences2.xul
@@ -1,25 +1,27 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <!--
   XUL Widget Test for preferences window
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            windowtype="test:preferences2"
-            buttons="accept,cancel"
-            onload="RunTest(window.arguments)"
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        windowtype="test:preferences2"
+        buttons="accept,cancel"
+        onload="RunTest(window.arguments)"
 >
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
   <script type="application/javascript">
   <![CDATA[
     function RunTest(aArgs)
     {
       // open child
-      document.documentElement.openSubDialog("window_preferences3.xul", "", {test: aArgs[0], accept: aArgs[1]});
+      openDialog("window_preferences3.xul", "", "modal,centerscreen,resizable=no", {test: aArgs[0], accept: aArgs[1]});
       // close dialog
       document.documentElement[aArgs[1] ? "acceptDialog" : "cancelDialog"]();
     }
   ]]>
   </script>
 
-  <prefpane id="sample_pane" label="Sample Prefpane"/>
-</prefwindow>
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane"/>
+</dialog>
--- a/toolkit/content/tests/chrome/window_preferences3.xul
+++ b/toolkit/content/tests/chrome/window_preferences3.xul
@@ -1,55 +1,45 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <!--
   XUL Widget Test for preferences window
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            windowtype="test:preferences3"
-            buttons="accept,cancel"
-            onload="RunTest(window.arguments)"
-            type="child"
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        windowtype="test:preferences3"
+        buttons="accept,cancel"
+        onload="RunTest(window.arguments)"
+        type="child"
 >
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
   <script type="application/javascript">
   <![CDATA[
     function RunTest(aArgs)
     {
       // run test
       aArgs[0].test(this);
       // close dialog
       document.documentElement[aArgs[0].accept ? "acceptDialog" : "cancelDialog"]();
     }
+
+    Preferences.addAll([
+      // one of each type known to Preference.valueFromPreferences
+      { id: "tests.static_preference_int", type: "int" },
+      { id: "tests.static_preference_bool", type: "bool" },
+      { id: "tests.static_preference_string", type: "string" },
+      { id: "tests.static_preference_wstring", type: "wstring" },
+      { id: "tests.static_preference_unichar", type: "unichar" },
+      { id: "tests.static_preference_file", type: "file" },
+    ]);
   ]]>
   </script>
 
-  <prefpane id="sample_pane" label="Sample Prefpane">
-    <preferences id="sample_preferences">
-      <!-- one of each type known to <preferences>.valueFromPreferences -->
-      <preference id  ="tests.static_preference_int"
-                  name="tests.static_preference_int"
-                  type="int"/>
-      <preference id  ="tests.static_preference_bool"
-                  name="tests.static_preference_bool"
-                  type="bool"/>
-      <preference id  ="tests.static_preference_string"
-                  name="tests.static_preference_string"
-                  type="string"/>
-      <preference id  ="tests.static_preference_wstring"
-                  name="tests.static_preference_wstring"
-                  type="wstring"/>
-      <preference id  ="tests.static_preference_unichar"
-                  name="tests.static_preference_unichar"
-                  type="unichar"/>
-      <preference id  ="tests.static_preference_file"
-                  name="tests.static_preference_file"
-                  type="file"/>
-    </preferences>
-
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane">
     <!-- one element for each preference type above -->
     <hbox>
       <label flex="1" value="int"/>
       <textbox id="static_element_int"     preference="tests.static_preference_int"/>
     </hbox>
     <hbox>
       <label flex="1" value="bool"/>
       <checkbox id="static_element_bool"   preference="tests.static_preference_bool"/>
@@ -65,10 +55,10 @@
     <hbox>
       <label flex="1" value="unichar"/>
       <textbox id="static_element_unichar" preference="tests.static_preference_unichar"/>
     </hbox>
     <hbox>
       <label flex="1" value="file"/>
       <textbox id="static_element_file"    preference="tests.static_preference_file"/>
     </hbox>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/toolkit/content/tests/chrome/window_preferences_beforeaccept.xul
+++ b/toolkit/content/tests/chrome/window_preferences_beforeaccept.xul
@@ -1,45 +1,44 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <!--
   XUL Widget Test for preferences window with beforeaccept
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            width="300" height="300"
-            windowtype="test:preferences"
-            buttons="accept,cancel"
-            onbeforeaccept="return beforeAccept();"
-            onload="onDialogLoad();"
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        width="300" height="300"
+        windowtype="test:preferences"
+        buttons="accept,cancel"
+        onbeforeaccept="return beforeAccept();"
+        onload="onDialogLoad();"
 >
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
   <script type="application/javascript">
   <![CDATA[
     function onDialogLoad() {
-      var pref = document.getElementById("tests.beforeaccept.dialogShown");
+      var pref = Preferences.get("tests.beforeaccept.dialogShown");
       pref.value = true;
 
       // call the onload handler we were passed
       window.arguments[0]();
     }
 
     function beforeAccept() {
-      var beforeAcceptPref = document.getElementById("tests.beforeaccept.called");
+      var beforeAcceptPref = Preferences.get("tests.beforeaccept.called");
       var oldValue = beforeAcceptPref.value;
       beforeAcceptPref.value = true;
 
       return !!oldValue;
     }
+
+    Preferences.addAll([
+      { id: "tests.beforeaccept.called", type: "bool" },
+      { id: "tests.beforeaccept.dialogShown", type: "bool" },
+    ]);
   ]]>
   </script>
 
-  <prefpane id="sample_pane" label="Sample Prefpane">
-    <preferences id="sample_preferences">
-      <preference id="tests.beforeaccept.called"
-                  name="tests.beforeaccept.called"
-                  type="bool"/>
-      <preference id="tests.beforeaccept.dialogShown"
-                  name="tests.beforeaccept.dialogShown"
-                  type="bool"/>
-    </preferences>
-  </prefpane>
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane">
+  </vbox>
   <label>Test Prefpane</label>
-</prefwindow>
+</dialog>
--- a/toolkit/content/tests/chrome/window_preferences_commandretarget.xul
+++ b/toolkit/content/tests/chrome/window_preferences_commandretarget.xul
@@ -1,36 +1,36 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <!--
   XUL Widget Test for preferences window. This particular test ensures that
   a checkbox with a command attribute properly updates even though the command
   event gets retargeted.
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            windowtype="test:preferences"
-            buttons="accept,cancel"
-            onload="RunTest(window.arguments)">
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        windowtype="test:preferences"
+        buttons="accept,cancel"
+        onload="RunTest(window.arguments)">
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
   <script type="application/javascript">
   <![CDATA[
     function RunTest(aArgs)
     {
       aArgs[0](this);
       document.documentElement.cancelDialog();
     }
+
+    Preferences.addAll([
+      { id: "tests.static_preference_bool", type: "bool" },
+    ]);
   ]]>
   </script>
 
-  <prefpane id="sample_pane" label="Sample Prefpane">
-    <preferences id="sample_preferences">
-      <preference id="tests.static_preference_bool"
-                  name="tests.static_preference_bool"
-                  type="bool"/>
-    </preferences>
-
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane">
     <commandset>
       <command id="cmd_test" preference="tests.static_preference_bool"/>
     </commandset>
 
     <checkbox id="checkbox" label="Enable Option" preference="tests.static_preference_bool" command="cmd_test"/>
-  </prefpane>
-</prefwindow>
+  </vbox>
+</dialog>
--- a/toolkit/content/tests/chrome/window_preferences_onsyncfrompreference.xul
+++ b/toolkit/content/tests/chrome/window_preferences_onsyncfrompreference.xul
@@ -3,40 +3,40 @@
 <!-- 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/.  -->
 <!--
   XUL Widget Test for preferences window with onsyncfrompreference
   This test ensures that onsyncfrompreference handlers are called after all the
   values of the corresponding preference element have been set correctly
 -->
-<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-            title="preferences window"
-            width="300" height="300"
-            windowtype="test:preferences">
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        class="prefwindow"
+        title="preferences window"
+        width="300" height="300"
+        windowtype="test:preferences">
 
-  <prefpane id="sample_pane" label="Sample Prefpane">
-    <preferences id="sample_preferences">
-      <preference id="tests.onsyncfrompreference.pref1"
-                  name="tests.onsyncfrompreference.pref1"
-                  type="int"/>
-      <preference id="tests.onsyncfrompreference.pref2"
-                  name="tests.onsyncfrompreference.pref2"
-                  type="int"/>
-      <preference id="tests.onsyncfrompreference.pref3"
-                  name="tests.onsyncfrompreference.pref3"
-                  type="int"/>
-    </preferences>
-  </prefpane>
+  <script type="application/javascript" src="chrome://global/content/preferencesBindings.js"/>
+  <script type="application/javascript">
+  <![CDATA[
+    Preferences.addAll([
+      { id: "tests.onsyncfrompreference.pref1", type: "int" },
+      { id: "tests.onsyncfrompreference.pref2", type: "int" },
+      { id: "tests.onsyncfrompreference.pref3", type: "int" },
+    ]);
+  ]]>
+  </script>
+  <vbox id="sample_pane" class="prefpane" label="Sample Prefpane">
+  </vbox>
   <label>Test Prefpane</label>
         <checkbox id="check1" label="Label1"
                 preference="tests.onsyncfrompreference.pref1"
                 onsyncfrompreference="return window.arguments[0]();"
                 onsynctopreference="return 1;"/>
         <checkbox id="check2" label="Label2"
                 preference="tests.onsyncfrompreference.pref2"
                 onsyncfrompreference="return window.arguments[0]();"
                 onsynctopreference="return 1;"/>
         <checkbox id="check3" label="Label3"
                 preference="tests.onsyncfrompreference.pref3"
                 onsyncfrompreference="return window.arguments[0]();"
                 onsynctopreference="return 1;"/>
-</prefwindow>
+</dialog>
--- a/toolkit/content/widgets/dialog.xml
+++ b/toolkit/content/widgets/dialog.xml
@@ -1,13 +1,17 @@
 <?xml version="1.0"?>
 <!-- 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/. -->
 
+<!DOCTYPE bindings [
+  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
+  %globalKeysDTD;
+]>
 
 <bindings id="dialogBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
     <resources>
@@ -35,16 +39,26 @@
         <xul:spacer anonid="spacer" flex="1" hidden="true"/>
         <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
         <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
         <xul:button dlgtype="cancel" class="dialog-button"/>
         <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
         <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
 #endif
       </xul:hbox>
+
+    <xul:keyset>
+      <xul:key phase="capturing" oncommand="document.documentElement.openHelp(event)"
+#ifdef XP_MACOSX
+           key="&openHelpMac.commandkey;" modifiers="accel"/>
+#else
+           keycode="&openHelp.commandkey;"/>
+#endif
+    </xul:keyset>
+
     </content>
 
     <implementation>
       <field name="_mStrBundle">null</field>
       <field name="_closeHandler">(function(event) {
         if (!document.documentElement.cancelDialog())
           event.preventDefault();
       })</field>
@@ -204,16 +218,30 @@
           }
 
           // Give focus after onload completes, see bug 103197.
           setTimeout(focusInit, 0);
         ]]>
         </body>
       </method>
 
+      <method name="openHelp">
+        <parameter name="event"/>
+        <body>
+        <![CDATA[
+          var helpButton = document.documentElement.getButton("help");
+          if (helpButton.disabled || helpButton.hidden)
+            return;
+          this._fireButtonEvent("help");
+          event.stopPropagation();
+          event.preventDefault();
+        ]]>
+        </body>
+      </method>
+
       <property name="mStrBundle">
         <getter>
         <![CDATA[
           if (!this._mStrBundle) {
             // need to create string bundle manually instead of using <xul:stringbundle/>
             // see bug 63370 for details
             this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
                                          .getService(Components.interfaces.nsIStringBundleService)
deleted file mode 100644
--- a/toolkit/content/widgets/preferences.xml
+++ /dev/null
@@ -1,1409 +0,0 @@
-<?xml version="1.0"?>
-
-<!DOCTYPE bindings [
-  <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
-  %preferencesDTD;
-  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
-  %globalKeysDTD;
-]>
-
-<bindings id="preferencesBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xbl="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-#
-# = Preferences Window Framework
-#
-#   The syntax for use looks something like:
-#
-#   <prefwindow>
-#     <prefpane id="prefPaneA">
-#       <preferences>
-#         <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
-#         <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
-#       </preferences>
-#       <checkbox label="Preference" preference="preference1"/>
-#     </prefpane>
-#   </prefwindow>
-#
-
-  <binding id="preferences">
-    <implementation implements="nsIObserver">
-      <method name="_constructAfterChildren">
-      <body>
-      <![CDATA[
-      // This method will be called after the last of the child
-      // <preference> elements is constructed. Its purpose is to propagate
-      // the values to the associated form elements. Sometimes the code for
-      // some <preference> initializers depend on other <preference> elements
-      // being initialized so we wait and call updateElements on all of them
-      // once the last one has been constructed. See bugs 997570 and 992185.
-
-      var elements = this.getElementsByTagName("preference");
-      for (let element of elements) {
-        element.updateElements();
-      }
-
-      this._constructAfterChildrenCalled = true;
-      ]]>
-      </body>
-      </method>
-      <method name="observe">
-        <parameter name="aSubject"/>
-        <parameter name="aTopic"/>
-        <parameter name="aData"/>
-        <body>
-        <![CDATA[
-          for (var i = 0; i < this.childNodes.length; ++i) {
-            var preference = this.childNodes[i];
-            if (preference.name == aData) {
-              preference.value = preference.valueFromPreferences;
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <method name="fireChangedEvent">
-        <parameter name="aPreference"/>
-        <body>
-        <![CDATA[
-          // Value changed, synthesize an event
-          try {
-            var event = document.createEvent("Events");
-            event.initEvent("change", true, true);
-            aPreference.dispatchEvent(event);
-          } catch (e) {
-            Components.utils.reportError(e);
-          }
-        ]]>
-        </body>
-      </method>
-
-      <field name="service">
-        Components.classes["@mozilla.org/preferences-service;1"]
-                  .getService(Components.interfaces.nsIPrefService);
-      </field>
-      <field name="rootBranch">
-        Components.classes["@mozilla.org/preferences-service;1"]
-                  .getService(Components.interfaces.nsIPrefBranch);
-      </field>
-      <field name="defaultBranch">
-        this.service.getDefaultBranch("");
-      </field>
-      <field name="rootBranchInternal">
-        Components.classes["@mozilla.org/preferences-service;1"]
-                  .getService(Components.interfaces.nsIPrefBranch);
-      </field>
-      <property name="type" readonly="true">
-        <getter>
-          <![CDATA[
-            return document.documentElement.type || "";
-          ]]>
-        </getter>
-      </property>
-      <property name="instantApply" readonly="true">
-        <getter>
-          <![CDATA[
-            var doc = document.documentElement;
-            return this.type == "child" ? doc.instantApply
-                                        : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
-          ]]>
-        </getter>
-      </property>
-
-      <!-- We want to call _constructAfterChildren after all child
-           <preference> elements have been constructed. To do this, we get
-           and store the node list of all child <preference> elements in the
-           constructor, and maintain a count which is incremented in the
-           constructor of <preference>. _constructAfterChildren is called
-           when the count matches the length of the list. -->
-      <field name="_constructedChildrenCount">0</field>
-      <field name="_preferenceChildren">null</field>
-      <!-- Some <preference> elements are added dynamically after
-           _constructAfterChildren has already been called - we want to
-           avoid looping over all of them again in this case so we remember
-           if we already called it. -->
-      <field name="_constructAfterChildrenCalled">false</field>
-      <constructor>
-      <![CDATA[
-        this._preferenceChildren = this.getElementsByTagName("preference");
-      ]]>
-      </constructor>
-    </implementation>
-  </binding>
-
-  <binding id="preference">
-    <implementation>
-      <constructor>
-      <![CDATA[
-        // if the element has been inserted without the name attribute set,
-        // we have nothing to do here
-        if (!this.name)
-          return;
-
-        this.preferences.rootBranchInternal
-            .addObserver(this.name, this.preferences);
-        // In non-instant apply mode, we must try and use the last saved state
-        // from any previous opens of a child dialog instead of the value from
-        // preferences, to pick up any edits a user may have made.
-
-        var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-                    .getService(Components.interfaces.nsIScriptSecurityManager);
-        if (this.preferences.type == "child" &&
-            !this.instantApply && window.opener &&
-            secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
-          var pdoc = window.opener.document;
-
-          // Try to find a preference element for the same preference.
-          var preference = null;
-          var parentPreferences = pdoc.getElementsByTagName("preferences");
-          for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
-            var parentPrefs = parentPreferences[k]
-                                    .getElementsByAttribute("name", this.name);
-            for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
-              if (parentPrefs[l].localName == "preference")
-                preference = parentPrefs[l];
-            }
-          }
-
-          // Don't use the value setter here, we don't want updateElements to be prematurely fired.
-          this._value = preference ? preference.value : this.valueFromPreferences;
-        } else {
-          this._value = this.valueFromPreferences;
-        }
-        if (this.preferences._constructAfterChildrenCalled) {
-          // This <preference> was added after _constructAfterChildren() was already called.
-          // We can directly call updateElements().
-          this.updateElements();
-          return;
-        }
-        this.preferences._constructedChildrenCount++;
-        if (this.preferences._constructedChildrenCount ==
-            this.preferences._preferenceChildren.length) {
-          // This is the last <preference>, time to updateElements() on all of them.
-          this.preferences._constructAfterChildren();
-        }
-      ]]>
-      </constructor>
-      <destructor>
-        this.preferences.rootBranchInternal
-            .removeObserver(this.name, this.preferences);
-      </destructor>
-      <field name="_constructed">false</field>
-      <property name="instantApply">
-        <getter>
-          if (this.getAttribute("instantApply") == "false")
-            return false;
-          return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
-        </getter>
-      </property>
-
-      <property name="preferences" onget="return this.parentNode"/>
-      <property name="name" onget="return this.getAttribute('name');">
-        <setter>
-          if (val == this.name)
-            return val;
-
-          this.preferences.rootBranchInternal
-              .removeObserver(this.name, this.preferences);
-          this.setAttribute("name", val);
-          this.preferences.rootBranchInternal
-              .addObserver(val, this.preferences);
-
-          return val;
-        </setter>
-      </property>
-      <property name="type" onget="return this.getAttribute('type');"
-                            onset="this.setAttribute('type', val); return val;"/>
-      <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
-                                onset="this.setAttribute('inverted', val); return val;"/>
-      <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
-                                onset="this.setAttribute('readonly', val); return val;"/>
-
-      <field name="_value">null</field>
-      <method name="_setValue">
-        <parameter name="aValue"/>
-        <body>
-        <![CDATA[
-          if (this.value !== aValue) {
-            this._value = aValue;
-            if (this.instantApply)
-              this.valueFromPreferences = aValue;
-            this.preferences.fireChangedEvent(this);
-          }
-          return aValue;
-        ]]>
-        </body>
-      </method>
-      <property name="value" onget="return this._value" onset="return this._setValue(val);"/>
-
-      <property name="locked">
-        <getter>
-          return this.preferences.rootBranch.prefIsLocked(this.name);
-        </getter>
-      </property>
-
-      <property name="disabled">
-        <getter>
-          return this.getAttribute("disabled") == "true";
-        </getter>
-        <setter>
-        <![CDATA[
-          if (val)
-            this.setAttribute("disabled", "true");
-          else
-            this.removeAttribute("disabled");
-
-          if (!this.id)
-            return val;
-
-          var elements = document.getElementsByAttribute("preference", this.id);
-          for (var i = 0; i < elements.length; ++i) {
-            elements[i].disabled = val;
-
-            var labels = document.getElementsByAttribute("control", elements[i].id);
-            for (var j = 0; j < labels.length; ++j)
-              labels[j].disabled = val;
-          }
-
-          return val;
-        ]]>
-        </setter>
-      </property>
-
-      <property name="tabIndex">
-        <getter>
-          return parseInt(this.getAttribute("tabindex"));
-        </getter>
-        <setter>
-        <![CDATA[
-          if (val)
-            this.setAttribute("tabindex", val);
-          else
-            this.removeAttribute("tabindex");
-
-          if (!this.id)
-            return val;
-
-          var elements = document.getElementsByAttribute("preference", this.id);
-          for (var i = 0; i < elements.length; ++i) {
-            elements[i].tabIndex = val;
-
-            var labels = document.getElementsByAttribute("control", elements[i].id);
-            for (var j = 0; j < labels.length; ++j)
-              labels[j].tabIndex = val;
-          }
-
-          return val;
-        ]]>
-        </setter>
-      </property>
-
-      <property name="hasUserValue">
-        <getter>
-        <![CDATA[
-          return this.preferences.rootBranch.prefHasUserValue(this.name) &&
-                 this.value !== undefined;
-        ]]>
-        </getter>
-      </property>
-
-      <method name="reset">
-        <body>
-          // defer reset until preference update
-          this.value = undefined;
-        </body>
-      </method>
-
-      <field name="_useDefault">false</field>
-      <property name="defaultValue">
-        <getter>
-        <![CDATA[
-          this._useDefault = true;
-          var val = this.valueFromPreferences;
-          this._useDefault = false;
-          return val;
-        ]]>
-        </getter>
-      </property>
-
-      <property name="_branch">
-        <getter>
-          return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
-        </getter>
-      </property>
-
-      <field name="batching">false</field>
-
-      <method name="_reportUnknownType">
-        <body>
-        <![CDATA[
-          var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
-                                         .getService(Components.interfaces.nsIConsoleService);
-          var msg = "<preference> with id='" + this.id + "' and name='" +
-                    this.name + "' has unknown type '" + this.type + "'.";
-          consoleService.logStringMessage(msg);
-        ]]>
-        </body>
-      </method>
-
-      <property name="valueFromPreferences">
-        <getter>
-        <![CDATA[
-          try {
-            // Force a resync of value with preferences.
-            switch (this.type) {
-            case "int":
-              return this._branch.getIntPref(this.name);
-            case "bool":
-              var val = this._branch.getBoolPref(this.name);
-              return this.inverted ? !val : val;
-            case "wstring":
-              return this._branch
-                         .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
-                         .data;
-            case "string":
-            case "unichar":
-              return this._branch.getStringPref(this.name);
-            case "fontname":
-              var family = this._branch.getStringPref(this.name);
-              var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
-                                             .createInstance(Components.interfaces.nsIFontEnumerator);
-              return fontEnumerator.getStandardFamilyName(family);
-            case "file":
-              var f = this._branch
-                          .getComplexValue(this.name, Components.interfaces.nsIFile);
-              return f;
-            default:
-              this._reportUnknownType();
-            }
-          } catch (e) { }
-          return null;
-        ]]>
-        </getter>
-        <setter>
-        <![CDATA[
-          // Exit early if nothing to do.
-          if (this.readonly || this.valueFromPreferences == val)
-            return val;
-
-          // The special value undefined means 'reset preference to default'.
-          if (val === undefined) {
-            this.preferences.rootBranch.clearUserPref(this.name);
-            return val;
-          }
-
-          // Force a resync of preferences with value.
-          switch (this.type) {
-          case "int":
-            this.preferences.rootBranch.setIntPref(this.name, val);
-            break;
-          case "bool":
-            this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
-            break;
-          case "wstring":
-            var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
-                                .createInstance(Components.interfaces.nsIPrefLocalizedString);
-            pls.data = val;
-            this.preferences.rootBranch
-                .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
-            break;
-          case "string":
-          case "unichar":
-          case "fontname":
-            this.preferences.rootBranch.setStringPref(this.name, val);
-            break;
-          case "file":
-            var lf;
-            if (typeof(val) == "string") {
-              lf = Components.classes["@mozilla.org/file/local;1"]
-                             .createInstance(Components.interfaces.nsIFile);
-              lf.persistentDescriptor = val;
-              if (!lf.exists())
-                lf.initWithPath(val);
-            } else
-              lf = val.QueryInterface(Components.interfaces.nsIFile);
-            this.preferences.rootBranch
-                .setComplexValue(this.name, Components.interfaces.nsIFile, lf);
-            break;
-          default:
-            this._reportUnknownType();
-          }
-          if (!this.batching)
-            this.preferences.service.savePrefFile(null);
-          return val;
-        ]]>
-        </setter>
-      </property>
-
-      <method name="setElementValue">
-        <parameter name="aElement"/>
-        <body>
-        <![CDATA[
-          if (this.locked)
-            aElement.disabled = true;
-
-          if (!this.isElementEditable(aElement))
-            return;
-
-          var rv = undefined;
-          if (aElement.hasAttribute("onsyncfrompreference")) {
-            // Value changed, synthesize an event
-            try {
-              var event = document.createEvent("Events");
-              event.initEvent("syncfrompreference", true, true);
-              var f = new Function("event",
-                                   aElement.getAttribute("onsyncfrompreference"));
-              rv = f.call(aElement, event);
-            } catch (e) {
-              Components.utils.reportError(e);
-            }
-          }
-          var val = rv;
-          if (val === undefined)
-            val = this.instantApply ? this.valueFromPreferences : this.value;
-          // if the preference is marked for reset, show default value in UI
-          if (val === undefined)
-            val = this.defaultValue;
-
-          /**
-           * Initialize a UI element property with a value. Handles the case
-           * where an element has not yet had a XBL binding attached for it and
-           * the property setter does not yet exist by setting the same attribute
-           * on the XUL element using DOM apis and assuming the element's
-           * constructor or property getters appropriately handle this state.
-           */
-          function setValue(element, attribute, value) {
-            if (attribute in element)
-              element[attribute] = value;
-            else
-              element.setAttribute(attribute, value);
-          }
-          if (aElement.localName == "checkbox" ||
-              aElement.localName == "listitem")
-            setValue(aElement, "checked", val);
-          else if (aElement.localName == "colorpicker")
-            setValue(aElement, "color", val);
-          else if (aElement.localName == "textbox") {
-            // XXXmano Bug 303998: Avoid a caret placement issue if either the
-            // preference observer or its setter calls updateElements as a result
-            // of the input event handler.
-            if (aElement.value !== val)
-              setValue(aElement, "value", val);
-          } else
-            setValue(aElement, "value", val);
-        ]]>
-        </body>
-      </method>
-
-      <method name="getElementValue">
-        <parameter name="aElement"/>
-        <body>
-        <![CDATA[
-          if (aElement.hasAttribute("onsynctopreference")) {
-            // Value changed, synthesize an event
-            try {
-              var event = document.createEvent("Events");
-              event.initEvent("synctopreference", true, true);
-              var f = new Function("event",
-                                   aElement.getAttribute("onsynctopreference"));
-              var rv = f.call(aElement, event);
-              if (rv !== undefined)
-                return rv;
-            } catch (e) {
-              Components.utils.reportError(e);
-            }
-          }
-
-          /**
-           * Read the value of an attribute from an element, assuming the
-           * attribute is a property on the element's node API. If the property
-           * is not present in the API, then assume its value is contained in
-           * an attribute, as is the case before a binding has been attached.
-           */
-          function getValue(element, attribute) {
-            if (attribute in element)
-              return element[attribute];
-            return element.getAttribute(attribute);
-          }
-          if (aElement.localName == "checkbox" ||
-              aElement.localName == "listitem")
-            var value = getValue(aElement, "checked");
-          else if (aElement.localName == "colorpicker")
-            value = getValue(aElement, "color");
-          else
-            value = getValue(aElement, "value");
-
-          switch (this.type) {
-          case "int":
-            return parseInt(value, 10) || 0;
-          case "bool":
-            return typeof(value) == "boolean" ? value : value == "true";
-          }
-          return value;
-        ]]>
-        </body>
-      </method>
-
-      <method name="isElementEditable">
-        <parameter name="aElement"/>
-        <body>
-        <![CDATA[
-          switch (aElement.localName) {
-          case "checkbox":
-          case "colorpicker":
-          case "radiogroup":
-          case "textbox":
-          case "listitem":
-          case "listbox":
-          case "menulist":
-            return true;
-          }
-          return aElement.getAttribute("preference-editable") == "true";
-        ]]>
-        </body>
-      </method>
-
-      <method name="updateElements">
-        <body>
-        <![CDATA[
-          if (!this.id)
-            return;
-
-          // This "change" event handler tracks changes made to preferences by
-          // sources other than the user in this window.
-          var elements = document.getElementsByAttribute("preference", this.id);
-          for (var i = 0; i < elements.length; ++i)
-            this.setElementValue(elements[i]);
-        ]]>
-        </body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="change">
-        this.updateElements();
-      </handler>
-    </handlers>
-  </binding>
-
-  <binding id="prefwindow"
-           extends="chrome://global/content/bindings/dialog.xml#dialog">
-    <resources>
-      <stylesheet src="chrome://global/skin/preferences.css"/>
-    </resources>
-    <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
-             closebuttonlabel="&preferencesCloseButton.label;"
-             closebuttonaccesskey="&preferencesCloseButton.accesskey;"
-             role="dialog"
-#ifdef XP_WIN
-             title="&preferencesDefaultTitleWin.title;">
-#else
-             title="&preferencesDefaultTitleMac.title;">
-#endif
-      <xul:windowdragbox orient="vertical">
-        <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
-                        role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
-      </xul:windowdragbox>
-      <xul:hbox flex="1" class="paneDeckContainer">
-        <xul:deck anonid="paneDeck" flex="1">
-          <children includes="prefpane"/>
-        </xul:deck>
-      </xul:hbox>
-      <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
-#ifdef XP_UNIX
-        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-        <xul:spacer anonid="spacer" flex="1"/>
-        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-#else
-        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-        <xul:spacer anonid="spacer" flex="1"/>
-        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-#endif
-      </xul:hbox>
-      <xul:hbox>
-        <children/>
-      </xul:hbox>
-    </content>
-    <implementation implements="nsITimerCallback">
-      <constructor>
-      <![CDATA[
-        if (this.type != "child") {
-          if (!this._instantApplyInitialized) {
-            let psvc = Components.classes["@mozilla.org/preferences-service;1"]
-                                 .getService(Components.interfaces.nsIPrefBranch);
-            this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
-          }
-          if (this.instantApply) {
-            var docElt = document.documentElement;
-            var acceptButton = docElt.getButton("accept");
-            acceptButton.hidden = true;
-            var cancelButton  = docElt.getButton("cancel");
-            if (/Mac/.test(navigator.platform)) {
-              // no buttons on Mac except Help
-              cancelButton.hidden = true;
-              // Move Help button to the end
-              document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;
-              // Also, don't fire onDialogAccept on enter
-              acceptButton.disabled = true;
-            } else {
-              // morph the Cancel button into the Close button
-              cancelButton.setAttribute("icon", "close");
-              cancelButton.label = docElt.getAttribute("closebuttonlabel");
-              cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
-            }
-          }
-        }
-        this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
-        var panes = this.preferencePanes;
-
-        var lastPane = null;
-        if (this.lastSelected) {
-          lastPane = document.getElementById(this.lastSelected);
-          if (!lastPane) {
-            this.lastSelected = "";
-          }
-        }
-
-        var paneToLoad;
-        if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
-          paneToLoad = document.getElementById(window.arguments[0]);
-          this.lastSelected = paneToLoad.id;
-        } else if (lastPane)
-          paneToLoad = lastPane;
-        else
-          paneToLoad = panes[0];
-
-        for (var i = 0; i < panes.length; ++i) {
-          this._makePaneButton(panes[i]);
-          if (panes[i].loaded) {
-            // Inline pane content, fire load event to force initialization.
-            this._fireEvent("paneload", panes[i]);
-          }
-        }
-        this.showPane(paneToLoad);
-
-        if (panes.length == 1)
-          this._selector.setAttribute("collapsed", "true");
-      ]]>
-      </constructor>
-
-      <destructor>
-      <![CDATA[
-        // Release timers to avoid reference cycles.
-        if (this._animateTimer) {
-          this._animateTimer.cancel();
-          this._animateTimer = null;
-        }
-        if (this._fadeTimer) {
-          this._fadeTimer.cancel();
-          this._fadeTimer = null;
-        }
-      ]]>
-      </destructor>
-
-      <!-- Derived bindings can set this to true to cause us to skip
-           reading the browser.preferences.instantApply pref in the constructor.
-           Then they can set instantApply to their wished value. -->
-      <field name="_instantApplyInitialized">false</field>
-      <!-- Controls whether changed pref values take effect immediately. -->
-      <field name="instantApply">false</field>
-
-      <property name="preferencePanes"
-                onget="return this.getElementsByTagName('prefpane');"/>
-
-      <property name="type" onget="return this.getAttribute('type');"/>
-      <property name="_paneDeck"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
-      <property name="_paneDeckContainer"
-                onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
-      <property name="_selector"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
-      <property name="lastSelected"
-                onget="return this.getAttribute('lastSelected');">
-        <setter>
-          this.setAttribute("lastSelected", val);
-          document.persist(this.id, "lastSelected");
-          return val;
-        </setter>
-      </property>
-      <property name="currentPane"
-                onset="return this._currentPane = val;">
-        <getter>
-          if (!this._currentPane)
-            this._currentPane = this.preferencePanes[0];
-
-          return this._currentPane;
-        </getter>
-      </property>
-      <field name="_currentPane">null</field>
-
-
-      <method name="_makePaneButton">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          var radio = document.createElement("radio");
-          radio.setAttribute("pane", aPaneElement.id);
-          radio.setAttribute("label", aPaneElement.label);
-          // Expose preference group choice to accessibility APIs as an unchecked list item
-          // The parent group is exposed to accessibility APIs as a list
-          if (aPaneElement.image)
-            radio.setAttribute("src", aPaneElement.image);
-          radio.style.listStyleImage = aPaneElement.style.listStyleImage;
-          this._selector.appendChild(radio);
-          return radio;
-        ]]>
-        </body>
-      </method>
-
-      <method name="showPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          if (!aPaneElement)
-            return;
-
-          this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
-          if (!aPaneElement.loaded) {
-            let OverlayLoadObserver = function(aPane) {
-              this._pane = aPane;
-            };
-            OverlayLoadObserver.prototype = {
-              _outer: this,
-              observe(aSubject, aTopic, aData) {
-                this._pane.loaded = true;
-                this._outer._fireEvent("paneload", this._pane);
-                this._outer._selectPane(this._pane);
-              }
-            };
-
-            var obs = new OverlayLoadObserver(aPaneElement);
-            document.loadOverlay(aPaneElement.src, obs);
-          } else
-            this._selectPane(aPaneElement);
-        ]]>
-        </body>
-      </method>
-
-      <method name="_fireEvent">
-        <parameter name="aEventName"/>
-        <parameter name="aTarget"/>
-        <body>
-        <![CDATA[
-          // Panel loaded, synthesize a load event.
-          try {
-            var event = document.createEvent("Events");
-            event.initEvent(aEventName, true, true);
-            var cancel = !aTarget.dispatchEvent(event);
-            if (aTarget.hasAttribute("on" + aEventName)) {
-              var fn = new Function("event", aTarget.getAttribute("on" + aEventName));
-              var rv = fn.call(aTarget, event);
-              if (rv == false)
-                cancel = true;
-            }
-            return !cancel;
-          } catch (e) {
-            Components.utils.reportError(e);
-          }
-          return false;
-        ]]>
-        </body>
-      </method>
-
-      <field name="_initialized">false</field>
-      <method name="_selectPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          if (/Mac/.test(navigator.platform)) {
-            var paneTitle = aPaneElement.label;
-            if (paneTitle != "")
-              document.title = paneTitle;
-          }
-          var helpButton = document.documentElement.getButton("help");
-          if (aPaneElement.helpTopic)
-            helpButton.hidden = false;
-          else
-            helpButton.hidden = true;
-
-          // Find this pane's index in the deck and set the deck's
-          // selectedIndex to that value to switch to it.
-          var prefpanes = this.preferencePanes;
-          for (var i = 0; i < prefpanes.length; ++i) {
-            if (prefpanes[i] == aPaneElement) {
-              this._paneDeck.selectedIndex = i;
-
-              if (this.type != "child") {
-                if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
-                    prefpanes.length > 1)
-                  aPaneElement.removeAttribute("flex");
-                // Calling sizeToContent after the first prefpane is loaded
-                // will size the windows contents so style information is
-                // available to calculate correct sizing.
-                if (!this._initialized && prefpanes.length > 1) {
-                  if (this._shouldAnimate)
-                    this.style.minHeight = 0;
-                  window.sizeToContent();
-                }
-
-                var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
-                oldPane.selected = !(aPaneElement.selected = true);
-                this.lastSelected = aPaneElement.id;
-                this.currentPane = aPaneElement;
-                this._initialized = true;
-
-                // Only animate if we've switched between prefpanes
-                if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
-                  aPaneElement.style.opacity = 0.0;
-                  this.animate(oldPane, aPaneElement);
-                } else if (!this._shouldAnimate && prefpanes.length > 1) {
-                  var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height);
-                  var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop);
-                  verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom);
-                  if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
-                    // To workaround the bottom border of a groupbox from being
-                    // cutoff an hbox with a class of bottomBox may enclose it.
-                    // This needs to include its padding to resize properly.
-                    // See bug 394433
-                    var bottomPadding = 0;
-                    var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
-                    if (bottomBox)
-                      bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom);
-                    window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
-                  }
-
-                  // XXX rstrong - extend the contents of the prefpane to
-                  // prevent elements from being cutoff (see bug 349098).
-                  if (aPaneElement.contentHeight + verticalPadding < targetHeight)
-                    aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
-                }
-              }
-              break;
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <property name="_shouldAnimate">
-        <getter>
-        <![CDATA[
-          var psvc = Components.classes["@mozilla.org/preferences-service;1"]
-                               .getService(Components.interfaces.nsIPrefBranch);
-          return psvc.getBoolPref("browser.preferences.animateFadeIn",
-                                  /Mac/.test(navigator.platform));
-        ]]>
-        </getter>
-      </property>
-
-      <method name="animate">
-        <parameter name="aOldPane"/>
-        <parameter name="aNewPane"/>
-        <body>
-        <![CDATA[
-          // if we are already resizing, use currentHeight
-          var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
-
-          this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
-          var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
-          this._animateRemainder = sizeDelta % this._animateIncrement;
-
-          this._setUpAnimationTimer(oldHeight);
-        ]]>
-        </body>
-      </method>
-
-      <property name="_sizeIncrement">
-        <getter>
-        <![CDATA[
-          var lastSelectedPane = document.getElementById(this.lastSelected);
-          var increment = this._animateIncrement * this._multiplier;
-          var newHeight = this._currentHeight + increment;
-          if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
-              (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
-            return 0;
-
-          if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
-              (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
-            increment = this._animateRemainder * this._multiplier;
-          return increment;
-        ]]>
-        </getter>
-      </property>
-
-      <method name="notify">
-        <parameter name="aTimer"/>
-        <body>
-        <![CDATA[
-          if (!document)
-            aTimer.cancel();
-
-          if (aTimer == this._animateTimer) {
-            var increment = this._sizeIncrement;
-            if (increment != 0) {
-              window.innerHeight += increment;
-              this._currentHeight += increment;
-            } else {
-              aTimer.cancel();
-              this._setUpFadeTimer();
-            }
-          } else if (aTimer == this._fadeTimer) {
-            var elt = document.getElementById(this.lastSelected);
-            var newOpacity = parseFloat(window.getComputedStyle(elt).opacity) + this._fadeIncrement;
-            if (newOpacity < 1.0)
-              elt.style.opacity = newOpacity;
-            else {
-              aTimer.cancel();
-              elt.style.opacity = 1.0;
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <method name="_setUpAnimationTimer">
-        <parameter name="aStartHeight"/>
-        <body>
-        <![CDATA[
-          if (!this._animateTimer)
-            this._animateTimer = Components.classes["@mozilla.org/timer;1"]
-                                           .createInstance(Components.interfaces.nsITimer);
-          else
-            this._animateTimer.cancel();
-          this._currentHeight = aStartHeight;
-
-          this._animateTimer.initWithCallback(this, this._animateDelay,
-                                              Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
-        ]]>
-        </body>
-      </method>
-
-      <method name="_setUpFadeTimer">
-        <body>
-        <![CDATA[
-          if (!this._fadeTimer)
-            this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
-                                        .createInstance(Components.interfaces.nsITimer);
-          else
-            this._fadeTimer.cancel();
-
-          this._fadeTimer.initWithCallback(this, this._fadeDelay,
-                                           Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
-        ]]>
-        </body>
-      </method>
-
-      <field name="_animateTimer">null</field>
-      <field name="_fadeTimer">null</field>
-      <field name="_animateDelay">15</field>
-      <field name="_animateIncrement">40</field>
-      <field name="_fadeDelay">5</field>
-      <field name="_fadeIncrement">0.40</field>
-      <field name="_animateRemainder">0</field>
-      <field name="_currentHeight">0</field>
-      <field name="_multiplier">0</field>
-
-      <method name="addPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          this.appendChild(aPaneElement);
-
-          // Set up pane button
-          this._makePaneButton(aPaneElement);
-        ]]>
-        </body>
-      </method>
-
-      <method name="openSubDialog">
-        <parameter name="aURL"/>
-        <parameter name="aFeatures"/>
-        <parameter name="aParams"/>
-        <body>
-          return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
-        </body>
-      </method>
-
-      <method name="openWindow">
-        <parameter name="aWindowType"/>
-        <parameter name="aURL"/>
-        <parameter name="aFeatures"/>
-        <parameter name="aParams"/>
-        <body>
-        <![CDATA[
-          var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-                             .getService(Components.interfaces.nsIWindowMediator);
-          var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
-          if (win) {
-            if ("initWithParams" in win)
-              win.initWithParams(aParams);
-            win.focus();
-          } else {
-            var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
-            var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
-            win = parentWindow.openDialog(aURL, "_blank", features, aParams);
-          }
-          return win;
-        ]]>
-        </body>
-      </method>
-    </implementation>
-    <handlers>
-      <handler event="dialogaccept">
-      <![CDATA[
-        if (!this._fireEvent("beforeaccept", this)) {
-          return false;
-        }
-
-        var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-                    .getService(Components.interfaces.nsIScriptSecurityManager);
-        if (this.type == "child" && window.opener &&
-            secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
-          var pdocEl = window.opener.document.documentElement;
-          if (pdocEl.instantApply) {
-            let panes = this.preferencePanes;
-            for (let i = 0; i < panes.length; ++i)
-              panes[i].writePreferences(true);
-          } else {
-            // Clone all the preferences elements from the child document and
-            // insert them into the pane collection of the parent.
-            var pdoc = window.opener.document;
-            if (pdoc.documentElement.localName == "prefwindow") {
-              var currentPane = pdoc.documentElement.currentPane;
-              var id = window.location.href + "#childprefs";
-              var childPrefs = pdoc.getElementById(id);
-              if (!childPrefs) {
-                childPrefs = pdoc.createElement("preferences");
-                currentPane.appendChild(childPrefs);
-                childPrefs.id = id;
-              }
-              let panes = this.preferencePanes;
-              for (let i = 0; i < panes.length; ++i) {
-                var preferences = panes[i].preferences;
-                for (var j = 0; j < preferences.length; ++j) {
-                  // Try to find a preference element for the same preference.
-                  var preference = null;
-                  var parentPreferences = pdoc.getElementsByTagName("preferences");
-                  for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
-                    var parentPrefs = parentPreferences[k]
-                                         .getElementsByAttribute("name", preferences[j].name);
-                    for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
-                      if (parentPrefs[l].localName == "preference")
-                        preference = parentPrefs[l];
-                    }
-                  }
-                  if (!preference) {
-                    // No matching preference in the parent window.
-                    preference = pdoc.createElement("preference");
-                    childPrefs.appendChild(preference);
-                    preference.name     = preferences[j].name;
-                    preference.type     = preferences[j].type;
-                    preference.inverted = preferences[j].inverted;
-                    preference.readonly = preferences[j].readonly;
-                    preference.disabled = preferences[j].disabled;
-                  }
-                  preference.value = preferences[j].value;
-                }
-              }
-            }
-          }
-        } else {
-          let panes = this.preferencePanes;
-          for (var i = 0; i < panes.length; ++i)
-            panes[i].writePreferences(false);
-
-          let psvc = Components.classes["@mozilla.org/preferences-service;1"]
-                               .getService(Components.interfaces.nsIPrefService);
-          psvc.savePrefFile(null);
-        }
-
-        return true;
-      ]]>
-      </handler>
-      <handler event="command">
-        if (event.originalTarget.hasAttribute("pane")) {
-          var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
-          this.showPane(pane);
-        }
-      </handler>
-
-      <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
-      <![CDATA[
-        if (this.instantApply)
-          window.close();
-        event.stopPropagation();
-        event.preventDefault();
-      ]]>
-      </handler>
-
-      <handler event="keypress"
-#ifdef XP_MACOSX
-               key="&openHelpMac.commandkey;" modifiers="accel"
-#else
-               keycode="&openHelp.commandkey;"
-#endif
-               phase="capturing">
-      <![CDATA[
-        var helpButton = this.getButton("help");
-        if (helpButton.disabled || helpButton.hidden)
-          return;
-        this._fireEvent("dialoghelp", this);
-        event.stopPropagation();
-        event.preventDefault();
-      ]]>
-      </handler>
-    </handlers>
-  </binding>
-
-  <binding id="prefpane">
-    <resources>
-      <stylesheet src="chrome://global/skin/preferences.css"/>
-    </resources>
-    <content>
-      <xul:vbox class="content-box" xbl:inherits="flex">
-        <children/>
-      </xul:vbox>
-    </content>
-    <implementation>
-      <method name="writePreferences">
-        <parameter name="aFlushToDisk"/>
-        <body>
-        <![CDATA[
-          // Write all values to preferences.
-          if (this._deferredValueUpdateElements.size) {
-            this._finalizeDeferredElements();
-          }
-
-          var preferences = this.preferences;
-          for (var i = 0; i < preferences.length; ++i) {
-            var preference = preferences[i];
-            preference.batching = true;
-            preference.valueFromPreferences = preference.value;
-            preference.batching = false;
-          }
-          if (aFlushToDisk) {
-            var psvc = Components.classes["@mozilla.org/preferences-service;1"]
-                                 .getService(Components.interfaces.nsIPrefService);
-            psvc.savePrefFile(null);
-          }
-        ]]>
-        </body>
-      </method>
-
-      <property name="src"
-                onget="return this.getAttribute('src');"
-                onset="this.setAttribute('src', val); return val;"/>
-      <property name="selected"
-                onget="return this.getAttribute('selected') == 'true';"
-                onset="this.setAttribute('selected', val); return val;"/>
-      <property name="image"
-                onget="return this.getAttribute('image');"
-                onset="this.setAttribute('image', val); return val;"/>
-      <property name="label"
-                onget="return this.getAttribute('label');"
-                onset="this.setAttribute('label', val); return val;"/>
-
-      <property name="preferenceElements"
-                onget="return this.getElementsByAttribute('preference', '*');"/>
-      <property name="preferences"
-                onget="return this.getElementsByTagName('preference');"/>
-
-      <property name="helpTopic">
-        <getter>
-        <![CDATA[
-          // if there are tabs, and the selected tab provides a helpTopic, return that
-          var box = this.getElementsByTagName("tabbox");
-          if (box[0]) {
-            var tab = box[0].selectedTab;
-            if (tab && tab.hasAttribute("helpTopic"))
-              return tab.getAttribute("helpTopic");
-          }
-
-          // otherwise, return the helpTopic of the current panel
-          return this.getAttribute("helpTopic");
-        ]]>
-        </getter>
-      </property>
-
-      <field name="_loaded">false</field>
-      <property name="loaded"
-                onget="return !this.src ? true : this._loaded;"
-                onset="this._loaded = val; return val;"/>
-
-      <method name="preferenceForElement">
-        <parameter name="aElement"/>
-        <body>
-          return document.getElementById(aElement.getAttribute("preference"));
-        </body>
-      </method>
-
-      <method name="getPreferenceElement">
-        <parameter name="aStartElement"/>
-        <body>
-        <![CDATA[
-          var temp = aStartElement;
-          while (temp && temp.nodeType == Node.ELEMENT_NODE &&
-                 !temp.hasAttribute("preference"))
-            temp = temp.parentNode;
-          return temp && temp.nodeType == Node.ELEMENT_NODE ?
-                 temp : aStartElement;
-        ]]>
-        </body>
-      </method>
-
-      <property name="DeferredTask" readonly="true">
-        <getter><![CDATA[
-          let module = {};
-          Components.utils.import("resource://gre/modules/DeferredTask.jsm", module);
-          Object.defineProperty(this, "DeferredTask", {
-            configurable: true,
-            enumerable: true,
-            writable: true,
-            value: module.DeferredTask
-          });
-          return module.DeferredTask;
-        ]]></getter>
-      </property>
-      <method name="_deferredValueUpdate">
-        <parameter name="aElement"/>
-        <body>
-        <![CDATA[
-          delete aElement._deferredValueUpdateTask;
-          let preference = document.getElementById(aElement.getAttribute("preference"));
-          let prefVal = preference.getElementValue(aElement);
-          preference.value = prefVal;
-          this._deferredValueUpdateElements.delete(aElement);
-        ]]>
-        </body>
-      </method>
-      <field name="_deferredValueUpdateElements">
-        new Set();
-      </field>
-      <method name="_finalizeDeferredElements">
-        <body>
-        <![CDATA[
-          for (let el of this._deferredValueUpdateElements) {
-            if (el._deferredValueUpdateTask) {
-              el._deferredValueUpdateTask.finalize();
-            }
-          }
-        ]]>
-        </body>
-      </method>
-      <method name="userChangedValue">
-        <parameter name="aElement"/>
-        <body>
-        <![CDATA[
-          let element = this.getPreferenceElement(aElement);
-          if (element.hasAttribute("preference")) {
-            if (element.getAttribute("delayprefsave") != "true") {
-              var preference = document.getElementById(element.getAttribute("preference"));
-              var prefVal = preference.getElementValue(element);
-              preference.value = prefVal;
-            } else {
-              if (!element._deferredValueUpdateTask) {
-                element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000);
-                this._deferredValueUpdateElements.add(element);
-              } else {
-                // Each time the preference is changed, restart the delay.
-                element._deferredValueUpdateTask.disarm();
-              }
-              element._deferredValueUpdateTask.arm();
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <property name="contentHeight">
-        <getter>
-          var targetHeight = parseInt(window.getComputedStyle(this._content).height);
-          targetHeight += parseInt(window.getComputedStyle(this._content).marginTop);
-          targetHeight += parseInt(window.getComputedStyle(this._content).marginBottom);
-          return targetHeight;
-        </getter>
-      </property>
-      <field name="_content">
-        document.getAnonymousElementByAttribute(this, "class", "content-box");
-      </field>
-    </implementation>
-    <handlers>
-      <handler event="command">
-        // This "command" event handler tracks changes made to preferences by
-        // the user in this window.
-        if (event.sourceEvent)
-          event = event.sourceEvent;
-        this.userChangedValue(event.target);
-      </handler>
-      <handler event="select">
-        // This "select" event handler tracks changes made to colorpicker
-        // preferences by the user in this window.
-        if (event.target.localName == "colorpicker")
-          this.userChangedValue(event.target);
-      </handler>
-      <handler event="change">
-        // This "change" event handler tracks changes made to preferences by
-        // the user in this window.
-        this.userChangedValue(event.target);
-      </handler>
-      <handler event="input">
-        // This "input" event handler tracks changes made to preferences by
-        // the user in this window.
-        this.userChangedValue(event.target);
-      </handler>
-      <handler event="paneload">
-      <![CDATA[
-        // Initialize all values from preferences.
-        var elements = this.preferenceElements;
-        for (var i = 0; i < elements.length; ++i) {
-          try {
-            var preference = this.preferenceForElement(elements[i]);
-            preference.setElementValue(elements[i]);
-          } catch (e) {
-            dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
-          }
-        }
-      ]]>
-      </handler>
-    </handlers>
-  </binding>
-
-  <binding id="panebutton" role="xul:listitem"
-           extends="chrome://global/content/bindings/radio.xml#radio">
-    <resources>
-      <stylesheet src="chrome://global/skin/preferences.css"/>
-    </resources>
-    <content>
-      <xul:image class="paneButtonIcon" xbl:inherits="src"/>
-      <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
-    </content>
-  </binding>
-
-</bindings>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# 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/.
-
-#
-# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
-#
-#    Historical References:
-#    PrefWindow V   (February 1, 2003)
-#    PrefWindow IV  (April 24, 2000)
-#    PrefWindow III (January 6, 2000)
-#    PrefWindow II  (???)
-#    PrefWindow I   (June 4, 1999)
-#
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -1010,66 +1010,16 @@ wizardpage {
 .wizard-header {
   -moz-binding: url("chrome://global/content/bindings/wizard.xml#wizard-header");
 }
 
 .wizard-buttons {
   -moz-binding: url("chrome://global/content/bindings/wizard.xml#wizard-buttons");
 }
 
-/********** preferences ********/
-
-prefwindow,
-prefwindow:root /* override :root from above */ {
-  -moz-binding: url("chrome://global/content/bindings/preferences.xml#prefwindow");
-  -moz-box-orient: vertical;
-}
-
-prefpane {
-  -moz-binding: url("chrome://global/content/bindings/preferences.xml#prefpane");
-  -moz-box-orient: vertical;
-}
-
-prefwindow > .paneDeckContainer {
-  overflow: hidden;
-}
-
-prefpane > .content-box {
-  overflow: hidden;
-}
-
-prefwindow[type="child"] > .paneDeckContainer {
-  overflow: -moz-hidden-unscrollable;
-}
-
-prefwindow[type="child"] > prefpane > .content-box {
-  -moz-box-flex: 1;
-  overflow: -moz-hidden-unscrollable;
-}
-
-preferences {
-  -moz-binding: url("chrome://global/content/bindings/preferences.xml#preferences");
-  visibility: collapse;
-}
-
-preference {
-  -moz-binding: url("chrome://global/content/bindings/preferences.xml#preference");
-  visibility: collapse;
-}
-
-radio[pane] {
-  -moz-binding: url("chrome://global/content/bindings/preferences.xml#panebutton") !important;
-  -moz-box-orient: vertical;
-  -moz-box-align: center;
-}
-
-prefwindow[chromehidden~="toolbar"] .chromeclass-toolbar {
-  display: none;
-}
-
 /********** expander ********/
 
 expander {
   -moz-binding: url("chrome://global/content/bindings/expander.xml#expander");
   -moz-box-orient: vertical;
 }
 
 
--- a/toolkit/mozapps/preferences/fontbuilder.js
+++ b/toolkit/mozapps/preferences/fontbuilder.js
@@ -1,14 +1,16 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 
 /* 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/. */
 
+/* import-globals-from ../../content/preferencesBindings.js */
+
 var FontBuilder = {
   _enumerator: null,
   get enumerator() {
     if (!this._enumerator) {
       this._enumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
                                    .createInstance(Components.interfaces.nsIFontEnumerator);
     }
     return this._enumerator;
@@ -86,17 +88,17 @@ var FontBuilder = {
     aMenuList.appendChild(popup);
   },
 
   readFontSelection(aElement) {
     // Determine the appropriate value to select, for the following cases:
     // - there is no setting
     // - the font selected by the user is no longer present (e.g. deleted from
     //   fonts folder)
-    const preference = document.getElementById(aElement.getAttribute("preference"));
+    const preference = Preferences.get(aElement.getAttribute("preference"));
     if (preference.value) {
       const fontItems = aElement.getElementsByAttribute("value", preference.value);
 
       // There is a setting that actually is in the list. Respect it.
       if (fontItems.length)
         return undefined;
     }
 
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -36,18 +36,17 @@ progressmeter[mode="undetermined"] {
   --arrowpanel-border-color: ThreeDShadow;
 }
 
 /* ::::: root elements ::::: */
 
 window,
 page,
 dialog,
-wizard,
-prefwindow {
+wizard {
   -moz-appearance: window;
   background-color: -moz-Dialog;
   color: -moz-DialogText;
   font: message-box;
 }
 
 /* deprecated */
 window.dialog {
--- a/toolkit/themes/linux/global/jar.mn
+++ b/toolkit/themes/linux/global/jar.mn
@@ -18,17 +18,16 @@ toolkit.jar:
    skin/classic/global/groupbox.css
    skin/classic/global/listbox.css
    skin/classic/global/menu.css
    skin/classic/global/menulist.css
    skin/classic/global/netError.css
 *  skin/classic/global/notification.css
    skin/classic/global/numberbox.css
    skin/classic/global/popup.css
-   skin/classic/global/preferences.css
    skin/classic/global/printPreview.css
    skin/classic/global/radio.css
    skin/classic/global/scrollbox.css
    skin/classic/global/splitter.css
    skin/classic/global/tabbox.css
    skin/classic/global/textbox.css
    skin/classic/global/toolbar.css
    skin/classic/global/toolbarbutton.css
deleted file mode 100644
--- a/toolkit/themes/linux/global/preferences.css
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 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/. */
-
-/* ===== preferences.css =====================================================
-  == Styles used by the XUL prefwindow element.
-  ======================================================================= */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* ::::: dialog ::::: */
-
-prefwindow {
-  padding: 0px;
-}
-
-prefpane {
-  padding: 8px;
-}
-
-prefwindow[type="child"] {
-  padding: 8px;
-}
-
-prefwindow[type="child"] > prefpane {
-  padding: 0px;
-}
-
-.prefWindow-dlgbuttons {
-  padding-bottom: 8px;
-  padding-inline-start: 8px;
-  padding-inline-end: 8px;
-}
-
-prefwindow[type="child"] .prefWindow-dlgbuttons {
-  padding: 0px;
-}
-
-radio[pane] {
-  -moz-appearance: none;
-  min-width: 4.5em;
-  margin: 0;
-  padding: 3px;
-  color: -moz-FieldText;
-}
-
-.paneSelector {
-  -moz-appearance: listbox;
-  margin: 8px 8px 0 8px;
-  padding: 0;
-}
-
-.paneButtonIcon {
-  width: 32px;
-  height: 32px;
-}
-
-radio[pane][selected="true"] {
-  background-color: Highlight;
-  color: HighlightText;
-}
-
--- a/toolkit/themes/mobile/jar.mn
+++ b/toolkit/themes/mobile/jar.mn
@@ -12,17 +12,16 @@ toolkit.jar:
    skin/classic/global/dropmarker.css                      (global/empty.css)
    skin/classic/global/global.css                          (global/empty.css)
    skin/classic/global/groupbox.css                        (global/empty.css)
    skin/classic/global/listbox.css                         (global/empty.css)
    skin/classic/global/menu.css                            (global/empty.css)
    skin/classic/global/menulist.css                        (global/empty.css)
    skin/classic/global/numberbox.css                       (global/empty.css)
    skin/classic/global/popup.css                           (global/empty.css)
-   skin/classic/global/preferences.css                     (global/empty.css)
    skin/classic/global/progressmeter.css                   (global/empty.css)
    skin/classic/global/radio.css                           (global/empty.css)
    skin/classic/global/resizer.css                         (global/empty.css)
    skin/classic/global/richlistbox.css                     (global/empty.css)
    skin/classic/global/scale.css                           (global/empty.css)
    skin/classic/global/scrollbox.css                       (global/empty.css)
    skin/classic/global/spinbuttons.css                     (global/empty.css)
    skin/classic/global/splitter.css                        (global/empty.css)
--- a/toolkit/themes/osx/global/global.css
+++ b/toolkit/themes/osx/global/global.css
@@ -25,31 +25,23 @@ menulist > menupopup {
   --focus-ring-box-shadow: @focusRingShadow@;
 }
 
 /* ::::: root elements ::::: */
 
 window,
 page,
 dialog,
-wizard,
-prefwindow {
+wizard {
   -moz-appearance: dialog;
   background-color: #FFFFFF;
   color: -moz-DialogText;
   font: message-box;
 }
 
-prefwindow[type="child"] {
-  padding-top: 18px;
-  padding-bottom: 15px;
-  padding-inline-start: 18px;
-  padding-inline-end: 20px;
-}
-
 /* deprecated */
 window.dialog {
   padding-top: 8px;
   padding-bottom: 10px;
   padding-inline-start: 8px;
   padding-inline-end: 10px;
 }
 
deleted file mode 100644
index ca241c7b8a1026051003876e4a75ff0c8113392a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index de527b6627c3b2aea12200a5e84f9fe0967a6bcf..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -20,17 +20,16 @@ toolkit.jar:
   skin/classic/global/groupbox.css
   skin/classic/global/listbox.css
   skin/classic/global/menu.css
   skin/classic/global/menulist.css
 * skin/classic/global/notification.css
   skin/classic/global/netError.css
   skin/classic/global/numberbox.css
   skin/classic/global/popup.css
-  skin/classic/global/preferences.css
   skin/classic/global/progressmeter.css
   skin/classic/global/radio.css
   skin/classic/global/resizer.css
   skin/classic/global/richlistbox.css
   skin/classic/global/scrollbars.css                                 (nativescrollbars.css)
   skin/classic/global/scrollbox.css
   skin/classic/global/spinbuttons.css
   skin/classic/global/splitter.css
@@ -66,18 +65,16 @@ toolkit.jar:
   skin/classic/global/dirListing/dirListing.css                      (dirListing/dirListing.css)
   skin/classic/global/dirListing/folder.png                          (dirListing/folder.png)
   skin/classic/global/dirListing/up.png                              (dirListing/up.png)
   skin/classic/global/icons/blacklist_favicon.png                    (icons/blacklist_favicon.png)
   skin/classic/global/icons/blacklist_64.png                         (icons/blacklist_64.png)
   skin/classic/global/icons/glyph-dropdown.png                       (icons/glyph-dropdown.png)
   skin/classic/global/icons/glyph-dropdown@2x.png                    (icons/glyph-dropdown@2x.png)
   skin/classic/global/icons/notfound.png                             (icons/notfound.png)
-  skin/classic/global/icons/panebutton-active.png                    (icons/panebutton-active.png)
-  skin/classic/global/icons/panebutton-inactive.png                  (icons/panebutton-inactive.png)
   skin/classic/global/icons/panel-dropmarker.png                     (icons/panel-dropmarker.png)
   skin/classic/global/icons/resizer.png                              (icons/resizer.png)
   skin/classic/global/icons/resizer@2x.png                           (icons/resizer@2x.png)
   skin/classic/global/icons/resizer-rtl.png                          (icons/resizer-rtl.png)
   skin/classic/global/icons/resizer-rtl@2x.png                       (icons/resizer-rtl@2x.png)
   skin/classic/global/icons/search-textbox.svg                       (icons/search-textbox.svg)
   skin/classic/global/icons/searchfield-cancel.svg                   (icons/searchfield-cancel.svg)
   skin/classic/global/icons/tabprompts-bgtexture.png                 (icons/tabprompts-bgtexture.png)
deleted file mode 100644
--- a/toolkit/themes/osx/global/preferences.css
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-prefwindow {
-  padding: 0;
-  font: -moz-dialog !important;
-}
-
-prefpane {
-  padding: 12px 12px 0 12px;
-}
-
-prefwindow[type="child"] > prefpane {
-  padding: 0;
-}
-
-.prefWindow-dlgbuttons {
-  margin: 0 12px 12px;
-  padding-top: 0 !important;
-}
-
-.paneSelector {
-  font: message-box;
-  padding: 1px 4px;
-  -moz-appearance: toolbar;
-  margin: 0;
-}
-
-radio[pane] {
-  border: solid transparent;
-  border-width: 0 2px;
-  padding: 5px 4px 3px;
-  margin: 0;
-  -moz-appearance: none;
-  text-shadow: rgba(255, 255, 255, 0.4) 0 1px;
-}
-
-radio[pane]:active:hover {
-  text-shadow: none;
-}
-
-radio[pane]:active:hover > .paneButtonIcon {
-  filter: brightness(0.55);
-}
-
-radio[pane][selected="true"] {
-  -moz-border-image: url("chrome://global/skin/icons/panebutton-active.png") 0 2 fill repeat stretch;
-}
-
-radio[pane][selected="true"]:-moz-window-inactive {
-  -moz-border-image: url("chrome://global/skin/icons/panebutton-inactive.png") 0 2 fill repeat stretch;
-}
-
-.paneButtonLabel {
-  margin: 0 !important;
-}
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -89,20 +89,16 @@ xul|caption xul|label {
   margin: 0 !important;
 }
 
 *|*.main-content {
   padding: 40px 28px;
   overflow: auto;
 }
 
-xul|prefpane > xul|*.content-box {
-  overflow: visible;
-}
-
 /* groupboxes */
 
 xul|groupbox {
   -moz-appearance: none;
   border: none;
   margin: 0;
   padding: 0;
 }
--- a/toolkit/themes/windows/global/global.css
+++ b/toolkit/themes/windows/global/global.css
@@ -32,18 +32,17 @@ menulist > menupopup {
   }
 }
 
 /* ::::: root elements ::::: */
 
 window,
 page,
 dialog,
-wizard,
-prefwindow {
+wizard {
   -moz-appearance: window;
   background-color: -moz-Dialog;
   color: -moz-DialogText;
   font: message-box;
 }
 
 /* deprecated */
 window.dialog {
--- a/toolkit/themes/windows/global/jar.mn
+++ b/toolkit/themes/windows/global/jar.mn
@@ -19,17 +19,16 @@ toolkit.jar:
   skin/classic/global/colorpicker.css
   skin/classic/global/commonDialog.css
   skin/classic/global/findBar.css
 * skin/classic/global/global.css
   skin/classic/global/listbox.css
   skin/classic/global/netError.css
   skin/classic/global/numberbox.css
 * skin/classic/global/notification.css
-  skin/classic/global/preferences.css
   skin/classic/global/printPageSetup.css
   skin/classic/global/printPreview.css
   skin/classic/global/scrollbox.css
   skin/classic/global/splitter.css
   skin/classic/global/toolbar.css
   skin/classic/global/toolbarbutton.css
 * skin/classic/global/tree.css
 * skin/classic/global/alerts/alert.css                     (alerts/alert.css)
deleted file mode 100644
--- a/toolkit/themes/windows/global/preferences.css
+++ /dev/null
@@ -1,76 +0,0 @@
-/* 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/. */
-
-/* ===== preferences.css =====================================================
-  == Styles used by the XUL prefwindow element.
-  ======================================================================= */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* ::::: dialog ::::: */
-
-prefwindow {
-  padding: 0px;
-}
-
-prefpane {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  padding-inline-start: 8px;
-  padding-inline-end: 10px;
-}
-
-prefwindow[type="child"] {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  padding-inline-start: 8px;
-  padding-inline-end: 10px;
-}
-
-prefwindow[type="child"] > prefpane {
-  padding: 0px;
-}
-
-.prefWindow-dlgbuttons {
-  padding-bottom: 10px;
-  padding-inline-start: 8px;
-  padding-inline-end: 10px;
-}
-
-prefwindow[type="child"] .prefWindow-dlgbuttons {
-  padding: 0px;
-}
-
-radio[pane] {
-  -moz-appearance: none;
-  margin: 0px 1px 0px 1px;
-  padding: 1px 3px 1px 3px;
-  min-width: 4.5em;
-}
-
-.paneSelector {
-  border-bottom: 2px groove ThreeDFace;
-  margin: 0px;
-  padding-inline-start: 10px;
-  background-color: -moz-Field;
-  color: -moz-FieldText;
-}
-
-.paneButtonIcon {
-  width: 32px;
-  height: 32px;
-}
-
-radio[pane]:hover {
-  background-color: #E0E8F6;
-  color: black;
-  -moz-appearance: none;
-}
-
-radio[pane][selected="true"] {
-  background-color: #C1D2EE;
-  color: black; 
-  -moz-appearance: none;
-}
-