Bug 1362384 - Remove code to import data from "downloads.sqlite". r=mak draft
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Fri, 05 May 2017 14:46:41 +0100
changeset 576202 2f4687de671173263ddede8da3848609c188c30b
parent 575474 ebbcdaa5b5802ecd39624dd2acbdda8547b8384d
child 576203 c6b47c5b0026904c4b2fc785b50d125a6a687979
push id58277
push userpaolo.mozmail@amadzone.org
push dateThu, 11 May 2017 12:27:47 +0000
reviewersmak
bugs1362384
milestone55.0a1
Bug 1362384 - Remove code to import data from "downloads.sqlite". r=mak When upgrading an old profile that still uses "downloads.sqlite", information about in-progress and paused downloads will be lost. The history of completed downloads will be preserved because it is stored in the Places database, although it may be affected by history expiration. MozReview-Commit-ID: GFqvACKC4E1
toolkit/components/jsdownloads/src/DownloadImport.jsm
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/jsdownloads/src/moz.build
toolkit/components/jsdownloads/test/unit/test_DownloadImport.js
toolkit/components/jsdownloads/test/unit/xpcshell.ini
toolkit/components/telemetry/Telemetry.cpp
toolkit/modules/Troubleshoot.jsm
deleted file mode 100644
--- a/toolkit/components/jsdownloads/src/DownloadImport.jsm
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
-/* 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";
-
-this.EXPORTED_SYMBOLS = [
-  "DownloadImport",
-];
-
-// Globals
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
-                                  "resource://gre/modules/Downloads.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
-                                  "resource://gre/modules/osfile.jsm")
-XPCOMUtils.defineLazyModuleGetter(this, "Task",
-                                  "resource://gre/modules/Task.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
-                                  "resource://gre/modules/Sqlite.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
-
-/**
- * These values come from the previous interface
- * nsIDownloadManager, which has now been deprecated.
- * These are the only types of download states that
- * we will import.
- */
-const DOWNLOAD_NOTSTARTED = -1;
-const DOWNLOAD_DOWNLOADING = 0;
-const DOWNLOAD_PAUSED = 4;
-const DOWNLOAD_QUEUED = 5;
-
-// DownloadImport
-
-/**
- * Provides an object that has a method to import downloads
- * from the previous SQLite storage format.
- *
- * @param aList   A DownloadList where each successfully
- *                imported download will be added.
- * @param aPath   The path to the database file.
- */
-this.DownloadImport = function(aList, aPath) {
-  this.list = aList;
-  this.path = aPath;
-}
-
-this.DownloadImport.prototype = {
-  /**
-   * Imports unfinished downloads from the previous SQLite storage
-   * format (supporting schemas 7 and up), to the new Download object
-   * format. Each imported download will be added to the DownloadList
-   *
-   * @return {Promise}
-   * @resolves When the operation has completed (i.e., every download
-   *           from the previous database has been read and added to
-   *           the DownloadList)
-   */
-  import() {
-    return Task.spawn(function* task_DI_import() {
-      let connection = yield Sqlite.openConnection({ path: this.path });
-
-      try {
-        let schemaVersion = yield connection.getSchemaVersion();
-        // We don't support schemas older than version 7 (from 2007)
-        // - Version 7 added the columns mimeType, preferredApplication
-        //   and preferredAction in 2007
-        // - Version 8 added the column autoResume in 2007
-        //   (if we encounter version 7 we will treat autoResume = false)
-        // - Version 9 is the last known version, which added a unique
-        //   GUID text column that is not used here
-        if (schemaVersion < 7) {
-          throw new Error("Unable to import in-progress downloads because "
-                          + "the existing profile is too old.");
-        }
-
-        let rows = yield connection.execute("SELECT * FROM moz_downloads");
-
-        for (let row of rows) {
-          try {
-            // Get the DB row data
-            let source = row.getResultByName("source");
-            let target = row.getResultByName("target");
-            let tempPath = row.getResultByName("tempPath");
-            let startTime = row.getResultByName("startTime");
-            let state = row.getResultByName("state");
-            let referrer = row.getResultByName("referrer");
-            let maxBytes = row.getResultByName("maxBytes");
-            let mimeType = row.getResultByName("mimeType");
-            let preferredApplication = row.getResultByName("preferredApplication");
-            let preferredAction = row.getResultByName("preferredAction");
-            let entityID = row.getResultByName("entityID");
-
-            let autoResume = false;
-            try {
-              autoResume = (row.getResultByName("autoResume") == 1);
-            } catch (ex) {
-              // autoResume wasn't present in schema version 7
-            }
-
-            if (!source) {
-              throw new Error("Attempted to import a row with an empty " +
-                              "source column.");
-            }
-
-            let resumeDownload = false;
-
-            switch (state) {
-              case DOWNLOAD_NOTSTARTED:
-              case DOWNLOAD_QUEUED:
-              case DOWNLOAD_DOWNLOADING:
-                resumeDownload = true;
-                break;
-
-              case DOWNLOAD_PAUSED:
-                resumeDownload = autoResume;
-                break;
-
-              default:
-                // We won't import downloads in other states
-                continue;
-            }
-
-            // Transform the data
-            let targetPath = NetUtil.newURI(target)
-                                    .QueryInterface(Ci.nsIFileURL).file.path;
-
-            let launchWhenSucceeded = (preferredAction != Ci.nsIMIMEInfo.saveToDisk);
-
-            let downloadOptions = {
-              source: {
-                url: source,
-                referrer
-              },
-              target: {
-                path: targetPath,
-                partFilePath: tempPath,
-              },
-              saver: {
-                type: "copy",
-                entityID
-              },
-              startTime: new Date(startTime / 1000),
-              totalBytes: maxBytes,
-              hasPartialData: !!tempPath,
-              tryToKeepPartialData: true,
-              launchWhenSucceeded,
-              contentType: mimeType,
-              launcherPath: preferredApplication
-            };
-
-            // Paused downloads that should not be auto-resumed are considered
-            // in a "canceled" state.
-            if (!resumeDownload) {
-              downloadOptions.canceled = true;
-            }
-
-            let download = yield Downloads.createDownload(downloadOptions);
-
-            yield this.list.add(download);
-
-            if (resumeDownload) {
-              download.start().catch(() => {});
-            } else {
-              yield download.refresh();
-            }
-
-          } catch (ex) {
-            Cu.reportError("Error importing download: " + ex);
-          }
-        }
-
-      } catch (ex) {
-        Cu.reportError(ex);
-      } finally {
-        yield connection.close();
-      }
-    }.bind(this));
-  }
-}
-
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -105,22 +105,16 @@ const Timer = Components.Constructor("@m
  *
  * For best efficiency, this value should be high enough that the input/output
  * for opening or closing the target file does not overlap with the one for
  * saving the list of downloads.
  */
 const kSaveDelayMs = 1500;
 
 /**
- * This pref indicates if we have already imported (or attempted to import)
- * the downloads database from the previous SQLite storage.
- */
-const kPrefImportedFromSqlite = "browser.download.importedFromSqlite";
-
-/**
  * List of observers to listen against
  */
 const kObserverTopics = [
   "quit-application-requested",
   "offline-requested",
   "last-pb-context-exiting",
   "last-pb-context-exited",
   "sleep_notification",
@@ -227,45 +221,17 @@ this.DownloadIntegration = {
     }
 
     this._store = new DownloadStore(list, OS.Path.join(
                                              OS.Constants.Path.profileDir,
                                              "downloads.json"));
     this._store.onsaveitem = this.shouldPersistDownload.bind(this);
 
     try {
-      if (this._importedFromSqlite) {
-        yield this._store.load();
-      } else {
-        let sqliteDBpath = OS.Path.join(OS.Constants.Path.profileDir,
-                                        "downloads.sqlite");
-
-        if (yield OS.File.exists(sqliteDBpath)) {
-          let sqliteImport = new DownloadImport(list, sqliteDBpath);
-          yield sqliteImport.import();
-
-          let importCount = (yield list.getAll()).length;
-          if (importCount > 0) {
-            try {
-              yield this._store.save();
-            } catch (ex) { }
-          }
-
-          // No need to wait for the file removal.
-          OS.File.remove(sqliteDBpath).then(null, Cu.reportError);
-        }
-
-        Services.prefs.setBoolPref(kPrefImportedFromSqlite, true);
-
-        // Don't even report error here because this file is pre Firefox 3
-        // and most likely doesn't exist.
-        OS.File.remove(OS.Path.join(OS.Constants.Path.profileDir,
-                                    "downloads.rdf")).catch(() => {});
-
-      }
+      yield this._store.load();
     } catch (ex) {
       Cu.reportError(ex);
     }
 
     // Add the view used for detecting changes to downloads to be persisted.
     // We must do this after the list of persistent downloads has been loaded,
     // even if the load operation failed. We wait for a complete initialization
     // so other callers cannot modify the list without being detected. The
@@ -869,30 +835,16 @@ this.DownloadIntegration = {
    * @resolves When _store.save() completes.
    */
   forceSave() {
     if (this._store) {
       return this._store.save();
     }
     return Promise.resolve();
   },
-
-  /**
-   * Checks if we have already imported (or attempted to import)
-   * the downloads database from the previous SQLite storage.
-   *
-   * @return boolean True if we the previous DB was imported.
-   */
-  get _importedFromSqlite() {
-    try {
-      return Services.prefs.getBoolPref(kPrefImportedFromSqlite);
-    } catch (ex) {
-      return false;
-    }
-  },
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadObserver
 
 this.DownloadObserver = {
   /**
    * Flag to determine if the observers have been added previously.
--- a/toolkit/components/jsdownloads/src/moz.build
+++ b/toolkit/components/jsdownloads/src/moz.build
@@ -10,17 +10,16 @@ SOURCES += [
 
 EXTRA_COMPONENTS += [
     'DownloadLegacy.js',
     'Downloads.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'DownloadCore.jsm',
-    'DownloadImport.jsm',
     'DownloadList.jsm',
     'Downloads.jsm',
     'DownloadStore.jsm',
     'DownloadUIHelper.jsm',
 ]
 
 EXTRA_PP_JS_MODULES += [
     'DownloadIntegration.jsm',
deleted file mode 100644
--- a/toolkit/components/jsdownloads/test/unit/test_DownloadImport.js
+++ /dev/null
@@ -1,699 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Tests the DownloadImport object.
- */
-
-"use strict";
-
-// Globals
-
-XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
-                                  "resource://gre/modules/Sqlite.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DownloadImport",
-                                  "resource://gre/modules/DownloadImport.jsm");
-
-// Importable states
-const DOWNLOAD_NOTSTARTED = -1;
-const DOWNLOAD_DOWNLOADING = 0;
-const DOWNLOAD_PAUSED = 4;
-const DOWNLOAD_QUEUED = 5;
-
-// Non importable states
-const DOWNLOAD_FAILED = 2;
-const DOWNLOAD_CANCELED = 3;
-const DOWNLOAD_BLOCKED_PARENTAL = 6;
-const DOWNLOAD_SCANNING = 7;
-const DOWNLOAD_DIRTY = 8;
-const DOWNLOAD_BLOCKED_POLICY = 9;
-
-// The TEST_DATA_TAINTED const is a version of TEST_DATA_SHORT in which the
-// beginning of the data was changed (with the TEST_DATA_REPLACEMENT value).
-// We use this to test that the entityID is properly imported and the download
-// can be resumed from where it was paused.
-// For simplification purposes, the test requires that TEST_DATA_SHORT and
-// TEST_DATA_TAINTED have the same length.
-const TEST_DATA_REPLACEMENT = "-changed- ";
-const TEST_DATA_TAINTED = TEST_DATA_REPLACEMENT +
-                          TEST_DATA_SHORT.substr(TEST_DATA_REPLACEMENT.length);
-const TEST_DATA_LENGTH = TEST_DATA_SHORT.length;
-
-// The length of the partial file that we'll write to disk as an existing
-// ongoing download.
-const TEST_DATA_PARTIAL_LENGTH = TEST_DATA_REPLACEMENT.length;
-
-// The value of the "maxBytes" column stored in the DB about the downloads.
-// It's intentionally different than TEST_DATA_LENGTH to test that each value
-// is seen when expected.
-const MAXBYTES_IN_DB = TEST_DATA_LENGTH - 10;
-
-var gDownloadsRowToImport;
-var gDownloadsRowNonImportable;
-
-/**
- * Creates a database with an empty moz_downloads table and leaves an
- * open connection to it.
- *
- * @param aPath
- *        String containing the path of the database file to be created.
- * @param aSchemaVersion
- *        Number with the version of the database schema to set.
- *
- * @return {Promise}
- * @resolves The open connection to the database.
- * @rejects If an error occurred during the database creation.
- */
-function promiseEmptyDatabaseConnection({aPath, aSchemaVersion}) {
-  return Task.spawn(function* () {
-    let connection = yield Sqlite.openConnection({ path: aPath });
-
-    yield connection.execute("CREATE TABLE moz_downloads ("
-                             + "id INTEGER PRIMARY KEY,"
-                             + "name TEXT,"
-                             + "source TEXT,"
-                             + "target TEXT,"
-                             + "tempPath TEXT,"
-                             + "startTime INTEGER,"
-                             + "endTime INTEGER,"
-                             + "state INTEGER,"
-                             + "referrer TEXT,"
-                             + "entityID TEXT,"
-                             + "currBytes INTEGER NOT NULL DEFAULT 0,"
-                             + "maxBytes INTEGER NOT NULL DEFAULT -1,"
-                             + "mimeType TEXT,"
-                             + "preferredApplication TEXT,"
-                             + "preferredAction INTEGER NOT NULL DEFAULT 0,"
-                             + "autoResume INTEGER NOT NULL DEFAULT 0,"
-                             + "guid TEXT)");
-
-    yield connection.setSchemaVersion(aSchemaVersion);
-
-    return connection;
-  });
-}
-
-/**
- * Inserts a new entry in the database with the given columns' values.
- *
- * @param aConnection
- *        The database connection.
- * @param aDownloadRow
- *        An object representing the values for each column of the row
- *        being inserted.
- *
- * @return {Promise}
- * @resolves When the operation completes.
- * @rejects If there's an error inserting the row.
- */
-function promiseInsertRow(aConnection, aDownloadRow) {
-  // We can't use the aDownloadRow obj directly in the execute statement
-  // because the obj bind code in Sqlite.jsm doesn't allow objects
-  // with extra properties beyond those being binded. So we might as well
-  // use an array as it is simpler.
-  let values = [
-    aDownloadRow.source, aDownloadRow.target, aDownloadRow.tempPath,
-    aDownloadRow.startTime.getTime() * 1000, aDownloadRow.state,
-    aDownloadRow.referrer, aDownloadRow.entityID, aDownloadRow.maxBytes,
-    aDownloadRow.mimeType, aDownloadRow.preferredApplication,
-    aDownloadRow.preferredAction, aDownloadRow.autoResume
-  ];
-
-  return aConnection.execute("INSERT INTO moz_downloads ("
-                            + "name, source, target, tempPath, startTime,"
-                            + "endTime, state, referrer, entityID, currBytes,"
-                            + "maxBytes, mimeType, preferredApplication,"
-                            + "preferredAction, autoResume, guid)"
-                            + "VALUES ("
-                            + "'', ?, ?, ?, ?, " // name,
-                            + "0, ?, ?, ?, 0, "  // endTime, currBytes
-                            + " ?, ?, ?, "       //
-                            + " ?, ?, '')",      // and guid are not imported
-                            values);
-}
-
-/**
- * Retrieves the number of rows in the moz_downloads table of the
- * database.
- *
- * @param aConnection
- *        The database connection.
- *
- * @return {Promise}
- * @resolves With the number of rows.
- * @rejects Never.
- */
-function promiseTableCount(aConnection) {
-  return aConnection.execute("SELECT COUNT(*) FROM moz_downloads")
-                    .then(res => res[0].getResultByName("COUNT(*)"))
-                    .then(null, Cu.reportError);
-}
-
-/**
- * Briefly opens a network channel to a given URL to retrieve
- * the entityID of this url, as generated by the network code.
- *
- * @param aUrl
- *        The URL to retrieve the entityID.
- *
- * @return {Promise}
- * @resolves The EntityID of the given URL.
- * @rejects When there's a problem accessing the URL.
- */
-function promiseEntityID(aUrl) {
-  let deferred = Promise.defer();
-  let entityID = "";
-  let channel = NetUtil.newChannel({
-    uri: NetUtil.newURI(aUrl),
-    loadUsingSystemPrincipal: true
-  });
-
-  channel.asyncOpen2({
-    onStartRequest(aRequest) {
-      if (aRequest instanceof Ci.nsIResumableChannel) {
-        entityID = aRequest.entityID;
-      }
-      aRequest.cancel(Cr.NS_BINDING_ABORTED);
-    },
-
-    onStopRequest(aRequest, aContext, aStatusCode) {
-      if (aStatusCode == Cr.NS_BINDING_ABORTED) {
-        deferred.resolve(entityID);
-      } else {
-        deferred.reject("Unexpected status code received");
-      }
-    },
-
-    onDataAvailable() {}
-  });
-
-  return deferred.promise;
-}
-
-/**
- * Gets a file path to a temporary writeable download target, in the
- * correct format as expected to be stored in the downloads database,
- * which is file:///absolute/path/to/file
- *
- * @param aLeafName
- *        A hint leaf name for the file.
- *
- * @return String The path to the download target.
- */
-function getDownloadTarget(aLeafName) {
-  return NetUtil.newURI(getTempFile(aLeafName)).spec;
-}
-
-/**
- * Generates a temporary partial file to use as an in-progress
- * download. The file is written to disk with a part of the total expected
- * download content pre-written.
- *
- * @param aLeafName
- *        A hint leaf name for the file.
- * @param aTainted
- *        A boolean value. When true, the partial content of the file
- *        will be different from the expected content of the original source
- *        file. See the declaration of TEST_DATA_TAINTED for more information.
- *
- * @return {Promise}
- * @resolves When the operation completes, and returns a string with the path
- *           to the generated file.
- * @rejects If there's an error writing the file.
- */
-function getPartialFile(aLeafName, aTainted = false) {
-  let tempDownload = getTempFile(aLeafName);
-  let partialContent = aTainted
-                     ? TEST_DATA_TAINTED.substr(0, TEST_DATA_PARTIAL_LENGTH)
-                     : TEST_DATA_SHORT.substr(0, TEST_DATA_PARTIAL_LENGTH);
-
-  return OS.File.writeAtomic(tempDownload.path, partialContent,
-                             { tmpPath: tempDownload.path + ".tmp",
-                               flush: true })
-                .then(() => tempDownload.path);
-}
-
-/**
- * Generates a Date object to be used as the startTime for the download rows
- * in the DB. A date that is obviously different from the current time is
- * generated to make sure this stored data and a `new Date()` can't collide.
- *
- * @param aOffset
- *        A offset from the base generated date is used to differentiate each
- *        row in the database.
- *
- * @return A Date object.
- */
-function getStartTime(aOffset) {
-  return new Date(1000000 + (aOffset * 10000));
-}
-
-/**
- * Performs various checks on an imported Download object to make sure
- * all properties are properly set as expected from the import procedure.
- *
- * @param aDownload
- *        The Download object to be checked.
- * @param aDownloadRow
- *        An object that represents a row from the original database table,
- *        with extra properties describing expected values that are not
- *        explictly part of the database.
- *
- * @return {Promise}
- * @resolves When the operation completes
- * @rejects Never
- */
-function checkDownload(aDownload, aDownloadRow) {
-  return Task.spawn(function*() {
-    do_check_eq(aDownload.source.url, aDownloadRow.source);
-    do_check_eq(aDownload.source.referrer, aDownloadRow.referrer);
-
-    do_check_eq(aDownload.target.path,
-                NetUtil.newURI(aDownloadRow.target)
-                       .QueryInterface(Ci.nsIFileURL).file.path);
-
-    do_check_eq(aDownload.target.partFilePath, aDownloadRow.tempPath);
-
-    if (aDownloadRow.expectedResume) {
-      do_check_true(!aDownload.stopped || aDownload.succeeded);
-      yield promiseDownloadStopped(aDownload);
-
-      do_check_true(aDownload.succeeded);
-      do_check_eq(aDownload.progress, 100);
-      // If the download has resumed, a new startTime will be set.
-      // By calling toJSON we're also testing that startTime is a Date object.
-      do_check_neq(aDownload.startTime.toJSON(),
-                   aDownloadRow.startTime.toJSON());
-    } else {
-      do_check_false(aDownload.succeeded);
-      do_check_eq(aDownload.startTime.toJSON(),
-                  aDownloadRow.startTime.toJSON());
-    }
-
-    do_check_eq(aDownload.stopped, true);
-
-    let serializedSaver = aDownload.saver.toSerializable();
-    if (typeof(serializedSaver) == "object") {
-      do_check_eq(serializedSaver.type, "copy");
-    } else {
-      do_check_eq(serializedSaver, "copy");
-    }
-
-    if (aDownloadRow.entityID) {
-      do_check_eq(aDownload.saver.entityID, aDownloadRow.entityID);
-    }
-
-    do_check_eq(aDownload.currentBytes, aDownloadRow.expectedCurrentBytes);
-    do_check_eq(aDownload.totalBytes, aDownloadRow.expectedTotalBytes);
-
-    if (aDownloadRow.expectedContent) {
-      let fileToCheck = aDownloadRow.expectedResume
-                        ? aDownload.target.path
-                        : aDownload.target.partFilePath;
-      yield promiseVerifyContents(fileToCheck, aDownloadRow.expectedContent);
-    }
-
-    do_check_eq(aDownload.contentType, aDownloadRow.expectedContentType);
-    do_check_eq(aDownload.launcherPath, aDownloadRow.preferredApplication);
-
-    do_check_eq(aDownload.launchWhenSucceeded,
-                aDownloadRow.preferredAction != Ci.nsIMIMEInfo.saveToDisk);
-  });
-}
-
-// Preparation tasks
-
-/**
- * Prepares the list of downloads to be added to the database that should
- * be imported by the import procedure.
- */
-add_task(function* prepareDownloadsToImport() {
-
-  let sourceUrl = httpUrl("source.txt");
-  let sourceEntityId = yield promiseEntityID(sourceUrl);
-
-  gDownloadsRowToImport = [
-    // Paused download with autoResume and a partial file. By
-    // setting the correct entityID the download can resume from
-    // where it stopped, and to test that this works properly we
-    // intentionally set different data in the beginning of the
-    // partial file to make sure it was not replaced.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress1.txt"),
-      tempPath: yield getPartialFile("inprogress1.txt.part", true),
-      startTime: getStartTime(1),
-      state: DOWNLOAD_PAUSED,
-      referrer: httpUrl("referrer1"),
-      entityID: sourceEntityId,
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType1",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication1",
-      autoResume: 1,
-
-      // Even though the information stored in the DB said
-      // maxBytes was MAXBYTES_IN_DB, the download turned out to be
-      // a different length. Here we make sure the totalBytes property
-      // was correctly set with the actual value. The same consideration
-      // applies to the contentType.
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_TAINTED,
-    },
-
-    // Paused download with autoResume and a partial file,
-    // but missing entityID. This means that the download will
-    // start from beginning, and the entire original content of the
-    // source file should replace the different data that was stored
-    // in the partial file.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress2.txt"),
-      tempPath: yield getPartialFile("inprogress2.txt.part", true),
-      startTime: getStartTime(2),
-      state: DOWNLOAD_PAUSED,
-      referrer: httpUrl("referrer2"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType2",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication2",
-      autoResume: 1,
-
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_SHORT
-    },
-
-    // Paused download with no autoResume and a partial file.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress3.txt"),
-      tempPath: yield getPartialFile("inprogress3.txt.part"),
-      startTime: getStartTime(3),
-      state: DOWNLOAD_PAUSED,
-      referrer: httpUrl("referrer3"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType3",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication3",
-      autoResume: 0,
-
-      // Since this download has not been resumed, the actual data
-      // about its total size and content type is not known.
-      // Therefore, we're going by the information imported from the DB.
-      expectedCurrentBytes: TEST_DATA_PARTIAL_LENGTH,
-      expectedTotalBytes: MAXBYTES_IN_DB,
-      expectedResume: false,
-      expectedContentType: "mimeType3",
-      expectedContent: TEST_DATA_SHORT.substr(0, TEST_DATA_PARTIAL_LENGTH),
-    },
-
-    // Paused download with autoResume and no partial file.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress4.txt"),
-      tempPath: "",
-      startTime: getStartTime(4),
-      state: DOWNLOAD_PAUSED,
-      referrer: httpUrl("referrer4"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "text/plain",
-      preferredAction: Ci.nsIMIMEInfo.useHelperApp,
-      preferredApplication: "prerredApplication4",
-      autoResume: 1,
-
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_SHORT
-    },
-
-    // Paused download with no autoResume and no partial file.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress5.txt"),
-      tempPath: "",
-      startTime: getStartTime(5),
-      state: DOWNLOAD_PAUSED,
-      referrer: httpUrl("referrer4"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "text/plain",
-      preferredAction: Ci.nsIMIMEInfo.useSystemDefault,
-      preferredApplication: "prerredApplication5",
-      autoResume: 0,
-
-      expectedCurrentBytes: 0,
-      expectedTotalBytes: MAXBYTES_IN_DB,
-      expectedResume: false,
-      expectedContentType: "text/plain",
-    },
-
-    // Queued download with no autoResume and no partial file.
-    // Even though autoResume=0, queued downloads always autoResume.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress6.txt"),
-      tempPath: "",
-      startTime: getStartTime(6),
-      state: DOWNLOAD_QUEUED,
-      referrer: httpUrl("referrer6"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "text/plain",
-      preferredAction: Ci.nsIMIMEInfo.useHelperApp,
-      preferredApplication: "prerredApplication6",
-      autoResume: 0,
-
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_SHORT
-    },
-
-    // Notstarted download with no autoResume and no partial file.
-    // Even though autoResume=0, notstarted downloads always autoResume.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress7.txt"),
-      tempPath: "",
-      startTime: getStartTime(7),
-      state: DOWNLOAD_NOTSTARTED,
-      referrer: httpUrl("referrer7"),
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "text/plain",
-      preferredAction: Ci.nsIMIMEInfo.useHelperApp,
-      preferredApplication: "prerredApplication7",
-      autoResume: 0,
-
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_SHORT
-    },
-
-    // Downloading download with no autoResume and a partial file.
-    // Even though autoResume=0, downloading downloads always autoResume.
-    {
-      source: sourceUrl,
-      target: getDownloadTarget("inprogress8.txt"),
-      tempPath: yield getPartialFile("inprogress8.txt.part", true),
-      startTime: getStartTime(8),
-      state: DOWNLOAD_DOWNLOADING,
-      referrer: httpUrl("referrer8"),
-      entityID: sourceEntityId,
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "text/plain",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication8",
-      autoResume: 0,
-
-      expectedCurrentBytes: TEST_DATA_LENGTH,
-      expectedTotalBytes: TEST_DATA_LENGTH,
-      expectedResume: true,
-      expectedContentType: "text/plain",
-      expectedContent: TEST_DATA_TAINTED
-    },
-  ];
-});
-
-/**
- * Prepares the list of downloads to be added to the database that should
- * *not* be imported by the import procedure.
- */
-add_task(function* prepareNonImportableDownloads() {
-  gDownloadsRowNonImportable = [
-    // Download with no source (should never happen in normal circumstances).
-    {
-      source: "",
-      target: "nonimportable1.txt",
-      tempPath: "",
-      startTime: getStartTime(1),
-      state: DOWNLOAD_PAUSED,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType1",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication1",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_FAILED
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable2.txt",
-      tempPath: "",
-      startTime: getStartTime(2),
-      state: DOWNLOAD_FAILED,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType2",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication2",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_CANCELED
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable3.txt",
-      tempPath: "",
-      startTime: getStartTime(3),
-      state: DOWNLOAD_CANCELED,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType3",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication3",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_BLOCKED_PARENTAL
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable4.txt",
-      tempPath: "",
-      startTime: getStartTime(4),
-      state: DOWNLOAD_BLOCKED_PARENTAL,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType4",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication4",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_SCANNING
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable5.txt",
-      tempPath: "",
-      startTime: getStartTime(5),
-      state: DOWNLOAD_SCANNING,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType5",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication5",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_DIRTY
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable6.txt",
-      tempPath: "",
-      startTime: getStartTime(6),
-      state: DOWNLOAD_DIRTY,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType6",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication6",
-      autoResume: 1
-    },
-
-    // state = DOWNLOAD_BLOCKED_POLICY
-    {
-      source: httpUrl("source.txt"),
-      target: "nonimportable7.txt",
-      tempPath: "",
-      startTime: getStartTime(7),
-      state: DOWNLOAD_BLOCKED_POLICY,
-      referrer: "",
-      entityID: "",
-      maxBytes: MAXBYTES_IN_DB,
-      mimeType: "mimeType7",
-      preferredAction: Ci.nsIMIMEInfo.saveToDisk,
-      preferredApplication: "prerredApplication7",
-      autoResume: 1
-    },
-  ];
-});
-
-// Test
-
-/**
- * Creates a temporary Sqlite database with download data and perform an
- * import of that data to the new Downloads API to verify that the import
- * worked correctly.
- */
-add_task(function* test_downloadImport() {
-  let connection = null;
-  let downloadsSqlite = getTempFile("downloads.sqlite").path;
-
-  try {
-    // Set up the database.
-    connection = yield promiseEmptyDatabaseConnection({
-      aPath: downloadsSqlite,
-      aSchemaVersion: 9
-    });
-
-    // Insert both the importable and non-importable
-    // downloads together.
-    for (let downloadRow of gDownloadsRowToImport) {
-      yield promiseInsertRow(connection, downloadRow);
-    }
-
-    for (let downloadRow of gDownloadsRowNonImportable) {
-      yield promiseInsertRow(connection, downloadRow);
-    }
-
-    // Check that every item was inserted.
-    do_check_eq((yield promiseTableCount(connection)),
-                gDownloadsRowToImport.length +
-                gDownloadsRowNonImportable.length);
-  } finally {
-    // Close the connection so that DownloadImport can open it.
-    yield connection.close();
-  }
-
-  // Import items.
-  let list = yield promiseNewList(false);
-  yield new DownloadImport(list, downloadsSqlite).import();
-  let items = yield list.getAll();
-
-  do_check_eq(items.length, gDownloadsRowToImport.length);
-
-  for (let i = 0; i < gDownloadsRowToImport.length; i++) {
-    yield checkDownload(items[i], gDownloadsRowToImport[i]);
-  }
-})
--- a/toolkit/components/jsdownloads/test/unit/xpcshell.ini
+++ b/toolkit/components/jsdownloads/test/unit/xpcshell.ini
@@ -3,17 +3,16 @@ head = head.js
 skip-if = toolkit == 'android'
 
 # Note: The "tail.js" file is not defined in the "tail" key because it calls
 #       the "add_test_task" function, that does not work properly in tail files.
 support-files =
   common_test_Download.js
 
 [test_DownloadCore.js]
-[test_DownloadImport.js]
 [test_DownloadIntegration.js]
 [test_DownloadLegacy.js]
 [test_DownloadList.js]
 [test_Downloads.js]
 [test_DownloadStore.js]
 [test_PrivateTemp.js]
 # coverage flag is for bug 1336730
 skip-if = (os != 'linux' || coverage)
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -2522,17 +2522,16 @@ struct TrackedDBEntry
 // A whitelist of database names. If the database name exactly matches one of
 // these then its SQL statements will always be recorded.
 static constexpr TrackedDBEntry kTrackedDBs[] = {
   // IndexedDB for about:home, see aboutHome.js
   TRACKEDDB_ENTRY("818200132aebmoouht.sqlite"),
   TRACKEDDB_ENTRY("addons.sqlite"),
   TRACKEDDB_ENTRY("content-prefs.sqlite"),
   TRACKEDDB_ENTRY("cookies.sqlite"),
-  TRACKEDDB_ENTRY("downloads.sqlite"),
   TRACKEDDB_ENTRY("extensions.sqlite"),
   TRACKEDDB_ENTRY("favicons.sqlite"),
   TRACKEDDB_ENTRY("formhistory.sqlite"),
   TRACKEDDB_ENTRY("index.sqlite"),
   TRACKEDDB_ENTRY("netpredictions.sqlite"),
   TRACKEDDB_ENTRY("permissions.sqlite"),
   TRACKEDDB_ENTRY("places.sqlite"),
   TRACKEDDB_ENTRY("reading-list.sqlite"),
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -24,17 +24,16 @@ try {
 // under the "accessibility.*" branch.
 const PREFS_WHITELIST = [
   "accessibility.",
   "apz.",
   "browser.cache.",
   "browser.display.",
   "browser.download.folderList",
   "browser.download.hide_plugins_without_extensions",
-  "browser.download.importedFromSqlite",
   "browser.download.lastDir.savePerSite",
   "browser.download.manager.addToRecentDocs",
   "browser.download.manager.alertOnEXEOpen",
   "browser.download.manager.resumeOnWakeDelay",
   "browser.download.preferred.",
   "browser.download.useDownloadDir",
   "browser.fixup.",
   "browser.history_expire_",