summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/Sanitizer.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/Sanitizer.jsm')
-rw-r--r--mobile/android/modules/Sanitizer.jsm303
1 files changed, 303 insertions, 0 deletions
diff --git a/mobile/android/modules/Sanitizer.jsm b/mobile/android/modules/Sanitizer.jsm
new file mode 100644
index 000000000..014a89688
--- /dev/null
+++ b/mobile/android/modules/Sanitizer.jsm
@@ -0,0 +1,303 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 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/. */
+
+/*globals LoadContextInfo, FormHistory, Accounts */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/LoadContextInfo.jsm");
+Cu.import("resource://gre/modules/FormHistory.jsm");
+Cu.import("resource://gre/modules/Messaging.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/Downloads.jsm");
+Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/Accounts.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration",
+ "resource://gre/modules/DownloadIntegration.jsm");
+
+function dump(a) {
+ Services.console.logStringMessage(a);
+}
+
+this.EXPORTED_SYMBOLS = ["Sanitizer"];
+
+function Sanitizer() {}
+Sanitizer.prototype = {
+ clearItem: function (aItemName)
+ {
+ let item = this.items[aItemName];
+ let canClear = item.canClear;
+ if (typeof canClear == "function") {
+ canClear(function clearCallback(aCanClear) {
+ if (aCanClear)
+ item.clear();
+ });
+ } else if (canClear) {
+ item.clear();
+ }
+ },
+
+ items: {
+ cache: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
+ try {
+ cache.clear();
+ } catch(er) {}
+
+ let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
+ .getImgCacheForDocument(null);
+ try {
+ imageCache.clearCache(false); // true=chrome, false=content
+ } catch(er) {}
+
+ resolve();
+ });
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ cookies: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ Services.cookies.removeAll();
+ resolve();
+ });
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ siteSettings: {
+ clear: Task.async(function* () {
+ // Clear site-specific permissions like "Allow this site to open popups"
+ Services.perms.removeAll();
+
+ // Clear site-specific settings like page-zoom level
+ Cc["@mozilla.org/content-pref/service;1"]
+ .getService(Ci.nsIContentPrefService2)
+ .removeAllDomains(null);
+
+ // Clear site security settings
+ var sss = Cc["@mozilla.org/ssservice;1"]
+ .getService(Ci.nsISiteSecurityService);
+ sss.clearAll();
+
+ // Clear push subscriptions
+ yield new Promise((resolve, reject) => {
+ let push = Cc["@mozilla.org/push/Service;1"]
+ .getService(Ci.nsIPushService);
+ push.clearForDomain("*", status => {
+ if (Components.isSuccessCode(status)) {
+ resolve();
+ } else {
+ reject(new Error("Error clearing push subscriptions: " +
+ status));
+ }
+ });
+ });
+ }),
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ offlineApps: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
+ var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
+ try {
+ appCacheStorage.asyncEvictStorage(null);
+ } catch(er) {}
+
+ resolve();
+ });
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ history: {
+ clear: function ()
+ {
+ return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory" })
+ .catch(e => Cu.reportError("Java-side history clearing failed: " + e))
+ .then(function() {
+ try {
+ Services.obs.notifyObservers(null, "browser:purge-session-history", "");
+ }
+ catch (e) { }
+
+ try {
+ var predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
+ predictor.reset();
+ } 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;
+ }
+ },
+
+ searchHistory: {
+ clear: function ()
+ {
+ return Messaging.sendRequestForResult({ type: "Sanitize:ClearHistory", clearSearchHistory: true })
+ .catch(e => Cu.reportError("Java-side search history clearing failed: " + e))
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ formdata: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ FormHistory.update({ op: "remove" });
+ resolve();
+ });
+ },
+
+ canClear: function (aCallback)
+ {
+ let count = 0;
+ let countDone = {
+ handleResult: function(aResult) { count = aResult; },
+ handleError: function(aError) { Cu.reportError(aError); },
+ handleCompletion: function(aReason) { aCallback(aReason == 0 && count > 0); }
+ };
+ FormHistory.count({}, countDone);
+ }
+ },
+
+ downloadFiles: {
+ clear: Task.async(function* () {
+ let list = yield Downloads.getList(Downloads.ALL);
+ let downloads = yield list.getAll();
+ var finalizePromises = [];
+
+ // Logic copied from DownloadList.removeFinished. Ideally, we would
+ // just use that method directly, but we want to be able to remove the
+ // downloaded files as well.
+ for (let download of downloads) {
+ // Remove downloads that have been canceled, even if the cancellation
+ // operation hasn't completed yet so we don't check "stopped" here.
+ // Failed downloads with partial data are also removed.
+ if (download.stopped && (!download.hasPartialData || download.error)) {
+ // Remove the download first, so that the views don't get the change
+ // notifications that may occur during finalization.
+ yield list.remove(download);
+ // Ensure that the download is stopped and no partial data is kept.
+ // This works even if the download state has changed meanwhile. We
+ // don't need to wait for the procedure to be complete before
+ // processing the other downloads in the list.
+ finalizePromises.push(download.finalize(true).then(() => null, Cu.reportError));
+
+ // Delete the downloaded files themselves.
+ OS.File.remove(download.target.path).then(() => null, ex => {
+ if (!(ex instanceof OS.File.Error && ex.becauseNoSuchFile)) {
+ Cu.reportError(ex);
+ }
+ });
+ }
+ }
+
+ yield Promise.all(finalizePromises);
+ yield DownloadIntegration.forceSave();
+ }),
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ passwords: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ Services.logins.removeAllLogins();
+ resolve();
+ });
+ },
+
+ get canClear()
+ {
+ let count = Services.logins.countLogins("", "", ""); // count all logins
+ return (count > 0);
+ }
+ },
+
+ sessions: {
+ clear: function ()
+ {
+ return new Promise(function(resolve, reject) {
+ // clear all auth tokens
+ var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
+ sdr.logoutAndTeardown();
+
+ // clear FTP and plain HTTP auth sessions
+ Services.obs.notifyObservers(null, "net:clear-active-logins", null);
+
+ resolve();
+ });
+ },
+
+ get canClear()
+ {
+ return true;
+ }
+ },
+
+ syncedTabs: {
+ clear: function ()
+ {
+ return Messaging.sendRequestForResult({ type: "Sanitize:ClearSyncedTabs" })
+ .catch(e => Cu.reportError("Java-side synced tabs clearing failed: " + e));
+ },
+
+ canClear: function(aCallback)
+ {
+ Accounts.anySyncAccountsExist().then(aCallback)
+ .catch(function(err) {
+ Cu.reportError("Java-side synced tabs clearing failed: " + err)
+ aCallback(false);
+ });
+ }
+ }
+
+ }
+};
+
+this.Sanitizer = new Sanitizer();