Bug 948040 - Back out the download manager from 1.3 a=1.3+
authorFabrice Desré <fabrice@mozilla.com>
Fri, 20 Dec 2013 11:37:27 +0100
changeset 175444 e7079364d19bfb8c0b0a458d46cbe17c6be41621
parent 175443 bc261bbedf76af1bb6ddd2779609fc88f0688b3b
child 175445 274f1e06b821c2eb3e76a64fbbecf965fa99514f
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewers1
bugs948040
milestone28.0a2
Bug 948040 - Back out the download manager from 1.3 a=1.3+
b2g/app/b2g.js
b2g/chrome/content/shell.js
b2g/confvars.sh
b2g/installer/package-manifest.in
content/events/test/test_all_synthetic_events.html
dom/apps/src/PermissionsTable.jsm
dom/base/DOMRequestHelper.jsm
dom/base/Navigator.cpp
dom/downloads/moz.build
dom/downloads/src/DownloadsAPI.js
dom/downloads/src/DownloadsAPI.jsm
dom/downloads/src/DownloadsAPI.manifest
dom/downloads/src/DownloadsIPC.jsm
dom/downloads/src/moz.build
dom/downloads/tests/mochitest.ini
dom/downloads/tests/moz.build
dom/downloads/tests/serve_file.sjs
dom/downloads/tests/test_downloads_basic.html
dom/downloads/tests/test_downloads_large.html
dom/downloads/tests/test_downloads_navigator_object.html
dom/downloads/tests/test_downloads_pause_remove.html
dom/downloads/tests/test_downloads_pause_resume.html
dom/moz.build
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/DownloadEvent.webidl
dom/webidl/Downloads.webidl
dom/webidl/moz.build
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -839,20 +839,16 @@ pref("gfx.gralloc.fence-with-readpixels"
 pref("ril.cellbroadcast.disabled", false);
 
 // The url of the page used to display network error details.
 pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
-// Downloads API
-pref("dom.mozDownloads.enabled", true);
-pref("dom.downloads.max_retention_days", 7);
-
 // Inactivity time in milliseconds after which we shut down the OS.File worker.
 pref("osfile.reset_worker_delay", 5000);
 
 // The URL of the Firefox Accounts auth server backend
 pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
 
 // APZC preferences.
 //
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -21,18 +21,16 @@ Cu.import('resource://gre/modules/ErrorP
 #ifdef MOZ_WIDGET_GONK
 Cu.import('resource://gre/modules/NetworkStatsService.jsm');
 #endif
 
 // identity
 Cu.import('resource://gre/modules/SignInToWebsite.jsm');
 SignInToWebsiteController.init();
 
-Cu.import('resource://gre/modules/DownloadsAPI.jsm');
-
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
                                    'nsIStyleSheetService');
 
@@ -1490,26 +1488,8 @@ Services.obs.addObserver(function resetP
 #endif
   },
   'profile-before-change2', false);
 
   let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
                      .getService(Ci.nsIAppStartup);
   appStartup.quit(Ci.nsIAppStartup.eForceQuit);
 }, 'b2g-reset-profile', false);
-
-/**
-  * CID of our implementation of nsIDownloadManagerUI.
-  */
-const kTransferCid = Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}");
-
-/**
-  * Contract ID of the service implementing nsITransfer.
-  */
-const kTransferContractId = "@mozilla.org/transfer;1";
-
-// Override Toolkit's nsITransfer implementation with the one from the
-// JavaScript API for downloads.  This will eventually be removed when
-// nsIDownloadManager will not be available anymore (bug 851471).  The
-// old code in this module will be removed in bug 899110.
-Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
-                  .registerFactory(kTransferCid, "",
-                                   kTransferContractId, null);
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -55,10 +55,8 @@ MOZ_PAY=1
 MOZ_TOOLKIT_SEARCH=
 MOZ_PLACES=
 MOZ_B2G=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_NUWA_PROCESS=
 fi
 MOZ_FOLD_LIBS=1
-
-MOZ_JSDOWNLOADS=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -388,18 +388,16 @@
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/SiteSpecificUserAgent.manifest
 @BINPATH@/components/storage-mozStorage.js
 @BINPATH@/components/crypto-SDR.js
 @BINPATH@/components/jsconsole-clhandler.manifest
 @BINPATH@/components/jsconsole-clhandler.js
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
-@BINPATH@/components/Downloads.manifest
-@BINPATH@/components/DownloadLegacy.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 
 ; WiFi, NetworkManager, NetworkStats
 #ifdef MOZ_WIDGET_GONK
 @BINPATH@/components/DOMWifiManager.js
 @BINPATH@/components/DOMWifiManager.manifest
 @BINPATH@/components/NetworkInterfaceListService.js
@@ -559,19 +557,16 @@
 @BINPATH@/components/TCPSocketParentIntermediary.js
 @BINPATH@/components/TCPSocket.manifest
 
 @BINPATH@/components/Payment.js
 @BINPATH@/components/PaymentFlowInfo.js
 @BINPATH@/components/PaymentRequestInfo.js
 @BINPATH@/components/Payment.manifest
 
-@BINPATH@/components/DownloadsAPI.js
-@BINPATH@/components/DownloadsAPI.manifest
-
 ; InputMethod API
 @BINPATH@/components/MozKeyboard.js
 @BINPATH@/components/InputMethod.manifest
 
 ; Modules
 @BINPATH@/modules/*
 
 ; Safe Browsing
@@ -785,17 +780,16 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/YoutubeProtocolHandler.js
 @BINPATH@/components/RecoveryService.js
 @BINPATH@/components/MailtoProtocolHandler.js
 @BINPATH@/components/SmsProtocolHandler.js
 @BINPATH@/components/TelProtocolHandler.js
 @BINPATH@/components/B2GAboutRedirector.js
 @BINPATH@/components/FilePicker.js
 @BINPATH@/components/HelperAppDialog.js
-@BINPATH@/components/DownloadsUI.js
 
 @BINPATH@/components/DataStore.manifest
 @BINPATH@/components/DataStoreService.js
 @BINPATH@/components/dom_datastore.xpt
 
 #ifdef MOZ_WEBSPEECH
 @BINPATH@/components/dom_webspeechsynth.xpt
 #endif
--- a/content/events/test/test_all_synthetic_events.html
+++ b/content/events/test/test_all_synthetic_events.html
@@ -127,20 +127,16 @@ const kEventConstructors = {
   DeviceProximityEvent:                      { create: function (aName, aProps) {
                                                          return new DeviceProximityEvent(aName, aProps);
                                                        },
                                              },
   DeviceStorageChangeEvent:                  { create: function (aName, aProps) {
                                                          return new DeviceStorageChangeEvent(aName, aProps);
                                                        },
                                              },
-  DownloadEvent:                             { create: function (aName, aProps) {
-                                                         return new DownloadEvent(aName, aProps);
-                                                       },
-                                             },
   DOMTransactionEvent:                       { create: function (aName, aProps) {
                                                          return new DOMTransactionEvent(aName, aProps);
                                                        },
                                              },
   DragEvent:                                 { create: function (aName, aProps) {
                                                          var e = document.createEvent("dragevent");
                                                          e.initDragEvent(aName, aProps.bubbles, aProps.cancelable,
                                                                          aProps.view, aProps.detail,
--- a/dom/apps/src/PermissionsTable.jsm
+++ b/dom/apps/src/PermissionsTable.jsm
@@ -313,21 +313,16 @@ this.PermissionsTable =  { geolocation: 
                              privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
                            },
                            "speaker-control": {
                              app: DENY_ACTION,
                              privileged: ALLOW_ACTION,
                              certified: ALLOW_ACTION
                            },
-                           "downloads": {
-                             app: DENY_ACTION,
-                             privileged: DENY_ACTION,
-                             certified: ALLOW_ACTION
-                           },
                          };
 
 /**
  * Append access modes to the permission name as suffixes.
  *   e.g. permission name 'contacts' with ['read', 'write'] =
  *   ['contacts-read', contacts-write']
  * @param string aPermName
  * @param array aAccess
--- a/dom/base/DOMRequestHelper.jsm
+++ b/dom/base/DOMRequestHelper.jsm
@@ -179,23 +179,22 @@ DOMRequestIpcHelper.prototype = {
         this._listeners[aName] ? cpmm.removeWeakMessageListener(aName, this)
                                : cpmm.removeMessageListener(aName, this);
         delete this._listeners[aName];
       });
     }
 
     this._listeners = null;
     this._requests = null;
+    this._window = null;
 
     // Objects inheriting from DOMRequestIPCHelper may have an uninit function.
     if (this.uninit) {
       this.uninit();
     }
-
-    this._window = null;
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic !== "inner-window-destroyed") {
       return;
     }
 
     let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1534,23 +1534,16 @@ Navigator::DoNewResolve(JSContext* aCx, 
         bool hasPermission = CheckPermission("settings-read") ||
                              CheckPermission("settings-write");
         if (!hasPermission) {
           aValue.setNull();
           return true;
         }
       }
 
-      if (name.EqualsLiteral("mozDownloadManager")) {
-        if (!CheckPermission("downloads")) {
-          aValue.setNull();
-          return true;
-        }
-      }
-
       domObject = construct(aCx, naviObj);
       if (!domObject) {
         return Throw(aCx, NS_ERROR_FAILURE);
       }
     }
 
     if (!JS_WrapObject(aCx, &domObject)) {
       return false;
deleted file mode 100644
--- a/dom/downloads/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-if CONFIG["MOZ_B2G"]:
-	TEST_DIRS += ['tests']
-
-PARALLEL_DIRS += ['src']
deleted file mode 100644
--- a/dom/downloads/src/DownloadsAPI.js
+++ /dev/null
@@ -1,320 +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;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-Cu.import("resource://gre/modules/DownloadsIPC.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
-                                   "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIMessageSender");
-
-function debug(aStr) {
-  dump("-*- DownloadsAPI.js : " + aStr + "\n");
-}
-
-function DOMDownloadManagerImpl() {
-  debug("DOMDownloadManagerImpl constructor");
-}
-
-DOMDownloadManagerImpl.prototype = {
-  __proto__: DOMRequestIpcHelper.prototype,
-
-  // nsIDOMGlobalPropertyInitializer implementation
-  init: function(aWindow) {
-    debug("DownloadsManager init");
-    this.initDOMRequestHelper(aWindow,
-                              ["Downloads:Added",
-                               "Downloads:Removed"]);
-  },
-
-  uninit: function() {
-    debug("uninit");
-    downloadsCache.evict(this._window);
-  },
-
-  set ondownloadstart(aHandler) {
-    this.__DOM_IMPL__.setEventHandler("ondownloadstart", aHandler);
-  },
-
-  get ondownloadstart() {
-    return this.__DOM_IMPL__.getEventHandler("ondownloadstart");
-  },
-
-  getDownloads: function() {
-    debug("getDownloads()");
-
-    return this.createPromise(function (aResolve, aReject) {
-      DownloadsIPC.getDownloads().then(
-        function(aDownloads) {
-          // Turn the list of download objects into DOM objects and
-          // send them.
-          let array = Cu.createArrayIn(this._window);
-          for (let id in aDownloads) {
-            let dom = createDOMDownloadObject(this._window, aDownloads[id]);
-            array.push(this._prepareForContent(dom));
-          }
-          aResolve(array);
-        }.bind(this),
-        function() {
-          aReject("GetDownloadsError");
-        }
-      );
-    }.bind(this));
-  },
-
-  clearAllDone: function() {
-    debug("clearAllDone()");
-    return this.createPromise(function (aResolve, aReject) {
-      DownloadsIPC.clearAllDone().then(
-        function(aDownloads) {
-          // Turn the list of download objects into DOM objects and
-          // send them.
-          let array = Cu.createArrayIn(this._window);
-          for (let id in aDownloads) {
-            let dom = createDOMDownloadObject(this._window, aDownloads[id]);
-            array.push(this._prepareForContent(dom));
-          }
-          aResolve(array);
-        }.bind(this),
-        function() {
-          aReject("ClearAllDoneError");
-        }
-      );
-    }.bind(this));
-  },
-
-  remove: function(aDownload) {
-    debug("remove " + aDownload.url + " " + aDownload.id);
-    return this.createPromise(function (aResolve, aReject) {
-      if (!downloadsCache.has(this._window, aDownload.id)) {
-        debug("no download " + aDownload.id);
-        aReject("InvalidDownload");
-        return;
-      }
-
-      DownloadsIPC.remove(aDownload.id).then(
-        function(aResult) {
-          let dom = createDOMDownloadObject(this._window, aResult);
-          // Change the state right away to not race against the update message.
-          dom.wrappedJSObject.state = "finalized";
-          aResolve(this._prepareForContent(dom));
-        }.bind(this),
-        function() {
-          aReject("RemoveError");
-        }
-      );
-    }.bind(this));
-  },
-
-  /**
-    * Turns a chrome download object into a content accessible one.
-    * When we have __DOM_IMPL__ available we just use that, otherwise
-    * we run _create() with the wrapped js object.
-    */
-  _prepareForContent: function(aChromeObject) {
-    if (aChromeObject.__DOM_IMPL__) {
-      return aChromeObject.__DOM_IMPL__;
-    }
-    let res = this._window.DOMDownload._create(this._window,
-                                            aChromeObject.wrappedJSObject);
-    return res;
-  },
-
-  receiveMessage: function(aMessage) {
-    let data = aMessage.data;
-    switch(aMessage.name) {
-      case "Downloads:Added":
-        debug("Adding " + uneval(data));
-        let event = new this._window.DownloadEvent("downloadstart", {
-          download:
-            this._prepareForContent(createDOMDownloadObject(this._window, data))
-        });
-        this.__DOM_IMPL__.dispatchEvent(event);
-        break;
-    }
-  },
-
-  classID: Components.ID("{c6587afa-0696-469f-9eff-9dac0dd727fe}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
-                                         Ci.nsISupportsWeakReference,
-                                         Ci.nsIObserver,
-                                         Ci.nsIDOMGlobalPropertyInitializer]),
-
-};
-
-/**
-  * Keep track of download objects per window.
-  */
-let downloadsCache = {
-  init: function() {
-    this.cache = new WeakMap();
-  },
-
-  has: function(aWindow, aId) {
-    let downloads = this.cache.get(aWindow);
-    return !!(downloads && downloads[aId]);
-  },
-
-  get: function(aWindow, aDownload) {
-    let downloads = this.cache.get(aWindow);
-    if (!(downloads && downloads[aDownload.id])) {
-      debug("Adding download " + aDownload.id + " to cache.");
-      if (!downloads) {
-        this.cache.set(aWindow, {});
-        downloads = this.cache.get(aWindow);
-      }
-      // Create the object and add it to the cache.
-      let impl = Cc["@mozilla.org/downloads/download;1"]
-                   .createInstance(Ci.nsISupports);
-      impl.wrappedJSObject._init(aWindow, aDownload);
-      downloads[aDownload.id] = impl;
-    }
-    return downloads[aDownload.id];
-  },
-
-  evict: function(aWindow) {
-    this.cache.delete(aWindow);
-  }
-};
-
-downloadsCache.init();
-
-/**
-  * The DOM facade of a download object.
-  */
-
-function createDOMDownloadObject(aWindow, aDownload) {
-  return downloadsCache.get(aWindow, aDownload);
-}
-
-function DOMDownloadImpl() {
-  debug("DOMDownloadImpl constructor ");
-  this.wrappedJSObject = this;
-  this.totalBytes = 0;
-  this.currentBytes = 0;
-  this.url = null;
-  this.path = null;
-  this.state = "stopped";
-  this.contentType = null;
-  this.startTime = Date.now();
-  this.error = null;
-
-  /* private fields */
-  this.id = null;
-}
-
-DOMDownloadImpl.prototype = {
-
-  createPromise: function(aPromiseInit) {
-    return new this._window.Promise(aPromiseInit);
-  },
-
-  pause: function() {
-    debug("DOMDownloadImpl pause");
-    let id = this.id;
-    // We need to wrap the Promise.jsm promise in a "real" DOM promise...
-    return this.createPromise(function(aResolve, aReject) {
-      DownloadsIPC.pause(id).then(aResolve, aReject);
-    });
-  },
-
-  resume: function() {
-    debug("DOMDownloadImpl resume");
-    let id = this.id;
-    // We need to wrap the Promise.jsm promise in a "real" DOM promise...
-    return this.createPromise(function(aResolve, aReject) {
-      DownloadsIPC.resume(id).then(aResolve, aReject);
-    });
-  },
-
-  set onstatechange(aHandler) {
-    this.__DOM_IMPL__.setEventHandler("onstatechange", aHandler);
-  },
-
-  get onstatechange() {
-    return this.__DOM_IMPL__.getEventHandler("onstatechange");
-  },
-
-  _init: function(aWindow, aDownload) {
-    this._window = aWindow;
-    this.id = aDownload.id;
-    this._update(aDownload);
-    Services.obs.addObserver(this, "downloads-state-change-" + this.id,
-                             /* ownsWeak */ true);
-    debug("observer set for " + this.id);
-  },
-
-  /**
-    * Updates the state of the object and fires the statechange event.
-    */
-  _update: function(aDownload) {
-    debug("update " + uneval(aDownload));
-    if (this.id != aDownload.id) {
-      return;
-    }
-
-    let props = ["totalBytes", "currentBytes", "url", "path", "state",
-                 "contentType", "startTime"];
-    let changed = false;
-
-    props.forEach((prop) => {
-      if (aDownload[prop] && (aDownload[prop] != this[prop])) {
-        this[prop] = aDownload[prop];
-        changed = true;
-      }
-    });
-
-    if (aDownload.error) {
-      this.error = new this._window.DOMError("DownloadError", aDownload.error);
-    } else {
-      this.error = null;
-    }
-
-    // The visible state has not changed, so no need to fire an event.
-    if (!changed) {
-      return;
-    }
-
-    // __DOM_IMPL__ may not be available at first update.
-    if (this.__DOM_IMPL__) {
-      let event = new this._window.DownloadEvent("statechange", {
-        download: this.__DOM_IMPL__
-      });
-      debug("Dispatching statechange event. state=" + this.state);
-      this.__DOM_IMPL__.dispatchEvent(event);
-    }
-  },
-
-  observe: function(aSubject, aTopic, aData) {
-    debug("DOMDownloadImpl observe " + aTopic);
-    if (aTopic !== "downloads-state-change-" + this.id) {
-      return;
-    }
-
-    try {
-      let download = JSON.parse(aData);
-      // We get the start time as milliseconds, not as a Date object.
-      if (download.startTime) {
-        download.startTime = new Date(download.startTime);
-      }
-      this._update(download);
-    } catch(e) {}
-  },
-
-  classID: Components.ID("{96b81b99-aa96-439d-8c59-92eeed34705f}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
-                                         Ci.nsIObserver,
-                                         Ci.nsISupportsWeakReference])
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMDownloadManagerImpl,
-                                                     DOMDownloadImpl]);
deleted file mode 100644
--- a/dom/downloads/src/DownloadsAPI.jsm
+++ /dev/null
@@ -1,255 +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");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageBroadcaster");
-
-function debug(aStr) {
-  dump("-*- DownloadsAPI.jsm : " + aStr + "\n");
-}
-
-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);
-}
-
-let 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"].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()
-    };
-
-    if (aDownload.error) {
-      res.error = aDownload.error.name;
-    }
-
-    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);
-    // Removing 'Downloads:' and turning first letter to lower case to
-    // build the function name from the message name.
-    let c = aMessage.name[10].toLowerCase();
-    let methodName = c + aMessage.name.substring(11);
-    if (this[methodName] && typeof this[methodName] === "function") {
-      this[methodName](aMessage.data, aMessage.target);
-    } else {
-      debug("Unimplemented method:  " + methodName);
-    }
-  },
-
-  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!");
-    let self = this;
-    Task.spawn(function () {
-      let list = yield Downloads.getList(Downloads.ALL);
-      yield list.removeFinished();
-      list = yield Downloads.getList(Downloads.ALL);
-      let downloads = yield list.getAll();
-      let res = [];
-      downloads.forEach((aDownload) => {
-        res.push(self.jsonDownload(aDownload));
-      });
-      aMm.sendAsyncMessage("Downloads:ClearAllDone:Return", res);
-    }).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");
-      }
-    );
-  }
-};
-
-DownloadsAPI.init();
deleted file mode 100644
--- a/dom/downloads/src/DownloadsAPI.manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-# DownloadsAPI.js
-component {c6587afa-0696-469f-9eff-9dac0dd727fe} DownloadsAPI.js
-contract @mozilla.org/downloads/manager;1 {c6587afa-0696-469f-9eff-9dac0dd727fe}
-
-component {96b81b99-aa96-439d-8c59-92eeed34705f} DownloadsAPI.js
-contract @mozilla.org/downloads/download;1 {96b81b99-aa96-439d-8c59-92eeed34705f}
deleted file mode 100644
--- a/dom/downloads/src/DownloadsIPC.jsm
+++ /dev/null
@@ -1,221 +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 = ["DownloadsIPC"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
-                                   "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIMessageSender");
-
-/**
-  * This module lives in the child process and receives the ipc messages
-  * from the parent. It saves the download's state and redispatch changes
-  * to DOM objects using an observer notification.
-  *
-  * This module needs to be loaded once and only once per process.
-  */
-
-function debug(aStr) {
-  dump("-*- DownloadsIPC.jsm : " + aStr + "\n");
-}
-
-const ipcMessages = ["Downloads:Added",
-                     "Downloads:Removed",
-                     "Downloads:Changed",
-                     "Downloads:GetList:Return",
-                     "Downloads:ClearAllDone:Return",
-                     "Downloads:Remove:Return",
-                     "Downloads:Pause:Return",
-                     "Downloads:Resume:Return"];
-
-this.DownloadsIPC = {
-  downloads: {},
-
-  init: function() {
-    debug("init");
-    Services.obs.addObserver(this, "xpcom-shutdown", false);
-    ipcMessages.forEach((aMessage) => {
-      cpmm.addMessageListener(aMessage, this);
-    });
-
-    // We need to get the list of current downloads.
-    this.ready = false;
-    this.getListPromises = [];
-    this.clearAllPromises = [];
-    this.downloadPromises = {};
-    cpmm.sendAsyncMessage("Downloads:GetList", {});
-    this._promiseId = 0;
-  },
-
-  notifyChanges: function(aId) {
-    // TODO: use the subject instead of stringifying.
-    if (this.downloads[aId]) {
-      debug("notifyChanges notifying changes for " + aId);
-      Services.obs.notifyObservers(null, "downloads-state-change-" + aId,
-                                   JSON.stringify(this.downloads[aId]));
-    } else {
-      debug("notifyChanges failed for " + aId)
-    }
-  },
-
-  _updateDownloadsArray: function(aDownloads) {
-    this.downloads = [];
-    // We actually have an array of downloads.
-    aDownloads.forEach((aDownload) => {
-      this.downloads[aDownload.id] = aDownload;
-    });
-  },
-
-  receiveMessage: function(aMessage) {
-    let download = aMessage.data;
-    debug("message: " + aMessage.name + " " + download.id);
-    switch(aMessage.name) {
-      case "Downloads:GetList:Return":
-        this._updateDownloadsArray(download);
-
-        if (!this.ready) {
-          this.getListPromises.forEach(aPromise =>
-                                       aPromise.resolve(this.downloads));
-          this.getListPromises.length = 0;
-        }
-        this.ready = true;
-        break;
-      case "Downloads:ClearAllDone:Return":
-        this._updateDownloadsArray(download);
-        this.clearAllPromises.forEach(aPromise =>
-                                      aPromise.resolve(this.downloads));
-        this.clearAllPromises.length = 0;
-        break;
-      case "Downloads:Added":
-        this.downloads[download.id] = download;
-        this.notifyChanges(download.id);
-        break;
-      case "Downloads:Removed":
-        if (this.downloads[download.id]) {
-          this.downloads[download.id] = download;
-          this.notifyChanges(download.id);
-          delete this.downloads[download.id];
-        }
-        break;
-      case "Downloads:Changed":
-        // Only update properties that actually changed.
-        let cached = this.downloads[download.id];
-        if (!cached) {
-          debug("No download found for " + download.id);
-          return;
-        }
-        let props = ["totalBytes", "currentBytes", "url", "path", "state",
-                     "contentType", "startTime"];
-        let changed = false;
-
-        props.forEach((aProp) => {
-          if (download[aProp] && (download[aProp] != cached[aProp])) {
-            cached[aProp] = download[aProp];
-            changed = true;
-          }
-        });
-
-        // Updating the error property. We always get a 'state' change as
-        // well.
-        cached.error = download.error;
-
-        if (changed) {
-          this.notifyChanges(download.id);
-        }
-        break;
-      case "Downloads:Remove:Return":
-      case "Downloads:Pause:Return":
-      case "Downloads:Resume:Return":
-        if (this.downloadPromises[download.promiseId]) {
-          if (!download.error) {
-          this.downloadPromises[download.promiseId].resolve(download);
-          } else {
-            this.downloadPromises[download.promiseId].reject(download);
-          }
-          delete this.downloadPromises[download.promiseId];
-        }
-        break;
-    }
-  },
-
-  /**
-    * Returns a promise that is resolved with the list of current downloads.
-    */
-  getDownloads: function() {
-    debug("getDownloads()");
-    let deferred = Promise.defer();
-    if (this.ready) {
-      debug("Returning existing list.");
-      deferred.resolve(this.downloads);
-    } else {
-      this.getListPromises.push(deferred);
-    }
-    return deferred.promise;
-  },
-
-  /**
-    * Returns a promise that is resolved with the list of current downloads.
-    */
-  clearAllDone: function() {
-    debug("clearAllDone");
-    let deferred = Promise.defer();
-    this.clearAllPromises.push(deferred);
-    cpmm.sendAsyncMessage("Downloads:ClearAllDone", {});
-    return deferred.promise;
-  },
-
-  promiseId: function() {
-    return this._promiseId++;
-  },
-
-  remove: function(aId) {
-    debug("remove " + aId);
-    let deferred = Promise.defer();
-    let pId = this.promiseId();
-    this.downloadPromises[pId] = deferred;
-    cpmm.sendAsyncMessage("Downloads:Remove",
-                          { id: aId, promiseId: pId });
-    return deferred.promise;
-  },
-
-  pause: function(aId) {
-    debug("pause " + aId);
-    let deferred = Promise.defer();
-    let pId = this.promiseId();
-    this.downloadPromises[pId] = deferred;
-    cpmm.sendAsyncMessage("Downloads:Pause",
-                          { id: aId, promiseId: pId });
-    return deferred.promise;
-  },
-
-  resume: function(aId) {
-    debug("resume " + aId);
-    let deferred = Promise.defer();
-    let pId = this.promiseId();
-    this.downloadPromises[pId] = deferred;
-    cpmm.sendAsyncMessage("Downloads:Resume",
-                          { id: aId, promiseId: pId });
-    return deferred.promise;
-  },
-
-  observe: function(aSubject, aTopic, aData) {
-    if (aTopic == "xpcom-shutdown") {
-      ipcMessages.forEach((aMessage) => {
-        cpmm.removeMessageListener(aMessage, this);
-      });
-    }
-  }
-};
-
-DownloadsIPC.init();
deleted file mode 100644
--- a/dom/downloads/src/moz.build
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-EXTRA_COMPONENTS += [
-    'DownloadsAPI.js',
-    'DownloadsAPI.manifest',
-]
-
-EXTRA_JS_MODULES += [
-    'DownloadsAPI.jsm',
-    'DownloadsIPC.jsm',
-]
deleted file mode 100644
--- a/dom/downloads/tests/mochitest.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-support-files =
-  serve_file.sjs
-
-[test_downloads_navigator_object.html]
-[test_downloads_basic.html]
-[test_downloads_large.html]
-[test_downloads_pause_remove.html]
-[test_downloads_pause_resume.html]
deleted file mode 100644
--- a/dom/downloads/tests/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-MOCHITEST_MANIFESTS += ['mochitest.ini']
deleted file mode 100644
--- a/dom/downloads/tests/serve_file.sjs
+++ /dev/null
@@ -1,107 +0,0 @@
-// Serves a file with a given mime type and size at an optionally given rate.
-
-function getQuery(request) {
-  var query = {};
-  request.queryString.split('&').forEach(function (val) {
-    var [name, value] = val.split('=');
-    query[name] = unescape(value);
-  });
-  return query;
-}
-
-// Timer used to handle the request response.
-var timer = null;
-
-function handleResponse() {
-  // Is this a rate limited response?
-  if (this.state.rate > 0) {
-    // Calculate how many bytes we have left to send.
-    var bytesToWrite = this.state.totalBytes - this.state.sentBytes;
-
-    // Do we have any bytes left to send? If not we'll just fall thru and
-    // cancel our repeating timer and finalize the response.
-    if (bytesToWrite > 0) {
-      // Figure out how many bytes to send, based on the rate limit.
-      bytesToWrite =
-        (bytesToWrite > this.state.rate) ? this.state.rate : bytesToWrite;
-
-      for (let i = 0; i < bytesToWrite; i++) {
-        this.response.write("0");
-      }
-
-      // Update the number of bytes we've sent to the client.
-      this.state.sentBytes += bytesToWrite;
-
-      // Wait until the next call to do anything else.
-      return;
-    }
-  }
-  else {
-    // Not rate limited, write it all out.
-    for (let i = 0; i < this.state.totalBytes; i++) {
-      this.response.write("0");
-    }
-  }
-
-  // Finalize the response.
-  this.response.finish();
-
-  // All done sending, go ahead and cancel our repeating timer.
-  timer.cancel();
-}
-
-function handleRequest(request, response) {
-  var query = getQuery(request);
-
-  // Default values for content type, size and rate.
-  var contentType = "text/plain";
-  var size = 1024;
-  var rate = 0;
-
-  // optional content type to be used by our response.
-  if ("contentType" in query) {
-    contentType = query["contentType"];
-  }
-
-  // optional size (in bytes) for generated file.
-  if ("size" in query) {
-    size = parseInt(query["size"]);
-  }
-
-  // optional rate (in bytes/s) at which to send the file.
-  if ("rate" in query) {
-    rate = parseInt(query["rate"]);
-  }
-
-  // The context for the responseHandler.
-  var context = {
-    response: response,
-    state: {
-      contentType: contentType,
-      totalBytes: size,
-      sentBytes: 0,
-      rate: rate
-    }
-  };
-
-  // The notify implementation for the timer.
-  context.notify = handleResponse.bind(context);
-
-  timer =
-    Components.classes["@mozilla.org/timer;1"]
-              .createInstance(Components.interfaces.nsITimer);
-
-  // sending at a specific rate requires our response to be asynchronous so
-  // we handle all requests asynchronously. See handleResponse().
-  response.processAsync();
-
-  // generate the content.
-  response.setHeader("Content-Type", contentType, false);
-  response.setHeader("Content-Length", size.toString(), false);
-
-  // initialize the timer and start writing out the response.
-  timer.initWithCallback(context,
-                         1000,
-                         Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
-
-}
deleted file mode 100644
--- a/dom/downloads/tests/test_downloads_basic.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
-  <title>Test for Bug 938023 Downloads API</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=1024" download="test.bin" id="download1">Download #1</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing a simple download, waiting for it to be done.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next() {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index]();
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-function downloadChange(evt) {
-  var download = evt.download;
-  if (download.state == "succeeded") {
-    ok(download.totalBytes == 1024, "Download size is 1024 bytes.");
-    ok(download.contentType == "application/octet-stream",
-       "contentType is application/octet-stream.");
-    SimpleTest.finish();
-  }
-}
-
-var steps = [
-  // Start by setting the pref to true.
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", true]]
-    }, next);
-  },
-
-  // Setup the event listeners.
-  function() {
-    SpecialPowers.pushPermissions([
-      {type: "downloads", allow: true, context: document}
-    ], function() {
-      navigator.mozDownloadManager.ondownloadstart =
-        function(evt) {
-          ok(true, "Download started");
-          evt.download.addEventListener("statechange", downloadChange);
-        }
-      next();
-    });
-  },
-
-  // Click on the <a download> to start the download.
-  function() {
-    document.getElementById("download1").click();
-  }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/downloads/tests/test_downloads_large.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
-  <title>Test for Bug 938023 Downloads API</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing downloading a file, then checking getDownloads() and clearAllDone().
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index](args);
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-// Catch all error function.
-function error() {
-  ok(false, "API failure");
-  SimpleTest.finish();
-}
-
-function getDownloads(downloads) {
-  ok(downloads.length == 1, "One downloads after getDownloads");
-  navigator.mozDownloadManager.clearAllDone().then(clearAllDone, error);
-}
-
-function clearAllDone(downloads) {
-  ok(downloads.length == 0, "No downloads after clearAllDone");
-  SimpleTest.finish();
-}
-
-function downloadChange(evt) {
-  var download = evt.download;
-
-  if (download.state == "succeeded") {
-    ok(download.totalBytes == 102400, "Download size is 100k bytes.");
-    navigator.mozDownloadManager.getDownloads().then(getDownloads, error);
-  }
-}
-
-var steps = [
-  // Start by setting the pref to true.
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", true]]
-    }, next);
-  },
-
-  // Setup permission and clear current list.
-  function() {
-    SpecialPowers.pushPermissions([
-      {type: "downloads", allow: true, context: document}
-    ], function() {
-      navigator.mozDownloadManager.clearAllDone().then(next, error);
-    });
-  },
-
-  function(downloads) {
-    ok(downloads.length == 0, "Start with an empty download list.");
-    next();
-  },
-
-  // Setup the event listeners.
-  function() {
-    navigator.mozDownloadManager.ondownloadstart =
-      function(evt) {
-        ok(true, "Download started");
-        evt.download.addEventListener("statechange", downloadChange);
-      }
-    next();
-  },
-
-  // Click on the <a download> to start the download.
-  function() {
-    document.getElementById("download1").click();
-  }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/downloads/tests/test_downloads_navigator_object.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
-  <title>Test for Bug 938023 Downloads API</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-<iframe></iframe>
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next() {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index]();
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-var steps = [
-  // Start by setting the pref to true.
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", true]]
-    }, next);
-  },
-
-  function() {
-    SpecialPowers.pushPermissions([
-      {type: "downloads", allow: 0, context: document}
-    ], function() {
-      ise(frames[0].navigator.mozDownloadManager, null, "navigator.mozDownloadManager is null when the page doesn't have permissions");
-      next();
-    });
-  },
-
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", false]]
-    }, function() {
-      ise(navigator.mozDownloadManager, undefined, "navigator.mozDownloadManager is undefined");
-      next();
-    });
-  },
-
-  function() {
-    SimpleTest.finish();
-  }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/downloads/tests/test_downloads_pause_remove.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
-  <title>Test for Bug 938023 Downloads API</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400&rate=1024" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing pausing a download and then removing it.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index](args);
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-var pausing = false;
-
-// Catch all error function.
-function error() {
-  ok(false, "API failure");
-  SimpleTest.finish();
-}
-
-function checkDownloadList(downloads) {
-  ok(downloads.length == 0, "No downloads left");
-  SimpleTest.finish();
-}
-
-function checkRemoved(download) {
-  ok(download.state == "finalized", "Download removed.");
-  navigator.mozDownloadManager.getDownloads()
-           .then(checkDownloadList, error);
-}
-
-function downloadChange(evt) {
-  var download = evt.download;
-
-  if (download.state == "downloading" && !pausing) {
-    pausing = true;
-    download.pause();
-  } else if (download.state == "stopped") {
-    ok(pausing, "Download stopped by pause()");
-    navigator.mozDownloadManager.remove(download)
-             .then(checkRemoved, error);
-  }
-}
-
-var steps = [
-  // Start by setting the pref to true.
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", true]]
-    }, next);
-  },
-
-  // Setup permission and clear current list.
-  function() {
-    SpecialPowers.pushPermissions([
-      {type: "downloads", allow: true, context: document}
-    ], function() {
-      navigator.mozDownloadManager.clearAllDone().then(next, error);
-    });
-  },
-
-  function(downloads) {
-    ok(downloads.length == 0, "Start with an empty download list.");
-    next();
-  },
-
-  // Setup the event listeners.
-  function() {
-    navigator.mozDownloadManager.ondownloadstart =
-      function(evt) {
-        ok(true, "Download started");
-        evt.download.addEventListener("statechange", downloadChange);
-      }
-    next();
-  },
-
-  // Click on the <a download> to start the download.
-  function() {
-    document.getElementById("download1").click();
-  }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/downloads/tests/test_downloads_pause_resume.html
+++ /dev/null
@@ -1,119 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=938023
--->
-<head>
-  <title>Test for Bug 938023 Downloads API</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938023">Mozilla Bug 938023</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<a href="serve_file.sjs?contentType=application/octet-stream&size=102400&rate=1024" download="test.bin" id="download1">Large Download</a>
-<pre id="test">
-<script class="testbody" type="text/javascript;version=1.7">
-
-// Testing pausing a download and then resuming it.
-
-SimpleTest.waitForExplicitFinish();
-
-var index = -1;
-
-function next(args) {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index](args);
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-var pausing = false;
-var resuming = false;
-
-// Catch all error function.
-function error() {
-  ok(false, "API failure");
-  SimpleTest.finish();
-}
-
-function checkDownloadList(downloads) {
-  ok(downloads.length == 0, "No downloads left");
-  SimpleTest.finish();
-}
-
-function checkResumedFailed(download) {
-  ok(download.state == "stopped", "Download fails to resume.");
-  navigator.mozDownloadManager.clearAllDone()
-           .then(checkDownloadList, error);
-}
-
-function downloadChange(evt) {
-  var download = evt.download;
-
-  if (download.state == "downloading" && !pausing) {
-    pausing = true;
-    download.pause();
-  } else if (download.state == "stopped" && !resuming) {
-    resuming = true;
-    ok(pausing, "Download stopped by pause()");
-    // serve_file.sjs does not support resuming, so that should fail.
-    download.resume()
-            .then(error, function() { checkResumedFailed(download); });
-  }
-}
-
-var steps = [
-  // Start by setting the pref to true.
-  function() {
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozDownloads.enabled", true]]
-    }, next);
-  },
-
-  // Setup permission and clear current list.
-  function() {
-    SpecialPowers.pushPermissions([
-      {type: "downloads", allow: true, context: document}
-    ], function() {
-      navigator.mozDownloadManager.clearAllDone().then(next, error);
-    });
-  },
-
-  function(downloads) {
-    ok(downloads.length == 0, "Start with an empty download list.");
-    next();
-  },
-
-  // Setup the event listeners.
-  function() {
-    navigator.mozDownloadManager.ondownloadstart =
-      function(evt) {
-        ok(true, "Download started");
-        evt.download.addEventListener("statechange", downloadChange);
-      }
-    next();
-  },
-
-  // Click on the <a download> to start the download.
-  function() {
-    document.getElementById("download1").click();
-  }
-];
-
-next();
-
-</script>
-</pre>
-</body>
-</html>
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -99,19 +99,16 @@ if CONFIG['MOZ_PAY']:
     PARALLEL_DIRS += ['payment']
 
 if CONFIG['MOZ_GAMEPAD']:
     PARALLEL_DIRS += ['gamepad']
 
 if CONFIG['MOZ_NFC']:
     PARALLEL_DIRS += ['nfc']
 
-if CONFIG['MOZ_B2G']:
-    PARALLEL_DIRS += ['downloads']
-
 # bindings/test is here, because it needs to build after bindings/, and
 # we build subdirectories before ourselves.
 TEST_DIRS += [
     'tests',
     'imptests',
     'bindings/test',
 ]
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -216,19 +216,16 @@ var interfaceNamesInGlobalScope =
     "DOMRect",
     "DOMRectList",
     "DOMRequest",
     "DOMSettableTokenList",
     "DOMStringList",
     "DOMStringMap",
     "DOMTokenList",
     "DOMTransactionEvent",
-    {name: "DOMDownload", b2g: true, pref: "dom.mozDownloads.enabled"},
-    {name: "DOMDownloadManager", b2g: true, pref: "dom.mozDownloads.enabled"},
-    {name: "DownloadEvent", b2g: true, pref: "dom.mozDownloads.enabled"},
     "DragEvent",
     "DynamicsCompressorNode",
     "Element",
     "ElementReplaceEvent",
     "ErrorEvent",
     "Event",
     "EventListenerInfo",
     "EventSource",
deleted file mode 100644
--- a/dom/webidl/DownloadEvent.webidl
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
- */
-
-[Constructor(DOMString type, optional DownloadEventInit eventInitDict),
- Pref="dom.mozDownloads.enabled"]
-interface DownloadEvent : Event
-{
-  readonly attribute DOMDownload? download;
-};
-
-dictionary DownloadEventInit : EventInit
-{
-  DOMDownload? download = null;
-};
deleted file mode 100644
--- a/dom/webidl/Downloads.webidl
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
- */
-
-[NavigatorProperty="mozDownloadManager",
- JSImplementation="@mozilla.org/downloads/manager;1",
- Pref="dom.mozDownloads.enabled"]
-interface DOMDownloadManager : EventTarget {
-  // This promise returns an array of downloads with all the current
-  // download objects.
-  Promise getDownloads();
-
-  // Removes one download from the downloads set. Returns a promise resolved
-  // with the finalized download.
-  Promise remove(DOMDownload download);
-
-  // Removes all the completed downloads from the set.
-  Promise clearAllDone();
-
-  // Fires when a new download starts.
-  attribute EventHandler ondownloadstart;
-};
-
-[JSImplementation="@mozilla.org/downloads/download;1",
- Pref="dom.mozDownloads.enabled"]
-interface DOMDownload : EventTarget {
-  // The full size of the resource.
-  readonly attribute long totalBytes;
-
-  // The number of bytes that we have currently downloaded.
-  readonly attribute long currentBytes;
-
-  // The url of the resource.
-  readonly attribute DOMString url;
-
-  // The path in local storage where the file will end up once the download
-  // is complete.
-  readonly attribute DOMString path;
-
-  // The state of the download. Can be any of:
-  // "downloading": The resource is actively transfering.
-  // "stopped"    : No network tranfer is happening.
-  // "succeeded"  : The resource has been downloaded successfully.
-  // "finalized"  : We won't try to download this resource, but the DOM
-  //                object is still alive.
-  readonly attribute DOMString state;
-
-  // The mime type for this resource.
-  readonly attribute DOMString contentType;
-
-  // The timestamp this download started.
-  readonly attribute Date startTime;
-
-  // An opaque identifier for this download. All instances of the same
-  // download (eg. in different windows) will have the same id.
-  readonly attribute DOMString id;
-
-  // A DOM error object, that will be not null when a download is stopped
-  // because something failed.
-  readonly attribute DOMError error;
-
-  // Pauses the download.
-  Promise pause();
-
-  // Resumes the download. This resolves only once the download has
-  // succeeded.
-  Promise resume();
-
-  // This event is triggered anytime a property of the object changes:
-  // - when the transfer progresses, updating currentBytes.
-  // - when the state and/or error attributes change.
-  attribute EventHandler onstatechange;
-};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -81,17 +81,16 @@ WEBIDL_FILES = [
     'DOMParser.webidl',
     'DOMRect.webidl',
     'DOMRectList.webidl',
     'DOMRequest.webidl',
     'DOMSettableTokenList.webidl',
     'DOMStringMap.webidl',
     'DOMTokenList.webidl',
     'DOMTransaction.webidl',
-    'Downloads.webidl',
     'DragEvent.webidl',
     'DummyBinding.webidl',
     'DynamicsCompressorNode.webidl',
     'Element.webidl',
     'Event.webidl',
     'EventHandler.webidl',
     'EventListener.webidl',
     'EventSource.webidl',
@@ -565,17 +564,16 @@ if CONFIG['ENABLE_TESTS']:
     ]
 
 GENERATED_EVENTS_WEBIDL_FILES = [
     'BlobEvent.webidl',
     'CallGroupErrorEvent.webidl',
     'DataStoreChangeEvent.webidl',
     'DeviceLightEvent.webidl',
     'DeviceProximityEvent.webidl',
-    'DownloadEvent.webidl',
     'ErrorEvent.webidl',
     'IccChangeEvent.webidl',
     'MediaStreamEvent.webidl',
     'MozContactChangeEvent.webidl',
     'MozInterAppMessageEvent.webidl',
     'MozStkCommandEvent.webidl',
     'RTCDataChannelEvent.webidl',
     'RTCPeerConnectionIceEvent.webidl',
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -303,26 +303,17 @@ this.DownloadIntegration = {
    * @return True to save the download, false otherwise.
    */
   shouldPersistDownload: function (aDownload)
   {
     // In the default implementation, we save all the downloads currently in
     // progress, as well as stopped downloads for which we retained partially
     // downloaded data.  Stopped downloads for which we don't need to track the
     // presence of a ".part" file are only retained in the browser history.
-    // On b2g, we keep a few days of history.
-#ifdef MOZ_B2G
-    let maxTime = Date.now() -
-      Services.prefs.getIntPref("dom.downloads.max_retention_days") * 24 * 60 * 60 * 1000;
-    return (aDownload.startTime > maxTime) ||
-           aDownload.hasPartialData ||
-           !aDownload.stopped;
-#else
     return aDownload.hasPartialData || !aDownload.stopped;
-#endif
   },
 
   /**
    * Returns the system downloads directory asynchronously.
    *
    * @return {Promise}
    * @resolves The downloads directory string path.
    */
--- a/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
@@ -103,17 +103,17 @@ XPCOMUtils.defineLazyGetter(DownloadUIHe
  * Allows displaying prompts related to downloads.
  *
  * @param aParent
  *        The nsIDOMWindow to which prompts should be attached, or null to
  *        attach prompts to the most recently active window.
  */
 this.DownloadPrompter = function (aParent)
 {
-#ifdef MOZ_B2G
+#ifdef MOZ_WIDGET_GONK
   // On B2G there is no prompter implementation.
   this._prompter = null;
 #else
   this._prompter = Services.ww.getNewPrompter(aParent);
 #endif
 }
 
 this.DownloadPrompter.prototype = {