toolkit/forgetaboutsite/ForgetAboutSite.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 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 Components.utils.import("resource://gre/modules/Services.jsm");
michael@0 6 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 7 Components.utils.import("resource://gre/modules/NetUtil.jsm");
michael@0 8 Components.utils.import("resource://gre/modules/Task.jsm");
michael@0 9 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
michael@0 10 "resource://gre/modules/PlacesUtils.jsm");
michael@0 11 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
michael@0 12 "resource://gre/modules/Downloads.jsm");
michael@0 13
michael@0 14 this.EXPORTED_SYMBOLS = ["ForgetAboutSite"];
michael@0 15
michael@0 16 /**
michael@0 17 * Returns true if the string passed in is part of the root domain of the
michael@0 18 * current string. For example, if this is "www.mozilla.org", and we pass in
michael@0 19 * "mozilla.org", this will return true. It would return false the other way
michael@0 20 * around.
michael@0 21 */
michael@0 22 function hasRootDomain(str, aDomain)
michael@0 23 {
michael@0 24 let index = str.indexOf(aDomain);
michael@0 25 // If aDomain is not found, we know we do not have it as a root domain.
michael@0 26 if (index == -1)
michael@0 27 return false;
michael@0 28
michael@0 29 // If the strings are the same, we obviously have a match.
michael@0 30 if (str == aDomain)
michael@0 31 return true;
michael@0 32
michael@0 33 // Otherwise, we have aDomain as our root domain iff the index of aDomain is
michael@0 34 // aDomain.length subtracted from our length and (since we do not have an
michael@0 35 // exact match) the character before the index is a dot or slash.
michael@0 36 let prevChar = str[index - 1];
michael@0 37 return (index == (str.length - aDomain.length)) &&
michael@0 38 (prevChar == "." || prevChar == "/");
michael@0 39 }
michael@0 40
michael@0 41 const Cc = Components.classes;
michael@0 42 const Ci = Components.interfaces;
michael@0 43 const Cu = Components.utils;
michael@0 44
michael@0 45 this.ForgetAboutSite = {
michael@0 46 removeDataFromDomain: function CRH_removeDataFromDomain(aDomain)
michael@0 47 {
michael@0 48 PlacesUtils.history.removePagesFromHost(aDomain, true);
michael@0 49
michael@0 50 // Cache
michael@0 51 let (cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"].
michael@0 52 getService(Ci.nsICacheStorageService)) {
michael@0 53 // NOTE: there is no way to clear just that domain, so we clear out
michael@0 54 // everything)
michael@0 55 try {
michael@0 56 cs.clear();
michael@0 57 } catch (ex) {
michael@0 58 Cu.reportError("Exception thrown while clearing the cache: " +
michael@0 59 ex.toString());
michael@0 60 }
michael@0 61 }
michael@0 62
michael@0 63 // Image Cache
michael@0 64 let (imageCache = Cc["@mozilla.org/image/tools;1"].
michael@0 65 getService(Ci.imgITools).getImgCacheForDocument(null)) {
michael@0 66 try {
michael@0 67 imageCache.clearCache(false); // true=chrome, false=content
michael@0 68 } catch (ex) {
michael@0 69 Cu.reportError("Exception thrown while clearing the image cache: " +
michael@0 70 ex.toString());
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 // Cookies
michael@0 75 let (cm = Cc["@mozilla.org/cookiemanager;1"].
michael@0 76 getService(Ci.nsICookieManager2)) {
michael@0 77 let enumerator = cm.getCookiesFromHost(aDomain);
michael@0 78 while (enumerator.hasMoreElements()) {
michael@0 79 let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie);
michael@0 80 cm.remove(cookie.host, cookie.name, cookie.path, false);
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 // Plugin data
michael@0 85 const phInterface = Ci.nsIPluginHost;
michael@0 86 const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
michael@0 87 let (ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface)) {
michael@0 88 let tags = ph.getPluginTags();
michael@0 89 for (let i = 0; i < tags.length; i++) {
michael@0 90 try {
michael@0 91 ph.clearSiteData(tags[i], aDomain, FLAG_CLEAR_ALL, -1);
michael@0 92 } catch (e) {
michael@0 93 // Ignore errors from the plugin
michael@0 94 }
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 // Downloads
michael@0 99 let useJSTransfer = false;
michael@0 100 try {
michael@0 101 // This method throws an exception if the old Download Manager is disabled.
michael@0 102 Services.downloads.activeDownloadCount;
michael@0 103 } catch (ex) {
michael@0 104 useJSTransfer = true;
michael@0 105 }
michael@0 106
michael@0 107 if (useJSTransfer) {
michael@0 108 Task.spawn(function() {
michael@0 109 let list = yield Downloads.getList(Downloads.ALL);
michael@0 110 list.removeFinished(download => hasRootDomain(
michael@0 111 NetUtil.newURI(download.source.url).host, aDomain));
michael@0 112 }).then(null, Cu.reportError);
michael@0 113 }
michael@0 114 else {
michael@0 115 let (dm = Cc["@mozilla.org/download-manager;1"].
michael@0 116 getService(Ci.nsIDownloadManager)) {
michael@0 117 // Active downloads
michael@0 118 for (let enumerator of [dm.activeDownloads, dm.activePrivateDownloads]) {
michael@0 119 while (enumerator.hasMoreElements()) {
michael@0 120 let dl = enumerator.getNext().QueryInterface(Ci.nsIDownload);
michael@0 121 if (hasRootDomain(dl.source.host, aDomain)) {
michael@0 122 dl.cancel();
michael@0 123 dl.remove();
michael@0 124 }
michael@0 125 }
michael@0 126 }
michael@0 127
michael@0 128 function deleteAllLike(db) {
michael@0 129 // NOTE: This is lossy, but we feel that it is OK to be lossy here and not
michael@0 130 // invoke the cost of creating a URI for each download entry and
michael@0 131 // ensure that the hostname matches.
michael@0 132 let stmt = db.createStatement(
michael@0 133 "DELETE FROM moz_downloads " +
michael@0 134 "WHERE source LIKE ?1 ESCAPE '/' " +
michael@0 135 "AND state NOT IN (?2, ?3, ?4)"
michael@0 136 );
michael@0 137 let pattern = stmt.escapeStringForLIKE(aDomain, "/");
michael@0 138 stmt.bindByIndex(0, "%" + pattern + "%");
michael@0 139 stmt.bindByIndex(1, Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING);
michael@0 140 stmt.bindByIndex(2, Ci.nsIDownloadManager.DOWNLOAD_PAUSED);
michael@0 141 stmt.bindByIndex(3, Ci.nsIDownloadManager.DOWNLOAD_QUEUED);
michael@0 142 try {
michael@0 143 stmt.execute();
michael@0 144 }
michael@0 145 finally {
michael@0 146 stmt.finalize();
michael@0 147 }
michael@0 148 }
michael@0 149
michael@0 150 // Completed downloads
michael@0 151 deleteAllLike(dm.DBConnection);
michael@0 152 deleteAllLike(dm.privateDBConnection);
michael@0 153
michael@0 154 // We want to rebuild the list if the UI is showing, so dispatch the
michael@0 155 // observer topic
michael@0 156 let os = Cc["@mozilla.org/observer-service;1"].
michael@0 157 getService(Ci.nsIObserverService);
michael@0 158 os.notifyObservers(null, "download-manager-remove-download", null);
michael@0 159 }
michael@0 160 }
michael@0 161
michael@0 162 // Passwords
michael@0 163 let (lm = Cc["@mozilla.org/login-manager;1"].
michael@0 164 getService(Ci.nsILoginManager)) {
michael@0 165 // Clear all passwords for domain
michael@0 166 try {
michael@0 167 let logins = lm.getAllLogins();
michael@0 168 for (let i = 0; i < logins.length; i++)
michael@0 169 if (hasRootDomain(logins[i].hostname, aDomain))
michael@0 170 lm.removeLogin(logins[i]);
michael@0 171 }
michael@0 172 // XXXehsan: is there a better way to do this rather than this
michael@0 173 // hacky comparison?
michael@0 174 catch (ex if ex.message.indexOf("User canceled Master Password entry") != -1) { }
michael@0 175
michael@0 176 // Clear any "do not save for this site" for this domain
michael@0 177 let disabledHosts = lm.getAllDisabledHosts();
michael@0 178 for (let i = 0; i < disabledHosts.length; i++)
michael@0 179 if (hasRootDomain(disabledHosts[i], aDomain))
michael@0 180 lm.setLoginSavingEnabled(disabledHosts, true);
michael@0 181 }
michael@0 182
michael@0 183 // Permissions
michael@0 184 let (pm = Cc["@mozilla.org/permissionmanager;1"].
michael@0 185 getService(Ci.nsIPermissionManager)) {
michael@0 186 // Enumerate all of the permissions, and if one matches, remove it
michael@0 187 let enumerator = pm.enumerator;
michael@0 188 while (enumerator.hasMoreElements()) {
michael@0 189 let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
michael@0 190 if (hasRootDomain(perm.host, aDomain))
michael@0 191 pm.remove(perm.host, perm.type);
michael@0 192 }
michael@0 193 }
michael@0 194
michael@0 195 // Offline Storages
michael@0 196 let (qm = Cc["@mozilla.org/dom/quota/manager;1"].
michael@0 197 getService(Ci.nsIQuotaManager)) {
michael@0 198 // delete data from both HTTP and HTTPS sites
michael@0 199 let caUtils = {};
michael@0 200 let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
michael@0 201 getService(Ci.mozIJSSubScriptLoader);
michael@0 202 scriptLoader.loadSubScript("chrome://global/content/contentAreaUtils.js",
michael@0 203 caUtils);
michael@0 204 let httpURI = caUtils.makeURI("http://" + aDomain);
michael@0 205 let httpsURI = caUtils.makeURI("https://" + aDomain);
michael@0 206 qm.clearStoragesForURI(httpURI);
michael@0 207 qm.clearStoragesForURI(httpsURI);
michael@0 208 }
michael@0 209
michael@0 210 function onContentPrefsRemovalFinished() {
michael@0 211 // Everybody else (including extensions)
michael@0 212 Services.obs.notifyObservers(null, "browser:purge-domain-data", aDomain);
michael@0 213 }
michael@0 214
michael@0 215 // Content Preferences
michael@0 216 let cps2 = Cc["@mozilla.org/content-pref/service;1"].
michael@0 217 getService(Ci.nsIContentPrefService2);
michael@0 218 cps2.removeBySubdomain(aDomain, null, {
michael@0 219 handleCompletion: function() onContentPrefsRemovalFinished(),
michael@0 220 handleError: function() {}
michael@0 221 });
michael@0 222
michael@0 223 // Predictive network data - like cache, no way to clear this per
michael@0 224 // domain, so just trash it all
michael@0 225 let ns = Cc["@mozilla.org/network/seer;1"].
michael@0 226 getService(Ci.nsINetworkSeer);
michael@0 227 ns.reset();
michael@0 228 }
michael@0 229 };

mercurial