diff options
Diffstat (limited to 'base/content/sanitize.js')
-rw-r--r-- | base/content/sanitize.js | 534 |
1 files changed, 0 insertions, 534 deletions
diff --git a/base/content/sanitize.js b/base/content/sanitize.js deleted file mode 100644 index b4d13d8..0000000 --- a/base/content/sanitize.js +++ /dev/null @@ -1,534 +0,0 @@ -# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -# 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/. - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", - "resource://gre/modules/PlacesUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FormHistory", - "resource://gre/modules/FormHistory.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Downloads", - "resource://gre/modules/Downloads.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource://gre/modules/Console.jsm"); - -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) - this.items[aItemName].clear(); - }, - - canClearItem: function (aItemName, aCallback, aArg) - { - let canClear = this.items[aItemName].canClear; - if (typeof canClear == "function") { - canClear(aCallback, aArg); - return false; - } - - aCallback(aItemName, canClear, aArg); - return canClear; - }, - - prefDomain: "", - isShutDown: false, - - getNameFromPreference: function (aPreferenceName) - { - return aPreferenceName.substr(this.prefDomain.length); - }, - - /** - * Deletes privacy sensitive data in a batch, according to user preferences. - * Returns a promise which is resolved if no errors occurred. If an error - * occurs, a message is reported to the console and all other items are still - * cleared before the promise is finally rejected. - */ - sanitize: function () - { - var deferred = Promise.defer(); - var psvc = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService); - var branch = psvc.getBranch(this.prefDomain); - var seenError = false; - - // Cache the range of times to clear - if (this.ignoreTimespan) - var range = null; // If we ignore timespan, clear everything - else - range = this.range || Sanitizer.getClearRange(); - - let itemCount = Object.keys(this.items).length; - let onItemComplete = function() { - if (!--itemCount) { - seenError ? deferred.reject() : deferred.resolve(); - } - }; - for (var itemName in this.items) { - let item = this.items[itemName]; - item.range = range; - item.isShutDown = this.isShutDown; - if ("clear" in item && branch.getBoolPref(itemName)) { - let clearCallback = (itemName, aCanClear) => { - // 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 - let item = this.items[itemName]; - try { - if (aCanClear) - item.clear(); - } catch(er) { - seenError = true; - console.error("Error sanitizing " + itemName + ": " + er + "\n"); - } - onItemComplete(); - }; - this.canClearItem(itemName, clearCallback); - } else { - onItemComplete(); - } - } - - return deferred.promise; - }, - - // Time span only makes sense in certain cases. Consumers who want - // to only clear some private data can opt in by setting this to false, - // and can optionally specify a specific range. If timespan is not ignored, - // and range is not set, sanitize() will use the value of the timespan - // pref to determine a range - ignoreTimespan : true, - range : null, - - items: { - cache: { - clear: function () - { - var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]. - getService(Ci.nsICacheStorageService); - try { - // Cache doesn't consult timespan, nor does it have the - // facility for timespan-based eviction. Wipe it. - cache.clear(); - } catch(er) {} - - var imageCache = Cc["@mozilla.org/image/tools;1"]. - getService(Ci.imgITools).getImgCacheForDocument(null); - try { - imageCache.clearCache(false); // true=chrome, false=content - } catch(er) {} - }, - - get canClear() - { - return true; - } - }, - - cookies: { - clear: function () - { - var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"] - .getService(Ci.nsICookieManager); - if (this.range) { - // Iterate through the cookies and delete any created after our cutoff. - var cookiesEnum = cookieMgr.enumerator; - while (cookiesEnum.hasMoreElements()) { - var cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2); - - if (cookie.creationTime > this.range[0]) - // This cookie was created after our cutoff, clear it - cookieMgr.remove(cookie.host, cookie.name, cookie.path, - false, cookie.originAttributes); - } - } - else { - // Remove everything - cookieMgr.removeAll(); - } - - // Clear plugin data. - const phInterface = Ci.nsIPluginHost; - const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL; - let ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface); - - // Determine age range in seconds. (-1 means clear all.) We don't know - // that this.range[1] is actually now, so we compute age range based - // on the lower bound. If this.range results in a negative age, do - // nothing. - let age = this.range ? (Date.now() / 1000 - this.range[0] / 1000000) - : -1; - if (!this.range || age >= 0) { - let tags = ph.getPluginTags(); - for (let i = 0; i < tags.length; i++) { - try { - ph.clearSiteData(tags[i], null, FLAG_CLEAR_ALL, age); - } catch (e) { - // If the plugin doesn't support clearing by age, clear everything. - if (e.result == Components.results. - NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED) { - try { - ph.clearSiteData(tags[i], null, FLAG_CLEAR_ALL, -1); - } catch (e) { - // Ignore errors from the plugin - } - } - } - } - } - }, - - get canClear() - { - return true; - } - }, - - offlineApps: { - clear: function () - { - Components.utils.import("resource:///modules/offlineAppCache.jsm"); - OfflineAppCacheHelper.clear(); - if (!this.range || this.isShutDown) { - Components.utils.import("resource:///modules/QuotaManager.jsm"); - QuotaManagerHelper.clear(this.isShutDown); - } - }, - - get canClear() - { - return true; - } - }, - - history: { - clear: function () - { - if (this.range) { - PlacesUtils.history.removeVisitsByFilter({ - beginDate: new Date(this.range[0] / 1000), - endDate: new Date(this.range[1] / 1000) - }).catch(Components.utils.reportError);; - } else { - // Remove everything. - PlacesUtils.history.clear() - .catch(Components.utils.reportError); - } - - try { - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.notifyObservers(null, "browser:purge-session-history", ""); - } - catch (e) { } - - // Clear last URL of the Open Web Location dialog - var prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - try { - prefs.clearUserPref("general.open_location.last_url"); - } - catch (e) { } - }, - - get canClear() - { - // bug 347231: Always allow clearing history due to dependencies on - // the browser:purge-session-history notification. (like error console) - return true; - } - }, - - formdata: { - clear: function () - { - // Clear undo history of all searchBars - var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'] - .getService(Components.interfaces.nsIWindowMediator); - var windows = windowManager.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let currentDocument = windows.getNext().document; - let searchBar = currentDocument.getElementById("searchbar"); - if (searchBar) - searchBar.textbox.reset(); - let findBar = currentDocument.getElementById("FindToolbar"); - if (findBar) - findBar.clear(); - } - - let change = { op: "remove" }; - if (this.range) { - [ change.firstUsedStart, change.firstUsedEnd ] = this.range; - } - FormHistory.update(change); - }, - - canClear : function(aCallback, aArg) - { - var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'] - .getService(Components.interfaces.nsIWindowMediator); - var windows = windowManager.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let currentDocument = windows.getNext().document; - let searchBar = currentDocument.getElementById("searchbar"); - if (searchBar) { - let transactionMgr = searchBar.textbox.editor.transactionManager; - if (searchBar.value || - transactionMgr.numberOfUndoItems || - transactionMgr.numberOfRedoItems) { - aCallback("formdata", true, aArg); - return false; - } - } - let findBar = currentDocument.getElementById("FindToolbar"); - if (findBar && findBar.canClear) { - aCallback("formdata", true, aArg); - return false; - } - } - - let count = 0; - let countDone = { - handleResult : function(aResult) count = aResult, - handleError : function(aError) Components.utils.reportError(aError), - handleCompletion : - function(aReason) { aCallback("formdata", aReason == 0 && count > 0, aArg); } - }; - FormHistory.count({}, countDone); - return false; - } - }, - - downloads: { - clear: Task.async(function* (range) { - let refObj = {}; - try { - let filterByTime = null; - if (range) { - // Convert microseconds back to milliseconds for date comparisons. - let rangeBeginMs = range[0] / 1000; - let rangeEndMs = range[1] / 1000; - filterByTime = download => download.startTime >= rangeBeginMs && - download.startTime <= rangeEndMs; - } - - // Clear all completed/cancelled downloads - let list = yield Downloads.getList(Downloads.ALL); - list.removeFinished(filterByTime); - } finally {} - }), - - get canClear() - { - //Clearing is always possible with JSTransfers - return true; - } - }, - - passwords: { - clear: function () - { - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - // Passwords are timeless, and don't respect the timeSpan setting - pwmgr.removeAllLogins(); - }, - - get canClear() - { - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - var count = pwmgr.countLogins("", "", ""); // count all logins - return (count > 0); - } - }, - - sessions: { - clear: function () - { - // clear all auth tokens - var sdr = Components.classes["@mozilla.org/security/sdr;1"] - .getService(Components.interfaces.nsISecretDecoderRing); - sdr.logoutAndTeardown(); - - // clear FTP and plain HTTP auth sessions - var os = Components.classes["@mozilla.org/observer-service;1"] - .getService(Components.interfaces.nsIObserverService); - os.notifyObservers(null, "net:clear-active-logins", null); - }, - - get canClear() - { - return true; - } - }, - - siteSettings: { - clear: function () - { - // Clear site-specific permissions like "Allow this site to open popups" - var pm = Components.classes["@mozilla.org/permissionmanager;1"] - .getService(Components.interfaces.nsIPermissionManager); - pm.removeAll(); - - // Clear site-specific settings like page-zoom level - var cps = Components.classes["@mozilla.org/content-pref/service;1"] - .getService(Components.interfaces.nsIContentPrefService2); - cps.removeAllDomains(null); - - // Clear "Never remember passwords for this site", which is not handled by - // the permission manager - var pwmgr = Components.classes["@mozilla.org/login-manager;1"] - .getService(Components.interfaces.nsILoginManager); - var hosts = pwmgr.getAllDisabledHosts(); - for each (var host in hosts) { - pwmgr.setLoginSavingEnabled(host, true); - } - }, - - get canClear() - { - return true; - } - }, - - connectivityData: { - clear: function () - { - // Clear site security settings - var sss = Components.classes["@mozilla.org/ssservice;1"] - .getService(Components.interfaces.nsISiteSecurityService); - sss.clearAll(); - }, - - get canClear() - { - return true; - } - } - } -}; - - - -// "Static" members -Sanitizer.prefDomain = "privacy.sanitize."; -Sanitizer.prefShutdown = "sanitizeOnShutdown"; -Sanitizer.prefDidShutdown = "didShutdownSanitize"; - -// Time span constants corresponding to values of the privacy.sanitize.timeSpan -// pref. Used to determine how much history to clear, for various items -Sanitizer.TIMESPAN_EVERYTHING = 0; -Sanitizer.TIMESPAN_HOUR = 1; -Sanitizer.TIMESPAN_2HOURS = 2; -Sanitizer.TIMESPAN_4HOURS = 3; -Sanitizer.TIMESPAN_TODAY = 4; - -Sanitizer.IS_SHUTDOWN = true; - -// Return a 2 element array representing the start and end times, -// in the uSec-since-epoch format that PRTime likes. If we should -// clear everything, return null. Use ts if it is defined; otherwise -// use the timeSpan pref. -Sanitizer.getClearRange = function (ts) { - if (ts === undefined) - ts = Sanitizer.prefs.getIntPref("timeSpan"); - if (ts === Sanitizer.TIMESPAN_EVERYTHING) - return null; - - // PRTime is microseconds while JS time is milliseconds - var endDate = Date.now() * 1000; - switch (ts) { - case Sanitizer.TIMESPAN_HOUR : - var startDate = endDate - 3600000000; // 1*60*60*1000000 - break; - case Sanitizer.TIMESPAN_2HOURS : - startDate = endDate - 7200000000; // 2*60*60*1000000 - break; - case Sanitizer.TIMESPAN_4HOURS : - startDate = endDate - 14400000000; // 4*60*60*1000000 - break; - case Sanitizer.TIMESPAN_TODAY : - var d = new Date(); // Start with today - d.setHours(0); // zero us back to midnight... - d.setMinutes(0); - d.setSeconds(0); - startDate = d.valueOf() * 1000; // convert to epoch usec - break; - default: - throw "Invalid time span for clear private data: " + ts; - } - return [startDate, endDate]; -}; - -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); -#ifdef XP_MACOSX - ww.openWindow(null, // make this an app-modal window on Mac -#else - ww.openWindow(aParentWindow, -#endif - "chrome://browser/content/sanitize.xul", - "Sanitize", - "chrome,titlebar,dialog,centerscreen,modal", - null); -}; - -/** - * Deletes privacy sensitive data in a batch, optionally showing the - * sanitize UI, according to user preferences - */ -Sanitizer.sanitize = function(aParentWindow) -{ - Sanitizer.showUI(aParentWindow); -}; - -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(Sanitizer.IS_SHUTDOWN); -}; - -// this is called on startup and shutdown, to perform pending sanitizations -Sanitizer._checkAndSanitize = function(isShutDown) -{ - const prefs = Sanitizer.prefs; - if (prefs.getBoolPref(Sanitizer.prefShutdown) && - !prefs.prefHasUserValue(Sanitizer.prefDidShutdown)) { - // this is a shutdown or a startup after an unclean exit - var s = new Sanitizer(); - s.prefDomain = "privacy.clearOnShutdown."; - s.isShutDown = isShutDown; - s.sanitize().then(function() { - prefs.setBoolPref(Sanitizer.prefDidShutdown, true); - }); - } -}; |