Bug 284086: "Sanitize on shutdown" fails if the last closed window is not a browser window, patch by Giorgio Maone <g.maone@informaction.com>, r=mconnor

This commit is contained in:
gavin@gavinsharp.com 2007-10-02 20:35:22 -07:00
parent bb1236dbc0
commit a3d66492fa

View File

@ -19,6 +19,7 @@
#
# Contributor(s):
# Ben Goodger <ben@mozilla.org>
# Giorgio Maone <g.maone@informaction.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -36,6 +37,7 @@
function Sanitizer() {}
Sanitizer.prototype = {
// warning to the caller: this one may raise an exception (e.g. bug #265028)
clearItem: function (aItemName)
{
if (this.items[aItemName].canClear)
@ -53,26 +55,90 @@ Sanitizer.prototype = {
return aPreferenceName.substr(this._prefDomain.length);
},
/**
* Deletes privacy sensitive data in a batch, according to user preferences
*
* @returns null if everything's fine; an object in the form
* { itemName: error, ... } on (partial) failure
*/
sanitize: function ()
{
var psvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
var branch = psvc.getBranch(this._prefDomain);
var errors = null;
for (var itemName in this.items) {
var item = this.items[itemName];
if ("clear" in item && item.canClear && branch.getBoolPref(itemName))
item.clear();
if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) {
// Some of these clear() may raise exceptions (see bug #265028)
// to sanitize as much as possible, we catch and store them,
// rather than fail fast.
// Callers should check returned errors and give user feedback
// about items that could not be sanitized
try {
item.clear();
} catch(er) {
if (!errors)
errors = {};
errors[itemName] = er;
dump("Error sanitizing " + itemName + ": " + er + "\n");
}
}
}
return errors;
},
items: {
cache: {
clear: function ()
{
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
cacheService.evictEntries(Components.interfaces.nsICache.STORE_ON_DISK);
cacheService.evictEntries(Components.interfaces.nsICache.STORE_IN_MEMORY);
const cc = Components.classes;
const ci = Components.interfaces;
var cacheService = cc["@mozilla.org/network/cache-service;1"]
.getService(ci.nsICacheService);
// Here we play dirty, trying to brutally wipe out all the cache files
// even if the disk cache device has gone away (if it is still with us,
// our removal attempt will fail because the directory is locked,
// and we fall back to the "nice" way below)
var cacheDir;
// Look at nsCacheProfilePrefObserver::ReadPrefs()
// and nsDiskCacheDevice::SetCacheParentDirectory()
// for details on how we guess the cache directory
try {
cacheDir = cc["@mozilla.org/preferences-service;1"]
.getService(ci.nsIBranch)
.getComplexValue("browser.cache.disk.parent_directory",
ci.nsILocalFile);
} catch(er) {
const dirServ = cc["@mozilla.org/file/directory_service;1"]
.getService(ci.nsIProperties);
try {
cacheDir = dirServ.get("cachePDir",ci.nsILocalFile);
} catch(er) {
cacheDir = dirServ.get("ProfLD",ci.nsILocalFile);
}
}
if (cacheDir) {
// Here we try to prevent the "phantom Cache.Trash" issue
// reported in bug #296256
cacheDir.append("Cache.Trash");
try {
cacheDir.remove(true);
} catch(er) {}
cacheDir = cacheDir.parent;
cacheDir.append("Cache");
try {
cacheDir.remove(true);
} catch(er) {}
}
// The "nice" way
cacheService.evictEntries(ci.nsICache.STORE_ON_DISK);
cacheService.evictEntries(ci.nsICache.STORE_IN_MEMORY);
},
get canClear()
@ -88,8 +154,9 @@ Sanitizer.prototype = {
.getService(Components.interfaces.nsICookieManager);
var e = cookieMgr.enumerator;
var cookies = [];
var cookie;
while (e.hasMoreElements()) {
var cookie = e.getNext().QueryInterface(Components.interfaces.nsICookie);
cookie = e.getNext().QueryInterface(Components.interfaces.nsICookie);
cookies.push(cookie);
}
@ -113,7 +180,8 @@ Sanitizer.prototype = {
globalHistory.removeAllPages();
try {
var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.notifyObservers(null, "browser:purge-session-history", "");
}
catch (e) { }
@ -205,3 +273,74 @@ Sanitizer.prototype = {
}
};
// "Static" members
Sanitizer.prefDomain = "privacy.sanitize.";
Sanitizer.prefPrompt = "promptOnSanitize";
Sanitizer.prefShutdown = "sanitizeOnShutdown";
Sanitizer.prefDidShutdown = "didShutdownSanitize";
Sanitizer._prefs = null;
Sanitizer.__defineGetter__("prefs", function()
{
return Sanitizer._prefs ? Sanitizer._prefs
: Sanitizer._prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch(Sanitizer.prefDomain);
});
// Shows sanitization UI
Sanitizer.showUI = function(aParentWindow)
{
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
ww.openWindow(aParentWindow,
"chrome://browser/content/sanitize.xul",
"Sanitize",
"chrome,titlebar,centerscreen,modal",
null);
};
/**
* Deletes privacy sensitive data in a batch, optionally showing the
* sanitize UI, according to user preferences
*
* @returns null if everything's fine (no error or displayed UI, which
* should handle errors);
* an object in the form { itemName: error, ... } on (partial) failure
*/
Sanitizer.sanitize = function(aParentWindow)
{
if (Sanitizer.prefs.getBoolPref(Sanitizer.prefPrompt)) {
Sanitizer.showUI(aParentWindow);
return null;
}
return new Sanitizer().sanitize();
};
Sanitizer.onStartup = function()
{
// we check for unclean exit with pending sanitization
Sanitizer._checkAndSanitize();
};
Sanitizer.onShutdown = function()
{
// we check if sanitization is needed and perform it
Sanitizer._checkAndSanitize();
};
// this is called on startup and shutdown, to perform pending sanitizations
Sanitizer._checkAndSanitize = function()
{
const prefs = Sanitizer.prefs;
if (prefs.getBoolPref(Sanitizer.prefShutdown) &&
!prefs.prefHasUserValue(Sanitizer.prefDidShutdown)) {
// this is a shutdown or a startup after an unclean exit
Sanitizer.sanitize(null) || // sanitize() returns null on full success
prefs.setBoolPref(Sanitizer.prefDidShutdown, true);
}
};