mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1524200 - Sanitizer.jsm should retrieve the list of nsIPrincipal objects with site data only when needed, r=johannh
Differential Revision: https://phabricator.services.mozilla.com/D20995 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
130d8fe6b2
commit
53e4ef9c09
@ -664,6 +664,81 @@ async function sanitizeInternal(items, aItemsToClear, progress, options = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is an helper that retrieves the principals with site data just once
|
||||||
|
// and only when needed.
|
||||||
|
class PrincipalsCollector {
|
||||||
|
constructor() {
|
||||||
|
this.principals = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllPrincipals(progress) {
|
||||||
|
if (this.principals == null) {
|
||||||
|
// Here is the list of principals with site data.
|
||||||
|
progress.advancement = "get-principals";
|
||||||
|
this.principals = await this.getAllPrincipalsInternal(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.principals;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllPrincipalsInternal(progress) {
|
||||||
|
progress.step = "principals-quota-manager";
|
||||||
|
let principals = await new Promise(resolve => {
|
||||||
|
quotaManagerService.getUsage(request => {
|
||||||
|
progress.step = "principals-quota-manager-getUsage";
|
||||||
|
if (request.resultCode != Cr.NS_OK) {
|
||||||
|
// We are probably shutting down. We don't want to propagate the
|
||||||
|
// error, rejecting the promise.
|
||||||
|
resolve([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = [];
|
||||||
|
for (let item of request.result) {
|
||||||
|
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
|
||||||
|
let uri = principal.URI;
|
||||||
|
if (isSupportedURI(uri)) {
|
||||||
|
list.push(principal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.step = "principals-quota-manager-completed";
|
||||||
|
resolve(list);
|
||||||
|
});
|
||||||
|
}).catch(ex => {
|
||||||
|
Cu.reportError("QuotaManagerService promise failed: " + ex);
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
progress.step = "principals-service-workers";
|
||||||
|
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||||
|
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||||
|
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||||
|
// We don't need to check the scheme. SW are just exposed to http/https URLs.
|
||||||
|
principals.push(sw.principal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's take the list of unique hosts+OA from cookies.
|
||||||
|
progress.step = "principals-cookies";
|
||||||
|
let enumerator = Services.cookies.enumerator;
|
||||||
|
let hosts = new Set();
|
||||||
|
for (let cookie of enumerator) {
|
||||||
|
hosts.add(cookie.rawHost + ChromeUtils.originAttributesToSuffix(cookie.originAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.step = "principals-host-cookie";
|
||||||
|
hosts.forEach(host => {
|
||||||
|
// Cookies and permissions are handled by origin/host. Doesn't matter if we
|
||||||
|
// use http: or https: schema here.
|
||||||
|
principals.push(
|
||||||
|
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://" + host));
|
||||||
|
});
|
||||||
|
|
||||||
|
progress.step = "total-principals:" + principals.length;
|
||||||
|
return principals;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function sanitizeOnShutdown(progress) {
|
async function sanitizeOnShutdown(progress) {
|
||||||
log("Sanitizing on shutdown");
|
log("Sanitizing on shutdown");
|
||||||
|
|
||||||
@ -674,9 +749,7 @@ async function sanitizeOnShutdown(progress) {
|
|||||||
await Sanitizer.sanitize(itemsToClear, { progress });
|
await Sanitizer.sanitize(itemsToClear, { progress });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here is the list of principals with site data.
|
let principalsCollector = new PrincipalsCollector();
|
||||||
progress.advancement = "get-principals";
|
|
||||||
let principals = await getAllPrincipals(progress);
|
|
||||||
|
|
||||||
// Clear out QuotaManager storage for principals that have been marked as
|
// Clear out QuotaManager storage for principals that have been marked as
|
||||||
// session only. The cookie service has special logic that avoids writing
|
// session only. The cookie service has special logic that avoids writing
|
||||||
@ -704,6 +777,8 @@ async function sanitizeOnShutdown(progress) {
|
|||||||
Ci.nsICookieService.ACCEPT_NORMALLY) == Ci.nsICookieService.ACCEPT_SESSION) {
|
Ci.nsICookieService.ACCEPT_NORMALLY) == Ci.nsICookieService.ACCEPT_SESSION) {
|
||||||
log("Session-only configuration detected");
|
log("Session-only configuration detected");
|
||||||
progress.advancement = "session-only";
|
progress.advancement = "session-only";
|
||||||
|
|
||||||
|
let principals = await principalsCollector.getAllPrincipals(progress);
|
||||||
await maybeSanitizeSessionPrincipals(progress, principals);
|
await maybeSanitizeSessionPrincipals(progress, principals);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -725,6 +800,7 @@ async function sanitizeOnShutdown(progress) {
|
|||||||
log("Custom session cookie permission detected for: " + permission.principal.URI.spec);
|
log("Custom session cookie permission detected for: " + permission.principal.URI.spec);
|
||||||
|
|
||||||
// We use just the URI here, because permissions ignore OriginAttributes.
|
// We use just the URI here, because permissions ignore OriginAttributes.
|
||||||
|
let principals = await principalsCollector.getAllPrincipals(progress);
|
||||||
let selectedPrincipals = extractMatchingPrincipals(principals, permission.principal.URI);
|
let selectedPrincipals = extractMatchingPrincipals(principals, permission.principal.URI);
|
||||||
await maybeSanitizeSessionPrincipals(progress, selectedPrincipals);
|
await maybeSanitizeSessionPrincipals(progress, selectedPrincipals);
|
||||||
}
|
}
|
||||||
@ -745,61 +821,6 @@ async function sanitizeOnShutdown(progress) {
|
|||||||
progress.advancement = "done";
|
progress.advancement = "done";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the list of nsIPrincipals with site data.
|
|
||||||
async function getAllPrincipals(progress) {
|
|
||||||
progress.step = "principals-quota-manager";
|
|
||||||
let principals = await new Promise(resolve => {
|
|
||||||
quotaManagerService.getUsage(request => {
|
|
||||||
progress.step = "principals-quota-manager-getUsage";
|
|
||||||
if (request.resultCode != Cr.NS_OK) {
|
|
||||||
// We are probably shutting down. We don't want to propagate the
|
|
||||||
// error, rejecting the promise.
|
|
||||||
resolve([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let list = [];
|
|
||||||
for (let item of request.result) {
|
|
||||||
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
|
|
||||||
let uri = principal.URI;
|
|
||||||
if (isSupportedURI(uri)) {
|
|
||||||
list.push(principal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.step = "principals-quota-manager-completed";
|
|
||||||
resolve(list);
|
|
||||||
});
|
|
||||||
}).catch(() => []);
|
|
||||||
|
|
||||||
progress.step = "principals-service-workers";
|
|
||||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
|
||||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
|
||||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
|
||||||
// We don't need to check the scheme. SW are just exposed to http/https URLs.
|
|
||||||
principals.push(sw.principal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's take the list of unique hosts+OA from cookies.
|
|
||||||
progress.step = "principals-cookies";
|
|
||||||
let enumerator = Services.cookies.enumerator;
|
|
||||||
let hosts = new Set();
|
|
||||||
for (let cookie of enumerator) {
|
|
||||||
hosts.add(cookie.rawHost + ChromeUtils.originAttributesToSuffix(cookie.originAttributes));
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.step = "principals-host-cookie";
|
|
||||||
hosts.forEach(host => {
|
|
||||||
// Cookies and permissions are handled by origin/host. Doesn't matter if we
|
|
||||||
// use http: or https: schema here.
|
|
||||||
principals.push(
|
|
||||||
Services.scriptSecurityManager.createCodebasePrincipalFromOrigin("https://" + host));
|
|
||||||
});
|
|
||||||
|
|
||||||
progress.step = "total-principals:" + principals.length;
|
|
||||||
return principals;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the principals matching matchUri as root domain.
|
// Extracts the principals matching matchUri as root domain.
|
||||||
function extractMatchingPrincipals(principals, matchUri) {
|
function extractMatchingPrincipals(principals, matchUri) {
|
||||||
return principals.filter(principal => {
|
return principals.filter(principal => {
|
||||||
|
Loading…
Reference in New Issue
Block a user