Bug 446291: improved attachment preferences pane. ui-r=clarkbw, r=philor
authorMagnus Melin <mkmelin+mozilla@iki.fi>
Mon, 29 Jun 2009 13:12:55 +0300
changeset 2965 76a9c718b6fa02a20b74dc2093e1c49399470bae
parent 2964 23e14af0a02ba6b4eebc2601ba2579d11b833ff9
child 2966 370680198decbf7d8d7e2e240dc3b0d6fd56aa39
push idunknown
push userunknown
push dateunknown
reviewersclarkbw, philor
bugs446291
Bug 446291: improved attachment preferences pane. ui-r=clarkbw, r=philor
mail/app/profile/all-thunderbird.js
mail/components/preferences/applicationManager.js
mail/components/preferences/applicationManager.xul
mail/components/preferences/applications.js
mail/components/preferences/applications.xul
mail/components/preferences/changeaction.js
mail/components/preferences/changeaction.xul
mail/components/preferences/downloadactions.js
mail/components/preferences/downloadactions.xul
mail/components/preferences/downloads.js
mail/components/preferences/downloads.xul
mail/components/preferences/handlers.css
mail/components/preferences/handlers.xml
mail/components/preferences/jar.mn
mail/components/preferences/preferences.xul
mail/locales/en-US/chrome/messenger/preferences/applicationManager.dtd
mail/locales/en-US/chrome/messenger/preferences/applicationManager.properties
mail/locales/en-US/chrome/messenger/preferences/applications.dtd
mail/locales/en-US/chrome/messenger/preferences/changeaction.dtd
mail/locales/en-US/chrome/messenger/preferences/downloadactions.dtd
mail/locales/en-US/chrome/messenger/preferences/downloads.dtd
mail/locales/en-US/chrome/messenger/preferences/preferences.dtd
mail/locales/en-US/chrome/messenger/preferences/preferences.properties
mail/locales/jar.mn
mail/themes/gnomestripe/jar.mn
mail/themes/gnomestripe/mail/preferences/alwaysAsk.png
mail/themes/gnomestripe/mail/preferences/applications.css
mail/themes/gnomestripe/mail/preferences/preferences.css
mail/themes/pinstripe/jar.mn
mail/themes/pinstripe/mail/preferences/alwaysAsk.png
mail/themes/pinstripe/mail/preferences/application.png
mail/themes/pinstripe/mail/preferences/applications.css
mail/themes/pinstripe/mail/preferences/preferences.css
mail/themes/pinstripe/mail/preferences/saveFile.png
mail/themes/qute/jar.mn
mail/themes/qute/mail/preferences/alwaysAsk.png
mail/themes/qute/mail/preferences/application.png
mail/themes/qute/mail/preferences/applications.css
mail/themes/qute/mail/preferences/preferences.css
mail/themes/qute/mail/preferences/saveFile.png
--- a/mail/app/profile/all-thunderbird.js
+++ b/mail/app/profile/all-thunderbird.js
@@ -201,16 +201,19 @@ pref("browser.preferences.instantApply",
 pref("browser.preferences.instantApply", true);
 #endif
 #ifdef XP_MACOSX
 pref("browser.preferences.animateFadeIn", true);
 #else
 pref("browser.preferences.animateFadeIn", false);
 #endif
 
+pref("browser.download.show_plugins_in_list", false);
+pref("browser.download.hide_plugins_without_extensions", true);
+
 pref("accessibility.typeaheadfind", false);
 pref("accessibility.typeaheadfind.timeout", 5000);
 pref("accessibility.typeaheadfind.linksonly", false);
 pref("accessibility.typeaheadfind.flashBar", 1);
 
 pref("mail.close_message_window.on_delete", false);
 
 /////////////////////////////////////////////////////////////////
new file mode 100644
--- /dev/null
+++ b/mail/components/preferences/applicationManager.js
@@ -0,0 +1,125 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org Code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Florian Queze <florian@queze.net> (Original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+var gAppManagerDialog = {
+  _removed: [],
+
+  init: function appManager_init() {
+    this.handlerInfo = window.arguments[0];
+
+    var bundle = document.getElementById("appManagerBundle");
+
+    var description = gApplicationsPane._describeType(this.handlerInfo);
+    var key = (this.handlerInfo.wrappedHandlerInfo instanceof Components.interfaces.nsIMIMEInfo) ?
+                "handleFile" : "handleProtocol";
+    var 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))
+        continue;
+
+      app.QueryInterface(Components.interfaces.nsIHandlerApp);
+      var item = list.appendItem(app.name);
+      item.setAttribute("image", gApplicationsPane._getIconURLForHandlerApp(app));
+      item.className = "listitem-iconic";
+      item.app = app;
+    }
+
+    list.selectedIndex = 0;
+  },
+
+  onOK: function appManager_onOK() {
+    if (!this._removed.length) {
+      // return early to avoid calling the |store| method.
+      return;
+    }
+
+    for (var i = 0; i < this._removed.length; ++i)
+      this.handlerInfo.removePossibleApplicationHandler(this._removed[i]);
+
+    this.handlerInfo.store();
+  },
+
+  onCancel: function appManager_onCancel() {
+    // do nothing
+  },
+
+  remove: function appManager_remove() {
+    var list = document.getElementById("appList");
+    this._removed.push(list.selectedItem.app);
+    var index = list.selectedIndex;
+    list.removeItemAt(index);
+    if (list.getRowCount() == 0) {
+      // The list is now empty, make the bottom part disappear
+      document.getElementById("appDetails").hidden = true;
+    }
+    else {
+      // Select the item at the same index, if we removed the last
+      // item of the list, select the previous item
+      if (index == list.getRowCount())
+        --index;
+      list.selectedIndex = index;
+    }
+  },
+
+  onSelect: function appManager_onSelect() {
+    var list = document.getElementById("appList");
+    if (!list.selectedItem) {
+      document.getElementById("remove").disabled = true;
+      return;
+    }
+    document.getElementById("remove").disabled = false;
+    var app = list.selectedItem.app;
+    var address = "";
+    if (app instanceof Components.interfaces.nsILocalHandlerApp)
+      address = app.executable.path;
+    else if (app instanceof Components.interfaces.nsIWebHandlerApp)
+      address = app.uriTemplate;
+    else if (app instanceof Components.interfaces.nsIWebContentHandlerInfo)
+      address = app.uri;
+    document.getElementById("appLocation").value = address;
+    var bundle = document.getElementById("appManagerBundle");
+    var appType = (app instanceof Components.interfaces.nsILocalHandlerApp) ?
+                    "descriptionLocalApp" : "descriptionWebApp";
+    document.getElementById("appType").value = bundle.getString(appType);
+  }
+};
new file mode 100644
--- /dev/null
+++ b/mail/components/preferences/applicationManager.xul
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org Code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Florian Queze <florian@queze.net> (Original author)
+#   Magnus Melin <mkmelin+mozilla@iki.fi>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+<?xml-stylesheet href="chrome://global/skin/"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://messenger/locale/preferences/applicationManager.dtd">
+
+<dialog id="appManager"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        buttons="accept,cancel"
+        onload="gAppManagerDialog.init();"
+        ondialogaccept="gAppManagerDialog.onOK();"
+        ondialogcancel="gAppManagerDialog.onCancel();"
+        title="&appManager.title;"
+        style="&appManager.style;"
+        persist="screenX screenY">
+
+  <script type="application/javascript"
+          src="chrome://messenger/content/preferences/applications.js"/>
+  <script type="application/javascript"
+          src="chrome://messenger/content/preferences/applicationManager.js"/>
+
+  <commandset id="appManagerCommandSet">
+    <command id="cmd_delete"
+             oncommand="gAppManagerDialog.remove();"
+             disabled="true"/>
+  </commandset>
+
+  <keyset id="appManagerKeyset">
+    <key id="delete" keycode="VK_DELETE" command="cmd_delete"/>
+  </keyset>
+
+  <stringbundleset id="appManagerBundleset">
+    <stringbundle id="appManagerBundle"
+                  src="chrome://messenger/locale/preferences/applicationManager.properties"/>
+  </stringbundleset>
+
+  <description id="appDescription"/>
+  <separator class="thin"/>
+  <hbox flex="1">
+    <listbox id="appList" onselect="gAppManagerDialog.onSelect();" flex="1"/>
+    <vbox>
+      <button id="remove"
+              label="&remove.label;"
+              accesskey="&remove.accesskey;"
+              command="cmd_delete"/>
+      <spacer flex="1"/>
+    </vbox>
+  </hbox>
+  <vbox id="appDetails">
+    <separator class="thin"/>
+    <label id="appType"/>
+    <textbox id="appLocation" readonly="true" class="plain"/>
+  </vbox>
+</dialog>
new file mode 100755
--- /dev/null
+++ b/mail/components/preferences/applications.js
@@ -0,0 +1,1370 @@
+/*
+# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Download Actions Manager.
+#
+# The Initial Developer of the Original Code is
+# Ben Goodger.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Ben Goodger <ben@mozilla.org>
+#   Jeff Walden <jwalden+code@mit.edu>
+#   Asaf Romano <mozilla.mano@sent.com>
+#   Myk Melez <myk@mozilla.org>
+#   Florian Queze <florian@queze.net>
+#   Will Guaraldi <will.guaraldi@pculture.org>
+#   Magnus Melin <mkmelin+mozilla@iki.fi>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+ */
+
+//****************************************************************************//
+// Constants & Enumeration Values
+
+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";
+
+// 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;
+
+/*
+#ifdef MOZ_WIDGET_GTK2
+*/
+const ICON_URL_APP      = "moz-icon://dummy.exe?size=16";
+/*
+#else
+*/
+const ICON_URL_APP      = "chrome://messenger/skin/preferences/application.png";
+/*
+#endif
+*/
+
+// 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 getDisplayNameForFile(aFile) {
+/*
+#ifdef XP_WIN
+*/
+  if (aFile instanceof Components.interfaces.nsILocalFileWin) {
+    try {
+      return aFile.getVersionInfoField("FileDescription");
+    }
+    catch(ex) {
+      // fall through to the file name
+    }
+  }
+/*
+#endif
+#ifdef XP_MACOSX
+*/
+  if (aFile instanceof Components.interfaces.nsILocalFileMac) {
+    try {
+      return aFile.bundleDisplayName;
+    }
+    catch(ex) {
+      // fall through to the file name
+    }
+  }
+/*
+#endif
+*/
+  return aFile.leafName;
+}
+
+function getLocalHandlerApp(aFile) {
+  var localHandlerApp = Components.classes["@mozilla.org/uriloader/local-handler-app;1"]
+                                  .createInstance(Components.interfaces.nsILocalHandlerApp);
+  localHandlerApp.name = getDisplayNameForFile(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: function() {
+    return this._index < this._contents.length;
+  },
+
+  getNext: function() {
+    return this._contents[this._index++];
+  }
+};
+
+//****************************************************************************//
+// 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 navigator.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: Components.classes["@mozilla.org/uriloader/handler-service;1"]
+                         .getService(Components.interfaces.nsIHandlerService),
+
+  _prefSvc: Components.classes["@mozilla.org/preferences-service;1"]
+                      .getService(Components.interfaces.nsIPrefBranch2),
+
+  _categoryMgr: Components.classes["@mozilla.org/categorymanager;1"]
+                          .getService(Components.interfaces.nsICategoryManager),
+
+  //**************************************************************************//
+  // 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 document.getElementById("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: function(aNewHandler) {
+    try {
+      if (this.possibleApplicationHandlers.indexOf(0, aNewHandler) != -1)
+        return;
+    } catch (e) { }
+    this.possibleApplicationHandlers.appendElement(aNewHandler, false);
+  },
+
+  removePossibleApplicationHandler: function(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;
+    }
+
+    try {
+      var handlerIdx = this.possibleApplicationHandlers.indexOf(0, aHandler);
+      this.possibleApplicationHandlers.removeElementAt(handlerIdx);
+    } catch (e) { }
+  },
+
+  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.plugin && !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 ==
+          Components.interfaces.nsIHandlerInfo.useHelperApp &&
+        !gApplicationsPane.isValidHandlerApp(this.preferredApplicationHandler)) {
+      if (this.wrappedHandlerInfo.hasDefaultHandler)
+        return Components.interfaces.nsIHandlerInfo.useSystemDefault;
+      else
+        return Components.interfaces.nsIHandlerInfo.saveToDisk;
+    }
+
+    return this.wrappedHandlerInfo.preferredAction;
+  },
+
+  set preferredAction(aNewValue) {
+    // 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.plugin && 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 Components.interfaces.nsIMIMEInfo) &&
+        this.preferredAction == Components.interfaces.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 Components.interfaces.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: function() {
+    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.
+    return types ? types.split(",") : [];
+  },
+
+  disablePluginType: function() {
+    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: function() {
+    var disabledPluginTypes = this._getDisabledPluginTypes();
+
+    var type = this.type;
+    disabledPluginTypes = disabledPluginTypes.filter(function(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: function() {
+    this._handlerSvc.store(this.wrappedHandlerInfo);
+  },
+
+
+  //**************************************************************************//
+  // Icons
+
+  get smallIcon() {
+    return this._getIcon(16);
+  },
+
+  get largeIcon() {
+    return this._getIcon(32);
+  },
+
+  _getIcon: function(aSize) {
+    if (this.primaryExtension)
+      return "moz-icon://goat." + this.primaryExtension + "?size=" + aSize;
+
+    if (this.wrappedHandlerInfo instanceof Components.interfaces.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;
+  }
+};
+
+//****************************************************************************//
+// 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      : Components.classes["@mozilla.org/preferences-service;1"]
+                            .getService(Components.interfaces.nsIPrefBranch2),
+
+  _mimeSvc      : Components.classes["@mozilla.org/mime;1"]
+                            .getService(Components.interfaces.nsIMIMEService),
+
+  _helperAppSvc : Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
+                            .getService(Components.interfaces.nsIExternalHelperAppService),
+
+  _handlerSvc   : Components.classes["@mozilla.org/uriloader/handler-service;1"]
+                            .getService(Components.interfaces.nsIHandlerService),
+
+  _ioSvc        : Components.classes["@mozilla.org/network/io-service;1"]
+                            .getService(Components.interfaces.nsIIOService),
+
+
+  //**************************************************************************//
+  // Initialization & Destruction
+
+  init: function() {
+    // 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, false);
+    this._prefSvc.addObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this, false);
+
+    // Listen for window unload so we can remove our preference observers.
+    window.addEventListener("unload", this, false);
+
+    // 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?
+    this._sortColumn = document.getElementById("typeColumn")
+    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");
+    }
+
+    // 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
+      Components.classes["@mozilla.org/observer-service;1"]
+                .getService(Components.interfaces.nsIObserverService)
+                .notifyObservers(window, "app-handler-pane-loaded", null);
+    }
+    setTimeout(_delayedPaneLoad, 0, this);
+  },
+
+  destroy: function() {
+    window.removeEventListener("unload", this, false);
+    this._prefSvc.removeObserver(PREF_SHOW_PLUGINS_IN_LIST, this);
+    this._prefSvc.removeObserver(PREF_HIDE_PLUGINS_WITHOUT_EXTENSIONS, this);
+  },
+
+
+  //**************************************************************************//
+  // nsISupports
+
+  QueryInterface: function(aIID) {
+    if (aIID.equals(Components.interfaces.nsIObserver) ||
+        aIID.equals(Components.interfaces.nsIDOMEventListener ||
+        aIID.equals(Components.interfaces.nsISupports)))
+      return this;
+
+    throw Components.results.NS_ERROR_NO_INTERFACE;
+  },
+
+
+  //**************************************************************************//
+  // nsIObserver
+
+  observe: function (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: function(aEvent) {
+    if (aEvent.type == "unload")
+      this.destroy();
+  },
+
+
+  //**************************************************************************//
+  // Composed Model Construction
+
+  _loadData: function() {
+    this._loadPluginHandlers();
+    this._loadApplicationHandlers();
+  },
+
+  /**
+   * 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.
+   *
+   * I'll also note that my reading of nsPluginTag::RegisterWithCategoryManager
+   * suggests that enabledPlugin is only determined during registration
+   * and does not get updated when plugin.disable_full_page_plugin_for_types
+   * changes (unless modification of that preference spawns reregistration).
+   * 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: function() {
+    for (let i = 0; i < navigator.plugins.length; ++i) {
+      let plugin = navigator.plugins[i];
+      for (let j = 0; j < plugin.length; ++j) {
+        let type = plugin[j].type;
+
+        let handlerInfoWrapper;
+        if (type in this._handledTypes)
+          handlerInfoWrapper = this._handledTypes[type];
+        else {
+          let wrappedHandlerInfo =
+            this._mimeSvc.getFromTypeAndExtension(type, null);
+          handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo);
+          handlerInfoWrapper.handledOnlyByPlugin = true;
+          this._handledTypes[type] = handlerInfoWrapper;
+        }
+
+        handlerInfoWrapper.plugin = plugin;
+      }
+    }
+  },
+
+  /**
+   * Load the set of handlers defined by the application datastore.
+   */
+  _loadApplicationHandlers: function() {
+    var wrappedHandlerInfos = this._handlerSvc.enumerate();
+    while (wrappedHandlerInfos.hasMoreElements()) {
+      let wrappedHandlerInfo =
+        wrappedHandlerInfos.getNext().QueryInterface(Components.interfaces.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: function() {
+    // 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 Components.interfaces.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: function() {
+    // 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 each (let visibleType in 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: function(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
+   * @return {string} a description of the type
+   */
+  _describeType: function(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
+   * @return {string} a description of the action
+   */
+  _describePreferredAction: function(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)
+        return this._prefsBundle.getString("alwaysAsk");
+
+    switch (aHandlerInfo.preferredAction) {
+      case Components.interfaces.nsIHandlerInfo.saveToDisk:
+        return this._prefsBundle.getString("saveFile");
+
+      case Components.interfaces.nsIHandlerInfo.useHelperApp:
+        var preferredApp = aHandlerInfo.preferredApplicationHandler;
+        var name;
+        if (preferredApp instanceof Components.interfaces.nsILocalHandlerApp)
+          name = getDisplayNameForFile(preferredApp.executable);
+        else
+          name = preferredApp.name;
+        return this._prefsBundle.getFormattedString("useApp", [name]);
+
+      case Components.interfaces.nsIHandlerInfo.handleInternally:
+        // 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 Components.interfaces.nsIHandlerInfo.useSystemDefault:
+        return this._prefsBundle.getFormattedString("useDefault",
+                                                    [aHandlerInfo.defaultDescription]);
+
+      case kActionUsePlugin:
+        return this._prefsBundle.getFormattedString("usePluginIn",
+                                                    [aHandlerInfo.plugin.name,
+                                                     this._brandShortName]);
+    }
+  },
+
+  _selectLastSelectedType: function() {
+    // 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
+   * @return {boolean} whether or not it's valid
+   */
+  isValidHandlerApp: function(aHandlerApp) {
+    if (!aHandlerApp)
+      return false;
+
+    if (aHandlerApp instanceof Components.interfaces.nsILocalHandlerApp)
+      return this._isValidHandlerExecutable(aHandlerApp.executable);
+
+    if (aHandlerApp instanceof Components.interfaces.nsIWebHandlerApp)
+      return aHandlerApp.uriTemplate;
+
+    if (aHandlerApp instanceof Components.interfaces.nsIWebContentHandlerInfo)
+      return aHandlerApp.uri;
+
+    return false;
+  },
+
+  _isValidHandlerExecutable: function(aExecutable) {
+    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
+#ifdef XP_WIN
+#expand    aExecutable.leafName != "__MOZ_APP_NAME__.exe";
+#else
+#ifdef XP_MACOSX
+#expand    aExecutable.leafName != "__MOZ_APP_DISPLAYNAME__.app";
+#else
+#expand    aExecutable.leafName != "__MOZ_APP_NAME__-bin";
+#endif
+#endif
+  },
+
+  /**
+   * Rebuild the actions menu for the selected entry.  Gets called by
+   * the richlistitem constructor when an entry in the list gets selected.
+   */
+  rebuildActionsMenu: function() {
+    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);
+
+    var askMenuItem = document.createElement("menuitem");
+    askMenuItem.setAttribute("alwaysAsk", "true");
+    {
+      let 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.
+    if ((handlerInfo.wrappedHandlerInfo instanceof Components.interfaces.nsIMIMEInfo)) {
+      var saveMenuItem = document.createElement("menuitem");
+      saveMenuItem.setAttribute("action", Components.interfaces.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);
+    }
+
+    // Add a separator to distinguish these items from the helper app items
+    // that follow them.
+    let menuItem = document.createElement("menuseparator");
+    menuPopup.appendChild(menuItem);
+
+    // Create a menu item for the OS default application, if any.
+    if (handlerInfo.hasDefaultHandler) {
+      var defaultMenuItem = document.createElement("menuitem");
+      defaultMenuItem.setAttribute("action", Components.interfaces.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", Components.interfaces.nsIHandlerInfo.useHelperApp);
+      let label;
+      if (possibleApp instanceof Components.interfaces.nsILocalHandlerApp)
+        label = getDisplayNameForFile(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.plugin) {
+      var pluginMenuItem = document.createElement("menuitem");
+      pluginMenuItem.setAttribute("action", kActionUsePlugin);
+      let label = this._prefsBundle.getFormattedString("usePluginIn",
+                                                       [handlerInfo.plugin.name,
+                                                        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.
+#ifdef XP_WIN
+    // On Windows, selecting an application to open another application
+    // would be meaningless so we special case executables.
+    var executableType = Components.classes["@mozilla.org/mime;1"]
+                                   .getService(Components.interfaces.nsIMIMEService)
+                                   .getTypeFromExtension("exe");
+    if (handlerInfo.type != executableType)
+#endif
+    {
+      let menuItem = document.createElement("menuitem");
+      menuItem.setAttribute("oncommand", "gApplicationsPane.chooseApp(event)");
+      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.setAttribute("oncommand", "gApplicationsPane.manageApp(event)");
+      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 Components.interfaces.nsIHandlerInfo.handleInternally:
+        menu.selectedItem = internalMenuItem;
+        break;
+      case Components.interfaces.nsIHandlerInfo.useSystemDefault:
+        menu.selectedItem = defaultMenuItem;
+        break;
+      case Components.interfaces.nsIHandlerInfo.useHelperApp:
+        if (preferredApp)
+          menu.selectedItem =
+            possibleAppMenuItems.filter(function(v) v.handlerApp.equals(preferredApp))[0];
+        break;
+      case kActionUsePlugin:
+        menu.selectedItem = pluginMenuItem;
+        break;
+      case Components.interfaces.nsIHandlerInfo.saveToDisk:
+        menu.selectedItem = saveMenuItem;
+        break;
+    }
+  },
+
+
+  //**************************************************************************//
+  // Sorting & Filtering
+
+  _sortColumn: null,
+
+  /**
+   * Sort the list when the user clicks on a column header.
+   */
+  sort: function (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: function() {
+    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();
+  },
+
+  focusFilterBox: function() {
+    this._filter.focus();
+    this._filter.select();
+  },
+
+  //**************************************************************************//
+  // Changes
+
+  onSelectAction: function(aActionItem) {
+    this._storingAction = true;
+
+    try {
+      this._storeAction(aActionItem);
+    }
+    finally {
+      this._storingAction = false;
+    }
+  },
+
+  _storeAction: function(aActionItem) {
+    var typeItem = this._list.selectedItem;
+    var handlerInfo = this._handledTypes[typeItem.type];
+
+    if (aActionItem.hasAttribute("alwaysAsk")) {
+      handlerInfo.alwaysAskBeforeHandling = true;
+    }
+    else if (aActionItem.hasAttribute("action")) {
+      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.plugin && !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 == Components.interfaces.nsIHandlerInfo.useHelperApp)
+        handlerInfo.preferredApplicationHandler = aActionItem.handlerApp;
+
+      // Set the "always ask" flag.
+      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: function(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];
+
+    document.documentElement.openSubDialog(
+      "chrome://messenger/content/preferences/applicationManager.xul",
+      "", handlerInfo);
+
+    // 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));
+    }
+  },
+
+  chooseApp: function(aEvent) {
+    // Don't let the normal "on select action" handler get this event,
+    // as we handle it specially ourselves.
+    aEvent.stopPropagation();
+
+    var handlerApp;
+
+#ifdef XP_WIN
+    var params = {};
+    var handlerInfo = this._handledTypes[this._list.selectedItem.type];
+
+    params.mimeInfo = handlerInfo.wrappedHandlerInfo;
+
+    params.title         = this._prefsBundle.getString("fpTitleChooseApp");
+    params.description   = handlerInfo.description;
+    params.filename      = null;
+    params.handlerApp    = null;
+
+    window.openDialog("chrome://global/content/appPicker.xul", null,
+                      "chrome,modal,centerscreen,titlebar,dialog=yes",
+                      params);
+
+    if (params.handlerApp &&
+        params.handlerApp.executable &&
+        params.handlerApp.executable.isFile()) {
+      handlerApp = params.handlerApp;
+
+      // Add the app to the type's list of possible handlers.
+      handlerInfo.addPossibleApplicationHandler(handlerApp);
+    }
+#else
+    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker);
+    var winTitle = this._prefsBundle.getString("fpTitleChooseApp");
+    fp.init(window, winTitle, Components.interfaces.nsIFilePicker.modeOpen);
+    fp.appendFilters(Components.interfaces.nsIFilePicker.filterApps);
+
+    // 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.
+    if (fp.show() == Components.interfaces.nsIFilePicker.returnOK && fp.file &&
+        this._isValidHandlerExecutable(fp.file)) {
+      handlerApp = Components.classes["@mozilla.org/uriloader/local-handler-app;1"]
+                             .createInstance(Components.interfaces.nsILocalHandlerApp);
+      handlerApp.name = getDisplayNameForFile(fp.file);
+      handlerApp.executable = fp.file;
+
+      // Add the app to the type's list of possible handlers.
+      let handlerInfo = this._handledTypes[this._list.selectedItem.type];
+      handlerInfo.addPossibleApplicationHandler(handlerApp);
+    }
+#endif
+
+    // 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 (handlerApp) {
+      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(handlerApp)) {
+          actionsMenu.selectedIndex = i;
+          this.onSelectAction(menuItem);
+          break;
+        }
+      }
+    }
+  },
+
+  // 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: function() {
+    if (this._list.selectedItem)
+      this._list.setAttribute("lastSelectedType",
+                              this._list.selectedItem.getAttribute("type"));
+  },
+
+  _setIconClassForPreferredAction: function(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 Components.interfaces.nsIHandlerInfo.saveToDisk:
+        aElement.setAttribute(APP_ICON_ATTR_NAME, "save");
+        return true;
+
+      case Components.interfaces.nsIHandlerInfo.handleInternally:
+        break;
+
+      case kActionUsePlugin:
+        aElement.setAttribute(APP_ICON_ATTR_NAME, "plugin");
+        return true;
+    }
+    aElement.removeAttribute(APP_ICON_ATTR_NAME);
+    return false;
+  },
+
+  _getIconURLForPreferredAction: function(aHandlerInfo) {
+    switch (aHandlerInfo.preferredAction) {
+      case Components.interfaces.nsIHandlerInfo.useSystemDefault:
+        return this._getIconURLForSystemDefault(aHandlerInfo);
+
+      case Components.interfaces.nsIHandlerInfo.useHelperApp:
+        let (preferredApp = aHandlerInfo.preferredApplicationHandler) {
+          if (this.isValidHandlerApp(preferredApp))
+            return this._getIconURLForHandlerApp(preferredApp);
+        }
+        break;
+
+      // 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: function(aHandlerApp) {
+    if (aHandlerApp instanceof Components.interfaces.nsILocalHandlerApp)
+      return this._getIconURLForFile(aHandlerApp.executable);
+
+    if (aHandlerApp instanceof Components.interfaces.nsIWebHandlerApp)
+      return this._getIconURLForWebApp(aHandlerApp.uriTemplate);
+
+    if (aHandlerApp instanceof Components.interfaces.nsIWebContentHandlerInfo)
+      return this._getIconURLForWebApp(aHandlerApp.uri)
+
+    // We know nothing about other kinds of handler apps.
+    return "";
+  },
+
+  _getIconURLForFile: function(aFile) {
+    var fph = this._ioSvc.getProtocolHandler("file")
+                  .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
+    var urlSpec = fph.getURLSpecFromFile(aFile);
+
+    return "moz-icon://" + urlSpec + "?size=16";
+  },
+
+  _getIconURLForWebApp: function(aWebAppURITemplate) {
+    var uri = this._ioSvc.newURI(aWebAppURITemplate, null, null);
+
+    // 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))
+      return uri.prePath + "/favicon.ico";
+
+    return /^https?/.test(uri.scheme) ? uri.resolve("/favicon.ico") : "";
+  },
+
+  _getIconURLForSystemDefault: function(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 Components.interfaces.nsIMIMEInfo &&
+          wrappedHandlerInfo instanceof Components.interfaces.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;
+  }
+};
new file mode 100755
--- /dev/null
+++ b/mail/components/preferences/applications.xul
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is the Firefox Preferences System.
+   -
+   - The Initial Developer of the Original Code is
+   - Ben Goodger.
+   - Portions created by the Initial Developer are Copyright (C) 2005
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Ben Goodger <ben@mozilla.org>
+   -   Jeff Walden <jwalden+code@mit.edu>.
+   -   Asaf Romano <mozilla.mano@sent.com>
+   -   Myk Melez <myk@mozilla.org>
+   -   Magnus Melin <mkmelin+mozilla@iki.fi>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the LGPL or the GPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay [
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  <!ENTITY % applicationsDTD SYSTEM "chrome://messenger/locale/preferences/applications.dtd">
+  %brandDTD;
+  %applicationsDTD;
+]>
+
+<overlay id="ApplicationsPaneOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <prefpane id="paneApplications"
+            onpaneload="gApplicationsPane.init();"
+            flex="1">
+
+    <preferences id="downloadDirPreferences">
+      <preference id="browser.download.useDownloadDir"
+                  name="browser.download.useDownloadDir"
+                  type="bool"/>
+      <preference id="browser.download.folderList"
+                  name="browser.download.folderList"
+                  type="int"/>
+      <preference id="browser.download.downloadDir"
+                  name="browser.download.downloadDir"
+                  type="file"/>
+      <preference id="browser.download.dir"
+                  name="browser.download.dir"
+                  type="file"
+                  onchange="gDownloadDirSection.readDownloadDirPref();"/>
+      <preference id="pref.downloads.disable_button.edit_actions"
+                  name="pref.downloads.disable_button.edit_actions"
+                  type="bool"/>
+    </preferences>
+
+    <script type="application/javascript"
+            src="chrome://messenger/content/preferences/applications.js"/>
+
+    <keyset>
+      <key key="&focusSearch1.key;" modifiers="accel"
+           oncommand="gApplicationsPane.focusFilterBox();"/>
+      <key key="&focusSearch2.key;" modifiers="accel"
+           oncommand="gApplicationsPane.focusFilterBox();"/>
+    </keyset>
+
+    <hbox>
+      <textbox id="filter" flex="1"
+               type="search"
+               emptytext="&filter.emptytext;"
+               aria-controls="handlersView"
+               oncommand="gApplicationsPane.rebuildView();"/>
+    </hbox>
+
+    <separator class="thin"/>
+
+    <richlistbox id="handlersView" orient="vertical" persist="lastSelectedType"
+                 preference="pref.downloads.disable_button.edit_actions"
+                 onselect="gApplicationsPane.onSelectionChanged();">
+      <listheader equalsize="always" style="border: 0; padding: 0; -moz-appearance: none;">
+        <treecol id="typeColumn" label="&typeColumn.label;" value="type"
+                 accesskey="&typeColumn.accesskey;" persist="sortDirection"
+                 flex="1" onclick="gApplicationsPane.sort(event);"
+                 sortDirection="ascending"/>
+        <treecol id="actionColumn" label="&actionColumn2.label;" value="action"
+                 accesskey="&actionColumn2.accesskey;" persist="sortDirection"
+                 flex="1" onclick="gApplicationsPane.sort(event);"/>
+      </listheader>
+    </richlistbox>
+
+    <separator class="thin"/>
+
+    <script type="application/javascript"
+            src="chrome://messenger/content/preferences/downloads.js"/>
+
+    <vbox align="start">
+      <radiogroup id="saveWhere" flex="1"
+                  preference="browser.download.useDownloadDir"
+                  onsyncfrompreference="return gDownloadDirSection.onReadUseDownloadDir();">
+      <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 gDownloadDirSection.readDownloadDirPref();"
+                   onsynctopreference="return gDownloadDirSection.writeFolderList();"/>
+        <button id="chooseFolder" oncommand="gDownloadDirSection.chooseFolder();"
+#ifdef XP_MACOSX
+                accesskey="&chooseFolderMac.accesskey;"
+                label="&chooseFolderMac.label;"
+#else
+                accesskey="&chooseFolderWin.accesskey;"
+                label="&chooseFolderWin.label;"
+#endif
+                preference="browser.download.folderList"
+                onsynctopreference="return gDownloadDirSection.writeFolderList();"/>
+      </hbox>
+      <radio id="alwaysAsk" value="false"
+             label="&alwaysAsk.label;" accesskey="&alwaysAsk.accesskey;"/>
+      </radiogroup>
+    </vbox>
+  </prefpane>
+</overlay>
deleted file mode 100644
--- a/mail/components/preferences/changeaction.js
+++ /dev/null
@@ -1,224 +0,0 @@
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the Download Actions Manager.
-#
-# The Initial Developer of the Original Code is
-# Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2000-2005
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-var gChangeActionDialog = {
-  _item             : null,
-  _bundle           : null,
-  _lastSelectedMode : null,
-  _lastSelectedSave : null,
-
-  init: function ()
-  {
-    this._item = window.arguments[0];
-    this._bundle = document.getElementById("bundlePreferences");
-    
-    var typeField = document.getElementById("typeField");
-    typeField.value = this._item.typeName;
-    
-    var extensionField = document.getElementById("extensionField");
-    var ext = "." + this._item.extension.toLowerCase();
-    var contentType = this._item.type;
-    extensionField.value = this._bundle.getFormattedString("extensionStringFormat", [ext, contentType]);
-    
-    var typeIcon = document.getElementById("typeIcon");
-    typeIcon.src = this._item.bigIcon;
-
-    // Custom App Handler Path - this must be set before we set the selected
-    // radio button because the selection event handler for the radio group
-    // requires the extapp handler field to be non-empty for the extapp radio
-    // button to be selected. 
-    var customApp = document.getElementById("customApp");
-    if (this._item.customHandler)
-      customApp.file = this._item.customHandler;
-    else
-      customApp.file = null;
-
-    var defaultApp = document.getElementById("defaultApp");
-    var defaultAppIcon = null;
-    var fallbackIconURL = "moz-icon://goat?contentType=" + this._item.type + "&size=16";
-    if (this._item.mimeInfo instanceof Components.interfaces.nsIPropertyBag) {
-      try {
-        defaultAppIcon = this._item.mimeInfo.getProperty("defaultApplicationIconURL");
-      }
-      catch (e) { }
-      if (defaultAppIcon)
-        defaultAppIcon += "?size=16";
-    }
-    defaultApp.image = defaultAppIcon || fallbackIconURL;
-    defaultApp.label = this._item.mimeInfo.defaultDescription;
-     
-    // Selected Action Radiogroup
-    var handlerGroup = document.getElementById("handlerGroup");
-    if (this._item.handleMode == FILEACTION_OPEN_DEFAULT)
-      handlerGroup.selectedItem = document.getElementById("openDefault");
-    else if (this._item.handleMode == FILEACTION_SAVE_TO_DISK)
-      handlerGroup.selectedItem = document.getElementById("saveToDisk");
-    else
-      handlerGroup.selectedItem = document.getElementById("openApplication");
-
-    this._lastSelectedMode = handlerGroup.selectedItem;
-    
-    // Figure out the last selected Save As mode
-    var saveToOptions = document.getElementById("saveToOptions");
-    this._lastSelectedSave = saveToOptions.selectedItem;
-
-    // We don't let users open .exe files or random binary data directly 
-    // from the browser at the moment because of security concerns. 
-    var mimeType = this._item.mimeInfo.MIMEType;
-    if (mimeType == "application/octet-stream" ||
-        mimeType == "application/x-msdownload") {
-      document.getElementById("openApplication").disabled = true;
-      document.getElementById("openDefault").disabled = true;
-      handlerGroup.selectedItem = document.getElementById("saveToDisk");
-    }
-  },
-  
-  onAccept: function ()
-  {
-    var contentType = this._item.mimeInfo.MIMEType;
-    var handlerGroup = document.getElementById("handlerGroup");
-    switch (handlerGroup.selectedItem.value) {
-    case "system":
-      this._item.handledOnlyByPlugin = false;
-      this._item.handleMode = FILEACTION_OPEN_DEFAULT;
-      var defaultDescr = this._item.mimeInfo.defaultDescription;
-      this._item.action = this._bundle.getFormattedString("openWith", [defaultDescr]);
-      break;
-    case "app":
-      this._item.handledOnlyByPlugin = false;
-      this._item.handleMode = FILEACTION_OPEN_CUSTOM;
-      var customApp = document.getElementById("customApp");
-      this._item.action = this._bundle.getFormattedString("openWith", [customApp.label]);        
-      break;  
-    case "save":
-      this._item.handledOnlyByPlugin = false;
-      this._item.handleMode = FILEACTION_SAVE_TO_DISK;
-      this._item.action = this._bundle.getString("saveToDisk");
-      break;  
-    }
-    
-    // The opener uses the modifications to the FileAction item to update the
-    // datasource.
-    return true;
-  },
-  
-  doEnabling: function (aSelectedItem)
-  {
-    var defaultApp            = document.getElementById("defaultApp");
-    var saveToDefault         = document.getElementById("saveToDefault");
-    var saveToCustom          = document.getElementById("saveToCustom");
-    var customDownloadFolder  = document.getElementById("customDownloadFolder");
-    var chooseCustomDownloadFolder = document.getElementById("chooseCustomDownloadFolder");
-    var saveToAskMe           = document.getElementById("saveToAskMe");
-    var changeApp             = document.getElementById("changeApp");
-    var customApp             = document.getElementById("customApp");
-    
-    switch (aSelectedItem.id) {
-    case "openDefault":
-      changeApp.disabled = customApp.disabled = saveToDefault.disabled = saveToCustom.disabled = customDownloadFolder.disabled = chooseCustomDownloadFolder.disabled = saveToAskMe.disabled = true;
-      defaultApp.disabled = false;
-      break;
-    case "openApplication":
-      defaultApp.disabled = saveToDefault.disabled = saveToCustom.disabled = customDownloadFolder.disabled = chooseCustomDownloadFolder.disabled = saveToAskMe.disabled =  true;
-      changeApp.disabled = customApp.disabled = false;
-      if (!customApp.file && !this.changeApp()) {
-        this._lastSelectedMode.click();
-        return;
-      }
-      break;
-    case "saveToDisk":
-      changeApp.disabled = customApp.disabled = defaultApp.disabled = true;
-      var saveToOptions = document.getElementById("saveToOptions");
-      customDownloadFolder.disabled = chooseCustomDownloadFolder.disabled = !(saveToOptions.selectedItem.id == "saveToCustom");
-      saveToDefault.disabled = saveToCustom.disabled = saveToAskMe.disabled = false;
-      break;
-    }
-    this._lastSelectedMode = aSelectedItem;
-  },
-  
-  doSaveToDiskEnabling: function (aSelectedItem)
-  {
-    var isSaveToCustom = aSelectedItem.id == "saveToCustom";
-    var customDownloadFolder = document.getElementById("customDownloadFolder");
-    var chooseCustomDownloadFolder = document.getElementById("chooseCustomDownloadFolder");
-    chooseCustomDownloadFolder.disabled = customDownloadFolder.disabled = !isSaveToCustom;
-    
-    if (isSaveToCustom && 
-        !customDownloadFolder.file && !this.changeCustomFolder()) {
-      this._lastSelectedSave.click();
-      return;
-    }
-    this._lastSelectedSave = aSelectedItem;
-  },
-  
-  changeApp: function ()
-  {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    var fp = Components.classes["@mozilla.org/filepicker;1"]
-                       .createInstance(nsIFilePicker);
-    var winTitle = this._bundle.getString("fpTitleChooseApp");
-    fp.init(window, winTitle, nsIFilePicker.modeOpen);
-    fp.appendFilters(nsIFilePicker.filterApps);
-    if (fp.show() == nsIFilePicker.returnOK && fp.file) {
-      var customApp = document.getElementById("customApp");
-      customApp.file = fp.file;
-      this._item.customHandler = fp.file;      
-      return true;
-    }
-    return false;
-  },
-  
-  changeCustomFolder: function ()
-  {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    var fp = Components.classes["@mozilla.org/filepicker;1"]
-                       .createInstance(nsIFilePicker);
-
-    // extract the window title
-    var winTitle = this._bundle.getString("fpTitleChooseDL");
-    fp.init(window, winTitle, nsIFilePicker.modeGetFolder);
-    if (fp.show() == nsIFilePicker.returnOK && fp.file) {
-      var customDownloadFolder = document.getElementById("customDownloadFolder");
-      customDownloadFolder.file = fp.file;
-      customDownloadFolder.label = fp.file.path;
-      return true;
-    }
-    return false;
-  },
-};
-
deleted file mode 100644
--- a/mail/components/preferences/changeaction.xul
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the Download Actions Manager.
-#
-# The Initial Developer of the Original Code is
-# Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2000-2005
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css" type="text/css"?>
-<?xml-stylesheet href="chrome://messenger/skin/preferences/preferences.css" type="text/css"?>
-
-<!DOCTYPE window SYSTEM "chrome://messenger/locale/preferences/changeaction.dtd">
-
-<dialog id="ChangeActionDialog" title="&changeAction.title;"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="gChangeActionDialog.init();" 
-        ondialogaccept="return gChangeActionDialog.onAccept();" 
-        style="width: &window.width;;"
-        persist="screenX screenY">
-
-  <script type="application/x-javascript" src="chrome://messenger/content/preferences/actionsshared.js"/>
-  <script type="application/x-javascript" src="chrome://messenger/content/preferences/changeaction.js"/>
-  
-  <stringbundle id="bundlePreferences" src="chrome://messenger/locale/preferences/preferences.properties"/>
-
-  <hbox id="changeActionHeader" align="center" class="indent">
-    <image id="typeIcon"/>
-    <vbox flex="1">
-      <label id="typeField" crop="right"/>
-      <label id="extensionField" crop="right"/>
-    </vbox>
-  </hbox>
-  <vbox id="changeActionContent" flex="1">
-    <label control="handlerGroup">&whenDownloading.label;</label>
-    <radiogroup id="handlerGroup" onselect="gChangeActionDialog.doEnabling(this.selectedItem);" 
-                flex="1" aria-describedby="changeActionHeader">
-      <separator class="thin"/>
-      <radio id="openDefault" value="system" 
-             label="&openDefault.label;" accesskey="&openDefault.accesskey;"/>
-      <filefield class="indent" id="defaultApp" disabled="true" aria-labelledby="openDefault"/>
-      <separator class="thin"/>
-      <radio id="openApplication" value="app" 
-             label="&openApplication.label;" accesskey="&openApplication.accesskey;"/>
-      <hbox align="center">
-        <filefield id="customApp" class="indent" flex="1" disabled="true" aria-labelledby="openApplication"/>
-        <button id="changeApp" oncommand="gChangeActionDialog.changeApp();" 
-                label="&changeApp.label;" accesskey="&changeApp.accesskey;"
-                disabled="true"/>
-      </hbox>
-      <separator class="thin"/>
-      <radio id="saveToDisk" value="save" 
-             label="&saveToDisk.label;" accesskey="&saveToDisk.accesskey;"/>
-      <radiogroup id="saveToOptions" class="indent" onselect="gChangeActionDialog.doSaveToDiskEnabling(this.selectedItem);"
-                  hidden="true" aria-labelledby="saveToDisk">
-        <radio id="saveToDefault" value="default" selected="true"
-               label="&saveToDefaultFolder.label;" accesskey="&saveToDefaultFolder.accesskey;"/>
-        <radio id="saveToCustom" value="custom"
-               label="&saveToThisFolder.label;" accesskey="&saveToThisFolder.accesskey;"/>
-        <hbox align="center" class="indent">
-          <filefield id="customDownloadFolder" flex="1" aria-labelledby="saveToCustom"/>
-          <button id="chooseCustomDownloadFolder" oncommand="gChangeActionDialog.changeCustomFolder();"
-                  label="&chooseFolder.label;" accesskey="&chooseFolder.accesskey;"/>
-        </hbox>
-        <radio id="saveToAskMe" value="ask"
-               label="&saveToAskMe.label;" accesskey="&saveToAskMe.accesskey;"/>
-      </radiogroup>
-    </radiogroup>
-  </vbox>
-</dialog>
-
deleted file mode 100644
--- a/mail/components/preferences/downloadactions.js
+++ /dev/null
@@ -1,777 +0,0 @@
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the Download Actions Manager.
-#
-# The Initial Developer of the Original Code is
-# Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2000-2005
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-const kRootTypePrefix = "urn:mimetype:";
-
-///////////////////////////////////////////////////////////////////////////////
-// MIME Types Datasource RDF Utils
-function NC_URI(aProperty)
-{
-  return "http://home.netscape.com/NC-rdf#" + aProperty;
-}
-
-function MIME_URI(aType)
-{
-  return "urn:mimetype:" + aType;
-}
-
-function HANDLER_URI(aHandler)
-{
-  return "urn:mimetype:handler:" + aHandler;
-}
-
-function APP_URI(aType)
-{
-  return "urn:mimetype:externalApplication:" + aType;
-}
-
-var gDownloadActionsWindow = {  
-  _tree         : null,
-  _editButton   : null,
-  _removeButton : null,
-  _actions      : [],
-  _plugins      : {},
-  _bundle       : null,
-  _pref         : Components.classes["@mozilla.org/preferences-service;1"]
-                            .getService(Components.interfaces.nsIPrefBranch),
-  _mimeSvc      : Components.classes["@mozilla.org/mime;1"]
-                            .getService(Components.interfaces.nsIMIMEService),
-  _excludingPlugins           : false,
-  _excludingMissingExtensions : false,
-  
-  init: function ()
-  {
-    (this._editButton = document.getElementById("editFileHandler")).disabled = true;
-    (this._removeButton = document.getElementById("removeFileHandler")).disabled = true;    
-   
-    // Initialize the File Type list
-    this._bundle = document.getElementById("bundlePreferences");
-    this._tree = document.getElementById("fileHandlersList");
-    this._loadView();
-    // Determine any exclusions being applied - e.g. don't show types for which
-    // only a plugin handler exists, don't show types lacking extensions, etc. 
-    this._view._rowCount = this._updateExclusions();    
-    this._tree.treeBoxObject.view = this._view;  
-
-    var indexToSelect = parseInt(this._tree.getAttribute("lastSelected"));
-    if (indexToSelect < this._tree.view.rowCount)
-      this._tree.view.selection.select(indexToSelect);
-    this._tree.focus();    
-  },
-  
-  _loadView: function ()
-  {
-    // Reset ALL the collections and state flags, because we can call this after
-    // the window has initially displayed by resetting the filter. 
-    this._actions = [];
-    this._plugins = {};
-    this._view._filtered = false;
-    this._view._filterSet = [];
-    this._view._usingExclusionSet = false;
-    this._view._exclusionSet = [];
-    this._view._filterValue = "";
-
-    this._loadPluginData();
-    this._loadMIMERegistryData();
-  },
-  
-  _updateRowCount: function (aNewRowCount)
-  {
-    var oldCount = this._view._rowCount;
-    this._view._rowCount = 0;
-    this._tree.treeBoxObject.rowCountChanged(0, -oldCount);
-    this._view._rowCount = aNewRowCount;
-    this._tree.treeBoxObject.rowCountChanged(0, aNewRowCount);
-  },
-  
-  uninit: function ()
-  {
-  },
-  
-  _updateExclusions: function ()
-  {
-    this._excludingPlugins = true;
-    this._excludingMissingExtensions = true;    
-    this._view._exclusionSet = [].concat(this._actions);
-    if (this._excludingMissingExtensions) {
-      this._view._usingExclusionSet = true;
-      for (var i = 0; i < this._view._exclusionSet.length;) {
-        if (!this._view._exclusionSet[i].hasExtension)
-          this._view._exclusionSet.splice(i, 1);
-        else
-          ++i;
-      }
-    }
-    if (this._excludingPlugins) {
-      this._view._usingExclusionSet = true;
-      for (i = 0; i < this._view._exclusionSet.length;) {
-        if (this._view._exclusionSet[i].handledOnlyByPlugin)
-          this._view._exclusionSet.splice(i, 1);
-        else
-          ++i        
-      }      
-    }
-
-    return this._view._usingExclusionSet ? this._view._exclusionSet.length 
-                                         : this._view._filtered ? this._view._filterSet.length 
-                                                                : this._actions.length;
-  },   
-  
-  _loadPluginData: function ()
-  {
-  },
-
-  _createAction: function (aMIMEType, aActionName, 
-                           aIsEditable, aHandleMode, aCustomHandler,
-                           aPluginAvailable, aPluginEnabled, 
-                           aHandledOnlyByPlugin)
-  {
-    var newAction = !(aMIMEType in this._plugins);
-    var action = newAction ? new FileAction() : this._plugins[aMIMEType];
-    action.type = aMIMEType;
-    var info = this._mimeSvc.getFromTypeAndExtension(action.type, null);
-    
-    // File Extension
-    try {
-      action.extension = info.primaryExtension;
-    }
-    catch (e) {
-      action.extension = this._bundle.getString("extensionNone");
-      action.hasExtension = false;
-    }
-    
-    // Large and Small Icon
-    try {
-      action.smallIcon = "moz-icon://goat." + info.primaryExtension + "?size=16";
-      action.bigIcon = "moz-icon://goat." + info.primaryExtension + "?size=32";
-    }
-    catch (e) {
-      action.smallIcon = "moz-icon://goat?size=16&contentType=" + info.MIMEType;
-      action.bigIcon = "moz-icon://goat?contentType=" + info.MIMEType + "&size=32";
-    }
-
-    // Pretty Type Name
-    if (info.description == "") {
-      try {
-        action.typeName = this._bundle.getFormattedString("fileEnding", [info.primaryExtension.toUpperCase()]);
-      }
-      catch (e) { 
-        // Wow, this sucks, just show the MIME type as a last ditch effort to display
-        // the type of file that this is. 
-        action.typeName = info.MIMEType;
-      }
-    }
-    else
-      action.typeName = info.description;
-
-    // Pretty Action Name
-    if (aActionName)
-      action.action         = aActionName;
-    action.pluginAvailable  = aPluginAvailable;
-    action.pluginEnabled    = aPluginEnabled;
-    action.editable         = aIsEditable;
-    action.handleMode       = aHandleMode;
-    action.customHandler    = aCustomHandler;
-    action.mimeInfo         = info;
-    action.handledOnlyByPlugin  = aHandledOnlyByPlugin
-    
-    if (newAction && !(action.handledOnlyByPlugin && !action.pluginEnabled)) {
-      this._actions.push(action);
-      this._plugins[action.type] = action;
-    }      
-    return action;
-  },
-  
-  _loadMIMEDS: function ()
-  {
-    var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
-                                .getService(Components.interfaces.nsIProperties);
-    
-    var file = fileLocator.get("UMimTyp", Components.interfaces.nsIFile);
-
-    var ioService = Components.classes["@mozilla.org/network/io-service;1"]
-                              .getService(Components.interfaces.nsIIOService);
-    var fileHandler = ioService.getProtocolHandler("file")
-                               .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
-    this._mimeDS = this._rdf.GetDataSourceBlocking(fileHandler.getURLSpecFromFile(file));
-  },
-  
-  _getLiteralValue: function (aResource, aProperty)
-  {
-    var property = this._rdf.GetResource(NC_URI(aProperty));
-    var value = this._mimeDS.GetTarget(aResource, property, true);
-    if (value)
-      return value.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
-    return "";
-  },
-  
-  _getChildResource: function (aResource, aProperty)
-  {
-    var property = this._rdf.GetResource(NC_URI(aProperty));
-    return this._mimeDS.GetTarget(aResource, property, true);
-  },
-  
-  _getDisplayNameForFile: function (aFile)
-  {
-#ifdef XP_WIN
-    if (aFile instanceof Components.interfaces.nsILocalFileWin) {
-      try {
-        return aFile.getVersionInfoField("FileDescription"); 
-      }
-      catch (e) {
-        // fall through to the filename
-      }
-    }
-#endif
-    // XXXben - Read the bundle name on OS X.
-    var ios = Components.classes["@mozilla.org/network/io-service;1"]
-                        .getService(Components.interfaces.nsIIOService);
-    var url = ios.newFileURI(aFile).QueryInterface(Components.interfaces.nsIURL);
-    return url.fileName;
-  },  
-  
-  _loadMIMERegistryData: function ()
-  {
-    this._rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
-                          .getService(Components.interfaces.nsIRDFService);
-    this._loadMIMEDS();                          
-                          
-    var root = this._rdf.GetResource("urn:mimetypes:root");
-    var container = Components.classes["@mozilla.org/rdf/container;1"]
-                              .createInstance(Components.interfaces.nsIRDFContainer);
-    container.Init(this._mimeDS, root);
-    
-    var elements = container.GetElements();
-    while (elements.hasMoreElements()) {
-      var type = elements.getNext();
-      if (!(type instanceof Components.interfaces.nsIRDFResource))
-        break;
-      var editable = this._getLiteralValue(type, "editable") == "true";
-      if (!editable)
-        continue;
-      
-      var handler = this._getChildResource(type, "handlerProp");
-      var alwaysAsk = this._getLiteralValue(handler, "alwaysAsk") == "true";
-      if (alwaysAsk)
-        continue;
-      var saveToDisk        = this._getLiteralValue(handler, "saveToDisk") == "true";
-      var useSystemDefault  = this._getLiteralValue(handler, "useSystemDefault") == "true";
-      var editable          = this._getLiteralValue(type, "editable") == "true";
-      var handledInternally = this._getLiteralValue(handler, "handleInternal") == "true";
-      var externalApp       = this._getChildResource(handler, "externalApplication");
-      var externalAppPath   = this._getLiteralValue(externalApp, "path");
-      try {
-        var customHandler = Components.classes["@mozilla.org/file/local;1"]
-                                      .createInstance(Components.interfaces.nsILocalFile);
-        customHandler.initWithPath(externalAppPath);
-      }
-      catch (e) {
-        customHandler = null;
-      }      
-      if (customHandler && !customHandler.exists())
-        customHandler = null;
-      var mimeType = this._getLiteralValue(type, "value");
-      var typeInfo = this._mimeSvc.getFromTypeAndExtension(mimeType, null);
-
-      // Determine the pretty name of the associated action.
-      var actionName = "";
-      var handleMode = 0;
-      if (saveToDisk) {
-        // Save the file to disk
-        actionName = this._bundle.getString("saveToDisk");
-        handleMode = FILEACTION_SAVE_TO_DISK;
-      }
-      else if (useSystemDefault) {
-        // Use the System Default handler
-        actionName = this._bundle.getFormattedString("openWith", 
-                                                     [typeInfo.defaultDescription]);
-        handleMode = FILEACTION_OPEN_DEFAULT;
-      }
-      else {
-        // Custom Handler
-        if (customHandler) {
-          actionName = this._bundle.getFormattedString("openWith", 
-                                                       [this._getDisplayNameForFile(customHandler)]);
-          handleMode = FILEACTION_OPEN_CUSTOM;
-        }
-        else {
-          // Corrupt datasource, invalid custom handler path. Revert to default.
-          actionName = this._bundle.getFormattedString("openWith", 
-                                                       [typeInfo.defaultDescription]);
-          handleMode = FILEACTION_OPEN_DEFAULT;
-        }
-      }
-
-      if (handledInternally)
-        handleMode = FILEACTION_OPEN_INTERNALLY;
-      
-      var pluginAvailable = mimeType in this._plugins && this._plugins[mimeType].pluginAvailable;
-      var pluginEnabled = pluginAvailable && this._plugins[mimeType].pluginEnabled;
-      if (pluginEnabled) {
-        handleMode = FILEACTION_OPEN_PLUGIN;
-        actionName = null;
-      }
-      var action = this._createAction(mimeType, actionName, editable, handleMode, 
-                                      customHandler, pluginAvailable, pluginEnabled,
-                                      false);
-    }
-  },
-  
-  _view: {
-    _filtered           : false,
-    _filterSet          : [],
-    _usingExclusionSet  : false,
-    _exclusionSet       : [],
-    _filterValue        : "",
-
-    _rowCount: 0,
-    get rowCount() 
-    { 
-      return this._rowCount; 
-    },
-    
-    get activeCollection ()
-    {
-      return this._filtered ? this._filterSet 
-                            : this._usingExclusionSet ? this._exclusionSet 
-                                                      : gDownloadActionsWindow._actions;
-    },
-
-    getItemAtIndex: function (aIndex)
-    {
-      return this.activeCollection[aIndex];
-    },
-    
-    getCellText: function (aIndex, aColumn)
-    {
-      switch (aColumn.id) {
-      case "fileExtension":
-        return this.getItemAtIndex(aIndex).extension.toUpperCase();
-      case "fileType":
-        return this.getItemAtIndex(aIndex).typeName;
-      case "fileMIMEType":
-        return this.getItemAtIndex(aIndex).type;
-      case "fileHandler":
-        return this.getItemAtIndex(aIndex).action;
-      }
-      return "";
-    },
-    getImageSrc: function (aIndex, aColumn) 
-    {
-      if (aColumn.id == "fileExtension") 
-        return this.getItemAtIndex(aIndex).smallIcon;
-      return "";
-    },
-    _selection: null, 
-    get selection () { return this._selection; },
-    set selection (val) { this._selection = val; return val; },
-    getRowProperties: function (aIndex, aProperties) {},
-    getCellProperties: function (aIndex, aColumn, aProperties) {},
-    getColumnProperties: function (aColumn, aProperties) {},
-    isContainer: function (aIndex) { return false; },
-    isContainerOpen: function (aIndex) { return false; },
-    isContainerEmpty: function (aIndex) { return false; },
-    isSeparator: function (aIndex) { return false; },
-    isSorted: function (aIndex) { return false; },
-    canDrop: function (aIndex, aOrientation) { return false; },
-    drop: function (aIndex, aOrientation) {},
-    getParentIndex: function (aIndex) { return -1; },
-    hasNextSibling: function (aParentIndex, aIndex) { return false; },
-    getLevel: function (aIndex) { return 0; },
-    getProgressMode: function (aIndex, aColumn) {},    
-    getCellValue: function (aIndex, aColumn) {},
-    setTree: function (aTree) {},    
-    toggleOpenState: function (aIndex) { },
-    cycleHeader: function (aColumn) {},    
-    selectionChanged: function () {},    
-    cycleCell: function (aIndex, aColumn) {},    
-    isEditable: function (aIndex, aColumn) { return false; },
-    isSelectable: function (aIndex, aColumn) { return false; },
-    setCellValue: function (aIndex, aColumn, aValue) {},    
-    setCellText: function (aIndex, aColumn, aValue) {},    
-    performAction: function (aAction) {},  
-    performActionOnRow: function (aAction, aIndex) {},    
-    performActionOnCell: function (aAction, aindex, aColumn) {}
-  },
-
-  removeFileHandler: function ()
-  {
-    var selection = this._tree.view.selection; 
-    if (selection.count < 1)
-      return;
-      
-    var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
-                                  .getService(Components.interfaces.nsIPromptService);
-    var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0;
-    flags += promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1;
-
-    var title = this._bundle.getString("removeTitle" + (selection.count > 1 ? "Multiple" : "Single"));
-    var message = this._bundle.getString("removeMessage" + (selection.count > 1 ? "Multiple" : "Single"));
-    var button = this._bundle.getString("removeButton" + (selection.count > 1 ? "Multiple" : "Single"));
-    rv = promptService.confirmEx(window, title, message, flags, button, 
-                                 null, null, null, { value: 0 });
-    if (rv != 0)
-      return;     
-
-    var rangeCount = selection.getRangeCount();
-    var lastSelected = 0;
-    var mimeDSDirty = false;
-    for (var i = 0; i < rangeCount; ++i) {
-      var min = { }; var max = { };
-      selection.getRangeAt(i, min, max);
-      for (var j = min.value; j <= max.value; ++j) {
-        var item = this._view.getItemAtIndex(j);
-        if (!item.handledOnlyByPlugin) {
-          // There is data for this type in the MIME registry, so make sure we
-          // remove it from the MIME registry. We don't disable the plugin here because
-          // if we do there's currently no way through the UI to re-enable it. We may
-          // come up with some sort of solution for that at a later date. 
-          var typeRes = this._rdf.GetResource(MIME_URI(item.type));
-          var handlerRes = this._getChildResource(typeRes, "handlerProp");
-          var extAppRes = this._getChildResource(handlerRes, "externalApplication");
-          this._cleanResource(extAppRes);
-          this._cleanResource(handlerRes);
-          this._cleanResource(typeRes); 
-          mimeDSDirty = true;         
-        }
-        lastSelected = (j + 1) >= this._view.rowCount ? j-1 : j;
-      }
-    }
-    if (mimeDSDirty && 
-        this._mimeDS instanceof Components.interfaces.nsIRDFRemoteDataSource)
-      this._mimeDS.Flush();
-    
-    // Just reload the list to make sure deletions are respected
-    this._loadView();
-    this._updateRowCount(this._updateExclusions());
-
-    selection.select(lastSelected);
-  },
-  
-  _cleanResource: function (aResource)
-  {
-    var labels = this._mimeDS.ArcLabelsOut(aResource);
-    while (labels.hasMoreElements()) {
-      var arc = labels.getNext();
-      if (!(arc instanceof Components.interfaces.nsIRDFResource))
-        break;
-      var target = this._mimeDS.GetTarget(aResource, arc, true);
-      this._mimeDS.Unassert(aResource, arc, target);
-    }
-  },
-  
-  _disablePluginForItem: function (aItem)
-  {
-  },
-  
-  _enablePluginForItem: function (aItem)
-  {
-  },
-  
-  _ensureMIMERegistryEntry: function (aItem)
-  {
-    var root = this._rdf.GetResource("urn:mimetypes:root");
-    var container = Components.classes["@mozilla.org/rdf/container;1"]
-                              .createInstance(Components.interfaces.nsIRDFContainer);
-    container.Init(this._mimeDS, root);
-    
-    var itemResource = this._rdf.GetResource(MIME_URI(aItem.type));
-    var handlerResource = null;
-    if (container.IndexOf(itemResource) == -1) {
-      container.AppendElement(itemResource);
-      this._setLiteralValue(itemResource, "editable", "true");
-      this._setLiteralValue(itemResource, "value", aItem.type);
-      
-      handlerResource = this._rdf.GetResource(HANDLER_URI(aItem.type));
-      this._setLiteralValue(handlerResource, "alwaysAsk", "false");
-      var handlerProp = this._rdf.GetResource(NC_URI("handlerProp"));
-      this._mimeDS.Assert(itemResource, handlerProp, handlerResource, true);
-      
-      var extAppResource = this._rdf.GetResource(APP_URI(aItem.type));
-      this._setLiteralValue(extAppResource, "path", "");
-      var extAppProp = this._rdf.GetResource(NC_URI("externalApplication"));
-      this._mimeDS.Assert(handlerResource, extAppProp, extAppResource, true);
-    }
-    else
-      handlerResource = this._getChildResource(itemResource, "handlerProp");
-        
-    return handlerResource;
-  },
-  
-  _setLiteralValue: function (aResource, aProperty, aValue)
-  {
-    var property = this._rdf.GetResource(NC_URI(aProperty));
-    var newValue = this._rdf.GetLiteral(aValue);
-    var oldValue = this._mimeDS.GetTarget(aResource, property, true);
-    if (oldValue)
-      this._mimeDS.Change(aResource, property, oldValue, newValue);
-    else
-      this._mimeDS.Assert(aResource, property, newValue, true);
-  },
-  
-  editFileHandler: function ()
-  {
-    var selection = this._tree.view.selection; 
-    if (selection.count != 1)
-      return;
-
-    var item = this._view.getItemAtIndex(selection.currentIndex);
-    openDialog("chrome://messenger/content/preferences/changeaction.xul", 
-               "_blank", "modal,centerscreen", item);
-    
-    // Update the database
-    switch (item.handleMode) {
-    case FILEACTION_OPEN_PLUGIN:
-      this._enablePluginForItem(item);
-      // We don't need to adjust the database because plugin settings always
-      // supercede whatever is in the db, leaving it untouched allows the last
-      // user setting(s) to be preserved if they ever revert.
-      break;
-    case FILEACTION_OPEN_DEFAULT:
-      this._disablePluginForItem(item);
-      var handlerRes = this._ensureMIMERegistryEntry(item);
-      this._setLiteralValue(handlerRes, "useSystemDefault", "true");
-      this._setLiteralValue(handlerRes, "saveToDisk", "false");
-      break;
-    case FILEACTION_OPEN_CUSTOM:
-      this._disablePluginForItem(item);
-      var handlerRes = this._ensureMIMERegistryEntry(item);
-      this._setLiteralValue(handlerRes, "useSystemDefault", "false");
-      this._setLiteralValue(handlerRes, "saveToDisk", "false");
-      var extAppRes = this._getChildResource(handlerRes, "externalApplication");
-      this._setLiteralValue(extAppRes, "path", item.customHandler.path);
-      break;
-    case FILEACTION_SAVE_TO_DISK:
-      this._disablePluginForItem(item);
-      var handlerRes = this._ensureMIMERegistryEntry(item);
-      this._setLiteralValue(handlerRes, "useSystemDefault", "false");
-      this._setLiteralValue(handlerRes, "saveToDisk", "true");
-      break;
-    }
-    
-    if (this._mimeDS instanceof Components.interfaces.nsIRDFRemoteDataSource)
-      this._mimeDS.Flush();
-    
-    // Update the view
-    this._tree.treeBoxObject.invalidateRow(selection.currentIndex);    
-  },
-  
-  onSelectionChanged: function ()
-  {
-    if (this._tree.view.rowCount == 0)
-      return;
-      
-    var selection = this._tree.view.selection; 
-    var selected = selection.count;
-    this._removeButton.disabled = selected == 0;
-    this._editButton.disabled = selected != 1;
-    var stringKey = selected > 1 ? "removeButtonMultiple" : "removeButtonSingle";
-    this._removeButton.label = this._bundle.getString(stringKey);
-    
-    var canRemove = true;
-    var canEdit = true;
-    
-    var rangeCount = selection.getRangeCount();
-    var min = { }, max = { };
-    var setLastSelected = false;
-    for (var i = 0; i < rangeCount; ++i) {
-      selection.getRangeAt(i, min, max);
-      
-      for (var j = min.value; j <= max.value; ++j) {
-        if (!setLastSelected) {
-          // Set the last selected index to the first item in the selection
-          this._tree.setAttribute("lastSelected", j);
-          setLastSelected = true;
-        }
-
-        var item = this._view.getItemAtIndex(j);
-        if (item && 
-            (!item.editable || item.handleMode == FILEACTION_OPEN_INTERNALLY))
-          canEdit = false;
-        
-        if (item && 
-            (!item.editable || item.handleMode == FILEACTION_OPEN_INTERNALLY ||
-             item.handledOnlyByPlugin))
-          canRemove = false;
-      }
-    }
-    
-    if (!canRemove)
-      this._removeButton.disabled = true;
-    if (!canEdit)
-      this._editButton.disabled = true;
-  },
-  
-  _lastSortProperty : "",
-  _lastSortAscending: false,
-  sort: function (aProperty) 
-  {
-    var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;
-    function sortByProperty(a, b) 
-    {
-      return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase());
-    }
-    function sortByExtension(a, b)
-    {
-      if (!a.hasExtension && b.hasExtension)
-        return 1;
-      if (!b.hasExtension && a.hasExtension)
-        return -1;
-      return a.extension.toLowerCase().localeCompare(b.extension.toLowerCase());
-    }
-    // Sort the Filtered List, if in Filtered mode
-    if (!this._view._filtered) { 
-      this._view.activeCollection.sort(aProperty == "extension" ? sortByExtension : sortByProperty);
-      if (!ascending)
-        this._view.activeCollection.reverse();
-    }
-
-    this._view.selection.clearSelection();
-    this._view.selection.select(0);
-    this._tree.treeBoxObject.invalidate();
-    this._tree.treeBoxObject.ensureRowIsVisible(0);
-
-    this._lastSortAscending = ascending;
-    this._lastSortProperty = aProperty;
-  },
-  
-  clearFilter: function ()
-  {    
-    // Clear the Filter and the Tree Display
-    document.getElementById("filter").value = "";
-    this._view._filtered = false;
-    this._view._filterSet = [];
-
-    // Just reload the list to make sure deletions are respected
-    this._loadView();
-    this._updateRowCount(this._updateExclusions());
-
-    // Restore selection
-    this._view.selection.clearSelection();
-    for (i = 0; i < this._lastSelectedRanges.length; ++i) {
-      var range = this._lastSelectedRanges[i];
-      this._view.selection.rangedSelect(range.min, range.max, true);
-    }
-    this._lastSelectedRanges = [];
-
-    document.getElementById("actionsIntro").value = this._bundle.getString("actionsAll");
-    document.getElementById("clearFilter").disabled = true;
-  },
-  
-  _actionMatchesFilter: function (aAction)
-  {
-    return aAction.extension.toLowerCase().indexOf(this._view._filterValue) != -1 ||
-           aAction.typeName.toLowerCase().indexOf(this._view._filterValue) != -1 || 
-           aAction.type.toLowerCase().indexOf(this._view._filterValue) != -1 ||
-           aAction.action.toLowerCase().indexOf(this._view._filterValue) != -1;
-  },
-  
-  _filterActions: function (aFilterValue)
-  {
-    this._view._filterValue = aFilterValue;
-    var actions = [];
-    var collection = this._view._usingExclusionSet ? this._view._exclusionSet : this._actions;
-    for (var i = 0; i < collection.length; ++i) {
-      var action = collection[i];
-      if (this._actionMatchesFilter(action)) 
-        actions.push(action);
-    }
-    return actions;
-  },
-  
-  _lastSelectedRanges: [],
-  _saveState: function ()
-  {
-    // Save selection
-    var seln = this._view.selection;
-    this._lastSelectedRanges = [];
-    var rangeCount = seln.getRangeCount();
-    for (var i = 0; i < rangeCount; ++i) {
-      var min = {}; var max = {};
-      seln.getRangeAt(i, min, max);
-      this._lastSelectedRanges.push({ min: min.value, max: max.value });
-    }
-  },
-  
-  _filterTimeout: -1,
-  onFilterInput: function ()
-  {
-    if (this._filterTimeout != -1)
-      clearTimeout(this._filterTimeout);
-   
-    function filterActions()
-    {
-      var filter = document.getElementById("filter").value;
-      if (filter == "") {
-        gDownloadActionsWindow.clearFilter();
-        return;
-      }        
-      var view = gDownloadActionsWindow._view;
-      view._filterSet = gDownloadActionsWindow._filterActions(filter);
-      if (!view._filtered) {
-        // Save Display Info for the Non-Filtered mode when we first
-        // enter Filtered mode. 
-        gDownloadActionsWindow._saveState();
-        view._filtered = true;
-      }
-
-      // Clear the display
-      gDownloadActionsWindow._updateRowCount(view._filterSet.length);
-      
-      view.selection.select(0);
-      document.getElementById("actionsIntro").value = gDownloadActionsWindow._bundle.getString("actionsFiltered");
-      document.getElementById("clearFilter").disabled = false;
-    }
-    window.filterActions = filterActions;
-    this._filterTimeout = setTimeout(filterActions, 500);
-  },
-  
-  onFilterKeyPress: function (aEvent)
-  {
-    if (aEvent.keyCode == 27) // ESC key
-      this.clearFilter();
-  },
-  
-  focusFilterBox: function ()
-  { 
-    var filter = document.getElementById("filter");
-    filter.focus();
-    filter.select();
-  }  
-};
-
deleted file mode 100644
--- a/mail/components/preferences/downloadactions.xul
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the Firefox Preferences System.
-#
-# The Initial Developer of the Original Code is
-# Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2005
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-<?xml-stylesheet href="chrome://global/skin/"?>
-<?xml-stylesheet href="chrome://messenger/skin/preferences/preferences.css"?>
-
-<!DOCTYPE prefwindow [
-  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-  <!ENTITY % downloadactionsDTD SYSTEM "chrome://messenger/locale/preferences/downloadactions.dtd">
-  %brandDTD;
-  %downloadactionsDTD;
-]>
-
-<window id="DownloadActionsWindow" class="windowDialog"
-        windowtype="Preferences:DownloadActions"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        onload="gDownloadActionsWindow.init();"
-        onunload="gDownloadActionsWindow.uninit();"
-        title="&downloadactionsWindow.title;"
-        width="&window.width;" height="&window.height;" persist="width height screenX screenY">
-
-  <script type="application/x-javascript" src="chrome://messenger/content/preferences/actionsshared.js"/>
-  <script type="application/x-javascript" src="chrome://messenger/content/preferences/downloadactions.js"/>
-
-  <stringbundle id="bundlePreferences" src="chrome://messenger/locale/preferences/preferences.properties"/>
-
-  <keyset>
-    <key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
-    <key key="&focusSearch1.key;" modifiers="accel" oncommand="gDownloadActionsWindow.focusFilterBox();"/>
-    <key key="&focusSearch2.key;" modifiers="accel" oncommand="gDownloadActionsWindow.focusFilterBox();"/>
-  </keyset>
-           
-  <vbox flex="1" class="contentPane">
-    <hbox align="center">
-      <label accesskey="&filter.accesskey;" control="filter">&filter.label;</label>
-      <textbox id="filter" flex="1" oninput="gDownloadActionsWindow.onFilterInput();" 
-              onkeypress="gDownloadActionsWindow.onFilterKeyPress(event);"/>
-      <button id="clearFilter" label="&clear.label;" accesskey="&clear.accesskey;" 
-              oncommand="gDownloadActionsWindow.clearFilter();" disabled="true"/>
-    </hbox>
-    <separator class="thin"/>
-    <label id="actionsIntro" control="fileHandlersList">
-      &fileTypesDescription.label;
-    </label>
-    <separator class="thin"/>
-    <tree id="fileHandlersList" flex="1"
-          lastSelected="0" persist="lastSelected"
-          onselect="gDownloadActionsWindow.onSelectionChanged();"
-          ondblclick="gDownloadActionsWindow.editFileHandler();">
-      <treechildren id="extensionChildren"/>
-      <treecols>
-        <treecol id="fileExtension" ignoreincolumnpicker="true"
-                  class="sortDirectionIndicator" persist="width"
-                  label="&fileExtensionColumn.label;" accesskey="&fileExtensionColumn.accesskey;"
-                  onclick="gDownloadActionsWindow.sort('extension');"/>
-        <treecol id="fileType" flex="1"
-                  class="sortDirectionIndicator" persist="width"
-                  label="&fileTypeColumn.label;" accesskey="&fileTypeColumn.accesskey;"
-                  onclick="gDownloadActionsWindow.sort('typeName');"/>
-        <splitter class="tree-splitter" />
-        <treecol id="fileMIMEType" flex="1" hidden="true"
-                  class="sortDirectionIndicator" persist="width"
-                  label="&fileMIMETypeColumn.label;" accesskey="&fileMIMETypeColumn.accesskey;"
-                  onclick="gDownloadActionsWindow.sort('type');"/>
-        <splitter class="tree-splitter" />
-        <treecol id="fileHandler" flex="1"
-                  class="sortDirectionIndicator" persist="width"
-                  label="&fileHandlerColumn.label;" accesskey="&fileHandlerColumn.accesskey;"
-                  onclick="gDownloadActionsWindow.sort('action');"/>                
-        <splitter class="tree-splitter" />
-      </treecols>
-    </tree>
-  </vbox>
-  <separator class="thin"/>
-  <hbox>
-    <hbox flex="1" class="actionButtons">
-      <button id="removeFileHandler"
-              label="&remove.label;" accesskey="&remove.accesskey;"
-              oncommand="gDownloadActionsWindow.removeFileHandler();"/>
-      <button id="editFileHandler"
-              label="&edit.label;" accesskey="&edit.accesskey;"
-              oncommand="gDownloadActionsWindow.editFileHandler();"/>
-      <spacer flex="1"/>
-#ifndef XP_MACOSX
-      <button oncommand="close();"
-              label="&button.close.label;" accesskey="&button.close.accesskey;"/>
-#endif
-    </hbox>
-    <resizer dir="bottomright"/>
-  </hbox>
-</window>
-
--- a/mail/components/preferences/downloads.js
+++ b/mail/components/preferences/downloads.js
@@ -17,86 +17,87 @@
 # The Initial Developer of the Original Code is
 # Ben Goodger.
 # Portions created by the Initial Developer are Copyright (C) 2005
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Ben Goodger <ben@mozilla.org>
 #   Dan Mosedale <dmose@mozilla.org>
+#   Magnus Melin <mkmelin+mozilla@iki.fi>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-var gDownloadsPane = {
+var gDownloadDirSection = {
   chooseFolder: function ()
   {
     const nsIFilePicker = Components.interfaces.nsIFilePicker;
     var fp = Components.classes["@mozilla.org/filepicker;1"]
                        .createInstance(nsIFilePicker);
     var bundlePreferences = document.getElementById("bundlePreferences");
-    var title = bundlePreferences.getString("chooseDownloadFolderTitle");
+    var title = bundlePreferences.getString("chooseAttachmentsFolderTitle");
     fp.init(window, title, nsIFilePicker.modeGetFolder);
-    
+
     const nsILocalFile = Components.interfaces.nsILocalFile;
     var customDirPref = document.getElementById("browser.download.dir");
     if (customDirPref.value)
       fp.displayDirectory = customDirPref.value;
     fp.appendFilters(nsIFilePicker.filterAll);
     if (fp.show() == nsIFilePicker.returnOK) {
       var file = fp.file.QueryInterface(nsILocalFile);
       var currentDirPref = document.getElementById("browser.download.downloadDir");
       customDirPref.value = currentDirPref.value = file;
       var folderListPref = document.getElementById("browser.download.folderList");
       folderListPref.value = this._fileToIndex(file);
     }
   },
-  
+
   onReadUseDownloadDir: function ()
   {
     var downloadFolder = document.getElementById("downloadFolder");
     var chooseFolder = document.getElementById("chooseFolder");
     var preference = document.getElementById("browser.download.useDownloadDir");
     downloadFolder.disabled = !preference.value;
-    chooseFolder.disabled = !preference.value;      
+    chooseFolder.disabled = !preference.value;
     return undefined;
   },
-  
+
   _fileToIndex: function (aFile)
-  { 
+  {
     if (!aFile || aFile.equals(this._getDownloadsFolder("Desktop")))
       return 0;
     else if (aFile.equals(this._getDownloadsFolder("Downloads")))
       return 1;
     return 2;
   },
-  
+
   _indexToFile: function (aIndex)
   {
     switch (aIndex) {
     case 0: 
       return this._getDownloadsFolder("Desktop");
     case 1:
       return this._getDownloadsFolder("Downloads");
     }
     var customDirPref = document.getElementById("browser.download.dir");
     return customDirPref.value;
   },
-  
+
   _getSpecialFolderKey: function (aFolderType)
   {
     if (aFolderType == "Desktop")
       return "Desk";
 
     if (aFolderType != "Downloads")
       throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
 
@@ -110,75 +111,49 @@ var gDownloadsPane = {
 #endif
 #endif
   },
 
   _getDownloadsFolder: function (aFolder)
   {
     var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
                                 .getService(Components.interfaces.nsIProperties);
-    var dir = fileLocator.get(this._getSpecialFolderKey(aFolder), 
+    var dir = fileLocator.get(this._getSpecialFolderKey(aFolder),
                               Components.interfaces.nsILocalFile);
     if (aFolder != "Desktop")
       dir.append("My Downloads");
-      
+
     return dir;
   },
-  
-  _getDisplayNameOfFile: function (aFolder)
-  {
-    // TODO: would like to add support for 'Downloads on Macintosh HD' 
-    //       for OS X users.
-    return aFolder ? aFolder.path : "";
-  },
-  
+
   readDownloadDirPref: function ()
   {
     var folderListPref = document.getElementById("browser.download.folderList");
     var bundlePreferences = document.getElementById("bundlePreferences");
     var downloadFolder = document.getElementById("downloadFolder");
 
     var customDirPref = document.getElementById("browser.download.dir");
     var customIndex = customDirPref.value ? this._fileToIndex(customDirPref.value) : 0;
     if (folderListPref.value == 0 || customIndex == 0)
       downloadFolder.label = bundlePreferences.getString("desktopFolderName");
     else if (folderListPref.value == 1 || customIndex == 1) 
       downloadFolder.label = bundlePreferences.getString("myDownloadsFolderName");
     else
-      downloadFolder.label = this._getDisplayNameOfFile(customDirPref.value);
-    
+      downloadFolder.label = customDirPref.value ? customDirPref.value.path : "";
+
     var ios = Components.classes["@mozilla.org/network/io-service;1"]
                         .getService(Components.interfaces.nsIIOService);
     var fph = ios.getProtocolHandler("file")
                  .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
     var currentDirPref = document.getElementById("browser.download.downloadDir");
     var downloadDir = currentDirPref.value || this._indexToFile(folderListPref.value);
     var urlspec = fph.getURLSpecFromFile(downloadDir);
     downloadFolder.image = "moz-icon://" + urlspec + "?size=16";
-    
+
     return undefined;
   },
-  
+
   writeFolderList: function ()
   {
     var currentDirPref = document.getElementById("browser.download.downloadDir");
     return this._fileToIndex(currentDirPref.value);
-  },
-  
-  showWhenStartingPrefChanged: function ()
-  {
-    document.getElementById("browser.download.manager.closeWhenDone")
-            .disabled = !document.getElementById("browser.download.manager.showWhenStarting").value;
-  },
-  
-  readShowWhenStartingPref: function ()
-  {
-    this.showWhenStartingPrefChanged();
-    return undefined;
-  },
-  
-  showFileTypeActions: function ()
-  {
-    document.documentElement.openWindow("Preferences:DownloadActions",
-                                        "chrome://messenger/content/preferences/downloadactions.xul",
-                                        "", null);
   }
 };
deleted file mode 100644
--- a/mail/components/preferences/downloads.xul
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0"?>
-
-# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the Thunderbird Preferences System.
-#
-# The Initial Developer of the Original Code is
-# Ben Goodger.
-# Portions created by the Initial Developer are Copyright (C) 2005
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Ben Goodger <ben@mozilla.org>
-#   Scott MacGregor <mscott@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-<!DOCTYPE overlay [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % downloadsDTD SYSTEM "chrome://messenger/locale/preferences/downloads.dtd">
-%brandDTD;
-%downloadsDTD;
-]>
-
-<overlay id="DownloadsPaneOverlay"
-         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <prefpane id="paneDownloads">
-    <preferences id="downloadsPreferences">
-      <preference id="browser.download.useDownloadDir"    name="browser.download.useDownloadDir"    type="bool"/>
-      <preference id="browser.download.folderList"        name="browser.download.folderList"        type="int"/>
-      <preference id="browser.download.downloadDir"       name="browser.download.downloadDir"       type="file"/>
-      <preference id="browser.download.dir"
-                  name="browser.download.dir"
-                  type="file"
-                  onchange="gDownloadsPane.readDownloadDirPref();"/>
-      <preference id="pref.downloads.disable_button.edit_actions"
-                  name="pref.downloads.disable_button.edit_actions"
-                  type="bool"/>
-    </preferences>
-    
-    <script type="application/x-javascript" src="chrome://messenger/content/preferences/downloads.js"/>
-    
-    <stringbundle id="bundlePreferences" src="chrome://messenger/locale/preferences/preferences.properties"/>
-
-    <groupbox>
-      <caption label="&askOnSave.label;"/>
-      
-      <radiogroup id="askOnSave" flex="1"
-                  preference="browser.download.useDownloadDir"
-                  onsyncfrompreference="return gDownloadsPane.onReadUseDownloadDir();">
-        <radio id="alwaysAsk" label="&alwaysAsk.label;" accesskey="&alwaysAsk.accesskey;" value="false"/>
-        <vbox flex="1">
-          <radio id="neverAsk" label="&neverAsk.label;" accesskey="&neverAsk.accesskey;" value="true"/>
-          <hbox class="indent" align="center">
-            <filefield id="downloadFolder" flex="1"
-                       preference="browser.download.folderList"
-                       preference-editable="true"
-                       onsyncfrompreference="return gDownloadsPane.readDownloadDirPref();"
-                       onsynctopreference="return gDownloadsPane.writeFolderList()"/>
-            <button id="chooseFolder" oncommand="gDownloadsPane.chooseFolder();"
-                    preference="browser.download.folderList"
-                    onsynctopreference="return gDownloadsPane.writeFolderList()"
-#ifdef XP_MACOSX
-                    accesskey="&chooseFolderMac.accesskey;" label="&chooseFolderMac.label;"/>
-#else
-                    accesskey="&chooseFolderWin.accesskey;" label="&chooseFolderWin.label;"/>
-#endif
-          </hbox>
-        </vbox>
-      </radiogroup>
-    </groupbox>
-    
-    <groupbox>
-      <caption label="&fileTypes.label;"/>
-      
-      <description control="configureActions">&fileTypesDescription.label;</description>
-      <separator class="thin"/>
-      <hbox>
-        <button id="configureActions" label="&configureActions.label;"
-                accesskey="&configureActions.accesskey;"
-                oncommand="gDownloadsPane.showFileTypeActions();"
-                preference="pref.downloads.disable_button.edit_actions"/>
-      </hbox>
-    </groupbox>
-  </prefpane>
-
-</overlay>
new file mode 100755
--- /dev/null
+++ b/mail/components/preferences/handlers.css
@@ -0,0 +1,54 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Myk Melez <myk@mozilla.org>
+ *   Magnus Melin <mkmelin+mozilla@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+richlistitem {
+  -moz-binding: url("chrome://messenger/content/preferences/handlers.xml#handler");
+}
+
+richlistitem[selected="true"] {
+  -moz-binding: url("chrome://messenger/content/preferences/handlers.xml#handler-selected");
+}
+
+.actionsMenu > menupopup > menuitem > .menu-iconic-left {
+  /**
+    * Make the icons appear.
+    * Note: we display the icon box for every item whether or not it has an icon
+    * so the labels of all the items align vertically.
+    */
+  display: -moz-box;
+  min-width: 16px;
+}
new file mode 100755
--- /dev/null
+++ b/mail/components/preferences/handlers.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is the Mozilla browser.
+   -
+   - The Initial Developer of the Original Code is Mozilla.
+   - Portions created by the Initial Developer are Copyright (C) 2007
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Myk Melez <myk@mozilla.org>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the LGPL or the GPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<!DOCTYPE overlay [
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  <!ENTITY % applicationsDTD SYSTEM "chrome://messenger/locale/preferences/applications.dtd">
+  %brandDTD;
+  %applicationsDTD;
+]>
+
+<bindings id="handlerBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+
+  <binding id="handler-base" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
+    <implementation>
+      <property name="type" readonly="true">
+        <getter>
+          return this.getAttribute("type");
+        </getter>
+      </property>
+    </implementation>
+  </binding>
+
+  <binding id="handler" extends="chrome://messenger/content/preferences/handlers.xml#handler-base">
+    <content>
+      <xul:hbox flex="1" equalsize="always">
+        <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" align="center" xbl:inherits="tooltiptext=actionDescription">
+          <xul:image xbl:inherits="src=actionIcon" height="16" width="16" class="actionIcon"/>
+          <xul:label flex="1" crop="end" xbl:inherits="value=actionDescription"/>
+        </xul:hbox>
+      </xul:hbox>
+    </content>
+  </binding>
+
+  <binding id="handler-selected" extends="chrome://messenger/content/preferences/handlers.xml#handler-base">
+    <content>
+      <xul:hbox flex="1" equalsize="always">
+        <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)">
+            <xul:menupopup/>
+          </xul:menulist>
+        </xul:hbox>
+      </xul:hbox>
+    </content>
+
+    <implementation>
+      <constructor>
+        gApplicationsPane.rebuildActionsMenu();
+      </constructor>
+    </implementation>
+
+  </binding>
+</bindings>
--- a/mail/components/preferences/jar.mn
+++ b/mail/components/preferences/jar.mn
@@ -13,20 +13,21 @@ messenger.jar:
 *   content/messenger/preferences/junkLog.xul
 *   content/messenger/preferences/junkLog.js
 *   content/messenger/preferences/advanced.js
 *   content/messenger/preferences/advanced.xul
 *   content/messenger/preferences/receipts.xul
 *   content/messenger/preferences/connection.js
 *   content/messenger/preferences/connection.xul
 *   content/messenger/preferences/downloads.js
-*   content/messenger/preferences/downloads.xul
 *   content/messenger/preferences/attachmentReminder.js
 *   content/messenger/preferences/attachmentReminder.xul
-*   content/messenger/preferences/downloadactions.js
-*   content/messenger/preferences/downloadactions.xul
+*   content/messenger/preferences/applications.xul
+*   content/messenger/preferences/applications.js
+*   content/messenger/preferences/applicationManager.xul
+*   content/messenger/preferences/applicationManager.js
+*   content/messenger/preferences/handlers.xml
+*   content/messenger/preferences/handlers.css
 *   content/messenger/preferences/actionsshared.js
-*   content/messenger/preferences/changeaction.js
-*   content/messenger/preferences/changeaction.xul
 *   content/messenger/preferences/fonts.js
 *   content/messenger/preferences/fonts.xul
 *   content/messenger/preferences/notifications.xul
 *   content/messenger/preferences/offline.xul
--- a/mail/components/preferences/preferences.xul
+++ b/mail/components/preferences/preferences.xul
@@ -17,17 +17,18 @@
 # The Original Code is the Thunderbird Preferences System.
 #
 # The Initial Developer of the Original Code is
 # Scott MacGregor.
 # Portions created by the Initial Developer are Copyright (C) 2005
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-#   Scott MacGregor <mscott@mozilla.org
+#   Scott MacGregor <mscott@mozilla.org>
+#   Magnus Melin <mkmelin+mozilla@iki.fi>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -38,16 +39,24 @@
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://global/skin/global.css"?>
 <?xml-stylesheet href="chrome://messenger/skin/preferences/preferences.css"?>
 <?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
 <?xml-stylesheet href="chrome://messenger/content/messenger.css"?>
 
+<!-- XXX This should be in applications.xul, but bug 393953 means putting it
+   - there causes the Applications pane not to work the first time you open
+   - the Preferences dialog in a browsing session, so we work around the problem
+   - by putting it here instead.
+   -->
+<?xml-stylesheet href="chrome://messenger/content/preferences/handlers.css"?>
+<?xml-stylesheet href="chrome://messenger/skin/preferences/applications.css"?>
+
 <!DOCTYPE prefwindow [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
 <!ENTITY % preferencesDTD SYSTEM "chrome://messenger/locale/preferences/preferences.dtd">
 %brandDTD;
 %preferencesDTD;
 ]>
 
 #ifdef XP_WIN
@@ -74,22 +83,25 @@
             style="&prefWindow.styleWindows;">
 #else
 #ifdef XP_MACOSX
             style="&prefWindow.styleMac;">
 #else
             style="&prefWindow.styleGNOME;">
 #endif
 #endif
-  
+  <stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
+  <stringbundle id="bundlePreferences"
+                src="chrome://messenger/locale/preferences/preferences.properties"/>
+
   <prefpane id="paneGeneral" label="&paneGeneral.title;"
             src="chrome://messenger/content/preferences/general.xul"/>
   <prefpane id="paneDisplay" label="&paneDisplay.title;"
             src="chrome://messenger/content/preferences/display.xul"/>
   <prefpane id="paneCompose" label="&paneComposition.title;"
             src="chrome://messenger/content/preferences/compose.xul"/>
   <prefpane id="paneSecurity" label="&paneSecurity.title;"
             src="chrome://messenger/content/preferences/security.xul"/>
-  <prefpane id="paneDownloads" label="&paneAttachments.title;"
-            src="chrome://messenger/content/preferences/downloads.xul"/>
+  <prefpane id="paneApplications" label="&paneAttachments.title;"
+            src="chrome://messenger/content/preferences/applications.xul"/>
   <prefpane id="paneAdvanced" label="&paneAdvanced.title;"
             src="chrome://messenger/content/preferences/advanced.xul"/>
 </prefwindow>
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/preferences/applicationManager.dtd
@@ -0,0 +1,4 @@
+<!ENTITY appManager.title     "Application Details">
+<!ENTITY appManager.style     "width: 30em; min-height: 20em;">
+<!ENTITY remove.label         "Remove">
+<!ENTITY remove.accesskey     "R">
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/preferences/applicationManager.properties
@@ -0,0 +1,9 @@
+# LOCALIZATION NOTE
+# in descriptionApplications, %S will be replaced by one of the 3 following strings
+descriptionApplications=The following applications can be used to handle %S.
+
+handleProtocol=%S links
+handleFile=%S content
+
+descriptionWebApp=This web application is hosted at:
+descriptionLocalApp=This application is located at:
new file mode 100755
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/preferences/applications.dtd
@@ -0,0 +1,19 @@
+<!ENTITY  typeColumn.label            "Content Type">
+<!ENTITY  typeColumn.accesskey        "T">
+
+<!ENTITY  actionColumn2.label         "Action">
+<!ENTITY  actionColumn2.accesskey     "A">
+
+<!ENTITY  focusSearch1.key            "f">
+<!ENTITY  focusSearch2.key            "k">
+
+<!ENTITY  filter.emptytext            "Search">
+
+<!ENTITY saveTo.label                 "Save files to">
+<!ENTITY saveTo.accesskey             "S">
+<!ENTITY alwaysAsk.label              "Always ask me where to save files">
+<!ENTITY alwaysAsk.accesskey          "A">
+<!ENTITY chooseFolderWin.label        "Browse…">
+<!ENTITY chooseFolderWin.accesskey    "B">
+<!ENTITY chooseFolderMac.label        "Choose…">
+<!ENTITY chooseFolderMac.accesskey    "C">
deleted file mode 100644
--- a/mail/locales/en-US/chrome/messenger/preferences/changeaction.dtd
+++ /dev/null
@@ -1,21 +0,0 @@
-<!ENTITY  changeAction.title                  "Change Action">
-<!ENTITY  window.width                         "36em">
-
-<!ENTITY  whenDownloading.label               "When downloading files like this:">
-
-<!ENTITY  openDefault.label                   "Open them with the default application:">
-<!ENTITY  openDefault.accesskey               "O">
-<!ENTITY  openApplication.label               "Open them with this application:">
-<!ENTITY  openApplication.accesskey           "e">
-<!ENTITY  changeApp.label                     "Browse…">
-<!ENTITY  changeApp.accesskey                 "B">
-<!ENTITY  saveToDisk.label                    "Save them on my computer">
-<!ENTITY  saveToDisk.accesskey                "S">
-<!ENTITY  saveToDefaultFolder.label           "in the default download folder">
-<!ENTITY  saveToDefaultFolder.accesskey       "d">
-<!ENTITY  saveToThisFolder.label              "in this folder:">
-<!ENTITY  saveToThisFolder.accesskey          "h">
-<!ENTITY  chooseFolder.label                  "Browse…">
-<!ENTITY  chooseFolder.accesskey              "w">
-<!ENTITY  saveToAskMe.label                   "ask me where to save the file">
-<!ENTITY  saveToAskMe.accesskey               "a">
deleted file mode 100644
--- a/mail/locales/en-US/chrome/messenger/preferences/downloadactions.dtd
+++ /dev/null
@@ -1,32 +0,0 @@
-<!ENTITY  downloadactionsWindow.title         "Download Actions">
-<!ENTITY  window.width                         "480">
-<!ENTITY  window.height                        "310">
-
-<!ENTITY  fileTypesDescription.label          "Automatically perform the associated Action with each of the following file types:">
-
-<!ENTITY  fileHandlerColumn.label             "Action">
-<!ENTITY  fileHandlerColumn.accesskey         "A">
-<!ENTITY  fileTypeColumn.label                "File Type">
-<!ENTITY  fileTypeColumn.accesskey            "T">
-<!ENTITY  fileMIMETypeColumn.label            "MIME Type">
-<!ENTITY  fileMIMETypeColumn.accesskey        "M">
-<!ENTITY  fileExtensionColumn.label           "Extension">
-<!ENTITY  fileExtensionColumn.accesskey       "E">
-
-<!ENTITY  remove.label                        "Remove Action">
-<!ENTITY  remove.accesskey                    "R">
-<!ENTITY  edit.label                          "Change Action…">
-<!ENTITY  edit.accesskey                      "C">
-
-<!ENTITY  windowClose.key                     "w">
-<!ENTITY  focusSearch1.key                    "f">
-<!ENTITY  focusSearch2.key                    "k">
-
-<!ENTITY  filter.label                        "Search:">
-<!ENTITY  filter.accesskey                    "S">
-<!ENTITY  clear.label                         "Clear">
-<!ENTITY  clear.accesskey                     "l">
-
-<!ENTITY  button.close.label                  "Close">
-<!ENTITY  button.close.accesskey              "o">
-
deleted file mode 100644
--- a/mail/locales/en-US/chrome/messenger/preferences/downloads.dtd
+++ /dev/null
@@ -1,15 +0,0 @@
-<!ENTITY askOnSave.label              "Attachments Folder">
-<!ENTITY alwaysAsk.label              "Ask me where to save every file">
-<!ENTITY alwaysAsk.accesskey          "A">
-<!ENTITY neverAsk.label               "Save all attachments to this folder:">
-<!ENTITY neverAsk.accesskey           "S">
-<!ENTITY chooseFolderWin.label        "Browse…">
-<!ENTITY chooseFolderWin.accesskey    "B">
-<!ENTITY chooseFolderMac.label        "Choose…">
-<!ENTITY chooseFolderMac.accesskey    "C">
-
-
-<!ENTITY fileTypes.label              "Download Actions">
-<!ENTITY configureActions.label       "View &amp; Edit Actions…">
-<!ENTITY configureActions.accesskey   "V">
-<!ENTITY fileTypesDescription.label   "&brandShortName; can automatically save or open attachments of certain types.">
--- a/mail/locales/en-US/chrome/messenger/preferences/preferences.dtd
+++ b/mail/locales/en-US/chrome/messenger/preferences/preferences.dtd
@@ -1,9 +1,8 @@
-
 <!ENTITY  prefWindow.titleWin     "Options">
 <!ENTITY  prefWindow.titleGNOME   "&brandShortName; Preferences">
 <!ENTITY  prefWindow.styleWindows "width: 44em; min-height: 38.5em;">
 <!ENTITY  prefWindow.styleMac     "width: 47em;">
 <!ENTITY  prefWindow.styleGNOME   "width: 42em; min-height: 38em;">
 
 <!ENTITY paneGeneral.title        "General">
 <!ENTITY paneDisplay.title        "Display">
--- a/mail/locales/en-US/chrome/messenger/preferences/preferences.properties
+++ b/mail/locales/en-US/chrome/messenger/preferences/preferences.properties
@@ -10,36 +10,41 @@ domainDuplicationError=The domain name %
 
 #### Junk
 confirmResetJunkTrainingTitle=Confirm
 confirmResetJunkTrainingText=Are you sure you want to reset the adaptive filter training data?
 
 #### Downloads
 desktopFolderName=Desktop
 myDownloadsFolderName=My Downloads
-chooseDownloadFolderTitle=Choose Download Folder:
+chooseAttachmentsFolderTitle=Choose Folder
+
+#### Applications
+
+fileEnding=%S file
+saveFile=Save File
+
+# LOCALIZATION NOTE (useApp, useDefault): %S = Application name
+useApp=Use %S
+useDefault=Use %S (default)
 
-#### Download Actions
-extensionNone=(NONE)
-removeButtonSingle=Remove Action
-removeButtonMultiple=Remove Actions
-removeTitleSingle=Remove Action
-removeTitleMultiple=Remove Actions
-removeMessageSingle=The selected Action will no longer be performed when files of the affected types are downloaded. Are you sure you want to remove this Action?
-removeMessageMultiple=The selected Actions will no longer be performed when files of the affected types are downloaded. Are you sure you want to remove these Actions?
-fileEnding=%S file
-saveToDisk=Save to Disk
-openWith=Open with %S
-actionsFiltered=The following Actions match your search:
-actionsAll=Automatically perform the associated Action with each of the following file types:
+useOtherApp=Use other…
+fpTitleChooseApp=Select Helper Application
+manageApp=Application Details…
+alwaysAsk=Always ask
 
-#### Change Action
-extensionStringFormat=%S, %S
-fpTitleChooseApp=Select Helper Application
-fpTitleChooseDL=Select Download Folder
+# LOCALIZATION NOTE (usePluginIn):
+# %1$S = plugin name (for example "QuickTime Plugin-in 7.2")
+# %2$S = brandShortName from brand.properties (for example "Shredder")
+usePluginIn=Use %1$S (in %2$S)
+
+# LOCALIZATION NOTE (typeDescriptionWithType):
+# %1$S = type description (for example "Portable Document Format")
+# %2$S = type (for example "application/pdf")
+typeDescriptionWithType=%1$S (%2$S)
 
 #### Sound Notifications
 soundFilePickerTitle=Choose Sound
 
 #### Shell Service
 alreadyDefaultClientTitle=Default Client
 alreadyDefault=%S is already set as your default mail client.
 
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -120,19 +120,19 @@
   locale/@AB_CD@/messenger/preferences/compose.dtd                      (%chrome/messenger/preferences/compose.dtd)
   locale/@AB_CD@/messenger/preferences/sendoptions.dtd                  (%chrome/messenger/preferences/sendoptions.dtd)
   locale/@AB_CD@/messenger/preferences/security.dtd                     (%chrome/messenger/preferences/security.dtd)
   locale/@AB_CD@/messenger/preferences/junkLog.dtd                      (%chrome/messenger/preferences/junkLog.dtd)
   locale/@AB_CD@/messenger/preferences/advanced.dtd                     (%chrome/messenger/preferences/advanced.dtd)
   locale/@AB_CD@/messenger/preferences/attachmentReminder.dtd           (%chrome/messenger/preferences/attachmentReminder.dtd)
   locale/@AB_CD@/messenger/preferences/receipts.dtd                     (%chrome/messenger/preferences/receipts.dtd)
   locale/@AB_CD@/messenger/preferences/connection.dtd                   (%chrome/messenger/preferences/connection.dtd)
-  locale/@AB_CD@/messenger/preferences/downloads.dtd                    (%chrome/messenger/preferences/downloads.dtd)
-  locale/@AB_CD@/messenger/preferences/downloadactions.dtd              (%chrome/messenger/preferences/downloadactions.dtd)
-  locale/@AB_CD@/messenger/preferences/changeaction.dtd                 (%chrome/messenger/preferences/changeaction.dtd)
+  locale/@AB_CD@/messenger/preferences/applications.dtd                 (%chrome/messenger/preferences/applications.dtd)
+  locale/@AB_CD@/messenger/preferences/applicationManager.dtd           (%chrome/messenger/preferences/applicationManager.dtd)
+  locale/@AB_CD@/messenger/preferences/applicationManager.properties    (%chrome/messenger/preferences/applicationManager.properties)
   locale/@AB_CD@/messenger/preferences/fonts.dtd                        (%chrome/messenger/preferences/fonts.dtd)
   locale/@AB_CD@/messenger/preferences/offline.dtd                      (%chrome/messenger/preferences/offline.dtd)
   locale/@AB_CD@/messenger/preferences/notifications.dtd                (%chrome/messenger/preferences/notifications.dtd)
   locale/@AB_CD@/messenger/preferences/preferences.properties           (%chrome/messenger/preferences/preferences.properties)
   locale/@AB_CD@/messenger/migration/migration.dtd                      (%chrome/messenger/migration/migration.dtd)
   locale/@AB_CD@/messenger/migration/migration.properties               (%chrome/messenger/migration/migration.properties)
   locale/@AB_CD@/messenger/searchIntegrationWin.dtd                     (%chrome/messenger/searchIntegrationWin.dtd)
   locale/@AB_CD@/messenger/searchIntegrationMac.dtd                     (%chrome/messenger/searchIntegrationMac.dtd)
--- a/mail/themes/gnomestripe/jar.mn
+++ b/mail/themes/gnomestripe/jar.mn
@@ -63,22 +63,24 @@ classic.jar:
   skin/classic/messenger/messengercompose/editorOverlay.css    (mail/compose/editorOverlay.css)
   skin/classic/messenger/messengercompose/compose-toolbar.png  (mail/compose/compose-toolbar.png)
   skin/classic/messenger/messengercompose/compose-toolbar-small.png   (mail/compose/compose-toolbar-small.png)
   skin/classic/messenger/messengercompose/format-buttons.png  (mail/compose/format-buttons.png)
 % skin messenger-newsblog classic/1.0 %skin/classic/messenger-newsblog/
   skin/classic/messenger-newsblog/feed-subscriptions.css      (mail/newsblog/feed-subscriptions.css)
   skin/classic/messenger-newsblog/icons/rss-feed.png          (mail/newsblog/rss-feed.png)
   skin/classic/messenger-newsblog/icons/server-rss.png        (mail/newsblog/server-rss.png)
+  skin/classic/messenger/preferences/alwaysAsk.png            (mail/preferences/alwaysAsk.png)
   skin/classic/messenger/preferences/preferences.css          (mail/preferences/preferences.css)
   skin/classic/messenger/preferences/general.png              (mail/preferences/general.png)
   skin/classic/messenger/preferences/display.png              (mail/preferences/display.png)
   skin/classic/messenger/preferences/composition.png          (mail/preferences/composition.png)
   skin/classic/messenger/preferences/security.png             (mail/preferences/security.png)
   skin/classic/messenger/preferences/attachments.png          (mail/preferences/attachments.png)
+  skin/classic/messenger/preferences/applications.css         (mail/preferences/applications.css)
   skin/classic/messenger/preferences/advanced.png             (mail/preferences/advanced.png)
   skin/classic/messenger/preferences/background.png           (mail/preferences/background.png)
   skin/classic/messenger/preferences/hover.png                (mail/preferences/hover.png)
   skin/classic/messenger/preferences/selected.png             (mail/preferences/selected.png)
   skin/classic/messenger/smime/msgCompSMIMEOverlay.css        (mail/smime/msgCompSMIMEOverlay.css)
   skin/classic/messenger/smime/msgHdrViewSMIMEOverlay.css     (mail/smime/msgHdrViewSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSMIMEOverlay.css        (mail/smime/msgReadSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSecurityInfo.css        (mail/smime/msgReadSecurityInfo.css)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..45256d4e76b2aabb4c32889dc03bca3f9e5f80f4
GIT binary patch
literal 575
zc$@)00>J%=P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10lY~>K~y-6jZ;Bu6HyTUW;0n+wH}KgNH0%8^ybZrh!-ssjN~2)
zJ+#!G)S!5cB&+xbM6lpN3RyuKQS{!EE!0xm=F*%*@UoDmn`HXNgW1(hHj)qK^1e4S
z-#7CfRlM@F>$+7D$y;j~W5977VP?PE?UvYe-RjKk*@7{K2sBPU6v~Z8qfr0w9xNhx
zV+@5yM^M$V3J?*DF(e{+w$?I%V69DDTKU?>>P7$nxOHg~OV>{SRiKJ~4m;7IRhx*n
z>pxH{PN7zuLVfcm#2zR32=UN#K!HDh9$826X8jlLT%G`_rdo^(*a4C=z~}7%K`X?<
z&2vM1gpn3Ha*SuSZOmOiJH(}07#w1TfOn;<$dJO?(c6g?sM?{Jeewm}o}_ZI0wNMs
zWzevSwWl{?dx@@&^JkSr!p!XN?e7*Yn2Xd74{_LTVe-@&Oyo|2DE(!sD)#nwm6?62
zc;)GAHtXe1<nAsm+;adR?1Xr|@=AgrNc|iA&VH}gD?$7Ft$1ZsRc$s8<oSzgv*MMn
zMBM)((c$B#dS~bR&YFl6OAj8mMvnd;#07{b-1@e){P6yxm*XTx_zeR~Eq)WNar6KH
N002ovPDHLkV1hx51f>7~
new file mode 100644
--- /dev/null
+++ b/mail/themes/gnomestripe/mail/preferences/applications.css
@@ -0,0 +1,92 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Firefox Preferences System.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Florian Queze <florian@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Line up the actions menu with action labels above and below it.
+ * Equalize the distance from the left side of the action box to the left side
+ * of the icon for both the menu and the non-menu versions of the action box.
+ * Also make sure the labels are the same distance away from the icons.
+ */
+.actionsMenu {
+  margin-top: -1px;
+  margin-bottom: -1px;
+  -moz-margin-start: -1px;
+  -moz-margin-end: 0;
+}
+
+.typeIcon,
+.actionIcon {
+  margin: 0px 3px;
+}
+
+richlistitem label {
+  -moz-margin-start: 1px;
+  margin-top: 2px;
+}
+
+richlistitem {
+  min-height: 25px;
+}
+
+richlistitem[appHandlerIcon="ask"],
+menuitem[appHandlerIcon="ask"] {
+  list-style-image: url("chrome://messenger/skin/preferences/alwaysAsk.png");
+}
+
+richlistitem[appHandlerIcon="save"],
+menuitem[appHandlerIcon="save"] {
+  list-style-image: url("moz-icon://stock/gtk-save?size=menu");
+}
+
+richlistitem[appHandlerIcon="plugin"],
+menuitem[appHandlerIcon="plugin"] {
+  list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+}
+
+.actionsMenu .menulist-icon {
+  -moz-margin-end: 1px;
+  height: 16px;
+  width: 16px;
+}
+
+.actionsMenu > menupopup > menuitem > .menu-iconic-left {
+  -moz-padding-start: 0;
+  -moz-padding-end: 4px !important;
+}
+
+.actionsMenu > menupopup > menuitem {
+  -moz-padding-start: 3px;
+}
--- a/mail/themes/gnomestripe/mail/preferences/preferences.css
+++ b/mail/themes/gnomestripe/mail/preferences/preferences.css
@@ -47,23 +47,32 @@ radio[pane=paneDisplay] {
   list-style-image: url("chrome://messenger/skin/preferences/display.png");
 }
 radio[pane=paneCompose] {
   list-style-image: url("chrome://messenger/skin/preferences/composition.png");
 }
 radio[pane=paneSecurity] {
   list-style-image: url("chrome://messenger/skin/preferences/security.png");
 }
-radio[pane=paneDownloads] {
+radio[pane=paneApplications] {
   list-style-image: url("chrome://messenger/skin/preferences/attachments.png");
 }
 radio[pane=paneAdvanced] {
   list-style-image: url("chrome://messenger/skin/preferences/advanced.png");
 }
 
+/* Attachments Pane */
+#MailPreferences[animated="true"] #handlersView {
+  height: 25em;
+}
+
+#MailPreferences[animated="false"] #handlersView {
+  -moz-box-flex: 1;
+}
+
 /* File Field Widget */
 filefield {
   margin: 2px 4px;
   -moz-appearance: textfield;
 }
 
 .fileFieldContentBox {
   background-color: -moz-Dialog;
@@ -105,89 +114,16 @@ filefield[disabled="true"] .fileFieldIco
 .contentPane {
   margin: 9px 8px 5px;
 }
 
 .actionButtons {
   margin: 0px 3px 6px !important;
 }
 
-/* Download Actions Manager */
-#fileExtension {
-  width: 5em; 
-}
-
-#extensionChildren::-moz-tree-image(fileExtension) {
-  margin-top: 0px;
-  margin-bottom: 0px;
-  -moz-margin-start: 0px;
-  -moz-margin-end: 5px;
-}
-
-#typeField {
-  font-weight: bold; 
-}
-
-/* Change Action Dialog */
-#typeIcon {
-  width: 32px;
-  height: 32px;
-  -moz-margin-end: 3px;
-}
-
-#typeField {
-  background-color: transparent;
-  margin-top: 1px !important;
-  margin-bottom: 2px !important;
-  -moz-margin-start: 6px !important;
-  -moz-margin-end: 5px !important;
-}
-
-#extensionField {
-  color: GrayText;
-  font-weight: bold;
-}
-
-#ChangeActionDialog {
-  padding: 0px;
-}
-
-#ChangeActionDialog .dialog-button-box {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  -moz-padding-start: 8px;
-  -moz-padding-end: 10px;
-}
-
-#changeActionHeader {
-  border-bottom: 2px groove ThreeDFace;
-  margin: 0px;
-  padding: 10px;
-  background-color: -moz-Field;
-  color: -moz-FieldText;  
-}
-
-#changeActionContent {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  -moz-padding-start: 9px;
-  -moz-padding-end: 10px;
-}
-
-#defaultAppIcon {
-  width: 16px;
-  height: 16px;
-  -moz-margin-start: 2px;
-}
-
-#defaultAppName {
-  -moz-margin-start: 6px !important; 
-  font-weight: bold;
-}
-
 /* override the color style for tag items when they 
    have selection */
 #tagList listitem[selected="true"] {
   color: -moz-DialogText !important;
 }
 
 #tagList:focus > listitem[selected="true"] {
   color: HighlightText !important;
--- a/mail/themes/pinstripe/jar.mn
+++ b/mail/themes/pinstripe/jar.mn
@@ -89,17 +89,21 @@ classic.jar:
   skin/classic/messenger/messengercompose/right-button-base.png   (mail/compose/right-button-base.png)
   skin/classic/messenger/messengercompose/right-button-disabled.png        (mail/compose/right-button-disabled.png)
   skin/classic/messenger/messengercompose/right-button-pressed.png         (mail/compose/right-button-pressed.png)
   skin/classic/messenger/messengercompose/small-button-base.png   (mail/compose/small-button-base.png)
   skin/classic/messenger/messengercompose/small-button-disabled.png        (mail/compose/small-button-disabled.png)
   skin/classic/messenger/messengercompose/small-button-pressed.png         (mail/compose/small-button-pressed.png)
 % skin messenger-newsblog classic/1.0 %skin/classic/messenger-newsblog/
   skin/classic/messenger-newsblog/feed-subscriptions.css         (mail/newsblog/feed-subscriptions.css)
+  skin/classic/messenger/preferences/alwaysAsk.png               (mail/preferences/alwaysAsk.png)
+  skin/classic/messenger/preferences/application.png             (mail/preferences/application.png)
+  skin/classic/messenger/preferences/saveFile.png                (mail/preferences/saveFile.png)
   skin/classic/messenger/preferences/preferences.css             (mail/preferences/preferences.css)
+  skin/classic/messenger/preferences/applications.css            (mail/preferences/applications.css)
   skin/classic/messenger/preferences/mail-options.png            (mail/preferences/mail-options.png)
   skin/classic/messenger/preferences/radio-selected-bg.png       (mail/preferences/radio-selected-bg.png)
   skin/classic/messenger/smime/msgCompSMIMEOverlay.css           (mail/smime/msgCompSMIMEOverlay.css)
   skin/classic/messenger/smime/msgHdrViewSMIMEOverlay.css        (mail/smime/msgHdrViewSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSMIMEOverlay.css           (mail/smime/msgReadSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSecurityInfo.css           (mail/smime/msgReadSecurityInfo.css)
   skin/classic/messenger/smime/msgCompSecurityInfo.css           (mail/smime/msgCompSecurityInfo.css)
   skin/classic/messenger/smime/certFetchingStatus.css            (mail/smime/certFetchingStatus.css)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c792d148871ee5790ecb55d5f0d9ab739980f087
GIT binary patch
literal 530
zc$@(e0`2{YP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006_W
z*OX`400009a7bBm000XU000XU0RWnu7ytkPv`IukR5;6}lS@kiVHAd4<Tj#p^e<Wj
z?fMgL+5|$&RuSQa5$_jBH(qKTwF+_(w2C0xSYiv6@-kjV%!pCE&7kr&=L5eKC4&w;
zbC`3^`_9an865y!JRUd3VzE!J*NbU<J|7m<XqGgj)zKjs3@VZ&VLTrHiCV1&(r^Qh
z$HN+mqHr#*b1)u1GU9gyULOnwY?d_Kz~ypbG#a7b?{hA1M7-u?B%Z&pfAlibqgm3-
z8T5KRbi3Ud&aNaJSl?%Aa|TYQ6T{&UolXbscAFu~GKA9<cK6aqBqcPPO%6SZ!{PWb
zu-olWRTYg!1NC~Hv$=B*Z}e@ZMvwt%xPi@PW6PoK64h#z<%g#NUeY2zpJbXP4L1-3
zfi0(8E<+SW&c^mFg6BzApYG8tX}E#g?N;daX^F*R5v5XzXS!;u)ndH~G)o$85RFDp
zv_+~`s}-qK3i*5<l}d#zGMmlPmj{c*0_s!N7O0Yj8)%`|SkqWHo6YQ1WilB=A`t`v
zfsarqbV$7^XjVUMz{6xRAsi0F@AprHs~Ri11+maT`(c&}e>E@|3|q^Da|Zw68#suu
UO@_C<*#H0l07*qoM6N<$g1?yCjQ{`u
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b4c1ca7d02bda83358e519639632ab55fafd6077
GIT binary patch
literal 795
zc$@(n1LXXPP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!y-7qtRCwBqlV40y0Tjj$a76;FYoNj=
z!2%I=12OW?bZfPy*@L3iw6~UQy}0EA8Y|W+HFetRCAF<t*4nJ*YRy%Xq;wkALUJh@
z2r8L~h+fd)6%a~$=>g1d`?mA&?e}obcOVoBK{z+J+%9`sQEqN*ZYhYA*)|a(C>RXV
za|lEp`u^pE`ddwsNV%|pwtF3ovZS<Tr&tQY1!rRX+*rr;oAtCk0qPnWCCBN4^Cy<j
z1RR*ik<)Tu4r^tU4YztvfFz-)DWNcjrC*u_k7?285Q{f?F<c~dQmas1QRnUoxT?NZ
zmJ#zh8*`7r1a}MOGZ|Wg&;LPmwgSLtV~Q|StFq=YEi9m>Rz=Iph*t4<F{po_5)iv)
z+3s-EkD90Ny3*3H)Z{GS7<ID!{<Z3V0mz?o-PxH!o6@WdzJ#>#3)rz+Fl{EgsZ8n_
zDwPT^^ai}DyaHzGz9A{BF{QFr#fyuJTi*fXX7c3@yN#DFIs_=$3+q-Z^qJTok&5|j
zR(v&%<M37g9UL4P@CB*x#xR8vQJW$=j{!j<eHOvyrvPvd<QL_GZ{`))tn)xkECZRC
z1O7k|=(GdCWkiFnzZZ_l3xLC{0(5N!oOUBn=s`gGKTQTIE9Ie($3n3GFu*(G!3}nD
zlw<IV2?&J0E81?{oR2^n<x1G;Vkx5SdkfB0N?_G8>qS@`!Bk3$K;Ri~he?YEGkbFs
z%8Tlra5ukE*U&B$iWCc)XUNLLFhm_K93&p*u|;m@PguYLpto~I?sv5HM5?XTVrlKH
zKDUU@>7Z1EBFRDfDdNCKE%Lm(GoUe0Mocb773`v}N1c}CsMy{tF*`txCIRl<1fpjR
z$26aVtvZA2<m0Y~7Wj`a5?$Ht;tY}Ykpts?bO?%zOLBL6*Kn50OA9VtD0xy;B&Yor
ZU;u{MV3Zvrsb2s9002ovPDHLkV1nrhZFv9y
new file mode 100644
--- /dev/null
+++ b/mail/themes/pinstripe/mail/preferences/applications.css
@@ -0,0 +1,85 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Firefox Preferences System.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Florian Queze <florian@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Line up the actions menu with action labels above and below it.
+ * Equalize the distance from the left side of the action box to the left side
+ * of the icon for both the menu and the non-menu versions of the action box.
+ * Also make sure the labels are the same distance away from the icons.
+ */
+.actionsMenu {
+  -moz-margin-start: -2px;
+  margin-top: 0;
+  margin-bottom: -1px;
+}
+
+.typeIcon,
+.actionIcon {
+  margin: 0px 3px;
+}
+
+richlistitem label {
+  -moz-margin-start: 1px;
+  margin-top: 2px;
+}
+
+richlistitem {
+  min-height: 22px;
+}
+
+richlistitem[appHandlerIcon="ask"],
+menuitem[appHandlerIcon="ask"] {
+  list-style-image: url("chrome://messenger/skin/preferences/alwaysAsk.png");
+}
+
+richlistitem[appHandlerIcon="save"],
+menuitem[appHandlerIcon="save"] {
+  list-style-image: url("chrome://messenger/skin/preferences/saveFile.png");
+}
+
+richlistitem[appHandlerIcon="plugin"],
+menuitem[appHandlerIcon="plugin"] {
+  list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+}
+
+.actionsMenu .menulist-icon {
+  -moz-margin-end: 1px;
+}
+
+.actionsMenu > menupopup > menuitem > .menu-iconic-left {
+  -moz-padding-start: 3px;
+  -moz-padding-end: 1px;
+}
--- a/mail/themes/pinstripe/mail/preferences/preferences.css
+++ b/mail/themes/pinstripe/mail/preferences/preferences.css
@@ -103,62 +103,53 @@ radio[pane=paneCompose]:active {
 radio[pane=paneSecurity] {
   -moz-image-region: rect(0px 128px 32px 96px);
 }
 
 radio[pane=paneSecurity]:active {
   -moz-image-region: rect(32px 128px 64px 96px);
 }
 
-radio[pane=paneDownloads] {
+radio[pane=paneApplications] {
   -moz-image-region: rect(0px 160px 32px 128px);
 }
 
-radio[pane=paneDownloads]:active {
+radio[pane=paneApplications]:active {
   -moz-image-region: rect(32px 160px 64px 128px);
 }
 
 radio[pane=paneAdvanced] {
   -moz-image-region: rect(0px, 256px, 32px, 224px)
 }
 
 radio[pane=paneAdvanced]:active {
   -moz-image-region: rect(32px, 256px, 64px, 224px)
 }
 
+/* Attachments Pane */
+#MailPreferences[animated="true"] #handlersView {
+  height: 25em;
+}
+
+#MailPreferences[animated="false"] #handlersView {
+  -moz-box-flex: 1;
+}
+
 #browserStartupHomepage {
   padding-top: 2px;
   padding-bottom: 3px;
   -moz-padding-start: 4px;
   -moz-padding-end: 2px;
 }
 
 #downloadFolderIcon {
   width: 16px;
   height: 16px;
 }
 
-#downloadFolderContainer {
-  margin-top: 2px;
-  margin-bottom: 2px;
-  -moz-margin-start: 27px;
-  -moz-margin-end: 4px;
-  -moz-appearance: textfield;
-}
-
-#downloadFolderContainer2 {
-  background-color: -moz-Dialog;
-  color: -moz-DialogText;
-  margin: 1px;
-  padding-top: 0px;
-  padding-bottom: 0px;
-  -moz-padding-start: 3px;
-  -moz-padding-end: 0px;
-}
-
 #downloadFolder {
   -moz-appearance: none;
   background-color: transparent;
   border: none;
   padding: 1px 0px 0px;
 }
 
 prefpane .groupbox-body {
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7177f8df3001e84c14d6e86e5bf327bb510f3cd1
GIT binary patch
literal 570
zc$@(`0>%A_P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz+(|@1RCwB)lfQ4;P!Pwz2LAv|OGP50
zcwmZJRe~W4OWQx8OCn`R{*A1eqC|?6`~my}RrXFD+Nl#umv%^1Awg)VGGM?MFgAAX
zp8aSj3{6k^TKCR(pLg&4tN?gPdXE3I?<zeijYi|LSS*$wQ`zhF+O=Bkm;u@Od|vK$
zyN}vhRaM?F%Ye*uIz^|`K^TVrS`5pw*v&A&2!a6pejmY$y_MwlosWwHYbjQ**HJ2!
z*fm543>XXs`1CEk0vOsMTCLVnjB~kW(Sh&#@H`KdyK~HDvlYnI)gNEibrcE(aE<Ih
z0IJoh2+}}BqGI~+<6RJ?LTD3H_~~>Snx-uQ^rRgz9M*U|Ms72NH<`o$mB6D6a=Bc*
zjv{#kT>ui=!fe}y@kGHGwph>gDIz=G`7hI#I*{f#4z>$AykIESLDt30F+rDYEkKh1
z9^}S;4_odC11`+OM+oT%siPa*;s(VJuV5I41ZXLqSF_pt$q?6d@$saMXXewj7pQ$<
ziX6`68m?97aX@-2FBysZw61@jR{HJ`ZZxD>I5^pP_m$$m_&4C@lKl5#qEd<FNpDDJ
z1c^?69P*2^B$k(7K}va0Nc|`eA-km4$@(+t3uz<)((VNq0K^{Rm*!FE?*IS*07*qo
IM6N<$g1FxUSO5S3
--- a/mail/themes/qute/jar.mn
+++ b/mail/themes/qute/jar.mn
@@ -89,22 +89,26 @@ classic.jar:
   skin/classic/messenger/addressbook/icons/abcard-large.png   (mail/addrbook/abcard-large.png)
   skin/classic/messenger/addressbook/icons/remote-addrbook.png (mail/addrbook/remote-addrbook.png)
   skin/classic/messenger/addressbook/icons/remote-addrbook-error.png      (mail/addrbook/remote-addrbook-error.png)
   skin/classic/messenger/addressbook/icons/secure-remote-addrbook.png     (mail/addrbook/secure-remote-addrbook.png)
   skin/classic/messenger/messengercompose/messengercompose.css (mail/compose/messengercompose.css)
   skin/classic/messenger/messengercompose/compose-toolbar.png  (mail/compose/compose-toolbar.png)
   skin/classic/messenger/messengercompose/compose-toolbar-small.png   (mail/compose/compose-toolbar-small.png)
   skin/classic/messenger/messengercompose/format-buttons.png  (mail/compose/format-buttons.png)
+  skin/classic/messenger/preferences/alwaysAsk.png            (mail/preferences/alwaysAsk.png)
+  skin/classic/messenger/preferences/application.png          (mail/preferences/application.png)
   skin/classic/messenger/preferences/preferences.css          (mail/preferences/preferences.css)
   skin/classic/messenger/preferences/general.png              (mail/preferences/general.png)
   skin/classic/messenger/preferences/display.png              (mail/preferences/display.png)
   skin/classic/messenger/preferences/composition.png          (mail/preferences/composition.png)
   skin/classic/messenger/preferences/security.png             (mail/preferences/security.png)
   skin/classic/messenger/preferences/attachments.png          (mail/preferences/attachments.png)
+  skin/classic/messenger/preferences/applications.css         (mail/preferences/applications.css)
+  skin/classic/messenger/preferences/saveFile.png             (mail/preferences/saveFile.png)
   skin/classic/messenger/preferences/advanced.png             (mail/preferences/advanced.png)
   skin/classic/messenger/preferences/background.png           (mail/preferences/background.png)
   skin/classic/messenger/preferences/hover.png                (mail/preferences/hover.png)
   skin/classic/messenger/preferences/selected.png             (mail/preferences/selected.png)
   skin/classic/messenger/smime/msgCompSMIMEOverlay.css        (mail/smime/msgCompSMIMEOverlay.css)
   skin/classic/messenger/smime/msgHdrViewSMIMEOverlay.css     (mail/smime/msgHdrViewSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSMIMEOverlay.css        (mail/smime/msgReadSMIMEOverlay.css)
   skin/classic/messenger/smime/msgReadSecurityInfo.css        (mail/smime/msgReadSecurityInfo.css)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ddd4cb2130b28944644838a11f4050da251dfbc6
GIT binary patch
literal 446
zc$@*g0YUzWP)<h;3K|Lk000e1NJLTq000mG000mO0{{R3C@l|D0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUyu~1A@MgRZ*hL56~sJ^Sd%>if34{y&l
zhSxWT*ie?;VW8lAujYQS=7x`=iM7?2!0emC?w-T$r^xZI&hWL-@VC#{yw>r()%U>H
z_rcip!`S!3+4siV_s84!%H8+M-T2Pm_|D+?&fxja;r7zw`P1Y1*X8-w<@(p=`rGLG
z-01q?>iXd7`{3*P;OqP3?fc~J`{nNY>G1pM@cilV{Oa=h?eqNb_5Jbn{q*<!_xb($
z`~7INcsKw600eYWPE!DXzu%b;G{pb_0Fy~XK~xwS1;If|!%!3ez)5)sF@dTp1;HD5
z|GShfnvI~F7Ji^j``>dW3=;s>3ez{XldmWKep;aFaN#_@_X~lleSIEpx84!RdY!Wj
zJrSr!*73f3$&Ns;N8WcIm4!fVS@V#YiNKaUo2jx8oPXacr@R7TU7(FuScPhH_GN5<
ofWC|kAmH@e00dSIfItDjKePZ;0q=p3p#T5?07*qoM6N<$f+EuPmH+?%
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ff2ecc2f351ef37d250264aa2bb273de08518165
GIT binary patch
literal 441
zc$@*b0Y?6bP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzTS-JgRCwB?ld(?2Fc5~%sR=_DiXuQr
zNPrju-B_6ciT401BwmD_0WtFiz|O#o)PaGGN^Gbt0~Kw2clhi$NfARKmYh2~ci;VI
z%Zizy&QR;ey_2Xhx{9L7%t<C&06jMpd#bk1x~yY_)m?&qZ|zUjhp%6tTKo6hOcs9)
zNZOmw-q7%H`!eNs8W(Uld4hw%r3Z}Ppa0eWe6j;N9=*Zi%@K6_<Czmb^a?D+44v~k
z(6W)H+mKo-H-ZF!_F}{mF&J5+x5lm!!TFg4*r5YeZWCF7jj@RYOeKW4gql#q&ZZf7
zfKQT5_JQaV4EkWHEWSYnS%|aiPu=nWk?tT|fly^FKvK?kh4MCv7Rde-*_cBdF!b!s
zB*-o;<$y>&SW!TEe?_(G{GqG>6oFW&%xWr`oGNxUKuQ2`E?;>y0meZ|I80TxlmpcA
j-gT|#sOmoFZvh4XI{Y{EXY5e800000NkvXXu0mjfIC{Zy
new file mode 100644
--- /dev/null
+++ b/mail/themes/qute/mail/preferences/applications.css
@@ -0,0 +1,90 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Firefox Preferences System.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Florian Queze <florian@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Line up the actions menu with action labels above and below it.
+ * Equalize the distance from the left side of the action box to the left side
+ * of the icon for both the menu and the non-menu versions of the action box.
+ * Also make sure the labels are the same distance away from the icons.
+ */
+.actionsMenu {
+  margin-top: 0;
+  margin-bottom: 0;
+  -moz-margin-start: -2px;
+  -moz-margin-end: 0;
+}
+
+.typeIcon,
+.actionIcon {
+  margin: 0px 3px;
+}
+
+richlistitem label {
+  -moz-margin-start: 1px;
+  margin-top: 2px;
+}
+
+richlistitem {
+  min-height: 22px;
+}
+
+richlistitem[appHandlerIcon="ask"],
+menuitem[appHandlerIcon="ask"] {
+  list-style-image: url("chrome://messenger/skin/preferences/alwaysAsk.png");
+}
+
+richlistitem[appHandlerIcon="save"],
+menuitem[appHandlerIcon="save"] {
+  list-style-image: url("chrome://messenger/skin/preferences/saveFile.png");
+}
+
+richlistitem[appHandlerIcon="plugin"],
+menuitem[appHandlerIcon="plugin"] {
+  list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+}
+
+.actionsMenu .menulist-icon {
+  -moz-margin-end: 3px;
+}
+
+.actionsMenu > menupopup > menuitem > .menu-iconic-left {
+  -moz-padding-start: 0px;
+  -moz-padding-end: 2px;
+}
+
+.actionsMenu > menupopup > menuitem {
+  -moz-padding-start: 4px;
+}
--- a/mail/themes/qute/mail/preferences/preferences.css
+++ b/mail/themes/qute/mail/preferences/preferences.css
@@ -77,23 +77,32 @@ radio[pane=paneDisplay] {
   list-style-image: url("chrome://messenger/skin/preferences/display.png");
 }
 radio[pane=paneCompose] {
   list-style-image: url("chrome://messenger/skin/preferences/composition.png");
 }
 radio[pane=paneSecurity] {
   list-style-image: url("chrome://messenger/skin/preferences/security.png");
 }
-radio[pane=paneDownloads] {
+radio[pane=paneApplications] {
   list-style-image: url("chrome://messenger/skin/preferences/attachments.png");
 }
 radio[pane=paneAdvanced] {
   list-style-image: url("chrome://messenger/skin/preferences/advanced.png");
 }
 
+/* Attachments Pane */
+#MailPreferences[animated="true"] #handlersView {
+  height: 25em;
+}
+
+#MailPreferences[animated="false"] #handlersView {
+  -moz-box-flex: 1;
+}
+
 /* File Field Widget */
 filefield {
   margin: 2px 4px;
   -moz-appearance: textfield;
 }
 
 .fileFieldContentBox {
   background-color: -moz-Dialog;
@@ -135,89 +144,16 @@ filefield[disabled="true"] .fileFieldIco
 .contentPane {
   margin: 9px 8px 5px;
 }
 
 .actionButtons {
   margin: 0px 3px 6px !important;
 }
 
-/* Download Actions Manager */
-#fileExtension {
-  width: 5em; 
-}
-
-#extensionChildren::-moz-tree-image(fileExtension) {
-  margin-top: 0px;
-  margin-bottom: 0px;
-  -moz-margin-start: 0px;
-  -moz-margin-end: 5px;
-}
-
-#typeField {
-  font-weight: bold; 
-}
-
-/* Change Action Dialog */
-#typeIcon {
-  width: 32px;
-  height: 32px;
-  -moz-margin-end: 3px;
-}
-
-#typeField {
-  background-color: transparent;
-  margin-top: 1px !important;
-  margin-bottom: 2px !important;
-  -moz-margin-start: 6px !important;
-  -moz-margin-end: 5px !important;
-}
-
-#extensionField {
-  color: GrayText;
-  font-weight: bold;
-}
-
-#ChangeActionDialog {
-  padding: 0px;
-}
-
-#ChangeActionDialog .dialog-button-box {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  -moz-padding-start: 8px;
-  -moz-padding-end: 10px;
-}
-
-#changeActionHeader {
-  border-bottom: 2px groove ThreeDFace;
-  margin: 0px;
-  padding: 10px;
-  background-color: -moz-Field;
-  color: -moz-FieldText;  
-}
-
-#changeActionContent {
-  padding-top: 8px;
-  padding-bottom: 10px;
-  -moz-padding-start: 9px;
-  -moz-padding-end: 10px;
-}
-
-#defaultAppIcon {
-  width: 16px;
-  height: 16px;
-  -moz-margin-start: 2px;
-}
-
-#defaultAppName {
-  -moz-margin-start: 6px !important; 
-  font-weight: bold;
-}
-
 /* override the color style for tag items when they 
    have selection */
 #tagList listitem[selected="true"] {
   color: -moz-DialogText !important;
 }
 
 #tagList:focus > listitem[selected="true"] {
   color: HighlightText !important;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c210e8473f4c7ee9958a80b94965d522a15e4584
GIT binary patch
literal 791
zc$@(j1L*vTP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!xk*GpRCwBqQ%^_~Q5gTt%-fxvo!LKb
z?rOAaD+Y>x@L-W5v_-X*SQwRo7G!}+*r7v4b;+W_n?%u`Hav9c804u_P+mF)ff1Ry
z>bSe1uDdfkyF1gH5w<Lae(=3FZ@z!O?|a{448y>7Xq_a6w&H-U5KByaeUf7Swj<a9
zy2j$f>1g@<CiY=lJ1fBO@bKNnrnX1A;RMUF@K?IZ26OUE`FrB&E2CH}LdmTnvG8Rq
z7K`1t0tBk|9_r~igYR=J1VKPstAxk#f3ro7oX6tgB67JkC`#rqP0X-#5vr?$^)5+5
zq|=Xq_W?AGyHUz)txj8z(0#8NgU_R27y_@is*e74vUCah{ej&a;ZZ06H;;`W5b`40
zb+YW7p_FU-WY`0F^mSdMWpWT*z5rE)%`^=jPX%8r5&T#H`s!|>s2X_r?ip%YcUjI^
zWfe<reK^-Xh)Adx*=!aLUbIu+CX+#<%k84H0FH*6`KIA`<tVzVujA8XdeeEzhu(uD
zI2yhTP1C3?1Djni$?YSO%h#afotRG)5vU~KD(uK9z}e<eY^)o2J@o<?4vgSb;}xi?
zx>-^t1Kw_fDEXR+$Lnvg*&N8{^DvCf#t9CfRAO;8a);it0~gzGSbFn{&FnnS({mP*
zRMA2h5T7is!0j#|l}cGge@e9e64L234OoIX0|m3w6snr1CG!#~m2^W8oQTKcG>9AF
za2U0<wbmXAdhp=k#Fp#q@9#%4nM5LyFxlv=0YfAlM+ZZ(6lQ%UU0v6~(H0Xzwn%V~
zAE8hP(;ug)o)d|hTU$=0mZ~~CJ0Qz4bu>qHg9ciIoD?96LOHuAikO>U!tCrU+B^2+
zXY%thGc+_bz&pIRiA{8y143yTW}{58Kwqm)#rQ3ZsViui^}M<|&g}G@{};am7y$KC
V4iS|FcUu4e002ovPDHLkV1njJbGZNj