Bug 781973 - Use filepicker's open() instead of the obsolete show() in /browser. r=bbondy
authorAndres Hernandez <andres@appcoast.com>
Wed, 19 Sep 2012 17:21:38 -0600
changeset 114088 b22c10ecf39093cbb540e3722245b4bbd638d885
parent 114087 294643a303c1b9fa4351a793406daf1ec7b8f0cf
child 114089 6731957980f9e11a211944bcb448ba3b85aac478
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs781973
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 781973 - Use filepicker's open() instead of the obsolete show() in /browser. r=bbondy
browser/base/content/browser.js
browser/base/content/openLocation.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/sync/utils.js
browser/components/feeds/src/FeedWriter.js
browser/components/places/content/places.js
browser/components/preferences/applications.js
browser/components/preferences/in-content/applications.js
browser/components/preferences/in-content/main.js
browser/components/preferences/main.js
browser/devtools/scratchpad/scratchpad.js
browser/devtools/styleeditor/StyleEditor.jsm
widget/nsIFilePicker.idl
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2071,31 +2071,38 @@ var gLastOpenDirectory = {
     this._lastDir = null;
   }
 };
 
 function BrowserOpenFileWindow()
 {
   // Get filepicker component.
   try {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
-    fp.init(window, gNavigatorBundle.getString("openFile"), nsIFilePicker.modeOpen);
-    fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | nsIFilePicker.filterImages |
-                     nsIFilePicker.filterXML | nsIFilePicker.filterHTML);
+    const nsIFilePicker = Ci.nsIFilePicker;
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == nsIFilePicker.returnOK) {
+        try {
+          if (fp.file) {
+            gLastOpenDirectory.path =
+              fp.file.parent.QueryInterface(Ci.nsILocalFile);
+          }
+        } catch (ex) {
+        }
+        openUILinkIn(fp.fileURL.spec, "current");
+      }
+    };
+
+    fp.init(window, gNavigatorBundle.getString("openFile"),
+            nsIFilePicker.modeOpen);
+    fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText |
+                     nsIFilePicker.filterImages | nsIFilePicker.filterXML |
+                     nsIFilePicker.filterHTML);
     fp.displayDirectory = gLastOpenDirectory.path;
-
-    if (fp.show() == nsIFilePicker.returnOK) {
-      try {
-        if (fp.file)
-          gLastOpenDirectory.path = fp.file.parent.QueryInterface(Ci.nsILocalFile);
-      } catch(e) {
-      }
-      openUILinkIn(fp.fileURL.spec, "current");
-    }
+    fp.open(fpCallback);
   } catch (ex) {
   }
 }
 
 function BrowserCloseTabOrWindow() {
 #ifdef XP_MACOSX
   // If we're not a browser window, just close the window
   if (window.location.href != getBrowserURL()) {
--- a/browser/base/content/openLocation.js
+++ b/browser/base/content/openLocation.js
@@ -107,20 +107,27 @@ function createInstance(contractid, iidN
   var iid = Components.interfaces[iidName];
   return Components.classes[contractid].createInstance(iid);
 }
 
 const nsIFilePicker = Components.interfaces.nsIFilePicker;
 function onChooseFile()
 {
   try {
-    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
-    fp.init(window, dialog.bundle.getString("chooseFileDialogTitle"), nsIFilePicker.modeOpen);
-    fp.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterText |
-                     nsIFilePicker.filterAll | nsIFilePicker.filterImages | nsIFilePicker.filterXML);
+    let fp = Components.classes["@mozilla.org/filepicker;1"].
+             createInstance(nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == nsIFilePicker.returnOK && fp.fileURL.spec &&
+          fp.fileURL.spec.length > 0) {
+        dialog.input.value = fp.fileURL.spec;
+      }
+      doEnabling();
+    };
 
-    if (fp.show() == nsIFilePicker.returnOK && fp.fileURL.spec && fp.fileURL.spec.length > 0)
-      dialog.input.value = fp.fileURL.spec;
+    fp.init(window, dialog.bundle.getString("chooseFileDialogTitle"),
+            nsIFilePicker.modeOpen);
+    fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText |
+                     nsIFilePicker.filterImages | nsIFilePicker.filterXML |
+                     nsIFilePicker.filterHTML);
+    fp.open(fpCallback);
+  } catch (ex) {
   }
-  catch(ex) {
-  }
-  doEnabling();
 }
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -756,41 +756,43 @@ function getSelectedRows(tree)
 }
 
 function getSelectedRow(tree)
 {
   var rows = getSelectedRows(tree);
   return (rows.length == 1) ? rows[0] : -1;
 }
 
-function selectSaveFolder()
+function selectSaveFolder(aCallback)
 {
   const nsILocalFile = Components.interfaces.nsILocalFile;
   const nsIFilePicker = Components.interfaces.nsIFilePicker;
-  var fp = Components.classes["@mozilla.org/filepicker;1"]
-                     .createInstance(nsIFilePicker);
-
-  var titleText = gBundle.getString("mediaSelectFolder");
-  fp.init(window, titleText, nsIFilePicker.modeGetFolder);
-  try {
-    var prefs = Components.classes[PREFERENCES_CONTRACTID]
-                          .getService(Components.interfaces.nsIPrefBranch);
+  let titleText = gBundle.getString("mediaSelectFolder");
+  let fp = Components.classes["@mozilla.org/filepicker;1"].
+           createInstance(nsIFilePicker);
+  let fpCallback = function fpCallback_done(aResult) {
+    if (aResult == nsIFilePicker.returnOK) {
+      aCallback(fp.file.QueryInterface(nsILocalFile));
+    } else {
+      aCallback(null);
+    }
+  };
 
-    var initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile);
-    if (initialDir)
+  fp.init(window, titleText, nsIFilePicker.modeGetFolder);
+  fp.appendFilters(nsIFilePicker.filterAll);
+  try {
+    let prefs = Components.classes[PREFERENCES_CONTRACTID].
+                getService(Components.interfaces.nsIPrefBranch);
+    let initialDir = prefs.getComplexValue("browser.download.dir", nsILocalFile);
+    if (initialDir) {
       fp.displayDirectory = initialDir;
+    }
+  } catch (ex) {
   }
-  catch (ex) { }
-
-  fp.appendFilters(nsIFilePicker.filterAll);
-  var ret = fp.show();
-
-  if (ret == nsIFilePicker.returnOK)
-    return fp.file.QueryInterface(nsILocalFile);
-  return null;
+  fp.open(fpCallback);
 }
 
 function saveMedia()
 {
   var tree = document.getElementById("imagetree");
   var rowArray = getSelectedRows(tree);
   if (rowArray.length == 1) {
     var row = rowArray[0];
@@ -802,47 +804,49 @@ function saveMedia()
 
       if (item instanceof HTMLVideoElement)
         titleKey = "SaveVideoTitle";
       else if (item instanceof HTMLAudioElement)
         titleKey = "SaveAudioTitle";
 
       saveURL(url, null, titleKey, false, false, makeURI(item.baseURI));
     }
-  }
-  else {
-    var odir  = selectSaveFolder();
-
-    var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
-      internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
-                   aChosenData, aBaseURI);
-    }
-
-    for (var i = 0; i < rowArray.length; i++) {
-      var v = rowArray[i];
-      var dir = odir.clone();
-      var item = gImageView.data[v][COL_IMAGE_NODE];
-      var uriString = gImageView.data[v][COL_IMAGE_ADDRESS];
-      var uri = makeURI(uriString);
- 
-      try {
-        uri.QueryInterface(Components.interfaces.nsIURL);
-        dir.append(decodeURIComponent(uri.fileName));
+  } else {
+    selectSaveFolder(function(aDirectory) {
+      if (aDirectory) {
+        var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
+          internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
+                       aChosenData, aBaseURI);
+        };
+      
+        for (var i = 0; i < rowArray.length; i++) {
+          var v = rowArray[i];
+          var dir = aDirectory.clone();
+          var item = gImageView.data[v][COL_IMAGE_NODE];
+          var uriString = gImageView.data[v][COL_IMAGE_ADDRESS];
+          var uri = makeURI(uriString);
+  
+          try {
+            uri.QueryInterface(Components.interfaces.nsIURL);
+            dir.append(decodeURIComponent(uri.fileName));
+          } catch(ex) {
+            /* data: uris */
+          }
+  
+          if (i == 0) {
+            saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI));
+          } else {
+            // This delay is a hack which prevents the download manager
+            // from opening many times. See bug 377339.
+            setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri),
+                       makeURI(item.baseURI));
+          }
+        }
       }
-      catch(ex) { /* data: uris */ }
-
-      if (i == 0)
-        saveAnImage(uriString, new AutoChosen(dir, uri), makeURI(item.baseURI));
-      else {
-        // This delay is a hack which prevents the download manager
-        // from opening many times. See bug 377339.
-        setTimeout(saveAnImage, 200, uriString, new AutoChosen(dir, uri),
-                   makeURI(item.baseURI));
-      }
-    }
+    });
   }
 }
 
 function onBlockImage()
 {
   var permissionManager = Components.classes[PERMISSION_CONTRACTID]
                                     .getService(nsIPermissionManager);
 
--- a/browser/base/content/sync/utils.js
+++ b/browser/base/content/sync/utils.js
@@ -146,36 +146,38 @@ let gSyncUtils = {
    * Save passphrase backup document to disk as HTML file.
    * 
    * @param elid : ID of the form element containing the passphrase.
    */
   passphraseSave: function(elid) {
     let dialogTitle = this.bundle.GetStringFromName("save.recoverykey.title");
     let defaultSaveName = this.bundle.GetStringFromName("save.recoverykey.defaultfilename");
     this._preparePPiframe(elid, function(iframe) {
-      let filepicker = Cc["@mozilla.org/filepicker;1"]
-                         .createInstance(Ci.nsIFilePicker);
-      filepicker.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
-      filepicker.appendFilters(Ci.nsIFilePicker.filterHTML);
-      filepicker.defaultString = defaultSaveName;
-      let rv = filepicker.show();
-      if (rv == Ci.nsIFilePicker.returnOK
-          || rv == Ci.nsIFilePicker.returnReplace) {
-        let stream = Cc["@mozilla.org/network/file-output-stream;1"]
-                       .createInstance(Ci.nsIFileOutputStream);
-        stream.init(filepicker.file, -1, 0600, 0);
+      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+      let fpCallback = function fpCallback_done(aResult) {
+        if (aResult == Ci.nsIFilePicker.returnOK ||
+            aResult == Ci.nsIFilePicker.returnReplace) {
+          let stream = Cc["@mozilla.org/network/file-output-stream;1"].
+                       createInstance(Ci.nsIFileOutputStream);
+          stream.init(fp.file, -1, 0600, 0);
 
-        let serializer = new XMLSerializer();
-        let output = serializer.serializeToString(iframe.contentDocument);
-        output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
-          '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
-          '"DTD/xhtml1-strict.dtd">');
-        output = Weave.Utils.encodeUTF8(output);
-        stream.write(output, output.length);
-      }
+          let serializer = new XMLSerializer();
+          let output = serializer.serializeToString(iframe.contentDocument);
+          output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
+            '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
+            '"DTD/xhtml1-strict.dtd">');
+          output = Weave.Utils.encodeUTF8(output);
+          stream.write(output, output.length);
+        }
+      };
+
+      fp.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
+      fp.appendFilters(Ci.nsIFilePicker.filterHTML);
+      fp.defaultString = defaultSaveName;
+      fp.open(fpCallback);
       return false;
     });
   },
 
   /**
    * validatePassword
    *
    * @param el1 : the first textbox element in the form
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -703,56 +703,63 @@ FeedWriter.prototype = {
    */
   _getUIElement: function FW__getUIElement(id) {
     return this._document.getAnonymousElementByAttribute(
       this._document.getElementById("feedSubscribeLine"), "anonid", id);
   },
 
   /**
    * Displays a prompt from which the user may choose a (client) feed reader.
-   * @return - true if a feed reader was selected, false otherwise.
+   * @param aCallback the callback method, passes in true if a feed reader was
+   *        selected, false otherwise.
    */
-  _chooseClientApp: function FW__chooseClientApp() {
+  _chooseClientApp: function FW__chooseClientApp(aCallback) {
     try {
-      var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-      fp.init(this._window,
-              this._getString("chooseApplicationDialogTitle"),
-              Ci.nsIFilePicker.modeOpen);
-      fp.appendFilters(Ci.nsIFilePicker.filterApps);
-
-      if (fp.show() == Ci.nsIFilePicker.returnOK) {
-        this._selectedApp = fp.file;
-        if (this._selectedApp) {
-          // 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
+      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+      let fpCallback = function fpCallback_done(aResult) {
+        if (aResult == Ci.nsIFilePicker.returnOK) {
+          this._selectedApp = fp.file;
+          if (this._selectedApp) {
+            // 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           if (fp.file.leafName != "__MOZ_APP_NAME__.exe") {
+#expand             if (fp.file.leafName != "__MOZ_APP_NAME__.exe") {
 #else
 #ifdef XP_MACOSX
-#expand           if (fp.file.leafName != "__MOZ_MACBUNDLE_NAME__") {
+#expand             if (fp.file.leafName != "__MOZ_MACBUNDLE_NAME__") {
 #else
-#expand           if (fp.file.leafName != "__MOZ_APP_NAME__-bin") {
+#expand             if (fp.file.leafName != "__MOZ_APP_NAME__-bin") {
 #endif
 #endif
-            this._initMenuItemWithFile(this._contentSandbox.selectedAppMenuItem,
-                                       this._selectedApp);
+              this._initMenuItemWithFile(this._contentSandbox.selectedAppMenuItem,
+                                         this._selectedApp);
 
-            // Show and select the selected application menuitem
-            var codeStr = "selectedAppMenuItem.hidden = false;" +
-                          "selectedAppMenuItem.doCommand();"
-            Cu.evalInSandbox(codeStr, this._contentSandbox);
-            return true;
+              // Show and select the selected application menuitem
+              let codeStr = "selectedAppMenuItem.hidden = false;" +
+                            "selectedAppMenuItem.doCommand();"
+              Cu.evalInSandbox(codeStr, this._contentSandbox);
+              if (aCallback) {
+                aCallback(true);
+                return;
+              }
+            }
           }
         }
-      }
+        if (aCallback) {
+          aCallback(false);
+        }
+      }.bind(this);
+
+      fp.init(this._window, this._getString("chooseApplicationDialogTitle"),
+              Ci.nsIFilePicker.modeOpen);
+      fp.appendFilters(Ci.nsIFilePicker.filterApps);
+      fp.open(fpCallback);
+    } catch(ex) {
     }
-    catch(ex) { }
-
-    return false;
   },
 
   _setAlwaysUseCheckedState: function FW__setAlwaysUseCheckedState(feedType) {
     var checkbox = this._getUIElement("alwaysUse");
     if (checkbox) {
       var alwaysUse = false;
       try {
         var prefs = Cc["@mozilla.org/preferences-service;1"].
@@ -828,20 +835,24 @@ FeedWriter.prototype = {
            * by ignoring command events while the dropdown is closed (user
            * arrowing through the combobox), but handling them while the
            * combobox dropdown is open (user pressed enter when an item was
            * selected). If we don't show the filepicker here, it will be shown
            * when clicking "Subscribe Now".
            */
           var popupbox = this._handlersMenuList.firstChild.boxObject;
           popupbox.QueryInterface(Components.interfaces.nsIPopupBoxObject);
-          if (popupbox.popupState == "hiding" && !this._chooseClientApp()) {
-            // Select the (per-prefs) selected handler if no application was
-            // selected
-            this._setSelectedHandler(this._getFeedType());
+          if (popupbox.popupState == "hiding") {
+            this._chooseClientApp(function(aResult) {
+              if (!aResult) {
+                // Select the (per-prefs) selected handler if no application
+                // was selected
+                this._setSelectedHandler(this._getFeedType());
+              }
+            }.bind(this));
           }
           break;
         default:
           this._setAlwaysUseLabel();
       }
     }
   },
 
@@ -1205,80 +1216,87 @@ FeedWriter.prototype = {
 
     // Subscribe to the feed using the selected handler and save prefs
     var prefs = Cc["@mozilla.org/preferences-service;1"].
                 getService(Ci.nsIPrefBranch);
     var defaultHandler = "reader";
     var useAsDefault = this._getUIElement("alwaysUse").getAttribute("checked");
 
     var selectedItem = this._getSelectedItemFromMenulist(this._handlersMenuList);
+    let subscribeCallback = function() {
+      if (selectedItem.hasAttribute("webhandlerurl")) {
+        var webURI = selectedItem.getAttribute("webhandlerurl");
+        prefs.setCharPref(getPrefReaderForType(feedType), "web");
+
+        var supportsString = Cc["@mozilla.org/supports-string;1"].
+                             createInstance(Ci.nsISupportsString);
+        supportsString.data = webURI;
+        prefs.setComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString,
+                              supportsString);
+
+        var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
+                   getService(Ci.nsIWebContentConverterService);
+        var handler = wccr.getWebContentHandlerByURI(this._getMimeTypeForFeedType(feedType), webURI);
+        if (handler) {
+          if (useAsDefault) {
+            wccr.setAutoHandler(this._getMimeTypeForFeedType(feedType), handler);
+          }
+
+          this._window.location.href = handler.getHandlerURI(this._window.location.href);
+        }
+      } else {
+        switch (selectedItem.getAttribute("anonid")) {
+          case "selectedAppMenuItem":
+            prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile, 
+                                  this._selectedApp);
+            prefs.setCharPref(getPrefReaderForType(feedType), "client");
+            break;
+          case "defaultHandlerMenuItem":
+            prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile, 
+                                  this._defaultSystemReader);
+            prefs.setCharPref(getPrefReaderForType(feedType), "client");
+            break;
+          case "liveBookmarksMenuItem":
+            defaultHandler = "bookmarks";
+            prefs.setCharPref(getPrefReaderForType(feedType), "bookmarks");
+            break;
+        }
+        var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
+                          getService(Ci.nsIFeedResultService);
+
+        // Pull the title and subtitle out of the document
+        var feedTitle = this._document.getElementById(TITLE_ID).textContent;
+        var feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
+        feedService.addToClientReader(this._window.location.href, feedTitle, feedSubtitle, feedType);
+      }
+
+      // If "Always use..." is checked, we should set PREF_*SELECTED_ACTION
+      // to either "reader" (If a web reader or if an application is selected),
+      // or to "bookmarks" (if the live bookmarks option is selected).
+      // Otherwise, we should set it to "ask"
+      if (useAsDefault) {
+        prefs.setCharPref(getPrefActionForType(feedType), defaultHandler);
+      } else {
+        prefs.setCharPref(getPrefActionForType(feedType), "ask");
+      }
+    }.bind(this);
 
     // Show the file picker before subscribing if the
     // choose application menuitem was chosen using the keyboard
     if (selectedItem.getAttribute("anonid") == "chooseApplicationMenuItem") {
-      if (!this._chooseClientApp())
-        return;
-      
-      selectedItem = this._getSelectedItemFromMenulist(this._handlersMenuList);
-    }
-
-    if (selectedItem.hasAttribute("webhandlerurl")) {
-      var webURI = selectedItem.getAttribute("webhandlerurl");
-      prefs.setCharPref(getPrefReaderForType(feedType), "web");
-
-      var supportsString = Cc["@mozilla.org/supports-string;1"].
-                           createInstance(Ci.nsISupportsString);
-      supportsString.data = webURI;
-      prefs.setComplexValue(getPrefWebForType(feedType), Ci.nsISupportsString,
-                            supportsString);
-
-      var wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
-                 getService(Ci.nsIWebContentConverterService);
-      var handler = wccr.getWebContentHandlerByURI(this._getMimeTypeForFeedType(feedType), webURI);
-      if (handler) {
-        if (useAsDefault)
-          wccr.setAutoHandler(this._getMimeTypeForFeedType(feedType), handler);
-
-        this._window.location.href = handler.getHandlerURI(this._window.location.href);
-      }
+      this._chooseClientApp(function(aResult) {
+        if (aResult) {
+          selectedItem =
+            this._getSelectedItemFromMenulist(this._handlersMenuList);
+          subscribeCallback();
+        }
+      }.bind(this));
+    } else {
+      subscribeCallback();
     }
-    else {
-      switch (selectedItem.getAttribute("anonid")) {
-        case "selectedAppMenuItem":
-          prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile, 
-                                this._selectedApp);
-          prefs.setCharPref(getPrefReaderForType(feedType), "client");
-          break;
-        case "defaultHandlerMenuItem":
-          prefs.setComplexValue(getPrefAppForType(feedType), Ci.nsILocalFile, 
-                                this._defaultSystemReader);
-          prefs.setCharPref(getPrefReaderForType(feedType), "client");
-          break;
-        case "liveBookmarksMenuItem":
-          defaultHandler = "bookmarks";
-          prefs.setCharPref(getPrefReaderForType(feedType), "bookmarks");
-          break;
-      }
-      var feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
-                        getService(Ci.nsIFeedResultService);
-
-      // Pull the title and subtitle out of the document
-      var feedTitle = this._document.getElementById(TITLE_ID).textContent;
-      var feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
-      feedService.addToClientReader(this._window.location.href, feedTitle, feedSubtitle, feedType);
-    }
-
-    // If "Always use..." is checked, we should set PREF_*SELECTED_ACTION
-    // to either "reader" (If a web reader or if an application is selected),
-    // or to "bookmarks" (if the live bookmarks option is selected).
-    // Otherwise, we should set it to "ask"
-    if (useAsDefault)
-      prefs.setCharPref(getPrefActionForType(feedType), defaultHandler);
-    else
-      prefs.setCharPref(getPrefActionForType(feedType), "ask");
   },
 
   // nsIObserver
   observe: function FW_observe(subject, topic, data) {
     if (!this._window) {
       // this._window is null unless this.init was called with a trusted
       // window object.
       return;
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -349,44 +349,49 @@ var PlacesOrganizer = {
   importFromBrowser: function PO_importFromBrowser() {
     MigrationUtils.showMigrationWizard(window);
   },
 
   /**
    * Open a file-picker and import the selected file into the bookmarks store
    */
   importFromFile: function PO_importFromFile() {
-    var fp = Cc["@mozilla.org/filepicker;1"].
-             createInstance(Ci.nsIFilePicker);
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult != Ci.nsIFilePicker.returnCancel && fp.fileURL) {
+        Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
+        BookmarkHTMLUtils.importFromURL(fp.fileURL.spec, false);
+      }
+    };
+
     fp.init(window, PlacesUIUtils.getString("SelectImport"),
             Ci.nsIFilePicker.modeOpen);
     fp.appendFilters(Ci.nsIFilePicker.filterHTML);
-    if (fp.show() != Ci.nsIFilePicker.returnCancel) {
-      if (fp.fileURL) {
-        Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
-        BookmarkHTMLUtils.importFromURL(fp.fileURL.spec, false);
-      }
-    }
+    fp.open(fpCallback);
   },
 
   /**
    * Allows simple exporting of bookmarks.
    */
   exportBookmarks: function PO_exportBookmarks() {
-    var fp = Cc["@mozilla.org/filepicker;1"].
-             createInstance(Ci.nsIFilePicker);
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult != Ci.nsIFilePicker.returnCancel) {
+        let exporter =
+          Cc["@mozilla.org/browser/places/import-export-service;1"].
+            getService(Ci.nsIPlacesImportExportService);
+        exporter.exportHTMLToFile(fp.file);
+      }
+    };
+
     fp.init(window, PlacesUIUtils.getString("EnterExport"),
             Ci.nsIFilePicker.modeSave);
     fp.appendFilters(Ci.nsIFilePicker.filterHTML);
     fp.defaultString = "bookmarks.html";
-    if (fp.show() != Ci.nsIFilePicker.returnCancel) {
-      var exporter = Cc["@mozilla.org/browser/places/import-export-service;1"].
-                     getService(Ci.nsIPlacesImportExportService);
-      exporter.exportHTMLToFile(fp.file);
-    }
+    fp.open(fpCallback);
   },
 
   /**
    * Populates the restore menu with the dates of the backups available.
    */
   populateRestoreMenu: function PO_populateRestoreMenu() {
     let restorePopup = document.getElementById("fileRestorePopup");
 
@@ -436,30 +441,33 @@ var PlacesOrganizer = {
     }
   },
 
   /**
    * Called when 'Choose File...' is selected from the restore menu.
    * Prompts for a file and restores bookmarks to those in the file.
    */
   onRestoreBookmarksFromFile: function PO_onRestoreBookmarksFromFile() {
-    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+                 getService(Ci.nsIProperties);
+    let backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult != Ci.nsIFilePicker.returnCancel) {
+        this.restoreBookmarksFromFile(fp.file);
+      }
+    }.bind(this);
+
     fp.init(window, PlacesUIUtils.getString("bookmarksRestoreTitle"),
             Ci.nsIFilePicker.modeOpen);
     fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
                     PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
     fp.appendFilters(Ci.nsIFilePicker.filterAll);
-
-    var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-                 getService(Ci.nsIProperties);
-    var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
     fp.displayDirectory = backupsDir;
-
-    if (fp.show() != Ci.nsIFilePicker.returnCancel)
-      this.restoreBookmarksFromFile(fp.file);
+    fp.open(fpCallback);
   },
 
   /**
    * Restores bookmarks from a JSON file.
    */
   restoreBookmarksFromFile: function PO_restoreBookmarksFromFile(aFile) {
     // check file extension
     if (!aFile.leafName.match(/\.json$/)) {
@@ -493,31 +501,33 @@ var PlacesOrganizer = {
   },
 
   /**
    * Backup bookmarks to desktop, auto-generate a filename with a date.
    * The file is a JSON serialization of bookmarks, tags and any annotations
    * of those items.
    */
   backupBookmarks: function PO_backupBookmarks() {
-    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+                 getService(Ci.nsIProperties);
+    let backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult != Ci.nsIFilePicker.returnCancel) {
+        PlacesUtils.backups.saveBookmarksToJSONFile(fp.file);
+      }
+    };
+
     fp.init(window, PlacesUIUtils.getString("bookmarksBackupTitle"),
             Ci.nsIFilePicker.modeSave);
     fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
                     PlacesUIUtils.getString("bookmarksRestoreFilterExtension"));
-
-    var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-                 getService(Ci.nsIProperties);
-    var backupsDir = dirSvc.get("Desk", Ci.nsILocalFile);
+    fp.defaultString = PlacesUtils.backups.getFilenameForDate();
     fp.displayDirectory = backupsDir;
-
-    fp.defaultString = PlacesUtils.backups.getFilenameForDate();
-
-    if (fp.show() != Ci.nsIFilePicker.returnCancel)
-      PlacesUtils.backups.saveBookmarksToJSONFile(fp.file);
+    fp.open(fpCallback);
   },
 
   _paneDisabled: false,
   _setDetailsFieldsDisabledState:
   function PO__setDetailsFieldsDisabledState(aDisabled) {
     if (aDisabled) {
       document.getElementById("paneElementsBroadcaster")
               .setAttribute("disabled", "true");
--- a/browser/components/preferences/applications.js
+++ b/browser/components/preferences/applications.js
@@ -1710,16 +1710,38 @@ var gApplicationsPane = {
   },
 
   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;
+    let chooseAppCallback = function(aHandlerApp) {
+      // Rebuild the actions menu whether the user picked an app or canceled.
+      // If they picked an app, we want to add the app to the menu and select it.
+      // If they canceled, we want to go back to their previous selection.
+      this.rebuildActionsMenu();
+
+      // If the user picked a new app from the menu, select it.
+      if (aHandlerApp) {
+        let typeItem = this._list.selectedItem;
+        let actionsMenu =
+          document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+        let menuItems = actionsMenu.menupopup.childNodes;
+        for (let i = 0; i < menuItems.length; i++) {
+          let menuItem = menuItems[i];
+          if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
+            actionsMenu.selectedIndex = i;
+            this.onSelectAction(menuItem);
+            break;
+          }
+        }
+      }
+    }.bind(this);
 
 #ifdef XP_WIN
     var params = {};
     var handlerInfo = this._handledTypes[this._list.selectedItem.type];
 
     if (isFeedType(handlerInfo.type)) {
       // MIME info will be null, create a temp object.
       params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type, 
@@ -1738,57 +1760,43 @@ var gApplicationsPane = {
                       params);
 
     if (this.isValidHandlerApp(params.handlerApp)) {
       handlerApp = params.handlerApp;
 
       // Add the app to the type's list of possible handlers.
       handlerInfo.addPossibleApplicationHandler(handlerApp);
     }
+
+    chooseAppCallback(handlerApp);
 #else
-    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-    var winTitle = this._prefsBundle.getString("fpTitleChooseApp");
-    fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
-    fp.appendFilters(Ci.nsIFilePicker.filterApps);
+    let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
+          this._isValidHandlerExecutable(fp.file)) {
+        handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+                     createInstance(Ci.nsILocalHandlerApp);
+        handlerApp.name = getFileDisplayName(fp.file);
+        handlerApp.executable = fp.file;
+
+        // Add the app to the type's list of possible handlers.
+        let handlerInfo = this._handledTypes[this._list.selectedItem.type];
+        handlerInfo.addPossibleApplicationHandler(handlerApp);
+
+        chooseAppCallback(handlerApp);
+      }
+    }.bind(this);
 
     // 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() == Ci.nsIFilePicker.returnOK && fp.file &&
-        this._isValidHandlerExecutable(fp.file)) {
-      handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
-                   createInstance(Ci.nsILocalHandlerApp);
-      handlerApp.name = getFileDisplayName(fp.file);
-      handlerApp.executable = fp.file;
-
-      // Add the app to the type's list of possible handlers.
-      let handlerInfo = this._handledTypes[this._list.selectedItem.type];
-      handlerInfo.addPossibleApplicationHandler(handlerApp);
-    }
+    fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
+    fp.appendFilters(Ci.nsIFilePicker.filterApps);
+    fp.open(fpCallback);
 #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"));
--- a/browser/components/preferences/in-content/applications.js
+++ b/browser/components/preferences/in-content/applications.js
@@ -1697,16 +1697,38 @@ var gApplicationsPane = {
   },
 
   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;
+    let chooseAppCallback = function(aHandlerApp) {
+      // Rebuild the actions menu whether the user picked an app or canceled.
+      // If they picked an app, we want to add the app to the menu and select it.
+      // If they canceled, we want to go back to their previous selection.
+      this.rebuildActionsMenu();
+
+      // If the user picked a new app from the menu, select it.
+      if (aHandlerApp) {
+        let typeItem = this._list.selectedItem;
+        let actionsMenu =
+          document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
+        let menuItems = actionsMenu.menupopup.childNodes;
+        for (let i = 0; i < menuItems.length; i++) {
+          let menuItem = menuItems[i];
+          if (menuItem.handlerApp && menuItem.handlerApp.equals(aHandlerApp)) {
+            actionsMenu.selectedIndex = i;
+            this.onSelectAction(menuItem);
+            break;
+          }
+        }
+      }
+    }.bind(this);
 
 #ifdef XP_WIN
     var params = {};
     var handlerInfo = this._handledTypes[this._list.selectedItem.type];
 
     if (isFeedType(handlerInfo.type)) {
       // MIME info will be null, create a temp object.
       params.mimeInfo = this._mimeSvc.getFromTypeAndExtension(handlerInfo.type, 
@@ -1725,57 +1747,43 @@ var gApplicationsPane = {
                       params);
 
     if (this.isValidHandlerApp(params.handlerApp)) {
       handlerApp = params.handlerApp;
 
       // Add the app to the type's list of possible handlers.
       handlerInfo.addPossibleApplicationHandler(handlerApp);
     }
+
+    chooseAppCallback(handlerApp);
 #else
-    var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-    var winTitle = this._prefsBundle.getString("fpTitleChooseApp");
-    fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
-    fp.appendFilters(Ci.nsIFilePicker.filterApps);
+    let winTitle = this._prefsBundle.getString("fpTitleChooseApp");
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == Ci.nsIFilePicker.returnOK && fp.file &&
+          this._isValidHandlerExecutable(fp.file)) {
+        handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
+                     createInstance(Ci.nsILocalHandlerApp);
+        handlerApp.name = getFileDisplayName(fp.file);
+        handlerApp.executable = fp.file;
+
+        // Add the app to the type's list of possible handlers.
+        let handlerInfo = this._handledTypes[this._list.selectedItem.type];
+        handlerInfo.addPossibleApplicationHandler(handlerApp);
+
+        chooseAppCallback(handlerApp);
+      }
+    }.bind(this);
 
     // 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() == Ci.nsIFilePicker.returnOK && fp.file &&
-        this._isValidHandlerExecutable(fp.file)) {
-      handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
-                   createInstance(Ci.nsILocalHandlerApp);
-      handlerApp.name = getFileDisplayName(fp.file);
-      handlerApp.executable = fp.file;
-
-      // Add the app to the type's list of possible handlers.
-      let handlerInfo = this._handledTypes[this._list.selectedItem.type];
-      handlerInfo.addPossibleApplicationHandler(handlerApp);
-    }
+    fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen);
+    fp.appendFilters(Ci.nsIFilePicker.filterApps);
+    fp.open(fpCallback);
 #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"));
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -253,49 +253,50 @@ var gMainPane = {
    * downloads are automatically saved, updating preferences and UI in
    * response to the choice, if one is made.
    */
   chooseFolder: function ()
   {
     const nsIFilePicker = Components.interfaces.nsIFilePicker;
     const nsILocalFile = Components.interfaces.nsILocalFile;
 
-    var fp = Components.classes["@mozilla.org/filepicker;1"]
-                       .createInstance(nsIFilePicker);
-    var bundlePreferences = document.getElementById("bundlePreferences");
-    var title = bundlePreferences.getString("chooseDownloadFolderTitle");
+    let bundlePreferences = document.getElementById("bundlePreferences");
+    let title = bundlePreferences.getString("chooseDownloadFolderTitle");
+    let folderListPref = document.getElementById("browser.download.folderList");
+    let currentDirPref = this._indexToFolder(folderListPref.value); // file
+    let defDownloads = this._indexToFolder(1); // file
+    let fp = Components.classes["@mozilla.org/filepicker;1"].
+             createInstance(nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == nsIFilePicker.returnOK) {
+        let file = fp.file.QueryInterface(nsILocalFile);
+        let downloadDirPref = document.getElementById("browser.download.dir");
+
+        downloadDirPref.value = file;
+        folderListPref.value = this._folderToIndex(file);
+        // Note, the real prefs will not be updated yet, so dnld manager's
+        // userDownloadsDirectory may not return the right folder after
+        // this code executes. displayDownloadDirPref will be called on
+        // the assignment above to update the UI.
+      }
+    }.bind(this);
+
     fp.init(window, title, nsIFilePicker.modeGetFolder);
     fp.appendFilters(nsIFilePicker.filterAll);
-
-    var folderListPref = document.getElementById("browser.download.folderList");
-    var currentDirPref = this._indexToFolder(folderListPref.value); // file
-    var defDownloads = this._indexToFolder(1); // file
-
     // First try to open what's currently configured
     if (currentDirPref && currentDirPref.exists()) {
       fp.displayDirectory = currentDirPref;
     } // Try the system's download dir
     else if (defDownloads && defDownloads.exists()) {
       fp.displayDirectory = defDownloads;
     } // Fall back to Desktop
     else {
       fp.displayDirectory = this._indexToFolder(0);
     }
-
-    if (fp.show() == nsIFilePicker.returnOK) {
-      var file = fp.file.QueryInterface(nsILocalFile);
-      var currentDirPref = document.getElementById("browser.download.dir");
-      currentDirPref.value = file;
-      var folderListPref = document.getElementById("browser.download.folderList");
-      folderListPref.value = this._folderToIndex(file);
-      // Note, the real prefs will not be updated yet, so dnld manager's
-      // userDownloadsDirectory may not return the right folder after
-      // this code executes. displayDownloadDirPref will be called on
-      // the assignment above to update the UI.
-    }
+    fp.open(fpCallback);
   },
 
   /**
    * Initializes the download folder display settings based on the user's
    * preferences.
    */
   displayDownloadDirPref: function ()
   {
--- a/browser/components/preferences/main.js
+++ b/browser/components/preferences/main.js
@@ -250,49 +250,50 @@ var gMainPane = {
    * downloads are automatically saved, updating preferences and UI in
    * response to the choice, if one is made.
    */
   chooseFolder: function ()
   {
     const nsIFilePicker = Components.interfaces.nsIFilePicker;
     const nsILocalFile = Components.interfaces.nsILocalFile;
 
-    var fp = Components.classes["@mozilla.org/filepicker;1"]
-                       .createInstance(nsIFilePicker);
-    var bundlePreferences = document.getElementById("bundlePreferences");
-    var title = bundlePreferences.getString("chooseDownloadFolderTitle");
+    let bundlePreferences = document.getElementById("bundlePreferences");
+    let title = bundlePreferences.getString("chooseDownloadFolderTitle");
+    let folderListPref = document.getElementById("browser.download.folderList");
+    let currentDirPref = this._indexToFolder(folderListPref.value); // file
+    let defDownloads = this._indexToFolder(1); // file
+    let fp = Components.classes["@mozilla.org/filepicker;1"].
+             createInstance(nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == nsIFilePicker.returnOK) {
+        let file = fp.file.QueryInterface(nsILocalFile);
+        let downloadDirPref = document.getElementById("browser.download.dir");
+
+        downloadDirPref.value = file;
+        folderListPref.value = this._folderToIndex(file);
+        // Note, the real prefs will not be updated yet, so dnld manager's
+        // userDownloadsDirectory may not return the right folder after
+        // this code executes. displayDownloadDirPref will be called on
+        // the assignment above to update the UI.
+      }
+    }.bind(this);
+
     fp.init(window, title, nsIFilePicker.modeGetFolder);
     fp.appendFilters(nsIFilePicker.filterAll);
-
-    var folderListPref = document.getElementById("browser.download.folderList");
-    var currentDirPref = this._indexToFolder(folderListPref.value); // file
-    var defDownloads = this._indexToFolder(1); // file
-
     // First try to open what's currently configured
     if (currentDirPref && currentDirPref.exists()) {
       fp.displayDirectory = currentDirPref;
     } // Try the system's download dir
     else if (defDownloads && defDownloads.exists()) {
       fp.displayDirectory = defDownloads;
     } // Fall back to Desktop
     else {
       fp.displayDirectory = this._indexToFolder(0);
     }
-
-    if (fp.show() == nsIFilePicker.returnOK) {
-      var file = fp.file.QueryInterface(nsILocalFile);
-      var currentDirPref = document.getElementById("browser.download.dir");
-      currentDirPref.value = file;
-      var folderListPref = document.getElementById("browser.download.folderList");
-      folderListPref.value = this._folderToIndex(file);
-      // Note, the real prefs will not be updated yet, so dnld manager's
-      // userDownloadsDirectory may not return the right folder after
-      // this code executes. displayDownloadDirPref will be called on
-      // the assignment above to update the UI.
-    }
+    fp.open(fpCallback);
   },
 
   /**
    * Initializes the download folder display settings based on the user's 
    * preferences.
    */
   displayDownloadDirPref: function ()
   {
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -663,49 +663,57 @@ var Scratchpad = {
   /**
    * Open a file to edit in the Scratchpad.
    *
    * @param integer aIndex
    *        Optional integer: clicked menuitem in the 'Open Recent'-menu.
    */
   openFile: function SP_openFile(aIndex)
   {
-    let fp;
-    if (!aIndex && aIndex !== 0) {
-      fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-      fp.init(window, this.strings.GetStringFromName("openFile.title"),
-              Ci.nsIFilePicker.modeOpen);
-      fp.defaultString = "";
-    }
-
-    if (aIndex > -1 || fp.show() != Ci.nsIFilePicker.returnCancel) {
+    let promptCallback = function(aFile) {
       this.promptSave(function(aCloseFile, aSaved, aStatus) {
         let shouldOpen = aCloseFile;
         if (aSaved && !Components.isSuccessCode(aStatus)) {
           shouldOpen = false;
         }
 
         if (shouldOpen) {
           this._skipClosePrompt = true;
 
           let file;
-          if (fp) {
-            file = fp.file;
+          if (aFile) {
+            file = aFile;
           } else {
             file = Components.classes["@mozilla.org/file/local;1"].
                    createInstance(Components.interfaces.nsILocalFile);
             let filePath = this.getRecentFiles()[aIndex];
             file.initWithPath(filePath);
           }
 
           this.setFilename(file.path);
           this.importFromFile(file, false);
           this.setRecentFile(file);
         }
       }.bind(this));
+    }.bind(this);
+
+    if (aIndex > -1) {
+      promptCallback();
+    } else {
+      let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+      let fpCallback = function fpCallback_done(aResult) {
+        if (aResult != Ci.nsIFilePicker.returnCancel) {
+          promptCallback(fp.file);
+        }
+      };
+
+      fp.init(window, this.strings.GetStringFromName("openFile.title"),
+              Ci.nsIFilePicker.modeOpen);
+      fp.defaultString = "";
+      fp.open(fpCallback);
     }
   },
 
   /**
    * Get recent files.
    *
    * @return Array
    *         File paths.
@@ -889,32 +897,35 @@ var Scratchpad = {
    * Save the textbox content to a new file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
    */
   saveFileAs: function SP_saveFileAs(aCallback)
   {
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult != Ci.nsIFilePicker.returnCancel) {
+        this.setFilename(fp.file.path);
+        this.exportToFile(fp.file, true, false, function(aStatus) {
+          if (Components.isSuccessCode(aStatus)) {
+            this.editor.dirty = false;
+            this.setRecentFile(fp.file);
+          }
+          if (aCallback) {
+            aCallback(aStatus);
+          }
+        });
+      }
+    }.bind(this);
+
     fp.init(window, this.strings.GetStringFromName("saveFileAs"),
             Ci.nsIFilePicker.modeSave);
     fp.defaultString = "scratchpad.js";
-    if (fp.show() != Ci.nsIFilePicker.returnCancel) {
-      this.setFilename(fp.file.path);
-
-      this.exportToFile(fp.file, true, false, function(aStatus) {
-        if (Components.isSuccessCode(aStatus)) {
-          this.editor.dirty = false;
-          this.setRecentFile(fp.file);
-        }
-        if (aCallback) {
-          aCallback(aStatus);
-        }
-      });
-    }
+    fp.open(fpCallback);
   },
 
   /**
    * Restore content from saved version of current file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
    */
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -283,32 +283,34 @@ StyleEditor.prototype = {
    * @param mixed aFile
    *        Optional nsIFile or filename string.
    *        If not set a file picker will be shown.
    * @param nsIWindow aParentWindow
    *        Optional parent window for the file picker.
    */
   importFromFile: function SE_importFromFile(aFile, aParentWindow)
   {
-    aFile = this._showFilePicker(aFile, false, aParentWindow);
-    if (!aFile) {
-      return;
-    }
-    this._savedFile = aFile; // remember filename for next save if any
+    let callback = function(aFile) {
+      if (aFile) {
+        this._savedFile = aFile; // remember filename for next save if any
 
-    NetUtil.asyncFetch(aFile, function onAsyncFetch(aStream, aStatus) {
-      if (!Components.isSuccessCode(aStatus)) {
-        return this._signalError(LOAD_ERROR);
+        NetUtil.asyncFetch(aFile, function onAsyncFetch(aStream, aStatus) {
+          if (!Components.isSuccessCode(aStatus)) {
+            return this._signalError(LOAD_ERROR);
+          }
+          let source = NetUtil.readInputStreamToString(aStream, aStream.available());
+          aStream.close();
+    
+          this._appendNewStyleSheet(source);
+          this.clearFlag(StyleEditorFlags.ERROR);
+        }.bind(this));
       }
-      let source = NetUtil.readInputStreamToString(aStream, aStream.available());
-      aStream.close();
+    }.bind(this);
 
-      this._appendNewStyleSheet(source);
-      this.clearFlag(StyleEditorFlags.ERROR);
-    }.bind(this));
+    this._showFilePicker(aFile, false, aParentWindow, callback);
   },
 
   /**
     * Retrieve localized error message of last error condition, or null if none.
     * This is set when the editor has flag StyleEditorFlags.ERROR.
     *
     * @see addActionListener
     */
@@ -548,56 +550,58 @@ StyleEditor.prototype = {
    * @param function(nsIFile aFile) aCallback
    *        Optional callback called when the operation has finished.
    *        aFile has the nsIFile object for saved file or null if the operation
    *        has failed or has been canceled by the user.
    * @see savedFile
    */
   saveToFile: function SE_saveToFile(aFile, aCallback)
   {
-    aFile = this._showFilePicker(aFile || this._styleSheetFilePath, true);
-
-    if (!aFile) {
-      if (aCallback) {
-        aCallback(null);
-      }
-      return;
-    }
-
-    if (this._sourceEditor) {
-      this._state.text = this._sourceEditor.getText();
-    }
-
-    let ostream = FileUtils.openSafeFileOutputStream(aFile);
-    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
-                      .createInstance(Ci.nsIScriptableUnicodeConverter);
-    converter.charset = "UTF-8";
-    let istream = converter.convertToInputStream(this._state.text);
-
-    NetUtil.asyncCopy(istream, ostream, function SE_onStreamCopied(status) {
-      if (!Components.isSuccessCode(status)) {
+    let callback = function(aReturnFile) {
+      if (!aReturnFile) {
         if (aCallback) {
           aCallback(null);
         }
-        this._signalError(SAVE_ERROR);
         return;
       }
-      FileUtils.closeSafeFileOutputStream(ostream);
+
+      if (this._sourceEditor) {
+        this._state.text = this._sourceEditor.getText();
+      }
 
-      // remember filename for next save if any
-      this._friendlyName = null;
-      this._savedFile = aFile;
-      this._persistExpando();
+      let ostream = FileUtils.openSafeFileOutputStream(aReturnFile);
+      let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+                        .createInstance(Ci.nsIScriptableUnicodeConverter);
+      converter.charset = "UTF-8";
+      let istream = converter.convertToInputStream(this._state.text);
 
-      if (aCallback) {
-        aCallback(aFile);
-      }
-      this.clearFlag(StyleEditorFlags.UNSAVED);
-      this.clearFlag(StyleEditorFlags.ERROR);
-    }.bind(this));
+      NetUtil.asyncCopy(istream, ostream, function SE_onStreamCopied(status) {
+        if (!Components.isSuccessCode(status)) {
+          if (aCallback) {
+            aCallback(null);
+          }
+          this._signalError(SAVE_ERROR);
+          return;
+        }
+        FileUtils.closeSafeFileOutputStream(ostream);
+
+        // remember filename for next save if any
+        this._friendlyName = null;
+        this._savedFile = aReturnFile;
+        this._persistExpando();
+
+        if (aCallback) {
+          aCallback(aReturnFile);
+        }
+        this.clearFlag(StyleEditorFlags.UNSAVED);
+        this.clearFlag(StyleEditorFlags.ERROR);
+      }.bind(this));
+    }.bind(this);
+
+    this._showFilePicker(aFile || this._styleSheetFilePath, true, null, callback);
   },
 
   /**
    * Queue a throttled task to update the live style sheet.
    *
    * @param boolean aImmediate
    *        Optional. If true the update is performed immediately.
    */
@@ -685,56 +689,67 @@ StyleEditor.prototype = {
    *
    * @param mixed aFile
    *        Optional nsIFile or string representing the filename to auto-select.
    * @param boolean aSave
    *        If true, the user is selecting a filename to save.
    * @param nsIWindow aParentWindow
    *        Optional parent window. If null the parent window of the file picker
    *        will be the window of the attached input element.
-   * @return nsIFile
-   *         The selected file or null if the user did not pick one.
+   * @param aCallback
+   *        The callback method, which will be called passing in the selected
+   *        file or null if the user did not pick one.
    */
-  _showFilePicker: function SE__showFilePicker(aFile, aSave, aParentWindow)
+  _showFilePicker: function SE__showFilePicker(aFile, aSave, aParentWindow, aCallback)
   {
     if (typeof(aFile) == "string") {
       try {
         if (Services.io.extractScheme(aFile) == "file") {
           let uri = Services.io.newURI(aFile, null, null);
           let file = uri.QueryInterface(Ci.nsIFileURL).file;
-          return file;
+          aCallback(file);
+          return;
         }
       } catch (ex) {
       }
       try {
         let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
         file.initWithPath(aFile);
-        return file;
+        aCallback(file);
+        return;
       } catch (ex) {
         this._signalError(aSave ? SAVE_ERROR : LOAD_ERROR);
-        return null;
+        aCallback(null);
+        return;
       }
     }
     if (aFile) {
-      return aFile;
+      aCallback(aFile);
+      return;
     }
 
     let window = aParentWindow
                  ? aParentWindow
                  : this.inputElement.ownerDocument.defaultView;
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     let mode = aSave ? fp.modeSave : fp.modeOpen;
     let key = aSave ? "saveStyleSheet" : "importStyleSheet";
+    let fpCallback = function fpCallback_done(aResult) {
+      if (aResult == Ci.nsIFilePicker.returnCancel) {
+        aCallback(null);
+      } else {
+        aCallback(fp.file);
+      }
+    };
 
     fp.init(window, _(key + ".title"), mode);
     fp.appendFilters(_(key + ".filter"), "*.css");
     fp.appendFilters(fp.filterAll);
-
-    let rv = fp.show();
-    return (rv == fp.returnCancel) ? null : fp.file;
+    fp.open(fpCallback);
+    return;
   },
 
   /**
    * Retrieve the style sheet source from the cache or from a local file.
    */
   _loadSource: function SE__loadSource()
   {
     if (!this.styleSheet.href) {
--- a/widget/nsIFilePicker.idl
+++ b/widget/nsIFilePicker.idl
@@ -6,17 +6,17 @@
 
 #include "nsISupports.idl"
 
 interface nsIFile;
 interface nsIURI;
 interface nsIDOMWindow;
 interface nsISimpleEnumerator;
 
-[scriptable, uuid(0d79adad-b244-49A5-9997-2a8cad93fc44)]
+[scriptable, function, uuid(0d79adad-b244-49A5-9997-2a8cad93fc44)]
 interface nsIFilePickerShownCallback : nsISupports
 {
  /**
   * Callback which is called when a filepicker is shown and a result
   * is returned.
   *
   * @param aResult One of returnOK, returnCancel, or returnReplace
   */