Bug 1365133 - Reorganize Preferences sections and regroup <xul:groupbox> elements by new categories - Part 1. draft
authorEvan Tseng <evan@tseng.io>
Fri, 16 Jun 2017 16:24:33 +0800
changeset 607491 cf24dc6a6da232c10784f7075e0cc0e6205bca30
parent 606958 6fec4855b5345eb63fef57089e61829b88f5f4eb
child 607492 89cf60ac69ee8d478d113c959c56d52460d3f0c1
child 607557 493a5891004143aab3c7d61a9a528798c8d99db3
child 607612 9b835d7611d7318948644ef0690c16151d0c7f16
push id67991
push userbmo:evan@tseng.io
push dateWed, 12 Jul 2017 09:14:44 +0000
bugs1365133
milestone56.0a1
Bug 1365133 - Reorganize Preferences sections and regroup <xul:groupbox> elements by new categories - Part 1. MozReview-Commit-ID: Lh8iduzVoad
browser/app/profile/firefox.js
browser/base/content/aboutDialog-appUpdater.js
browser/components/preferences/applicationManager.js
browser/components/preferences/applicationManager.xul
browser/components/preferences/handlers.xml
browser/components/preferences/in-content-new/advanced.js
browser/components/preferences/in-content-new/advanced.xul
browser/components/preferences/in-content-new/applications.js
browser/components/preferences/in-content-new/applications.xul
browser/components/preferences/in-content-new/containers.js
browser/components/preferences/in-content-new/containers.xul
browser/components/preferences/in-content-new/findInPage.js
browser/components/preferences/in-content-new/jar.mn
browser/components/preferences/in-content-new/main.js
browser/components/preferences/in-content-new/main.xul
browser/components/preferences/in-content-new/preferences.js
browser/components/preferences/in-content-new/preferences.xul
browser/components/preferences/in-content-new/privacy.js
browser/components/preferences/in-content-new/privacy.xul
browser/components/preferences/in-content-new/search.js
browser/components/preferences/in-content-new/search.xul
browser/components/preferences/in-content-new/sync.xul
browser/installer/allowed-dupes.mn
browser/locales/en-US/chrome/browser/preferences/advanced.dtd
browser/locales/en-US/chrome/browser/preferences/containers.dtd
browser/locales/en-US/chrome/browser/preferences/content.dtd
browser/locales/en-US/chrome/browser/preferences/main.dtd
browser/locales/en-US/chrome/browser/preferences/preferences.dtd
browser/locales/en-US/chrome/browser/preferences/preferences.properties
browser/locales/en-US/chrome/browser/preferences/privacy.dtd
browser/locales/en-US/chrome/browser/preferences/search.dtd
browser/locales/en-US/chrome/browser/preferences/security.dtd
browser/themes/shared/incontentprefs/preferences.inc.css
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -975,16 +975,20 @@ pref("browser.zoom.full", true);
 pref("browser.zoom.siteSpecific", true);
 
 // Whether or not to update background tabs to the current zoom level.
 pref("browser.zoom.updateBackgroundTabs", true);
 
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
 
+// URL for "Learn More" for DataCollection
+pref("toolkit.datacollection.infoURL",
+     "https://www.mozilla.org/legal/privacy/firefox.html");
+
 // URL for "Learn More" for Crash Reporter
 pref("toolkit.crashreporter.infoURL",
      "https://www.mozilla.org/legal/privacy/firefox.html#crash-reporter");
 
 // base URL for web-based support pages
 pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
 
 // a11y conflicts with e10s support page
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -181,24 +181,19 @@ appUpdater.prototype =
           let year = buildID.slice(0, 4);
           let month = buildID.slice(4, 6);
           let day = buildID.slice(6, 8);
           updateVersion += ` (${year}-${month}-${day})`;
         }
         button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1);
         button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
       }
-      this.updateDeck.selectedPanel = panel;
-      if (!document.commandDispatcher.focusedElement || // don't steal the focus
-          document.commandDispatcher.focusedElement.localName == "button") // except from the other buttons
-        button.focus();
+    }
 
-    } else {
-      this.updateDeck.selectedPanel = panel;
-    }
+    this.updateDeck.selectedPanel = panel;
   },
 
   /**
    * Check for updates
    */
   checkForUpdates() {
     // Clear prefs that could prevent a user from discovering available updates.
     if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
--- a/browser/components/preferences/applicationManager.js
+++ b/browser/components/preferences/applicationManager.js
@@ -7,41 +7,51 @@
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 
 var gAppManagerDialog = {
   _removed: [],
 
   init: function appManager_init() {
     this.handlerInfo = window.arguments[0];
-
+    // The applicationManager will be used
+    // in in-content's gApplicationsPane and in-content-new's gMainPane.
+    // Remove this once we use the in-content-new preferences page.
+    var pane;
+    if (Services.prefs.getBoolPref("browser.preferences.useOldOrganization")) {
+      Services.scriptloader.loadSubScript("chrome://browser/content/preferences/in-content/applications.js");
+      pane = gApplicationsPane;
+    } else {
+      Services.scriptloader.loadSubScript("chrome://browser/content/preferences/in-content-new/main.js");
+      pane = gMainPane;
+    }
     var bundle = document.getElementById("appManagerBundle");
     var contentText;
     if (this.handlerInfo.type == TYPE_MAYBE_FEED)
       contentText = bundle.getString("handleWebFeeds");
     else {
-      var description = gApplicationsPane._describeType(this.handlerInfo);
+      var description = pane._describeType(this.handlerInfo);
       var key =
         (this.handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) ? "handleFile"
                                                                         : "handleProtocol";
         contentText = bundle.getFormattedString(key, [description]);
     }
     contentText = bundle.getFormattedString("descriptionApplications", [contentText]);
     document.getElementById("appDescription").textContent = contentText;
 
     var list = document.getElementById("appList");
     var apps = this.handlerInfo.possibleApplicationHandlers.enumerate();
     while (apps.hasMoreElements()) {
       let app = apps.getNext();
-      if (!gApplicationsPane.isValidHandlerApp(app))
+      if (!pane.isValidHandlerApp(app))
         continue;
 
       app.QueryInterface(Ci.nsIHandlerApp);
       var item = list.appendItem(app.name);
-      item.setAttribute("image", gApplicationsPane._getIconURLForHandlerApp(app));
+      item.setAttribute("image", pane._getIconURLForHandlerApp(app));
       item.className = "listitem-iconic";
       item.app = app;
     }
 
     list.selectedIndex = 0;
   },
 
   onOK: function appManager_onOK() {
--- a/browser/components/preferences/applicationManager.xul
+++ b/browser/components/preferences/applicationManager.xul
@@ -16,18 +16,16 @@
         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://browser/content/preferences/applicationManager.js"/>
-  <script type="application/javascript"
-          src="chrome://browser/content/preferences/in-content-new/applications.js"/>
 
   <commandset id="appManagerCommandSet">
     <command id="cmd_remove"
              oncommand="gAppManagerDialog.remove();"
              disabled="true"/>
   </commandset>
 
   <keyset id="appManagerKeyset">
--- a/browser/components/preferences/handlers.xml
+++ b/browser/components/preferences/handlers.xml
@@ -51,26 +51,32 @@
         <xul:hbox flex="1" align="center" xbl:inherits="tooltiptext=typeDescription">
           <xul:image src="moz-icon://goat?size=16" class="typeIcon"
                      xbl:inherits="src=typeIcon" height="16" width="16"/>
           <xul:label flex="1" crop="end" xbl:inherits="value=typeDescription"/>
         </xul:hbox>
         <xul:hbox flex="1">
           <xul:menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1"
                         xbl:inherits="tooltiptext=actionDescription"
-                        oncommand="gApplicationsPane.onSelectAction(event.originalTarget)">
+                        oncommand="Services.prefs.getBoolPref('browser.preferences.useOldOrganization') ?
+                          gApplicationsPane.onSelectAction(event.originalTarget) :
+                          gMainPane.onSelectAction(event.originalTarget)">
             <xul:menupopup/>
           </xul:menulist>
         </xul:hbox>
       </xul:hbox>
     </content>
 
     <implementation>
       <constructor>
-        gApplicationsPane.rebuildActionsMenu();
+        if (Services.prefs.getBoolPref("browser.preferences.useOldOrganization")) {
+          gApplicationsPane.rebuildActionsMenu();
+        } else {
+          gMainPane.rebuildActionsMenu();
+        }
       </constructor>
     </implementation>
 
   </binding>
 
   <binding id="container">
     <content>
       <xul:hbox flex="1" equalsize="always">
deleted file mode 100644
--- a/browser/components/preferences/in-content-new/advanced.js
+++ /dev/null
@@ -1,202 +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/. */
-
-/* import-globals-from preferences.js */
-/* import-globals-from ../../../base/content/aboutDialog-appUpdater.js */
-
-// Load DownloadUtils module for convertByteUnits
-Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
-Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-var gAdvancedPane = {
-  _inited: false,
-
-  init() {
-    function setEventListener(aId, aEventType, aCallback) {
-      document.getElementById(aId)
-              .addEventListener(aEventType, aCallback.bind(gAdvancedPane));
-    }
-
-    this._inited = true;
-
-    let version = AppConstants.MOZ_APP_VERSION_DISPLAY;
-
-    // Include the build ID if this is an "a#" (nightly) build
-    if (/a\d+$/.test(version)) {
-      let buildID = Services.appinfo.appBuildID;
-      let year = buildID.slice(0, 4);
-      let month = buildID.slice(4, 6);
-      let day = buildID.slice(6, 8);
-      version += ` (${year}-${month}-${day})`;
-    }
-
-    // Append "(32-bit)" or "(64-bit)" build architecture to the version number:
-    let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
-    let archResource = Services.appinfo.is64Bit
-                       ? "aboutDialog.architecture.sixtyFourBit"
-                       : "aboutDialog.architecture.thirtyTwoBit";
-    let arch = bundle.GetStringFromName(archResource);
-    version += ` (${arch})`;
-
-    document.getElementById("version").textContent = version;
-
-    // Show a release notes link if we have a URL.
-    let relNotesLink = document.getElementById("releasenotes");
-    let relNotesPrefType = Services.prefs.getPrefType("app.releaseNotesURL");
-    if (relNotesPrefType != Services.prefs.PREF_INVALID) {
-      let relNotesURL = Services.urlFormatter.formatURLPref("app.releaseNotesURL");
-      if (relNotesURL != "about:blank") {
-        relNotesLink.href = relNotesURL;
-        relNotesLink.hidden = false;
-      }
-    }
-
-    let distroId = Services.prefs.getCharPref("distribution.id", "");
-    if (distroId) {
-      let distroVersion = Services.prefs.getCharPref("distribution.version");
-
-      let distroIdField = document.getElementById("distributionId");
-      distroIdField.value = distroId + " - " + distroVersion;
-      distroIdField.hidden = false;
-
-      let distroAbout = Services.prefs.getStringPref("distribution.about", "");
-      if (distroAbout) {
-        let distroField = document.getElementById("distribution");
-        distroField.value = distroAbout;
-        distroField.hidden = false;
-      }
-    }
-
-    if (AppConstants.MOZ_UPDATER) {
-      gAppUpdater = new appUpdater();
-      let onUnload = () => {
-        window.removeEventListener("unload", onUnload);
-        Services.prefs.removeObserver("app.update.", this);
-      };
-      window.addEventListener("unload", onUnload);
-      Services.prefs.addObserver("app.update.", this);
-      this.updateReadPrefs();
-      setEventListener("updateRadioGroup", "command",
-                       gAdvancedPane.updateWritePrefs);
-      setEventListener("showUpdateHistory", "command",
-                       gAdvancedPane.showUpdates);
-    }
-  },
-
-  /*
-   * Preferences:
-   *
-   * app.update.enabled
-   * - true if updates to the application are enabled, false otherwise
-   * app.update.auto
-   * - true if updates should be automatically downloaded and installed and
-   * false if the user should be asked what he wants to do when an update is
-   * available
-   * extensions.update.enabled
-   * - true if updates to extensions and themes are enabled, false otherwise
-   * browser.search.update
-   * - true if updates to search engines are enabled, false otherwise
-   */
-
-  /**
-   * Selects the item of the radiogroup based on the pref values and locked
-   * states.
-   *
-   * UI state matrix for update preference conditions
-   *
-   * UI Components:                              Preferences
-   * Radiogroup                                  i   = app.update.enabled
-   *                                             ii  = app.update.auto
-   *
-   * Disabled states:
-   * 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 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
-
-      var canCheck = Components.classes["@mozilla.org/updates/update-service;1"].
-                       getService(Components.interfaces.nsIApplicationUpdateService).
-                       canCheckForUpdates;
-      // canCheck is false if the enabledPref is false and locked,
-      // or the binary platform or OS version is not known.
-      // A locked pref is sufficient to disable the radiogroup.
-      radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked;
-
-      if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
-        // Check to see if the maintenance service is installed.
-        // If it is don't show the preference at all.
-        var installed;
-        try {
-          var wrk = Components.classes["@mozilla.org/windows-registry-key;1"]
-                    .createInstance(Components.interfaces.nsIWindowsRegKey);
-          wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
-                   "SOFTWARE\\Mozilla\\MaintenanceService",
-                   wrk.ACCESS_READ | wrk.WOW64_64);
-          installed = wrk.readIntValue("Installed");
-          wrk.close();
-        } catch (e) {
-        }
-        if (installed != 1) {
-          document.getElementById("useService").hidden = true;
-        }
-      }
-    }
-  },
-
-  /**
-   * 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 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;
-          autoPref.value = false;
-          break;
-        case "manual":    // 3. Never check for updates.
-          enabledPref.value = false;
-          autoPref.value = false;
-      }
-    }
-  },
-
-  /**
-   * Displays the history of installed updates.
-   */
-  showUpdates() {
-    gSubDialog.open("chrome://mozapps/content/update/history.xul");
-  },
-
-  observe(aSubject, aTopic, aData) {
-    if (AppConstants.MOZ_UPDATER) {
-      switch (aTopic) {
-        case "nsPref:changed":
-          this.updateReadPrefs();
-          break;
-      }
-    }
-  },
-};
deleted file mode 100644
--- a/browser/components/preferences/in-content-new/advanced.xul
+++ /dev/null
@@ -1,195 +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/.
-
-<!-- Advanced panel -->
-
-#ifdef MOZ_UPDATER
-  <script type="application/javascript" src="chrome://browser/content/aboutDialog-appUpdater.js"/>
-#endif
-
-<script type="application/javascript"
-        src="chrome://browser/content/preferences/in-content-new/advanced.js"/>
-
-<preferences id="advancedPreferences" hidden="true" data-category="paneAdvanced">
-  <preference id="browser.preferences.advanced.selectedTabIndex"
-              name="browser.preferences.advanced.selectedTabIndex"
-              type="int"/>
-
-<!-- Update tab -->
-#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>
-
-#ifdef HAVE_SHELL_SERVICE
-  <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
-  <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
-#endif
-
-<hbox id="header-advanced"
-      class="header"
-      hidden="true"
-      data-category="paneAdvanced">
-  <label class="header-name" flex="1">&paneUpdates.title;</label>
-</hbox>
-
-<!-- Update -->
-<groupbox id="updateApp" data-category="paneAdvanced" hidden="true">
-  <caption><label>&updateApplication.label;</label></caption>
-  <hbox align="start">
-    <vbox flex="1">
-      <description>
-        &updateApplication.version.pre;<label id="version"/>&updateApplication.version.post;
-        <label id="releasenotes" class="learnMore text-link" hidden="true">&releaseNotes.link;</label>
-      </description>
-      <description id="distribution" class="text-blurb" hidden="true"/>
-      <description id="distributionId" class="text-blurb" hidden="true"/>
-    </vbox>
-#ifdef MOZ_UPDATER
-    <spacer flex="1"/>
-    <vbox>
-      <button id="showUpdateHistory"
-              class="accessory-button"
-              label="&updateHistory2.label;"
-              accesskey="&updateHistory2.accesskey;"
-              preference="app.update.disable_button.showUpdateHistory"
-              searchkeywords="&history.title; &history.intro;"/>
-    </vbox>
-#endif
-  </hbox>
-#ifdef MOZ_UPDATER
-  <vbox id="updateBox">
-    <deck id="updateDeck" orient="vertical">
-      <hbox id="checkForUpdates" align="center">
-        <spacer flex="1"/>
-        <button id="checkForUpdatesButton"
-                label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                oncommand="gAppUpdater.checkForUpdates();"/>
-      </hbox>
-      <hbox id="downloadAndInstall" align="center">
-        <spacer flex="1"/>
-        <button id="downloadAndInstallButton"
-                oncommand="gAppUpdater.startDownload();"/>
-                <!-- label and accesskey will be filled by JS -->
-      </hbox>
-      <hbox id="apply" align="center">
-        <spacer flex="1"/>
-        <button id="updateButton"
-                label="&update.updateButton.label3;"
-                accesskey="&update.updateButton.accesskey;"
-                oncommand="gAppUpdater.buttonRestartAfterDownload();"/>
-      </hbox>
-      <hbox id="checkingForUpdates" align="center">
-        <image class="update-throbber"/><label>&update.checkingForUpdates;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <hbox id="downloading" align="center">
-        <image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
-      </hbox>
-      <hbox id="applying" align="center">
-        <image class="update-throbber"/><label>&update.applying;</label>
-      </hbox>
-      <hbox id="downloadFailed" align="center">
-        <label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                oncommand="gAppUpdater.checkForUpdates();"/>
-      </hbox>
-      <hbox id="adminDisabled" align="center">
-        <label>&update.adminDisabled;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <hbox id="noUpdatesFound" align="center">
-        <label>&update.noUpdatesFound;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                oncommand="gAppUpdater.checkForUpdates();"/>
-      </hbox>
-      <hbox id="otherInstanceHandlingUpdates" align="center">
-        <label>&update.otherInstanceHandlingUpdates;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <hbox id="manualUpdate" align="center">
-        <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <hbox id="unsupportedSystem" align="center">
-        <label>&update.unsupported.start;</label><label id="unsupportedLink" class="text-link">&update.unsupported.linkText;</label><label>&update.unsupported.end;</label>
-        <spacer flex="1"/>
-        <button label="&update.checkForUpdatesButton.label;"
-                accesskey="&update.checkForUpdatesButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <hbox id="restarting" align="center">
-        <image class="update-throbber"/><label>&update.restarting;</label>
-        <spacer flex="1"/>
-        <button label="&update.updateButton.label3;"
-                accesskey="&update.updateButton.accesskey;"
-                disabled="true"/>
-      </hbox>
-    </deck>
-  </vbox>
-#endif
-
-  <separator/>
-#ifdef MOZ_UPDATER
-  <description>&updateApplication.description;</description>
-  <radiogroup id="updateRadioGroup">
-    <radio id="autoDesktop"
-           value="auto"
-           label="&updateAuto2.label;"
-           accesskey="&updateAuto2.accesskey;"/>
-    <radio value="checkOnly"
-          label="&updateCheckChoose2.label;"
-          accesskey="&updateCheckChoose2.accesskey;"/>
-    <radio value="manual"
-          label="&updateManual2.label;"
-          accesskey="&updateManual2.accesskey;"/>
-  </radiogroup>
-#ifdef MOZ_MAINTENANCE_SERVICE
-  <checkbox id="useService"
-            label="&useService.label;"
-            accesskey="&useService.accesskey;"
-            preference="app.update.service.enabled"/>
-#endif
-#endif
-  <checkbox id="enableSearchUpdate"
-            label="&enableSearchUpdate2.label;"
-            accesskey="&enableSearchUpdate2.accesskey;"
-            preference="browser.search.update"/>
-</groupbox>
deleted file mode 100644
--- a/browser/components/preferences/in-content-new/applications.js
+++ /dev/null
@@ -1,2101 +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/. */
-
-/* import-globals-from preferences.js */
-
-"use strict";
-
-// Constants & Enumeration Values
-
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-
-const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
-const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
-const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
-const TYPE_PDF = "application/pdf";
-
-const PREF_PDFJS_DISABLED = "pdfjs.disabled";
-const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
-
-const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
-
-// Preferences that affect which entries to show in the list.
-const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
-const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
-  "browser.download.hide_plugins_without_extensions";
-
-/*
- * Preferences where we store handling information about the feed type.
- *
- * browser.feeds.handler
- * - "bookmarks", "reader" (clarified further using the .default preference),
- *   or "ask" -- indicates the default handler being used to process feeds;
- *   "bookmarks" is obsolete; to specify that the handler is bookmarks,
- *   set browser.feeds.handler.default to "bookmarks";
- *
- * browser.feeds.handler.default
- * - "bookmarks", "client" or "web" -- indicates the chosen feed reader used
- *   to display feeds, either transiently (i.e., when the "use as default"
- *   checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
- *   or more permanently (i.e., the item displayed in the dropdown in Feeds
- *   preferences)
- *
- * browser.feeds.handler.webservice
- * - the URL of the currently selected web service used to read feeds
- *
- * browser.feeds.handlers.application
- * - nsILocalFile, stores the current client-side feed reading app if one has
- *   been chosen
- */
-const PREF_FEED_SELECTED_APP    = "browser.feeds.handlers.application";
-const PREF_FEED_SELECTED_WEB    = "browser.feeds.handlers.webservice";
-const PREF_FEED_SELECTED_ACTION = "browser.feeds.handler";
-const PREF_FEED_SELECTED_READER = "browser.feeds.handler.default";
-
-const PREF_VIDEO_FEED_SELECTED_APP    = "browser.videoFeeds.handlers.application";
-const PREF_VIDEO_FEED_SELECTED_WEB    = "browser.videoFeeds.handlers.webservice";
-const PREF_VIDEO_FEED_SELECTED_ACTION = "browser.videoFeeds.handler";
-const PREF_VIDEO_FEED_SELECTED_READER = "browser.videoFeeds.handler.default";
-
-const PREF_AUDIO_FEED_SELECTED_APP    = "browser.audioFeeds.handlers.application";
-const PREF_AUDIO_FEED_SELECTED_WEB    = "browser.audioFeeds.handlers.webservice";
-const PREF_AUDIO_FEED_SELECTED_ACTION = "browser.audioFeeds.handler";
-const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
-
-// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
-// the actions the application can take with content of various types.
-// But since nsIHandlerInfo doesn't support plugins, there's no value
-// identifying the "use plugin" action, so we use this constant instead.
-const kActionUsePlugin = 5;
-
-const ICON_URL_APP = AppConstants.platform == "linux" ?
-                     "moz-icon://dummy.exe?size=16" :
-                     "chrome://browser/skin/preferences/application.png";
-
-// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
-// was set by us to a custom handler icon and CSS should not try to override it.
-const APP_ICON_ATTR_NAME = "appHandlerIcon";
-
-// Utilities
-
-function getFileDisplayName(file) {
-  if (AppConstants.platform == "win") {
-    if (file instanceof Ci.nsILocalFileWin) {
-      try {
-        return file.getVersionInfoField("FileDescription");
-      } catch (e) {}
-    }
-  }
-  if (AppConstants.platform == "macosx") {
-    if (file instanceof Ci.nsILocalFileMac) {
-      try {
-        return file.bundleDisplayName;
-      } catch (e) {}
-    }
-  }
-  return file.leafName;
-}
-
-function getLocalHandlerApp(aFile) {
-  var localHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
-                        createInstance(Ci.nsILocalHandlerApp);
-  localHandlerApp.name = getFileDisplayName(aFile);
-  localHandlerApp.executable = aFile;
-
-  return localHandlerApp;
-}
-
-/**
- * An enumeration of items in a JS array.
- *
- * FIXME: use ArrayConverter once it lands (bug 380839).
- *
- * @constructor
- */
-function ArrayEnumerator(aItems) {
-  this._index = 0;
-  this._contents = aItems;
-}
-
-ArrayEnumerator.prototype = {
-  _index: 0,
-
-  hasMoreElements() {
-    return this._index < this._contents.length;
-  },
-
-  getNext() {
-    return this._contents[this._index++];
-  }
-};
-
-function isFeedType(t) {
-  return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
-}
-
-// HandlerInfoWrapper
-
-/**
- * This object wraps nsIHandlerInfo with some additional functionality
- * the Applications prefpane needs to display and allow modification of
- * the list of handled types.
- *
- * We create an instance of this wrapper for each entry we might display
- * in the prefpane, and we compose the instances from various sources,
- * including plugins and the handler service.
- *
- * We don't implement all the original nsIHandlerInfo functionality,
- * just the stuff that the prefpane needs.
- *
- * In theory, all of the custom functionality in this wrapper should get
- * pushed down into nsIHandlerInfo eventually.
- */
-function HandlerInfoWrapper(aType, aHandlerInfo) {
-  this._type = aType;
-  this.wrappedHandlerInfo = aHandlerInfo;
-}
-
-HandlerInfoWrapper.prototype = {
-  // The wrapped nsIHandlerInfo object.  In general, this object is private,
-  // but there are a couple cases where callers access it directly for things
-  // we haven't (yet?) implemented, so we make it a public property.
-  wrappedHandlerInfo: null,
-
-
-  // Convenience Utils
-
-  _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
-               getService(Ci.nsIHandlerService),
-
-  _prefSvc: Cc["@mozilla.org/preferences-service;1"].
-            getService(Ci.nsIPrefBranch),
-
-  _categoryMgr: Cc["@mozilla.org/categorymanager;1"].
-                getService(Ci.nsICategoryManager),
-
-  element(aID) {
-    return document.getElementById(aID);
-  },
-
-
-  // nsIHandlerInfo
-
-  // The MIME type or protocol scheme.
-  _type: null,
-  get type() {
-    return this._type;
-  },
-
-  get description() {
-    if (this.wrappedHandlerInfo.description)
-      return this.wrappedHandlerInfo.description;
-
-    if (this.primaryExtension) {
-      var extension = this.primaryExtension.toUpperCase();
-      return this.element("bundlePreferences").getFormattedString("fileEnding",
-                                                                  [extension]);
-    }
-
-    return this.type;
-  },
-
-  get preferredApplicationHandler() {
-    return this.wrappedHandlerInfo.preferredApplicationHandler;
-  },
-
-  set preferredApplicationHandler(aNewValue) {
-    this.wrappedHandlerInfo.preferredApplicationHandler = aNewValue;
-
-    // Make sure the preferred handler is in the set of possible handlers.
-    if (aNewValue)
-      this.addPossibleApplicationHandler(aNewValue)
-  },
-
-  get possibleApplicationHandlers() {
-    return this.wrappedHandlerInfo.possibleApplicationHandlers;
-  },
-
-  addPossibleApplicationHandler(aNewHandler) {
-    var possibleApps = this.possibleApplicationHandlers.enumerate();
-    while (possibleApps.hasMoreElements()) {
-      if (possibleApps.getNext().equals(aNewHandler))
-        return;
-    }
-    this.possibleApplicationHandlers.appendElement(aNewHandler);
-  },
-
-  removePossibleApplicationHandler(aHandler) {
-    var defaultApp = this.preferredApplicationHandler;
-    if (defaultApp && aHandler.equals(defaultApp)) {
-      // If the app we remove was the default app, we must make sure
-      // it won't be used anymore
-      this.alwaysAskBeforeHandling = true;
-      this.preferredApplicationHandler = null;
-    }
-
-    var handlers = this.possibleApplicationHandlers;
-    for (var i = 0; i < handlers.length; ++i) {
-      var handler = handlers.queryElementAt(i, Ci.nsIHandlerApp);
-      if (handler.equals(aHandler)) {
-        handlers.removeElementAt(i);
-        break;
-      }
-    }
-  },
-
-  get hasDefaultHandler() {
-    return this.wrappedHandlerInfo.hasDefaultHandler;
-  },
-
-  get defaultDescription() {
-    return this.wrappedHandlerInfo.defaultDescription;
-  },
-
-  // What to do with content of this type.
-  get preferredAction() {
-    // If we have an enabled plugin, then the action is to use that plugin.
-    if (this.pluginName && !this.isDisabledPluginType)
-      return kActionUsePlugin;
-
-    // If the action is to use a helper app, but we don't have a preferred
-    // handler app, then switch to using the system default, if any; otherwise
-    // fall back to saving to disk, which is the default action in nsMIMEInfo.
-    // Note: "save to disk" is an invalid value for protocol info objects,
-    // but the alwaysAskBeforeHandling getter will detect that situation
-    // and always return true in that case to override this invalid value.
-    if (this.wrappedHandlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
-        !gApplicationsPane.isValidHandlerApp(this.preferredApplicationHandler)) {
-      if (this.wrappedHandlerInfo.hasDefaultHandler)
-        return Ci.nsIHandlerInfo.useSystemDefault;
-      return Ci.nsIHandlerInfo.saveToDisk;
-    }
-
-    return this.wrappedHandlerInfo.preferredAction;
-  },
-
-  set preferredAction(aNewValue) {
-    // If the action is to use the plugin,
-    // we must set the preferred action to "save to disk".
-    // But only if it's not currently the preferred action.
-    if ((aNewValue == kActionUsePlugin) &&
-        (this.preferredAction != Ci.nsIHandlerInfo.saveToDisk)) {
-      aNewValue = Ci.nsIHandlerInfo.saveToDisk;
-    }
-
-    // We don't modify the preferred action if the new action is to use a plugin
-    // because handler info objects don't understand our custom "use plugin"
-    // value.  Also, leaving it untouched means that we can automatically revert
-    // to the old setting if the user ever removes the plugin.
-
-    if (aNewValue != kActionUsePlugin)
-      this.wrappedHandlerInfo.preferredAction = aNewValue;
-  },
-
-  get alwaysAskBeforeHandling() {
-    // If this type is handled only by a plugin, we can't trust the value
-    // in the handler info object, since it'll be a default based on the absence
-    // of any user configuration, and the default in that case is to always ask,
-    // even though we never ask for content handled by a plugin, so special case
-    // plugin-handled types by returning false here.
-    if (this.pluginName && this.handledOnlyByPlugin)
-      return false;
-
-    // If this is a protocol type and the preferred action is "save to disk",
-    // which is invalid for such types, then return true here to override that
-    // action.  This could happen when the preferred action is to use a helper
-    // app, but the preferredApplicationHandler is invalid, and there isn't
-    // a default handler, so the preferredAction getter returns save to disk
-    // instead.
-    if (!(this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
-        this.preferredAction == Ci.nsIHandlerInfo.saveToDisk)
-      return true;
-
-    return this.wrappedHandlerInfo.alwaysAskBeforeHandling;
-  },
-
-  set alwaysAskBeforeHandling(aNewValue) {
-    this.wrappedHandlerInfo.alwaysAskBeforeHandling = aNewValue;
-  },
-
-
-  // nsIMIMEInfo
-
-  // The primary file extension associated with this type, if any.
-  //
-  // XXX Plugin objects contain an array of MimeType objects with "suffixes"
-  // properties; if this object has an associated plugin, shouldn't we check
-  // those properties for an extension?
-  get primaryExtension() {
-    try {
-      if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
-          this.wrappedHandlerInfo.primaryExtension)
-        return this.wrappedHandlerInfo.primaryExtension
-    } catch (ex) {}
-
-    return null;
-  },
-
-
-  // Plugin Handling
-
-  // A plugin that can handle this type, if any.
-  //
-  // Note: just because we have one doesn't mean it *will* handle the type.
-  // That depends on whether or not the type is in the list of types for which
-  // plugin handling is disabled.
-  plugin: null,
-
-  // Whether or not this type is only handled by a plugin or is also handled
-  // by some user-configured action as specified in the handler info object.
-  //
-  // Note: we can't just check if there's a handler info object for this type,
-  // because OS and user configuration is mixed up in the handler info object,
-  // so we always need to retrieve it for the OS info and can't tell whether
-  // it represents only OS-default information or user-configured information.
-  //
-  // FIXME: once handler info records are broken up into OS-provided records
-  // and user-configured records, stop using this boolean flag and simply
-  // check for the presence of a user-configured record to determine whether
-  // or not this type is only handled by a plugin.  Filed as bug 395142.
-  handledOnlyByPlugin: undefined,
-
-  get isDisabledPluginType() {
-    return this._getDisabledPluginTypes().indexOf(this.type) != -1;
-  },
-
-  _getDisabledPluginTypes() {
-    var types = "";
-
-    if (this._prefSvc.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES))
-      types = this._prefSvc.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
-
-    // Only split if the string isn't empty so we don't end up with an array
-    // containing a single empty string.
-    if (types != "")
-      return types.split(",");
-
-    return [];
-  },
-
-  disablePluginType() {
-    var disabledPluginTypes = this._getDisabledPluginTypes();
-
-    if (disabledPluginTypes.indexOf(this.type) == -1)
-      disabledPluginTypes.push(this.type);
-
-    this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
-                              disabledPluginTypes.join(","));
-
-    // Update the category manager so existing browser windows update.
-    this._categoryMgr.deleteCategoryEntry("Gecko-Content-Viewers",
-                                          this.type,
-                                          false);
-  },
-
-  enablePluginType() {
-    var disabledPluginTypes = this._getDisabledPluginTypes();
-
-    var type = this.type;
-    disabledPluginTypes = disabledPluginTypes.filter(v => v != type);
-
-    this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
-                              disabledPluginTypes.join(","));
-
-    // Update the category manager so existing browser windows update.
-    this._categoryMgr.
-      addCategoryEntry("Gecko-Content-Viewers",
-                       this.type,
-                       "@mozilla.org/content/plugin/document-loader-factory;1",
-                       false,
-                       true);
-  },
-
-
-  // Storage
-
-  store() {
-    this._handlerSvc.store(this.wrappedHandlerInfo);
-  },
-
-
-  // Icons
-
-  get smallIcon() {
-    return this._getIcon(16);
-  },
-
-  _getIcon(aSize) {
-    if (this.primaryExtension)
-      return "moz-icon://goat." + this.primaryExtension + "?size=" + aSize;
-
-    if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo)
-      return "moz-icon://goat?size=" + aSize + "&contentType=" + this.type;
-
-    // FIXME: consider returning some generic icon when we can't get a URL for
-    // one (for example in the case of protocol schemes).  Filed as bug 395141.
-    return null;
-  }
-
-};
-
-
-// Feed Handler Info
-
-/**
- * This object implements nsIHandlerInfo for the feed types.  It's a separate
- * object because we currently store handling information for the feed type
- * in a set of preferences rather than the nsIHandlerService-managed datastore.
- *
- * This object inherits from HandlerInfoWrapper in order to get functionality
- * that isn't special to the feed type.
- *
- * XXX Should we inherit from HandlerInfoWrapper?  After all, we override
- * most of that wrapper's properties and methods, and we have to dance around
- * the fact that the wrapper expects to have a wrappedHandlerInfo, which we
- * don't provide.
- */
-
-function FeedHandlerInfo(aMIMEType) {
-  HandlerInfoWrapper.call(this, aMIMEType, null);
-}
-
-FeedHandlerInfo.prototype = {
-  __proto__: HandlerInfoWrapper.prototype,
-
-  // Convenience Utils
-
-  _converterSvc:
-    Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
-    getService(Ci.nsIWebContentConverterService),
-
-  _shellSvc: AppConstants.HAVE_SHELL_SERVICE ? getShellService() : null,
-
-  // nsIHandlerInfo
-
-  get description() {
-    return this.element("bundlePreferences").getString(this._appPrefLabel);
-  },
-
-  get preferredApplicationHandler() {
-    switch (this.element(this._prefSelectedReader).value) {
-      case "client":
-        var file = this.element(this._prefSelectedApp).value;
-        if (file)
-          return getLocalHandlerApp(file);
-
-        return null;
-
-      case "web":
-        var uri = this.element(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";
-    } else if (aNewValue instanceof Ci.nsIWebContentHandlerInfo) {
-      this.element(this._prefSelectedWeb).value = aNewValue.uri;
-      this.element(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);
-    }
-  },
-
-  _possibleApplicationHandlers: null,
-
-  get possibleApplicationHandlers() {
-    if (this._possibleApplicationHandlers)
-      return this._possibleApplicationHandlers;
-
-    // A minimal implementation of nsIMutableArray.  It only supports the two
-    // methods its callers invoke, namely appendElement and nsIArray::enumerate.
-    this._possibleApplicationHandlers = {
-      _inner: [],
-      _removed: [],
-
-      QueryInterface(aIID) {
-        if (aIID.equals(Ci.nsIMutableArray) ||
-            aIID.equals(Ci.nsIArray) ||
-            aIID.equals(Ci.nsISupports))
-          return this;
-
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      },
-
-      get length() {
-        return this._inner.length;
-      },
-
-      enumerate() {
-        return new ArrayEnumerator(this._inner);
-      },
-
-      appendElement(aHandlerApp, aWeak) {
-        this._inner.push(aHandlerApp);
-      },
-
-      removeElementAt(aIndex) {
-        this._removed.push(this._inner[aIndex]);
-        this._inner.splice(aIndex, 1);
-      },
-
-      queryElementAt(aIndex, aInterface) {
-        return this._inner[aIndex].QueryInterface(aInterface);
-      }
-    };
-
-    // 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;
-    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.
-    var webHandlers = this._converterSvc.getContentHandlers(this.type);
-    for (let webHandler of webHandlers)
-      this._possibleApplicationHandlers.appendElement(webHandler);
-
-    return this._possibleApplicationHandlers;
-  },
-
-  __defaultApplicationHandler: undefined,
-  get _defaultApplicationHandler() {
-    if (typeof this.__defaultApplicationHandler != "undefined")
-      return this.__defaultApplicationHandler;
-
-    var defaultFeedReader = null;
-    if (AppConstants.HAVE_SHELL_SERVICE) {
-      try {
-        defaultFeedReader = this._shellSvc.defaultFeedReader;
-      } catch (ex) {
-        // no default reader or _shellSvc is null
-      }
-    }
-
-    if (defaultFeedReader) {
-      let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
-                       createInstance(Ci.nsIHandlerApp);
-      handlerApp.name = getFileDisplayName(defaultFeedReader);
-      handlerApp.QueryInterface(Ci.nsILocalHandlerApp);
-      handlerApp.executable = defaultFeedReader;
-
-      this.__defaultApplicationHandler = handlerApp;
-    } else {
-      this.__defaultApplicationHandler = null;
-    }
-
-    return this.__defaultApplicationHandler;
-  },
-
-  get hasDefaultHandler() {
-    if (AppConstants.HAVE_SHELL_SERVICE) {
-      try {
-        if (this._shellSvc.defaultFeedReader)
-          return true;
-      } catch (ex) {
-        // no default reader or _shellSvc is null
-      }
-    }
-
-    return false;
-  },
-
-  get defaultDescription() {
-    if (this.hasDefaultHandler)
-      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) {
-
-      case "bookmarks":
-        return Ci.nsIHandlerInfo.handleInternally;
-
-      case "reader": {
-        let preferredApp = this.preferredApplicationHandler;
-        let defaultApp = this._defaultApplicationHandler;
-
-        // If we have a valid preferred app, return useSystemDefault if it's
-        // the default app; otherwise return useHelperApp.
-        if (gApplicationsPane.isValidHandlerApp(preferredApp)) {
-          if (defaultApp && defaultApp.equals(preferredApp))
-            return Ci.nsIHandlerInfo.useSystemDefault;
-
-          return Ci.nsIHandlerInfo.useHelperApp;
-        }
-
-        // The pref is set to "reader", but we don't have a valid preferred app.
-        // What do we do now?  Not sure this is the best option (perhaps we
-        // should direct the user to the default app, if any), but for now let's
-        // direct the user to live bookmarks.
-        return Ci.nsIHandlerInfo.handleInternally;
-      }
-
-      // If the action is "ask", then alwaysAskBeforeHandling will override
-      // the action, so it doesn't matter what we say it is, it just has to be
-      // something that doesn't cause the controller to hide the type.
-      case "ask":
-      default:
-        return Ci.nsIHandlerInfo.handleInternally;
-    }
-  },
-
-  set preferredAction(aNewValue) {
-    switch (aNewValue) {
-
-      case Ci.nsIHandlerInfo.handleInternally:
-        this.element(this._prefSelectedReader).value = "bookmarks";
-        break;
-
-      case Ci.nsIHandlerInfo.useHelperApp:
-        this.element(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";
-        this.preferredApplicationHandler = this._defaultApplicationHandler;
-        break;
-    }
-  },
-
-  get alwaysAskBeforeHandling() {
-    return this.element(this._prefSelectedAction).value == "ask";
-  },
-
-  set alwaysAskBeforeHandling(aNewValue) {
-    if (aNewValue == true)
-      this.element(this._prefSelectedAction).value = "ask";
-    else
-      this.element(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.
-  _storingAction: false,
-
-
-  // nsIMIMEInfo
-
-  get primaryExtension() {
-    return "xml";
-  },
-
-
-  // Storage
-
-  // 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);
-        var preferredAppFile = pref.value;
-        if (preferredAppFile) {
-          let preferredApp = getLocalHandlerApp(preferredAppFile);
-          if (app.equals(preferredApp))
-            pref.reset();
-        }
-      } else {
-        app.QueryInterface(Ci.nsIWebContentHandlerInfo);
-        this._converterSvc.removeContentHandler(app.contentType, app.uri);
-      }
-    }
-    this._possibleApplicationHandlers._removed = [];
-  },
-
-
-  // Icons
-
-  get smallIcon() {
-    return this._smallIcon;
-  }
-
-};
-
-var feedHandlerInfo = {
-  __proto__: new FeedHandlerInfo(TYPE_MAYBE_FEED),
-  _prefSelectedApp: PREF_FEED_SELECTED_APP,
-  _prefSelectedWeb: PREF_FEED_SELECTED_WEB,
-  _prefSelectedAction: PREF_FEED_SELECTED_ACTION,
-  _prefSelectedReader: PREF_FEED_SELECTED_READER,
-  _smallIcon: "chrome://browser/skin/feeds/feedIcon16.png",
-  _appPrefLabel: "webFeed"
-}
-
-var videoFeedHandlerInfo = {
-  __proto__: new FeedHandlerInfo(TYPE_MAYBE_VIDEO_FEED),
-  _prefSelectedApp: PREF_VIDEO_FEED_SELECTED_APP,
-  _prefSelectedWeb: PREF_VIDEO_FEED_SELECTED_WEB,
-  _prefSelectedAction: PREF_VIDEO_FEED_SELECTED_ACTION,
-  _prefSelectedReader: PREF_VIDEO_FEED_SELECTED_READER,
-  _smallIcon: "chrome://browser/skin/feeds/videoFeedIcon16.png",
-  _appPrefLabel: "videoPodcastFeed"
-}
-
-var audioFeedHandlerInfo = {
-  __proto__: new FeedHandlerInfo(TYPE_MAYBE_AUDIO_FEED),
-  _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP,
-  _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB,
-  _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION,
-  _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
-  _smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
-  _appPrefLabel: "audioPodcastFeed"
-}
-
-/**
- * InternalHandlerInfoWrapper provides a basic mechanism to create an internal
- * mime type handler that can be enabled/disabled in the applications preference
- * menu.
- */
-function InternalHandlerInfoWrapper(aMIMEType) {
-  var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
-  var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
-
-  HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
-}
-
-InternalHandlerInfoWrapper.prototype = {
-  __proto__: HandlerInfoWrapper.prototype,
-
-  // Override store so we so we can notify any code listening for registration
-  // or unregistration of this handler.
-  store() {
-    HandlerInfoWrapper.prototype.store.call(this);
-    Services.obs.notifyObservers(null, this._handlerChanged);
-  },
-
-  get enabled() {
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
-  get description() {
-    return this.element("bundlePreferences").getString(this._appPrefLabel);
-  }
-};
-
-var pdfHandlerInfo = {
-  __proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
-  _handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
-  _appPrefLabel: "portableDocumentFormat",
-  get enabled() {
-    return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
-  },
-};
-
-
-// Prefpane Controller
-
-var gApplicationsPane = {
-  // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
-  // objects, indexed by type.
-  _handledTypes: {},
-
-  // The list of types we can show, sorted by the sort column/direction.
-  // An array of HandlerInfoWrapper objects.  We build this list when we first
-  // load the data and then rebuild it when users change a pref that affects
-  // what types we can show or change the sort column/direction.
-  // Note: this isn't necessarily the list of types we *will* show; if the user
-  // provides a filter string, we'll only show the subset of types in this list
-  // that match that string.
-  _visibleTypes: [],
-
-  // A count of the number of times each visible type description appears.
-  // We use these counts to determine whether or not to annotate descriptions
-  // with their types to distinguish duplicate descriptions from each other.
-  // A hash of integer counts, indexed by string description.
-  _visibleTypeDescriptionCount: {},
-
-
-  // Convenience & Performance Shortcuts
-
-  // These get defined by init().
-  _brandShortName: null,
-  _prefsBundle: null,
-  _list: null,
-  _filter: null,
-
-  _prefSvc: Cc["@mozilla.org/preferences-service;1"].
-            getService(Ci.nsIPrefBranch),
-
-  _mimeSvc: Cc["@mozilla.org/mime;1"].
-            getService(Ci.nsIMIMEService),
-
-  _helperAppSvc: Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
-                 getService(Ci.nsIExternalHelperAppService),
-
-  _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
-               getService(Ci.nsIHandlerService),
-
-  _ioSvc: Cc["@mozilla.org/network/io-service;1"].
-          getService(Ci.nsIIOService),
-
-
-  // Initialization & Destruction
-
-  init() {
-    function setEventListener(aId, aEventType, aCallback) {
-      document.getElementById(aId)
-              .addEventListener(aEventType, aCallback.bind(gApplicationsPane));
-    }
-
-    // Initialize shortcuts to some commonly accessed elements & values.
-    this._brandShortName =
-      document.getElementById("bundleBrand").getString("brandShortName");
-    this._prefsBundle = document.getElementById("bundlePreferences");
-    this._list = document.getElementById("handlersView");
-    this._filter = document.getElementById("filter");
-
-    // Observe preferences that influence what we display so we can rebuild
-    // the view when they change.
-    this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
-    this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_WEB, this);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_ACTION, this);
-    this._prefSvc.addObserver(PREF_FEED_SELECTED_READER, this);
-
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
-    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
-
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
-    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
-
-
-    setEventListener("focusSearch1", "command", gApplicationsPane.focusFilterBox);
-    setEventListener("focusSearch2", "command", gApplicationsPane.focusFilterBox);
-    setEventListener("filter", "command", gApplicationsPane.filter);
-    setEventListener("handlersView", "select",
-      gApplicationsPane.onSelectionChanged);
-    setEventListener("typeColumn", "click", gApplicationsPane.sort);
-    setEventListener("actionColumn", "click", gApplicationsPane.sort);
-    setEventListener("chooseFolder", "command", gApplicationsPane.chooseFolder);
-    setEventListener("browser.download.dir", "change", gApplicationsPane.displayDownloadDirPref);
-
-    // 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")) {
-      this._sortColumn = document.getElementById("actionColumn");
-      // The typeColumn element always has a sortDirection attribute,
-      // either because it was persisted or because the default value
-      // from the xul file was used.  If we are sorting on the other
-      // column, we should remove it.
-      document.getElementById("typeColumn").removeAttribute("sortDirection");
-    } else
-      this._sortColumn = document.getElementById("typeColumn");
-
-    // Load the data and build the list of handlers.
-    // By doing this in a timeout, we let the preferences dialog resize itself
-    // to an appropriate size before we add a bunch of items to the list.
-    // Otherwise, if there are many items, and the Applications prefpane
-    // is the one that gets displayed when the user first opens the dialog,
-    // the dialog might stretch too much in an attempt to fit them all in.
-    // XXX Shouldn't we perhaps just set a max-height on the richlistbox?
-    var _delayedPaneLoad = function(self) {
-      self._loadData();
-      self._rebuildVisibleTypes();
-      self._sortVisibleTypes();
-      self._rebuildView();
-
-      // Notify observers that the UI is now ready
-      Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService).
-      notifyObservers(window, "app-handler-pane-loaded");
-    }
-    setTimeout(_delayedPaneLoad, 0, this);
-  },
-
-  destroy() {
-    window.removeEventListener("unload", this);
-    this._prefSvc.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
-    this._prefSvc.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
-    this._prefSvc.removeObserver(PREF_FEED_SELECTED_APP, this);
-    this._prefSvc.removeObserver(PREF_FEED_SELECTED_WEB, this);
-    this._prefSvc.removeObserver(PREF_FEED_SELECTED_ACTION, this);
-    this._prefSvc.removeObserver(PREF_FEED_SELECTED_READER, this);
-
-    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
-    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
-    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
-    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
-
-    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
-    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
-    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
-    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
-  },
-
-
-  // nsISupports
-
-  QueryInterface(aIID) {
-    if (aIID.equals(Ci.nsIObserver) ||
-        aIID.equals(Ci.nsIDOMEventListener ||
-        aIID.equals(Ci.nsISupports)))
-      return this;
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-
-  // nsIObserver
-
-  observe(aSubject, aTopic, aData) {
-    // Rebuild the list when there are changes to preferences that influence
-    // whether or not to show certain entries in the list.
-    if (aTopic == "nsPref:changed" && !this._storingAction) {
-      // These two prefs alter the list of visible types, so we have to rebuild
-      // that list when they change.
-      if (aData == PREF_SHOW_PLUGINS_IN_LIST ||
-          aData == PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS) {
-        this._rebuildVisibleTypes();
-        this._sortVisibleTypes();
-      }
-
-      // All the prefs we observe can affect what we display, so we rebuild
-      // the view when any of them changes.
-      this._rebuildView();
-    }
-  },
-
-
-  // nsIDOMEventListener
-
-  handleEvent(aEvent) {
-    if (aEvent.type == "unload") {
-      this.destroy();
-    }
-  },
-
-
-  // Composed Model Construction
-
-  _loadData() {
-    this._loadFeedHandler();
-    this._loadInternalHandlers();
-    this._loadPluginHandlers();
-    this._loadApplicationHandlers();
-  },
-
-  _loadFeedHandler() {
-    this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
-    feedHandlerInfo.handledOnlyByPlugin = false;
-
-    this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
-    videoFeedHandlerInfo.handledOnlyByPlugin = false;
-
-    this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
-    audioFeedHandlerInfo.handledOnlyByPlugin = false;
-  },
-
-  /**
-   * Load higher level internal handlers so they can be turned on/off in the
-   * applications menu.
-   */
-  _loadInternalHandlers() {
-    var internalHandlers = [pdfHandlerInfo];
-    for (let internalHandler of internalHandlers) {
-      if (internalHandler.enabled) {
-        this._handledTypes[internalHandler.type] = internalHandler;
-      }
-    }
-  },
-
-  /**
-   * Load the set of handlers defined by plugins.
-   *
-   * Note: if there's more than one plugin for a given MIME type, we assume
-   * the last one is the one that the application will use.  That may not be
-   * correct, but it's how we've been doing it for years.
-   *
-   * Perhaps we should instead query navigator.mimeTypes for the set of types
-   * supported by the application and then get the plugin from each MIME type's
-   * enabledPlugin property.  But if there's a plugin for a type, we need
-   * to know about it even if it isn't enabled, since we're going to give
-   * the user an option to enable it.
-   *
-   * Also note that enabledPlugin does not get updated when
-   * plugin.disable_full_page_plugin_for_types changes, so even if we could use
-   * enabledPlugin to get the plugin that would be used, we'd still need to
-   * check the pref ourselves to find out if it's enabled.
-   */
-  _loadPluginHandlers() {
-    "use strict";
-
-    let mimeTypes = navigator.mimeTypes;
-
-    for (let mimeType of mimeTypes) {
-      let handlerInfoWrapper;
-      if (mimeType.type in this._handledTypes) {
-        handlerInfoWrapper = this._handledTypes[mimeType.type];
-      } else {
-        let wrappedHandlerInfo =
-              this._mimeSvc.getFromTypeAndExtension(mimeType.type, null);
-        handlerInfoWrapper = new HandlerInfoWrapper(mimeType.type, wrappedHandlerInfo);
-        handlerInfoWrapper.handledOnlyByPlugin = true;
-        this._handledTypes[mimeType.type] = handlerInfoWrapper;
-      }
-      handlerInfoWrapper.pluginName = mimeType.enabledPlugin.name;
-    }
-  },
-
-  /**
-   * Load the set of handlers defined by the application datastore.
-   */
-  _loadApplicationHandlers() {
-    var wrappedHandlerInfos = this._handlerSvc.enumerate();
-    while (wrappedHandlerInfos.hasMoreElements()) {
-      let wrappedHandlerInfo =
-        wrappedHandlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
-      let type = wrappedHandlerInfo.type;
-
-      let handlerInfoWrapper;
-      if (type in this._handledTypes)
-        handlerInfoWrapper = this._handledTypes[type];
-      else {
-        handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo);
-        this._handledTypes[type] = handlerInfoWrapper;
-      }
-
-      handlerInfoWrapper.handledOnlyByPlugin = false;
-    }
-  },
-
-
-  // View Construction
-
-  _rebuildVisibleTypes() {
-    // Reset the list of visible types and the visible type description counts.
-    this._visibleTypes = [];
-    this._visibleTypeDescriptionCount = {};
-
-    // Get the preferences that help determine what types to show.
-    var showPlugins = this._prefSvc.getBoolPref(PREF_SHOW_PLUGINS_IN_LIST);
-    var hidePluginsWithoutExtensions =
-      this._prefSvc.getBoolPref(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS);
-
-    for (let type in this._handledTypes) {
-      let handlerInfo = this._handledTypes[type];
-
-      // Hide plugins without associated extensions if so prefed so we don't
-      // show a whole bunch of obscure types handled by plugins on Mac.
-      // Note: though protocol types don't have extensions, we still show them;
-      // the pref is only meant to be applied to MIME types, since plugins are
-      // only associated with MIME types.
-      // FIXME: should we also check the "suffixes" property of the plugin?
-      // Filed as bug 395135.
-      if (hidePluginsWithoutExtensions && handlerInfo.handledOnlyByPlugin &&
-          handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
-          !handlerInfo.primaryExtension)
-        continue;
-
-      // Hide types handled only by plugins if so prefed.
-      if (handlerInfo.handledOnlyByPlugin && !showPlugins)
-        continue;
-
-      // We couldn't find any reason to exclude the type, so include it.
-      this._visibleTypes.push(handlerInfo);
-
-      if (handlerInfo.description in this._visibleTypeDescriptionCount)
-        this._visibleTypeDescriptionCount[handlerInfo.description]++;
-      else
-        this._visibleTypeDescriptionCount[handlerInfo.description] = 1;
-    }
-  },
-
-  _rebuildView() {
-    // Clear the list of entries.
-    while (this._list.childNodes.length > 1)
-      this._list.removeChild(this._list.lastChild);
-
-    var visibleTypes = this._visibleTypes;
-
-    // If the user is filtering the list, then only show matching types.
-    if (this._filter.value)
-      visibleTypes = visibleTypes.filter(this._matchesFilter, this);
-
-    for (let visibleType of visibleTypes) {
-      let item = document.createElement("richlistitem");
-      item.setAttribute("type", visibleType.type);
-      item.setAttribute("typeDescription", this._describeType(visibleType));
-      if (visibleType.smallIcon)
-        item.setAttribute("typeIcon", visibleType.smallIcon);
-      item.setAttribute("actionDescription",
-                        this._describePreferredAction(visibleType));
-
-      if (!this._setIconClassForPreferredAction(visibleType, item)) {
-        item.setAttribute("actionIcon",
-                          this._getIconURLForPreferredAction(visibleType));
-      }
-
-      this._list.appendChild(item);
-    }
-
-    this._selectLastSelectedType();
-  },
-
-  _matchesFilter(aType) {
-    var filterValue = this._filter.value.toLowerCase();
-    return this._describeType(aType).toLowerCase().indexOf(filterValue) != -1 ||
-           this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1;
-  },
-
-  /**
-   * Describe, in a human-readable fashion, the type represented by the given
-   * handler info object.  Normally this is just the description provided by
-   * the info object, but if more than one object presents the same description,
-   * then we annotate the duplicate descriptions with the type itself to help
-   * users distinguish between those types.
-   *
-   * @param aHandlerInfo {nsIHandlerInfo} the type being described
-   * @returns {string} a description of the type
-   */
-  _describeType(aHandlerInfo) {
-    if (this._visibleTypeDescriptionCount[aHandlerInfo.description] > 1)
-      return this._prefsBundle.getFormattedString("typeDescriptionWithType",
-                                                  [aHandlerInfo.description,
-                                                   aHandlerInfo.type]);
-
-    return aHandlerInfo.description;
-  },
-
-  /**
-   * Describe, in a human-readable fashion, the preferred action to take on
-   * the type represented by the given handler info object.
-   *
-   * XXX Should this be part of the HandlerInfoWrapper interface?  It would
-   * violate the separation of model and view, but it might make more sense
-   * nonetheless (f.e. it would make sortTypes easier).
-   *
-   * @param aHandlerInfo {nsIHandlerInfo} the type whose preferred action
-   *                                      is being described
-   * @returns {string} a description of the action
-   */
-  _describePreferredAction(aHandlerInfo) {
-    // alwaysAskBeforeHandling overrides the preferred action, so if that flag
-    // is set, then describe that behavior instead.  For most types, this is
-    // the "alwaysAsk" string, but for the feed type we show something special.
-    if (aHandlerInfo.alwaysAskBeforeHandling) {
-      if (isFeedType(aHandlerInfo.type))
-        return this._prefsBundle.getFormattedString("previewInApp",
-                                                    [this._brandShortName]);
-      return this._prefsBundle.getString("alwaysAsk");
-    }
-
-    switch (aHandlerInfo.preferredAction) {
-      case Ci.nsIHandlerInfo.saveToDisk:
-        return this._prefsBundle.getString("saveFile");
-
-      case Ci.nsIHandlerInfo.useHelperApp:
-        var preferredApp = aHandlerInfo.preferredApplicationHandler;
-        var name;
-        if (preferredApp instanceof Ci.nsILocalHandlerApp)
-          name = getFileDisplayName(preferredApp.executable);
-        else
-          name = preferredApp.name;
-        return this._prefsBundle.getFormattedString("useApp", [name]);
-
-      case Ci.nsIHandlerInfo.handleInternally:
-        // For the feed type, handleInternally means live bookmarks.
-        if (isFeedType(aHandlerInfo.type)) {
-          return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
-                                                      [this._brandShortName]);
-        }
-
-        if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
-          return this._prefsBundle.getFormattedString("previewInApp",
-                                                      [this._brandShortName]);
-        }
-
-        // For other types, handleInternally looks like either useHelperApp
-        // or useSystemDefault depending on whether or not there's a preferred
-        // handler app.
-        if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
-          return aHandlerInfo.preferredApplicationHandler.name;
-
-        return aHandlerInfo.defaultDescription;
-
-        // XXX Why don't we say the app will handle the type internally?
-        // Is it because the app can't actually do that?  But if that's true,
-        // then why would a preferredAction ever get set to this value
-        // in the first place?
-
-      case Ci.nsIHandlerInfo.useSystemDefault:
-        return this._prefsBundle.getFormattedString("useDefault",
-                                                    [aHandlerInfo.defaultDescription]);
-
-      case kActionUsePlugin:
-        return this._prefsBundle.getFormattedString("usePluginIn",
-                                                    [aHandlerInfo.pluginName,
-                                                     this._brandShortName]);
-      default:
-        throw new Error(`Unexpected preferredAction: ${aHandlerInfo.preferredAction}`);
-    }
-  },
-
-  _selectLastSelectedType() {
-    // If the list is disabled by the pref.downloads.disable_button.edit_actions
-    // preference being locked, then don't select the type, as that would cause
-    // it to appear selected, with a different background and an actions menu
-    // that makes it seem like you can choose an action for the type.
-    if (this._list.disabled)
-      return;
-
-    var lastSelectedType = this._list.getAttribute("lastSelectedType");
-    if (!lastSelectedType)
-      return;
-
-    var item = this._list.getElementsByAttribute("type", lastSelectedType)[0];
-    if (!item)
-      return;
-
-    this._list.selectedItem = item;
-  },
-
-  /**
-   * Whether or not the given handler app is valid.
-   *
-   * @param aHandlerApp {nsIHandlerApp} the handler app in question
-   *
-   * @returns {boolean} whether or not it's valid
-   */
-  isValidHandlerApp(aHandlerApp) {
-    if (!aHandlerApp)
-      return false;
-
-    if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
-      return this._isValidHandlerExecutable(aHandlerApp.executable);
-
-    if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
-      return aHandlerApp.uriTemplate;
-
-    if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
-      return aHandlerApp.uri;
-
-    return false;
-  },
-
-  _isValidHandlerExecutable(aExecutable) {
-    let leafName;
-    if (AppConstants.platform == "win") {
-      leafName = `${AppConstants.MOZ_APP_NAME}.exe`;
-    } else if (AppConstants.platform == "macosx") {
-      leafName = AppConstants.MOZ_MACBUNDLE_NAME;
-    } else {
-      leafName = `${AppConstants.MOZ_APP_NAME}-bin`;
-    }
-    return aExecutable &&
-           aExecutable.exists() &&
-           aExecutable.isExecutable() &&
-// XXXben - we need to compare this with the running instance executable
-//          just don't know how to do that via script...
-// XXXmano TBD: can probably add this to nsIShellService
-           aExecutable.leafName != leafName;
-  },
-
-  /**
-   * Rebuild the actions menu for the selected entry.  Gets called by
-   * the richlistitem constructor when an entry in the list gets selected.
-   */
-  rebuildActionsMenu() {
-    var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
-    var menu =
-      document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
-    var menuPopup = menu.menupopup;
-
-    // Clear out existing items.
-    while (menuPopup.hasChildNodes())
-      menuPopup.removeChild(menuPopup.lastChild);
-
-    let internalMenuItem;
-    // Add the "Preview in Firefox" option for optional internal handlers.
-    if (handlerInfo instanceof InternalHandlerInfoWrapper) {
-      internalMenuItem = document.createElement("menuitem");
-      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
-      let label = this._prefsBundle.getFormattedString("previewInApp",
-                                                       [this._brandShortName]);
-      internalMenuItem.setAttribute("label", label);
-      internalMenuItem.setAttribute("tooltiptext", label);
-      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
-      menuPopup.appendChild(internalMenuItem);
-    }
-
-    {
-      var askMenuItem = document.createElement("menuitem");
-      askMenuItem.setAttribute("action", Ci.nsIHandlerInfo.alwaysAsk);
-      let label;
-      if (isFeedType(handlerInfo.type))
-        label = this._prefsBundle.getFormattedString("previewInApp",
-                                                     [this._brandShortName]);
-      else
-        label = this._prefsBundle.getString("alwaysAsk");
-      askMenuItem.setAttribute("label", label);
-      askMenuItem.setAttribute("tooltiptext", label);
-      askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
-      menuPopup.appendChild(askMenuItem);
-    }
-
-    // Create a menu item for saving to disk.
-    // Note: this option isn't available to protocol types, since we don't know
-    // what it means to save a URL having a certain scheme to disk, nor is it
-    // available to feeds, since the feed code doesn't implement the capability.
-    if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
-        !isFeedType(handlerInfo.type)) {
-      var saveMenuItem = document.createElement("menuitem");
-      saveMenuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
-      let label = this._prefsBundle.getString("saveFile");
-      saveMenuItem.setAttribute("label", label);
-      saveMenuItem.setAttribute("tooltiptext", label);
-      saveMenuItem.setAttribute(APP_ICON_ATTR_NAME, "save");
-      menuPopup.appendChild(saveMenuItem);
-    }
-
-    // If this is the feed type, add a Live Bookmarks item.
-    if (isFeedType(handlerInfo.type)) {
-      internalMenuItem = document.createElement("menuitem");
-      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
-      let label = this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
-                                                       [this._brandShortName]);
-      internalMenuItem.setAttribute("label", label);
-      internalMenuItem.setAttribute("tooltiptext", label);
-      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "feed");
-      menuPopup.appendChild(internalMenuItem);
-    }
-
-    // Add a separator to distinguish these items from the helper app items
-    // that follow them.
-    let menuseparator = document.createElement("menuseparator");
-    menuPopup.appendChild(menuseparator);
-
-    // Create a menu item for the OS default application, if any.
-    if (handlerInfo.hasDefaultHandler) {
-      var defaultMenuItem = document.createElement("menuitem");
-      defaultMenuItem.setAttribute("action", Ci.nsIHandlerInfo.useSystemDefault);
-      let label = this._prefsBundle.getFormattedString("useDefault",
-                                                       [handlerInfo.defaultDescription]);
-      defaultMenuItem.setAttribute("label", label);
-      defaultMenuItem.setAttribute("tooltiptext", handlerInfo.defaultDescription);
-      defaultMenuItem.setAttribute("image", this._getIconURLForSystemDefault(handlerInfo));
-
-      menuPopup.appendChild(defaultMenuItem);
-    }
-
-    // Create menu items for possible handlers.
-    let preferredApp = handlerInfo.preferredApplicationHandler;
-    let possibleApps = handlerInfo.possibleApplicationHandlers.enumerate();
-    var possibleAppMenuItems = [];
-    while (possibleApps.hasMoreElements()) {
-      let possibleApp = possibleApps.getNext();
-      if (!this.isValidHandlerApp(possibleApp))
-        continue;
-
-      let menuItem = document.createElement("menuitem");
-      menuItem.setAttribute("action", Ci.nsIHandlerInfo.useHelperApp);
-      let label;
-      if (possibleApp instanceof Ci.nsILocalHandlerApp)
-        label = getFileDisplayName(possibleApp.executable);
-      else
-        label = possibleApp.name;
-      label = this._prefsBundle.getFormattedString("useApp", [label]);
-      menuItem.setAttribute("label", label);
-      menuItem.setAttribute("tooltiptext", label);
-      menuItem.setAttribute("image", this._getIconURLForHandlerApp(possibleApp));
-
-      // Attach the handler app object to the menu item so we can use it
-      // to make changes to the datastore when the user selects the item.
-      menuItem.handlerApp = possibleApp;
-
-      menuPopup.appendChild(menuItem);
-      possibleAppMenuItems.push(menuItem);
-    }
-
-    // Create a menu item for the plugin.
-    if (handlerInfo.pluginName) {
-      var pluginMenuItem = document.createElement("menuitem");
-      pluginMenuItem.setAttribute("action", kActionUsePlugin);
-      let label = this._prefsBundle.getFormattedString("usePluginIn",
-                                                       [handlerInfo.pluginName,
-                                                        this._brandShortName]);
-      pluginMenuItem.setAttribute("label", label);
-      pluginMenuItem.setAttribute("tooltiptext", label);
-      pluginMenuItem.setAttribute(APP_ICON_ATTR_NAME, "plugin");
-      menuPopup.appendChild(pluginMenuItem);
-    }
-
-    // Create a menu item for selecting a local application.
-    let canOpenWithOtherApp = true;
-    if (AppConstants.platform == "win") {
-      // On Windows, selecting an application to open another application
-      // would be meaningless so we special case executables.
-      let executableType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
-                                                    .getTypeFromExtension("exe");
-      canOpenWithOtherApp = handlerInfo.type != executableType;
-    }
-    if (canOpenWithOtherApp) {
-      let menuItem = document.createElement("menuitem");
-      menuItem.className = "choose-app-item";
-      menuItem.addEventListener("command", function(e) {
-        gApplicationsPane.chooseApp(e);
-      });
-      let label = this._prefsBundle.getString("useOtherApp");
-      menuItem.setAttribute("label", label);
-      menuItem.setAttribute("tooltiptext", label);
-      menuPopup.appendChild(menuItem);
-    }
-
-    // Create a menu item for managing applications.
-    if (possibleAppMenuItems.length) {
-      let menuItem = document.createElement("menuseparator");
-      menuPopup.appendChild(menuItem);
-      menuItem = document.createElement("menuitem");
-      menuItem.className = "manage-app-item";
-      menuItem.addEventListener("command", function(e) {
-        gApplicationsPane.manageApp(e);
-      });
-      menuItem.setAttribute("label", this._prefsBundle.getString("manageApp"));
-      menuPopup.appendChild(menuItem);
-    }
-
-    // Select the item corresponding to the preferred action.  If the always
-    // ask flag is set, it overrides the preferred action.  Otherwise we pick
-    // the item identified by the preferred action (when the preferred action
-    // is to use a helper app, we have to pick the specific helper app item).
-    if (handlerInfo.alwaysAskBeforeHandling)
-      menu.selectedItem = askMenuItem;
-    else switch (handlerInfo.preferredAction) {
-      case Ci.nsIHandlerInfo.handleInternally:
-        if (internalMenuItem) {
-          menu.selectedItem = internalMenuItem;
-        } else {
-          Cu.reportError("No menu item defined to set!")
-        }
-        break;
-      case Ci.nsIHandlerInfo.useSystemDefault:
-        menu.selectedItem = defaultMenuItem;
-        break;
-      case Ci.nsIHandlerInfo.useHelperApp:
-        if (preferredApp)
-          menu.selectedItem =
-            possibleAppMenuItems.filter(v => v.handlerApp.equals(preferredApp))[0];
-        break;
-      case kActionUsePlugin:
-        menu.selectedItem = pluginMenuItem;
-        break;
-      case Ci.nsIHandlerInfo.saveToDisk:
-        menu.selectedItem = saveMenuItem;
-        break;
-    }
-  },
-
-
-  // Sorting & Filtering
-
-  _sortColumn: null,
-
-  /**
-   * Sort the list when the user clicks on a column header.
-   */
-  sort(event) {
-    var column = event.target;
-
-    // If the user clicked on a new sort column, remove the direction indicator
-    // from the old column.
-    if (this._sortColumn && this._sortColumn != column)
-      this._sortColumn.removeAttribute("sortDirection");
-
-    this._sortColumn = column;
-
-    // Set (or switch) the sort direction indicator.
-    if (column.getAttribute("sortDirection") == "ascending")
-      column.setAttribute("sortDirection", "descending");
-    else
-      column.setAttribute("sortDirection", "ascending");
-
-    this._sortVisibleTypes();
-    this._rebuildView();
-  },
-
-  /**
-   * Sort the list of visible types by the current sort column/direction.
-   */
-  _sortVisibleTypes() {
-    if (!this._sortColumn)
-      return;
-
-    var t = this;
-
-    function sortByType(a, b) {
-      return t._describeType(a).toLowerCase().
-             localeCompare(t._describeType(b).toLowerCase());
-    }
-
-    function sortByAction(a, b) {
-      return t._describePreferredAction(a).toLowerCase().
-             localeCompare(t._describePreferredAction(b).toLowerCase());
-    }
-
-    switch (this._sortColumn.getAttribute("value")) {
-      case "type":
-        this._visibleTypes.sort(sortByType);
-        break;
-      case "action":
-        this._visibleTypes.sort(sortByAction);
-        break;
-    }
-
-    if (this._sortColumn.getAttribute("sortDirection") == "descending")
-      this._visibleTypes.reverse();
-  },
-
-  /**
-   * Filter the list when the user enters a filter term into the filter field.
-   */
-  filter() {
-    this._rebuildView();
-  },
-
-  focusFilterBox() {
-    this._filter.focus();
-    this._filter.select();
-  },
-
-
-  // Changes
-
-  onSelectAction(aActionItem) {
-    this._storingAction = true;
-
-    try {
-      this._storeAction(aActionItem);
-    } finally {
-      this._storingAction = false;
-    }
-  },
-
-  _storeAction(aActionItem) {
-    var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
-
-    let action = parseInt(aActionItem.getAttribute("action"));
-
-    // Set the plugin state if we're enabling or disabling a plugin.
-    if (action == kActionUsePlugin)
-      handlerInfo.enablePluginType();
-    else if (handlerInfo.pluginName && !handlerInfo.isDisabledPluginType)
-      handlerInfo.disablePluginType();
-
-    // Set the preferred application handler.
-    // We leave the existing preferred app in the list when we set
-    // the preferred action to something other than useHelperApp so that
-    // legacy datastores that don't have the preferred app in the list
-    // of possible apps still include the preferred app in the list of apps
-    // the user can choose to handle the type.
-    if (action == Ci.nsIHandlerInfo.useHelperApp)
-      handlerInfo.preferredApplicationHandler = aActionItem.handlerApp;
-
-    // Set the "always ask" flag.
-    if (action == Ci.nsIHandlerInfo.alwaysAsk)
-      handlerInfo.alwaysAskBeforeHandling = true;
-    else
-      handlerInfo.alwaysAskBeforeHandling = false;
-
-    // Set the preferred action.
-    handlerInfo.preferredAction = action;
-
-    handlerInfo.store();
-
-    // Make sure the handler info object is flagged to indicate that there is
-    // now some user configuration for the type.
-    handlerInfo.handledOnlyByPlugin = false;
-
-    // Update the action label and image to reflect the new preferred action.
-    typeItem.setAttribute("actionDescription",
-                          this._describePreferredAction(handlerInfo));
-    if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
-      typeItem.setAttribute("actionIcon",
-                            this._getIconURLForPreferredAction(handlerInfo));
-    }
-  },
-
-  manageApp(aEvent) {
-    // Don't let the normal "on select action" handler get this event,
-    // as we handle it specially ourselves.
-    aEvent.stopPropagation();
-
-    var typeItem = this._list.selectedItem;
-    var handlerInfo = this._handledTypes[typeItem.type];
-
-    let onComplete = () => {
-      // Rebuild the actions menu so that we revert to the previous selection,
-      // or "Always ask" if the previous default application has been removed
-      this.rebuildActionsMenu();
-
-      // update the richlistitem too. Will be visible when selecting another row
-      typeItem.setAttribute("actionDescription",
-                            this._describePreferredAction(handlerInfo));
-      if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
-        typeItem.setAttribute("actionIcon",
-                              this._getIconURLForPreferredAction(handlerInfo));
-      }
-    };
-
-    gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul",
-                    "resizable=no", handlerInfo, onComplete);
-
-  },
-
-  chooseApp(aEvent) {
-    // Don't let the normal "on select action" handler get this event,
-    // as we handle it specially ourselves.
-    aEvent.stopPropagation();
-
-    var handlerApp;
-    let chooseAppCallback = aHandlerApp => {
-      // Rebuild the actions menu whether the user picked an app or canceled.
-      // If they picked an app, we want to add the app to the menu and select it.
-      // If they canceled, we want to go back to their previous selection.
-      this.rebuildActionsMenu();
-
-      // If the user picked a new app from the menu, select it.
-      if (aHandlerApp) {
-        let typeItem = this._list.selectedItem;
-        let actionsMenu =
-          document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
-        let menuItems = actionsMenu.menupopup.childNodes;
-        for (let i = 0; i < menuItems.length; i++) {
-          let menuItem = menuItems[i];
-          if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
-            actionsMenu.selectedIndex = i;
-            this.onSelectAction(menuItem);
-            break;
-          }
-        }
-      }
-    };
-
-    if (AppConstants.platform == "win") {
-      var params = {};
-      var handlerInfo = this._handledTypes[this._list.selectedItem.type];
-
-      if (isFeedType(handlerInfo.type)) {
-        // MIME info will be null, create a temp object.
-        params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type,
-                                                   handlerInfo.primaryExtension);
-      } else {
-        params.mimeInfo = handlerInfo.wrappedHandlerInfo;
-      }
-
-      params.title         = this._prefsBundle.getString("fpTitleChooseApp");
-      params.description   = handlerInfo.description;
-      params.filename      = null;
-      params.handlerApp    = null;
-
-      let onAppSelected = () => {
-        if (this.isValidHandlerApp(params.handlerApp)) {
-          handlerApp = params.handlerApp;
-
-          // Add the app to the type's list of possible handlers.
-          handlerInfo.addPossibleApplicationHandler(handlerApp);
-        }
-
-        chooseAppCallback(handlerApp);
-      };
-
-      gSubDialog.open("chrome://global/content/appPicker.xul",
-                      null, params, onAppSelected);
-    } else {
-      let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
-      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-      let fpCallback = aResult => {
-        if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
-            this._isValidHandlerExecutable(fp.file)) {
-          handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
-                       createInstance(Ci.nsILocalHandlerApp);
-          handlerApp.name = getFileDisplayName(fp.file);
-          handlerApp.executable = fp.file;
-
-          // Add the app to the type's list of possible handlers.
-          let handler = this._handledTypes[this._list.selectedItem.type];
-          handler.addPossibleApplicationHandler(handlerApp);
-
-          chooseAppCallback(handlerApp);
-        }
-      };
-
-      // Prompt the user to pick an app.  If they pick one, and it's a valid
-      // selection, then add it to the list of possible handlers.
-      fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
-      fp.appendFilters(Ci.nsIFilePicker.filterApps);
-      fp.open(fpCallback);
-    }
-  },
-
-  // Mark which item in the list was last selected so we can reselect it
-  // when we rebuild the list or when the user returns to the prefpane.
-  onSelectionChanged() {
-    if (this._list.selectedItem)
-      this._list.setAttribute("lastSelectedType",
-                              this._list.selectedItem.getAttribute("type"));
-  },
-
-  _setIconClassForPreferredAction(aHandlerInfo, aElement) {
-    // If this returns true, the attribute that CSS sniffs for was set to something
-    // so you shouldn't manually set an icon URI.
-    // This removes the existing actionIcon attribute if any, even if returning false.
-    aElement.removeAttribute("actionIcon");
-
-    if (aHandlerInfo.alwaysAskBeforeHandling) {
-      aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
-      return true;
-    }
-
-    switch (aHandlerInfo.preferredAction) {
-      case Ci.nsIHandlerInfo.saveToDisk:
-        aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
-        return true;
-
-      case Ci.nsIHandlerInfo.handleInternally:
-        if (isFeedType(aHandlerInfo.type)) {
-          aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
-          return true;
-        } else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
-          aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
-          return true;
-        }
-        break;
-
-      case kActionUsePlugin:
-        aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
-        return true;
-    }
-    aElement.removeAttribute(APP_ICON_ATTR_NAME);
-    return false;
-  },
-
-  _getIconURLForPreferredAction(aHandlerInfo) {
-    switch (aHandlerInfo.preferredAction) {
-      case Ci.nsIHandlerInfo.useSystemDefault:
-        return this._getIconURLForSystemDefault(aHandlerInfo);
-
-      case Ci.nsIHandlerInfo.useHelperApp:
-        let preferredApp = aHandlerInfo.preferredApplicationHandler;
-        if (this.isValidHandlerApp(preferredApp))
-          return this._getIconURLForHandlerApp(preferredApp);
-        // Explicit fall-through
-
-      // This should never happen, but if preferredAction is set to some weird
-      // value, then fall back to the generic application icon.
-      default:
-        return ICON_URL_APP;
-    }
-  },
-
-  _getIconURLForHandlerApp(aHandlerApp) {
-    if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
-      return this._getIconURLForFile(aHandlerApp.executable);
-
-    if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
-      return this._getIconURLForWebApp(aHandlerApp.uriTemplate);
-
-    if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
-      return this._getIconURLForWebApp(aHandlerApp.uri)
-
-    // We know nothing about other kinds of handler apps.
-    return "";
-  },
-
-  _getIconURLForFile(aFile) {
-    var fph = this._ioSvc.getProtocolHandler("file").
-              QueryInterface(Ci.nsIFileProtocolHandler);
-    var urlSpec = fph.getURLSpecFromFile(aFile);
-
-    return "moz-icon://" + urlSpec + "?size=16";
-  },
-
-  _getIconURLForWebApp(aWebAppURITemplate) {
-    var uri = this._ioSvc.newURI(aWebAppURITemplate);
-
-    // Unfortunately we can't use the favicon service to get the favicon,
-    // because the service looks in the annotations table for a record with
-    // the exact URL we give it, and users won't have such records for URLs
-    // they don't visit, and users won't visit the web app's URL template,
-    // they'll only visit URLs derived from that template (i.e. with %s
-    // in the template replaced by the URL of the content being handled).
-
-    if (/^https?$/.test(uri.scheme) && this._prefSvc.getBoolPref("browser.chrome.favicons"))
-      return uri.prePath + "/favicon.ico";
-
-    return "";
-  },
-
-  _getIconURLForSystemDefault(aHandlerInfo) {
-    // Handler info objects for MIME types on some OSes implement a property bag
-    // interface from which we can get an icon for the default app, so if we're
-    // dealing with a MIME type on one of those OSes, then try to get the icon.
-    if ("wrappedHandlerInfo" in aHandlerInfo) {
-      let wrappedHandlerInfo = aHandlerInfo.wrappedHandlerInfo;
-
-      if (wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
-          wrappedHandlerInfo instanceof Ci.nsIPropertyBag) {
-        try {
-          let url = wrappedHandlerInfo.getProperty("defaultApplicationIconURL");
-          if (url)
-            return url + "?size=16";
-        } catch (ex) {}
-      }
-    }
-
-    // If this isn't a MIME type object on an OS that supports retrieving
-    // the icon, or if we couldn't retrieve the icon for some other reason,
-    // then use a generic icon.
-    return ICON_URL_APP;
-  },
-
-  // DOWNLOADS
-
-  /*
-   * Preferences:
-   *
-   * browser.download.useDownloadDir - bool
-   *   True - Save files directly to the folder configured via the
-   *   browser.download.folderList preference.
-   *   False - Always ask the user where to save a file and default to
-   *   browser.download.lastDir when displaying a folder picker dialog.
-   * browser.download.dir - local file handle
-   *   A local folder the user may have selected for downloaded files to be
-   *   saved. Migration of other browser settings may also set this path.
-   *   This folder is enabled when folderList equals 2.
-   * browser.download.lastDir - local file handle
-   *   May contain the last folder path accessed when the user browsed
-   *   via the file save-as dialog. (see contentAreaUtils.js)
-   * browser.download.folderList - int
-   *   Indicates the location users wish to save downloaded files too.
-   *   It is also used to display special file labels when the default
-   *   download location is either the Desktop or the Downloads folder.
-   *   Values:
-   *     0 - The desktop is the default download location.
-   *     1 - The system's downloads folder is the default download location.
-   *     2 - The default download location is elsewhere as specified in
-   *         browser.download.dir.
-   * browser.download.downloadDir
-   *   deprecated.
-   * browser.download.defaultFolder
-   *   deprecated.
-   */
-
-  /**
-   * 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");
-    downloadFolder.disabled = !preference.value || preference.locked;
-    chooseFolder.disabled = !preference.value || preference.locked;
-
-    // don't override the preference's value in UI
-    return undefined;
-  },
-
-  /**
-   * 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 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
-    if (currentDirPref && currentDirPref.exists()) {
-      fp.displayDirectory = currentDirPref;
-    } else if (defDownloads && defDownloads.exists()) {
-      // Try the system's download dir
-      fp.displayDirectory = defDownloads;
-    } else {
-      // Fall back to Desktop
-      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");
-    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.
-  },
-
-  /**
-   * Initializes the download folder display settings based on the user's
-   * preferences.
-   */
-  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 bundlePreferences = document.getElementById("bundlePreferences");
-    var downloadFolder = document.getElementById("downloadFolder");
-    var currentDirPref = document.getElementById("browser.download.dir");
-
-    // Used in defining the correct path to the folder icon.
-    var ios = Components.classes["@mozilla.org/network/io-service;1"]
-                        .getService(Components.interfaces.nsIIOService);
-    var fph = ios.getProtocolHandler("file")
-                 .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
-    var iconUrlSpec;
-
-    // Display a 'pretty' label or the path in the UI.
-    if (folderListPref.value == 2) {
-      // Custom path selected and is configured
-      downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value);
-      iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
-    } else if (folderListPref.value == 1) {
-      // 'Downloads'
-      downloadFolder.label = bundlePreferences.getString("downloadsFolderName");
-      iconUrlSpec = fph.getURLSpecFromFile(await this._indexToFolder(1));
-    } else {
-      // 'Desktop'
-      downloadFolder.label = bundlePreferences.getString("desktopFolderName");
-      iconUrlSpec = fph.getURLSpecFromFile(await this._getDownloadsFolder("Desktop"));
-    }
-    downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16";
-  },
-
-  /**
-   * Returns the textual path of a folder in readable form.
-   */
-  _getDisplayNameOfFile(aFolder) {
-    // TODO: would like to add support for 'Downloads on Macintosh HD'
-    //       for OS X users.
-    return aFolder ? aFolder.path : "";
-  },
-
-  /**
-   * Returns the Downloads folder.  If aFolder is "Desktop", then the Downloads
-   * folder returned is the desktop folder; otherwise, it is a folder whose name
-   * indicates that it is a download folder and whose path is as determined by
-   * the XPCOM directory service via the download manager's attribute
-   * defaultDownloadsDirectory.
-   *
-   * @throws if aFolder is not "Desktop" or "Downloads"
-   */
-  async _getDownloadsFolder(aFolder) {
-    switch (aFolder) {
-      case "Desktop":
-        var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
-                                    .getService(Components.interfaces.nsIProperties);
-        return fileLoc.get("Desk", Components.interfaces.nsILocalFile);
-      case "Downloads":
-        let downloadsDir = await Downloads.getSystemDownloadsDirectory();
-        return new FileUtils.File(downloadsDir);
-    }
-    throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-  },
-
-  /**
-   * Determines the type of the given folder.
-   *
-   * @param   aFolder
-   *          the folder whose type is to be determined
-   * @returns integer
-   *          0 if aFolder is the Desktop or is unspecified,
-   *          1 if aFolder is the Downloads folder,
-   *          2 otherwise
-   */
-  async _folderToIndex(aFolder) {
-    if (!aFolder || aFolder.equals(await this._getDownloadsFolder("Desktop")))
-      return 0;
-    else if (aFolder.equals(await this._getDownloadsFolder("Downloads")))
-      return 1;
-    return 2;
-  },
-
-  /**
-   * Converts an integer into the corresponding folder.
-   *
-   * @param   aIndex
-   *          an integer
-   * @returns the Desktop folder if aIndex == 0,
-   *          the Downloads folder if aIndex == 1,
-   *          the folder stored in browser.download.dir
-   */
-  async _indexToFolder(aIndex) {
-    switch (aIndex) {
-      case 0:
-        return await this._getDownloadsFolder("Desktop");
-      case 1:
-        return await this._getDownloadsFolder("Downloads");
-    }
-    var currentDirPref = document.getElementById("browser.download.dir");
-    return currentDirPref.value;
-  }
-
-};
deleted file mode 100644
--- a/browser/components/preferences/in-content-new/applications.xul
+++ /dev/null
@@ -1,131 +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/.
-
-<!-- Applications panel -->
-
-<script type="application/javascript"
-        src="chrome://browser/content/preferences/in-content-new/applications.js"/>
-
-<preferences id="feedsPreferences" hidden="true" data-category="paneApplications">
-  <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"/>
-</preferences>
-
-<keyset data-category="paneApplications">
-  <!-- Ctrl+f/k focus the search box in the Applications pane.
-       These <key>s have oncommand attributes because of bug 371900. -->
-  <key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
-  <key key="&focusSearch2.key;" modifiers="accel" id="focusSearch2" oncommand=";"/>
-</keyset>
-
-<hbox id="header-applications"
-      class="header"
-      hidden="true"
-      data-category="paneApplications">
-  <label class="header-name" flex="1">&paneFilesApplications.title;</label>
-</hbox>
-
-<vbox id="applicationsContent"
-      data-category="paneApplications"
-      hidden="true"
-      flex="1">
-
-  <!--Downloads-->
-  <groupbox id="downloadsGroup">
-    <caption><label>&downloads.label;</label></caption>
-
-    <radiogroup id="saveWhere"
-                preference="browser.download.useDownloadDir"
-                onsyncfrompreference="return gApplicationsPane.readUseDownloadDir();">
-      <hbox id="saveToRow">
-        <radio id="saveTo"
-              value="true"
-              label="&saveTo.label;"
-              accesskey="&saveTo.accesskey;"
-              aria-labelledby="saveTo downloadFolder"/>
-        <filefield id="downloadFolder"
-                  flex="1"
-                  preference="browser.download.folderList"
-                  preference-editable="true"
-                  aria-labelledby="saveTo"
-                  onsyncfrompreference="return gApplicationsPane.displayDownloadDirPref();"/>
-        <button id="chooseFolder"
-#ifdef XP_MACOSX
-                accesskey="&chooseFolderMac.accesskey;"
-                label="&chooseFolderMac.label;"
-#else
-                accesskey="&chooseFolderWin.accesskey;"
-                label="&chooseFolderWin.label;"
-#endif
-        />
-      </hbox>
-      <radio id="alwaysAsk"
-            value="false"
-            label="&alwaysAskWhere.label;"
-            accesskey="&alwaysAskWhere.accesskey;"/>
-    </radiogroup>
-  </groupbox>
-
-  <groupbox id="applicationsGroup">
-    <caption><label>&applications.label;</label></caption>
-    <description>&applications.description;</description>
-    <textbox id="filter" flex="1"
-             type="search"
-             placeholder="&filter2.emptytext;"
-             aria-controls="handlersView"/>
-
-    <richlistbox id="handlersView" orient="vertical" persist="lastSelectedType"
-                 preference="pref.downloads.disable_button.edit_actions"
-                 flex="1">
-      <listheader equalsize="always">
-          <treecol id="typeColumn" label="&typeColumn.label;" value="type"
-                   accesskey="&typeColumn.accesskey;" persist="sortDirection"
-                   flex="1" sortDirection="ascending"/>
-          <treecol id="actionColumn" label="&actionColumn2.label;" value="action"
-                   accesskey="&actionColumn2.accesskey;" persist="sortDirection"
-                   flex="1"/>
-      </listheader>
-    </richlistbox>
-  </groupbox>
-</vbox>
--- a/browser/components/preferences/in-content-new/containers.js
+++ b/browser/components/preferences/in-content-new/containers.js
@@ -13,17 +13,17 @@ const defaultContainerIcon = "fingerprin
 const defaultContainerColor = "blue";
 
 let gContainersPane = {
 
   init() {
     this._list = document.getElementById("containersView");
 
     document.getElementById("backContainersLink").addEventListener("click", function() {
-      gotoPref("privacy");
+      gotoPref("general");
     });
 
     this._rebuildView();
   },
 
   _rebuildView() {
     const containers = ContextualIdentityService.getPublicIdentities();
     while (this._list.firstChild) {
--- a/browser/components/preferences/in-content-new/containers.xul
+++ b/browser/components/preferences/in-content-new/containers.xul
@@ -13,17 +13,17 @@
               name="privacy.userContext.enabled"
               type="bool"/>
 
 </preferences>
 
 <hbox hidden="true"
       class="container-header-links"
       data-category="paneContainers">
-  <label class="text-link" id="backContainersLink">&backLink.label;</label>
+  <label class="text-link" id="backContainersLink">&backLink2.label;</label>
 </hbox>
 
 <hbox id="header-containers"
       class="header"
       hidden="true"
       data-category="paneContainers">
   <label class="header-name" flex="1">&paneContainers.title;</label>
 </hbox>
--- a/browser/components/preferences/in-content-new/findInPage.js
+++ b/browser/components/preferences/in-content-new/findInPage.js
@@ -34,16 +34,20 @@ var gSearchResultsPane = {
             this.listSearchTooltips.forEach((anchorNode) => {
               this.calculateTooltipPosition(anchorNode);
             });
             callbackId = null;
           });
         }
       });
     }
+    let strings = this.strings;
+    this.searchInput.placeholder = AppConstants.platform == "win" ?
+      strings.getString("searchInput.labelWin") :
+      strings.getString("searchInput.labelUnix");
   },
 
   handleEvent(event) {
     if (event.type === "command") {
       this.searchFunction(event);
     }
   },
 
--- a/browser/components/preferences/in-content-new/jar.mn
+++ b/browser/components/preferences/in-content-new/jar.mn
@@ -3,14 +3,13 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 browser.jar:
    content/browser/preferences/in-content-new/preferences.js
 *  content/browser/preferences/in-content-new/preferences.xul
    content/browser/preferences/in-content-new/subdialogs.js
 
    content/browser/preferences/in-content-new/main.js
+   content/browser/preferences/in-content-new/search.js
    content/browser/preferences/in-content-new/privacy.js
    content/browser/preferences/in-content-new/containers.js
-   content/browser/preferences/in-content-new/advanced.js
-   content/browser/preferences/in-content-new/applications.js
    content/browser/preferences/in-content-new/sync.js
    content/browser/preferences/in-content-new/findInPage.js
--- a/browser/components/preferences/in-content-new/main.js
+++ b/browser/components/preferences/in-content-new/main.js
@@ -1,49 +1,148 @@
 /* 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 preferences.js */
 /* import-globals-from ../../../../toolkit/mozapps/preferences/fontbuilder.js */
+/* import-globals-from ../../../base/content/aboutDialog-appUpdater.js */
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Downloads.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
 Components.utils.import("resource:///modules/ShellService.jsm");
 Components.utils.import("resource:///modules/TransientPrefs.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/AppConstants.jsm");
+
+// Constants & Enumeration Values
+const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
+const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
+const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
+const TYPE_PDF = "application/pdf";
+
+const PREF_PDFJS_DISABLED = "pdfjs.disabled";
+const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
+
+const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
+
+// Preferences that affect which entries to show in the list.
+const PREF_SHOW_PLUGINS_IN_LIST = "browser.download.show_plugins_in_list";
+const PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS =
+  "browser.download.hide_plugins_without_extensions";
+
+/*
+ * Preferences where we store handling information about the feed type.
+ *
+ * browser.feeds.handler
+ * - "bookmarks", "reader" (clarified further using the .default preference),
+ *   or "ask" -- indicates the default handler being used to process feeds;
+ *   "bookmarks" is obsolete; to specify that the handler is bookmarks,
+ *   set browser.feeds.handler.default to "bookmarks";
+ *
+ * browser.feeds.handler.default
+ * - "bookmarks", "client" or "web" -- indicates the chosen feed reader used
+ *   to display feeds, either transiently (i.e., when the "use as default"
+ *   checkbox is unchecked, corresponds to when browser.feeds.handler=="ask")
+ *   or more permanently (i.e., the item displayed in the dropdown in Feeds
+ *   preferences)
+ *
+ * browser.feeds.handler.webservice
+ * - the URL of the currently selected web service used to read feeds
+ *
+ * browser.feeds.handlers.application
+ * - nsILocalFile, stores the current client-side feed reading app if one has
+ *   been chosen
+ */
+const PREF_FEED_SELECTED_APP    = "browser.feeds.handlers.application";
+const PREF_FEED_SELECTED_WEB    = "browser.feeds.handlers.webservice";
+const PREF_FEED_SELECTED_ACTION = "browser.feeds.handler";
+const PREF_FEED_SELECTED_READER = "browser.feeds.handler.default";
+
+const PREF_VIDEO_FEED_SELECTED_APP    = "browser.videoFeeds.handlers.application";
+const PREF_VIDEO_FEED_SELECTED_WEB    = "browser.videoFeeds.handlers.webservice";
+const PREF_VIDEO_FEED_SELECTED_ACTION = "browser.videoFeeds.handler";
+const PREF_VIDEO_FEED_SELECTED_READER = "browser.videoFeeds.handler.default";
+
+const PREF_AUDIO_FEED_SELECTED_APP    = "browser.audioFeeds.handlers.application";
+const PREF_AUDIO_FEED_SELECTED_WEB    = "browser.audioFeeds.handlers.webservice";
+const PREF_AUDIO_FEED_SELECTED_ACTION = "browser.audioFeeds.handler";
+const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
+
+// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify
+// the actions the application can take with content of various types.
+// But since nsIHandlerInfo doesn't support plugins, there's no value
+// identifying the "use plugin" action, so we use this constant instead.
+const kActionUsePlugin = 5;
+
+const ICON_URL_APP = AppConstants.platform == "linux" ?
+                     "moz-icon://dummy.exe?size=16" :
+                     "chrome://browser/skin/preferences/application.png";
+
+// For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
+// was set by us to a custom handler icon and CSS should not try to override it.
+const APP_ICON_ATTR_NAME = "appHandlerIcon";
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 
 if (AppConstants.E10S_TESTING_ONLY) {
   XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
                                     "resource://gre/modules/UpdateUtils.jsm");
 }
 
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
-                                  "resource://gre/modules/PlacesUtils.jsm");
-
 if (AppConstants.MOZ_DEV_EDITION) {
   XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
                                     "resource://gre/modules/FxAccounts.jsm");
 }
 
-const ENGINE_FLAVOR = "text/x-moz-search-engine";
-
-var gEngineView = null;
-
 var gMainPane = {
-  /**
-   * Initialize autocomplete to ensure prefs are in sync.
-   */
-  _initAutocomplete() {
-    Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
-              .getService(Components.interfaces.mozIPlacesAutoComplete);
-  },
+  // The set of types the app knows how to handle.  A hash of HandlerInfoWrapper
+  // objects, indexed by type.
+  _handledTypes: {},
+
+  // The list of types we can show, sorted by the sort column/direction.
+  // An array of HandlerInfoWrapper objects.  We build this list when we first
+  // load the data and then rebuild it when users change a pref that affects
+  // what types we can show or change the sort column/direction.
+  // Note: this isn't necessarily the list of types we *will* show; if the user
+  // provides a filter string, we'll only show the subset of types in this list
+  // that match that string.
+  _visibleTypes: [],
+
+  // A count of the number of times each visible type description appears.
+  // We use these counts to determine whether or not to annotate descriptions
+  // with their types to distinguish duplicate descriptions from each other.
+  // A hash of integer counts, indexed by string description.
+  _visibleTypeDescriptionCount: {},
+
+
+  // Convenience & Performance Shortcuts
+
+  // These get defined by init().
+  _brandShortName: null,
+  _prefsBundle: null,
+  _list: null,
+  _filter: null,
+
+  _prefSvc: Cc["@mozilla.org/preferences-service;1"].
+            getService(Ci.nsIPrefBranch),
+
+  _mimeSvc: Cc["@mozilla.org/mime;1"].
+            getService(Ci.nsIMIMEService),
+
+  _helperAppSvc: Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
+                 getService(Ci.nsIExternalHelperAppService),
+
+  _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
+               getService(Ci.nsIHandlerService),
+
+  _ioSvc: Cc["@mozilla.org/network/io-service;1"].
+          getService(Ci.nsIIOService),
 
   /**
    * Initialization of this.
    */
   init() {
     function setEventListener(aId, aEventType, aCallback) {
       document.getElementById(aId)
               .addEventListener(aEventType, aCallback.bind(gMainPane));
@@ -74,52 +173,23 @@ var gMainPane = {
         };
 
         window.setTimeout(() => {
           window.requestIdleCallback(pollForDefaultBrowser);
         }, 1000);
       }
     }
 
-    gEngineView = new EngineView(new EngineStore());
-    document.getElementById("engineList").view = gEngineView;
-    this.buildDefaultEngineDropDown();
-
+    this.initBrowserContainers();
     this.buildContentProcessCountMenuList();
 
-    let addEnginesLink = document.getElementById("addEngines");
-    let searchEnginesURL = Services.wm.getMostRecentWindow("navigator:browser")
-                                      .BrowserSearch.searchEnginesURL;
-    addEnginesLink.setAttribute("href", searchEnginesURL);
-
     let performanceSettingsLink = document.getElementById("performanceSettingsLearnMore");
     let performanceSettingsUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "performance";
     performanceSettingsLink.setAttribute("href", performanceSettingsUrl);
 
-    window.addEventListener("click", this);
-    window.addEventListener("command", this);
-    window.addEventListener("dragstart", this);
-    window.addEventListener("keypress", this);
-    window.addEventListener("select", this);
-    window.addEventListener("blur", this, true);
-
-    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();
-    });
-    this.updateSuggestsCheckbox();
-
     this.updateDefaultPerformanceSettingsPref();
 
     let defaultPerformancePref =
       document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
     defaultPerformancePref.addEventListener("change", () => {
       this.updatePerformanceSettingsBox();
     });
     this.updatePerformanceSettingsBox();
@@ -171,16 +241,22 @@ var gMainPane = {
     setEventListener("font.language.group", "change",
       gMainPane._rebuildFonts);
     setEventListener("advancedFonts", "command",
       gMainPane.configureFonts);
     setEventListener("colors", "command",
       gMainPane.configureColors);
     setEventListener("layers.acceleration.disabled", "change",
       gMainPane.updateHardwareAcceleration);
+    setEventListener("connectionSettings", "command",
+      gMainPane.showConnections);
+    setEventListener("browserContainersCheckbox", "command",
+      gMainPane.checkBrowserContainers);
+    setEventListener("browserContainersSettings", "command",
+      gMainPane.showContainerSettings);
 
     // Initializes the fonts dropdowns displayed in this pane.
     this._rebuildFonts();
 
     this.updateOnScreenKeyboardVisibility();
 
     // Show translation preferences if we may:
     const prefName = "browser.translation.ui.show";
@@ -226,22 +302,183 @@ var gMainPane = {
                                                () => separateProfileModeCheckbox.checked = true);
 
       fxAccounts.getSignedInUser().then(data => {
         document.getElementById("getStarted").selectedIndex = data ? 1 : 0;
       })
       .catch(Cu.reportError);
     }
 
+    // Initialize the Firefox Updates section.
+    let version = AppConstants.MOZ_APP_VERSION_DISPLAY;
+
+    // Include the build ID if this is an "a#" (nightly) build
+    if (/a\d+$/.test(version)) {
+      let buildID = Services.appinfo.appBuildID;
+      let year = buildID.slice(0, 4);
+      let month = buildID.slice(4, 6);
+      let day = buildID.slice(6, 8);
+      version += ` (${year}-${month}-${day})`;
+    }
+
+    // Append "(32-bit)" or "(64-bit)" build architecture to the version number:
+    let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+    let archResource = Services.appinfo.is64Bit
+                       ? "aboutDialog.architecture.sixtyFourBit"
+                       : "aboutDialog.architecture.thirtyTwoBit";
+    let arch = bundle.GetStringFromName(archResource);
+    version += ` (${arch})`;
+
+    document.getElementById("version").textContent = version;
+
+    // Show a release notes link if we have a URL.
+    let relNotesLink = document.getElementById("releasenotes");
+    let relNotesPrefType = Services.prefs.getPrefType("app.releaseNotesURL");
+    if (relNotesPrefType != Services.prefs.PREF_INVALID) {
+      let relNotesURL = Services.urlFormatter.formatURLPref("app.releaseNotesURL");
+      if (relNotesURL != "about:blank") {
+        relNotesLink.href = relNotesURL;
+        relNotesLink.hidden = false;
+      }
+    }
+
+    let distroId = Services.prefs.getCharPref("distribution.id", "");
+    if (distroId) {
+      let distroVersion = Services.prefs.getCharPref("distribution.version");
+
+      let distroIdField = document.getElementById("distributionId");
+      distroIdField.value = distroId + " - " + distroVersion;
+      distroIdField.hidden = false;
+
+      let distroAbout = Services.prefs.getStringPref("distribution.about", "");
+      if (distroAbout) {
+        let distroField = document.getElementById("distribution");
+        distroField.value = distroAbout;
+        distroField.hidden = false;
+      }
+    }
+
+    if (AppConstants.MOZ_UPDATER) {
+      gAppUpdater = new appUpdater();
+      let onUnload = () => {
+        window.removeEventListener("unload", onUnload);
+        Services.prefs.removeObserver("app.update.", this);
+      };
+      window.addEventListener("unload", onUnload);
+      Services.prefs.addObserver("app.update.", this);
+      this.updateReadPrefs();
+      setEventListener("updateRadioGroup", "command",
+                       gMainPane.updateWritePrefs);
+      setEventListener("showUpdateHistory", "command",
+                       gMainPane.showUpdates);
+    }
+
+    // Initilize Application section.
+    // Initialize shortcuts to some commonly accessed elements & values.
+    this._brandShortName =
+      document.getElementById("bundleBrand").getString("brandShortName");
+    this._prefsBundle = document.getElementById("bundlePreferences");
+    this._list = document.getElementById("handlersView");
+    this._filter = document.getElementById("filter");
+
+    // Observe preferences that influence what we display so we can rebuild
+    // the view when they change.
+    this._prefSvc.addObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
+    this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_FEED_SELECTED_READER, this);
+
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
+
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.addObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
+
+    setEventListener("focusSearch1", "command", gMainPane.focusFilterBox);
+    setEventListener("focusSearch2", "command", gMainPane.focusFilterBox);
+    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);
+
+    // 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")) {
+      this._sortColumn = document.getElementById("actionColumn");
+      // The typeColumn element always has a sortDirection attribute,
+      // either because it was persisted or because the default value
+      // from the xul file was used.  If we are sorting on the other
+      // column, we should remove it.
+      document.getElementById("typeColumn").removeAttribute("sortDirection");
+    } else
+      this._sortColumn = document.getElementById("typeColumn");
+
+    // Load the data and build the list of handlers.
+    // By doing this in a timeout, we let the preferences dialog resize itself
+    // to an appropriate size before we add a bunch of items to the list.
+    // Otherwise, if there are many items, and the Applications prefpane
+    // is the one that gets displayed when the user first opens the dialog,
+    // the dialog might stretch too much in an attempt to fit them all in.
+    // XXX Shouldn't we perhaps just set a max-height on the richlistbox?
+    var _delayedPaneLoad = function(self) {
+      self._loadData();
+      self._rebuildVisibleTypes();
+      self._sortVisibleTypes();
+      self._rebuildView();
+    }
+    setTimeout(_delayedPaneLoad, 0, this);
+
+    let browserBundle = document.getElementById("browserBundle");
+    appendSearchKeywords("browserContainersSettings", [
+      browserBundle.getString("userContextPersonal.label"),
+      browserBundle.getString("userContextWork.label"),
+      browserBundle.getString("userContextBanking.label"),
+      browserBundle.getString("userContextShopping.label"),
+    ]);
+
     // Notify observers that the UI is now ready
     Components.classes["@mozilla.org/observer-service;1"]
               .getService(Components.interfaces.nsIObserverService)
               .notifyObservers(window, "main-pane-loaded");
   },
 
+  /**
+   * Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
+   */
+  initBrowserContainers() {
+    if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
+      // The browserContainersGroup element has its own internal padding that
+      // is visible even if the browserContainersbox is visible, so hide the whole
+      // groupbox if the feature is disabled to prevent a gap in the preferences.
+      document.getElementById("browserContainersbox").setAttribute("data-hidden-from-search", "true");
+      return;
+    }
+
+    let link = document.getElementById("browserContainersLearnMore");
+    link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
+
+    document.getElementById("browserContainersbox").hidden = false;
+
+    document.getElementById("browserContainersCheckbox").checked =
+      Services.prefs.getBoolPref("privacy.userContext.enabled");
+  },
+
   isE10SEnabled() {
     let e10sEnabled;
     try {
       let e10sStatus = Components.classes["@mozilla.org/supports-PRUint64;1"]
                          .createInstance(Ci.nsISupportsPRUint64);
       let appinfo = Services.appinfo.QueryInterface(Ci.nsIObserver);
       appinfo.observe(e10sStatus, "getE10SBlocked", "");
       e10sEnabled = e10sStatus.data < 2;
@@ -667,16 +904,67 @@ var gMainPane = {
   /**
    * Displays the colors dialog, where default web page/link/etc. colors can be
    * configured.
    */
   configureColors() {
     gSubDialog.open("chrome://browser/content/preferences/colors.xul", "resizable=no");
   },
 
+  // NETWORK
+  /**
+   * Displays a dialog in which proxy settings may be changed.
+   */
+  showConnections() {
+    gSubDialog.open("chrome://browser/content/preferences/connection.xul");
+  },
+
+  checkBrowserContainers(event) {
+    let checkbox = document.getElementById("browserContainersCheckbox");
+    if (checkbox.checked) {
+      Services.prefs.setBoolPref("privacy.userContext.enabled", true);
+      return;
+    }
+
+    let count = ContextualIdentityService.countContainerTabs();
+    if (count == 0) {
+      Services.prefs.setBoolPref("privacy.userContext.enabled", false);
+      return;
+    }
+
+    let bundlePreferences = document.getElementById("bundlePreferences");
+
+    let title = bundlePreferences.getString("disableContainersAlertTitle");
+    let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
+                            .replace("#S", count)
+    let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
+                             .replace("#S", count)
+    let cancelButton = bundlePreferences.getString("disableContainersButton2");
+
+    let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
+                      (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
+
+    let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
+                                       okButton, cancelButton, null, null, {});
+    if (rv == 0) {
+      ContextualIdentityService.closeContainerTabs();
+      Services.prefs.setBoolPref("privacy.userContext.enabled", false);
+      return;
+    }
+
+    checkbox.checked = true;
+  },
+
+  /**
+   * Displays container panel for customising and adding containers.
+   */
+  showContainerSettings() {
+    gotoPref("containers");
+  },
+
   /**
    * ui.osk.enabled
    * - when set to true, subject to other conditions, we may sometimes invoke
    *   an on-screen keyboard when a text input is focused.
    *   (Currently Windows-only, and depending on prefs, may be Windows-8-only)
    */
   updateOnScreenKeyboardVisibility() {
     if (AppConstants.platform == "win") {
@@ -807,36 +1095,16 @@ var gMainPane = {
       if (this._storedSpellCheck == 2) {
         return 2;
       }
       return 1;
     }
     return 0;
   },
 
-  updateSuggestsCheckbox() {
-    let suggestsPref =
-      document.getElementById("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");
-    urlbarSuggests.checked = urlbarSuggestsPref.value;
-    if (urlbarSuggests.disabled) {
-      urlbarSuggests.checked = false;
-    }
-
-    let permanentPBLabel =
-      document.getElementById("urlBarSuggestionPermanentPBLabel");
-    permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
-  },
-
   updateDefaultPerformanceSettingsPref() {
     let defaultPerformancePref =
       document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
     let processCountPref = document.getElementById("dom.ipc.processCount");
     let accelerationPref = document.getElementById("layers.acceleration.disabled");
     if (processCountPref.value != processCountPref.defaultValue ||
         accelerationPref.value != accelerationPref.defaultValue) {
       defaultPerformancePref.value = false;
@@ -876,536 +1144,2009 @@ var gMainPane = {
     } else {
       document.getElementById("limitContentProcess").disabled = true;
       document.getElementById("contentProcessCount").disabled = true;
       document.getElementById("contentProcessCountEnabledDescription").hidden = true;
       document.getElementById("contentProcessCountDisabledDescription").hidden = false;
     }
   },
 
-  buildDefaultEngineDropDown() {
-    // This is called each time something affects the list of engines.
-    let list = document.getElementById("defaultEngine");
-    // Set selection to the current default engine.
-    let currentEngine = Services.search.currentEngine.name;
-
-    // If the current engine isn't in the list any more, select the first item.
-    let engines = gEngineView._engineStore._engines;
-    if (!engines.some(e => e.name == currentEngine))
-      currentEngine = engines[0].name;
-
-    // Now clean-up and rebuild the list.
-    list.removeAllItems();
-    gEngineView._engineStore._engines.forEach(e => {
-      let item = list.appendItem(e.name);
-      item.setAttribute("class", "menuitem-iconic searchengine-menuitem menuitem-with-favicon");
-      if (e.iconURI) {
-        item.setAttribute("image", e.iconURI.spec);
+  /*
+   * Preferences:
+   *
+   * app.update.enabled
+   * - true if updates to the application are enabled, false otherwise
+   * app.update.auto
+   * - true if updates should be automatically downloaded and installed and
+   * false if the user should be asked what he wants to do when an update is
+   * available
+   * extensions.update.enabled
+   * - true if updates to extensions and themes are enabled, false otherwise
+   * browser.search.update
+   * - true if updates to search engines are enabled, false otherwise
+   */
+
+  /**
+   * Selects the item of the radiogroup based on the pref values and locked
+   * states.
+   *
+   * UI state matrix for update preference conditions
+   *
+   * UI Components:                              Preferences
+   * Radiogroup                                  i   = app.update.enabled
+   *                                             ii  = app.update.auto
+   *
+   * Disabled states:
+   * 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 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
+
+      var canCheck = Components.classes["@mozilla.org/updates/update-service;1"].
+                       getService(Components.interfaces.nsIApplicationUpdateService).
+                       canCheckForUpdates;
+      // canCheck is false if the enabledPref is false and locked,
+      // or the binary platform or OS version is not known.
+      // A locked pref is sufficient to disable the radiogroup.
+      radiogroup.disabled = !canCheck || enabledPref.locked || autoPref.locked;
+
+      if (AppConstants.MOZ_MAINTENANCE_SERVICE) {
+        // Check to see if the maintenance service is installed.
+        // If it is don't show the preference at all.
+        var installed;
+        try {
+          var wrk = Components.classes["@mozilla.org/windows-registry-key;1"]
+                    .createInstance(Components.interfaces.nsIWindowsRegKey);
+          wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
+                   "SOFTWARE\\Mozilla\\MaintenanceService",
+                   wrk.ACCESS_READ | wrk.WOW64_64);
+          installed = wrk.readIntValue("Installed");
+          wrk.close();
+        } catch (e) {
+        }
+        if (installed != 1) {
+          document.getElementById("useService").hidden = true;
+        }
       }
-      item.engine = e;
-      if (e.name == currentEngine)
-        list.selectedItem = item;
-    });
+    }
+  },
+
+  /**
+   * 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 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;
+          autoPref.value = false;
+          break;
+        case "manual":    // 3. Never check for updates.
+          enabledPref.value = false;
+          autoPref.value = false;
+      }
+    }
+  },
+
+  /**
+   * Displays the history of installed updates.
+   */
+  showUpdates() {
+    gSubDialog.open("chrome://mozapps/content/update/history.xul");
   },
 
+  destroy() {
+    window.removeEventListener("unload", this);
+    this._prefSvc.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
+    this._prefSvc.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
+    this._prefSvc.removeObserver(PREF_FEED_SELECTED_APP, this);
+    this._prefSvc.removeObserver(PREF_FEED_SELECTED_WEB, this);
+    this._prefSvc.removeObserver(PREF_FEED_SELECTED_ACTION, this);
+    this._prefSvc.removeObserver(PREF_FEED_SELECTED_READER, this);
+
+    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_APP, this);
+    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_WEB, this);
+    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.removeObserver(PREF_VIDEO_FEED_SELECTED_READER, this);
+
+    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_APP, this);
+    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_WEB, this);
+    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this);
+    this._prefSvc.removeObserver(PREF_AUDIO_FEED_SELECTED_READER, this);
+  },
+
+
+  // nsISupports
+
+  QueryInterface(aIID) {
+    if (aIID.equals(Ci.nsIObserver) ||
+        aIID.equals(Ci.nsIDOMEventListener ||
+        aIID.equals(Ci.nsISupports)))
+      return this;
+
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+
+  // nsIObserver
+
+  observe(aSubject, aTopic, aData) {
+    if (aTopic == "nsPref:changed") {
+      // Rebuild the list when there are changes to preferences that influence
+      // whether or not to show certain entries in the list.
+      if (!this._storingAction) {
+        // These two prefs alter the list of visible types, so we have to rebuild
+        // that list when they change.
+        if (aData == PREF_SHOW_PLUGINS_IN_LIST ||
+            aData == PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS) {
+          this._rebuildVisibleTypes();
+          this._sortVisibleTypes();
+        }
+
+        // All the prefs we observe can affect what we display, so we rebuild
+        // the view when any of them changes.
+        this._rebuildView();
+      }
+      if (AppConstants.MOZ_UPDATER) {
+        this.updateReadPrefs();
+      }
+    }
+  },
+
+
+  // nsIDOMEventListener
+
   handleEvent(aEvent) {
-    switch (aEvent.type) {
-      case "click":
-        if (aEvent.target.id != "engineChildren" &&
-            !aEvent.target.classList.contains("searchEngineAction")) {
-          let engineList = document.getElementById("engineList");
-          // We don't want to toggle off selection while editing keyword
-          // so proceed only when the input field is hidden.
-          // We need to check that engineList.view is defined here
-          // because the "click" event listener is on <window> and the
-          // view might have been destroyed if the pane has been navigated
-          // away from.
-          if (engineList.inputField.hidden && engineList.view) {
-            let selection = engineList.view.selection;
-            if (selection.count > 0) {
-              selection.toggleSelect(selection.currentIndex);
-            }
-            engineList.blur();
-          }
+    if (aEvent.type == "unload") {
+      this.destroy();
+    }
+  },
+
+
+  // Composed Model Construction
+
+  _loadData() {
+    this._loadFeedHandler();
+    this._loadInternalHandlers();
+    this._loadPluginHandlers();
+    this._loadApplicationHandlers();
+  },
+
+  _loadFeedHandler() {
+    this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo;
+    feedHandlerInfo.handledOnlyByPlugin = false;
+
+    this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo;
+    videoFeedHandlerInfo.handledOnlyByPlugin = false;
+
+    this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo;
+    audioFeedHandlerInfo.handledOnlyByPlugin = false;
+  },
+
+  /**
+   * Load higher level internal handlers so they can be turned on/off in the
+   * applications menu.
+   */
+  _loadInternalHandlers() {
+    var internalHandlers = [pdfHandlerInfo];
+    for (let internalHandler of internalHandlers) {
+      if (internalHandler.enabled) {
+        this._handledTypes[internalHandler.type] = internalHandler;
+      }
+    }
+  },
+
+  /**
+   * Load the set of handlers defined by plugins.
+   *
+   * Note: if there's more than one plugin for a given MIME type, we assume
+   * the last one is the one that the application will use.  That may not be
+   * correct, but it's how we've been doing it for years.
+   *
+   * Perhaps we should instead query navigator.mimeTypes for the set of types
+   * supported by the application and then get the plugin from each MIME type's
+   * enabledPlugin property.  But if there's a plugin for a type, we need
+   * to know about it even if it isn't enabled, since we're going to give
+   * the user an option to enable it.
+   *
+   * Also note that enabledPlugin does not get updated when
+   * plugin.disable_full_page_plugin_for_types changes, so even if we could use
+   * enabledPlugin to get the plugin that would be used, we'd still need to
+   * check the pref ourselves to find out if it's enabled.
+   */
+  _loadPluginHandlers() {
+    "use strict";
+
+    let mimeTypes = navigator.mimeTypes;
+
+    for (let mimeType of mimeTypes) {
+      let handlerInfoWrapper;
+      if (mimeType.type in this._handledTypes) {
+        handlerInfoWrapper = this._handledTypes[mimeType.type];
+      } else {
+        let wrappedHandlerInfo =
+              this._mimeSvc.getFromTypeAndExtension(mimeType.type, null);
+        handlerInfoWrapper = new HandlerInfoWrapper(mimeType.type, wrappedHandlerInfo);
+        handlerInfoWrapper.handledOnlyByPlugin = true;
+        this._handledTypes[mimeType.type] = handlerInfoWrapper;
+      }
+      handlerInfoWrapper.pluginName = mimeType.enabledPlugin.name;
+    }
+  },
+
+  /**
+   * Load the set of handlers defined by the application datastore.
+   */
+  _loadApplicationHandlers() {
+    var wrappedHandlerInfos = this._handlerSvc.enumerate();
+    while (wrappedHandlerInfos.hasMoreElements()) {
+      let wrappedHandlerInfo =
+        wrappedHandlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo);
+      let type = wrappedHandlerInfo.type;
+
+      let handlerInfoWrapper;
+      if (type in this._handledTypes)
+        handlerInfoWrapper = this._handledTypes[type];
+      else {
+        handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo);
+        this._handledTypes[type] = handlerInfoWrapper;
+      }
+
+      handlerInfoWrapper.handledOnlyByPlugin = false;
+    }
+  },
+
+
+  // View Construction
+
+  _rebuildVisibleTypes() {
+    // Reset the list of visible types and the visible type description counts.
+    this._visibleTypes = [];
+    this._visibleTypeDescriptionCount = {};
+
+    // Get the preferences that help determine what types to show.
+    var showPlugins = this._prefSvc.getBoolPref(PREF_SHOW_PLUGINS_IN_LIST);
+    var hidePluginsWithoutExtensions =
+      this._prefSvc.getBoolPref(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS);
+
+    for (let type in this._handledTypes) {
+      let handlerInfo = this._handledTypes[type];
+
+      // Hide plugins without associated extensions if so prefed so we don't
+      // show a whole bunch of obscure types handled by plugins on Mac.
+      // Note: though protocol types don't have extensions, we still show them;
+      // the pref is only meant to be applied to MIME types, since plugins are
+      // only associated with MIME types.
+      // FIXME: should we also check the "suffixes" property of the plugin?
+      // Filed as bug 395135.
+      if (hidePluginsWithoutExtensions && handlerInfo.handledOnlyByPlugin &&
+          handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
+          !handlerInfo.primaryExtension)
+        continue;
+
+      // Hide types handled only by plugins if so prefed.
+      if (handlerInfo.handledOnlyByPlugin && !showPlugins)
+        continue;
+
+      // We couldn't find any reason to exclude the type, so include it.
+      this._visibleTypes.push(handlerInfo);
+
+      if (handlerInfo.description in this._visibleTypeDescriptionCount)
+        this._visibleTypeDescriptionCount[handlerInfo.description]++;
+      else
+        this._visibleTypeDescriptionCount[handlerInfo.description] = 1;
+    }
+  },
+
+  _rebuildView() {
+    // Clear the list of entries.
+    while (this._list.childNodes.length > 1)
+      this._list.removeChild(this._list.lastChild);
+
+    var visibleTypes = this._visibleTypes;
+
+    // If the user is filtering the list, then only show matching types.
+    if (this._filter.value)
+      visibleTypes = visibleTypes.filter(this._matchesFilter, this);
+
+    for (let visibleType of visibleTypes) {
+      let item = document.createElement("richlistitem");
+      item.setAttribute("type", visibleType.type);
+      item.setAttribute("typeDescription", this._describeType(visibleType));
+      if (visibleType.smallIcon)
+        item.setAttribute("typeIcon", visibleType.smallIcon);
+      item.setAttribute("actionDescription",
+                        this._describePreferredAction(visibleType));
+
+      if (!this._setIconClassForPreferredAction(visibleType, item)) {
+        item.setAttribute("actionIcon",
+                          this._getIconURLForPreferredAction(visibleType));
+      }
+
+      this._list.appendChild(item);
+    }
+
+    this._selectLastSelectedType();
+  },
+
+  _matchesFilter(aType) {
+    var filterValue = this._filter.value.toLowerCase();
+    return this._describeType(aType).toLowerCase().indexOf(filterValue) != -1 ||
+           this._describePreferredAction(aType).toLowerCase().indexOf(filterValue) != -1;
+  },
+
+  /**
+   * Describe, in a human-readable fashion, the type represented by the given
+   * handler info object.  Normally this is just the description provided by
+   * the info object, but if more than one object presents the same description,
+   * then we annotate the duplicate descriptions with the type itself to help
+   * users distinguish between those types.
+   *
+   * @param aHandlerInfo {nsIHandlerInfo} the type being described
+   * @returns {string} a description of the type
+   */
+  _describeType(aHandlerInfo) {
+    if (this._visibleTypeDescriptionCount[aHandlerInfo.description] > 1)
+      return this._prefsBundle.getFormattedString("typeDescriptionWithType",
+                                                  [aHandlerInfo.description,
+                                                   aHandlerInfo.type]);
+
+    return aHandlerInfo.description;
+  },
+
+  /**
+   * Describe, in a human-readable fashion, the preferred action to take on
+   * the type represented by the given handler info object.
+   *
+   * XXX Should this be part of the HandlerInfoWrapper interface?  It would
+   * violate the separation of model and view, but it might make more sense
+   * nonetheless (f.e. it would make sortTypes easier).
+   *
+   * @param aHandlerInfo {nsIHandlerInfo} the type whose preferred action
+   *                                      is being described
+   * @returns {string} a description of the action
+   */
+  _describePreferredAction(aHandlerInfo) {
+    // alwaysAskBeforeHandling overrides the preferred action, so if that flag
+    // is set, then describe that behavior instead.  For most types, this is
+    // the "alwaysAsk" string, but for the feed type we show something special.
+    if (aHandlerInfo.alwaysAskBeforeHandling) {
+      if (isFeedType(aHandlerInfo.type))
+        return this._prefsBundle.getFormattedString("previewInApp",
+                                                    [this._brandShortName]);
+      return this._prefsBundle.getString("alwaysAsk");
+    }
+
+    switch (aHandlerInfo.preferredAction) {
+      case Ci.nsIHandlerInfo.saveToDisk:
+        return this._prefsBundle.getString("saveFile");
+
+      case Ci.nsIHandlerInfo.useHelperApp:
+        var preferredApp = aHandlerInfo.preferredApplicationHandler;
+        var name;
+        if (preferredApp instanceof Ci.nsILocalHandlerApp)
+          name = getFileDisplayName(preferredApp.executable);
+        else
+          name = preferredApp.name;
+        return this._prefsBundle.getFormattedString("useApp", [name]);
+
+      case Ci.nsIHandlerInfo.handleInternally:
+        // For the feed type, handleInternally means live bookmarks.
+        if (isFeedType(aHandlerInfo.type)) {
+          return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
+                                                      [this._brandShortName]);
+        }
+
+        if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          return this._prefsBundle.getFormattedString("previewInApp",
+                                                      [this._brandShortName]);
+        }
+
+        // For other types, handleInternally looks like either useHelperApp
+        // or useSystemDefault depending on whether or not there's a preferred
+        // handler app.
+        if (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler))
+          return aHandlerInfo.preferredApplicationHandler.name;
+
+        return aHandlerInfo.defaultDescription;
+
+        // XXX Why don't we say the app will handle the type internally?
+        // Is it because the app can't actually do that?  But if that's true,
+        // then why would a preferredAction ever get set to this value
+        // in the first place?
+
+      case Ci.nsIHandlerInfo.useSystemDefault:
+        return this._prefsBundle.getFormattedString("useDefault",
+                                                    [aHandlerInfo.defaultDescription]);
+
+      case kActionUsePlugin:
+        return this._prefsBundle.getFormattedString("usePluginIn",
+                                                    [aHandlerInfo.pluginName,
+                                                     this._brandShortName]);
+      default:
+        throw new Error(`Unexpected preferredAction: ${aHandlerInfo.preferredAction}`);
+    }
+  },
+
+  _selectLastSelectedType() {
+    // If the list is disabled by the pref.downloads.disable_button.edit_actions
+    // preference being locked, then don't select the type, as that would cause
+    // it to appear selected, with a different background and an actions menu
+    // that makes it seem like you can choose an action for the type.
+    if (this._list.disabled)
+      return;
+
+    var lastSelectedType = this._list.getAttribute("lastSelectedType");
+    if (!lastSelectedType)
+      return;
+
+    var item = this._list.getElementsByAttribute("type", lastSelectedType)[0];
+    if (!item)
+      return;
+
+    this._list.selectedItem = item;
+  },
+
+  /**
+   * Whether or not the given handler app is valid.
+   *
+   * @param aHandlerApp {nsIHandlerApp} the handler app in question
+   *
+   * @returns {boolean} whether or not it's valid
+   */
+  isValidHandlerApp(aHandlerApp) {
+    if (!aHandlerApp)
+      return false;
+
+    if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
+      return this._isValidHandlerExecutable(aHandlerApp.executable);
+
+    if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
+      return aHandlerApp.uriTemplate;
+
+    if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
+      return aHandlerApp.uri;
+
+    return false;
+  },
+
+  _isValidHandlerExecutable(aExecutable) {
+    let leafName;
+    if (AppConstants.platform == "win") {
+      leafName = `${AppConstants.MOZ_APP_NAME}.exe`;
+    } else if (AppConstants.platform == "macosx") {
+      leafName = AppConstants.MOZ_MACBUNDLE_NAME;
+    } else {
+      leafName = `${AppConstants.MOZ_APP_NAME}-bin`;
+    }
+    return aExecutable &&
+           aExecutable.exists() &&
+           aExecutable.isExecutable() &&
+// XXXben - we need to compare this with the running instance executable
+//          just don't know how to do that via script...
+// XXXmano TBD: can probably add this to nsIShellService
+           aExecutable.leafName != leafName;
+  },
+
+  /**
+   * Rebuild the actions menu for the selected entry.  Gets called by
+   * the richlistitem constructor when an entry in the list gets selected.
+   */
+  rebuildActionsMenu() {
+    var typeItem = this._list.selectedItem;
+    var handlerInfo = this._handledTypes[typeItem.type];
+    var menu =
+      document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+    var menuPopup = menu.menupopup;
+
+    // Clear out existing items.
+    while (menuPopup.hasChildNodes())
+      menuPopup.removeChild(menuPopup.lastChild);
+
+    let internalMenuItem;
+    // Add the "Preview in Firefox" option for optional internal handlers.
+    if (handlerInfo instanceof InternalHandlerInfoWrapper) {
+      internalMenuItem = document.createElement("menuitem");
+      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
+      let label = this._prefsBundle.getFormattedString("previewInApp",
+                                                       [this._brandShortName]);
+      internalMenuItem.setAttribute("label", label);
+      internalMenuItem.setAttribute("tooltiptext", label);
+      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
+      menuPopup.appendChild(internalMenuItem);
+    }
+
+    {
+      var askMenuItem = document.createElement("menuitem");
+      askMenuItem.setAttribute("action", Ci.nsIHandlerInfo.alwaysAsk);
+      let label;
+      if (isFeedType(handlerInfo.type))
+        label = this._prefsBundle.getFormattedString("previewInApp",
+                                                     [this._brandShortName]);
+      else
+        label = this._prefsBundle.getString("alwaysAsk");
+      askMenuItem.setAttribute("label", label);
+      askMenuItem.setAttribute("tooltiptext", label);
+      askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
+      menuPopup.appendChild(askMenuItem);
+    }
+
+    // Create a menu item for saving to disk.
+    // Note: this option isn't available to protocol types, since we don't know
+    // what it means to save a URL having a certain scheme to disk, nor is it
+    // available to feeds, since the feed code doesn't implement the capability.
+    if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
+        !isFeedType(handlerInfo.type)) {
+      var saveMenuItem = document.createElement("menuitem");
+      saveMenuItem.setAttribute("action", Ci.nsIHandlerInfo.saveToDisk);
+      let label = this._prefsBundle.getString("saveFile");
+      saveMenuItem.setAttribute("label", label);
+      saveMenuItem.setAttribute("tooltiptext", label);
+      saveMenuItem.setAttribute(APP_ICON_ATTR_NAME, "save");
+      menuPopup.appendChild(saveMenuItem);
+    }
+
+    // If this is the feed type, add a Live Bookmarks item.
+    if (isFeedType(handlerInfo.type)) {
+      internalMenuItem = document.createElement("menuitem");
+      internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
+      let label = this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
+                                                       [this._brandShortName]);
+      internalMenuItem.setAttribute("label", label);
+      internalMenuItem.setAttribute("tooltiptext", label);
+      internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "feed");
+      menuPopup.appendChild(internalMenuItem);
+    }
+
+    // Add a separator to distinguish these items from the helper app items
+    // that follow them.
+    let menuseparator = document.createElement("menuseparator");
+    menuPopup.appendChild(menuseparator);
+
+    // Create a menu item for the OS default application, if any.
+    if (handlerInfo.hasDefaultHandler) {
+      var defaultMenuItem = document.createElement("menuitem");
+      defaultMenuItem.setAttribute("action", Ci.nsIHandlerInfo.useSystemDefault);
+      let label = this._prefsBundle.getFormattedString("useDefault",
+                                                       [handlerInfo.defaultDescription]);
+      defaultMenuItem.setAttribute("label", label);
+      defaultMenuItem.setAttribute("tooltiptext", handlerInfo.defaultDescription);
+      defaultMenuItem.setAttribute("image", this._getIconURLForSystemDefault(handlerInfo));
+
+      menuPopup.appendChild(defaultMenuItem);
+    }
+
+    // Create menu items for possible handlers.
+    let preferredApp = handlerInfo.preferredApplicationHandler;
+    let possibleApps = handlerInfo.possibleApplicationHandlers.enumerate();
+    var possibleAppMenuItems = [];
+    while (possibleApps.hasMoreElements()) {
+      let possibleApp = possibleApps.getNext();
+      if (!this.isValidHandlerApp(possibleApp))
+        continue;
+
+      let menuItem = document.createElement("menuitem");
+      menuItem.setAttribute("action", Ci.nsIHandlerInfo.useHelperApp);
+      let label;
+      if (possibleApp instanceof Ci.nsILocalHandlerApp)
+        label = getFileDisplayName(possibleApp.executable);
+      else
+        label = possibleApp.name;
+      label = this._prefsBundle.getFormattedString("useApp", [label]);
+      menuItem.setAttribute("label", label);
+      menuItem.setAttribute("tooltiptext", label);
+      menuItem.setAttribute("image", this._getIconURLForHandlerApp(possibleApp));
+
+      // Attach the handler app object to the menu item so we can use it
+      // to make changes to the datastore when the user selects the item.
+      menuItem.handlerApp = possibleApp;
+
+      menuPopup.appendChild(menuItem);
+      possibleAppMenuItems.push(menuItem);
+    }
+
+    // Create a menu item for the plugin.
+    if (handlerInfo.pluginName) {
+      var pluginMenuItem = document.createElement("menuitem");
+      pluginMenuItem.setAttribute("action", kActionUsePlugin);
+      let label = this._prefsBundle.getFormattedString("usePluginIn",
+                                                       [handlerInfo.pluginName,
+                                                        this._brandShortName]);
+      pluginMenuItem.setAttribute("label", label);
+      pluginMenuItem.setAttribute("tooltiptext", label);
+      pluginMenuItem.setAttribute(APP_ICON_ATTR_NAME, "plugin");
+      menuPopup.appendChild(pluginMenuItem);
+    }
+
+    // Create a menu item for selecting a local application.
+    let canOpenWithOtherApp = true;
+    if (AppConstants.platform == "win") {
+      // On Windows, selecting an application to open another application
+      // would be meaningless so we special case executables.
+      let executableType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
+                                                    .getTypeFromExtension("exe");
+      canOpenWithOtherApp = handlerInfo.type != executableType;
+    }
+    if (canOpenWithOtherApp) {
+      let menuItem = document.createElement("menuitem");
+      menuItem.className = "choose-app-item";
+      menuItem.addEventListener("command", function(e) {
+        gMainPane.chooseApp(e);
+      });
+      let label = this._prefsBundle.getString("useOtherApp");
+      menuItem.setAttribute("label", label);
+      menuItem.setAttribute("tooltiptext", label);
+      menuPopup.appendChild(menuItem);
+    }
+
+    // Create a menu item for managing applications.
+    if (possibleAppMenuItems.length) {
+      let menuItem = document.createElement("menuseparator");
+      menuPopup.appendChild(menuItem);
+      menuItem = document.createElement("menuitem");
+      menuItem.className = "manage-app-item";
+      menuItem.addEventListener("command", function(e) {
+        gMainPane.manageApp(e);
+      });
+      menuItem.setAttribute("label", this._prefsBundle.getString("manageApp"));
+      menuPopup.appendChild(menuItem);
+    }
+
+    // Select the item corresponding to the preferred action.  If the always
+    // ask flag is set, it overrides the preferred action.  Otherwise we pick
+    // the item identified by the preferred action (when the preferred action
+    // is to use a helper app, we have to pick the specific helper app item).
+    if (handlerInfo.alwaysAskBeforeHandling)
+      menu.selectedItem = askMenuItem;
+    else switch (handlerInfo.preferredAction) {
+      case Ci.nsIHandlerInfo.handleInternally:
+        if (internalMenuItem) {
+          menu.selectedItem = internalMenuItem;
+        } else {
+          Cu.reportError("No menu item defined to set!")
         }
         break;
-      case "command":
-        switch (aEvent.target.id) {
-          case "":
-            if (aEvent.target.parentNode &&
-                aEvent.target.parentNode.parentNode &&
-                aEvent.target.parentNode.parentNode.id == "defaultEngine") {
-              gMainPane.setDefaultEngine();
-            }
-            break;
-          case "restoreDefaultSearchEngines":
-            gMainPane.onRestoreDefaults();
-            break;
-          case "removeEngineButton":
-            Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
-            break;
-        }
+      case Ci.nsIHandlerInfo.useSystemDefault:
+        menu.selectedItem = defaultMenuItem;
         break;
-      case "dragstart":
-        if (aEvent.target.id == "engineChildren") {
-          onDragEngineStart(aEvent);
-        }
-        break;
-      case "keypress":
-        if (aEvent.target.id == "engineList") {
-          gMainPane.onTreeKeyPress(aEvent);
-        }
+      case Ci.nsIHandlerInfo.useHelperApp:
+        if (preferredApp)
+          menu.selectedItem =
+            possibleAppMenuItems.filter(v => v.handlerApp.equals(preferredApp))[0];
         break;
-      case "select":
-        if (aEvent.target.id == "engineList") {
-          gMainPane.onTreeSelect();
-        }
+      case kActionUsePlugin:
+        menu.selectedItem = pluginMenuItem;
         break;
-      case "blur":
-        if (aEvent.target.id == "engineList" &&
-            aEvent.target.inputField == document.getBindingParent(aEvent.originalTarget)) {
-          gMainPane.onInputBlur();
-        }
+      case Ci.nsIHandlerInfo.saveToDisk:
+        menu.selectedItem = saveMenuItem;
         break;
     }
   },
 
-  observe(aEngine, aTopic, aVerb) {
-    if (aTopic == "browser-search-engine-modified") {
-      aEngine.QueryInterface(Components.interfaces.nsISearchEngine);
-      switch (aVerb) {
-      case "engine-added":
-        gEngineView._engineStore.addEngine(aEngine);
-        gEngineView.rowCountChanged(gEngineView.lastIndex, 1);
-        gMainPane.buildDefaultEngineDropDown();
+
+  // Sorting & Filtering
+
+  _sortColumn: null,
+
+  /**
+   * Sort the list when the user clicks on a column header.
+   */
+  sort(event) {
+    var column = event.target;
+
+    // If the user clicked on a new sort column, remove the direction indicator
+    // from the old column.
+    if (this._sortColumn && this._sortColumn != column)
+      this._sortColumn.removeAttribute("sortDirection");
+
+    this._sortColumn = column;
+
+    // Set (or switch) the sort direction indicator.
+    if (column.getAttribute("sortDirection") == "ascending")
+      column.setAttribute("sortDirection", "descending");
+    else
+      column.setAttribute("sortDirection", "ascending");
+
+    this._sortVisibleTypes();
+    this._rebuildView();
+  },
+
+  /**
+   * Sort the list of visible types by the current sort column/direction.
+   */
+  _sortVisibleTypes() {
+    if (!this._sortColumn)
+      return;
+
+    var t = this;
+
+    function sortByType(a, b) {
+      return t._describeType(a).toLowerCase().
+             localeCompare(t._describeType(b).toLowerCase());
+    }
+
+    function sortByAction(a, b) {
+      return t._describePreferredAction(a).toLowerCase().
+             localeCompare(t._describePreferredAction(b).toLowerCase());
+    }
+
+    switch (this._sortColumn.getAttribute("value")) {
+      case "type":
+        this._visibleTypes.sort(sortByType);
+        break;
+      case "action":
+        this._visibleTypes.sort(sortByAction);
         break;
-      case "engine-changed":
-        gEngineView._engineStore.reloadIcons();
-        gEngineView.invalidate();
+    }
+
+    if (this._sortColumn.getAttribute("sortDirection") == "descending")
+      this._visibleTypes.reverse();
+  },
+
+  /**
+   * Filter the list when the user enters a filter term into the filter field.
+   */
+  filter() {
+    this._rebuildView();
+  },
+
+  focusFilterBox() {
+    this._filter.focus();
+    this._filter.select();
+  },
+
+
+  // Changes
+
+  onSelectAction(aActionItem) {
+    this._storingAction = true;
+
+    try {
+      this._storeAction(aActionItem);
+    } finally {
+      this._storingAction = false;
+    }
+  },
+
+  _storeAction(aActionItem) {
+    var typeItem = this._list.selectedItem;
+    var handlerInfo = this._handledTypes[typeItem.type];
+
+    let action = parseInt(aActionItem.getAttribute("action"));
+
+    // Set the plugin state if we're enabling or disabling a plugin.
+    if (action == kActionUsePlugin)
+      handlerInfo.enablePluginType();
+    else if (handlerInfo.pluginName && !handlerInfo.isDisabledPluginType)
+      handlerInfo.disablePluginType();
+
+    // Set the preferred application handler.
+    // We leave the existing preferred app in the list when we set
+    // the preferred action to something other than useHelperApp so that
+    // legacy datastores that don't have the preferred app in the list
+    // of possible apps still include the preferred app in the list of apps
+    // the user can choose to handle the type.
+    if (action == Ci.nsIHandlerInfo.useHelperApp)
+      handlerInfo.preferredApplicationHandler = aActionItem.handlerApp;
+
+    // Set the "always ask" flag.
+    if (action == Ci.nsIHandlerInfo.alwaysAsk)
+      handlerInfo.alwaysAskBeforeHandling = true;
+    else
+      handlerInfo.alwaysAskBeforeHandling = false;
+
+    // Set the preferred action.
+    handlerInfo.preferredAction = action;
+
+    handlerInfo.store();
+
+    // Make sure the handler info object is flagged to indicate that there is
+    // now some user configuration for the type.
+    handlerInfo.handledOnlyByPlugin = false;
+
+    // Update the action label and image to reflect the new preferred action.
+    typeItem.setAttribute("actionDescription",
+                          this._describePreferredAction(handlerInfo));
+    if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
+      typeItem.setAttribute("actionIcon",
+                            this._getIconURLForPreferredAction(handlerInfo));
+    }
+  },
+
+  manageApp(aEvent) {
+    // Don't let the normal "on select action" handler get this event,
+    // as we handle it specially ourselves.
+    aEvent.stopPropagation();
+
+    var typeItem = this._list.selectedItem;
+    var handlerInfo = this._handledTypes[typeItem.type];
+
+    let onComplete = () => {
+      // Rebuild the actions menu so that we revert to the previous selection,
+      // or "Always ask" if the previous default application has been removed
+      this.rebuildActionsMenu();
+
+      // update the richlistitem too. Will be visible when selecting another row
+      typeItem.setAttribute("actionDescription",
+                            this._describePreferredAction(handlerInfo));
+      if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) {
+        typeItem.setAttribute("actionIcon",
+                              this._getIconURLForPreferredAction(handlerInfo));
+      }
+    };
+
+    gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul",
+                    "resizable=no", handlerInfo, onComplete);
+
+  },
+
+  chooseApp(aEvent) {
+    // Don't let the normal "on select action" handler get this event,
+    // as we handle it specially ourselves.
+    aEvent.stopPropagation();
+
+    var handlerApp;
+    let chooseAppCallback = aHandlerApp => {
+      // Rebuild the actions menu whether the user picked an app or canceled.
+      // If they picked an app, we want to add the app to the menu and select it.
+      // If they canceled, we want to go back to their previous selection.
+      this.rebuildActionsMenu();
+
+      // If the user picked a new app from the menu, select it.
+      if (aHandlerApp) {
+        let typeItem = this._list.selectedItem;
+        let actionsMenu =
+          document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+        let menuItems = actionsMenu.menupopup.childNodes;
+        for (let i = 0; i < menuItems.length; i++) {
+          let menuItem = menuItems[i];
+          if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
+            actionsMenu.selectedIndex = i;
+            this.onSelectAction(menuItem);
+            break;
+          }
+        }
+      }
+    };
+
+    if (AppConstants.platform == "win") {
+      var params = {};
+      var handlerInfo = this._handledTypes[this._list.selectedItem.type];
+
+      if (isFeedType(handlerInfo.type)) {
+        // MIME info will be null, create a temp object.
+        params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type,
+                                                   handlerInfo.primaryExtension);
+      } else {
+        params.mimeInfo = handlerInfo.wrappedHandlerInfo;
+      }
+
+      params.title         = this._prefsBundle.getString("fpTitleChooseApp");
+      params.description   = handlerInfo.description;
+      params.filename      = null;
+      params.handlerApp    = null;
+
+      let onAppSelected = () => {
+        if (this.isValidHandlerApp(params.handlerApp)) {
+          handlerApp = params.handlerApp;
+
+          // Add the app to the type's list of possible handlers.
+          handlerInfo.addPossibleApplicationHandler(handlerApp);
+        }
+
+        chooseAppCallback(handlerApp);
+      };
+
+      gSubDialog.open("chrome://global/content/appPicker.xul",
+                      null, params, onAppSelected);
+    } else {
+      let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
+      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+      let fpCallback = aResult => {
+        if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
+            this._isValidHandlerExecutable(fp.file)) {
+          handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+                       createInstance(Ci.nsILocalHandlerApp);
+          handlerApp.name = getFileDisplayName(fp.file);
+          handlerApp.executable = fp.file;
+
+          // Add the app to the type's list of possible handlers.
+          let handler = this._handledTypes[this._list.selectedItem.type];
+          handler.addPossibleApplicationHandler(handlerApp);
+
+          chooseAppCallback(handlerApp);
+        }
+      };
+
+      // Prompt the user to pick an app.  If they pick one, and it's a valid
+      // selection, then add it to the list of possible handlers.
+      fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
+      fp.appendFilters(Ci.nsIFilePicker.filterApps);
+      fp.open(fpCallback);
+    }
+  },
+
+  // Mark which item in the list was last selected so we can reselect it
+  // when we rebuild the list or when the user returns to the prefpane.
+  onSelectionChanged() {
+    if (this._list.selectedItem)
+      this._list.setAttribute("lastSelectedType",
+                              this._list.selectedItem.getAttribute("type"));
+  },
+
+  _setIconClassForPreferredAction(aHandlerInfo, aElement) {
+    // If this returns true, the attribute that CSS sniffs for was set to something
+    // so you shouldn't manually set an icon URI.
+    // This removes the existing actionIcon attribute if any, even if returning false.
+    aElement.removeAttribute("actionIcon");
+
+    if (aHandlerInfo.alwaysAskBeforeHandling) {
+      aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
+      return true;
+    }
+
+    switch (aHandlerInfo.preferredAction) {
+      case Ci.nsIHandlerInfo.saveToDisk:
+        aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
+        return true;
+
+      case Ci.nsIHandlerInfo.handleInternally:
+        if (isFeedType(aHandlerInfo.type)) {
+          aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
+          return true;
+        } else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
+          aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
+          return true;
+        }
         break;
-      case "engine-removed":
-        gMainPane.remove(aEngine);
-        break;
-      case "engine-current":
-        // If the user is going through the drop down using up/down keys, the
-        // dropdown may still be open (eg. on Windows) when engine-current is
-        // fired, so rebuilding the list unconditionally would get in the way.
-        let selectedEngine =
-          document.getElementById("defaultEngine").selectedItem.engine;
-        if (selectedEngine.name != aEngine.name)
-          gMainPane.buildDefaultEngineDropDown();
-        break;
-      case "engine-default":
-        // Not relevant
+
+      case kActionUsePlugin:
+        aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
+        return true;
+    }
+    aElement.removeAttribute(APP_ICON_ATTR_NAME);
+    return false;
+  },
+
+  _getIconURLForPreferredAction(aHandlerInfo) {
+    switch (aHandlerInfo.preferredAction) {
+      case Ci.nsIHandlerInfo.useSystemDefault:
+        return this._getIconURLForSystemDefault(aHandlerInfo);
+
+      case Ci.nsIHandlerInfo.useHelperApp:
+        let preferredApp = aHandlerInfo.preferredApplicationHandler;
+        if (this.isValidHandlerApp(preferredApp))
+          return this._getIconURLForHandlerApp(preferredApp);
+        // Explicit fall-through
+
+      // This should never happen, but if preferredAction is set to some weird
+      // value, then fall back to the generic application icon.
+      default:
+        return ICON_URL_APP;
+    }
+  },
+
+  _getIconURLForHandlerApp(aHandlerApp) {
+    if (aHandlerApp instanceof Ci.nsILocalHandlerApp)
+      return this._getIconURLForFile(aHandlerApp.executable);
+
+    if (aHandlerApp instanceof Ci.nsIWebHandlerApp)
+      return this._getIconURLForWebApp(aHandlerApp.uriTemplate);
+
+    if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo)
+      return this._getIconURLForWebApp(aHandlerApp.uri)
+
+    // We know nothing about other kinds of handler apps.
+    return "";
+  },
+
+  _getIconURLForFile(aFile) {
+    var fph = this._ioSvc.getProtocolHandler("file").
+              QueryInterface(Ci.nsIFileProtocolHandler);
+    var urlSpec = fph.getURLSpecFromFile(aFile);
+
+    return "moz-icon://" + urlSpec + "?size=16";
+  },
+
+  _getIconURLForWebApp(aWebAppURITemplate) {
+    var uri = this._ioSvc.newURI(aWebAppURITemplate);
+
+    // Unfortunately we can't use the favicon service to get the favicon,
+    // because the service looks in the annotations table for a record with
+    // the exact URL we give it, and users won't have such records for URLs
+    // they don't visit, and users won't visit the web app's URL template,
+    // they'll only visit URLs derived from that template (i.e. with %s
+    // in the template replaced by the URL of the content being handled).
+
+    if (/^https?$/.test(uri.scheme) && this._prefSvc.getBoolPref("browser.chrome.favicons"))
+      return uri.prePath + "/favicon.ico";
+
+    return "";
+  },
+
+  _getIconURLForSystemDefault(aHandlerInfo) {
+    // Handler info objects for MIME types on some OSes implement a property bag
+    // interface from which we can get an icon for the default app, so if we're
+    // dealing with a MIME type on one of those OSes, then try to get the icon.
+    if ("wrappedHandlerInfo" in aHandlerInfo) {
+      let wrappedHandlerInfo = aHandlerInfo.wrappedHandlerInfo;
+
+      if (wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
+          wrappedHandlerInfo instanceof Ci.nsIPropertyBag) {
+        try {
+          let url = wrappedHandlerInfo.getProperty("defaultApplicationIconURL");
+          if (url)
+            return url + "?size=16";
+        } catch (ex) {}
+      }
+    }
+
+    // If this isn't a MIME type object on an OS that supports retrieving
+    // the icon, or if we couldn't retrieve the icon for some other reason,
+    // then use a generic icon.
+    return ICON_URL_APP;
+  },
+
+  // DOWNLOADS
+
+  /*
+   * Preferences:
+   *
+   * browser.download.useDownloadDir - bool
+   *   True - Save files directly to the folder configured via the
+   *   browser.download.folderList preference.
+   *   False - Always ask the user where to save a file and default to
+   *   browser.download.lastDir when displaying a folder picker dialog.
+   * browser.download.dir - local file handle
+   *   A local folder the user may have selected for downloaded files to be
+   *   saved. Migration of other browser settings may also set this path.
+   *   This folder is enabled when folderList equals 2.
+   * browser.download.lastDir - local file handle
+   *   May contain the last folder path accessed when the user browsed
+   *   via the file save-as dialog. (see contentAreaUtils.js)
+   * browser.download.folderList - int
+   *   Indicates the location users wish to save downloaded files too.
+   *   It is also used to display special file labels when the default
+   *   download location is either the Desktop or the Downloads folder.
+   *   Values:
+   *     0 - The desktop is the default download location.
+   *     1 - The system's downloads folder is the default download location.
+   *     2 - The default download location is elsewhere as specified in
+   *         browser.download.dir.
+   * browser.download.downloadDir
+   *   deprecated.
+   * browser.download.defaultFolder
+   *   deprecated.
+   */
+
+  /**
+   * 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");
+    downloadFolder.disabled = !preference.value || preference.locked;
+    chooseFolder.disabled = !preference.value || preference.locked;
+
+    // don't override the preference's value in UI
+    return undefined;
+  },
+
+  /**
+   * 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 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
+    if (currentDirPref && currentDirPref.exists()) {
+      fp.displayDirectory = currentDirPref;
+    } else if (defDownloads && defDownloads.exists()) {
+      // Try the system's download dir
+      fp.displayDirectory = defDownloads;
+    } else {
+      // Fall back to Desktop
+      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");
+    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.
+  },
+
+  /**
+   * Initializes the download folder display settings based on the user's
+   * preferences.
+   */
+  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 bundlePreferences = document.getElementById("bundlePreferences");
+    var downloadFolder = document.getElementById("downloadFolder");
+    var currentDirPref = document.getElementById("browser.download.dir");
+
+    // Used in defining the correct path to the folder icon.
+    var ios = Components.classes["@mozilla.org/network/io-service;1"]
+                        .getService(Components.interfaces.nsIIOService);
+    var fph = ios.getProtocolHandler("file")
+                 .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
+    var iconUrlSpec;
+
+    // Display a 'pretty' label or the path in the UI.
+    if (folderListPref.value == 2) {
+      // Custom path selected and is configured
+      downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value);
+      iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
+    } else if (folderListPref.value == 1) {
+      // 'Downloads'
+      downloadFolder.label = bundlePreferences.getString("downloadsFolderName");
+      iconUrlSpec = fph.getURLSpecFromFile(await this._indexToFolder(1));
+    } else {
+      // 'Desktop'
+      downloadFolder.label = bundlePreferences.getString("desktopFolderName");
+      iconUrlSpec = fph.getURLSpecFromFile(await this._getDownloadsFolder("Desktop"));
+    }
+    downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16";
+  },
+
+  /**
+   * Returns the textual path of a folder in readable form.
+   */
+  _getDisplayNameOfFile(aFolder) {
+    // TODO: would like to add support for 'Downloads on Macintosh HD'
+    //       for OS X users.
+    return aFolder ? aFolder.path : "";
+  },
+
+  /**
+   * Returns the Downloads folder.  If aFolder is "Desktop", then the Downloads
+   * folder returned is the desktop folder; otherwise, it is a folder whose name
+   * indicates that it is a download folder and whose path is as determined by
+   * the XPCOM directory service via the download manager's attribute
+   * defaultDownloadsDirectory.
+   *
+   * @throws if aFolder is not "Desktop" or "Downloads"
+   */
+  async _getDownloadsFolder(aFolder) {
+    switch (aFolder) {
+      case "Desktop":
+        var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
+                                    .getService(Components.interfaces.nsIProperties);
+        return fileLoc.get("Desk", Components.interfaces.nsILocalFile);
+      case "Downloads":
+        let downloadsDir = await Downloads.getSystemDownloadsDirectory();
+        return new FileUtils.File(downloadsDir);
+    }
+    throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
+  },
+
+  /**
+   * Determines the type of the given folder.
+   *
+   * @param   aFolder
+   *          the folder whose type is to be determined
+   * @returns integer
+   *          0 if aFolder is the Desktop or is unspecified,
+   *          1 if aFolder is the Downloads folder,
+   *          2 otherwise
+   */
+  async _folderToIndex(aFolder) {
+    if (!aFolder || aFolder.equals(await this._getDownloadsFolder("Desktop")))
+      return 0;
+    else if (aFolder.equals(await this._getDownloadsFolder("Downloads")))
+      return 1;
+    return 2;
+  },
+
+  /**
+   * Converts an integer into the corresponding folder.
+   *
+   * @param   aIndex
+   *          an integer
+   * @returns the Desktop folder if aIndex == 0,
+   *          the Downloads folder if aIndex == 1,
+   *          the folder stored in browser.download.dir
+   */
+  async _indexToFolder(aIndex) {
+    switch (aIndex) {
+      case 0:
+        return await this._getDownloadsFolder("Desktop");
+      case 1:
+        return await this._getDownloadsFolder("Downloads");
+    }
+    var currentDirPref = document.getElementById("browser.download.dir");
+    return currentDirPref.value;
+  }
+};
+
+// Utilities
+
+function getFileDisplayName(file) {
+  if (AppConstants.platform == "win") {
+    if (file instanceof Ci.nsILocalFileWin) {
+      try {
+        return file.getVersionInfoField("FileDescription");
+      } catch (e) {}
+    }
+  }
+  if (AppConstants.platform == "macosx") {
+    if (file instanceof Ci.nsILocalFileMac) {
+      try {
+        return file.bundleDisplayName;
+      } catch (e) {}
+    }
+  }
+  return file.leafName;
+}
+
+function getLocalHandlerApp(aFile) {
+  var localHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+                        createInstance(Ci.nsILocalHandlerApp);
+  localHandlerApp.name = getFileDisplayName(aFile);
+  localHandlerApp.executable = aFile;
+
+  return localHandlerApp;
+}
+
+/**
+ * An enumeration of items in a JS array.
+ *
+ * FIXME: use ArrayConverter once it lands (bug 380839).
+ *
+ * @constructor
+ */
+function ArrayEnumerator(aItems) {
+  this._index = 0;
+  this._contents = aItems;
+}
+
+ArrayEnumerator.prototype = {
+  _index: 0,
+
+  hasMoreElements() {
+    return this._index < this._contents.length;
+  },
+
+  getNext() {
+    return this._contents[this._index++];
+  }
+};
+
+function isFeedType(t) {
+  return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED;
+}
+
+// HandlerInfoWrapper
+
+/**
+ * This object wraps nsIHandlerInfo with some additional functionality
+ * the Applications prefpane needs to display and allow modification of
+ * the list of handled types.
+ *
+ * We create an instance of this wrapper for each entry we might display
+ * in the prefpane, and we compose the instances from various sources,
+ * including plugins and the handler service.
+ *
+ * We don't implement all the original nsIHandlerInfo functionality,
+ * just the stuff that the prefpane needs.
+ *
+ * In theory, all of the custom functionality in this wrapper should get
+ * pushed down into nsIHandlerInfo eventually.
+ */
+function HandlerInfoWrapper(aType, aHandlerInfo) {
+  this._type = aType;
+  this.wrappedHandlerInfo = aHandlerInfo;
+}
+
+HandlerInfoWrapper.prototype = {
+  // The wrapped nsIHandlerInfo object.  In general, this object is private,
+  // but there are a couple cases where callers access it directly for things
+  // we haven't (yet?) implemented, so we make it a public property.
+  wrappedHandlerInfo: null,
+
+
+  // Convenience Utils
+
+  _handlerSvc: Cc["@mozilla.org/uriloader/handler-service;1"].
+               getService(Ci.nsIHandlerService),
+
+  _prefSvc: Cc["@mozilla.org/preferences-service;1"].
+            getService(Ci.nsIPrefBranch),
+
+  _categoryMgr: Cc["@mozilla.org/categorymanager;1"].
+                getService(Ci.nsICategoryManager),
+
+  element(aID) {
+    return document.getElementById(aID);
+  },
+
+
+  // nsIHandlerInfo
+
+  // The MIME type or protocol scheme.
+  _type: null,
+  get type() {
+    return this._type;
+  },
+
+  get description() {
+    if (this.wrappedHandlerInfo.description)
+      return this.wrappedHandlerInfo.description;
+
+    if (this.primaryExtension) {
+      var extension = this.primaryExtension.toUpperCase();
+      return this.element("bundlePreferences").getFormattedString("fileEnding",
+                                                                  [extension]);
+    }
+
+    return this.type;
+  },
+
+  get preferredApplicationHandler() {
+    return this.wrappedHandlerInfo.preferredApplicationHandler;
+  },
+
+  set preferredApplicationHandler(aNewValue) {
+    this.wrappedHandlerInfo.preferredApplicationHandler = aNewValue;
+
+    // Make sure the preferred handler is in the set of possible handlers.
+    if (aNewValue)
+      this.addPossibleApplicationHandler(aNewValue)
+  },
+
+  get possibleApplicationHandlers() {
+    return this.wrappedHandlerInfo.possibleApplicationHandlers;
+  },
+
+  addPossibleApplicationHandler(aNewHandler) {
+    var possibleApps = this.possibleApplicationHandlers.enumerate();
+    while (possibleApps.hasMoreElements()) {
+      if (possibleApps.getNext().equals(aNewHandler))
+        return;
+    }
+    this.possibleApplicationHandlers.appendElement(aNewHandler);
+  },
+
+  removePossibleApplicationHandler(aHandler) {
+    var defaultApp = this.preferredApplicationHandler;
+    if (defaultApp && aHandler.equals(defaultApp)) {
+      // If the app we remove was the default app, we must make sure
+      // it won't be used anymore
+      this.alwaysAskBeforeHandling = true;
+      this.preferredApplicationHandler = null;
+    }
+
+    var handlers = this.possibleApplicationHandlers;
+    for (var i = 0; i < handlers.length; ++i) {
+      var handler = handlers.queryElementAt(i, Ci.nsIHandlerApp);
+      if (handler.equals(aHandler)) {
+        handlers.removeElementAt(i);
         break;
       }
     }
   },
 
-  onInputBlur(aEvent) {
-    let tree = document.getElementById("engineList");
-    if (!tree.hasAttribute("editing"))
-      return;
-
-    // Accept input unless discarded.
-    let accept = aEvent.charCode != KeyEvent.DOM_VK_ESCAPE;
-    tree.stopEditing(accept);
+  get hasDefaultHandler() {
+    return this.wrappedHandlerInfo.hasDefaultHandler;
+  },
+
+  get defaultDescription() {
+    return this.wrappedHandlerInfo.defaultDescription;
+  },
+
+  // What to do with content of this type.
+  get preferredAction() {
+    // If we have an enabled plugin, then the action is to use that plugin.
+    if (this.pluginName && !this.isDisabledPluginType)
+      return kActionUsePlugin;
+
+    // If the action is to use a helper app, but we don't have a preferred
+    // handler app, then switch to using the system default, if any; otherwise
+    // fall back to saving to disk, which is the default action in nsMIMEInfo.
+    // Note: "save to disk" is an invalid value for protocol info objects,
+    // but the alwaysAskBeforeHandling getter will detect that situation
+    // and always return true in that case to override this invalid value.
+    if (this.wrappedHandlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
+        !gMainPane.isValidHandlerApp(this.preferredApplicationHandler)) {
+      if (this.wrappedHandlerInfo.hasDefaultHandler)
+        return Ci.nsIHandlerInfo.useSystemDefault;
+      return Ci.nsIHandlerInfo.saveToDisk;
+    }
+
+    return this.wrappedHandlerInfo.preferredAction;
+  },
+
+  set preferredAction(aNewValue) {
+    // If the action is to use the plugin,
+    // we must set the preferred action to "save to disk".
+    // But only if it's not currently the preferred action.
+    if ((aNewValue == kActionUsePlugin) &&
+        (this.preferredAction != Ci.nsIHandlerInfo.saveToDisk)) {
+      aNewValue = Ci.nsIHandlerInfo.saveToDisk;
+    }
+
+    // We don't modify the preferred action if the new action is to use a plugin
+    // because handler info objects don't understand our custom "use plugin"
+    // value.  Also, leaving it untouched means that we can automatically revert
+    // to the old setting if the user ever removes the plugin.
+
+    if (aNewValue != kActionUsePlugin)
+      this.wrappedHandlerInfo.preferredAction = aNewValue;
   },
 
-  onTreeSelect() {
-    document.getElementById("removeEngineButton").disabled =
-      !gEngineView.isEngineSelectedAndRemovable();
+  get alwaysAskBeforeHandling() {
+    // If this type is handled only by a plugin, we can't trust the value
+    // in the handler info object, since it'll be a default based on the absence
+    // of any user configuration, and the default in that case is to always ask,
+    // even though we never ask for content handled by a plugin, so special case
+    // plugin-handled types by returning false here.
+    if (this.pluginName && this.handledOnlyByPlugin)
+      return false;
+
+    // If this is a protocol type and the preferred action is "save to disk",
+    // which is invalid for such types, then return true here to override that
+    // action.  This could happen when the preferred action is to use a helper
+    // app, but the preferredApplicationHandler is invalid, and there isn't
+    // a default handler, so the preferredAction getter returns save to disk
+    // instead.
+    if (!(this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) &&
+        this.preferredAction == Ci.nsIHandlerInfo.saveToDisk)
+      return true;
+
+    return this.wrappedHandlerInfo.alwaysAskBeforeHandling;
+  },
+
+  set alwaysAskBeforeHandling(aNewValue) {
+    this.wrappedHandlerInfo.alwaysAskBeforeHandling = aNewValue;
+  },
+
+
+  // nsIMIMEInfo
+
+  // The primary file extension associated with this type, if any.
+  //
+  // XXX Plugin objects contain an array of MimeType objects with "suffixes"
+  // properties; if this object has an associated plugin, shouldn't we check
+  // those properties for an extension?
+  get primaryExtension() {
+    try {
+      if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo &&
+          this.wrappedHandlerInfo.primaryExtension)
+        return this.wrappedHandlerInfo.primaryExtension
+    } catch (ex) {}
+
+    return null;
+  },
+
+
+  // Plugin Handling
+
+  // A plugin that can handle this type, if any.
+  //
+  // Note: just because we have one doesn't mean it *will* handle the type.
+  // That depends on whether or not the type is in the list of types for which
+  // plugin handling is disabled.
+  plugin: null,
+
+  // Whether or not this type is only handled by a plugin or is also handled
+  // by some user-configured action as specified in the handler info object.
+  //
+  // Note: we can't just check if there's a handler info object for this type,
+  // because OS and user configuration is mixed up in the handler info object,
+  // so we always need to retrieve it for the OS info and can't tell whether
+  // it represents only OS-default information or user-configured information.
+  //
+  // FIXME: once handler info records are broken up into OS-provided records
+  // and user-configured records, stop using this boolean flag and simply
+  // check for the presence of a user-configured record to determine whether
+  // or not this type is only handled by a plugin.  Filed as bug 395142.
+  handledOnlyByPlugin: undefined,
+
+  get isDisabledPluginType() {
+    return this._getDisabledPluginTypes().indexOf(this.type) != -1;
+  },
+
+  _getDisabledPluginTypes() {
+    var types = "";
+
+    if (this._prefSvc.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES))
+      types = this._prefSvc.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
+
+    // Only split if the string isn't empty so we don't end up with an array
+    // containing a single empty string.
+    if (types != "")
+      return types.split(",");
+
+    return [];
   },
 
-  onTreeKeyPress(aEvent) {
-    let index = gEngineView.selectedIndex;
-    let tree = document.getElementById("engineList");
-    if (tree.hasAttribute("editing"))
-      return;
-
-    if (aEvent.charCode == KeyEvent.DOM_VK_SPACE) {
-      // Space toggles the checkbox.
-      let newValue = !gEngineView._engineStore.engines[index].shown;
-      gEngineView.setCellValue(index, tree.columns.getFirstColumn(),
-                               newValue.toString());
-      // Prevent page from scrolling on the space key.
-      aEvent.preventDefault();
-    } else {
-      let isMac = Services.appinfo.OS == "Darwin";
-      if ((isMac && aEvent.keyCode == KeyEvent.DOM_VK_RETURN) ||
-          (!isMac && aEvent.keyCode == KeyEvent.DOM_VK_F2)) {
-        tree.startEditing(index, tree.columns.getLastColumn());
-      } else if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE ||
-                 (isMac && aEvent.shiftKey &&
-                  aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE &&
-                  gEngineView.isEngineSelectedAndRemovable())) {
-        // Delete and Shift+Backspace (Mac) removes selected engine.
-        Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
-     }
+  disablePluginType() {
+    var disabledPluginTypes = this._getDisabledPluginTypes();
+
+    if (disabledPluginTypes.indexOf(this.type) == -1)
+      disabledPluginTypes.push(this.type);
+
+    this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
+                              disabledPluginTypes.join(","));
+
+    // Update the category manager so existing browser windows update.
+    this._categoryMgr.deleteCategoryEntry("Gecko-Content-Viewers",
+                                          this.type,
+                                          false);
+  },
+
+  enablePluginType() {
+    var disabledPluginTypes = this._getDisabledPluginTypes();
+
+    var type = this.type;
+    disabledPluginTypes = disabledPluginTypes.filter(v => v != type);
+
+    this._prefSvc.setCharPref(PREF_DISABLED_PLUGIN_TYPES,
+                              disabledPluginTypes.join(","));
+
+    // Update the category manager so existing browser windows update.
+    this._categoryMgr.
+      addCategoryEntry("Gecko-Content-Viewers",
+                       this.type,
+                       "@mozilla.org/content/plugin/document-loader-factory;1",
+                       false,
+                       true);
+  },
+
+
+  // Storage
+
+  store() {
+    this._handlerSvc.store(this.wrappedHandlerInfo);
+  },
+
+
+  // Icons
+
+  get smallIcon() {
+    return this._getIcon(16);
+  },
+
+  _getIcon(aSize) {
+    if (this.primaryExtension)
+      return "moz-icon://goat." + this.primaryExtension + "?size=" + aSize;
+
+    if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo)
+      return "moz-icon://goat?size=" + aSize + "&contentType=" + this.type;
+
+    // FIXME: consider returning some generic icon when we can't get a URL for
+    // one (for example in the case of protocol schemes).  Filed as bug 395141.
+    return null;
+  }
+
+};
+
+
+// Feed Handler Info
+
+/**
+ * This object implements nsIHandlerInfo for the feed types.  It's a separate
+ * object because we currently store handling information for the feed type
+ * in a set of preferences rather than the nsIHandlerService-managed datastore.
+ *
+ * This object inherits from HandlerInfoWrapper in order to get functionality
+ * that isn't special to the feed type.
+ *
+ * XXX Should we inherit from HandlerInfoWrapper?  After all, we override
+ * most of that wrapper's properties and methods, and we have to dance around
+ * the fact that the wrapper expects to have a wrappedHandlerInfo, which we
+ * don't provide.
+ */
+
+function FeedHandlerInfo(aMIMEType) {
+  HandlerInfoWrapper.call(this, aMIMEType, null);
+}
+
+FeedHandlerInfo.prototype = {
+  __proto__: HandlerInfoWrapper.prototype,
+
+  // Convenience Utils
+
+  _converterSvc:
+    Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
+    getService(Ci.nsIWebContentConverterService),
+
+  _shellSvc: AppConstants.HAVE_SHELL_SERVICE ? getShellService() : null,
+
+  // nsIHandlerInfo
+
+  get description() {
+    return this.element("bundlePreferences").getString(this._appPrefLabel);
+  },
+
+  get preferredApplicationHandler() {
+    switch (this.element(this._prefSelectedReader).value) {
+      case "client":
+        var file = this.element(this._prefSelectedApp).value;
+        if (file)
+          return getLocalHandlerApp(file);
+
+        return null;
+
+      case "web":
+        var uri = this.element(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";
+    } else if (aNewValue instanceof Ci.nsIWebContentHandlerInfo) {
+      this.element(this._prefSelectedWeb).value = aNewValue.uri;
+      this.element(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);
     }
   },
 
-  onRestoreDefaults() {
-    let num = gEngineView._engineStore.restoreDefaultEngines();
-    gEngineView.rowCountChanged(0, num);
-    gEngineView.invalidate();
-  },
-
-  showRestoreDefaults(aEnable) {
-    document.getElementById("restoreDefaultSearchEngines").disabled = !aEnable;
-  },
-
-  remove(aEngine) {
-    let index = gEngineView._engineStore.removeEngine(aEngine);
-    gEngineView.rowCountChanged(index, -1);
-    gEngineView.invalidate();
-    gEngineView.selection.select(Math.min(index, gEngineView.lastIndex));
-    gEngineView.ensureRowIsVisible(gEngineView.currentIndex);
-    document.getElementById("engineList").focus();
+  _possibleApplicationHandlers: null,
+
+  get possibleApplicationHandlers() {
+    if (this._possibleApplicationHandlers)
+      return this._possibleApplicationHandlers;
+
+    // A minimal implementation of nsIMutableArray.  It only supports the two
+    // methods its callers invoke, namely appendElement and nsIArray::enumerate.
+    this._possibleApplicationHandlers = {
+      _inner: [],
+      _removed: [],
+
+      QueryInterface(aIID) {
+        if (aIID.equals(Ci.nsIMutableArray) ||
+            aIID.equals(Ci.nsIArray) ||
+            aIID.equals(Ci.nsISupports))
+          return this;
+
+        throw Cr.NS_ERROR_NO_INTERFACE;
+      },
+
+      get length() {
+        return this._inner.length;
+      },
+
+      enumerate() {
+        return new ArrayEnumerator(this._inner);
+      },
+
+      appendElement(aHandlerApp, aWeak) {
+        this._inner.push(aHandlerApp);
+      },
+
+      removeElementAt(aIndex) {
+        this._removed.push(this._inner[aIndex]);
+        this._inner.splice(aIndex, 1);
+      },
+
+      queryElementAt(aIndex, aInterface) {
+        return this._inner[aIndex].QueryInterface(aInterface);
+      }
+    };
+
+    // 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;
+    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.
+    var webHandlers = this._converterSvc.getContentHandlers(this.type);
+    for (let webHandler of webHandlers)
+      this._possibleApplicationHandlers.appendElement(webHandler);
+
+    return this._possibleApplicationHandlers;
   },
 
-  async editKeyword(aEngine, aNewKeyword) {
-    let keyword = aNewKeyword.trim();
-    if (keyword) {
-      let eduplicate = false;
-      let dupName = "";
-
-      // Check for duplicates in Places keywords.
-      let bduplicate = !!(await PlacesUtils.keywords.fetch(keyword));
-
-      // Check for duplicates in changes we haven't committed yet
-      let engines = gEngineView._engineStore.engines;
-      let lc_keyword = keyword.toLocaleLowerCase();
-      for (let engine of engines) {
-        if (engine.alias &&
-            engine.alias.toLocaleLowerCase() == lc_keyword &&
-            engine.name != aEngine.name) {
-          eduplicate = true;
-          dupName = engine.name;
-          break;
-        }
+  __defaultApplicationHandler: undefined,
+  get _defaultApplicationHandler() {
+    if (typeof this.__defaultApplicationHandler != "undefined")
+      return this.__defaultApplicationHandler;
+
+    var defaultFeedReader = null;
+    if (AppConstants.HAVE_SHELL_SERVICE) {
+      try {
+        defaultFeedReader = this._shellSvc.defaultFeedReader;
+      } catch (ex) {
+        // no default reader or _shellSvc is null
       }
-
-      // Notify the user if they have chosen an existing engine/bookmark keyword
-      if (eduplicate || bduplicate) {
-        let strings = document.getElementById("engineManagerBundle");
-        let dtitle = strings.getString("duplicateTitle");
-        let bmsg = strings.getString("duplicateBookmarkMsg");
-        let emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
-
-        Services.prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
-        return false;
+    }
+
+    if (defaultFeedReader) {
+      let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+                       createInstance(Ci.nsIHandlerApp);
+      handlerApp.name = getFileDisplayName(defaultFeedReader);
+      handlerApp.QueryInterface(Ci.nsILocalHandlerApp);
+      handlerApp.executable = defaultFeedReader;
+
+      this.__defaultApplicationHandler = handlerApp;
+    } else {
+      this.__defaultApplicationHandler = null;
+    }
+
+    return this.__defaultApplicationHandler;
+  },
+
+  get hasDefaultHandler() {
+    if (AppConstants.HAVE_SHELL_SERVICE) {
+      try {
+        if (this._shellSvc.defaultFeedReader)
+          return true;
+      } catch (ex) {
+        // no default reader or _shellSvc is null
       }
     }
 
-    gEngineView._engineStore.changeEngine(aEngine, "alias", keyword);
-    gEngineView.invalidate();
-    return true;
+    return false;
+  },
+
+  get defaultDescription() {
+    if (this.hasDefaultHandler)
+      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) {
+
+      case "bookmarks":
+        return Ci.nsIHandlerInfo.handleInternally;
+
+      case "reader": {
+        let preferredApp = this.preferredApplicationHandler;
+        let defaultApp = this._defaultApplicationHandler;
+
+        // If we have a valid preferred app, return useSystemDefault if it's
+        // the default app; otherwise return useHelperApp.
+        if (gMainPane.isValidHandlerApp(preferredApp)) {
+          if (defaultApp && defaultApp.equals(preferredApp))
+            return Ci.nsIHandlerInfo.useSystemDefault;
+
+          return Ci.nsIHandlerInfo.useHelperApp;
+        }
+
+        // The pref is set to "reader", but we don't have a valid preferred app.
+        // What do we do now?  Not sure this is the best option (perhaps we
+        // should direct the user to the default app, if any), but for now let's
+        // direct the user to live bookmarks.
+        return Ci.nsIHandlerInfo.handleInternally;
+      }
+
+      // If the action is "ask", then alwaysAskBeforeHandling will override
+      // the action, so it doesn't matter what we say it is, it just has to be
+      // something that doesn't cause the controller to hide the type.
+      case "ask":
+      default:
+        return Ci.nsIHandlerInfo.handleInternally;
+    }
+  },
+
+  set preferredAction(aNewValue) {
+    switch (aNewValue) {
+
+      case Ci.nsIHandlerInfo.handleInternally:
+        this.element(this._prefSelectedReader).value = "bookmarks";
+        break;
+
+      case Ci.nsIHandlerInfo.useHelperApp:
+        this.element(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";
+        this.preferredApplicationHandler = this._defaultApplicationHandler;
+        break;
+    }
+  },
+
+  get alwaysAskBeforeHandling() {
+    return this.element(this._prefSelectedAction).value == "ask";
+  },
+
+  set alwaysAskBeforeHandling(aNewValue) {
+    if (aNewValue == true)
+      this.element(this._prefSelectedAction).value = "ask";
+    else
+      this.element(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.
+  _storingAction: false,
+
+
+  // nsIMIMEInfo
+
+  get primaryExtension() {
+    return "xml";
   },
 
-  saveOneClickEnginesList() {
-    let hiddenList = [];
-    for (let engine of gEngineView._engineStore.engines) {
-      if (!engine.shown)
-        hiddenList.push(engine.name);
+
+  // Storage
+
+  // 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);
+        var preferredAppFile = pref.value;
+        if (preferredAppFile) {
+          let preferredApp = getLocalHandlerApp(preferredAppFile);
+          if (app.equals(preferredApp))
+            pref.reset();
+        }
+      } else {
+        app.QueryInterface(Ci.nsIWebContentHandlerInfo);
+        this._converterSvc.removeContentHandler(app.contentType, app.uri);
+      }
     }
-    document.getElementById("browser.search.hiddenOneOffs").value =
-      hiddenList.join(",");
+    this._possibleApplicationHandlers._removed = [];
   },
 
-  setDefaultEngine() {
-    Services.search.currentEngine =
-      document.getElementById("defaultEngine").selectedItem.engine;
+
+  // Icons
+
+  get smallIcon() {
+    return this._smallIcon;
+  }
+
+};
+
+var feedHandlerInfo = {
+  __proto__: new FeedHandlerInfo(TYPE_MAYBE_FEED),
+  _prefSelectedApp: PREF_FEED_SELECTED_APP,
+  _prefSelectedWeb: PREF_FEED_SELECTED_WEB,
+  _prefSelectedAction: PREF_FEED_SELECTED_ACTION,
+  _prefSelectedReader: PREF_FEED_SELECTED_READER,
+  _smallIcon: "chrome://browser/skin/feeds/feedIcon16.png",
+  _appPrefLabel: "webFeed"
+}
+
+var videoFeedHandlerInfo = {
+  __proto__: new FeedHandlerInfo(TYPE_MAYBE_VIDEO_FEED),
+  _prefSelectedApp: PREF_VIDEO_FEED_SELECTED_APP,
+  _prefSelectedWeb: PREF_VIDEO_FEED_SELECTED_WEB,
+  _prefSelectedAction: PREF_VIDEO_FEED_SELECTED_ACTION,
+  _prefSelectedReader: PREF_VIDEO_FEED_SELECTED_READER,
+  _smallIcon: "chrome://browser/skin/feeds/videoFeedIcon16.png",
+  _appPrefLabel: "videoPodcastFeed"
+}
+
+var audioFeedHandlerInfo = {
+  __proto__: new FeedHandlerInfo(TYPE_MAYBE_AUDIO_FEED),
+  _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP,
+  _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB,
+  _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION,
+  _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER,
+  _smallIcon: "chrome://browser/skin/feeds/audioFeedIcon16.png",
+  _appPrefLabel: "audioPodcastFeed"
+}
+
+/**
+ * InternalHandlerInfoWrapper provides a basic mechanism to create an internal
+ * mime type handler that can be enabled/disabled in the applications preference
+ * menu.
+ */
+function InternalHandlerInfoWrapper(aMIMEType) {
+  var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+  var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
+
+  HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
+}
+
+InternalHandlerInfoWrapper.prototype = {
+  __proto__: HandlerInfoWrapper.prototype,
+
+  // Override store so we so we can notify any code listening for registration
+  // or unregistration of this handler.
+  store() {
+    HandlerInfoWrapper.prototype.store.call(this);
+    Services.obs.notifyObservers(null, this._handlerChanged);
+  },
+
+  get enabled() {
+    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  get description() {
+    return this.element("bundlePreferences").getString(this._appPrefLabel);
   }
 };
 
-function onDragEngineStart(event) {
-  var selectedIndex = gEngineView.selectedIndex;
-  var tree = document.getElementById("engineList");
-  var row = { }, col = { }, child = { };
-  tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, child);
-  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;
-  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);
-  gMainPane.showRestoreDefaults(someHidden);
-}
-EngineStore.prototype = {
-  _engines: null,
-  _defaultEngines: null,
-
-  get engines() {
-    return this._engines;
-  },
-  set engines(val) {
-    this._engines = val;
-    return val;
-  },
-
-  _getIndexForEngine(aEngine) {
-    return this._engines.indexOf(aEngine);
-  },
-
-  _getEngineByName(aName) {
-    return this._engines.find(engine => engine.name == aName);
-  },
-
-  _cloneEngine(aEngine) {
-    var clonedObj = {};
-    for (var i in aEngine)
-      clonedObj[i] = aEngine[i];
-    clonedObj.originalEngine = aEngine;
-    clonedObj.shown = this.hiddenList.indexOf(clonedObj.name) == -1;
-    return clonedObj;
-  },
-
-  // Callback for Array's some(). A thisObj must be passed to some()
-  _isSameEngine(aEngineClone) {
-    return aEngineClone.originalEngine == this.originalEngine;
-  },
-
-  addEngine(aEngine) {
-    this._engines.push(this._cloneEngine(aEngine));
+var pdfHandlerInfo = {
+  __proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
+  _handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
+  _appPrefLabel: "portableDocumentFormat",
+  get enabled() {
+    return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
   },
-
-  moveEngine(aEngine, aNewIndex) {
-    if (aNewIndex < 0 || aNewIndex > this._engines.length - 1)
-      throw new Error("ES_moveEngine: invalid aNewIndex!");
-    var index = this._getIndexForEngine(aEngine);
-    if (index == -1)
-      throw new Error("ES_moveEngine: invalid engine?");
-
-    if (index == aNewIndex)
-      return; // nothing to do
-
-    // Move the engine in our internal store
-    var removedEngine = this._engines.splice(index, 1)[0];
-    this._engines.splice(aNewIndex, 0, removedEngine);
-
-    Services.search.moveEngine(aEngine.originalEngine, aNewIndex);
-  },
-
-  removeEngine(aEngine) {
-    if (this._engines.length == 1) {
-      throw new Error("Cannot remove last engine!");
-    }
-
-    let engineName = aEngine.name;
-    let index = this._engines.findIndex(element => element.name == engineName);
-
-    if (index == -1)
-      throw new Error("invalid engine?");
-
-    let removedEngine = this._engines.splice(index, 1)[0];
-
-    if (this._defaultEngines.some(this._isSameEngine, removedEngine))
-      gMainPane.showRestoreDefaults(true);
-    gMainPane.buildDefaultEngineDropDown();
-    return index;
-  },
-
-  restoreDefaultEngines() {
-    var added = 0;
-
-    for (var i = 0; i < this._defaultEngines.length; ++i) {
-      var e = this._defaultEngines[i];
-
-      // If the engine is already in the list, just move it.
-      if (this._engines.some(this._isSameEngine, e)) {
-        this.moveEngine(this._getEngineByName(e.name), i);
-      } else {
-        // Otherwise, add it back to our internal store
-
-        // The search service removes the alias when an engine is hidden,
-        // so clear any alias we may have cached before unhiding the engine.
-        e.alias = "";
-
-        this._engines.splice(i, 0, e);
-        let engine = e.originalEngine;
-        engine.hidden = false;
-        Services.search.moveEngine(engine, i);
-        added++;
-      }
-    }
-    Services.search.resetToOriginalDefaultEngine();
-    gMainPane.showRestoreDefaults(false);
-    gMainPane.buildDefaultEngineDropDown();
-    return added;
-  },
-
-  changeEngine(aEngine, aProp, aNewValue) {
-    var index = this._getIndexForEngine(aEngine);
-    if (index == -1)
-      throw new Error("invalid engine?");
-
-    this._engines[index][aProp] = aNewValue;
-    aEngine.originalEngine[aProp] = aNewValue;
-  },
-
-  reloadIcons() {
-    this._engines.forEach(function(e) {
-      e.uri = e.originalEngine.uri;
-    });
-  }
 };
-
-function EngineView(aEngineStore) {
-  this._engineStore = aEngineStore;
-}
-EngineView.prototype = {
-  _engineStore: null,
-  tree: null,
-
-  get lastIndex() {
-    return this.rowCount - 1;
-  },
-  get selectedIndex() {
-    var seln = this.selection;
-    if (seln.getRangeCount() > 0) {
-      var min = {};
-      seln.getRangeAt(0, min, {});
-      return min.value;
-    }
-    return -1;
-  },
-  get selectedEngine() {
-    return this._engineStore.engines[this.selectedIndex];
-  },
-
-  // Helpers
-  rowCountChanged(index, count) {
-    this.tree.rowCountChanged(index, count);
-  },
-
-  invalidate() {
-    this.tree.invalidate();
-  },
-
-  ensureRowIsVisible(index) {
-    this.tree.ensureRowIsVisible(index);
-  },
-
-  getSourceIndexFromDrag(dataTransfer) {
-    return parseInt(dataTransfer.getData(ENGINE_FLAVOR));
-  },
-
-  isCheckBox(index, column) {
-    return column.id == "engineShown";
-  },
-
-  isEngineSelectedAndRemovable() {
-    return this.selectedIndex != -1 && this.lastIndex != 0;
-  },
-
-  // nsITreeView
-  get rowCount() {
-    return this._engineStore.engines.length;
-  },
-
-  getImageSrc(index, column) {
-    if (column.id == "engineName") {
-      if (this._engineStore.engines[index].iconURI)
-        return this._engineStore.engines[index].iconURI.spec;
-
-      if (window.devicePixelRatio > 1)
-        return "chrome://browser/skin/search-engine-placeholder@2x.png";
-      return "chrome://browser/skin/search-engine-placeholder.png";
-    }
-
-    return "";
-  },
-
-  getCellText(index, column) {
-    if (column.id == "engineName")
-      return this._engineStore.engines[index].name;
-    else if (column.id == "engineKeyword")
-      return this._engineStore.engines[index].alias;
-    return "";
-  },
-
-  setTree(tree) {
-    this.tree = tree;
-  },
-
-  canDrop(targetIndex, orientation, dataTransfer) {
-    var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
-    return (sourceIndex != -1 &&
-            sourceIndex != targetIndex &&
-            sourceIndex != targetIndex + orientation);
-  },
-
-  drop(dropIndex, orientation, dataTransfer) {
-    var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
-    var sourceEngine = this._engineStore.engines[sourceIndex];
-
-    const nsITreeView = Components.interfaces.nsITreeView;
-    if (dropIndex > sourceIndex) {
-      if (orientation == nsITreeView.DROP_BEFORE)
-        dropIndex--;
-    } else if (orientation == nsITreeView.DROP_AFTER) {
-      dropIndex++;
-    }
-
-    this._engineStore.moveEngine(sourceEngine, dropIndex);
-    gMainPane.showRestoreDefaults(true);
-    gMainPane.buildDefaultEngineDropDown();
-
-    // Redraw, and adjust selection
-    this.invalidate();
-    this.selection.select(dropIndex);
-  },
-
-  selection: null,
-  getRowProperties(index) { return ""; },
-  getCellProperties(index, column) { return ""; },
-  getColumnProperties(column) { return ""; },
-  isContainer(index) { return false; },
-  isContainerOpen(index) { return false; },
-  isContainerEmpty(index) { return false; },
-  isSeparator(index) { return false; },
-  isSorted(index) { return false; },
-  getParentIndex(index) { return -1; },
-  hasNextSibling(parentIndex, index) { return false; },
-  getLevel(index) { return 0; },
-  getProgressMode(index, column) { },
-  getCellValue(index, column) {
-    if (column.id == "engineShown")
-      return this._engineStore.engines[index].shown;
-    return undefined;
-  },
-  toggleOpenState(index) { },
-  cycleHeader(column) { },
-  selectionChanged() { },
-  cycleCell(row, column) { },
-  isEditable(index, column) { return column.id != "engineName"; },
-  isSelectable(index, column) { return false; },
-  setCellValue(index, column, value) {
-    if (column.id == "engineShown") {
-      this._engineStore.engines[index].shown = value == "true";
-      gEngineView.invalidate();
-      gMainPane.saveOneClickEnginesList();
-    }
-  },
-  setCellText(index, column, value) {
-    if (column.id == "engineKeyword") {
-      gMainPane.editKeyword(this._engineStore.engines[index], value)
-                 .then(valid => {
-        if (!valid)
-          document.getElementById("engineList").startEditing(index, column);
-      });
-    }
-  },
-  performAction(action) { },
-  performActionOnRow(action, index) { },
-  performActionOnCell(action, index, column) { }
-};
--- a/browser/components/preferences/in-content-new/main.xul
+++ b/browser/components/preferences/in-content-new/main.xul
@@ -2,21 +2,23 @@
 # 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/.
 
 <!-- General panel -->
 
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content-new/main.js"/>
 
+#ifdef MOZ_UPDATER
+  <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="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
-
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences.properties"/>
 
 <preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
 
 #ifdef E10S_TESTING_ONLY
     <preference id="browser.tabs.remote.autostart"
                 name="browser.tabs.remote.autostart"
                 type="bool"/>
@@ -55,29 +57,16 @@
     <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"/>
 
-    <!-- Search Engine -->
-    <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"/>
-
     <!-- Downloads -->
     <preference id="browser.download.useDownloadDir"
                 name="browser.download.useDownloadDir"
                 type="bool"/>
 
     <preference id="browser.download.folderList"
                 name="browser.download.folderList"
                 type="int"/>
@@ -194,20 +183,97 @@
   <preference id="dom.ipc.processCount"
               name="dom.ipc.processCount"
               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="header-general"
-      class="header"
+<hbox id="generalCategory"
+      class="subcategory"
       hidden="true"
       data-category="paneGeneral">
   <label class="header-name" flex="1">&paneGeneral.title;</label>
 </hbox>
 
 <!-- Startup -->
 <groupbox id="startupGroup"
           data-category="paneGeneral"
@@ -237,17 +303,17 @@
   <vbox id="defaultBrowserBox">
     <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
               label="&alwaysCheckDefault2.label;" accesskey="&alwaysCheckDefault2.accesskey;"/>
     <deck id="setDefaultPane">
       <hbox align="center" class="indent">
         <label id="isNotDefaultLabel" flex="1">&isNotDefault.label;</label>
         <button id="setDefaultButton"
                 class="accessory-button"
-                label="&setAsMyDefaultBrowser2.label;" accesskey="&setAsMyDefaultBrowser2.accesskey;"
+                label="&setAsMyDefaultBrowser3.label;" accesskey="&setAsMyDefaultBrowser3.accesskey;"
                 preference="pref.general.disable_button.default_browser"/>
       </hbox>
       <hbox align="center" class="indent">
         <label id="isDefaultLabel" flex="1">&isDefault.label;</label>
       </hbox>
     </deck>
     <separator class="thin"/>
   </vbox>
@@ -314,74 +380,18 @@
                 label="&restoreDefault.label;"
                 accesskey="&restoreDefault.accesskey;"
                 preference="pref.browser.homepage.disable_button.restore_default"/>
       </html:td>
     </html:tr>
   </html:table>
 </groupbox>
 
-<!-- Default Search Engine -->
-<groupbox id="defaultEngineGroup" data-category="paneGeneral" data-subcategory="search">
   <caption><label>&defaultSearchEngine.label;</label></caption>
-  <label>&chooseYourDefaultSearchEngine.label;</label>
-  <box align="start">
-    <menulist id="defaultEngine">
-      <menupopup/>
-    </menulist>
-  </box>
-  <checkbox id="suggestionsInSearchFieldsCheckbox"
-            label="&provideSearchSuggestions.label;"
-            accesskey="&provideSearchSuggestions.accesskey;"
-            preference="browser.search.suggest.enabled"/>
-  <vbox class="indent">
-    <checkbox id="urlBarSuggestion" label="&showURLBarSuggestions.label;"
-              accesskey="&showURLBarSuggestions.accesskey;"
-              preference="browser.urlbar.suggest.searches"/>
-    <hbox id="urlBarSuggestionPermanentPBLabel"
-          align="center" class="indent">
-      <label flex="1">&urlBarSuggestionsPermanentPB.label;</label>
-    </hbox>
-  </vbox>
-</groupbox>
-
-<groupbox id="oneClickSearchProvidersGroup" data-category="paneGeneral" data-subcategory="search">
   <caption><label>&oneClickSearchEngines.label;</label></caption>
-  <label>&chooseWhichOneToDisplay.label;</label>
-
-  <tree id="engineList" flex="1" rows="8" hidecolumnpicker="true" editable="true"
-        seltype="single" allowunderflowscroll="true">
-    <treechildren id="engineChildren" flex="1"/>
-    <treecols>
-      <treecol id="engineShown" type="checkbox" editable="true" sortable="false"/>
-      <treecol id="engineName" flex="4" label="&engineNameColumn.label;" sortable="false"/>
-      <treecol id="engineKeyword" flex="1" label="&engineKeywordColumn.label;" editable="true"
-                sortable="false"/>
-    </treecols>
-  </tree>
-
-  <hbox>
-    <button id="restoreDefaultSearchEngines"
-            label="&restoreDefaultSearchEngines.label;"
-            accesskey="&restoreDefaultSearchEngines.accesskey;"/>
-    <spacer flex="1"/>
-    <button id="removeEngineButton"
-            class="searchEngineAction accessory-button"
-            label="&removeEngine.label;"
-            accesskey="&removeEngine.accesskey;"
-            disabled="true"/>
-  </hbox>
-
-  <separator class="thin"/>
-
-  <hbox id="addEnginesBox" pack="start">
-    <label id="addEngines" class="text-link">&addMoreSearchEngines2.label;</label>
-  </hbox>
-</groupbox>
-
 <!-- Tab preferences -->
 <groupbox data-category="paneGeneral"
           hidden="true">
     <caption><label>&tabsGroup.label;</label></caption>
 
     <checkbox id="ctrlTabRecentlyUsedOrder" label="&ctrlTabRecentlyUsedOrder.label;"
               accesskey="&ctrlTabRecentlyUsedOrder.accesskey;"
               preference="browser.ctrlTab.previews"/>
@@ -404,90 +414,43 @@
               accesskey="&switchLinksToNewTabs.accesskey;"
               preference="browser.tabs.loadInBackground"/>
 
 #ifdef XP_WIN
     <checkbox id="showTabsInTaskbar" label="&showTabsInTaskbar.label;"
               accesskey="&showTabsInTaskbar.accesskey;"
               preference="browser.taskbar.previews.enable"/>
 #endif
-</groupbox>
 
-<!-- Accessibility -->
-<groupbox data-category="paneGeneral" id="accessibilityGroup">
-  <caption><label>&accessibility.label;</label></caption>
-
-#ifdef XP_WIN
-  <checkbox id="useOnScreenKeyboard"
-            hidden="true"
-            label="&useOnScreenKeyboard.label;"
-            accesskey="&useOnScreenKeyboard.accesskey;"
-            preference="ui.osk.enabled"/>
-#endif
-  <checkbox id="useCursorNavigation"
-            label="&useCursorNavigation.label;"
-            accesskey="&useCursorNavigation.accesskey;"
-            preference="accessibility.browsewithcaret"/>
-  <checkbox id="searchStartTyping"
-            label="&searchOnStartTyping.label;"
-            accesskey="&searchOnStartTyping.accesskey;"
-            preference="accessibility.typeaheadfind"/>
-  <checkbox id="blockAutoRefresh"
-            label="&blockAutoReload.label;"
-            accesskey="&blockAutoReload.accesskey;"
-            preference="accessibility.blockautorefresh"/>
+    <hbox id="browserContainersbox" hidden="true" align="center">
+      <checkbox id="browserContainersCheckbox"
+                label="&browserContainersEnabled.label;"
+                accesskey="&browserContainersEnabled.accesskey;"
+                preference="privacy.userContext.enabled"
+                onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
+      <label id="browserContainersLearnMore" class="learnMore text-link">
+        &browserContainersLearnMore.label;
+      </label>
+      <spacer flex="1"/>
+      <button id="browserContainersSettings"
+              class="accessory-button"
+              label="&browserContainersSettings.label;"
+              accesskey="&browserContainersSettings.accesskey;"
+              searchkeywords="&addButton.label;
+                              &preferencesButton.label;
+                              &removeButton.label;"/>
+    </hbox>
 </groupbox>
 
-<!-- Languages -->
-<groupbox id="languagesGroup" data-category="paneGeneral" hidden="true">
-  <caption><label>&languages.label;</label></caption>
-
-  <hbox id="languagesBox" align="center">
-    <description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
-    <button id="chooseLanguage"
-            class="accessory-button"
-            label="&chooseButton.label;"
-            accesskey="&chooseButton.accesskey;"
-            searchkeywords="&languages.customize.Header;
-                            &languages.customize.description;
-                            &languages.customize.moveUp.label;
-                            &languages.customize.moveDown.label;
-                            &languages.customize.deleteButton.label;
-                            &languages.customize.selectLanguage.label;
-                            &languages.customize.addButton.label;"/>
-  </hbox>
-
-  <hbox id="translationBox" hidden="true">
-    <hbox align="center" flex="1">
-      <checkbox id="translate" preference="browser.translation.detectLanguage"
-                label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
-                onsyncfrompreference="return gMainPane.updateButtons('translateButton',
-                                              'browser.translation.detectLanguage');"/>
-      <hbox id="bingAttribution" hidden="true">
-        <label>&translation.options.attribution.beforeLogo;</label>
-        <separator orient="vertical" class="thin"/>
-        <image id="translationAttributionImage" aria-label="Microsoft Translator"
-               src="chrome://browser/content/microsoft-translator-attribution.png"/>
-        <separator orient="vertical" class="thin"/>
-        <label>&translation.options.attribution.afterLogo;</label>
-      </hbox>
-    </hbox>
-    <button id="translateButton"
-            class="accessory-button"
-            label="&translateExceptions.label;"
-            accesskey="&translateExceptions.accesskey;"/>
-  </hbox>
-  <checkbox id="checkSpelling"
-          label="&checkUserSpelling.label;"
-          accesskey="&checkUserSpelling.accesskey;"
-          onsyncfrompreference="return gMainPane.readCheckSpelling();"
-          onsynctopreference="return gMainPane.writeCheckSpelling();"
-          preference="layout.spellcheckDefault"/>
-</groupbox>
-
+<hbox id="languageAndAppearanceCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&languageAndAppearance.label;</label>
+</hbox>
 
 <!-- Fonts and Colors -->
 <groupbox id="fontsGroup" data-category="paneGeneral" hidden="true">
   <caption><label>&fontsAndColors.label;</label></caption>
 
   <vbox>
     <hbox id="fontSettings">
       <hbox align="center">
@@ -605,34 +568,320 @@
                               &useSystemColors.label;
                               &underlineLinks.label;
                               &linkColor.label;
                               &visitedLinkColor.label;"/>
     </hbox>
   </vbox>
 </groupbox>
 
-<!-- Browsing -->
-<groupbox id="browsingGroup" data-category="paneGeneral">
-  <caption><label>&browsing.label;</label></caption>
+<!-- Languages -->
+<groupbox id="languagesGroup" data-category="paneGeneral" hidden="true">
+  <caption><label>&language2.label;</label></caption>
+
+  <hbox id="languagesBox" align="center">
+    <description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
+    <button id="chooseLanguage"
+            class="accessory-button"
+            label="&chooseButton.label;"
+            accesskey="&chooseButton.accesskey;"
+            searchkeywords="&languages.customize.Header;
+                            &languages.customize.description;
+                            &languages.customize.moveUp.label;
+                            &languages.customize.moveDown.label;
+                            &languages.customize.deleteButton.label;
+                            &languages.customize.selectLanguage.label;
+                            &languages.customize.addButton.label;"/>
+  </hbox>
+
+  <hbox id="translationBox" hidden="true">
+    <hbox align="center" flex="1">
+      <checkbox id="translate" preference="browser.translation.detectLanguage"
+                label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
+                onsyncfrompreference="return gMainPane.updateButtons('translateButton',
+                                              'browser.translation.detectLanguage');"/>
+      <hbox id="bingAttribution" hidden="true">
+        <label>&translation.options.attribution.beforeLogo;</label>
+        <separator orient="vertical" class="thin"/>
+        <image id="translationAttributionImage" aria-label="Microsoft Translator"
+               src="chrome://browser/content/microsoft-translator-attribution.png"/>
+        <separator orient="vertical" class="thin"/>
+        <label>&translation.options.attribution.afterLogo;</label>
+      </hbox>
+    </hbox>
+    <button id="translateButton"
+            class="accessory-button"
+            label="&translateExceptions.label;"
+            accesskey="&translateExceptions.accesskey;"/>
+  </hbox>
+  <checkbox id="checkSpelling"
+          label="&checkUserSpelling.label;"
+          accesskey="&checkUserSpelling.accesskey;"
+          onsyncfrompreference="return gMainPane.readCheckSpelling();"
+          onsynctopreference="return gMainPane.writeCheckSpelling();"
+          preference="layout.spellcheckDefault"/>
+</groupbox>
+
+<!-- Files and Applications -->
+<keyset data-category="paneGeneral">
+  <!-- Ctrl+f/k focus the search box in the Applications pane.
+       These <key>s have oncommand attributes because of bug 371900. -->
+  <key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
+  <key key="&focusSearch2.key;" modifiers="accel" id="focusSearch2" oncommand=";"/>
+</keyset>
+
+<hbox id="filesAndApplicationsCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&filesAndApplications.label;</label>
+</hbox>
+
+<!--Downloads-->
+<groupbox id="downloadsGroup" data-category="paneGeneral" hidden="true">
+  <caption><label>&downloads.label;</label></caption>
+
+  <radiogroup id="saveWhere"
+              preference="browser.download.useDownloadDir"
+              onsyncfrompreference="return gMainPane.readUseDownloadDir();">
+    <hbox id="saveToRow">
+      <radio id="saveTo"
+            value="true"
+            label="&saveTo.label;"
+            accesskey="&saveTo.accesskey;"
+            aria-labelledby="saveTo downloadFolder"/>
+      <filefield id="downloadFolder"
+                flex="1"
+                preference="browser.download.folderList"
+                preference-editable="true"
+                aria-labelledby="saveTo"
+                onsyncfrompreference="return gMainPane.displayDownloadDirPref();"/>
+      <button id="chooseFolder"
+#ifdef XP_MACOSX
+              accesskey="&chooseFolderMac.accesskey;"
+              label="&chooseFolderMac.label;"
+#else
+              accesskey="&chooseFolderWin.accesskey;"
+              label="&chooseFolderWin.label;"
+#endif
+      />
+    </hbox>
+    <radio id="alwaysAsk"
+          value="false"
+          label="&alwaysAskWhere.label;"
+          accesskey="&alwaysAskWhere.accesskey;"/>
+  </radiogroup>
+</groupbox>
+
+<groupbox id="applicationsGroup" data-category="paneGeneral" hidden="true">
+  <caption><label>&applications.label;</label></caption>
+  <description>&applications.description;</description>
+  <textbox id="filter" flex="1"
+           type="search"
+           placeholder="&filter2.emptytext;"
+           aria-controls="handlersView"/>
+
+  <richlistbox id="handlersView" orient="vertical" persist="lastSelectedType"
+               preference="pref.downloads.disable_button.edit_actions"
+               flex="1">
+    <listheader equalsize="always">
+        <treecol id="typeColumn" label="&typeColumn.label;" value="type"
+                 accesskey="&typeColumn.accesskey;" persist="sortDirection"
+                 flex="1" sortDirection="ascending"/>
+        <treecol id="actionColumn" label="&actionColumn2.label;" value="action"
+                 accesskey="&actionColumn2.accesskey;" persist="sortDirection"
+                 flex="1"/>
+    </listheader>
+  </richlistbox>
+</groupbox>
+
+
+<!-- DRM Content -->
+<groupbox id="drmGroup" data-category="paneGeneral" hidden="true">
+  <caption><label>&drmContent2.label;</label></caption>
+  <grid id="contentGrid2">
+    <columns>
+      <column flex="1"/>
+      <column/>
+    </columns>
+    <rows id="contentRows-2">
+      <row id="playDRMContentRow">
+        <hbox align="center">
+          <checkbox id="playDRMContent" preference="media.eme.enabled"
+                    label="&playDRMContent2.label;" accesskey="&playDRMContent2.accesskey;"/>
+          <label id="playDRMContentLink" class="learnMore text-link">
+            &playDRMContent.learnMore.label;
+          </label>
+        </hbox>
+      </row>
+    </rows>
+  </grid>
+</groupbox>
+
+#ifdef HAVE_SHELL_SERVICE
+  <stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
+  <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
+#endif
 
-  <checkbox id="useAutoScroll"
-            label="&useAutoScroll.label;"
-            accesskey="&useAutoScroll.accesskey;"
-            preference="general.autoScroll"/>
-  <checkbox id="useSmoothScrolling"
-            label="&useSmoothScrolling.label;"
-            accesskey="&useSmoothScrolling.accesskey;"
-            preference="general.smoothScroll"/>
+<hbox id="updatesCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&updateApplication.label;</label>
+</hbox>
+
+<!-- Update -->
+<groupbox id="updateApp" data-category="paneGeneral" hidden="true">
+  <hbox align="start">
+    <vbox flex="1">
+      <description>
+        &updateApplication.version.pre;<label id="version"/>&updateApplication.version.post;
+        <label id="releasenotes" class="learnMore text-link" hidden="true">&releaseNotes.link;</label>
+      </description>
+      <description id="distribution" class="text-blurb" hidden="true"/>
+      <description id="distributionId" class="text-blurb" hidden="true"/>
+    </vbox>
+#ifdef MOZ_UPDATER
+    <spacer flex="1"/>
+    <vbox>
+      <button id="showUpdateHistory"
+              class="accessory-button"
+              label="&updateHistory2.label;"
+              accesskey="&updateHistory2.accesskey;"
+              preference="app.update.disable_button.showUpdateHistory"
+              searchkeywords="&history.title; &history.intro;"/>
+    </vbox>
+#endif
+  </hbox>
+#ifdef MOZ_UPDATER
+  <vbox id="updateBox">
+    <deck id="updateDeck" orient="vertical">
+      <hbox id="checkForUpdates" align="center">
+        <spacer flex="1"/>
+        <button id="checkForUpdatesButton"
+                label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                oncommand="gAppUpdater.checkForUpdates();"/>
+      </hbox>
+      <hbox id="downloadAndInstall" align="center">
+        <spacer flex="1"/>
+        <button id="downloadAndInstallButton"
+                oncommand="gAppUpdater.startDownload();"/>
+                <!-- label and accesskey will be filled by JS -->
+      </hbox>
+      <hbox id="apply" align="center">
+        <spacer flex="1"/>
+        <button id="updateButton"
+                label="&update.updateButton.label3;"
+                accesskey="&update.updateButton.accesskey;"
+                oncommand="gAppUpdater.buttonRestartAfterDownload();"/>
+      </hbox>
+      <hbox id="checkingForUpdates" align="center">
+        <image class="update-throbber"/><label>&update.checkingForUpdates;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+      <hbox id="downloading" align="center">
+        <image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
+      </hbox>
+      <hbox id="applying" align="center">
+        <image class="update-throbber"/><label>&update.applying;</label>
+      </hbox>
+      <hbox id="downloadFailed" align="center">
+        <label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                oncommand="gAppUpdater.checkForUpdates();"/>
+      </hbox>
+      <hbox id="adminDisabled" align="center">
+        <label>&update.adminDisabled;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+      <hbox id="noUpdatesFound" align="center">
+        <label>&update.noUpdatesFound;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                oncommand="gAppUpdater.checkForUpdates();"/>
+      </hbox>
+      <hbox id="otherInstanceHandlingUpdates" align="center">
+        <label>&update.otherInstanceHandlingUpdates;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+      <hbox id="manualUpdate" align="center">
+        <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+      <hbox id="unsupportedSystem" align="center">
+        <label>&update.unsupported.start;</label><label id="unsupportedLink" class="text-link">&update.unsupported.linkText;</label><label>&update.unsupported.end;</label>
+        <spacer flex="1"/>
+        <button label="&update.checkForUpdatesButton.label;"
+                accesskey="&update.checkForUpdatesButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+      <hbox id="restarting" align="center">
+        <image class="update-throbber"/><label>&update.restarting;</label>
+        <spacer flex="1"/>
+        <button label="&update.updateButton.label3;"
+                accesskey="&update.updateButton.accesskey;"
+                disabled="true"/>
+      </hbox>
+    </deck>
+  </vbox>
+#endif
+
+  <separator/>
+#ifdef MOZ_UPDATER
+  <description>&updateApplication.description;</description>
+  <radiogroup id="updateRadioGroup">
+    <radio id="autoDesktop"
+           value="auto"
+           label="&updateAuto2.label;"
+           accesskey="&updateAuto2.accesskey;"/>
+    <radio value="checkOnly"
+          label="&updateCheckChoose2.label;"
+          accesskey="&updateCheckChoose2.accesskey;"/>
+    <radio value="manual"
+          label="&updateManual2.label;"
+          accesskey="&updateManual2.accesskey;"/>
+  </radiogroup>
+#ifdef MOZ_MAINTENANCE_SERVICE
+  <checkbox id="useService"
+            label="&useService.label;"
+            accesskey="&useService.accesskey;"
+            preference="app.update.service.enabled"/>
+#endif
+#endif
+  <checkbox id="enableSearchUpdate"
+            label="&enableSearchUpdate2.label;"
+            accesskey="&enableSearchUpdate2.accesskey;"
+            preference="browser.search.update"/>
 </groupbox>
 
+<hbox id="performanceCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&performance.label;</label>
+</hbox>
+
 <!-- Performance -->
 <groupbox id="performanceGroup" data-category="paneGeneral" hidden="true">
-  <caption><label>&performance.label;</label></caption>
-
   <hbox align="center">
     <checkbox id="useRecommendedPerformanceSettings"
               label="&useRecommendedPerformanceSettings2.label;"
               accesskey="&useRecommendedPerformanceSettings2.accesskey;"
               preference="browser.preferences.defaultPerformanceSettings.enabled"/>
     <label id="performanceSettingsLearnMore" class="learnMore text-link">&performanceSettingsLearnMore.label;</label>
   </hbox>
   <description class="indent">&useRecommendedPerformanceSettings2.description;</description>
@@ -655,8 +904,80 @@
           <menuitem label="7" value="7"/>
         </menupopup>
       </menulist>
     </hbox>
     <description id="contentProcessCountEnabledDescription">&limitContentProcessOption.description;</description>
     <description id="contentProcessCountDisabledDescription">&limitContentProcessOption.disabledDescription;<label class="text-link" href="https://wiki.mozilla.org/Electrolysis">&limitContentProcessOption.disabledDescriptionLink;</label></description>
   </vbox>
 </groupbox>
+
+<hbox id="browsingCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&browsing.label;</label>
+</hbox>
+
+<!-- Browsing -->
+<groupbox id="browsingGroup" data-category="paneGeneral" hidden="true">
+  <checkbox id="useAutoScroll"
+            label="&useAutoScroll.label;"
+            accesskey="&useAutoScroll.accesskey;"
+            preference="general.autoScroll"/>
+  <checkbox id="useSmoothScrolling"
+            label="&useSmoothScrolling.label;"
+            accesskey="&useSmoothScrolling.accesskey;"
+            preference="general.smoothScroll"/>
+
+#ifdef XP_WIN
+  <checkbox id="useOnScreenKeyboard"
+            hidden="true"
+            label="&useOnScreenKeyboard.label;"
+            accesskey="&useOnScreenKeyboard.accesskey;"
+            preference="ui.osk.enabled"/>
+#endif
+  <checkbox id="useCursorNavigation"
+            label="&useCursorNavigation.label;"
+            accesskey="&useCursorNavigation.accesskey;"
+            preference="accessibility.browsewithcaret"/>
+  <checkbox id="searchStartTyping"
+            label="&searchOnStartTyping.label;"
+            accesskey="&searchOnStartTyping.accesskey;"
+            preference="accessibility.typeaheadfind"/>
+</groupbox>
+
+<hbox id="networkProxyCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="paneGeneral">
+  <label class="header-name" flex="1">&networkProxy.label;</label>
+</hbox>
+
+<!-- Network Proxy-->
+<groupbox id="connectionGroup" data-category="paneGeneral" hidden="true">
+  <hbox align="center">
+    <description flex="1" control="connectionSettings">&connectionDesc.label;</description>
+    <button id="connectionSettings"
+            class="accessory-button"
+            icon="network"
+            label="&connectionSettings.label;"
+            accesskey="&connectionSettings.accesskey;"
+            searchkeywords="&connectionsDialog.title;
+                            &noProxyTypeRadio.label;
+                            &WPADTypeRadio.label;
+                            &systemTypeRadio.label;
+                            &manualTypeRadio.label;
+                            &http.label;
+                            &ssl.label;
+                            &ftp.label;
+                            &socks.label;
+                            &socks4.label;
+                            &socks5.label;
+                            &noproxy.label;
+                            &noproxyExplain.label;
+                            &shareproxy.label;
+                            &autoTypeRadio.label;
+                            &reload.label;
+                            &autologinproxy.label;
+                            &socksRemoteDNS.label2;"/>
+  </hbox>
+</groupbox>
--- a/browser/components/preferences/in-content-new/preferences.js
+++ b/browser/components/preferences/in-content-new/preferences.js
@@ -1,19 +1,18 @@
 /* - 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 the files imported by the .xul files.
 /* import-globals-from subdialogs.js */
-/* import-globals-from advanced.js */
 /* import-globals-from main.js */
+/* import-globals-from search.js */
 /* import-globals-from containers.js */
 /* import-globals-from privacy.js */
-/* import-globals-from applications.js */
 /* import-globals-from sync.js */
 /* import-globals-from findInPage.js */
 /* import-globals-from ../../../base/content/utilityOverlay.js */
 
 "use strict";
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
@@ -50,20 +49,19 @@ function register_module(categoryName, c
 
 document.addEventListener("DOMContentLoaded", init_all, {once: true});
 
 function init_all() {
   document.documentElement.instantApply = true;
 
   gSubDialog.init();
   register_module("paneGeneral", gMainPane);
+  register_module("paneSearch", gSearchPane);
   register_module("panePrivacy", gPrivacyPane);
   register_module("paneContainers", gContainersPane);
-  register_module("paneAdvanced", gAdvancedPane);
-  register_module("paneApplications", gApplicationsPane);
   register_module("paneSync", gSyncPane);
   register_module("paneSearchResults", gSearchResultsPane);
   gSearchResultsPane.init();
 
   let categories = document.getElementById("categories");
   categories.addEventListener("select", event => gotoPref(event.target.value));
 
   document.documentElement.addEventListener("keydown", function(event) {
@@ -339,8 +337,19 @@ function confirmRestartPrompt(aRestartTo
     Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
                                   "restart");
     if (cancelQuit.data) {
       buttonIndex = CONFIRM_RESTART_PROMPT_CANCEL;
     }
   }
   return buttonIndex;
 }
+
+// This function is used to append search keywords found
+// in the related subdialog to the button that will activate the subdialog.
+function appendSearchKeywords(aId, keywords) {
+  let element = document.getElementById(aId);
+  let searchKeywords = element.getAttribute("searchkeywords");
+  if (searchKeywords) {
+    keywords.push(searchKeywords);
+  }
+  element.setAttribute("searchkeywords", keywords.join(" "));
+}
--- a/browser/components/preferences/in-content-new/preferences.xul
+++ b/browser/components/preferences/in-content-new/preferences.xul
@@ -139,84 +139,72 @@
                     value="paneGeneral"
                     helpTopic="prefs-main"
                     tooltiptext="&paneGeneral.title;"
                     align="center">
         <image class="category-icon"/>
         <label class="category-name" flex="1">&paneGeneral.title;</label>
       </richlistitem>
 
-      <richlistitem id="category-application"
+      <richlistitem id="category-search"
                     class="category"
-                    value="paneApplications"
-                    helpTopic="prefs-applications"
-                    tooltiptext="&paneFilesApplications.title;"
+                    value="paneSearch"
+                    helpTopic="prefs-search"
+                    tooltiptext="&paneSearch.title;"
                     align="center">
         <image class="category-icon"/>
-        <label class="category-name" flex="1">&paneFilesApplications.title;</label>
+        <label class="category-name" flex="1">&paneSearch.title;</label>
       </richlistitem>
 
       <richlistitem id="category-containers"
                     class="category"
                     value="paneContainers"
                     helpTopic="prefs-containers"
                     hidden="true"/>
 
-      <richlistitem id="category-sync"
-                    class="category"
-                    value="paneSync"
-                    helpTopic="prefs-weave"
-                    tooltiptext="&paneSync1.title;"
-                    align="center">
-        <image class="category-icon"/>
-        <label class="category-name" flex="1">&paneSync1.title;</label>
-      </richlistitem>
-
       <richlistitem id="category-privacy"
                     class="category"
                     value="panePrivacy"
                     helpTopic="prefs-privacy"
                     tooltiptext="&panePrivacySecurity.title;"
                     align="center">
         <image class="category-icon"/>
         <label class="category-name" flex="1">&panePrivacySecurity.title;</label>
       </richlistitem>
 
-      <richlistitem id="category-advanced"
+      <richlistitem id="category-sync"
                     class="category"
-                    value="paneAdvanced"
-                    helpTopic="prefs-advanced-general"
-                    tooltiptext="&paneUpdates.title;"
+                    value="paneSync"
+                    helpTopic="prefs-weave"
+                    tooltiptext="&paneSync1.title;"
                     align="center">
         <image class="category-icon"/>
-        <label class="category-name" flex="1">&paneUpdates.title;</label>
+        <label class="category-name" flex="1">&paneSync1.title;</label>
       </richlistitem>
     </richlistbox>
 
     <keyset>
       <!-- Disable the findbar because it doesn't work properly.
            Remove this keyset once bug 1094240 ("disablefastfind" attribute
            broken in e10s mode) is fixed. -->
       <key key="&focusSearch1.key;" modifiers="accel" id="focusSearch1" oncommand=";"/>
     </keyset>
 
     <html:a class="help-button" target="_blank" aria-label="&helpButton2.label;">&helpButton2.label;</html:a>
 
     <vbox class="main-content" flex="1">
       <hbox pack="end">
-        <textbox type="search" id="searchInput" placeholder="&searchInput.label;" hidden="true"
-                 clickSelectsAll="true"/>
+        <textbox type="search" id="searchInput" hidden="true" clickSelectsAll="true"/>
       </hbox>
       <prefpane id="mainPrefPane">
 #include searchResults.xul
 #include main.xul
+#include search.xul
 #include privacy.xul
 #include containers.xul
-#include advanced.xul
-#include applications.xul
 #include sync.xul
       </prefpane>
     </vbox>
   </hbox>
 
   <stack id="dialogStack" hidden="true"/>
   <vbox id="dialogTemplate" class="dialogOverlay" align="center" pack="center" topmost="true" hidden="true">
     <groupbox class="dialogBox"
--- a/browser/components/preferences/in-content-new/privacy.js
+++ b/browser/components/preferences/in-content-new/privacy.js
@@ -1,16 +1,18 @@
 /* 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 preferences.js */
 
 Components.utils.import("resource://gre/modules/AppConstants.jsm");
 Components.utils.import("resource://gre/modules/PluralForm.jsm");
+Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
+Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
                                   "resource://gre/modules/ContextualIdentityService.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
                                   "resource://gre/modules/LoginHelper.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SiteDataManager",
@@ -80,98 +82,33 @@ var gPrivacyPane = {
    * Initialize autocomplete to ensure prefs are in sync.
    */
   _initAutocomplete() {
     Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
               .getService(Components.interfaces.mozIPlacesAutoComplete);
   },
 
   /**
-   * Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
-   */
-  _initBrowserContainers() {
-    if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
-      // The browserContainersGroup element has its own internal padding that
-      // is visible even if the browserContainersbox is visible, so hide the whole
-      // groupbox if the feature is disabled to prevent a gap in the preferences.
-      document.getElementById("browserContainersGroup").setAttribute("data-hidden-from-search", "true");
-      return;
-    }
-
-    let link = document.getElementById("browserContainersLearnMore");
-    link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
-
-    document.getElementById("browserContainersbox").hidden = false;
-
-    document.getElementById("browserContainersCheckbox").checked =
-      Services.prefs.getBoolPref("privacy.userContext.enabled");
-  },
-
-  _checkBrowserContainers(event) {
-    let checkbox = document.getElementById("browserContainersCheckbox");
-    if (checkbox.checked) {
-      Services.prefs.setBoolPref("privacy.userContext.enabled", true);
-      return;
-    }
-
-    let count = ContextualIdentityService.countContainerTabs();
-    if (count == 0) {
-      Services.prefs.setBoolPref("privacy.userContext.enabled", false);
-      return;
-    }
-
-    let bundlePreferences = document.getElementById("bundlePreferences");
-
-    let title = bundlePreferences.getString("disableContainersAlertTitle");
-    let message = PluralForm.get(count, bundlePreferences.getString("disableContainersMsg"))
-                            .replace("#S", count)
-    let okButton = PluralForm.get(count, bundlePreferences.getString("disableContainersOkButton"))
-                             .replace("#S", count)
-    let cancelButton = bundlePreferences.getString("disableContainersButton2");
-
-    let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
-                      (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
-
-    let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
-                                       okButton, cancelButton, null, null, {});
-    if (rv == 0) {
-      ContextualIdentityService.closeContainerTabs();
-      Services.prefs.setBoolPref("privacy.userContext.enabled", false);
-      return;
-    }
-
-    checkbox.checked = true;
-  },
-
-  /**
    * Sets up the UI for the number of days of history to keep, and updates the
    * label of the "Clear Now..." button.
    */
   init() {
     function setEventListener(aId, aEventType, aCallback) {
       document.getElementById(aId)
               .addEventListener(aEventType, aCallback.bind(gPrivacyPane));
     }
 
-    function appendSearchKeywords(aId, keywords) {
-      let element = document.getElementById(aId);
-      let searchKeywords = element.getAttribute("searchkeywords");
-      searchKeywords && keywords.push(searchKeywords);
-      element.setAttribute("searchkeywords", keywords.join(" "));
-    }
-
     this._updateSanitizeSettingsButton();
     this.initializeHistoryMode();
     this.updateHistoryModePane();
     this.updatePrivacyMicroControls();
     this.initAutoStartPrivateBrowsingReverter();
     this._initTrackingProtection();
     this._initTrackingProtectionPBM();
     this._initAutocomplete();
-    this._initBrowserContainers();
 
     setEventListener("privacy.sanitize.sanitizeOnShutdown", "change",
                      gPrivacyPane._updateSanitizeSettingsButton);
     setEventListener("browser.privatebrowsing.autostart", "change",
                      gPrivacyPane.updatePrivacyMicroControls);
     setEventListener("historyMode", "command", function() {
       gPrivacyPane.updateHistoryModePane();
       gPrivacyPane.updateHistoryModePrefs();
@@ -199,36 +136,30 @@ var gPrivacyPane = {
     setEventListener("clearDataSettings", "command",
                      gPrivacyPane.showClearPrivateDataSettings);
     setEventListener("trackingProtectionRadioGroup", "command",
                      gPrivacyPane.trackingProtectionWritePrefs);
     setEventListener("trackingProtectionExceptions", "command",
                      gPrivacyPane.showTrackingProtectionExceptions);
     setEventListener("changeBlockList", "command",
                      gPrivacyPane.showBlockLists);
-    setEventListener("browserContainersCheckbox", "command",
-                     gPrivacyPane._checkBrowserContainers);
-    setEventListener("browserContainersSettings", "command",
-                     gPrivacyPane.showContainerSettings);
     setEventListener("passwordExceptions", "command",
       gPrivacyPane.showPasswordExceptions);
     setEventListener("useMasterPassword", "command",
       gPrivacyPane.updateMasterPasswordButton);
     setEventListener("changeMasterPassword", "command",
       gPrivacyPane.changeMasterPassword);
     setEventListener("showPasswords", "command",
       gPrivacyPane.showPasswords);
     setEventListener("addonExceptions", "command",
       gPrivacyPane.showAddonExceptions);
     setEventListener("viewCertificatesButton", "command",
                      gPrivacyPane.showCertificates);
     setEventListener("viewSecurityDevicesButton", "command",
                      gPrivacyPane.showSecurityDevices);
-    setEventListener("connectionSettings", "command",
-                     gPrivacyPane.showConnections);
     setEventListener("clearCacheButton", "command",
                      gPrivacyPane.clearCache);
 
     this._pane = document.getElementById("panePrivacy");
     this._initMasterPasswordUI();
     this._initSafeBrowsing();
     this.updateCacheSizeInputField();
     this.updateActualCacheSize();
@@ -305,29 +236,28 @@ var gPrivacyPane = {
       emeUIEnabled = emeUIEnabled && parseFloat(Services.sysinfo.get("version")) >= 6;
     }
     if (!emeUIEnabled) {
       // Don't want to rely on .hidden for the toplevel groupbox because
       // of the pane hiding/showing code potentially interfering:
       document.getElementById("drmGroup").setAttribute("style", "display: none !important");
     }
 
+    this.initDataCollection();
     if (AppConstants.MOZ_CRASHREPORTER) {
       this.initSubmitCrashes();
     }
     this.initTelemetry();
     this.initSubmitHealthReport();
     setEventListener("submitHealthReportBox", "command",
                      gPrivacyPane.updateSubmitHealthReport);
 
-    // Append search keywords into the elements could open subdialogs.
     let bundlePrefs = document.getElementById("bundlePreferences");
     let signonBundle = document.getElementById("signonBundle");
     let pkiBundle = document.getElementById("pkiBundle");
-    let browserBundle = document.getElementById("browserBundle");
     appendSearchKeywords("passwordExceptions", [
       bundlePrefs.getString("savedLoginsExceptions_title"),
       bundlePrefs.getString("savedLoginsExceptions_desc"),
     ]);
     appendSearchKeywords("showPasswords", [
       signonBundle.getString("loginsDescriptionAll"),
     ]);
     appendSearchKeywords("trackingProtectionExceptions", [
@@ -348,22 +278,16 @@ var gPrivacyPane = {
     ]);
     appendSearchKeywords("addonExceptions", [
       bundlePrefs.getString("addons_permissions_title"),
       bundlePrefs.getString("addonspermissionstext"),
     ]);
     appendSearchKeywords("viewSecurityDevicesButton", [
       pkiBundle.getString("enable_fips"),
     ]);
-    appendSearchKeywords("browserContainersSettings", [
-      browserBundle.getString("userContextPersonal.label"),
-      browserBundle.getString("userContextWork.label"),
-      browserBundle.getString("userContextBanking.label"),
-      browserBundle.getString("userContextShopping.label"),
-    ]);
     appendSearchKeywords("siteDataSettings", [
       bundlePrefs.getString("siteDataSettings.description"),
       bundlePrefs.getString("removeAllCookies.label"),
       bundlePrefs.getString("removeSelectedCookies.label"),
     ]);
   },
 
   // TRACKING PROTECTION MODE
@@ -652,23 +576,16 @@ var gPrivacyPane = {
       windowTitle: bundlePreferences.getString("trackingprotectionpermissionstitle"),
       introText: bundlePreferences.getString("trackingprotectionpermissionstext"),
     };
     gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
                     null, params);
   },
 
   /**
-   * Displays container panel for customising and adding containers.
-   */
-  showContainerSettings() {
-    gotoPref("containers");
-  },
-
-  /**
    * Displays the available block lists for tracking protection.
    */
   showBlockLists() {
     var bundlePreferences = document.getElementById("bundlePreferences");
     let brandName = document.getElementById("bundleBrand")
                             .getString("brandShortName");
     var params = { brandShortName: brandName,
                    windowTitle: bundlePreferences.getString("blockliststitle"),
@@ -1227,24 +1144,16 @@ var gPrivacyPane = {
 
   /**
    * Displays a dialog from which the user can manage his security devices.
    */
   showSecurityDevices() {
     gSubDialog.open("chrome://pippki/content/device_manager.xul");
   },
 
-  // NETWORK
-  /**
-   * Displays a dialog in which proxy settings may be changed.
-   */
-  showConnections() {
-    gSubDialog.open("chrome://browser/content/preferences/connection.xul");
-  },
-
   /**
    * Clears the cache.
    */
   clearCache() {
     try {
       var cache = Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
                             .getService(Components.interfaces.nsICacheStorageService);
       cache.clear();
@@ -1389,31 +1298,34 @@ var gPrivacyPane = {
 
     let result = Services.prompt.confirmEx(
       window, title, text, flags, btn0Label, null, null, null, {});
     if (result == 0) {
       SiteDataManager.removeAll();
     }
   },
 
+  initDataCollection() {
+    this._setupLearnMoreLink("toolkit.datacollection.infoURL",
+                             "dataCollectionLearnMore");
+  },
+
   initSubmitCrashes() {
     this._setupLearnMoreLink("toolkit.crashreporter.infoURL",
                              "crashReporterLearnMore");
   },
 
   /**
    * The preference/checkbox is configured in XUL.
    *
    * In all cases, set up the Learn More link sanely.
    */
   initTelemetry() {
-    this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
-    // If we're not sending any Telemetry, disable the telemetry upload checkbox as well.
-    if (!AppConstants.MOZ_TELEMETRY_REPORTING) {
-      document.getElementById("submitTelemetryBox").setAttribute("disabled", "true");
+    if (AppConstants.MOZ_TELEMETRY_REPORTING) {
+      this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
     }
   },
 
   /**
    * Set up or hide the Learn More links for various data collection options
    */
   _setupLearnMoreLink(pref, element) {
     // set up the Learn More link with the correct URL
--- a/browser/components/preferences/in-content-new/privacy.xul
+++ b/browser/components/preferences/in-content-new/privacy.xul
@@ -75,21 +75,16 @@
   <!-- 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"/>
-  <!-- DRM content -->
-  <preference id="media.eme.enabled"
-              name="media.eme.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 -->
@@ -171,56 +166,58 @@
               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="header-privacy"
-      class="header"
+<hbox id="browserPrivacyCategory"
+      class="subcategory"
       hidden="true"
       data-category="panePrivacy">
-  <label class="header-name" flex="1">&panePrivacySecurity.title;</label>
+  <label class="header-name" flex="1">&browserPrivacy.label;</label>
 </hbox>
 
-<!-- Permissions -->
-<groupbox id="permissionsGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&permissions.label;</label></caption>
-  <separator class="thin"/>
-  <hbox align="start">
-    <checkbox id="popupPolicy" preference="dom.disable_open_during_load"
-              label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
-              onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
-                                         'dom.disable_open_during_load');"
-              flex="1" />
-    <button id="popupPolicyButton"
+<!-- Passwords -->
+<groupbox id="passwordsGroup" orient="vertical" data-category="panePrivacy" hidden="true">
+  <caption><label>&formsAndPasswords.label;</label></caption>
+
+  <vbox id="passwordSettings">
+    <hbox id="savePasswordsBox">
+      <checkbox id="savePasswords"
+                label="&rememberLogins1.label;" accesskey="&rememberLogins1.accesskey;"
+                preference="signon.rememberSignons"
+                onsyncfrompreference="return gPrivacyPane.readSavePasswords();"
+                flex="1" />
+      <button id="passwordExceptions"
+              class="accessory-button"
+              label="&passwordExceptions.label;"
+              accesskey="&passwordExceptions.accesskey;"
+              preference="pref.privacy.disable_button.view_passwords_exceptions"
+              searchkeywords="&address.label;"/>
+    </hbox>
+    <hbox id="showPasswordBox" pack="end">
+      <button id="showPasswords"
+              class="accessory-button"
+              label="&savedLogins.label;" accesskey="&savedLogins.accesskey;"
+              preference="pref.privacy.disable_button.view_passwords"
+              searchkeywords="&savedLogins.title;"/>
+    </hbox>
+  </vbox>
+  <hbox id="masterPasswordRow">
+    <checkbox id="useMasterPassword"
+              label="&useMasterPassword.label;"
+              accesskey="&useMasterPassword.accesskey;"
+              flex="1"/>
+    <button id="changeMasterPassword"
             class="accessory-button"
-            label="&popupExceptions.label;"
-            accesskey="&popupExceptions.accesskey;"
-            searchkeywords="&address.label; &button.cancel.label; &button.ok.label;"/>
-  </hbox>
-  <hbox id="addonInstallBox">
-    <checkbox id="warnAddonInstall"
-              label="&warnOnAddonInstall.label;"
-              accesskey="&warnOnAddonInstall.accesskey;"
-              preference="xpinstall.whitelist.required"
-              onsyncfrompreference="return gPrivacyPane.readWarnAddonInstall();"
-              flex="1" />
-    <button id="addonExceptions"
-            class="accessory-button"
-            label="&addonExceptions.label;"
-            accesskey="&addonExceptions.accesskey;"
-            searchkeywords="&address.label;
-                            &allow.label;
-                            &removepermission.label;
-                            &removeallpermissions.label;
-                            &button.cancel.label;
-                            &button.ok.label;"/>
+            label="&changeMasterPassword.label;"
+            accesskey="&changeMasterPassword.accesskey;"/>
   </hbox>
 </groupbox>
 
 <!-- History -->
 <groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&history.label;</label></caption>
   <hbox align="center">
     <label id="historyModeLabel"
@@ -358,52 +355,86 @@
                     accesskey="&clearOnCloseSettings.accesskey;"/>
           </hbox>
         </vbox>
       </vbox>
     </vbox>
   </deck>
 </groupbox>
 
-<!-- Passwords -->
-<groupbox id="passwordsGroup" orient="vertical" data-category="panePrivacy" hidden="true">
-  <caption><label>&formsAndPasswords.label;</label></caption>
+<!-- Address Bar -->
+<groupbox id="locationBarGroup"
+          data-category="panePrivacy"
+          hidden="true">
+  <caption><label>&addressBar.label;</label></caption>
+  <label id="locationBarSuggestionLabel">&addressBar.suggest.label;</label>
+  <checkbox id="historySuggestion" label="&locbar.history.label;"
+            accesskey="&locbar.history.accesskey;"
+            preference="browser.urlbar.suggest.history"/>
+  <checkbox id="bookmarkSuggestion" label="&locbar.bookmarks.label;"
+            accesskey="&locbar.bookmarks.accesskey;"
+            preference="browser.urlbar.suggest.bookmark"/>
+  <checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
+            accesskey="&locbar.openpage.accesskey;"
+            preference="browser.urlbar.suggest.openpage"/>
+  <label class="text-link" onclick="gotoPref('general')">
+    &suggestionSettings2.label;
+  </label>
+</groupbox>
+
+<!-- Cache -->
+<groupbox id="cacheGroup" data-category="panePrivacy" hidden="true">
+  <caption><label>&httpCache.label;</label></caption>
 
-  <vbox id="passwordSettings">
-    <hbox id="savePasswordsBox">
-      <checkbox id="savePasswords"
-                label="&rememberLogins1.label;" accesskey="&rememberLogins1.accesskey;"
-                preference="signon.rememberSignons"
-                onsyncfrompreference="return gPrivacyPane.readSavePasswords();"
-                flex="1" />
-      <button id="passwordExceptions"
-              class="accessory-button"
-              label="&passwordExceptions.label;"
-              accesskey="&passwordExceptions.accesskey;"
-              preference="pref.privacy.disable_button.view_passwords_exceptions"
-              searchkeywords="&address.label;"/>
-    </hbox>
-    <hbox id="showPasswordBox" pack="end">
-      <button id="showPasswords"
-              class="accessory-button"
-              label="&savedLogins.label;" accesskey="&savedLogins.accesskey;"
-              preference="pref.privacy.disable_button.view_passwords"
-              searchkeywords="&savedLogins.title;"/>
-    </hbox>
+  <hbox align="center">
+    <label id="actualDiskCacheSize" flex="1"/>
+    <button id="clearCacheButton"
+            class="accessory-button"
+            icon="clear"
+            label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"/>
+  </hbox>
+  <checkbox preference="browser.cache.disk.smart_size.enabled"
+            id="allowSmartSize"
+            onsyncfrompreference="return gPrivacyPane.readSmartSizeEnabled();"
+            label="&overrideSmartCacheSize.label;"
+            accesskey="&overrideSmartCacheSize.accesskey;"/>
+  <hbox align="center" class="indent">
+    <label id="useCacheBefore" control="cacheSize"
+            accesskey="&limitCacheSizeBefore.accesskey;">
+      &limitCacheSizeBefore.label;
+    </label>
+    <textbox id="cacheSize" type="number" size="4" max="1024"
+              aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
+    <label id="useCacheAfter" flex="1">&limitCacheSizeAfter.label;</label>
+  </hbox>
+</groupbox>
+
+<!-- Site Data -->
+<groupbox id="siteDataGroup" hidden="true" data-category="panePrivacy" data-hidden-from-search="true">
+  <caption><label>&siteData.label;</label></caption>
+
+  <hbox align="baseline">
+    <label id="totalSiteDataSize"></label>
+    <label id="siteDataLearnMoreLink" class="learnMore text-link" value="&siteDataLearnMoreLink.label;"></label>
+    <spacer flex="1" />
+    <button id="clearSiteDataButton"
+            class="accessory-button"
+            icon="clear"
+            label="&clearSiteData.label;" accesskey="&clearSiteData.accesskey;"/>
+  </hbox>
+  <vbox align="end">
+    <button id="siteDataSettings"
+            class="accessory-button"
+            label="&siteDataSettings.label;"
+            accesskey="&siteDataSettings.accesskey;"
+            searchkeywords="&window.title;
+                            &hostCol.label;
+                            &statusCol.label;
+                            &usageCol.label;"/>
   </vbox>
-  <hbox id="masterPasswordRow">
-    <checkbox id="useMasterPassword"
-              label="&useMasterPassword.label;"
-              accesskey="&useMasterPassword.accesskey;"
-              flex="1"/>
-    <button id="changeMasterPassword"
-            class="accessory-button"
-            label="&changeMasterPassword.label;"
-            accesskey="&changeMasterPassword.accesskey;"/>
-  </hbox>
 </groupbox>
 
 <!-- Tracking -->
 <groupbox id="trackingGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&trackingProtectionHeader2.label;</label></caption>
   <vbox>
     <hbox align="start">
       <vbox flex="1">
@@ -468,19 +499,25 @@
       <radiogroup id="doNotTrackRadioGroup" aria-labelledby="doNotTrackDesc" preference="privacy.donottrackheader.enabled">
         <radio value="false" label="&doNotTrack.default.label;"/>
         <radio value="true" label="&doNotTrack.always.label;"/>
       </radiogroup>
     </vbox>
   </vbox>
 </groupbox>
 
-<!-- Notifications -->
-<groupbox id="notificationsGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&notificationsPolicy.label;</label></caption>
+<hbox id="permissionsCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="panePrivacy">
+  <label class="header-name" flex="1">&permissions.label;</label>
+</hbox>
+
+<!-- Permissions -->
+<groupbox id="permissionsGroup" data-category="panePrivacy" hidden="true">
   <grid>
     <columns>
       <column flex="1"/>
       <column/>
     </columns>
     <rows>
       <row id="notificationsPolicyRow" align="center">
         <hbox flex="1">
@@ -502,41 +539,108 @@
     </rows>
   </grid>
   <vbox id="notificationsDoNotDisturbBox" hidden="true">
     <checkbox id="notificationsDoNotDisturb" label="&notificationsDoNotDisturb.label;"
               accesskey="&notificationsDoNotDisturb.accesskey;"/>
     <label id="notificationsDoNotDisturbDetails"
            class="indent">&notificationsDoNotDisturbDetails.value;</label>
   </vbox>
+
+  <hbox align="start">
+    <checkbox id="popupPolicy" preference="dom.disable_open_during_load"
+              label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
+              onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
+                                         'dom.disable_open_during_load');"
+              flex="1" />
+    <button id="popupPolicyButton"
+            class="accessory-button"
+            label="&popupExceptions.label;"
+            accesskey="&popupExceptions.accesskey;"
+            searchkeywords="&address.label; &button.cancel.label; &button.ok.label;"/>
+  </hbox>
+
+  <hbox id="addonInstallBox">
+    <checkbox id="warnAddonInstall"
+              label="&warnOnAddonInstall.label;"
+              accesskey="&warnOnAddonInstall.accesskey;"
+              preference="xpinstall.whitelist.required"
+              onsyncfrompreference="return gPrivacyPane.readWarnAddonInstall();"
+              flex="1" />
+    <button id="addonExceptions"
+            class="accessory-button"
+            label="&addonExceptions.label;"
+            accesskey="&addonExceptions.accesskey;"
+            searchkeywords="&address.label;
+                            &allow.label;
+                            &removepermission.label;
+                            &removeallpermissions.label;
+                            &button.cancel.label;
+                            &button.ok.label;"/>
+  </hbox>
 </groupbox>
 
-<!-- Location Bar -->
-<groupbox id="locationBarGroup"
-          data-category="panePrivacy"
-          hidden="true">
-  <caption><label>&locationBar.label;</label></caption>
-  <label id="locationBarSuggestionLabel">&locbar.suggest2.label;</label>
-  <checkbox id="historySuggestion" label="&locbar.history.label;"
-            accesskey="&locbar.history.accesskey;"
-            preference="browser.urlbar.suggest.history"/>
-  <checkbox id="bookmarkSuggestion" label="&locbar.bookmarks.label;"
-            accesskey="&locbar.bookmarks.accesskey;"
-            preference="browser.urlbar.suggest.bookmark"/>
-  <checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
-            accesskey="&locbar.openpage.accesskey;"
-            preference="browser.urlbar.suggest.openpage"/>
-  <label class="text-link" onclick="gotoPref('general')">
-    &suggestionSettings2.label;
-  </label>
+<hbox id="dataCollectionCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="panePrivacy">
+  <label class="header-name" flex="1">&dataCollection.label;</label>
+</hbox>
+
+<!-- Firefox Data Collection and Use -->
+#ifdef MOZ_DATA_REPORTING
+<groupbox id="dataCollectionGroup" data-category="panePrivacy" data-subcategory="reports" hidden="true">
+  <description>
+    &dataCollectionDesc.label;<label id="dataCollectionLearnMore" class="learnMore text-link">&dataCollectionLearnMore.label;</label>
+  </description>
+#ifndef MOZ_TELEMETRY_REPORTING
+  <description id="TelemetryDisabledDesc" control="telemetryGroup">&healthReportingDisabled.label;</description>
+#endif
+
+  <hbox align="center">
+    <checkbox id="submitHealthReportBox" label="&enableHealthReport.label;"
+              accesskey="&enableHealthReport.accesskey;"/>
+    <label id="FHRLearnMore"
+           class="learnMore text-link">&healthReportLearnMore.label;</label>
+  </hbox>
+  <description class="indent">&healthReportDesc.label;</description>
+  <vbox class="indent">
+    <hbox align="center">
+      <checkbox id="submitTelemetryBox" preference="toolkit.telemetry.enabled"
+                label="&enableTelemetryData.label;"
+                accesskey="&enableTelemetryData.accesskey;"/>
+      <label id="telemetryLearnMore"
+             class="learnMore text-link">&telemetryLearnMore.label;</label>
+    </hbox>
+    <description id="telemetryDataDesc"
+                 class="indent">&telemetryDesc.label;</description>
+  </vbox>
+#ifdef MOZ_CRASHREPORTER
+  <hbox align="center">
+    <checkbox id="automaticallySubmitCrashesBox"
+              preference="browser.crashReports.unsubmittedCheck.autoSubmit"
+              label="&alwaysSubmitCrashReports.label;"
+              accesskey="&alwaysSubmitCrashReports.accesskey;"/>
+    <label id="crashReporterLearnMore"
+           class="learnMore text-link">&crashReporterLearnMore.label;</label>
+  </hbox>
+#endif
 </groupbox>
+#endif
 
-<!-- Forgery (phishing) UI Security -->
-<groupbox id="phishingGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&security.label;</label></caption>
+<hbox id="securityCategory"
+      class="subcategory"
+      hidden="true"
+      data-category="panePrivacy">
+  <label class="header-name" flex="1">&security.label;</label>
+</hbox>
+
+<!-- addons, forgery (phishing) UI Security -->
+<groupbox id="addonsPhishingGroup" data-category="panePrivacy" hidden="true">
+  <caption><label>&phishingProtection.label;</label></caption>
   <checkbox id="enableSafeBrowsing"
             label="&enableSafeBrowsing.label;"
             accesskey="&enableSafeBrowsing.accesskey;" />
   <vbox class="indent">
     <checkbox id="blockDownloads"
               label="&blockDownloads.label;"
               accesskey="&blockDownloads.accesskey;" />
     <checkbox id="blockUncommonUnwanted"
@@ -608,123 +712,16 @@
                               &devmgr.button.logout.label;
                               &devmgr.button.changepw.label;
                               &devmgr.button.load.label;
                               &devmgr.button.unload.label;"/>
     </vbox>
   </hbox>
 </groupbox>
 
-<!-- DRM Content -->
-<groupbox id="drmGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&drmContent.label;</label></caption>
-  <grid id="contentGrid2">
-    <columns>
-      <column flex="1"/>
-      <column/>
-    </columns>
-    <rows id="contentRows-2">
-      <row id="playDRMContentRow">
-        <hbox align="center">
-          <checkbox id="playDRMContent" preference="media.eme.enabled"
-                    label="&playDRMContent.label;" accesskey="&playDRMContent.accesskey;"/>
-          <label id="playDRMContentLink" class="learnMore text-link">
-            &playDRMContent.learnMore.label;
-          </label>
-        </hbox>
-      </row>
-    </rows>
-  </grid>
-</groupbox>
-
-<!-- Containers -->
-<groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
-  <vbox id="browserContainersbox" hidden="true">
-    <caption><label>&browserContainersHeader.label;</label></caption>
-    <hbox align="center">
-      <checkbox id="browserContainersCheckbox"
-                label="&browserContainersEnabled.label;"
-                accesskey="&browserContainersEnabled.accesskey;"
-                preference="privacy.userContext.enabled"
-                onsyncfrompreference="return gPrivacyPane.readBrowserContainersCheckbox();"/>
-      <label id="browserContainersLearnMore" class="learnMore text-link">
-        &browserContainersLearnMore.label;
-      </label>
-      <spacer flex="1"/>
-      <button id="browserContainersSettings"
-              class="accessory-button"
-              label="&browserContainersSettings.label;"
-              accesskey="&browserContainersSettings.accesskey;"
-              searchkeywords="&addButton.label;
-                              &preferencesButton.label;
-                              &removeButton.label;"/>
-    </hbox>
-  </vbox>
-</groupbox>
-
-<!-- Network -->
-<!-- Connection -->
-<groupbox id="connectionGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&connection.label;</label></caption>
-
-  <hbox align="center">
-    <description flex="1" control="connectionSettings">&connectionDesc.label;</description>
-    <button id="connectionSettings"
-            class="accessory-button"
-            icon="network"
-            label="&connectionSettings.label;"
-            accesskey="&connectionSettings.accesskey;"
-            searchkeywords="&connectionsDialog.title;
-                            &noProxyTypeRadio.label;
-                            &WPADTypeRadio.label;
-                            &systemTypeRadio.label;
-                            &manualTypeRadio.label;
-                            &http.label;
-                            &ssl.label;
-                            &ftp.label;
-                            &socks.label;
-                            &socks4.label;
-                            &socks5.label;
-                            &noproxy.label;
-                            &noproxyExplain.label;
-                            &shareproxy.label;
-                            &autoTypeRadio.label;
-                            &reload.label;
-                            &autologinproxy.label;
-                            &socksRemoteDNS.label2;"/>
-  </hbox>
-</groupbox>
-
-<!-- Cache -->
-<groupbox id="cacheGroup" data-category="panePrivacy" hidden="true">
-  <caption><label>&httpCache.label;</label></caption>
-
-  <hbox align="center">
-    <label id="actualDiskCacheSize" flex="1"/>
-    <button id="clearCacheButton"
-            class="accessory-button"
-            icon="clear"
-            label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"/>
-  </hbox>
-  <checkbox preference="browser.cache.disk.smart_size.enabled"
-            id="allowSmartSize"
-            onsyncfrompreference="return gPrivacyPane.readSmartSizeEnabled();"
-            label="&overrideSmartCacheSize.label;"
-            accesskey="&overrideSmartCacheSize.accesskey;"/>
-  <hbox align="center" class="indent">
-    <label id="useCacheBefore" control="cacheSize"
-            accesskey="&limitCacheSizeBefore.accesskey;">
-      &limitCacheSizeBefore.label;
-    </label>
-    <textbox id="cacheSize" type="number" size="4" max="1024"
-              aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
-    <label id="useCacheAfter" flex="1">&limitCacheSizeAfter.label;</label>
-  </hbox>
-</groupbox>
-
 <!-- Offline apps -->
 <groupbox id="offlineGroup" data-category="panePrivacy" hidden="true" data-hidden-from-search="true">
   <caption><label>&offlineStorage2.label;</label></caption>
 
   <hbox align="center">
     <label id="actualAppCacheSize" flex="1"/>
     <button id="clearOfflineAppCacheButton"
             class="accessory-button"
@@ -754,78 +751,8 @@
       <button id="offlineAppsListRemove"
               class="accessory-button"
               disabled="true"
               label="&offlineAppsListRemove.label;"
               accesskey="&offlineAppsListRemove.accesskey;"/>
     </vbox>
   </hbox>
 </groupbox>
-
-<!-- Site Data -->
-<groupbox id="siteDataGroup" hidden="true" data-category="panePrivacy" data-hidden-from-search="true">
-  <caption><label>&siteData.label;</label></caption>
-
-  <hbox align="baseline">
-    <label id="totalSiteDataSize"></label>
-    <label id="siteDataLearnMoreLink" class="learnMore text-link" value="&siteDataLearnMoreLink.label;"></label>
-    <spacer flex="1" />
-    <button id="clearSiteDataButton"
-            class="accessory-button"
-            icon="clear"
-            label="&clearSiteData.label;" accesskey="&clearSiteData.accesskey;"/>
-  </hbox>
-  <vbox align="end">
-    <button id="siteDataSettings"
-            class="accessory-button"
-            label="&siteDataSettings.label;"
-            accesskey="&siteDataSettings.accesskey;"
-            searchkeywords="&window.title;
-                            &hostCol.label;
-                            &statusCol.label;
-                            &usageCol.label;"/>
-  </vbox>
-</groupbox>
-
-<!-- Data Choices -->
-#ifdef MOZ_DATA_REPORTING
-
-<groupbox id="telemetryGroup" data-category="panePrivacy" data-subcategory="reports" hidden="true">
-<caption><label>&reports.label;</label></caption>
-#ifndef MOZ_TELEMETRY_REPORTING
-  <description id="TelemetryDisabledDesc" control="telemetryGroup">&healthReportingDisabled.label;</description>
-#endif
-
-  <hbox align="center">
-    <checkbox id="submitHealthReportBox" label="&enableHealthReport.label;"
-              accesskey="&enableHealthReport.accesskey;"/>
-    <label id="FHRLearnMore"
-           class="learnMore text-link">&healthReportLearnMore.label;</label>
-  </hbox>
-  <description class="indent">&healthReportDesc.label;</description>
-  <vbox class="indent">
-    <hbox align="center">
-      <checkbox id="submitTelemetryBox" preference="toolkit.telemetry.enabled"
-                label="&enableTelemetryData.label;"
-                accesskey="&enableTelemetryData.accesskey;"/>
-      <label id="telemetryLearnMore"
-             class="learnMore text-link">&telemetryLearnMore.label;</label>
-    </hbox>
-    <description id="telemetryDataDesc"
-                 class="indent">&telemetryDesc.label;</description>
-  </vbox>
-</groupbox>
-
-#ifdef MOZ_CRASHREPORTER
-<groupbox id="crashReporterGroup" data-category="panePrivacy" data-subcategory="reports" hidden="true">
-  <hbox align="center">
-    <checkbox id="automaticallySubmitCrashesBox"
-              preference="browser.crashReports.unsubmittedCheck.autoSubmit"
-              label="&alwaysSubmitCrashReports.label;"
-              accesskey="&alwaysSubmitCrashReports.accesskey;"/>
-    <label id="crashReporterLearnMore"
-           class="learnMore text-link">&crashReporterLearnMore.label;</label>
-  </hbox>
-  <description class="indent">&crashReporterDesc2.label;</description>
-</groupbox>
-
-#endif
-#endif
copy from browser/components/preferences/in-content/search.js
copy to browser/components/preferences/in-content-new/search.js
copy from browser/components/preferences/in-content/search.xul
copy to browser/components/preferences/in-content-new/search.xul
--- a/browser/components/preferences/in-content/search.xul
+++ b/browser/components/preferences/in-content-new/search.xul
@@ -10,53 +10,52 @@
 
       <preference id="browser.search.hiddenOneOffs"
                   name="browser.search.hiddenOneOffs"
                   type="unichar"/>
 
     </preferences>
 
     <script type="application/javascript"
-            src="chrome://browser/content/preferences/in-content/search.js"/>
+            src="chrome://browser/content/preferences/in-content-new/search.js"/>
 
     <stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
 
-    <hbox id="header-search"
-          class="header"
+    <hbox id="searchCategory"
+          class="subcategory"
           hidden="true"
           data-category="paneSearch">
       <label class="header-name" flex="1">&paneSearch.title;</label>
-      <html:a class="help-button" target="_blank" aria-label="&helpButton.label;"></html:a>
     </hbox>
 
     <!-- Default Search Engine -->
     <groupbox id="defaultEngineGroup" align="start" data-category="paneSearch">
       <caption label="&defaultSearchEngine.label;"/>
-      <label>&chooseYourDefaultSearchEngine.label;</label>
+      <label>&chooseYourDefaultSearchEngine2.label;</label>
       <menulist id="defaultEngine">
         <menupopup/>
       </menulist>
       <checkbox id="suggestionsInSearchFieldsCheckbox"
                 label="&provideSearchSuggestions.label;"
                 accesskey="&provideSearchSuggestions.accesskey;"
                 preference="browser.search.suggest.enabled"/>
       <vbox class="indent">
-        <checkbox id="urlBarSuggestion" label="&showURLBarSuggestions.label;"
-                  accesskey="&showURLBarSuggestions.accesskey;"
+        <checkbox id="urlBarSuggestion" label="&showURLBarSuggestions2.label;"
+                  accesskey="&showURLBarSuggestions2.accesskey;"
                   preference="browser.urlbar.suggest.searches"/>
         <hbox id="urlBarSuggestionPermanentPBLabel"
               align="center" class="indent">
           <label flex="1">&urlBarSuggestionsPermanentPB.label;</label>
         </hbox>
       </vbox>
     </groupbox>
 
     <groupbox id="oneClickSearchProvidersGroup" data-category="paneSearch">
       <caption label="&oneClickSearchEngines.label;"/>
-      <label>&chooseWhichOneToDisplay.label;</label>
+      <label>&chooseWhichOneToDisplay2.label;</label>
 
       <tree id="engineList" flex="1" rows="8" hidecolumnpicker="true" editable="true"
             seltype="single">
         <treechildren id="engineChildren" flex="1"/>
         <treecols>
           <treecol id="engineShown" type="checkbox" editable="true" sortable="false"/>
           <treecol id="engineName" flex="4" label="&engineNameColumn.label;" sortable="false"/>
           <treecol id="engineKeyword" flex="1" label="&engineKeywordColumn.label;" editable="true"
@@ -76,11 +75,11 @@
                 accesskey="&removeEngine.accesskey;"
                 disabled="true"
                 />
       </hbox>
 
       <separator class="thin"/>
 
       <hbox id="addEnginesBox" pack="start">
-        <label id="addEngines" class="text-link" value="&addMoreSearchEngines.label;"/>
+        <label id="addEngines" class="text-link" value="&findMoreSearchEngines.label;"/>
       </hbox>
     </groupbox>
--- a/browser/components/preferences/in-content-new/sync.xul
+++ b/browser/components/preferences/in-content-new/sync.xul
@@ -23,18 +23,18 @@
   <preference id="engine.passwords"
               name="services.sync.engine.passwords"
               type="bool"/>
 </preferences>
 
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content-new/sync.js"/>
 
-<hbox id="header-sync"
-      class="header"
+<hbox id="firefoxAccountCategory"
+      class="searchCategory"
       hidden="true"
       data-category="paneSync">
   <label class="header-name" flex="1">&paneSync1.title;</label>
 </hbox>
 
 <deck id="weavePrefsDeck" data-category="paneSync" hidden="true">
   <vbox id="noFxaAccount">
     <hbox>
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -16,18 +16,16 @@ browser/chrome/browser/content/browser/p
 browser/chrome/browser/content/browser/preferences/in-content/containers.js
 browser/chrome/browser/content/browser/preferences/in-content/content.js
 browser/chrome/browser/content/browser/preferences/in-content/main.js
 browser/chrome/browser/content/browser/preferences/in-content/preferences.js
 browser/chrome/browser/content/browser/preferences/in-content/privacy.js
 browser/chrome/browser/content/browser/preferences/in-content/search.js
 browser/chrome/browser/content/browser/preferences/in-content/security.js
 browser/chrome/browser/content/browser/preferences/in-content/sync.js
-browser/chrome/browser/content/browser/preferences/in-content-new/advanced.js
-browser/chrome/browser/content/browser/preferences/in-content-new/applications.js
 browser/chrome/browser/content/browser/preferences/in-content-new/containers.js
 browser/chrome/browser/content/browser/preferences/in-content-new/content.js
 browser/chrome/browser/content/browser/preferences/in-content-new/main.js
 browser/chrome/browser/content/browser/preferences/in-content-new/preferences.js
 browser/chrome/browser/content/browser/preferences/in-content-new/privacy.js
 browser/chrome/browser/content/browser/preferences/in-content-new/search.js
 browser/chrome/browser/content/browser/preferences/in-content-new/security.js
 browser/chrome/browser/content/browser/preferences/in-content-new/sync.js
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -1,24 +1,20 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!-- Note: each tab panel must contain unique accesskeys -->
 
 <!ENTITY generalTab.label                "General">
 
-<!ENTITY accessibility.label             "Accessibility">
-
 <!ENTITY useCursorNavigation.label       "Always use the cursor keys to navigate within pages">
 <!ENTITY useCursorNavigation.accesskey   "c">
 <!ENTITY searchOnStartTyping.label       "Search for text when you start typing">
 <!ENTITY searchOnStartTyping.accesskey   "x">
-<!ENTITY blockAutoReload.label           "Warn you when websites try to redirect or reload the page">
-<!ENTITY blockAutoReload.accesskey       "b">
 <!ENTITY useOnScreenKeyboard.label       "Show a touch keyboard when necessary">
 <!ENTITY useOnScreenKeyboard.accesskey   "k">
 
 <!ENTITY browsing.label                  "Browsing">
 
 <!ENTITY useAutoScroll.label             "Use autoscrolling">
 <!ENTITY useAutoScroll.accesskey         "a">
 <!ENTITY useSmoothScrolling.label        "Use smooth scrolling">
@@ -38,24 +34,27 @@ available. -->
 <!ENTITY enableHealthReport.accesskey    "R">
 <!ENTITY healthReportLearnMore.label     "Learn more">
 
 <!ENTITY telemetryDesc.label             "Shares performance, usage, hardware and customization data about your browser with &vendorShortName; to help us make &brandShortName; better">
 <!ENTITY enableTelemetryData.label       "Share Additional Data (i.e., Telemetry)">
 <!ENTITY enableTelemetryData.accesskey   "T">
 <!ENTITY telemetryLearnMore.label        "Learn more">
 
-<!ENTITY crashReporterDesc2.label         "Crash reports help &vendorShortName; fix problems and make your browser more stable and secure">
-<!ENTITY alwaysSubmitCrashReports.label   "Allow &brandShortName; to send backlogged crash reports on your behalf">
+<!ENTITY dataCollection.label            "&brandShortName; Data Collection and Use">
+<!ENTITY dataCollectionDesc.label        "We strive to provide you with choices and collect only what we need to provide and improve &brandShortName; for everyone. We always ask permission before receiving personal information.">
+<!ENTITY dataCollectionLearnMore.label    "Learn more">
+
+<!ENTITY alwaysSubmitCrashReports.label  "Allow &brandShortName; to send backlogged crash reports on your behalf">
 <!ENTITY alwaysSubmitCrashReports.accesskey "c">
-<!ENTITY crashReporterLearnMore.label     "Learn more">
+<!ENTITY crashReporterLearnMore.label    "Learn more">
 
 <!ENTITY networkTab.label                "Network">
 
-<!ENTITY connection.label                "Connection">
+<!ENTITY networkProxy.label              "Network Proxy">
 
 <!ENTITY connectionDesc.label            "Configure how &brandShortName; connects to the Internet">
 <!ENTITY connectionSettings.label        "Settings…">
 <!ENTITY connectionSettings.accesskey    "e">
 
 <!ENTITY httpCache.label                 "Cached Web Content">
 
 <!ENTITY offlineStorage2.label           "Offline Web Content and User Data">
@@ -111,18 +110,16 @@ available. -->
 <!ENTITY updateHistory2.accesskey        "p">
 
 <!ENTITY useService.label                "Use a background service to install updates">
 <!ENTITY useService.accesskey            "b">
 
 <!ENTITY enableSearchUpdate2.label       "Automatically update search engines">
 <!ENTITY enableSearchUpdate2.accesskey   "e">
 
-<!ENTITY reports.label                   "Reports">
-
 <!ENTITY offlineStorageNotify.label               "Tell you when a website asks to store data for offline use">
 <!ENTITY offlineStorageNotify.accesskey           "T">
 <!ENTITY offlineStorageNotifyExceptions.label     "Exceptions…">
 <!ENTITY offlineStorageNotifyExceptions.accesskey "x">
 
 <!ENTITY offlineAppsList2.label          "The following websites are allowed to store data for offline use:">
 <!ENTITY offlineAppsList.height          "7em">
 <!ENTITY offlineAppsListRemove.label     "Remove…">
--- a/browser/locales/en-US/chrome/browser/preferences/containers.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/containers.dtd
@@ -2,17 +2,17 @@
    - 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 addButton.label      "Add New Container">
 <!ENTITY addButton.accesskey  "A">
 <!ENTITY preferencesButton.label "Preferences">
 <!ENTITY removeButton.label   "Remove">
 <!-- &#171; is &laquo; however it's not defined in XML -->
-<!ENTITY backLink.label       "&#171; Go Back to Privacy">
+<!ENTITY backLink2.label      "&#171; Go Back">
 
 <!ENTITY window.title         "Add New Container">
 <!ENTITY window.width         "45em">
 
 <!ENTITY name.label           "Name:">
 <!ENTITY name.accesskey       "N">
 <!ENTITY name.placeholder     "Enter a container name">
 <!ENTITY icon.label           "Icon:">
--- a/browser/locales/en-US/chrome/browser/preferences/content.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/content.dtd
@@ -1,17 +1,17 @@
 <!-- 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  permissions.label           "Permissions">
 
 <!ENTITY  blockPopups.label           "Block pop-up windows">
 <!ENTITY  blockPopups.accesskey       "B">
 
-<!ENTITY  notificationsPolicy.label            "Notifications">
 <!ENTITY  notificationsPolicyLearnMore.label   "Learn more">
 <!ENTITY  notificationsPolicyDesc3.label       "Choose which sites are allowed to send you notifications">
 <!ENTITY  notificationsPolicyButton.accesskey  "h">
 <!ENTITY  notificationsPolicyButton.label      "Choose…">
 <!ENTITY  notificationsDoNotDisturb.label      "Do not disturb me">
 <!ENTITY  notificationsDoNotDisturb.accesskey  "n">
 <!ENTITY  notificationsDoNotDisturbDetails.value "No notification will be shown until you restart &brandShortName;">
 
@@ -27,17 +27,17 @@
 
 <!ENTITY  advancedFonts.label         "Advanced…">
 <!ENTITY  advancedFonts.accesskey     "A">
 
 <!ENTITY  colors.label                "Colors…">
 <!ENTITY  colors.accesskey            "C">
 
 
-<!ENTITY languages.label              "Languages">
+<!ENTITY language2.label              "Language">
 <!ENTITY chooseLanguage.label         "Choose your preferred language for displaying pages">
 <!ENTITY chooseButton.label           "Choose…">
 <!ENTITY chooseButton.accesskey       "o">
 
 <!ENTITY translateWebPages.label      "Translate web content">
 <!ENTITY translateWebPages.accesskey  "T">
 <!ENTITY translateExceptions.label    "Exceptions…">
 <!ENTITY translateExceptions.accesskey "x">
@@ -47,13 +47,13 @@
   -  These 2 strings are displayed before and after a 'Microsoft Translator'
   -  logo.
   -  The translations for these strings should match the translations in
   -  browser/translation.dtd
   -->
 <!ENTITY translation.options.attribution.beforeLogo "Translations by">
 <!ENTITY translation.options.attribution.afterLogo "">
 
-<!ENTITY  drmContent.label             "DRM Content">
+<!ENTITY  drmContent2.label              "Digital Rights Management (DRM) Content">
 
-<!ENTITY  playDRMContent.label         "Play DRM content">
-<!ENTITY  playDRMContent.accesskey     "P">
+<!ENTITY  playDRMContent2.label          "Play DRM-controlled content">
+<!ENTITY  playDRMContent2.accesskey      "P">
 <!ENTITY  playDRMContent.learnMore.label "Learn more">
--- a/browser/locales/en-US/chrome/browser/preferences/main.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/main.dtd
@@ -5,17 +5,17 @@
 <!ENTITY startup.label             "Startup">
 
 <!ENTITY startupPage2.label        "When &brandShortName; starts">
 <!ENTITY startupPage2.accesskey    "s">
 <!ENTITY startupUserHomePage.label "Show your home page">
 <!ENTITY startupBlankPage.label    "Show a blank page">
 <!ENTITY startupPrevSession.label  "Show your windows and tabs from last time">
 
-<!ENTITY homepage2.label           "Home Page">
+<!ENTITY homepage2.label           "Home page">
 <!ENTITY homepage2.accesskey       "P">
 <!ENTITY useCurrentPage.label      "Use Current Page">
 <!ENTITY useCurrentPage.accesskey  "C">
 <!ENTITY useMultiple.label         "Use Current Pages">
 <!ENTITY chooseBookmark.label      "Use Bookmark…">
 <!ENTITY chooseBookmark.accesskey  "B">
 <!ENTITY restoreDefault.label      "Restore to Default">
 <!ENTITY restoreDefault.accesskey  "R">
@@ -28,18 +28,18 @@
 <!ENTITY chooseFolderWin.accesskey    "o">
 <!ENTITY chooseFolderMac.label        "Choose…">
 <!ENTITY chooseFolderMac.accesskey    "e">
 <!ENTITY alwaysAskWhere.label         "Always ask you where to save files">
 <!ENTITY alwaysAskWhere.accesskey     "A">
 
 <!ENTITY alwaysCheckDefault2.label        "Always check if &brandShortName; is your default browser">
 <!ENTITY alwaysCheckDefault2.accesskey    "y">
-<!ENTITY setAsMyDefaultBrowser2.label     "Make Default">
-<!ENTITY setAsMyDefaultBrowser2.accesskey "D">
+<!ENTITY setAsMyDefaultBrowser3.label     "Make Default…">
+<!ENTITY setAsMyDefaultBrowser3.accesskey "D">
 <!ENTITY isDefault.label                  "&brandShortName; is currently your default browser">
 <!ENTITY isNotDefault.label               "&brandShortName; is not your default browser">
 
 <!ENTITY separateProfileMode.label        "Allow &brandShortName; and Firefox to run at the same time">
 <!ENTITY useFirefoxSync.label             "Tip: This uses separate profiles. Use Sync to share data between them.">
 <!ENTITY getStarted.notloggedin.label     "Sign in to &syncBrand.shortName.label;…">
 <!ENTITY getStarted.configured.label      "Open &syncBrand.shortName.label; preferences">
 
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.dtd
@@ -10,19 +10,22 @@
 <!-- When making changes to prefWindow.styleWin test both Windows Classic and
      Luna since widget heights are different based on the OS theme -->
 <!ENTITY  prefWinMinSize.styleWin2      "width: 42em; min-height: 37.5em;">
 <!ENTITY  prefWinMinSize.styleMac       "width: 47em; min-height: 40em;">
 <!ENTITY  prefWinMinSize.styleGNOME     "width: 45.5em; min-height: 40.5em;">
 
 <!ENTITY  paneSearchResults.title       "Search Results">
 <!ENTITY  paneGeneral.title             "General">
+<!ENTITY  paneSearch.title              "Search">
 <!ENTITY  paneFilesApplications.title   "Files &amp; Applications">
 <!ENTITY  panePrivacySecurity.title     "Privacy &amp; Security">
 <!ENTITY  paneContainers.title          "Container Tabs">
 <!ENTITY  paneUpdates.title             "Updates">
 
+<!ENTITY  languageAndAppearance.label   "Language and Appearance">
+<!ENTITY  filesAndApplications.label    "Files and Applications">
+<!ENTITY  browserPrivacy.label          "Browser Privacy">
+
 <!-- LOCALIZATION NOTE (paneSync1.title): This should match syncBrand.fxAccount.label in ../syncBrand.dtd -->
 <!ENTITY  paneSync1.title          "Firefox Account">
 
 <!ENTITY  helpButton2.label        "&brandShortName; Support">
-
-<!ENTITY  searchInput.label        "Search">
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -250,16 +250,20 @@ removeContainerAlertTitle=Remove This Co
 # LOCALIZATION NOTE (removeContainerMsg): Semi-colon list of plural forms.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #S is the number of container tabs
 removeContainerMsg=If you remove this Container now, #S container tab will be closed. Are you sure you want to remove this Container?;If you remove this Container now, #S container tabs will be closed. Are you sure you want to remove this Container?
 
 removeContainerOkButton=Remove this Container
 removeContainerButton2=Don’t remove this Container
 
+# Search Input
+searchInput.labelWin=Find in Options
+searchInput.labelUnix=Find in Preferences
+
 # Search Results Pane
 # LOCALIZATION NOTE %S will be replaced by the word being searched
 searchResults.sorryMessageWin=Sorry! There are no results in Options for “%S”.
 searchResults.sorryMessageUnix=Sorry! There are no results in Preferences for “%S”.
 # LOCALIZATION NOTE (searchResults.needHelp2): %1$S is a link to SUMO, %2$S is
 # the browser name
 searchResults.needHelp2=Need help? Visit <html:a id="need-help-link" target="_blank" href="%1$S">%2$S Support</html:a>
 
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -28,19 +28,18 @@
 <!ENTITY  doNotTrack.description        "Send websites a “Do Not Track” signal that you don’t want to be tracked">
 <!ENTITY  doNotTrack.learnMore.label    "Learn more">
 <!ENTITY  doNotTrack.default.label      "Only when using Tracking Protection">
 <!ENTITY  doNotTrack.always.label       "Always">
 
 <!ENTITY  history.label                 "History">
 <!ENTITY  permissions.label             "Permissions">
 
-<!ENTITY  locationBar.label             "Location Bar">
-
-<!ENTITY  locbar.suggest2.label         "When using the location bar, suggest">
+<!ENTITY  addressBar.label              "Address Bar">
+<!ENTITY  addressBar.suggest.label      "When using the address bar, suggest">
 <!ENTITY  locbar.history.label          "History">
 <!ENTITY  locbar.history.accesskey      "H">
 <!ENTITY  locbar.bookmarks.label        "Bookmarks">
 <!ENTITY  locbar.bookmarks.accesskey    "k">
 <!ENTITY  locbar.openpage.label         "Open tabs">
 <!ENTITY  locbar.openpage.accesskey     "O">
 <!ENTITY  locbar.searches.label         "Related searches from the default search engine">
 <!ENTITY  locbar.searches.accesskey     "d">
@@ -104,14 +103,13 @@
 <!ENTITY  rememberSearchForm.accesskey   "f">
 
 <!ENTITY  clearOnClose.label             "Clear history when &brandShortName; closes">
 <!ENTITY  clearOnClose.accesskey         "r">
 
 <!ENTITY  clearOnCloseSettings.label     "Settings…">
 <!ENTITY  clearOnCloseSettings.accesskey "t">
 
-<!ENTITY  browserContainersHeader.label         "Container Tabs">
 <!ENTITY  browserContainersLearnMore.label      "Learn more">
 <!ENTITY  browserContainersEnabled.label        "Enable Container Tabs">
 <!ENTITY  browserContainersEnabled.accesskey    "n">
 <!ENTITY  browserContainersSettings.label        "Settings…">
 <!ENTITY  browserContainersSettings.accesskey    "i">
--- a/browser/locales/en-US/chrome/browser/preferences/search.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/search.dtd
@@ -1,29 +1,29 @@
 <!-- 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 defaultSearchEngine.label             "Default Search Engine">
 
-<!ENTITY chooseYourDefaultSearchEngine.label   "Choose your default search engine. &brandShortName; uses it in the location bar, search bar, and start page.">
+<!ENTITY chooseYourDefaultSearchEngine2.label   "Choose the default search engine to use in the address bar and search bar.">
 
 <!ENTITY provideSearchSuggestions.label        "Provide search suggestions">
 <!ENTITY provideSearchSuggestions.accesskey    "s">
 
-<!ENTITY showURLBarSuggestions.label           "Show search suggestions in location bar results">
-<!ENTITY showURLBarSuggestions.accesskey       "l">
+<!ENTITY showURLBarSuggestions2.label           "Show search suggestions in address bar results">
+<!ENTITY showURLBarSuggestions2.accesskey       "l">
 <!ENTITY urlBarSuggestionsPermanentPB.label    "Search suggestions will not be shown in location bar results because you have configured &brandShortName; to never remember history.">
 
 <!ENTITY oneClickSearchEngines.label           "One-Click Search Engines">
 
-<!ENTITY chooseWhichOneToDisplay.label         "The search bar lets you search alternate engines directly. Choose which ones to display.">
+<!ENTITY chooseWhichOneToDisplay2.label         "Choose the alternative search engines that appear below the address bar and search bar when you start to enter a keyword.">
 
 <!ENTITY engineNameColumn.label                "Search Engine">
 <!ENTITY engineKeywordColumn.label             "Keyword">
 
 <!ENTITY restoreDefaultSearchEngines.label     "Restore Default Search Engines">
 <!ENTITY restoreDefaultSearchEngines.accesskey "d">
 
 <!ENTITY removeEngine.label                    "Remove">
 <!ENTITY removeEngine.accesskey                "r">
 
-<!ENTITY addMoreSearchEngines2.label           "Add more search engines">
+<!ENTITY findMoreSearchEngines.label           "Find more search engines">
--- a/browser/locales/en-US/chrome/browser/preferences/security.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/security.dtd
@@ -1,13 +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/. -->
 
 <!ENTITY  security.label                 "Security">
+<!ENTITY  phishingProtection.label       "Phishing Protection">
 
 <!ENTITY  warnOnAddonInstall.label        "Warn you when sites try to install add-ons">
 <!ENTITY  warnOnAddonInstall.accesskey    "W">
 
 <!-- LOCALIZATION NOTE (enableSafeBrowsing.label, blockDownloads.label, blockUncommonUnwanted.label):
   It is important that wording follows the guidelines outlined on this page:
   https://developers.google.com/safe-browsing/developers_guide_v2#AcceptableUsage
 -->
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -52,16 +52,36 @@ treecol {
   font-weight: normal;
   white-space: nowrap;
 }
 
 .accessory-button {
   min-width: 145px;
 }
 
+/* Subcategory title */
+
+/**
+ * The first subcategory title for each category should not have margin-top.
+ */
+#generalCategory,
+#searchCategory,
+#browserPrivacyCategory,
+#firefoxAccountCategory {
+  margin-top: 0;
+}
+
+.header-name {
+  font-size: 2rem;
+}
+
+.subcategory {
+  margin-top: 48px;
+}
+
 /* Category List */
 
 #categories {
   max-height: 100vh;
 }
 
 #categories > scrollbox {
   overflow-x: hidden !important;
@@ -76,16 +96,20 @@ treecol {
   display: -moz-box;
   visibility: collapse;
 }
 
 #category-general > .category-icon {
   list-style-image: url("chrome://browser/skin/preferences/in-content-new/icons.svg#general");
 }
 
+#category-search > .category-icon {
+  list-style-image: url("chrome://browser/skin/preferences/in-content-new/icons.svg#searchResults");
+}
+
 #category-application > .category-icon {
   list-style-image: url("chrome://browser/skin/preferences/in-content-new/icons.svg#content");
 }
 
 #category-privacy > .category-icon {
   list-style-image: url("chrome://browser/skin/preferences/in-content-new/icons.svg#security");
 }
 
@@ -239,20 +263,16 @@ treecol {
 #doNotTrackLearnMoreBox {
   margin-top: 30px
 }
 
 #trackingProtectionAdvancedSettings {
   margin-inline-start: 15px;
 }
 
-#crashReporterGroup {
-  margin-top: 0;
-}
-
 /* Collapse the non-active vboxes in decks to use only the height the
    active vbox needs */
 #historyPane:not([selectedIndex="1"]) > #historyDontRememberPane,
 #historyPane:not([selectedIndex="2"]) > #historyCustomPane,
 #weavePrefsDeck:not([selectedIndex="1"]) > #hasFxaAccount,
 #fxaLoginStatus:not([selectedIndex="1"]) > #fxaLoginUnverified,
 #fxaLoginStatus:not([selectedIndex="2"]) > #fxaLoginRejected {
   visibility: collapse;