summaryrefslogtreecommitdiff
path: root/dom/downloads/DownloadsAPI.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/downloads/DownloadsAPI.jsm')
-rw-r--r--dom/downloads/DownloadsAPI.jsm365
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();