toolkit/components/jsdownloads/src/DownloadImport.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 "use strict";
     9 this.EXPORTED_SYMBOLS = [
    10   "DownloadImport",
    11 ];
    13 ////////////////////////////////////////////////////////////////////////////////
    14 //// Globals
    16 const Cc = Components.classes;
    17 const Ci = Components.interfaces;
    18 const Cu = Components.utils;
    19 const Cr = Components.results;
    21 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    23 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
    24                                   "resource://gre/modules/Downloads.jsm");
    25 XPCOMUtils.defineLazyModuleGetter(this, "OS",
    26                                   "resource://gre/modules/osfile.jsm")
    27 XPCOMUtils.defineLazyModuleGetter(this, "Task",
    28                                   "resource://gre/modules/Task.jsm");
    29 XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
    30                                   "resource://gre/modules/Sqlite.jsm");
    31 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
    32                                   "resource://gre/modules/NetUtil.jsm");
    34 /**
    35  * These values come from the previous interface
    36  * nsIDownloadManager, which has now been deprecated.
    37  * These are the only types of download states that
    38  * we will import.
    39  */
    40 const DOWNLOAD_NOTSTARTED = -1;
    41 const DOWNLOAD_DOWNLOADING = 0;
    42 const DOWNLOAD_PAUSED = 4;
    43 const DOWNLOAD_QUEUED = 5;
    45 ////////////////////////////////////////////////////////////////////////////////
    46 //// DownloadImport
    48 /**
    49  * Provides an object that has a method to import downloads
    50  * from the previous SQLite storage format.
    51  *
    52  * @param aList   A DownloadList where each successfully
    53  *                imported download will be added.
    54  * @param aPath   The path to the database file.
    55  */
    56 this.DownloadImport = function (aList, aPath)
    57 {
    58   this.list = aList;
    59   this.path = aPath;
    60 }
    62 this.DownloadImport.prototype = {
    63   /**
    64    * Imports unfinished downloads from the previous SQLite storage
    65    * format (supporting schemas 7 and up), to the new Download object
    66    * format. Each imported download will be added to the DownloadList
    67    *
    68    * @return {Promise}
    69    * @resolves When the operation has completed (i.e., every download
    70    *           from the previous database has been read and added to
    71    *           the DownloadList)
    72    */
    73   import: function () {
    74     return Task.spawn(function task_DI_import() {
    75       let connection = yield Sqlite.openConnection({ path: this.path });
    77       try {
    78         let schemaVersion = yield connection.getSchemaVersion();
    79         // We don't support schemas older than version 7 (from 2007)
    80         // - Version 7 added the columns mimeType, preferredApplication
    81         //   and preferredAction in 2007
    82         // - Version 8 added the column autoResume in 2007
    83         //   (if we encounter version 7 we will treat autoResume = false)
    84         // - Version 9 is the last known version, which added a unique
    85         //   GUID text column that is not used here
    86         if (schemaVersion < 7) {
    87           throw new Error("Unable to import in-progress downloads because "
    88                           + "the existing profile is too old.");
    89         }
    91         let rows = yield connection.execute("SELECT * FROM moz_downloads");
    93         for (let row of rows) {
    94           try {
    95             // Get the DB row data
    96             let source = row.getResultByName("source");
    97             let target = row.getResultByName("target");
    98             let tempPath = row.getResultByName("tempPath");
    99             let startTime = row.getResultByName("startTime");
   100             let state = row.getResultByName("state");
   101             let referrer = row.getResultByName("referrer");
   102             let maxBytes = row.getResultByName("maxBytes");
   103             let mimeType = row.getResultByName("mimeType");
   104             let preferredApplication = row.getResultByName("preferredApplication");
   105             let preferredAction = row.getResultByName("preferredAction");
   106             let entityID = row.getResultByName("entityID");
   108             let autoResume = false;
   109             try {
   110               autoResume = (row.getResultByName("autoResume") == 1);
   111             } catch (ex) {
   112               // autoResume wasn't present in schema version 7
   113             }
   115             if (!source) {
   116               throw new Error("Attempted to import a row with an empty " +
   117                               "source column.");
   118             }
   120             let resumeDownload = false;
   122             switch (state) {
   123               case DOWNLOAD_NOTSTARTED:
   124               case DOWNLOAD_QUEUED:
   125               case DOWNLOAD_DOWNLOADING:
   126                 resumeDownload = true;
   127                 break;
   129               case DOWNLOAD_PAUSED:
   130                 resumeDownload = autoResume;
   131                 break;
   133               default:
   134                 // We won't import downloads in other states
   135                 continue;
   136             }
   138             // Transform the data
   139             let targetPath = NetUtil.newURI(target)
   140                                     .QueryInterface(Ci.nsIFileURL).file.path;
   142             let launchWhenSucceeded = (preferredAction != Ci.nsIMIMEInfo.saveToDisk);
   144             let downloadOptions = {
   145               source: {
   146                 url: source,
   147                 referrer: referrer
   148               },
   149               target: {
   150                 path: targetPath,
   151                 partFilePath: tempPath,
   152               },
   153               saver: {
   154                 type: "copy",
   155                 entityID: entityID
   156               },
   157               startTime: new Date(startTime / 1000),
   158               totalBytes: maxBytes,
   159               hasPartialData: !!tempPath,
   160               tryToKeepPartialData: true,
   161               launchWhenSucceeded: launchWhenSucceeded,
   162               contentType: mimeType,
   163               launcherPath: preferredApplication
   164             };
   166             // Paused downloads that should not be auto-resumed are considered
   167             // in a "canceled" state.
   168             if (!resumeDownload) {
   169               downloadOptions.canceled = true;
   170             }
   172             let download = yield Downloads.createDownload(downloadOptions);
   174             yield this.list.add(download);
   176             if (resumeDownload) {
   177               download.start();
   178             } else {
   179               yield download.refresh();
   180             }
   182           } catch (ex) {
   183             Cu.reportError("Error importing download: " + ex);
   184           }
   185         }
   187       } catch (ex) {
   188         Cu.reportError(ex);
   189       } finally {
   190         yield connection.close();
   191       }
   192     }.bind(this));
   193   }
   194 }

mercurial