Bug config - Make Metro about:config better, r=mbrubeck
authorMark Capella <markcapella@twcny.rr.com>
Wed, 22 Jan 2014 05:57:23 -0500
changeset 164703 7b40032d4d181cd2fbaa8ba53a832d5fed6a502d
parent 164702 7a85fd2440e83eb7698abcf2994bd6b79058c65d
child 164704 a7ec92db9f0b4fdaf98bfbeee3dc4feffdca97ea
push id26058
push userryanvm@gmail.com
push dateWed, 22 Jan 2014 20:32:30 +0000
treeherdermozilla-central@cad591993bfa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs959031
milestone29.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 config - Make Metro about:config better, r=mbrubeck * * * Bug 959031 - Make Metro about:config better -- Nits, r=mbrubeck * * * Bug 959031 - Make Metro about:config better -- Retro Fit Strings, r=mbrubeck
browser/metro/base/content/config.js
browser/metro/base/content/config.xul
browser/metro/base/content/pages/config.js
browser/metro/base/content/pages/config.xhtml
browser/metro/base/jar.mn
browser/metro/locales/en-US/chrome/config.dtd
browser/metro/locales/en-US/chrome/config.properties
browser/metro/locales/jar.mn
browser/metro/theme/config.css
browser/metro/theme/images/lock.png
browser/metro/theme/images/reader-plus-icon-xhdpi.png
browser/metro/theme/images/search-clear-30.png
browser/metro/theme/images/search.png
browser/metro/theme/images/textfield.png
browser/metro/theme/jar.mn
deleted file mode 100644
--- a/browser/metro/base/content/config.js
+++ /dev/null
@@ -1,407 +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/. */
-
-let Ci = Components.interfaces;
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-var ViewConfig = {
-  get _main() {
-    delete this._main;
-    return this._main = document.getElementById("main-container");
-  },
-
-  get _container() {
-    delete this._container;
-    return this._container = document.getElementById("prefs-container");
-  },
-
-  get _editor() {
-    delete this._editor;
-    return this._editor = document.getElementById("editor");
-  },
-
-  init: function init() {
-    this._main.addEventListener("click", this, false);
-    window.addEventListener("resize", this, false);
-    window.addEventListener("prefchange", this, false);
-    window.addEventListener("prefnew", this, false);
-
-    this._handleWindowResize();
-    this.filter("");
-
-    document.getElementById("textbox").focus();
-  },
-
-  uninit: function uninit() {
-    this._main.removeEventListener("click", this, false);
-    window.removeEventListener("resize", this, false);
-    window.removeEventListener("prefchange", this, false);
-    window.removeEventListener("prefnew", this, false);
-  },
-
-  filter: function filter(aValue) {
-    let row = document.getElementById("editor-row");
-
-    let container = this._container;
-    container.scrollBoxObject.scrollTo(0, 0);
-    // Clear the list by replacing with a shallow copy
-    let empty = container.cloneNode(false);
-    empty.appendChild(row);
-    container.parentNode.replaceChild(empty, container);
-    this._container = empty;
-
-    let result = Utils.getPrefs(aValue);
-    this._container.setItems(result.map(this._createItem, this));
-  },
-
-  open: function open(aType) {
-    let buttons = document.getElementById("editor-buttons-add");
-    buttons.setAttribute("hidden", "true");
-
-    let shouldFocus = false;
-    let setting = document.getElementById("editor-setting");
-    switch (aType) {
-      case Ci.nsIPrefBranch.PREF_INT:
-        setting.setAttribute("type", "integer");
-        setting.setAttribute("min", -Infinity);
-        break;
-      case Ci.nsIPrefBranch.PREF_BOOL:
-        setting.setAttribute("type", "bool");
-        break;
-      case Ci.nsIPrefBranch.PREF_STRING:
-        setting.setAttribute("type", "string");
-        break;
-    }
-
-    setting.removeAttribute("title");
-    setting.removeAttribute("pref");
-    if (setting.input)
-      setting.input.value = "";
-
-    document.getElementById("editor-container").appendChild(this._editor);
-    let nameField = document.getElementById("editor-name");
-    nameField.value = "";
-
-    this._editor.setAttribute("hidden", "false");
-    this._currentItem = null;
-    nameField.focus();
-  },
-
-  close: function close(aValid) {
-    this._editor.setAttribute("hidden", "true");
-    let buttons = document.getElementById("editor-buttons-add");
-    buttons.setAttribute("hidden", "false");
-
-    if (aValid) {
-      let name = document.getElementById("editor-name").inputField.value;
-      if (name != "") {
-        let setting = document.getElementById("editor-setting");
-        setting.setAttribute("pref", name);
-        setting.valueToPreference();
-      }
-    }
-
-    document.getElementById("editor-container").appendChild(this._editor);
-  },
-
-  _currentItem: null,
-
-  delayEdit: function(aItem) {
-    setTimeout(this.edit.bind(this), 0, aItem);
-  },
-
-  edit: function(aItem) {
-    if (!aItem)
-      return;
-
-    let pref = Utils.getPref(aItem.getAttribute("name"));
-    if (pref.lock || !pref.name || aItem == this._currentItem)
-      return;
-
-    this.close(false);
-    this._currentItem = aItem;
-
-    let setting = document.getElementById("editor-setting");
-    let shouldFocus = false;
-    switch (pref.type) {
-      case Ci.nsIPrefBranch.PREF_BOOL:
-        setting.setAttribute("type", "bool");
-        break;
-
-      case Ci.nsIPrefBranch.PREF_INT:
-        setting.setAttribute("type", "integer");
-        setting.setAttribute("increment", this.getIncrementForValue(pref.value));
-        setting.setAttribute("min", -Infinity);
-        shouldFocus = true;
-        break;
-
-      case Ci.nsIPrefBranch.PREF_STRING:
-        setting.setAttribute("type", "string");
-        shouldFocus = true;
-        break;
-    }
-
-    setting.setAttribute("title", pref.name);
-    setting.setAttribute("pref", pref.name);
-
-    this._container.insertBefore(this._editor, aItem);
-
-    let resetButton = document.getElementById("editor-reset");
-    resetButton.setAttribute("disabled", pref.default);
-
-    this._editor.setAttribute("default", pref.default);
-    this._editor.setAttribute("hidden", "false");
-
-    if (shouldFocus && setting.input)
-      setting.input.focus();
-  },
-
-  reset: function reset(aItem) {
-    let setting = document.getElementById("editor-setting");
-    let pref = Utils.getPref(setting.getAttribute("pref"));
-    if (!pref.default)
-      Utils.resetPref(pref.name);
-  },
-
-  handleEvent: function handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "resize":
-        this._handleWindowResize();
-        break;
-
-      case "prefchange":
-      case "prefnew":
-        this._handlePrefChange(aEvent.detail, aEvent.type == "prefnew");
-        break;
-
-      case "click":
-        this._onClick();
-        break;
-    }
-  },
-
-  _handleWindowResize: function _handleWindowResize() {
-    let mainBox = document.getElementById("main-container");
-    let textbox = document.getElementById("textbox");
-    let height = window.innerHeight - textbox.getBoundingClientRect().height;
-
-    mainBox.setAttribute("height", height);
-  },
-
-  _onClick: function () {
-    // Blur the search box when tapping anywhere else in the content
-    // in order to close the soft keyboard.
-    document.getElementById("textbox").blur();
-  },
-
-  _handlePrefChange: function _handlePrefChange(aIndex, aNew) {
-    let isEditing = !this._editor.hidden;
-    let shouldUpdateEditor = false;
-    if (isEditing) {
-      let setting = document.getElementById("editor-setting");
-      let editorIndex = Utils.getPrefIndex(setting.getAttribute("pref"));
-      shouldUpdateEditor = (aIndex == editorIndex);
-      if(shouldUpdateEditor || aIndex > editorIndex)
-        aIndex += 1;
-    }
-
-    // XXX An item display value will probably fail if a pref is changed in the
-    //     background while there is a filter on the pref
-    let item = shouldUpdateEditor ? this._editor.nextSibling
-                                  : this._container.childNodes[aIndex + 1];// add 1 because of the new pref row
-    if (!item) // the pref is not viewable
-      return;
-
-    if (aNew) {
-      let pref = Utils.getPrefByIndex(aIndex);
-      let row = this._createItem(pref);
-      this._container.insertBefore(row, item);
-      return;
-    }
-
-    let pref = Utils.getPref(item.getAttribute("name"));
-    if (shouldUpdateEditor) {
-      this._editor.setAttribute("default", pref.default);
-
-      let resetButton = document.getElementById("editor-reset");
-      resetButton.disabled = pref.default;
-    }
-
-    item.setAttribute("default", pref.default);
-    item.lastChild.setAttribute("value", pref.value);
-  },
-
-  _createItem: function _createItem(aPref) {
-    let row = document.createElement("richlistitem");
-
-    row.setAttribute("name", aPref.name);
-    row.setAttribute("type", aPref.type);
-    row.setAttribute("role", "button");
-    row.setAttribute("default", aPref.default);
-
-    let label = document.createElement("label");
-    label.setAttribute("class", "preferences-title");
-    label.setAttribute("value", aPref.name);
-    label.setAttribute("crop", "end");
-    row.appendChild(label);
-
-    label = document.createElement("label");
-    label.setAttribute("class", "preferences-value");
-    label.setAttribute("value", aPref.value);
-    label.setAttribute("crop", "end");
-    row.appendChild(label);
-
-    return row;
-  },
-
-  getIncrementForValue: function getIncrementForValue(aValue) {
-    let count = 1;
-    while (aValue >= 100) {
-      aValue /= 10;
-      count *= 10;
-    }
-    return count;
-  }
-};
-
-var Utils = {
-  QueryInterface: function(aIID) {
-    if (!aIID.equals(Ci.nsIObserver) && !aIID.equals(Ci.nsISupportsWeakReference))
-      throw Components.results.NS_ERROR_NO_INTERFACE;
-    return this;
-  },
-
-  get _branch() {
-    delete this._branch;
-    this._branch = Services.prefs.getBranch(null);
-    this._branch.addObserver("", this, true);
-    return this._branch;
-  },
-
-  get _preferences() {
-    delete this._preferences;
-    let list = this._branch.getChildList("", {}).filter(function(element) {
-      return !(/^capability\./.test(element));
-    });
-    return this._preferences = list.sort().map(this.getPref, this);
-  },
-
-  getPrefs: function getPrefs(aValue) {
-    let result = this._preferences.slice();;
-    if (aValue != "") {
-      let reg = this._generateRegexp(aValue);
-      if (!reg)
-        return [];
-
-      result = this._preferences.filter(function(element, index, array) {
-        return reg.test(element.name + ";" + element.value);
-      });
-    }
-
-    return result;
-  },
-
-  getPref: function getPref(aPrefName) {
-    let branch = this._branch;
-    let pref = {
-                 name: aPrefName,
-                 value:  "",
-                 default: !branch.prefHasUserValue(aPrefName),
-                 lock: branch.prefIsLocked(aPrefName),
-                 type: branch.getPrefType(aPrefName)
-               };
-
-    try {
-      switch (pref.type) {
-        case Ci.nsIPrefBranch.PREF_BOOL:
-          pref.value = branch.getBoolPref(aPrefName).toString();
-          break;
-        case Ci.nsIPrefBranch.PREF_INT:
-          pref.value = branch.getIntPref(aPrefName).toString();
-          break;
-        default:
-        case Ci.nsIPrefBranch.PREF_STRING:
-          pref.value = branch.getComplexValue(aPrefName, Ci.nsISupportsString).data;
-          // Try in case it's a localized string (will throw an exception if not)
-          if (pref.default && /^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.value))
-            pref.value = branch.getComplexValue(aPrefName, Ci.nsIPrefLocalizedString).data;
-          break;
-      }
-    } catch (e) {}
-
-    return pref;
-  },
-
-  getPrefByIndex: function getPrefByIndex(aIndex) {
-    return this._preferences[aIndex];
-  },
-
-  getPrefIndex: function getPrefIndex(aPrefName) {
-    let prefs = this._preferences;
-    let high = prefs.length - 1;
-    let low = 0, middle, element;
-
-    while (low <= high) {
-      middle = parseInt((low + high) / 2);
-      element = prefs[middle];
-
-      if (element.name > aPrefName)
-        high = middle - 1;
-      else if (element.name < aPrefName)
-        low = middle + 1;
-      else
-        return middle;
-    }
-
-    return -1;
-  },
-
-  resetPref: function resetPref(aPrefName) {
-    this._branch.clearUserPref(aPrefName);
-  },
-
-  observe: function observe(aSubject, aTopic, aPrefName) {
-    if (aTopic != "nsPref:changed" || /^capability\./.test(aPrefName)) // avoid displaying "private" preferences
-      return;
-
-    let type = "prefchange";
-    let index = this.getPrefIndex(aPrefName);
-    if (index != - 1) {
-      // update the inner array
-      let pref = this.getPref(aPrefName);
-      this._preferences[index].value = pref.value;
-    }
-    else {
-      // XXX we could do better here
-      let list = this._branch.getChildList("", {}).filter(function(element, index, array) {
-        return !(/^capability\./.test(element));
-      });
-      this._preferences = list.sort().map(this.getPref, this);
-
-      type = "prefnew";
-      index = this.getPrefIndex(aPrefName);
-    }
-
-    let evt = document.createEvent("UIEvents");
-    evt.initUIEvent(type, true, true, window, index);
-    window.dispatchEvent(evt);
-  },
-
-  _generateRegexp: function _generateRegexp(aValue) {
-    if (aValue.charAt(0) == "/") {
-      try {
-        let rv = aValue.match(/^\/(.*)\/(i?)$/);
-        return RegExp(rv[1], rv[2]);
-      }
-      catch (e) {
-        return null; // Do nothing on incomplete or bad RegExp
-      }
-    }
-
-    return RegExp(aValue.replace(/([^* \w])/g, "\\$1").replace(/^\*+/, "")
-                        .replace(/\*+/g, ".*"), "i");
-  }
-};
-
deleted file mode 100644
--- a/browser/metro/base/content/config.xul
+++ /dev/null
@@ -1,65 +0,0 @@
-<?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/. -->
-
-<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/config.css" type="text/css"?>
-
-<!DOCTYPE window [
-<!ENTITY % configDTD SYSTEM "chrome://browser/locale/config.dtd">
-%configDTD;
-]>
-
-<window id="about:config"
-        onload="ViewConfig.init();"
-        onunload="ViewConfig.uninit();"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <script type="application/x-javascript" src="chrome://browser/content/config.js"/>
-
-  <vbox class="panel-dark" flex="1">
-    <textbox id="textbox"
-             oncommand="ViewConfig.filter(this.value)"
-             type="search"
-             timeout="400"
-             emptytext="&empty.label;"/>
-
-    <hbox id="main-container" class="panel-dark">
-      <richlistbox id="prefs-container" flex="1" onselect="ViewConfig.delayEdit(this.selectedItem)" batch="25">
-        <richlistitem id="editor-row">
-          <vbox id="editor-container" flex="1">
-
-            <hbox align="center" flex="1">
-              <label value="&newpref.label;" flex="1"/>
-              <spacer flex="1" />
-              <hbox id="editor-buttons-add">
-                <button label="&integer.label;" oncommand="ViewConfig.open(Ci.nsIPrefBranch.PREF_INT)"/>
-                <button label="&boolean.label;" oncommand="ViewConfig.open(Ci.nsIPrefBranch.PREF_BOOL)"/>
-                <button label="&string.label;" oncommand="ViewConfig.open(Ci.nsIPrefBranch.PREF_STRING)"/>
-              </hbox>
-            </hbox>
-
-            <vbox id="editor" hidden="true">
-              <hbox align="center">
-                <textbox id="editor-name" emptytext="&addpref.name;" flex="1"/>
-                <setting id="editor-setting" emptytext="&addpref.value;" onlabel="true" offlabel="false" flex="1"/>
-              </hbox>
-              <hbox id="editor-buttons">
-                <button id="editor-cancel" label="&cancel.label;" oncommand="ViewConfig.close(false)"/>
-                <spacer flex="1"/>
-                <button id="editor-reset" label="&reset.label;" oncommand="ViewConfig.reset(this.parentNode.parentNode.nextSibling)"/>
-                <button id="editor-done" label="&done.label;" oncommand="ViewConfig.close(true)"/>
-              </hbox>
-            </vbox>
-
-          </vbox>
-        </richlistitem>
-      </richlistbox>
-    </hbox>
-  </vbox>
-</window>
-
copy from mobile/android/chrome/content/config.js
copy to browser/metro/base/content/pages/config.js
--- a/mobile/android/chrome/content/config.js
+++ b/browser/metro/base/content/pages/config.js
@@ -1,19 +1,19 @@
 /* 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";
 
 const {classes: Cc, interfaces: Ci, manager: Cm, utils: Cu} = Components;
 Cu.import("resource://gre/modules/Services.jsm");
 
-const VKB_ENTER_KEY = 13;   // User press of VKB enter key
+const PRIVATE_PREF_PREFIX = "capability.";   // Tag to prevent exposing private preferences
 const INITIAL_PAGE_DELAY = 500;   // Initial pause on program start for scroll alignment
-const PREFS_BUFFER_MAX = 30;   // Max prefs buffer size for getPrefsBuffer()
+const PREFS_BUFFER_MAX = 100;   // Max prefs buffer size for getPrefsBuffer()
 const PAGE_SCROLL_TRIGGER = 200;     // Triggers additional getPrefsBuffer() on user scroll-to-bottom
 const FILTER_CHANGE_TRIGGER = 200;     // Delay between responses to filterInput changes
 const INNERHTML_VALUE_DELAY = 100;    // Delay before providing prefs innerHTML value
 
 let gStringBundle = Services.strings.createBundle("chrome://browser/locale/config.properties");
 let gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
 
 
@@ -81,19 +81,19 @@ var NewPrefDialog = {
   // As new pref name is initially displayed, re-focused, or modifed during user input
   _updatePositiveButton: function AC_updatePositiveButton(aPrefName) {
     this._positiveButton.textContent = gStringBundle.GetStringFromName("newPref.createButton");
     this._positiveButton.setAttribute("disabled", true);
     if (aPrefName == "") {
       return;
     }
 
-    // Avoid "private" preferences
-    if (/^capability\./.test(aPrefName)) {
-      this._positiveButton.textContent = "Private";
+    // Prevent addition of new "private" preferences
+    if (aPrefName.startsWith(PRIVATE_PREF_PREFIX)) {
+      this._positiveButton.textContent = gStringBundle.GetStringFromName("newPref.privateButton");
       return;
     }
 
     // If item already in list, it's being changed, else added
     let item = document.querySelector(".pref-item[name=" + aPrefName.quote() + "]");
     if (item) {
       this._positiveButton.textContent = gStringBundle.GetStringFromName("newPref.changeButton");
     } else {
@@ -135,17 +135,17 @@ var NewPrefDialog = {
     this._prefsShield.removeAttribute("shown");
 
     window.removeEventListener("keypress", this.handleKeypress, false);
   },
 
   // Watch user key input so we can provide Enter key action, commit input values
   handleKeypress: function AC_handleKeypress(aEvent) {
     // Close our VKB on new pref enter key press
-    if (aEvent.keyCode == VKB_ENTER_KEY)
+    if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
       aEvent.target.blur();
   },
 
   // New prefs create dialog only allows creating a non-existing preference, doesn't allow for
   // Changing an existing one on-the-fly, tap existing/displayed line item pref for that
   create: function AC_create(aEvent) {
     if (this._positiveButton.getAttribute("disabled") == "true") {
       return;
@@ -188,33 +188,32 @@ var NewPrefDialog = {
  *
  * Main AboutConfig object and methods
  *
  * Implements User Interfaces for maintenance of a list of Preference settings
  *
  */
 var AboutConfig = {
 
-  contextMenuLINode: null,
   filterInput: null,
   _filterPrevInput: null,
   _filterChangeTimer: null,
   _prefsContainer: null,
   _loadingContainer: null,
   _list: null,
 
   // Init the main AboutConfig dialog
   init: function AC_init() {
     this.filterInput = document.getElementById("filter-input");
     this._prefsContainer = document.getElementById("prefs-container");
     this._loadingContainer = document.getElementById("loading-container");
 
     let list = Services.prefs.getChildList("", {}).filter(function(aElement) {
-      // Avoid "private" preferences
-      return !(/^capability\./.test(aElement));
+      // Prevent display of "private" preferences
+      return !aElement.startsWith(PRIVATE_PREF_PREFIX);
     });
     this._list = list.sort().map( function AC_getMapPref(aPref) {
       return new Pref(aPref);
     }, this);
 
     // Display the current prefs list (retains searchFilter value)
     this.bufferFilterInput();
 
@@ -253,33 +252,33 @@ var AboutConfig = {
     this.filterInput.setAttribute("value", this.filterInput.value);
 
     // Don't start new filter search if same as last
     if (this.filterInput.value == this._filterPrevInput) {
       return;
     }
     this._filterPrevInput = this.filterInput.value;
 
-    // Clear list item selection / context menu, prefs list, get first buffer, set scrolling on
+    // Clear list item selection and prefs list, get first buffer, set scrolling on
     this.selected = "";
     this._clearPrefsContainer();
     this._addMorePrefsToContainer();
     window.onscroll = this.onScroll.bind(this);
 
     // Pause for screen to settle, then ensure at top
     setTimeout((function() {
       window.scrollTo(0, 0);
     }).bind(this), INITIAL_PAGE_DELAY);
   },
 
   // Clear the displayed preferences list
   _clearPrefsContainer: function AC_clearPrefsContainer() {
     // Quick clear the prefsContainer list
     let empty = this._prefsContainer.cloneNode(false);
-    this._prefsContainer.parentNode.replaceChild(empty, this._prefsContainer); 
+    this._prefsContainer.parentNode.replaceChild(empty, this._prefsContainer);
     this._prefsContainer = empty;
 
     // Quick clear the prefs li.HTML list
     this._list.forEach(function(item) {
       delete item.li;
     });
   },
 
@@ -325,17 +324,16 @@ var AboutConfig = {
   onScroll: function AC_onScroll(aEvent) {
     if (this._prefsContainer.scrollHeight - (window.pageYOffset + window.innerHeight) < PAGE_SCROLL_TRIGGER) {
       if (!this._filterChangeTimer) {
         this._addMorePrefsToContainer();
       }
     }
   },
 
-
   // Return currently selected list item node
   get selected() {
     return document.querySelector(".pref-item.selected");
   },
 
   // Set list item node as selected
   set selected(aSelection) {
     let currentSelection = this.selected;
@@ -353,17 +351,17 @@ var AboutConfig = {
     if (aSelection) {
       aSelection.classList.add("selected");
       aSelection.addEventListener("keypress", this.handleKeypress, false);
     }
   },
 
   // Watch user key input so we can provide Enter key action, commit input values
   handleKeypress: function AC_handleKeypress(aEvent) {
-    if (aEvent.keyCode == VKB_ENTER_KEY)
+    if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
       aEvent.target.blur();
   },
 
   // Return the target list item node of an action event
   getLINodeForEvent: function AC_getLINodeForEvent(aEvent) {
     let node = aEvent.target;
     while (node && node.nodeName != "li") {
       node = node.parentNode;
@@ -458,18 +456,18 @@ var AboutConfig = {
 
     pref.value += aInt;
   },
 
   // Observe preference changes
   observe: function AC_observe(aSubject, aTopic, aPrefName) {
     let pref = new Pref(aPrefName);
 
-    // Ignore uninteresting changes, and avoid "private" preferences
-    if ((aTopic != "nsPref:changed") || /^capability\./.test(pref.name)) {
+    // Ignore uninteresting preference changes, and external changes to "private" preferences
+    if ((aTopic != "nsPref:changed") || pref.name.startsWith(PRIVATE_PREF_PREFIX)) {
       return;
     }
 
     // If pref type invalid, refresh display as user reset/removed an item from the list
     if (pref.type == Services.prefs.PREF_INVALID) {
       document.location.reload();
       return;
     }
@@ -485,26 +483,16 @@ var AboutConfig = {
     item.setAttribute("value", pref.value);
     let input = item.querySelector("input");
     input.setAttribute("value", pref.value);
     input.value = pref.value;
 
     pref.default ?
       item.querySelector(".reset").setAttribute("disabled", "true") :
       item.querySelector(".reset").removeAttribute("disabled");
-  },
-
-  // Quick context menu helpers for about:config
-  clipboardCopy: function AC_clipboardCopy(aField) {
-    let pref = this._getPrefForNode(this.contextMenuLINode);
-    if (aField == 'name') {
-      gClipboardHelper.copyString(pref.name);
-    } else {
-      gClipboardHelper.copyString(pref.value);
-    }
   }
 }
 
 
 /* ============================== Pref ==============================
  *
  * Individual Preference object / methods
  *
@@ -528,16 +516,17 @@ Pref.prototype = {
       case Services.prefs.PREF_INT:
         return Services.prefs.getIntPref(this.name);
       case Services.prefs.PREF_STRING:
       default:
         return Services.prefs.getCharPref(this.name);
     }
 
   },
+
   set value(aPrefValue) {
     switch (this.type) {
       case Services.prefs.PREF_BOOL:
         Services.prefs.setBoolPref(this.name, aPrefValue);
         break;
       case Services.prefs.PREF_INT:
         Services.prefs.setIntPref(this.name, aPrefValue);
         break;
@@ -574,26 +563,16 @@ Pref.prototype = {
       // Click callback to ensure list item selected even on no-action tap events
       this.li.addEventListener("click",
         function(aEvent) {
           AboutConfig.selected = AboutConfig.getLINodeForEvent(aEvent);
         },
         false
       );
 
-      // Contextmenu callback to identify selected list item
-      this.li.addEventListener("contextmenu",
-        function(aEvent) {
-          AboutConfig.contextMenuLINode = AboutConfig.getLINodeForEvent(aEvent);
-        },
-        false
-      );
-
-      this.li.setAttribute("contextmenu", "prefs-context-menu");
-
       // Create list item outline, bind to object actions
       this.li.innerHTML =
         "<div class='pref-name' " +
             "onclick='AboutConfig.selectOrToggleBoolPref(event);'>" +
             this.name +
         "</div>" +
         "<div class='pref-item-line'>" +
           "<input class='pref-value' value='' " +
@@ -656,9 +635,8 @@ Pref.prototype = {
     }
 
     if (this.locked) {
       valDiv.setAttribute("disabled", this.locked);
       this.li.querySelector(".pref-name").setAttribute("locked", true);
     }
   }
 }
-
copy from mobile/android/chrome/content/config.xhtml
copy to browser/metro/base/content/pages/config.xhtml
--- a/mobile/android/chrome/content/config.xhtml
+++ b/browser/metro/base/content/pages/config.xhtml
@@ -1,86 +1,81 @@
 <?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 html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
-<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd" >
+<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
 %globalDTD;
 <!ENTITY % configDTD SYSTEM "chrome://browser/locale/config.dtd">
 %configDTD;
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 
 <head>
-    <meta name="viewport" content="width=device-width; user-scalable=0" />
+    <meta name="viewport" content="width=device-width; user-scalable=false" />
 
     <link rel="stylesheet" href="chrome://browser/skin/config.css" type="text/css"/>
-    <script type="text/javascript;version=1.8" src="chrome://browser/content/config.js"></script>
+    <script type="text/javascript;version=1.8" src="chrome://browser/content/pages/config.js"/>
 </head>
 
 <body dir="&locale.dir;" onload="NewPrefDialog.init(); AboutConfig.init();"
                          onunload="AboutConfig.uninit();">
 
     <div class="toolbar">
         <div class="toolbar-container">
             <div id="new-pref-toggle-button" onclick="NewPrefDialog.toggleShowHide();"/>
 
             <div class="toolbar-item" id="filter-container">
                 <div id="filter-search-button"/>
-                <input id="filter-input" type="search" placeholder="&toolbar.searchPlaceholder;" value=""
+                <input id="filter-input" type="search" placeholder="&empty.label;" value=""
                     oninput="AboutConfig.bufferFilterInput();"/>
                 <div id="filter-input-clear-button" onclick="AboutConfig.clearFilterInput();"/>
             </div>
         </div>
     </div>
 
     <div id="content" ontouchstart="AboutConfig.filterInput.blur();">
 
         <div id="new-pref-container">
             <li class="pref-item" id="new-pref-item">
                 <div class="pref-item-line">
-                    <input class="pref-name" id="new-pref-name" type="text" placeholder="&newPref.namePlaceholder;"
+                    <input class="pref-name" id="new-pref-name" type="text" placeholder="&addpref.name;"
                         onfocus="NewPrefDialog.focusName(event);"
                         oninput="NewPrefDialog.updateName(event);"/>
                     <select class="pref-value" id="new-pref-type" onchange="NewPrefDialog.type = event.target.value;">
-                        <option value="boolean">&newPref.valueBoolean;</option>
-                        <option value="string">&newPref.valueString;</option>
-                        <option value="int">&newPref.valueInteger;</option>
+                        <option value="boolean">&boolean.label;</option>
+                        <option value="string">&string.label;</option>
+                        <option value="int">&integer.label;</option>
                     </select>
                 </div>
 
                 <div class="pref-item-line" id="new-pref-line-boolean">
                     <input class="pref-value" id="new-pref-value-boolean" disabled="disabled"/>
-                    <div class="pref-button toggle" onclick="NewPrefDialog.toggleBoolValue();">&newPref.toggleButton;</div>
+                    <div class="pref-button toggle" onclick="NewPrefDialog.toggleBoolValue();">&toggle.label;</div>
                 </div>
 
                 <div class="pref-item-line">
-                    <input class="pref-value" id="new-pref-value-string" placeholder="&newPref.stringPlaceholder;"/>
-                    <input class="pref-value" id="new-pref-value-int" placeholder="&newPref.numberPlaceholder;" type="number"/>
+                    <input class="pref-value" id="new-pref-value-string" placeholder="&string.placeholder;"/>
+                    <input class="pref-value" id="new-pref-value-int" placeholder="&number.placeholder;" type="number"/>
                 </div>
 
                 <div class="pref-item-line">
-                    <div class="pref-button cancel" id="negative-button" onclick="NewPrefDialog.hide();">&newPref.cancelButton;</div>
+                    <div class="pref-button cancel" id="negative-button" onclick="NewPrefDialog.hide();">&cancel.label;</div>
                     <div class="pref-button create" id="positive-button" onclick="NewPrefDialog.create(event);"></div>
                 </div>
             </li>
         </div>
 
         <div id="prefs-shield"></div>
 
         <ul id="prefs-container"/>
 
         <ul id="loading-container"><li></li></ul>
 
     </div>
 
-    <menu type="context" id="prefs-context-menu">
-        <menuitem label="&contextMenu.copyPrefName;" onclick="AboutConfig.clipboardCopy('name');"></menuitem>
-        <menuitem label="&contextMenu.copyPrefValue;" onclick="AboutConfig.clipboardCopy('value');"></menuitem>
-    </menu>
-
 </body>
 </html>
--- a/browser/metro/base/jar.mn
+++ b/browser/metro/base/jar.mn
@@ -1,21 +1,22 @@
 #filter substitution
 # 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/.
 
 chrome.jar:
 % content browser %content/
 
+  content/aboutAddons.xhtml                    (content/pages/aboutAddons.xhtml)
   content/aboutCertError.xhtml                 (content/pages/aboutCertError.xhtml)
   content/aboutRights.xhtml                    (content/pages/aboutRights.xhtml)
   content/blockedSite.xhtml                    (content/pages/blockedSite.xhtml)
+  content/config.xhtml                         (content/pages/config.xhtml)
   content/netError.xhtml                       (content/pages/netError.xhtml)
-  content/aboutAddons.xhtml                    (content/pages/aboutAddons.xhtml)
 #ifdef MOZ_CRASHREPORTER
   content/crashprompt.xhtml                    (content/pages/crashprompt.xhtml)
 #endif
 
   content/bindings/bindings.xml                (content/bindings/bindings.xml)
   content/bindings/tabs.xml                    (content/bindings/tabs.xml)
   content/bindings/toggleswitch.xml            (content/bindings/toggleswitch.xml)
   content/bindings/browser.xml                 (content/bindings/browser.xml)
@@ -59,18 +60,17 @@ chrome.jar:
   content/contenthandlers/ConsoleAPIObserver.js (content/contenthandlers/ConsoleAPIObserver.js)
   content/contenthandlers/Content.js           (content/contenthandlers/Content.js)
 
   content/library/SelectionPrototype.js        (content/library/SelectionPrototype.js)
 
   content/ContentAreaObserver.js               (content/ContentAreaObserver.js)
   content/BrowserTouchHandler.js               (content/BrowserTouchHandler.js)
 * content/WebProgress.js                       (content/WebProgress.js)
-  content/config.xul                           (content/config.xul)
-  content/config.js                            (content/config.js)
+  content/pages/config.js                      (content/pages/config.js)
 * content/browser.xul                          (content/browser.xul)
   content/browser.js                           (content/browser.js)
 * content/browser-ui.js                        (content/browser-ui.js)
 * content/browser-scripts.js                   (content/browser-scripts.js)
   content/ContextCommands.js                   (content/ContextCommands.js)
   content/commandUtil.js                       (content/commandUtil.js)
   content/appbar.js                            (content/appbar.js)
   content/shell.xul                            (content/jsshell/shell.xul)
@@ -98,11 +98,11 @@ chrome.jar:
   content/BookmarksView.js                     (content/startui/BookmarksView.js)
   content/HistoryView.js                       (content/startui/HistoryView.js)
   content/TopSitesView.js                      (content/startui/TopSitesView.js)
   content/FirstRunOverlay.xul                  (content/startui/FirstRunOverlay.xul)
 #ifdef MOZ_SERVICES_SYNC
   content/RemoteTabsView.js                    (content/startui/RemoteTabsView.js)
 #endif
 
-% override chrome://global/content/config.xul chrome://browser/content/config.xul
+% override chrome://global/content/config.xul chrome://browser/content/config.xhtml
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
 % override chrome://mozapps/content/extensions/extensions.xul chrome://browser/content/aboutAddons.xhtml
--- a/browser/metro/locales/en-US/chrome/config.dtd
+++ b/browser/metro/locales/en-US/chrome/config.dtd
@@ -1,16 +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/. -->
 
 <!ENTITY empty.label            "Search">
-<!ENTITY newpref.label          "Add a New Preference">
 <!ENTITY addpref.name           "Name">
-<!ENTITY addpref.value          "Value">
 
 <!ENTITY cancel.label           "Cancel">
-<!ENTITY reset.label            "Reset">
-<!ENTITY done.label             "Done">
+<!ENTITY toggle.label           "Toggle">
 
 <!ENTITY integer.label          "Integer">
 <!ENTITY string.label           "String">
 <!ENTITY boolean.label          "Boolean">
+
+<!ENTITY string.placeholder     "Enter a string">
+<!ENTITY number.placeholder     "Enter a number">
new file mode 100644
--- /dev/null
+++ b/browser/metro/locales/en-US/chrome/config.properties
@@ -0,0 +1,10 @@
+# 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/.
+
+newPref.createButton=Create
+newPref.privateButton=Private
+newPref.changeButton=Change
+
+pref.toggleButton=Toggle
+pref.resetButton=Reset
--- a/browser/metro/locales/jar.mn
+++ b/browser/metro/locales/jar.mn
@@ -7,18 +7,19 @@
 # Metro jar resources
 #
 
 @AB_CD@.jar:
 % locale browser @AB_CD@ %locale/browser/
   locale/browser/aboutCertError.dtd       (%chrome/aboutCertError.dtd)
   locale/browser/browser.dtd              (%chrome/browser.dtd)
   locale/browser/browser.properties       (%chrome/browser.properties)
+  locale/browser/config.dtd               (%chrome/config.dtd)
+  locale/browser/config.properties        (%chrome/config.properties)
   locale/browser/region.properties        (%chrome/region.properties)
-  locale/browser/config.dtd               (%chrome/config.dtd)
   locale/browser/preferences.dtd          (%chrome/preferences.dtd)
   locale/browser/aboutPanel.dtd           (%chrome/aboutPanel.dtd)
   locale/browser/searchPanel.dtd          (%chrome/searchPanel.dtd)
   locale/browser/checkbox.dtd             (%chrome/checkbox.dtd)
   locale/browser/sync.dtd                 (%chrome/sync.dtd)
   locale/browser/sync.properties          (%chrome/sync.properties)
   locale/browser/passwordmgr.properties   (%chrome/passwordmgr.properties)
   locale/browser/phishing.dtd             (%chrome/phishing.dtd)
--- a/browser/metro/theme/config.css
+++ b/browser/metro/theme/config.css
@@ -1,97 +1,345 @@
 /* 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/. */
 
-@media (max-width: 499px) {
-  #editor-container > hbox {
-    -moz-box-orient: vertical;
-  }
+html,
+body {
+    margin: 0;
+    padding: 0;
+    background-color: #ced7de;
+    -moz-user-select: none;
+    font-family: "Segoe UI", sans-serif;
+    -moz-text-size-adjust: none;
 }
 
-richlistitem {
-  -moz-box-align: center;
+.toolbar {
+    width: 100%;
+    height: 3em;
+    position: fixed;
+    top: 0;
+    left: 0;
+    z-index: 10;
+    box-shadow: 0 0 3px #444;
+    background-color: #ced7de;
+    color: #000000;
+    font-weight: bold;
+    border-bottom: 2px solid;
+    -moz-border-bottom-colors: #ff9100 #f27900;
+}
+
+.toolbar-container {
+    max-width: 40em;
+    margin-left: auto;
+    margin-right: auto;
 }
 
-richlistitem .preferences-title {
-  pointer-events: none;
-  min-width: 200px;
-  -moz-box-flex: 1;
-  margin-right: 8px;
+#filter-container {
+    margin-top: 0.5em;
+    margin-bottom: 0.5em;
+    margin-right: 0.5em;
+    height: 2em;
+    border: 1px solid transparent;
+    border-image-source: url("chrome://browser/skin/images/textfield.png");
+    border-image-slice: 1 1 3 1;
+    border-image-width: 1px 1px 3px 1px;
+    overflow: hidden;
+    display: flex;
+    flex-direction: row;
 }
 
-/* XXX look  + sync */
-richlistitem[default="false"] .preferences-title {
-  font-weight: bold;
+#filter-input {
+    -moz-appearance: none;
+    border: none;
+    background-image: none;
+    background-color: transparent;
+    display: inline-block;
+    width: 12em;
+    min-width: 0;
+    color: #000000;
+    opacity: 1;
+    flex: 1 1 auto;
+}
+
+#filter-input:-moz-placeholder {
+    color: rgba(255,255,255,0.5);
+}
+
+.toolbar input {
+    display: inline-block;
+    height: 100%;
+    min-width: 3em;
+    -moz-box-sizing: border-box;
+    opacity: 0.75;
+}
+
+#new-pref-toggle-button {
+    background-position: center center;
+    background-image: url("chrome://browser/skin/images/reader-plus-icon-xhdpi.png");
+    background-size: 48px 48px;
+    height: 48px;
+    width: 48px;
+    display: inline-block;
+    outline-style: none;
 }
 
-richlistitem .preferences-value {
-  min-width: 200px;
-  pointer-events: none;
-  -moz-box-flex: 4;
-  text-align: end;
-  color: grey;
+#filter-search-button {
+    background-image: url("chrome://browser/skin/images/search.png");
+    background-size: 32px 32px;
+    height: 32px;
+    width: 32px;
+    display: inline-block;
+    outline-style: none;
+}
+
+#filter-input-clear-button {
+    background-image: url("chrome://browser/skin/images/search-clear-30.png");
+    background-size: 32px 32px;
+    height: 32px;
+    width: 32px;
+    display: inline-block;
+    outline-style: none;
+}
+
+#filter-input[value=""] + #filter-input-clear-button {
+    display: none;
+}
+
+.toolbar-item {
+    display: inline-block;
+    height: 3em;
+    min-width: 3em;
+    float: right;
+}
+
+#content {
+    position: relative;
+    margin: 0;
+    margin-left: auto;
+    margin-right: auto;
+    padding-top: 3em;
+    padding-left: 0;
+    padding-right: 0;
+    min-height: 100%;
+    max-width: 40em;
 }
 
-/* Editor */
-#editor-row {
-  padding: 0;
-  background: #E9E9E9;
+ul {
+    list-style-position: inside;
+    border: 1px solid #808080;
+    background-color: #ffffff;
+    min-height: 100%;
+    width: 100%;
+    padding-top: 0;
+    margin: 0;
+    padding-left: 0;
+    -moz-box-sizing: border-box;
+    box-shadow: 0 0 5px #000000;
+    overflow-x: hidden;
 }
 
-#editor {
-  border-bottom: 1px solid rgb(207,207,207);
+#new-pref-container {
+    width: 100%;
+    margin: 0;
+    background-color: #ffffff;
+    -moz-box-sizing: border-box;
+    box-shadow: 0 0 5px #000000;
+    overflow-x: hidden;
+    max-width: 40em;
+    max-height: 100%;
+    position: fixed;
+    top: 3em;
+    left: auto;
+    display: none;
+    z-index: 5;
 }
 
-#editor > hbox > #editor-name,
-#editor > hbox > #editor-cancel,
-#editor > hbox > #editor-done {
-  display: none;
+#new-pref-container input,
+#new-pref-container select {
+    border: none;
+    background-image: none;
+}
+
+#new-pref-container.show {
+    display: block;
+}
+
+li {
+    list-style-type: none;
+    border-bottom: 1px solid #d3d3d3;
+    opacity: 1;
+    background-color: #ffffff;
+    cursor: pointer;
 }
 
-#editor-container > #editor > hbox > #editor-name,
-#editor-container > #editor > hbox > #editor-cancel,
-#editor-container > #editor > hbox > #editor-done {
-  display: -moz-box;
+#new-pref-line-boolean,
+#new-pref-value-string,
+#new-pref-value-int {
+    display: none;
+}
+#new-pref-item[typestyle="boolean"] #new-pref-line-boolean,
+#new-pref-item[typestyle="string"] #new-pref-value-string,
+#new-pref-item[typestyle="int"] #new-pref-value-int {
+    display: block;
+}
+
+.pref-name,
+.pref-value {
+    padding: 15px 10px;
+    text-align: left;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    background-image: none;
 }
 
-#editor-container > #editor > hbox > #editor-reset {
-  display: none;
+.pref-value {
+    color: rgba(0,0,0,0.5);
+    flex: 1 1 auto;
+    border: none;
+    -moz-appearance: none;
+    background-image: none;
+    background-color: transparent;
+}
+
+.pref-name[locked] {
+    padding-right: 20px;
+    background-image: url("chrome://browser/skin/images/lock.png");
+    background-repeat: no-repeat;
+    background-position: right 50%;
+    background-size: auto 60%;
+}
+
+#new-pref-name {
+    width: 30em;
 }
 
-#editor-container > hbox > label {
-  pointer-events: none;
-  color: black;
+#new-pref-type {
+    display: inline-block !important;
+    border-left: 1px solid #d3d3d3;
+    width: 10em;
+    text-align: right;
+}
+
+.pref-item-line {
+    border-top: 1px solid rgba(0,0,0,0.05);
+    color: rgba(0,0,0,0.5);
+    display: flex;
+    flex-direction: row;
+}
+
+#new-pref-value-boolean {
+    flex: 1 1 auto;
 }
 
-#editor + richlistitem {
-  display: none;
+/* Disable newPref dialog spinbuttons, use custom version from Android */
+/* Filed Bug 962359 to enhance the default spinbutton style to be touch-friendly */
+#new-pref-value-int {
+    -moz-appearance: textfield;
 }
 
-#editor[default="false"] .preferences-title {
-  font-weight: bold;
+#new-pref-container .pref-button.toggle {
+    display: inline-block;
+    opacity: 1;
+    flex: 0 1 auto;
+    float: right;
+}
+
+#new-pref-container .pref-button.cancel,
+#new-pref-container .pref-button.create {
+    display: inline-block;
+    opacity: 1;
+    flex: 1 1 auto;
+}
+
+.pref-item-line {
+    pointer-events: none;
 }
 
-#editor-setting setting {
-  border-color: transparent !important;
+#new-pref-container .pref-item-line,
+.pref-item.selected .pref-item-line,
+.pref-item:not(.selected) .pref-button.reset {
+    pointer-events: auto;
+}
+
+#new-pref-container .pref-button.create[disabled] {
+    color: #d3d3d3;
+}
+
+.pref-item.selected {
+    background-color: rgba(0,0,255,0.05);
 }
 
-#editor-setting[type="string"] .setting-input {
-  -moz-box-flex: 4;
+.pref-button {
+    display: inline-block;
+    -moz-box-sizing: border-box;
+    text-align: center;
+    padding: 10px 1em;
+    border-left: 1px solid rgba(0,0,0,0.1);
+    opacity: 0;
+    transition-property: opacity;
+    transition-duration: 500ms;
 }
 
-#editor-setting[type="string"] .setting-input > textbox {
-  -moz-box-flex: 1;
+.pref-item.selected .pref-item-line .pref-button {
+    opacity: 1;
+}
+
+.pref-item:not(.selected) .pref-item-line .pref-button:not(.reset) {
+    display: none;
+}
+
+.pref-item:not(.selected) .pref-button.reset {
+    opacity: 1;
+}
+
+/* Disable detail list item spinbuttons, use custom version from Android */
+/* Filed Bug 962359 to enhance the default spinbutton style to be touch-friendly */
+.pref-item input[type="number"] {
+    -moz-appearance: textfield;
 }
 
-/* bug 647650: keep 'text-align: right' here instead of using start/end since 
- * the field should looks like ltr as much as possible
- */
-#editor-setting[type="string"] .setting-input > textbox:-moz-locale-dir(rtl) {
-  direction: ltr;
-  text-align: right;
+.pref-button:active {
+    background-color: rgba(0,0,255,0.2);
+}
+
+.pref-button[disabled] {
+    display: none;
+}
+
+.pref-button.up {
+    background-image: url("chrome://browser/skin/images/arrowup-16.png");
+    background-position: center center;
+    background-repeat: no-repeat;
+}
+
+.pref-button.down {
+    background-image: url("chrome://browser/skin/images/arrowdown-16.png");
+    background-position: center center;
+    background-repeat: no-repeat;
 }
 
-#editor-buttons {
-  margin: 2px;
+#prefs-shield {
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0,0,0,0.5);
+    position: fixed;
+    top: 0;
+    left: 0;
+    opacity: 0;
+    transition-property: opacity;
+    transition-duration: 500ms;
+    display: none;
 }
 
+#prefs-shield[shown] {
+    display: block;
+    opacity: 1;
+}
+
+#loading-container > li {
+    background-image: url(chrome://global/skin/media/throbber.png);
+    background-position: center center;
+    background-repeat: no-repeat;
+    padding-left: 40px;
+    height: 3em;
+    width: 100%;
+}
new file mode 100644
index 0000000000000000000000000000000000000000..5ff3654d317252ce95b4d62b168cf9893dfe9487
GIT binary patch
literal 636
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v
z2N=7Z%(epwmK8Xr!}Kz=|C%$Gfq}8b)5S5w<M`dH8}lv)h_F3)f6Fhbv%`hQK+*6y
zr<O#dkx1uU_6Lkc3LDGUgk1Y#C=g_>7PlaHnqQ(5$4c+O&K%<#TV;-$zdR7smvYkT
z`H%ho>;EmzmaA#`_oZfY)S;KPjI;WME9ZKN8cxtTq!W0G*XE#pw&S7~`ERW4HG1am
z*s`VM<&g+QlQ-WCIK0ls&d^e+c(ZtWT9}h+ih8q^*s?rb8S8BY*;yCw?>MV4wK}tn
z-_G;n(MvODhVS#7eb7ykMdsltOCip4u~%>EUjL<PbNEzmLay$PjfXDV3PqhRF89l5
zyA`r(-DSH5Eld5-+2OY3!TCmaLthz5Nc?^&z}(L>mE)hp1A)mux0bdvhP>N)eqC?D
zlj_xGhpONA>@B?bZBh2)fHWo7v`Z^xPb_H*<Xo^~YI{`i?K@dYNAns^HDB11f9+72
z*|t;P`~EX5us(A3@8#&boEORxt*c^QFg^L9+sp98?e1@d*EN5xcE9@8?cwofh4uf?
zE$3FfZ?4@Za-`0P-{c>Yk4OB<{aX&S0V77W#5JNMC9x#cD!C{XNHG{07#ivtnCKcB
zh8S2{85&ucTIw2@TNxNszW-^7q9HdwB{QuOw+4<)j;%lqk{}Ji`DrEPiAAXljw$&`
gsS2LCiRr09sfj6-g(p*OfQlGAUHx3vIVCg!08Rt~{{R30
new file mode 100644
index 0000000000000000000000000000000000000000..abfdbec4b9a6a76418e2d311d739d9d1781436aa
GIT binary patch
literal 274
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUto1QL?Ar-gY-caN_<RIYoP)R^Q
zNRL6T$wkRPhN*ppV^NEio&(d$Lkk=aFnUyRu{2dP9M%u;y=;=Wxn#2Xyg7G&p6Tj6
zqw|6R1RQJ`x+`YpFG<T<G)qfsWm&_{D(&B8JiG-#(^d-$JqTiW!30*vP|y5g(mbhf
z9c>05?Q?u{m`gI&#GSG!E#Tdu_4&qSQ-$DX#@8FxrXM(Kx?pWs*78eSwp`P0h0pN~
znV&8KG2sVe0iW!KbGr56y%QL8r>+Rey%ON6`f)EGM4II$yO!~@G#kdxq9CrPtDnm{
Hr-UW|1HD{P
new file mode 100644
index 0000000000000000000000000000000000000000..8bab39a08d350a1915c2fd1ae871333be1c9dd72
GIT binary patch
literal 476
zc$@*;0VDp2P)<h;3K|Lk000e1NJLTq0015U0015c1^@s6J20-I0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzen~_@RCwCtm%nbpFc8KAVqmI52b3(G
zSfdUMEmB{hec1LDDzzOLD%MOaq!|EZVru$XGLmaue0TXH1}uFNN}T)o&Uf}Ps_Qzs
z#27~x8k6&nhsP&wZVaW+9J=w|RZt1-zCPcN67c98>Hs)_7SK%S%mK==fTAtfY(oa!
zwT$K#+F${{nmwLEs}9h}e!GH0Qz_UyTSB)z<dCtk1bi$3XFWk(c*cQ~j^S+#JG@TF
za<XILe}Uw9bxQ6fWSyC7Y!{TrF;_CKVa+=`W>`#2fm3R>zj6xTKMO=ArNHy1rH0@N
z=s$*gfIM><!iAH|0c+z;eMy82OQ4-@Ckmj2wgO9%OAD^L?6DADQQ%SoHQ|+%nm0-c
zywgB6bxtu{@X=o4>cc?@Ke*kApIrHX<&<+B$o&8})E3@;bLF&w_B}%P)+SrWrbk-$
z1UEL;RNvKffSjNY+px6`udxB>DcDyxcy9LPXNdN8A}~}~4b#wH&3~sq0R{jkX|XC4
S*loiA0000<MNUMnLSTZjHO+_s
new file mode 100644
index 0000000000000000000000000000000000000000..2369d03f336bb909b9c6d19d39b114737bdca59a
GIT binary patch
literal 858
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v
z2N=7Z%(epwmK8Xr!}Kz=|C%!wq|MXCF~sBe*{kPQhlYx<e>i{d_g%J6ZoEE*Cdz9$
z)|zuXUDe3p$SN3Qa-~u5riz7y_Z$;WOJ>n4^^X)ko|zc+rCHpgS)iV^X>!4Y8J89u
z-240u+w++FFZWf?KOea6<jwTCd-uIQUcR>U$9`3xAhEf{KUElxdWf@1I)<IrW^7G;
zw$f13eU`$iWzH>zpI2-<cKhDfMYnjl_nC`ay{vF(#`ja~em7Q>`F~pTVAbKeNy}UX
zt)DL`I%0WH@%7s8b9(!3JaLy_z2x|n1s+<z&+dNW%->=Z%yN@kui~a(xJ#*}<bsS>
zdynZ}H2eNFM3?*I0qu3aj?NPe(wP0cdS3aNT3hC=I;(lV-1)Ng?!A;CsgHpydzx8!
zG^Z-(i|#uZt+ws%iVjn=-LKETJ1%6Dm;CyPQd#7RCI9!7|IAdH$#&t|gK1mMOd7?!
z?+Ql0zaGY*G0WlnW92g@yOLfWV~oiYj%_^lz<hRYvAh3THxb@1f8WgcyU1qNB+p)v
ztKWVcEPcQGZdrZE>)G4S*-cliv~)S0<2db3;bC<<)7SdUo45VG<hi-YT&F_AgzvZ5
zapf00m*)hRon+dSaIY}^%+8fX7sVfU_VgDAamH=G?!D=?-Y;3{n)L34lFMuF-IbUu
z?iE%p=H>J@yqL|2`{GUhx$ok(tni<vx>EjkV9v_Zaa)6@g_K3Sj!tx9xx7U6=a%z4
zs?N6YmRc)MZ48^2c5ln&#PqWgt3KQ^l3IRx(Z3hZno7%NeC&7rml1YOi@{3ZV&(ZC
zw-2USo8H~fC1vBK!tvImMO8{Zy4mg4*$JwiId!ICrw>I~PG^`e^i%xGi+vlocCk+c
zCOg#<*NBpo#FA92<f2p{#b9J$XsByosB2^qVq|1xVs2$>tZQIlWni$xujnL-hTQy=
z%(P0}8m<bTDg|ng1ZfD)Pb(=;EJ|f?Ovz75Rq)JBOiv9;O-!jQJeg_(RK(!v>gTe~
HDWM4fVe@hd
new file mode 100644
index 0000000000000000000000000000000000000000..436853fa1ea73eb25a3b42f2bd1744fe7f523a17
GIT binary patch
literal 166
zc%17D@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9j%oMI=>5Dp-y;YjHK@;M7UB8!3Q
zuY)k7lg8`{prB-lYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt;-)E{-7_
zGks5N<Yi#sIK1J)fBTaYQ=JYiUaqU2#dxJneLDkpb~6uaBLBUgK;;acu6{1-oD!M<
D{>&{{
--- a/browser/metro/theme/jar.mn
+++ b/browser/metro/theme/jar.mn
@@ -145,8 +145,15 @@ chrome.jar:
   skin/images/autoscroll.png                (images/autoscroll.png)
 
   skin/images/arrow-top.png                 (images/arrow-top.png)
   skin/images/arrow-top@1.4x.png            (images/arrow-top@1.4x.png)
   skin/images/arrow-top@1.8x.png            (images/arrow-top@1.8x.png)
   skin/images/arrow-left.png                (images/arrow-left.png)
   skin/images/arrow-left@1.4x.png           (images/arrow-left@1.4x.png)
   skin/images/arrow-left@1.8x.png           (images/arrow-left@1.8x.png)
+
+# AboutConfig specific:
+  skin/images/textfield.png                 (images/textfield.png)
+  skin/images/reader-plus-icon-xhdpi.png    (images/reader-plus-icon-xhdpi.png)
+  skin/images/search.png                    (images/search.png)
+  skin/images/search-clear-30.png           (images/search-clear-30.png)
+  skin/images/lock.png                      (images/lock.png)