1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/jsdownloads/src/Downloads.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,299 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/** 1.11 + * Main entry point to get references to all the back-end objects. 1.12 + */ 1.13 + 1.14 +"use strict"; 1.15 + 1.16 +this.EXPORTED_SYMBOLS = [ 1.17 + "Downloads", 1.18 +]; 1.19 + 1.20 +//////////////////////////////////////////////////////////////////////////////// 1.21 +//// Globals 1.22 + 1.23 +const Cc = Components.classes; 1.24 +const Ci = Components.interfaces; 1.25 +const Cu = Components.utils; 1.26 +const Cr = Components.results; 1.27 + 1.28 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.29 +Cu.import("resource://gre/modules/DownloadCore.jsm"); 1.30 + 1.31 +XPCOMUtils.defineLazyModuleGetter(this, "DownloadCombinedList", 1.32 + "resource://gre/modules/DownloadList.jsm"); 1.33 +XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration", 1.34 + "resource://gre/modules/DownloadIntegration.jsm"); 1.35 +XPCOMUtils.defineLazyModuleGetter(this, "DownloadList", 1.36 + "resource://gre/modules/DownloadList.jsm"); 1.37 +XPCOMUtils.defineLazyModuleGetter(this, "DownloadSummary", 1.38 + "resource://gre/modules/DownloadList.jsm"); 1.39 +XPCOMUtils.defineLazyModuleGetter(this, "DownloadUIHelper", 1.40 + "resource://gre/modules/DownloadUIHelper.jsm"); 1.41 +XPCOMUtils.defineLazyModuleGetter(this, "Promise", 1.42 + "resource://gre/modules/Promise.jsm"); 1.43 +XPCOMUtils.defineLazyModuleGetter(this, "Task", 1.44 + "resource://gre/modules/Task.jsm"); 1.45 + 1.46 +//////////////////////////////////////////////////////////////////////////////// 1.47 +//// Downloads 1.48 + 1.49 +/** 1.50 + * This object is exposed directly to the consumers of this JavaScript module, 1.51 + * and provides the only entry point to get references to back-end objects. 1.52 + */ 1.53 +this.Downloads = { 1.54 + /** 1.55 + * Work on downloads that were not started from a private browsing window. 1.56 + */ 1.57 + get PUBLIC() "{Downloads.PUBLIC}", 1.58 + /** 1.59 + * Work on downloads that were started from a private browsing window. 1.60 + */ 1.61 + get PRIVATE() "{Downloads.PRIVATE}", 1.62 + /** 1.63 + * Work on both Downloads.PRIVATE and Downloads.PUBLIC downloads. 1.64 + */ 1.65 + get ALL() "{Downloads.ALL}", 1.66 + 1.67 + /** 1.68 + * Creates a new Download object. 1.69 + * 1.70 + * @param aProperties 1.71 + * Provides the initial properties for the newly created download. 1.72 + * This matches the serializable representation of a Download object. 1.73 + * Some of the most common properties in this object include: 1.74 + * { 1.75 + * source: String containing the URI for the download source. 1.76 + * Alternatively, may be an nsIURI, a DownloadSource object, 1.77 + * or an object with the following properties: 1.78 + * { 1.79 + * url: String containing the URI for the download source. 1.80 + * isPrivate: Indicates whether the download originated from a 1.81 + * private window. If omitted, the download is public. 1.82 + * referrer: String containing the referrer URI of the download 1.83 + * source. Can be omitted or null if no referrer should 1.84 + * be sent or the download source is not HTTP. 1.85 + * }, 1.86 + * target: String containing the path of the target file. 1.87 + * Alternatively, may be an nsIFile, a DownloadTarget object, 1.88 + * or an object with the following properties: 1.89 + * { 1.90 + * path: String containing the path of the target file. 1.91 + * }, 1.92 + * saver: String representing the class of the download operation. 1.93 + * If omitted, defaults to "copy". Alternatively, may be the 1.94 + * serializable representation of a DownloadSaver object. 1.95 + * } 1.96 + * 1.97 + * @return {Promise} 1.98 + * @resolves The newly created Download object. 1.99 + * @rejects JavaScript exception. 1.100 + */ 1.101 + createDownload: function D_createDownload(aProperties) 1.102 + { 1.103 + try { 1.104 + return Promise.resolve(Download.fromSerializable(aProperties)); 1.105 + } catch (ex) { 1.106 + return Promise.reject(ex); 1.107 + } 1.108 + }, 1.109 + 1.110 + /** 1.111 + * Downloads data from a remote network location to a local file. 1.112 + * 1.113 + * This download method does not provide user interface, or the ability to 1.114 + * cancel or restart the download programmatically. For that, you should 1.115 + * obtain a reference to a Download object using the createDownload function. 1.116 + * 1.117 + * Since the download cannot be restarted, any partially downloaded data will 1.118 + * not be kept in case the download fails. 1.119 + * 1.120 + * @param aSource 1.121 + * String containing the URI for the download source. Alternatively, 1.122 + * may be an nsIURI or a DownloadSource object. 1.123 + * @param aTarget 1.124 + * String containing the path of the target file. Alternatively, may 1.125 + * be an nsIFile or a DownloadTarget object. 1.126 + * @param aOptions 1.127 + * An optional object used to control the behavior of this function. 1.128 + * You may pass an object with a subset of the following fields: 1.129 + * { 1.130 + * isPrivate: Indicates whether the download originated from a 1.131 + * private window. 1.132 + * } 1.133 + * 1.134 + * @return {Promise} 1.135 + * @resolves When the download has finished successfully. 1.136 + * @rejects JavaScript exception if the download failed. 1.137 + */ 1.138 + fetch: function (aSource, aTarget, aOptions) { 1.139 + return this.createDownload({ 1.140 + source: aSource, 1.141 + target: aTarget, 1.142 + }).then(function D_SD_onSuccess(aDownload) { 1.143 + if (aOptions && ("isPrivate" in aOptions)) { 1.144 + aDownload.source.isPrivate = aOptions.isPrivate; 1.145 + } 1.146 + return aDownload.start(); 1.147 + }); 1.148 + }, 1.149 + 1.150 + /** 1.151 + * Retrieves the specified type of DownloadList object. There is one download 1.152 + * list for each type, and this method always retrieves a reference to the 1.153 + * same download list when called with the same argument. 1.154 + * 1.155 + * Calling this function may cause the list of public downloads to be reloaded 1.156 + * from the previous session, if it wasn't loaded already. 1.157 + * 1.158 + * @param aType 1.159 + * This can be Downloads.PUBLIC, Downloads.PRIVATE, or Downloads.ALL. 1.160 + * Downloads added to the Downloads.PUBLIC and Downloads.PRIVATE lists 1.161 + * are reflected in the Downloads.ALL list, and downloads added to the 1.162 + * Downloads.ALL list are also added to either the Downloads.PUBLIC or 1.163 + * the Downloads.PRIVATE list based on their properties. 1.164 + * 1.165 + * @return {Promise} 1.166 + * @resolves The requested DownloadList or DownloadCombinedList object. 1.167 + * @rejects JavaScript exception. 1.168 + */ 1.169 + getList: function (aType) 1.170 + { 1.171 + if (!this._promiseListsInitialized) { 1.172 + this._promiseListsInitialized = Task.spawn(function () { 1.173 + let publicList = new DownloadList(); 1.174 + let privateList = new DownloadList(); 1.175 + let combinedList = new DownloadCombinedList(publicList, privateList); 1.176 + 1.177 + try { 1.178 + yield DownloadIntegration.addListObservers(publicList, false); 1.179 + yield DownloadIntegration.addListObservers(privateList, true); 1.180 + yield DownloadIntegration.initializePublicDownloadList(publicList); 1.181 + } catch (ex) { 1.182 + Cu.reportError(ex); 1.183 + } 1.184 + 1.185 + let publicSummary = yield this.getSummary(Downloads.PUBLIC); 1.186 + let privateSummary = yield this.getSummary(Downloads.PRIVATE); 1.187 + let combinedSummary = yield this.getSummary(Downloads.ALL); 1.188 + 1.189 + yield publicSummary.bindToList(publicList); 1.190 + yield privateSummary.bindToList(privateList); 1.191 + yield combinedSummary.bindToList(combinedList); 1.192 + 1.193 + this._lists[Downloads.PUBLIC] = publicList; 1.194 + this._lists[Downloads.PRIVATE] = privateList; 1.195 + this._lists[Downloads.ALL] = combinedList; 1.196 + }.bind(this)); 1.197 + } 1.198 + 1.199 + return this._promiseListsInitialized.then(() => this._lists[aType]); 1.200 + }, 1.201 + 1.202 + /** 1.203 + * Promise resolved when the initialization of the download lists has 1.204 + * completed, or null if initialization has never been requested. 1.205 + */ 1.206 + _promiseListsInitialized: null, 1.207 + 1.208 + /** 1.209 + * After initialization, this object is populated with one key for each type 1.210 + * of download list that can be returned (Downloads.PUBLIC, Downloads.PRIVATE, 1.211 + * or Downloads.ALL). The values are the DownloadList objects. 1.212 + */ 1.213 + _lists: {}, 1.214 + 1.215 + /** 1.216 + * Retrieves the specified type of DownloadSummary object. There is one 1.217 + * download summary for each type, and this method always retrieves a 1.218 + * reference to the same download summary when called with the same argument. 1.219 + * 1.220 + * Calling this function does not cause the list of public downloads to be 1.221 + * reloaded from the previous session. The summary will behave as if no 1.222 + * downloads are present until the getList method is called. 1.223 + * 1.224 + * @param aType 1.225 + * This can be Downloads.PUBLIC, Downloads.PRIVATE, or Downloads.ALL. 1.226 + * 1.227 + * @return {Promise} 1.228 + * @resolves The requested DownloadList or DownloadCombinedList object. 1.229 + * @rejects JavaScript exception. 1.230 + */ 1.231 + getSummary: function (aType) 1.232 + { 1.233 + if (aType != Downloads.PUBLIC && aType != Downloads.PRIVATE && 1.234 + aType != Downloads.ALL) { 1.235 + throw new Error("Invalid aType argument."); 1.236 + } 1.237 + 1.238 + if (!(aType in this._summaries)) { 1.239 + this._summaries[aType] = new DownloadSummary(); 1.240 + } 1.241 + 1.242 + return Promise.resolve(this._summaries[aType]); 1.243 + }, 1.244 + 1.245 + /** 1.246 + * This object is populated by the getSummary method with one key for each 1.247 + * type of object that can be returned (Downloads.PUBLIC, Downloads.PRIVATE, 1.248 + * or Downloads.ALL). The values are the DownloadSummary objects. 1.249 + */ 1.250 + _summaries: {}, 1.251 + 1.252 + /** 1.253 + * Returns the system downloads directory asynchronously. 1.254 + * Mac OSX: 1.255 + * User downloads directory 1.256 + * XP/2K: 1.257 + * My Documents/Downloads 1.258 + * Vista and others: 1.259 + * User downloads directory 1.260 + * Linux: 1.261 + * XDG user dir spec, with a fallback to Home/Downloads 1.262 + * Android: 1.263 + * standard downloads directory i.e. /sdcard 1.264 + * 1.265 + * @return {Promise} 1.266 + * @resolves The downloads directory string path. 1.267 + */ 1.268 + getSystemDownloadsDirectory: function D_getSystemDownloadsDirectory() { 1.269 + return DownloadIntegration.getSystemDownloadsDirectory(); 1.270 + }, 1.271 + 1.272 + /** 1.273 + * Returns the preferred downloads directory based on the user preferences 1.274 + * in the current profile asynchronously. 1.275 + * 1.276 + * @return {Promise} 1.277 + * @resolves The downloads directory string path. 1.278 + */ 1.279 + getPreferredDownloadsDirectory: function D_getPreferredDownloadsDirectory() { 1.280 + return DownloadIntegration.getPreferredDownloadsDirectory(); 1.281 + }, 1.282 + 1.283 + /** 1.284 + * Returns the temporary directory where downloads are placed before the 1.285 + * final location is chosen, or while the document is opened temporarily 1.286 + * with an external application. This may or may not be the system temporary 1.287 + * directory, based on the platform asynchronously. 1.288 + * 1.289 + * @return {Promise} 1.290 + * @resolves The downloads directory string path. 1.291 + */ 1.292 + getTemporaryDownloadsDirectory: function D_getTemporaryDownloadsDirectory() { 1.293 + return DownloadIntegration.getTemporaryDownloadsDirectory(); 1.294 + }, 1.295 + 1.296 + /** 1.297 + * Constructor for a DownloadError object. When you catch an exception during 1.298 + * a download, you can use this to verify if "ex instanceof Downloads.Error", 1.299 + * before reading the exception properties with the error details. 1.300 + */ 1.301 + Error: DownloadError, 1.302 +};