Bug 875648 - Use Downloads.jsm functions to get download directories in Firefox for Desktop. r=jaws
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Fri, 01 Nov 2013 18:24:00 +0000
changeset 221491 4e494ede6c2d84e10b8b6d7c05dde0ca22f038a5
parent 221490 bb24f0be1bcbc8cb04aa0bd4cabd003445a46e13
child 221492 77a3622f04d4c3a986289d53de61ada018736be9
push id28031
push userkwierso@gmail.com
push dateTue, 30 Dec 2014 00:55:49 +0000
treeherdermozilla-central@62e3a9f26d21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs875648
milestone37.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 875648 - Use Downloads.jsm functions to get download directories in Firefox for Desktop. r=jaws
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/main.xul
browser/components/preferences/main.js
browser/components/preferences/main.xul
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
-                                  "resource:///modules/DownloadsCommon.jsm");
+Components.utils.import("resource://gre/modules/Downloads.jsm");
+Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
 
 var gMainPane = {
   /**
    * Initialization of this.
    */
   init: function ()
   {
     function setEventListener(aId, aEventType, aCallback)
@@ -450,62 +451,67 @@ var gMainPane = {
     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 ()
+  chooseFolder() this.chooseFolderTask().catch(Components.utils.reportError),
+  chooseFolderTask: Task.async(function* ()
   {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    const nsILocalFile = Components.interfaces.nsILocalFile;
-
     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 currentDirPref = yield this._indexToFolder(folderListPref.value);
+    let defDownloads = yield this._indexToFolder(1);
     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");
+             createInstance(Components.interfaces.nsIFilePicker);
 
-        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);
+    fp.init(window, title, Components.interfaces.nsIFilePicker.modeGetFolder);
+    fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
     // First try to open what's currently configured
     if (currentDirPref && currentDirPref.exists()) {
       fp.displayDirectory = currentDirPref;
     } // Try the system's download dir
     else if (defDownloads && defDownloads.exists()) {
       fp.displayDirectory = defDownloads;
     } // Fall back to Desktop
     else {
-      fp.displayDirectory = this._indexToFolder(0);
+      fp.displayDirectory = yield this._indexToFolder(0);
+    }
+
+    let result = yield new Promise(resolve => fp.open(resolve));
+    if (result != Components.interfaces.nsIFilePicker.returnOK) {
+      return;
     }
-    fp.open(fpCallback);
-  },
+
+    let downloadDirPref = document.getElementById("browser.download.dir");
+    downloadDirPref.value = fp.file;
+    folderListPref.value = yield this._folderToIndex(fp.file);
+    // Note, the real prefs will not be updated yet, so dnld manager's
+    // userDownloadsDirectory may not return the right folder after
+    // this code executes. displayDownloadDirPref will be called on
+    // the assignment above to update the UI.
+  }),
 
   /**
    * Initializes the download folder display settings based on the user's
    * preferences.
    */
-  displayDownloadDirPref: function ()
+  displayDownloadDirPref()
+  {
+    this.displayDownloadDirPrefTask().catch(Components.utils.reportError);
+
+    // don't override the preference's value in UI
+    return undefined;
+  },
+
+  displayDownloadDirPrefTask: Task.async(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");
 
     // Used in defining the correct path to the folder icon.
     var ios = Components.classes["@mozilla.org/network/io-service;1"]
@@ -526,27 +532,24 @@ var gMainPane = {
       // 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));
+      iconUrlSpec = fph.getURLSpecFromFile(yield this._indexToFolder(1));
     } else {
       // 'Desktop'
       downloadFolder.label = bundlePreferences.getString("desktopFolderName");
-      iconUrlSpec = fph.getURLSpecFromFile(desk);
+      iconUrlSpec = fph.getURLSpecFromFile(yield this._getDownloadsFolder("Desktop"));
     }
     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.
@@ -557,95 +560,69 @@ var gMainPane = {
    * 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)
+  _getDownloadsFolder: Task.async(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;
+        let downloadsDir = yield Downloads.getSystemDownloadsDirectory();
+        return new FileUtils.File(downloadsDir);
     }
     throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-  },
+  }),
 
   /**
    * Determines the type of the given folder.
    *
    * @param   aFolder
    *          the folder whose type is to be determined
    * @returns integer
    *          0 if aFolder is the Desktop or is unspecified,
    *          1 if aFolder is the Downloads folder,
    *          2 otherwise
    */
-  _folderToIndex: function (aFolder)
+  _folderToIndex: Task.async(function* (aFolder)
   {
-    if (!aFolder || aFolder.equals(this._getDownloadsFolder("Desktop")))
+    if (!aFolder || aFolder.equals(yield this._getDownloadsFolder("Desktop")))
       return 0;
-    else if (aFolder.equals(this._getDownloadsFolder("Downloads")))
+    else if (aFolder.equals(yield this._getDownloadsFolder("Downloads")))
       return 1;
     return 2;
-  },
+  }),
 
   /**
    * Converts an integer into the corresponding folder.
    *
    * @param   aIndex
    *          an integer
    * @returns the Desktop folder if aIndex == 0,
    *          the Downloads folder if aIndex == 1,
    *          the folder stored in browser.download.dir
    */
-  _indexToFolder: function (aIndex)
+  _indexToFolder: Task.async(function* (aIndex)
   {
     switch (aIndex) {
       case 0:
-        return this._getDownloadsFolder("Desktop");
+        return yield this._getDownloadsFolder("Desktop");
       case 1:
-        return this._getDownloadsFolder("Downloads");
+        return yield this._getDownloadsFolder("Downloads");
     }
     var currentDirPref = document.getElementById("browser.download.dir");
     return currentDirPref.value;
-  },
-
-  /**
-   * Returns the value for the browser.download.folderList preference.
-   */
-  getFolderListPref: function ()
-  {
-    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;
-    }
-  },
+  }),
 
   /**
    * Hide/show the "Show my windows and tabs from last time" option based
    * on the value of the browser.privatebrowsing.autostart pref.
    */
   updateBrowserStartupLastSession: function()
   {
     let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -218,28 +218,26 @@
              label="&saveTo.label;"
              accesskey="&saveTo.accesskey;"
              aria-labelledby="saveTo downloadFolder"/>
       <filefield id="downloadFolder"
                  flex="1"
                  preference="browser.download.folderList"
                  preference-editable="true"
                  aria-labelledby="saveTo"
-                 onsyncfrompreference="return gMainPane.displayDownloadDirPref();"
-                 onsynctopreference="return gMainPane.getFolderListPref()"/>
+                 onsyncfrompreference="return gMainPane.displayDownloadDirPref();"/>
       <button id="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.getFolderListPref();"/>
+      />
     </hbox>
     <hbox>
       <radio id="alwaysAsk"
              value="false"
              label="&alwaysAsk.label;"
              accesskey="&alwaysAsk.accesskey;"/>
     </hbox>
   </radiogroup>
--- a/browser/components/preferences/main.js
+++ b/browser/components/preferences/main.js
@@ -1,16 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
-                                  "resource:///modules/DownloadsCommon.jsm");
+Components.utils.import("resource://gre/modules/Downloads.jsm");
+Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource://gre/modules/Task.jsm");
 
 var gMainPane = {
   _pane: null,
 
   /**
    * Initialization of this.
    */
   init: function ()
@@ -327,62 +327,67 @@ var gMainPane = {
     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 ()
+  chooseFolder() this.chooseFolderTask().catch(Components.utils.reportError),
+  chooseFolderTask: Task.async(function* ()
   {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    const nsILocalFile = Components.interfaces.nsILocalFile;
-
     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 currentDirPref = yield this._indexToFolder(folderListPref.value);
+    let defDownloads = yield this._indexToFolder(1);
     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");
+             createInstance(Components.interfaces.nsIFilePicker);
 
-        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);
+    fp.init(window, title, Components.interfaces.nsIFilePicker.modeGetFolder);
+    fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
     // First try to open what's currently configured
     if (currentDirPref && currentDirPref.exists()) {
       fp.displayDirectory = currentDirPref;
     } // Try the system's download dir
     else if (defDownloads && defDownloads.exists()) {
       fp.displayDirectory = defDownloads;
     } // Fall back to Desktop
     else {
-      fp.displayDirectory = this._indexToFolder(0);
+      fp.displayDirectory = yield this._indexToFolder(0);
+    }
+
+    let result = yield new Promise(resolve => fp.open(resolve));
+    if (result != Components.interfaces.nsIFilePicker.returnOK) {
+      return;
     }
-    fp.open(fpCallback);
-  },
+
+    let downloadDirPref = document.getElementById("browser.download.dir");
+    downloadDirPref.value = fp.file;
+    folderListPref.value = yield this._folderToIndex(fp.file);
+    // Note, the real prefs will not be updated yet, so dnld manager's
+    // userDownloadsDirectory may not return the right folder after
+    // this code executes. displayDownloadDirPref will be called on
+    // the assignment above to update the UI.
+  }),
 
   /**
    * Initializes the download folder display settings based on the user's 
    * preferences.
    */
-  displayDownloadDirPref: function ()
+  displayDownloadDirPref()
+  {
+    this.displayDownloadDirPrefTask().catch(Components.utils.reportError);
+
+    // don't override the preference's value in UI
+    return undefined;
+  },
+
+  displayDownloadDirPrefTask: Task.async(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");
 
     // Used in defining the correct path to the folder icon.
     var ios = Components.classes["@mozilla.org/network/io-service;1"]
@@ -403,27 +408,24 @@ var gMainPane = {
       // 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));
+      iconUrlSpec = fph.getURLSpecFromFile(yield this._indexToFolder(1));
     } else {
       // 'Desktop'
       downloadFolder.label = bundlePreferences.getString("desktopFolderName");
-      iconUrlSpec = fph.getURLSpecFromFile(this._getDownloadsFolder("Desktop"));
+      iconUrlSpec = fph.getURLSpecFromFile(yield this._getDownloadsFolder("Desktop"));
     }
     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.
@@ -434,95 +436,69 @@ var gMainPane = {
    * 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)
+  _getDownloadsFolder: Task.async(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;
+        let downloadsDir = yield Downloads.getSystemDownloadsDirectory();
+        return new FileUtils.File(downloadsDir);
     }
     throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'";
-  },
+  }),
 
   /**
    * Determines the type of the given folder.
    *
    * @param   aFolder
    *          the folder whose type is to be determined
    * @returns integer
    *          0 if aFolder is the Desktop or is unspecified,
    *          1 if aFolder is the Downloads folder,
    *          2 otherwise
    */
-  _folderToIndex: function (aFolder)
+  _folderToIndex: Task.async(function* (aFolder)
   {
-    if (!aFolder || aFolder.equals(this._getDownloadsFolder("Desktop")))
+    if (!aFolder || aFolder.equals(yield this._getDownloadsFolder("Desktop")))
       return 0;
-    else if (aFolder.equals(this._getDownloadsFolder("Downloads")))
+    else if (aFolder.equals(yield this._getDownloadsFolder("Downloads")))
       return 1;
     return 2;
-  },
+  }),
 
   /**
    * Converts an integer into the corresponding folder.
    *
    * @param   aIndex
    *          an integer
    * @returns the Desktop folder if aIndex == 0,
    *          the Downloads folder if aIndex == 1,
    *          the folder stored in browser.download.dir
    */
-  _indexToFolder: function (aIndex)
+  _indexToFolder: Task.async(function* (aIndex)
   {
     switch (aIndex) {
       case 0:
-        return this._getDownloadsFolder("Desktop");
+        return yield this._getDownloadsFolder("Desktop");
       case 1:
-        return this._getDownloadsFolder("Downloads");
+        return yield this._getDownloadsFolder("Downloads");
     }
     var currentDirPref = document.getElementById("browser.download.dir");
     return currentDirPref.value;
-  },
-
-  /**
-   * Returns the value for the browser.download.folderList preference.
-   */
-  getFolderListPref: function ()
-  {
-    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;
-    }
-  },
+  }),
 
   /**
    * Hide/show the "Show my windows and tabs from last time" option based
    * on the value of the browser.privatebrowsing.autostart pref.
    */
   updateBrowserStartupLastSession: function()
   {
     let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
--- a/browser/components/preferences/main.xul
+++ b/browser/components/preferences/main.xul
@@ -159,28 +159,26 @@
           <radio id="saveTo" value="true"
                  label="&saveTo.label;"
                  accesskey="&saveTo.accesskey;"
                  aria-labelledby="saveTo downloadFolder"/>
           <filefield id="downloadFolder" flex="1"
                      preference="browser.download.folderList"
                      preference-editable="true"
                      aria-labelledby="saveTo"
-                     onsyncfrompreference="return gMainPane.displayDownloadDirPref();"
-                     onsynctopreference="return gMainPane.getFolderListPref()"/>
+                     onsyncfrompreference="return gMainPane.displayDownloadDirPref();"/>
           <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.getFolderListPref();"/>
+          />
         </hbox>
         <radio id="alwaysAsk" value="false"
                label="&alwaysAsk.label;"
                accesskey="&alwaysAsk.accesskey;"/>
       </radiogroup>
     </groupbox>
 
   </prefpane>