Bug 308073 - Change default downloading folder in Windows Vista from Desktop to Downloads. Patch by Jim Mathies <jmathies@mozilla.com>. r=robarnold, r=robert.bugzilla, sr=dougt, a=mconnor
authorsdwilsh@shawnwilsher.com
Tue, 21 Aug 2007 10:22:02 -0700
changeset 4867 64c6b0dad41af255d92ccffeabf4e5a17e6273c0
parent 4866 1f13e952df48a94d2365cea99df23a5dd2998dca
child 4868 87368d468d630173e933e9f42f88c7429a590148
push idunknown
push userunknown
push dateunknown
reviewersrobarnold, robert.bugzilla, dougt, mconnor
bugs308073
milestone1.9a8pre
Bug 308073 - Change default downloading folder in Windows Vista from Desktop to Downloads. Patch by Jim Mathies <jmathies@mozilla.com>. r=robarnold, r=robert.bugzilla, sr=dougt, a=mconnor
browser/base/content/browser.js
browser/components/migration/src/nsOperaProfileMigrator.cpp
browser/components/migration/src/nsSafariProfileMigrator.cpp
browser/components/preferences/main.js
browser/components/preferences/main.xul
browser/locales/en-US/chrome/browser/preferences/preferences.properties
toolkit/components/downloads/public/nsIDownloadManager.idl
toolkit/components/downloads/src/nsDownloadManager.cpp
toolkit/content/contentAreaUtils.js
toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties
toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties
toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
xpcom/io/SpecialSystemDirectory.cpp
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1109,16 +1109,35 @@ function delayedStartup()
   try {
     ContentPrefSink.init();
     TextZoom.init();
   }
   catch(ex) {
     Components.utils.reportError("Failed to init content pref service:\n" + ex);
   }
 
+#ifdef XP_WIN
+  // For Vista, flip the default download folder pref once from Desktop to Downloads
+  // on new profiles.
+  try {
+    var sysInfo = Cc["@mozilla.org/system-info;1"].
+                  getService(Ci.nsIPropertyBag2);
+    if (parseFloat(sysInfo.getProperty("version")) >= 6 &&
+        !gPrefService.getPrefType("browser.download.dir") &&
+        gPrefService.getIntPref("browser.download.folderList") == 0) {
+      var dnldMgr = Cc["@mozilla.org/download-manager;1"]
+                              .getService(Ci.nsIDownloadManager);
+      gPrefService.setCharPref("browser.download.dir", 
+        dnldMgr.defaultDownloadsDirectory.path);
+      gPrefService.setIntPref("browser.download.folderList", 1);
+    }
+  } catch (ex) {
+  }
+#endif
+
   // initialize the session-restore service (in case it's not already running)
   if (document.documentElement.getAttribute("windowtype") == "navigator:browser") {
     try {
       var ss = Cc["@mozilla.org/browser/sessionstore;1"].
                getService(Ci.nsISessionStore);
       ss.init(window);
     } catch(ex) {
       dump("nsSessionStore could not be initialized: " + ex + "\n");
--- a/browser/components/migration/src/nsOperaProfileMigrator.cpp
+++ b/browser/components/migration/src/nsOperaProfileMigrator.cpp
@@ -309,17 +309,17 @@ nsOperaProfileMigrator::GetSourceHomePag
   return NS_OK;
 }
  
 
 #define _OPM(type) nsOperaProfileMigrator::type
 
 static
 nsOperaProfileMigrator::PrefTransform gTransforms[] = {
-  { "User Prefs", "Download Directory", _OPM(STRING), "browser.download.defaultFolder", _OPM(SetFile), PR_FALSE, -1 },
+  { "User Prefs", "Download Directory", _OPM(STRING), "browser.download.dir", _OPM(SetFile), PR_FALSE, -1 },
   { nsnull, "Enable Cookies", _OPM(INT), "network.cookie.cookieBehavior", _OPM(SetCookieBehavior), PR_FALSE, -1 },
   { nsnull, "Accept Cookies Session Only", _OPM(BOOL), "network.cookie.enableForCurrentSessionOnly", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Allow script to resize window", _OPM(BOOL), "dom.disable_window_move_resize", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Allow script to move window", _OPM(BOOL), "dom.disable_window_move_resize", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Allow script to raise window", _OPM(BOOL), "dom.disable_window_flip", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Allow script to change status", _OPM(BOOL), "dom.disable_window_status_change", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Ignore Unrequested Popups", _OPM(BOOL), "dom.disable_open_during_load", _OPM(SetBool), PR_FALSE, -1 },
   { nsnull, "Load Figures", _OPM(BOOL), "permissions.default.image", _OPM(SetImageBehavior), PR_FALSE, -1 },
--- a/browser/components/migration/src/nsSafariProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSafariProfileMigrator.cpp
@@ -511,17 +511,17 @@ nsSafariProfileMigrator::SetDownloadFold
   nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
   nsCOMPtr<nsILocalFile> desktopFolder;
   fileLocator->Get(NS_OSX_USER_DESKTOP_DIR, NS_GET_IID(nsILocalFile),
                    getter_AddRefs(desktopFolder));
 
   PRBool equals;
   downloadFolder->Equals(desktopFolder, &equals);
   aBranch->SetIntPref("browser.download.folderList", equals ? 0 : 2);
-  aBranch->SetComplexValue("browser.download.defaultFolder",
+  aBranch->SetComplexValue("browser.download.dir",
                            NS_GET_IID(nsILocalFile), downloadFolder);
 
   return NS_OK;
 }
 
 nsresult
 nsSafariProfileMigrator::SetDownloadHandlers(void* aTransform, nsIPrefBranch* aBranch)
 {
--- a/browser/components/preferences/main.js
+++ b/browser/components/preferences/main.js
@@ -166,36 +166,45 @@ var gMainPane = {
     homePage.value = homePage.defaultValue;
   },
 
   // DOWNLOADS
 
   /*
    * Preferences:
    * 
-   * browser.download.showWhenStarting
-   *   true if the Download Manager should be opened when a download is started,
-   *   false if it shouldn't be opened
-   * browser.download.closeWhenDone
-   *   true if the Download Manager should be closed when all downloads
-   *   complete, false if it shouldn't be closed
-   * browser.download.useDownloadDir
-   *   true if downloads are saved to a default location with no UI shown, false
-   *   if the user should always be asked where to save files
-   * browser.download.dir
-   *   the last directory to which a download was saved
+   * browser.download.showWhenStarting - bool
+   *   True if the Download Manager should be opened when a download is
+   *   started, false if it shouldn't be opened.
+   * browser.download.closeWhenDone - bool
+   *   True if the Download Manager should be closed when all downloads
+   *   complete, false if it should be left open.
+   * browser.download.useDownloadDir - bool
+   *   True if downloads are saved with no save-as UI shown, false if
+   *   the user should always be asked where to save a file.
+   * browser.download.dir - str path
+   *   A local path the user may have selected for downloaded files to be
+   *   saved. Migration of other browser settings may also set this path.
+   *   This path is enabled when folderList is equals 2.
+   * browser.download.lastDir - str path
+   *   May contain the last folder path accessed when the user browsed
+   *   via the file save-as dialog. (see contentAreaUtils.js)
+   * browser.download.folderList - int
+   *   Indicates the location users wish to save downloaded files too.
+   *   It is also used to display special file labels when the default
+   *   download location is either the Desktop or the Downloads folder.
+   *   Values:
+   *     0 - The desktop is the default download location.
+   *     1 - The system's downloads folder is the default download location.
+   *     2 - The default download location is elsewhere as specified in
+   *         browser.download.dir.
    * browser.download.downloadDir
-   *   the current default download location
-   * browser.download.folderList
-   *   0 if the desktop is the default download location,
-   *   1 if the downloads folder is the default download location,
-   *   2 if the default download location is elsewhere;
-   *   used to display special UI when the default location is the Desktop or
-   *   the Downloads folder in Download Manager UI and in the file field in
-   *   preferences
+   *   depreciated.
+   * browser.download.defaultFolder
+   *   depreciated.
    */
 
   /**
    * Updates preferences which depend upon the value of the preference which
    * determines whether the Downloads manager is opened at the start of a
    * download.
    */
   readShowDownloadsWhenStarting: function ()
@@ -227,78 +236,159 @@ var gMainPane = {
     var chooseFolder = document.getElementById("chooseFolder");
     var preference = document.getElementById("browser.download.useDownloadDir");
     downloadFolder.disabled = !preference.value;
     chooseFolder.disabled = !preference.value;
 
     // don't override the preference's value in UI
     return undefined;
   },
-
+  
   /**
    * Displays a file picker in which the user can choose the location where
    * downloads are automatically saved, updating preferences and UI in
    * response to the choice, if one is made.
    */
   chooseFolder: 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");
     fp.init(window, title, nsIFilePicker.modeGetFolder);
+    fp.appendFilters(nsIFilePicker.filterAll);
 
-    const nsILocalFile = Components.interfaces.nsILocalFile;
-    var customDirPref = document.getElementById("browser.download.dir");
-    if (customDirPref.value)
-      fp.displayDirectory = customDirPref.value;
-    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.downloadDir");
-      customDirPref.value = currentDirPref.value = file;
+      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.
     }
   },
 
   /**
-   * Initializes the download folder widget based on the folder as stored in
+   * Initializes the download folder display settings based on the user's 
    * preferences.
    */
-  readDownloadDirPref: function ()
+  displayDownloadDirPref: function ()
   {
     var folderListPref = document.getElementById("browser.download.folderList");
     var bundlePreferences = document.getElementById("bundlePreferences");
     var downloadFolder = document.getElementById("downloadFolder");
+    var currentDirPref = document.getElementById("browser.download.dir");
 
-    var customDirPref = document.getElementById("browser.download.dir");
-    var customIndex = customDirPref.value ? this._folderToIndex(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);
+    // The user's download folder is based on the preferences listed above.
+    // However, if the system does not support a download folder, the
+    // actual path returned will be the system's desktop or home folder.
+    // If this is the case, skip off displaying the Download label and
+    // display Desktop, even though folderList might be 1.
+    var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
+                                .getService(Components.interfaces.nsIProperties);
+    var desk = fileLocator.get("Desk", Components.interfaces.nsILocalFile);
+    var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
+                            .getService(Components.interfaces.nsIDownloadManager);
+    var supportDownloadLabel = !dnldMgr.defaultDownloadsDirectory.equals(desk);
 
+    // Used in defining the correct path to the folder icon.
     var ios = Components.classes["@mozilla.org/network/io-service;1"]
                         .getService(Components.interfaces.nsIIOService);
     var fph = ios.getProtocolHandler("file")
                  .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
-    var currentDirPref = document.getElementById("browser.download.downloadDir");
-    var downloadDir = currentDirPref.value || this._indexToFolder(folderListPref.value);
-    var urlspec = fph.getURLSpecFromFile(downloadDir);
-    downloadFolder.image = "moz-icon://" + urlspec + "?size=16";
-
+    var iconUrlSpec;
+      
+    // Display a 'pretty' label or the path in the UI.
+    if (folderListPref.value == 2) {
+      // Custom path selected and is configured
+      downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value);
+      iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
+    } else if (folderListPref.value == 1 && supportDownloadLabel) {
+      // 'Downloads'
+      // In 1.5, this pointed to a folder we created called 'My Downloads'
+      // and was available as an option in the 1.5 drop down. On XP this
+      // was in My Documents, on OSX it was in User Docs. In 2.0, we did
+      // away with the drop down option, although the special label was
+      // still supported for the folder if it existed. Because it was
+      // not exposed it was rarely used.
+      // With 3.0, a new desktop folder - 'Downloads' was introduced for
+      // platforms and versions that don't support a default system downloads
+      // folder. See nsDownloadManager for details. 
+      downloadFolder.label = bundlePreferences.getString("downloadsFolderName");
+      iconUrlSpec = fph.getURLSpecFromFile(this._indexToFolder(1));
+    } else {
+      // 'Desktop'
+      downloadFolder.label = bundlePreferences.getString("desktopFolderName");
+      iconUrlSpec = fph.getURLSpecFromFile(desk);
+    }
+    downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16";
+    
     // don't override the preference's value in UI
     return undefined;
   },
 
   /**
+   * Returns the textual path of a folder in readable form.
+   */
+  _getDisplayNameOfFile: function (aFolder)
+  {
+    // TODO: would like to add support for 'Downloads on Macintosh HD'
+    //       for OS X users.
+    return aFolder ? aFolder.path : "";
+  },
+
+  /**
+   * Returns the Downloads folder.  If aFolder is "Desktop", then the Downloads
+   * folder returned is the desktop folder; otherwise, it is a folder whose name
+   * indicates that it is a download folder and whose path is as determined by
+   * the XPCOM directory service via the download manager's attribute 
+   * defaultDownloadsDirectory.
+   *
+   * @throws if aFolder is not "Desktop" or "Downloads"
+   */
+  _getDownloadsFolder: function (aFolder)
+  {
+    switch(aFolder)
+    {
+      case "Desktop":
+        var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"]
+                                    .getService(Components.interfaces.nsIProperties);
+        return fileLoc.get("Desk", Components.interfaces.nsILocalFile);
+      break;
+      case "Downloads":
+        var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
+                                .getService(Components.interfaces.nsIDownloadManager);
+        return dnldMgr.defaultDownloadsDirectory;
+      break;
+    }
+    throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
+  },
+
+  /**
    * Determines the type of the given folder.
    *
    * @param   aFolder
    *          the folder whose type is to be determined
    * @returns integer
    *          0 if aFolder is the Desktop or is unspecified,
    *          1 if aFolder is the Downloads folder,
    *          2 otherwise
@@ -308,103 +398,57 @@ var gMainPane = {
     if (!aFolder || aFolder.equals(this._getDownloadsFolder("Desktop")))
       return 0;
     else if (aFolder.equals(this._getDownloadsFolder("Downloads")))
       return 1;
     return 2;
   },
 
   /**
-   * Returns the Downloads folder.  If aFolder is "Desktop", then the Downloads
-   * folder returned is the desktop folder; otherwise, it is a folder whose name
-   * indicates that it is a download folder and whose path is as determined by
-   * the XPCOM directory service from aFolder.
-   *
-   * @throws if aFolder is not "Desktop" or "Downloads"
-   */
-  _getDownloadsFolder: function (aFolder)
-  {
-    var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
-                                .getService(Components.interfaces.nsIProperties);
-    var dir = fileLocator.get(this._getSpecialFolderKey(aFolder),
-                              Components.interfaces.nsILocalFile);
-    if (aFolder != "Desktop")
-      dir.append("My Downloads"); // XXX l12y!
-
-    return dir;
-  },
-
-  /**
-   * Gets the platform-specific key to be fed to the directory service for the
-   * given special folder.
-   *
-   * @param   aFolder
-   *          either of the strings "Desktop" or "Downloads"
-   * @returns the platform-specific key for the location, which may be used with
-   *          the XPCOM directory service
-   */
-  _getSpecialFolderKey: function (aFolderType)
-  {
-    if (aFolderType == "Desktop")
-      return "Desk";
-
-    if (aFolderType == "Downloads")
-#ifdef XP_WIN
-      return "Pers";
-#else
-#ifdef XP_MACOSX
-      return "UsrDocs";
-#else
-      return "Home";
-#endif
-#endif
-
-      throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-  },
-
-  /**
-   * Returns the textual path of a folder in readable form.
-   */
-  _getDisplayNameOfFile: function (aFolder)
-  {
-    // TODO: would like to add support for 'Downloads on Macintosh HD'
-    //       for OS X users.
-    return aFolder ? aFolder.path : "";
-  },
-
-  /**
    * Converts an integer into the corresponding folder.
    *
    * @param   aIndex
    *          an integer
    * @returns the Desktop folder if aIndex == 0,
    *          the Downloads folder if aIndex == 1,
-   *          the folder stored in browser.download.dir otherwise
+   *          the folder stored in browser.download.dir
    */
   _indexToFolder: 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;
+    var currentDirPref = document.getElementById("browser.download.dir");
+    return currentDirPref.value;
   },
 
   /**
-   * Returns the value for the browser.download.folderList preference determined
-   * from the current value of browser.download.downloadDir.
+   * Returns the value for the browser.download.folderList preference.
    */
-  writeFolderList: function ()
+  getFolderListPref: function ()
   {
-    var currentDirPref = document.getElementById("browser.download.downloadDir");
-    return this._folderToIndex(currentDirPref.value);
+    var folderListPref = document.getElementById("browser.download.folderList");
+    switch(folderListPref.value) {
+      case 0: // Desktop
+      case 1: // Downloads
+        return folderListPref.value;
+      break;
+      case 2: // Custom
+        var currentDirPref = document.getElementById("browser.download.dir");
+        if (currentDirPref.value) {
+          // Resolve to a known location if possible. We are writing out
+          // to prefs on this call, so now would be a good time to do it.
+          return this._folderToIndex(currentDirPref.value);
+        }
+        return 0;
+      break;
+    }
   }
 
 #ifdef HAVE_SHELL_SERVICE
   ,
 
   // SYSTEM DEFAULTS
 
   /*
--- a/browser/components/preferences/main.xul
+++ b/browser/components/preferences/main.xul
@@ -86,17 +86,16 @@
                   type="bool"/>
       <preference id="browser.download.useDownloadDir"
                   name="browser.download.useDownloadDir"
                   type="bool"/>
       <preference id="browser.download.dir"
                   name="browser.download.dir"
                   type="file"
                   onchange="gMainPane.readDownloadDirPref();"/>
-      <preference id="browser.download.downloadDir"       name="browser.download.downloadDir"       type="file"/>
       <preference id="browser.download.folderList"        name="browser.download.folderList"        type="int"/>
 
       <!-- SYSTEM DEFAULTS -->
       <preference id="browser.shell.checkDefaultBrowser"
                   name="browser.shell.checkDefaultBrowser"
                   type="bool"/>
 
       <preference id="pref.general.disable_button.default_browser"
@@ -172,28 +171,28 @@
           <radio id="saveTo" value="true"
                  label="&saveTo.label;"
                  accesskey="&saveTo.accesskey;"
                  xmlns:aaa="http://www.w3.org/2005/07/aaa"
                  aaa:labelledby="saveTo downloadFolder"/>
           <filefield id="downloadFolder" flex="1"
                      preference="browser.download.folderList"
                      preference-editable="true"
-                     onsyncfrompreference="return gMainPane.readDownloadDirPref();"
-                     onsynctopreference="return gMainPane.writeFolderList()"/>
+                     onsyncfrompreference="return gMainPane.displayDownloadDirPref();"
+                     onsynctopreference="return gMainPane.getFolderListPref()"/>
           <button id="chooseFolder" oncommand="gMainPane.chooseFolder();"
 #ifdef XP_MACOSX
                   accesskey="&chooseFolderMac.accesskey;"
                   label="&chooseFolderMac.label;"
 #else
                   accesskey="&chooseFolderWin.accesskey;"
                   label="&chooseFolderWin.label;"
 #endif
                   preference="browser.download.folderList"
-                  onsynctopreference="return gMainPane.writeFolderList();"/>
+                  onsynctopreference="return gMainPane.getFolderListPref();"/>
         </hbox>
         <radio id="alwaysAsk" value="false"
                label="&alwaysAsk.label;"
                accesskey="&alwaysAsk.accesskey;"/>
       </radiogroup>
     </groupbox>
 
 #ifdef HAVE_SHELL_SERVICE
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -35,17 +35,17 @@ pw_change_failed_title=Password Change F
 #   %1$S = language name, %2$S = region name, %3$S = language-region code
 languageRegionCodeFormat=%1$S/%2$S  [%3$S]
 #   %1$S = language name, %2$S = language-region code
 languageCodeFormat=%1$S  [%2$S]
 
 #### Downloads
 
 desktopFolderName=Desktop
-myDownloadsFolderName=My Downloads
+downloadsFolderName=Downloads
 chooseDownloadFolderTitle=Choose Download Folder:
 
 #### Download Actions
 
 extensionNone=(NONE)
 removeButtonSingle=Remove Action
 removeButtonMultiple=Remove Actions
 removeTitleSingle=Remove Action
--- a/toolkit/components/downloads/public/nsIDownloadManager.idl
+++ b/toolkit/components/downloads/public/nsIDownloadManager.idl
@@ -46,17 +46,17 @@ interface nsIURI;
 interface nsILocalFile;
 interface nsIDownload;
 interface nsICancelable;
 interface nsIMIMEInfo;
 interface nsIDownloadProgressListener;
 interface nsISimpleEnumerator;
 interface mozIStorageConnection;
 
-[scriptable, uuid(a44925cb-186a-4e57-846e-8f9504b9f675)]
+[scriptable, uuid(b23d291f-2893-48ea-abda-ba9c9fe69c95)]
 interface nsIDownloadManager : nsISupports {
   // Download States
   const short DOWNLOAD_NOTSTARTED       = -1;
   const short DOWNLOAD_QUEUED           = 5;
   const short DOWNLOAD_DOWNLOADING      = 0;
   const short DOWNLOAD_FINISHED         = 1;
   const short DOWNLOAD_FAILED           = 2;
   const short DOWNLOAD_CANCELED         = 3;
@@ -205,11 +205,38 @@ interface nsIDownloadManager : nsISuppor
    * Adds a listener from the download manager.
    */
   void addListener(in nsIDownloadProgressListener aListener);
 
   /**
    * Removes a listener from the download manager.
    */
   void removeListener(in nsIDownloadProgressListener aListener);
+
+  /**
+   * Returns the platform default downloads directory.
+   */
+  readonly attribute nsILocalFile defaultDownloadsDirectory;
+
+  /**
+   * Returns the user configured downloads directory. 
+   * The path is dependent on two user configurable prefs
+   * set in preferences:
+   *
+   * browser.download.folderList
+   *   Indicates the location users wish to save downloaded 
+   *   files too.  
+   *   Values: 
+   *     0 - The desktop is the default download location. 
+   *     1 - The system's downloads folder is the default download location. 
+   *     2 - The default download location is elsewhere as specified in  
+   *         browser.download.dir. If invalid, userDownloadsDirectory
+   *         will fallback on defaultDownloadsDirectory.
+   *
+   * browser.download.dir - 
+   *   A local path the user may have selected at some point 
+   *   where downloaded files are saved. The use of which is
+   *   enabled when folderList equals 2. 
+   */
+  readonly attribute nsILocalFile userDownloadsDirectory;
 };
 
 
--- a/toolkit/components/downloads/src/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
@@ -47,32 +47,33 @@
 #include "nsNetUtil.h"
 #include "nsIURL.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceDefs.h"
 #include "nsIWindowWatcher.h"
 #include "nsIWindowMediator.h"
 #include "nsIPromptService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsVoidArray.h"
 #include "nsEnumeratorUtils.h"
 #include "nsIFileURL.h"
 #include "nsEmbedCID.h"
 #include "mozStorageCID.h"
 #include "mozIStorageService.h"
 #include "mozStorageHelper.h"
 #include "nsIMutableArray.h"
 #include "nsIAlertsService.h"
+#include "nsIPropertyBag2.h"
 #include "nsIHttpChannel.h"
-#include "nsIPropertyBag2.h"
 
 #ifdef XP_WIN
 #include <shlobj.h>
 #endif
 
 static PRBool gStoppingDownloads = PR_FALSE;
 
 #define DOWNLOAD_MANAGER_FE_URL "chrome://mozapps/content/downloads/downloads.xul"
@@ -703,16 +704,190 @@ nsDownloadManager::GetActiveDownloadCoun
 
 NS_IMETHODIMP
 nsDownloadManager::GetActiveDownloads(nsISimpleEnumerator **aResult)
 {
   return NS_NewArrayEnumerator(aResult, mCurrentDownloads);
 }
 
 NS_IMETHODIMP
+nsDownloadManager::GetDefaultDownloadsDirectory(nsILocalFile **aResult)
+{
+  nsCOMPtr<nsILocalFile> downloadDir;
+
+  nsresult rv;
+  nsCOMPtr<nsIProperties> dirService =
+     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // OSX:
+  // Safari download folder or Desktop/Downloads
+  // Vista:
+  // Downloads
+  // XP/2K:
+  // Desktop/Downloads
+  // Linux:
+  // Home/Downloads
+
+  nsXPIDLString folderName;
+  mBundle->GetStringFromName(NS_LITERAL_STRING("downloadsFolder").get(),
+                             getter_Copies(folderName));
+
+#if defined (XP_MACOSX)
+  nsCOMPtr<nsILocalFile> desktopDir;
+  rv = dirService->Get(NS_OSX_DEFAULT_DOWNLOAD_DIR,
+                       NS_GET_IID(nsILocalFile),
+                       getter_AddRefs(downloadDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = dirService->Get(NS_OSX_USER_DESKTOP_DIR,
+                       NS_GET_IID(nsILocalFile),
+                       getter_AddRefs(desktopDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check to see if we have the desktop or the Safari downloads folder
+  PRBool equals;
+  rv = downloadDir->Equals(desktopDir, &equals);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (equals) {
+    rv = downloadDir->Append(folderName);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+#elif defined (XP_WIN)
+  rv = dirService->Get(NS_WIN_DEFAULT_DOWNLOAD_DIR,
+                       NS_GET_IID(nsILocalFile),
+                       getter_AddRefs(downloadDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check the os version
+  #define NS_SYSTEMINFO_CONTRACTID "@mozilla.org/system-info;1"
+  nsCOMPtr<nsIPropertyBag2> infoService =
+     do_GetService(NS_SYSTEMINFO_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 version;
+  NS_NAMED_LITERAL_STRING(osVersion, "version");
+  rv = infoService->GetPropertyAsInt32(osVersion, &version);
+  if (version < 6) { // XP/2K
+    rv = downloadDir->Append(folderName);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+#else
+  rv = dirService->Get(NS_OS_HOME_DIR,
+                       NS_GET_IID(nsILocalFile),
+                       getter_AddRefs(downloadDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = downloadDir->Append(folderName);
+  NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
+  NS_ADDREF(*aResult = downloadDir);
+
+  return NS_OK;
+}
+
+#define NS_BRANCH_DOWNLOAD     "browser.download."
+#define NS_PREF_FOLDERLIST     "folderList"
+#define NS_PREF_DIR            "dir"
+
+NS_IMETHODIMP
+nsDownloadManager::GetUserDownloadsDirectory(nsILocalFile **aResult)
+{
+  nsresult rv;
+  nsCOMPtr<nsIProperties> dirService =
+     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIPrefService> prefService =
+     do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIPrefBranch> prefBranch;
+  rv = prefService->GetBranch(NS_BRANCH_DOWNLOAD, 
+                              getter_AddRefs(prefBranch));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 val;
+  rv = prefBranch->GetIntPref(NS_PREF_FOLDERLIST,
+                              &val);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRBool bRes = PR_FALSE;
+
+  switch(val) {
+    case 0: // Desktop
+      {
+        nsCOMPtr<nsILocalFile> downloadDir;
+        nsCOMPtr<nsIProperties> dirService =
+           do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = dirService->Get(NS_OS_DESKTOP_DIR,
+                             NS_GET_IID(nsILocalFile),
+                             getter_AddRefs(downloadDir));
+        NS_ENSURE_SUCCESS(rv, rv);
+        NS_ADDREF(*aResult = downloadDir);
+        return NS_OK;
+      }
+      break;
+    case 1: // Downloads
+      {
+        rv = GetDefaultDownloadsDirectory(aResult); // refup
+        NS_ENSURE_SUCCESS(rv, rv);
+        (*aResult)->Exists(&bRes);
+        if (!bRes) {
+          rv = (*aResult)->Create(nsIFile::DIRECTORY_TYPE, 755);
+          NS_ENSURE_SUCCESS(rv, rv);
+        }
+        return NS_OK;
+      }
+      break;
+    case 2: // Custom
+      {
+        nsCOMPtr<nsISupportsString> customDirectory;
+        prefBranch->GetComplexValue(NS_PREF_DIR, 
+                                    NS_GET_IID(nsISupportsString),
+                                    getter_AddRefs(customDirectory));
+        if (customDirectory) {
+          nsCOMPtr<nsILocalFile> aFile = 
+            do_CreateInstance("@mozilla.org/file/local;1", &rv);
+          NS_ENSURE_SUCCESS(rv, rv);
+          nsAutoString dir;
+          customDirectory->GetData(dir);
+          rv = aFile->InitWithNativePath(NS_ConvertUTF16toUTF8(dir));
+          NS_ENSURE_SUCCESS(rv, rv);
+          aFile->Exists(&bRes);
+          if (bRes) {
+            NS_ADDREF(*aResult = aFile);
+            return NS_OK;
+          }
+          rv = aFile->Create(nsIFile::DIRECTORY_TYPE, 755);
+          NS_ENSURE_SUCCESS(rv, rv);
+          if (bRes) {
+            NS_ADDREF(*aResult = aFile);
+            return NS_OK;
+          }
+        }
+        rv = GetDefaultDownloadsDirectory(aResult); // refup
+        NS_ENSURE_SUCCESS(rv, rv);
+        (*aResult)->Exists(&bRes);
+        if (!bRes) {
+          rv = (*aResult)->Create(nsIFile::DIRECTORY_TYPE, 755);
+          NS_ENSURE_SUCCESS(rv, rv);
+          // Update dir pref
+          prefBranch->SetComplexValue(NS_PREF_DIR,
+                                      NS_GET_IID(nsILocalFile),
+                                      *aResult);
+        }
+        return NS_OK;
+      }
+      break;
+  }
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
 nsDownloadManager::AddDownload(DownloadType aDownloadType, 
                                nsIURI* aSource,
                                nsIURI* aTarget,
                                const nsAString& aDisplayName,
                                nsIMIMEInfo *aMIMEInfo,
                                PRTime aStartTime,
                                nsILocalFile* aTempFile,
                                nsICancelable* aCancelable,
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -446,89 +446,45 @@ function getTargetFile(aFpP, aSkipPrompt
 {
   const prefSvcContractID = "@mozilla.org/preferences-service;1";
   const prefSvcIID = Components.interfaces.nsIPrefService;                              
   var prefs = Components.classes[prefSvcContractID]
                         .getService(prefSvcIID).getBranch("browser.download.");
 
   const nsILocalFile = Components.interfaces.nsILocalFile;
 
-  // ben 07/31/2003:
-  // |browser.download.defaultFolder| holds the default download folder for 
-  // all files when the user has elected to have all files automatically
-  // download to a folder. The values of |defaultFolder| can be either their
-  // desktop, their downloads folder (My Documents\My Downloads) or some other
-  // location of their choosing (which is mapped to |browser.download.dir|
-  // This pref is _unset_ when the user has elected to be asked about where
-  // to place every download - this will force the prompt to ask the user
-  // where to put saved files. 
-  var dir = null;
-  var useDownloadDir = prefs.getBoolPref("useDownloadDir");
-  
-  function getSpecialFolderKey(aFolderType) 
-  {
-    if (aFolderType == "Desktop")
-      return "Desk";
-    
-    if (aFolderType != "Downloads")
-      throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-    
-#ifdef XP_WIN
-    return "Pers";
-#else
-#ifdef XP_MACOSX
-    return "UsrDocs";
-#else
-    return "Home";
-#endif
-#endif
-  }
+  // For information on download folder preferences, see
+  // mozilla/browser/components/preferences/main.js
   
-  function getDownloadsFolder(aFolder)
-  {
-    var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
-                                .getService(Components.interfaces.nsIProperties);
-    
-    var dir = fileLocator.get(getSpecialFolderKey(aFolder), Components.interfaces.nsILocalFile);
-    
-    var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
-                           .getService(Components.interfaces.nsIStringBundleService);
-    bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
-    
-    var description = bundle.GetStringFromName("myDownloads");
-    if (aFolder != "Desktop")
-      dir.append(description);
-    
-    return dir;
+  var useDownloadDir = prefs.getBoolPref("useDownloadDir");
+  var dir = null;
+  
+  try {
+    // On prompt operations, default to lastDir, on direct to folder
+    // downloads, default to the user's configured download folder.
+    // (right-click save image vs. drag-and-drop into download manager)
+    var lastDir = prefs.getComplexValue("lastDir", nsILocalFile);
+    var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
+                            .getService(Components.interfaces.nsIDownloadManager);
+    if (!aSkipPrompt) {
+      dir = lastDir;
+    } else {
+      dir = dnldMgr.userDownloadsDirectory;
+    }
+  } catch (ex) {
   }
-  
-  switch (prefs.getIntPref("folderList")) {
-  case 0:
-    dir = getDownloadsFolder("Desktop")
-    break;
-  case 1:
-    dir = getDownloadsFolder("Downloads");
-    break;
-  case 2:
-    dir = prefs.getComplexValue("dir", nsILocalFile);
-    break;
-  }
-  
-  if (!aSkipPrompt || !useDownloadDir || !dir) {
+
+  if (!aSkipPrompt || !useDownloadDir || !dir || (dir && !dir.exists())) {
     // If we're asking the user where to save the file, root the Save As...
-    // dialog on they place they last picked. 
-    try {
-      dir = prefs.getComplexValue("lastDir", nsILocalFile);
-    }
-    catch (e) {
-      // No default download location. Default to desktop. 
+    // dialog on the place they last picked.
+    if (!dir || (dir && !dir.exists())) {
+      // Default to desktop.
       var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
                                   .getService(Components.interfaces.nsIProperties);
-      
-      dir = fileLocator.get(getSpecialFolderKey("Desktop"), nsILocalFile);
+      dir = fileLocator.get("Desk", nsILocalFile);
     }
 
     var fp = makeFilePicker();
     var titleKey = aFpP.fpTitleKey || "SaveLinkTitle";
     var bundle = getStringBundle();
     fp.init(window, bundle.GetStringFromName(titleKey), 
             Components.interfaces.nsIFilePicker.modeSave);
     
@@ -543,17 +499,17 @@ function getTargetFile(aFpP, aSkipPrompt
     
     if (aFpP.isDocument) {
       try {
         fp.filterIndex = prefs.getIntPref("save_converter_index");
       }
       catch (e) {
       }
     }
-  
+
     if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file)
       return false;
     
     var directory = fp.file.parent.QueryInterface(nsILocalFile);
     prefs.setComplexValue("lastDir", nsILocalFile, directory);
 
     fp.file.leafName = validateFileName(fp.file.leafName);
     aFpP.saveAsType = fp.filterIndex;
--- a/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/downloads/downloads.properties
@@ -55,8 +55,11 @@ chooseAppFilePickerTitle=Open With...
 downloadsTitle=%S%% of 1 file - Downloads
 downloadsTitleMultiple=%S%% of %S files - Downloads
 
 fileExecutableSecurityWarning="%S" is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch "%S"?
 fileExecutableSecurityWarningTitle=Open Executable File?
 fileExecutableSecurityWarningDontAsk=Don't ask me this again
 
 displayNameDesktop=Desktop
+
+# Desktop folder name for downloaded files
+downloadsFolder=Downloads
--- a/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/downloads/unknownContentType.properties
@@ -38,12 +38,11 @@
 
 title=Opening %S
 saveDialogTitle=Enter name of file to save to...
 defaultApp=%S (default)
 chooseAppFilePickerTitle=Choose Helper Application
 badApp=The application you chose ("%S") could not be found.  Check the file name or choose another application.
 badApp.title=Application not found
 selectDownloadDir=Select Download Folder
-myDownloads=My Downloads
 unknownAccept.label=Save File
 unknownCancel.label=Cancel
 fileType=%S file
--- a/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
+++ b/toolkit/mozapps/downloads/src/nsHelperAppDlg.js.in
@@ -116,144 +116,96 @@ nsUnknownContentTypeDialog.prototype = {
     //
     //                       Alternatively, if the user has selected to have all
     //                       files download to a specific location, return that
     //                       location and don't ask via the dialog. 
     //
     // Note - this function is called without a dialog, so it cannot access any part
     // of the dialog XUL as other functions on this object do. 
     promptForSaveToFile: function(aLauncher, aContext, aDefaultFile, aSuggestedFileExtension) {
-      var result = "";
+      var result = null;
       
       this.mLauncher = aLauncher;
 
-      // If the user is always downloading to the same location, the default download
-      // folder is stored in preferences. If a value is found stored, use that 
-      // automatically and don't ask via a dialog. 
+      // Check to see if the user wishes to auto save to the default download
+      // folder without prompting.
       var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
       var autodownload = prefs.getBoolPref("browser.download.useDownloadDir");
+      
       if (autodownload) {
-        function getSpecialFolderKey(aFolderType) 
-        {
-          if (aFolderType == "Desktop")
-            return "Desk";
-        
-          if (aFolderType != "Downloads")
-            throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-        
-#ifdef XP_WIN
-          return "Pers";
-#else
-#ifdef XP_MACOSX
-          return "UsrDocs";
-#else
-          return "Home";
-#endif
-#endif
-        }
-        
-        function getDownloadsFolder(aFolder)
-        {
-          var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
-
-          var dir = fileLocator.get(getSpecialFolderKey(aFolder), Components.interfaces.nsILocalFile);
-          
-          var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
-          bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
-
-          var description = bundle.GetStringFromName("myDownloads");
-          if (aFolder != "Desktop")
-            dir.append(description);
-            
-          return dir;
-        }
-
-        var defaultFolder = null;
-        switch (prefs.getIntPref("browser.download.folderList")) {
-        case 0:
-          defaultFolder = getDownloadsFolder("Desktop");
-          break;
-        case 1:
-          defaultFolder = getDownloadsFolder("Downloads");
-          break;
-        case 2:
-          defaultFolder = prefs.getComplexValue("browser.download.dir", Components.interfaces.nsILocalFile);
-          break;
-        }
-        
+        // Retrieve the user's default download directory
+        var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
+                                .getService(Components.interfaces.nsIDownloadManager);
+        var defaultFolder = dnldMgr.userDownloadsDirectory;
         result = this.validateLeafName(defaultFolder, aDefaultFile, aSuggestedFileExtension);
       }
       
-      if (!result) {
-        // Use file picker to show dialog.
-        var nsIFilePicker = Components.interfaces.nsIFilePicker;
-        var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
+      // Check to make sure we have a valid directory, otherwise, prompt
+      if (result)
+        return result;
+      
+      // Use file picker to show dialog.
+      var nsIFilePicker = Components.interfaces.nsIFilePicker;
+      var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
 
-        var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
-        bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
-
-        var windowTitle = bundle.GetStringFromName("saveDialogTitle");
-        var parent = aContext.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal);
-        picker.init(parent, windowTitle, nsIFilePicker.modeSave);
-        picker.defaultString = aDefaultFile;
+      var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
+      bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
 
-        if (aSuggestedFileExtension) {
-          // aSuggestedFileExtension includes the period, so strip it
-          picker.defaultExtension = aSuggestedFileExtension.substring(1);
+      var windowTitle = bundle.GetStringFromName("saveDialogTitle");
+      var parent = aContext.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal);
+      picker.init(parent, windowTitle, nsIFilePicker.modeSave);
+      picker.defaultString = aDefaultFile;
+
+      if (aSuggestedFileExtension) {
+        // aSuggestedFileExtension includes the period, so strip it
+        picker.defaultExtension = aSuggestedFileExtension.substring(1);
+      } 
+      else {
+        try {
+          picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension;
         } 
-        else {
-          try {
-            picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension;
-          } 
-          catch (ex) { }
-        }
-
-        var wildCardExtension = "*";
-        if (aSuggestedFileExtension) {
-          wildCardExtension += aSuggestedFileExtension;
-          picker.appendFilter(this.mLauncher.MIMEInfo.description, wildCardExtension);
-        }
-
-        picker.appendFilters( nsIFilePicker.filterAll );
+        catch (ex) { }
+      }
 
-        // Pull in the user's preferences and get the default download directory.
-        var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-        try {
-          var startDir = prefs.getComplexValue("browser.download.dir", Components.interfaces.nsILocalFile);
-          if (startDir.exists()) {
-            picker.displayDirectory = startDir;
-          }
-        } 
-        catch(exception) { }
+      var wildCardExtension = "*";
+      if (aSuggestedFileExtension) {
+        wildCardExtension += aSuggestedFileExtension;
+        picker.appendFilter(this.mLauncher.MIMEInfo.description, wildCardExtension);
+      }
 
-        var dlgResult = picker.show();
+      picker.appendFilters( nsIFilePicker.filterAll );
 
-        if (dlgResult == nsIFilePicker.returnCancel) {
-          // null result means user cancelled.
-          return null;
-        }
-
+      // Get the default download directory from download manager
+      var dnldMgr = Components.classes["@mozilla.org/download-manager;1"]
+                              .getService(Components.interfaces.nsIDownloadManager);
+      var startDir = dnldMgr.defaultDownloadsDirectory;
+      picker.displayDirectory = startDir;
 
-        // Be sure to save the directory the user chose through the Save As... 
-        // dialog  as the new browser.download.dir
-        result = picker.file;
+      if (picker.show() == nsIFilePicker.returnCancel) {
+        // null result means user cancelled.
+        return null;
+      }
+
+      // Be sure to save the directory the user chose through the Save As... 
+      // dialog  as the new browser.download.dir since the old one
+      // didn't exist.
+      result = picker.file;
 
-        if (result) {
-          try {
-            // Remove the file so that it's not there when we ensure non-existence later;
-            // this is safe because for the file to exist, the user would have had to
-            // confirm that he wanted the file overwritten.
-            if (result.exists())
-              result.remove(false);
-          }
-          catch (e) { }
-          var newDir = result.parent;
-          prefs.setComplexValue("browser.download.dir", Components.interfaces.nsILocalFile, newDir);
-          result = this.validateLeafName(newDir, result.leafName, null);
+      if (result) {
+        try {
+          // Remove the file so that it's not there when we ensure non-existence later;
+          // this is safe because for the file to exist, the user would have had to
+          // confirm that he wanted the file overwritten.
+          if (result.exists())
+            result.remove(false);
         }
+        catch (e) { }
+        var newDir = result.parent;
+        prefs.setComplexValue("browser.download.dir", Components.interfaces.nsILocalFile, newDir);
+        result = this.validateLeafName(newDir, result.leafName, null);
       }
       return result;
     },
 
     /**
      * Ensures that a local folder/file combination does not already exist in
      * the file system (or finds such a combination with a reasonably similar
      * leaf name), creates the corresponding file, and returns it.
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -445,22 +445,30 @@ GetSpecialSystemDirectory(SystemDirector
         {
             return GetWindowsFolder(CSIDL_DESKTOP, aFile);
         }
         case Win_Programs:
         {
             return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
         }
 
-        case Win_Downloads:
-        {
-            // Defined in KnownFolders.h.
-            GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
-            return GetKnownFolder(&folderid_downloads, aFile);
-        }
+        case Win_Downloads:
+        {
+            // Defined in KnownFolders.h.
+            GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64,
+                                       0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
+            nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
+            // On WinXP and 2k, there is no downloads folder, default
+            // to 'Desktop'.
+            if(NS_ERROR_FAILURE == rv)
+            {
+              rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
+            }
+            return rv;
+        }
 
         case Win_Controls:
         {
             return GetWindowsFolder(CSIDL_CONTROLS, aFile);
         }
         case Win_Printers:
         {
             return GetWindowsFolder(CSIDL_PRINTERS, aFile);