diff options
Diffstat (limited to 'dom/downloads/DownloadsAPI.jsm')
-rw-r--r-- | dom/downloads/DownloadsAPI.jsm | 365 |
1 files changed, 0 insertions, 365 deletions
diff --git a/dom/downloads/DownloadsAPI.jsm b/dom/downloads/DownloadsAPI.jsm deleted file mode 100644 index dfb8286fe0..0000000000 --- a/dom/downloads/DownloadsAPI.jsm +++ /dev/null @@ -1,365 +0,0 @@ -/* 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/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cu = Components.utils; - -this.EXPORTED_SYMBOLS = []; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Downloads.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "ppmm", - "@mozilla.org/parentprocessmessagemanager;1", - "nsIMessageBroadcaster"); - -/** - * Parent process logic that services download API requests from the - * DownloadAPI.js instances in content processeses. The actual work of managing - * downloads is done by Toolkit's Downloads.jsm. This module is loaded by B2G's - * shell.js - */ - -function debug(aStr) { -#ifdef MOZ_DEBUG - dump("-*- DownloadsAPI.jsm : " + aStr + "\n"); -#endif -} - -function sendPromiseMessage(aMm, aMessageName, aData, aError) { - debug("sendPromiseMessage " + aMessageName); - let msg = { - id: aData.id, - promiseId: aData.promiseId - }; - - if (aError) { - msg.error = aError; - } - - aMm.sendAsyncMessage(aMessageName, msg); -} - -var DownloadsAPI = { - init: function() { - debug("init"); - - this._ids = new WeakMap(); // Maps toolkit download objects to ids. - this._index = {}; // Maps ids to downloads. - - ["Downloads:GetList", - "Downloads:ClearAllDone", - "Downloads:Remove", - "Downloads:Pause", - "Downloads:Resume", - "Downloads:Adopt"].forEach((msgName) => { - ppmm.addMessageListener(msgName, this); - }); - - let self = this; - Task.spawn(function () { - let list = yield Downloads.getList(Downloads.ALL); - yield list.addView(self); - - debug("view added to download list."); - }).then(null, Components.utils.reportError); - - this._currentId = 0; - }, - - /** - * Returns a unique id for each download, hashing the url and the path. - */ - downloadId: function(aDownload) { - let id = this._ids.get(aDownload, null); - if (!id) { - id = "download-" + this._currentId++; - this._ids.set(aDownload, id); - this._index[id] = aDownload; - } - return id; - }, - - getDownloadById: function(aId) { - return this._index[aId]; - }, - - /** - * Converts a download object into a plain json object that we'll - * send to the DOM side. - */ - jsonDownload: function(aDownload) { - let res = { - totalBytes: aDownload.totalBytes, - currentBytes: aDownload.currentBytes, - url: aDownload.source.url, - path: aDownload.target.path, - contentType: aDownload.contentType, - startTime: aDownload.startTime.getTime(), - sourceAppManifestURL: aDownload._unknownProperties && - aDownload._unknownProperties.sourceAppManifestURL - }; - - if (aDownload.error) { - res.error = aDownload.error; - } - - res.id = this.downloadId(aDownload); - - // The state of the download. Can be any of "downloading", "stopped", - // "succeeded", finalized". - - // Default to "stopped" - res.state = "stopped"; - if (!aDownload.stopped && - !aDownload.canceled && - !aDownload.succeeded && - !aDownload.DownloadError) { - res.state = "downloading"; - } else if (aDownload.succeeded) { - res.state = "succeeded"; - } - return res; - }, - - /** - * download view methods. - */ - onDownloadAdded: function(aDownload) { - let download = this.jsonDownload(aDownload); - debug("onDownloadAdded " + uneval(download)); - ppmm.broadcastAsyncMessage("Downloads:Added", download); - }, - - onDownloadRemoved: function(aDownload) { - let download = this.jsonDownload(aDownload); - download.state = "finalized"; - debug("onDownloadRemoved " + uneval(download)); - ppmm.broadcastAsyncMessage("Downloads:Removed", download); - this._index[this._ids.get(aDownload)] = null; - this._ids.delete(aDownload); - }, - - onDownloadChanged: function(aDownload) { - let download = this.jsonDownload(aDownload); - debug("onDownloadChanged " + uneval(download)); - ppmm.broadcastAsyncMessage("Downloads:Changed", download); - }, - - receiveMessage: function(aMessage) { - if (!aMessage.target.assertPermission("downloads")) { - debug("No 'downloads' permission!"); - return; - } - - debug("message: " + aMessage.name); - - switch (aMessage.name) { - case "Downloads:GetList": - this.getList(aMessage.data, aMessage.target); - break; - case "Downloads:ClearAllDone": - this.clearAllDone(aMessage.data, aMessage.target); - break; - case "Downloads:Remove": - this.remove(aMessage.data, aMessage.target); - break; - case "Downloads:Pause": - this.pause(aMessage.data, aMessage.target); - break; - case "Downloads:Resume": - this.resume(aMessage.data, aMessage.target); - break; - case "Downloads:Adopt": - this.adoptDownload(aMessage.data, aMessage.target); - break; - default: - debug("Invalid message: " + aMessage.name); - } - }, - - getList: function(aData, aMm) { - debug("getList called!"); - let self = this; - Task.spawn(function () { - let list = yield Downloads.getList(Downloads.ALL); - let downloads = yield list.getAll(); - let res = []; - downloads.forEach((aDownload) => { - res.push(self.jsonDownload(aDownload)); - }); - aMm.sendAsyncMessage("Downloads:GetList:Return", res); - }).then(null, Components.utils.reportError); - }, - - clearAllDone: function(aData, aMm) { - debug("clearAllDone called!"); - Task.spawn(function () { - let list = yield Downloads.getList(Downloads.ALL); - list.removeFinished(); - }).then(null, Components.utils.reportError); - }, - - remove: function(aData, aMm) { - debug("remove id " + aData.id); - let download = this.getDownloadById(aData.id); - if (!download) { - sendPromiseMessage(aMm, "Downloads:Remove:Return", - aData, "NoSuchDownload"); - return; - } - - Task.spawn(function() { - yield download.finalize(true); - let list = yield Downloads.getList(Downloads.ALL); - yield list.remove(download); - }).then( - function() { - sendPromiseMessage(aMm, "Downloads:Remove:Return", aData); - }, - function() { - sendPromiseMessage(aMm, "Downloads:Remove:Return", - aData, "RemoveError"); - } - ); - }, - - pause: function(aData, aMm) { - debug("pause id " + aData.id); - let download = this.getDownloadById(aData.id); - if (!download) { - sendPromiseMessage(aMm, "Downloads:Pause:Return", - aData, "NoSuchDownload"); - return; - } - - download.cancel().then( - function() { - sendPromiseMessage(aMm, "Downloads:Pause:Return", aData); - }, - function() { - sendPromiseMessage(aMm, "Downloads:Pause:Return", - aData, "PauseError"); - } - ); - }, - - resume: function(aData, aMm) { - debug("resume id " + aData.id); - let download = this.getDownloadById(aData.id); - if (!download) { - sendPromiseMessage(aMm, "Downloads:Resume:Return", - aData, "NoSuchDownload"); - return; - } - - download.start().then( - function() { - sendPromiseMessage(aMm, "Downloads:Resume:Return", aData); - }, - function() { - sendPromiseMessage(aMm, "Downloads:Resume:Return", - aData, "ResumeError"); - } - ); - }, - - /** - * Receive a download to adopt in the same representation we produce from - * our "jsonDownload" normalizer and add it to the list of downloads. - */ - adoptDownload: function(aData, aMm) { - let adoptJsonRep = aData.jsonDownload; - debug("adoptDownload " + uneval(adoptJsonRep)); - - Task.spawn(function* () { - // Verify that the file exists on disk. This will result in a rejection - // if the file does not exist. We will also use this information for the - // file size to avoid weird inconsistencies. We ignore the filesystem - // timestamp in favor of whatever the caller is telling us. - let fileInfo = yield OS.File.stat(adoptJsonRep.path); - - // We also require that the file is not a directory. - if (fileInfo.isDir) { - throw new Error("AdoptFileIsDirectory"); - } - - // We need to create a Download instance to add to the list. Create a - // serialized representation and then from there the instance. - let serializedRep = { - // explicit initializations in toSerializable - source: { - url: adoptJsonRep.url - // This is where isPrivate would go if adoption supported private - // browsing. - }, - target: { - path: adoptJsonRep.path, - }, - startTime: adoptJsonRep.startTime, - // kPlainSerializableDownloadProperties propagations - succeeded: true, // (all adopted downloads are required to be completed) - totalBytes: fileInfo.size, - contentType: adoptJsonRep.contentType, - // unknown properties added/used by the DownloadsAPI - currentBytes: fileInfo.size, - sourceAppManifestURL: adoptJsonRep.sourceAppManifestURL - }; - - let download = yield Downloads.createDownload(serializedRep); - - // The ALL list is a DownloadCombinedList instance that combines the - // PUBLIC (persisted to disk) and PRIVATE (ephemeral) download lists.. - // When we call add on it, it dispatches to the appropriate list based on - // the 'isPrivate' field of the source. (Which we don't initialize and - // defaults to false.) - let allDownloadList = yield Downloads.getList(Downloads.ALL); - - // This add will automatically notify all views of the added download, - // including DownloadsAPI instances and the DownloadAutoSaveView that's - // subscribed to the PUBLIC list and will save the download. - yield allDownloadList.add(download); - - debug("download adopted"); - // The notification above occurred synchronously, and so we will have - // already dispatched an added notification for our download to the child - // process in question. As such, we only need to relay the download id - // since the download will already have been cached. - return download; - }.bind(this)).then( - (download) => { - sendPromiseMessage(aMm, "Downloads:Adopt:Return", - { - id: this.downloadId(download), - promiseId: aData.promiseId - }); - }, - (ex) => { - let reportAs = "AdoptError"; - // Provide better error codes for expected errors. - if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) { - reportAs = "AdoptNoSuchFile"; - } else if (ex.message === "AdoptFileIsDirectory") { - reportAs = ex.message; - } else { - // Anything else is unexpected and should be reported to help track - // down what's going wrong. - debug("unexpected download error: " + ex); - Cu.reportError(ex); - } - sendPromiseMessage(aMm, "Downloads:Adopt:Return", - { - promiseId: aData.promiseId - }, - reportAs); - }); - } -}; - -DownloadsAPI.init(); |