вторник

import-globals-from sanitizeDialog

PK

!<1%wK†K†*chrome/browser/content/browser/sanitize.js// -*- 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/. */

/* import-globals-from sanitizeDialog.js */

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

Components.utils.import("resource://gre/modules/Services.jsm");

XPCOMUtils.defineLazyModuleGetters(this, {

AppConstants: "resource://gre/modules/AppConstants.jsm",

PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",

FormHistory: "resource://gre/modules/FormHistory.jsm",

Downloads: "resource://gre/modules/Downloads.jsm",

DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",

TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",

console: "resource://gre/modules/Console.jsm",

setTimeout: "resource://gre/modules/Timer.jsm",

});

XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",

"@mozilla.org/serviceworkers/manager;1",

"nsIServiceWorkerManager");

XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",

"@mozilla.org/dom/quota-manager-service;1",

"nsIQuotaManagerService");

var {classes: Cc, interfaces: Ci, results: Cr} = Components;

/**

* A number of iterations after which to yield time back

* to the system.

*/

const YIELD_PERIOD = 10;

function Sanitizer() {

}

Sanitizer.prototype = {

// warning to the caller: this one may raise an exception (e.g. bug #265028)

clearItem(aItemName) {

this.items[aItemName].clear();

},

prefDomain: "",

getNameFromPreference(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.

*

* @param [optional] itemsToClear

* Array of items to be cleared. if specified only those

* items get cleared, irrespectively of the preference settings.

* @param [optional] options

* Object whose properties are options for this sanitization.

* TODO (bug 1167238) document options here.

*/

async sanitize(itemsToClear = null, options = {}) {

let progress = options.progress || {};

let promise = this._sanitize(itemsToClear, progress);

// Depending on preferences, the sanitizer may perform asynchronous

// work before it starts cleaning up the Places database (e.g. closing

// windows). We need to make sure that the connection to that database

// hasn't been closed by the time we use it.

// Though, if this is a sanitize on shutdown, we already have a blocker.

if (!progress.isShutdown) {

let shutdownClient = Cc["@mozilla.org/browser/nav-history-service;1"]

.getService(Ci.nsPIPlacesDatabase)

.shutdownClient

.jsclient;

shutdownClient.addBlocker("sanitize.js: Sanitize",

promise,

{

fetchState: () => ({ progress })

}

);

}

try {

await promise;

} finally {

Services.obs.notifyObservers(null, "sanitizer-sanitization-complete");

}

},

async _sanitize(aItemsToClear, progress = {}) {

let seenError = false;

let itemsToClear;

if (Array.isArray(aItemsToClear)) {

// Shallow copy the array, as we are going to modify

// it in place later.

itemsToClear = [...aItemsToClear];

} else {

let branch = Services.prefs.getBranch(this.prefDomain);

itemsToClear = Object.keys(this.items).filter(itemName => {

try {

return branch.getBoolPref(itemName);

} catch (ex) {

return false;

}

});

}

// Store the list of items to clear, in case we are killed before we

// get a chance to complete.

Services.prefs.setStringPref(Sanitizer.PREF_SANITIZE_IN_PROGRESS,

JSON.stringify(itemsToClear));

// Store the list of items to clear, for debugging/forensics purposes

for (let k of itemsToClear) {

progress[k] = "ready";

}

// Ensure open windows get cleared first, if they're in our list, so that they don't stick

// around in the recently closed windows list, and so we can cancel the whole thing

// if the user selects to keep a window open from a beforeunload prompt.

let openWindowsIndex = itemsToClear.indexOf("openWindows");

if (openWindowsIndex != -1) {

itemsToClear.splice(openWindowsIndex, 1);

await this.items.openWindows.clear();

progress.openWindows = "cleared";

}

// Cache the range of times to clear

let range = null;

// If we ignore timespan, clear everything,

// otherwise, pick a range.

if (!this.ignoreTimespan) {

range = this.range || Sanitizer.getClearRange();

}

// For performance reasons we start all the clear tasks at once, then wait

// for their promises later.

// Some of the clear() calls may raise exceptions (for example bug 265028),

// we catch and store them, but continue to sanitize as much as possible.

// Callers should check returned errors and give user feedback

// about items that could not be sanitized

let refObj = {};

TelemetryStopwatch.start("FX_SANITIZE_TOTAL", refObj);

let annotateError = (name, ex) => {

progress[name] = "failed";

seenError = true;

console.error("Error sanitizing " + name, ex);

};

// Array of objects in form { name, promise }.

// `name` is the item's name and `promise` may be a promise, if the

// sanitization is asynchronous, or the function return value, otherwise.

let handles = [];

for (let name of itemsToClear) {

let item = this.items[name];

try {

// Catch errors here, so later we can just loop through these.

handles.push({ name,

promise: item.clear(range)

.then(() => progress[name] = "cleared",

ex => annotateError(name, ex))

});

} catch (ex) {

annotateError(name, ex);

}

}

for (let handle of handles) {

progress[handle.name] = "blocking";

await handle.promise;

}

// Sanitization is complete.

TelemetryStopwatch.finish("FX_SANITIZE_TOTAL", refObj);

// Reset the inProgress preference since we were not killed during

// sanitization.

Services.prefs.clearUserPref(Sanitizer.PREF_SANITIZE_IN_PROGRESS);

progress = {};

if (seenError) {

throw new Error("Error sanitizing");

}

},

// 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: {

async clear(range) {

let seenException;

let refObj = {};

TelemetryStopwatch.start("FX_SANITIZE_CACHE", refObj);

try {

// Cache doesn't consult timespan, nor does it have the

// facility for timespan-based eviction. Wipe it.

let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]

.getService(Ci.nsICacheStorageService);

cache.clear();

} catch (ex) {

seenException = ex;

}

try {

let imageCache = Cc["@mozilla.org/image/tools;1"]

.getService(Ci.imgITools)

.getImgCacheForDocument(null);

imageCache.clearCache(false); // true=chrome, false=content

} catch (ex) {

seenException = ex;

}

TelemetryStopwatch.finish("FX_SANITIZE_CACHE", refObj);

if (seenException) {

throw seenException;

}

}

},

cookies: {

async clear(range) {

let seenException;

let yieldCounter = 0;

let refObj = {};

// Clear cookies.

TelemetryStopwatch.start("FX_SANITIZE_COOKIES_2", refObj);

try {

let cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"]

.getService(Ci.nsICookieManager);

if (range) {

// Iterate through the cookies and delete any created after our cutoff.

let cookiesEnum = cookieMgr.enumerator;

while (cookiesEnum.hasMoreElements()) {

let cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);

if (cookie.creationTime > range[0]) {

// This cookie was created after our cutoff, clear it

cookieMgr.remove(cookie.host, cookie.name, cookie.path,

false, cookie.originAttributes);

if (++yieldCounter % YIELD_PERIOD == 0) {

await new Promise(resolve => setTimeout(resolve, 0)); // Don't block the main thread too long

}

Комментариев нет:

Отправить комментарий