зеркало из https://github.com/mozilla/gecko-dev.git
184 строки
5.9 KiB
JavaScript
184 строки
5.9 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
|
|
|
|
/*
|
|
* The behavior implemented by gDownloadLastDir is documented here.
|
|
*
|
|
* In normal browsing sessions, gDownloadLastDir uses the browser.download.lastDir
|
|
* preference to store the last used download directory. The first time the user
|
|
* switches into the private browsing mode, the last download directory is
|
|
* preserved to the pref value, but if the user switches to another directory
|
|
* during the private browsing mode, that directory is not stored in the pref,
|
|
* and will be merely kept in memory. When leaving the private browsing mode,
|
|
* this in-memory value will be discarded, and the last download directory
|
|
* will be reverted to the pref value.
|
|
*
|
|
* Both the pref and the in-memory value will be cleared when clearing the
|
|
* browsing history. This effectively changes the last download directory
|
|
* to the default download directory on each platform.
|
|
*
|
|
* If passed a URI, the last used directory is also stored with that URI in the
|
|
* content preferences database. This can be disabled by setting the pref
|
|
* browser.download.lastDir.savePerSite to false.
|
|
*/
|
|
|
|
const LAST_DIR_PREF = "browser.download.lastDir";
|
|
const SAVE_PER_SITE_PREF = LAST_DIR_PREF + ".savePerSite";
|
|
const nsIFile = Ci.nsIFile;
|
|
|
|
var EXPORTED_SYMBOLS = ["DownloadLastDir"];
|
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
let nonPrivateLoadContext = Cu.createLoadContext();
|
|
let privateLoadContext = Cu.createPrivateLoadContext();
|
|
|
|
var observer = {
|
|
QueryInterface: ChromeUtils.generateQI([
|
|
"nsIObserver",
|
|
"nsISupportsWeakReference",
|
|
]),
|
|
|
|
observe(aSubject, aTopic, aData) {
|
|
switch (aTopic) {
|
|
case "last-pb-context-exited":
|
|
gDownloadLastDirFile = null;
|
|
break;
|
|
case "browser:purge-session-history":
|
|
gDownloadLastDirFile = null;
|
|
if (Services.prefs.prefHasUserValue(LAST_DIR_PREF)) {
|
|
Services.prefs.clearUserPref(LAST_DIR_PREF);
|
|
}
|
|
// Ensure that purging session history causes both the session-only PB cache
|
|
// and persistent prefs to be cleared.
|
|
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
|
Ci.nsIContentPrefService2
|
|
);
|
|
|
|
cps2.removeByName(LAST_DIR_PREF, nonPrivateLoadContext);
|
|
cps2.removeByName(LAST_DIR_PREF, privateLoadContext);
|
|
break;
|
|
}
|
|
},
|
|
};
|
|
|
|
Services.obs.addObserver(observer, "last-pb-context-exited", true);
|
|
Services.obs.addObserver(observer, "browser:purge-session-history", true);
|
|
|
|
function readLastDirPref() {
|
|
try {
|
|
return Services.prefs.getComplexValue(LAST_DIR_PREF, nsIFile);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function isContentPrefEnabled() {
|
|
try {
|
|
return Services.prefs.getBoolPref(SAVE_PER_SITE_PREF);
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
var gDownloadLastDirFile = readLastDirPref();
|
|
|
|
function DownloadLastDir(aWindow) {
|
|
let loadContext = aWindow.docShell.QueryInterface(Ci.nsILoadContext);
|
|
// Need this in case the real thing has gone away by the time we need it.
|
|
// We only care about the private browsing state. All the rest of the
|
|
// load context isn't of interest to the content pref service.
|
|
this.fakeContext = loadContext.usePrivateBrowsing
|
|
? privateLoadContext
|
|
: nonPrivateLoadContext;
|
|
}
|
|
|
|
DownloadLastDir.prototype = {
|
|
isPrivate: function DownloadLastDir_isPrivate() {
|
|
return this.fakeContext.usePrivateBrowsing;
|
|
},
|
|
// compat shims
|
|
get file() {
|
|
return this._getLastFile();
|
|
},
|
|
set file(val) {
|
|
this.setFile(null, val);
|
|
},
|
|
cleanupPrivateFile() {
|
|
gDownloadLastDirFile = null;
|
|
},
|
|
|
|
_getLastFile() {
|
|
if (gDownloadLastDirFile && !gDownloadLastDirFile.exists()) {
|
|
gDownloadLastDirFile = null;
|
|
}
|
|
|
|
if (this.isPrivate()) {
|
|
if (!gDownloadLastDirFile) {
|
|
gDownloadLastDirFile = readLastDirPref();
|
|
}
|
|
return gDownloadLastDirFile;
|
|
}
|
|
return readLastDirPref();
|
|
},
|
|
|
|
getFileAsync(aURI, aCallback) {
|
|
let plainPrefFile = this._getLastFile();
|
|
if (!aURI || !isContentPrefEnabled()) {
|
|
Services.tm.dispatchToMainThread(() => aCallback(plainPrefFile));
|
|
return;
|
|
}
|
|
|
|
let uri = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
|
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
|
Ci.nsIContentPrefService2
|
|
);
|
|
let result = null;
|
|
cps2.getByDomainAndName(uri, LAST_DIR_PREF, this.fakeContext, {
|
|
handleResult: aResult => (result = aResult),
|
|
handleCompletion(aReason) {
|
|
let file = plainPrefFile;
|
|
if (
|
|
aReason == Ci.nsIContentPrefCallback2.COMPLETE_OK &&
|
|
result instanceof Ci.nsIContentPref
|
|
) {
|
|
try {
|
|
file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
file.initWithPath(result.value);
|
|
} catch (e) {
|
|
file = plainPrefFile;
|
|
}
|
|
}
|
|
aCallback(file);
|
|
},
|
|
});
|
|
},
|
|
|
|
setFile(aURI, aFile) {
|
|
if (aURI && isContentPrefEnabled()) {
|
|
let uri = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
|
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
|
Ci.nsIContentPrefService2
|
|
);
|
|
if (aFile instanceof Ci.nsIFile) {
|
|
cps2.set(uri, LAST_DIR_PREF, aFile.path, this.fakeContext);
|
|
} else {
|
|
cps2.removeByDomainAndName(uri, LAST_DIR_PREF, this.fakeContext);
|
|
}
|
|
}
|
|
if (this.isPrivate()) {
|
|
if (aFile instanceof Ci.nsIFile) {
|
|
gDownloadLastDirFile = aFile.clone();
|
|
} else {
|
|
gDownloadLastDirFile = null;
|
|
}
|
|
} else if (aFile instanceof Ci.nsIFile) {
|
|
Services.prefs.setComplexValue(LAST_DIR_PREF, nsIFile, aFile);
|
|
} else if (Services.prefs.prefHasUserValue(LAST_DIR_PREF)) {
|
|
Services.prefs.clearUserPref(LAST_DIR_PREF);
|
|
}
|
|
},
|
|
};
|