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.

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

mercurial