toolkit/mozapps/downloads/DownloadLastDir.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: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * The behavior implemented by gDownloadLastDir is documented here.
     8  *
     9  * In normal browsing sessions, gDownloadLastDir uses the browser.download.lastDir
    10  * preference to store the last used download directory. The first time the user
    11  * switches into the private browsing mode, the last download directory is
    12  * preserved to the pref value, but if the user switches to another directory
    13  * during the private browsing mode, that directory is not stored in the pref,
    14  * and will be merely kept in memory.  When leaving the private browsing mode,
    15  * this in-memory value will be discarded, and the last download directory
    16  * will be reverted to the pref value.
    17  *
    18  * Both the pref and the in-memory value will be cleared when clearing the
    19  * browsing history.  This effectively changes the last download directory
    20  * to the default download directory on each platform.
    21  *
    22  * If passed a URI, the last used directory is also stored with that URI in the
    23  * content preferences database. This can be disabled by setting the pref
    24  * browser.download.lastDir.savePerSite to false.
    25  */
    27 const LAST_DIR_PREF = "browser.download.lastDir";
    28 const SAVE_PER_SITE_PREF = LAST_DIR_PREF + ".savePerSite";
    29 const nsIFile = Components.interfaces.nsIFile;
    31 this.EXPORTED_SYMBOLS = [ "DownloadLastDir" ];
    33 Components.utils.import("resource://gre/modules/Services.jsm");
    34 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
    36 let observer = {
    37   QueryInterface: function (aIID) {
    38     if (aIID.equals(Components.interfaces.nsIObserver) ||
    39         aIID.equals(Components.interfaces.nsISupports) ||
    40         aIID.equals(Components.interfaces.nsISupportsWeakReference))
    41       return this;
    42     throw Components.results.NS_NOINTERFACE;
    43   },
    44   observe: function (aSubject, aTopic, aData) {
    45     switch (aTopic) {
    46       case "last-pb-context-exited":
    47         gDownloadLastDirFile = null;
    48         break;
    49       case "browser:purge-session-history":
    50         gDownloadLastDirFile = null;
    51         if (Services.prefs.prefHasUserValue(LAST_DIR_PREF))
    52           Services.prefs.clearUserPref(LAST_DIR_PREF);
    53         // Ensure that purging session history causes both the session-only PB cache
    54         // and persistent prefs to be cleared.
    55         let cps2 = Components.classes["@mozilla.org/content-pref/service;1"].
    56                      getService(Components.interfaces.nsIContentPrefService2);
    58         cps2.removeByName(LAST_DIR_PREF, {usePrivateBrowsing: false});
    59         cps2.removeByName(LAST_DIR_PREF, {usePrivateBrowsing: true});
    60         break;
    61     }
    62   }
    63 };
    65 let os = Components.classes["@mozilla.org/observer-service;1"]
    66                    .getService(Components.interfaces.nsIObserverService);
    67 os.addObserver(observer, "last-pb-context-exited", true);
    68 os.addObserver(observer, "browser:purge-session-history", true);
    70 function readLastDirPref() {
    71   try {
    72     return Services.prefs.getComplexValue(LAST_DIR_PREF, nsIFile);
    73   }
    74   catch (e) {
    75     return null;
    76   }
    77 }
    79 function isContentPrefEnabled() {
    80   try {
    81     return Services.prefs.getBoolPref(SAVE_PER_SITE_PREF);
    82   }
    83   catch (e) {
    84     return true;
    85   }
    86 }
    88 let gDownloadLastDirFile = readLastDirPref();
    90 this.DownloadLastDir = function DownloadLastDir(aWindow) {
    91   this.window = aWindow;
    92 }
    94 DownloadLastDir.prototype = {
    95   isPrivate: function DownloadLastDir_isPrivate() {
    96     return PrivateBrowsingUtils.isWindowPrivate(this.window);
    97   },
    98   // compat shims
    99   get file() this._getLastFile(),
   100   set file(val) { this.setFile(null, val); },
   101   cleanupPrivateFile: function () {
   102     gDownloadLastDirFile = null;
   103   },
   104   // This function is now deprecated as it uses the sync nsIContentPrefService
   105   // interface. New consumers should use the getFileAsync function.
   106   getFile: function (aURI) {
   107     let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
   108     Deprecated.warning("DownloadLastDir.getFile is deprecated. Please use getFileAsync instead.",
   109                        "https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/DownloadLastDir.jsm",
   110                        Components.stack.caller);
   112     if (aURI && isContentPrefEnabled()) {
   113       let loadContext = this.window
   114                             .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   115                             .getInterface(Components.interfaces.nsIWebNavigation)
   116                             .QueryInterface(Components.interfaces.nsILoadContext);
   117       let lastDir = Services.contentPrefs.getPref(aURI, LAST_DIR_PREF, loadContext);
   118       if (lastDir) {
   119         var lastDirFile = Components.classes["@mozilla.org/file/local;1"]
   120                                     .createInstance(Components.interfaces.nsIFile);
   121         lastDirFile.initWithPath(lastDir);
   122         return lastDirFile;
   123       }
   124     }
   125     return this._getLastFile();
   126   },
   128   _getLastFile: function () {
   129     if (gDownloadLastDirFile && !gDownloadLastDirFile.exists())
   130       gDownloadLastDirFile = null;
   132     if (this.isPrivate()) {
   133       if (!gDownloadLastDirFile)
   134         gDownloadLastDirFile = readLastDirPref();
   135       return gDownloadLastDirFile;
   136     }
   137     return readLastDirPref();
   138   },
   140   getFileAsync: function(aURI, aCallback) {
   141     let plainPrefFile = this._getLastFile();
   142     if (!aURI || !isContentPrefEnabled()) {
   143       Services.tm.mainThread.dispatch(function() aCallback(plainPrefFile),
   144                                       Components.interfaces.nsIThread.DISPATCH_NORMAL);
   145       return;
   146     }
   148     let uri = aURI instanceof Components.interfaces.nsIURI ? aURI.spec : aURI;
   149     let cps2 = Components.classes["@mozilla.org/content-pref/service;1"]
   150                          .getService(Components.interfaces.nsIContentPrefService2);
   151     let loadContext = this.window
   152                           .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   153                           .getInterface(Components.interfaces.nsIWebNavigation)
   154                           .QueryInterface(Components.interfaces.nsILoadContext);
   155     let result = null;
   156     cps2.getByDomainAndName(uri, LAST_DIR_PREF, loadContext, {
   157       handleResult: function(aResult) result = aResult,
   158       handleCompletion: function(aReason) {
   159         let file = plainPrefFile;
   160         if (aReason == Components.interfaces.nsIContentPrefCallback2.COMPLETE_OK &&
   161            result instanceof Components.interfaces.nsIContentPref) {
   162           file = Components.classes["@mozilla.org/file/local;1"]
   163                            .createInstance(Components.interfaces.nsIFile);
   164           file.initWithPath(result.value);
   165         }
   166         aCallback(file);
   167       }
   168     });
   169   },
   171   setFile: function (aURI, aFile) {
   172     if (aURI && isContentPrefEnabled()) {
   173       let uri = aURI instanceof Components.interfaces.nsIURI ? aURI.spec : aURI;
   174       let cps2 = Components.classes["@mozilla.org/content-pref/service;1"]
   175                            .getService(Components.interfaces.nsIContentPrefService2);
   176       let loadContext = this.window
   177                             .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   178                             .getInterface(Components.interfaces.nsIWebNavigation)
   179                             .QueryInterface(Components.interfaces.nsILoadContext);
   180       if (aFile instanceof Components.interfaces.nsIFile)
   181         cps2.set(uri, LAST_DIR_PREF, aFile.path, loadContext);
   182       else
   183         cps2.removeByDomainAndName(uri, LAST_DIR_PREF, loadContext);
   184     }
   185     if (this.isPrivate()) {
   186       if (aFile instanceof Components.interfaces.nsIFile)
   187         gDownloadLastDirFile = aFile.clone();
   188       else
   189         gDownloadLastDirFile = null;
   190     } else {
   191       if (aFile instanceof Components.interfaces.nsIFile)
   192         Services.prefs.setComplexValue(LAST_DIR_PREF, nsIFile, aFile);
   193       else if (Services.prefs.prefHasUserValue(LAST_DIR_PREF))
   194         Services.prefs.clearUserPref(LAST_DIR_PREF);
   195     }
   196   }
   197 };

mercurial