Backed out 3 changesets (bug 1523272) for ES Linut failure CLOSED TREE

Backed out changeset 80d103201d1d (bug 1523272)
Backed out changeset bbd8f0b2e3b2 (bug 1523272)
Backed out changeset bf2ec5cdc33b (bug 1523272)
This commit is contained in:
Bogdan Tara 2019-02-14 18:29:54 +02:00
parent c9edc914a9
commit 4c0cf6db45
9 changed files with 367 additions and 393 deletions

View File

@ -15,8 +15,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "swm",
"@mozilla.org/serviceworkers/manager;1",
"nsIServiceWorkerManager");
XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]);
/**
* This module assists with tasks around testing functionality that shows
* or clears site data.
@ -27,44 +25,31 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["indexedDB", "Blob"]);
var SiteDataTestUtils = {
/**
* Makes an origin have persistent data storage.
*
* @param {String} origin - the origin of the site to give persistent storage
*
* @returns a Promise that resolves when storage was persisted
*/
persist(origin, value = Services.perms.ALLOW_ACTION) {
return new Promise(resolve => {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
Services.perms.addFromPrincipal(principal, "persistent-storage", value);
Services.qms.persist(principal).callback = () => resolve();
});
},
/**
* Adds a new blob entry to a dummy indexedDB database for the specified origin.
* Adds a new entry to a dummy indexedDB database for the specified origin.
*
* @param {String} origin - the origin of the site to add test data for
* @param {Number} size [optional] - the size of the entry in bytes
* @param {String} name [optional] - the entry key
* @param {String} value [optional] - the entry value
* @param {Object} originAttributes [optional] - the originAttributes
*
* @returns a Promise that resolves when the data was added successfully.
*/
addToIndexedDB(origin, size = 1024) {
addToIndexedDB(origin, key = "foo", value = "bar", originAttributes = {}) {
return new Promise(resolve => {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
let uri = Services.io.newURI(origin);
let principal =
Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes);
let request = indexedDB.openForPrincipal(principal, "TestDatabase", 1);
request.onupgradeneeded = function(e) {
let db = e.target.result;
db.createObjectStore("TestStore");
db.createObjectStore("TestStore", { keyPath: "id" });
};
request.onsuccess = function(e) {
let db = e.target.result;
let tx = db.transaction("TestStore", "readwrite");
let store = tx.objectStore("TestStore");
tx.oncomplete = resolve;
let buffer = new ArrayBuffer(size);
let blob = new Blob([buffer]);
store.add(blob, Cu.now());
store.put({ id: key, description: value});
};
});
},
@ -78,8 +63,8 @@ var SiteDataTestUtils = {
* @param {String} value [optional] - the cookie value
*/
addToCookies(origin, name = "foo", value = "bar") {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
Services.cookies.add(principal.URI.host, principal.URI.pathQueryRef, name, value,
let uri = Services.io.newURI(origin);
Services.cookies.add(uri.host, uri.pathQueryRef, name, value,
false, false, false, Date.now() + 24000 * 60 * 60, {},
Ci.nsICookie2.SAMESITE_UNSET);
},
@ -136,7 +121,8 @@ var SiteDataTestUtils = {
*/
getQuotaUsage(origin) {
return new Promise(resolve => {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
let uri = Services.io.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
});
},

View File

@ -18,9 +18,8 @@ function checkDataForAboutURL() {
}
function createIndexedDB(host, originAttributes) {
let uri = Services.io.newURI("https://" + host);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, originAttributes);
return SiteDataTestUtils.addToIndexedDB(principal.origin);
return SiteDataTestUtils.addToIndexedDB("https://" + host, "foo", "bar",
originAttributes);
}
function checkIndexedDB(host, originAttributes) {

View File

@ -12,8 +12,8 @@ function assertAllSitesNotListed(win) {
}
// Test selecting and removing all sites one by one
add_task(async function test_selectRemove() {
let hosts = await addTestData([
add_task(async function() {
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
@ -22,6 +22,7 @@ add_task(async function test_selectRemove() {
{
usage: 1024,
origin: "https://shopping.xyz.com",
persisted: false,
},
{
usage: 1024,
@ -31,11 +32,12 @@ add_task(async function test_selectRemove() {
{
usage: 1024,
origin: "http://email.bar.com",
persisted: false,
},
]);
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
@ -48,7 +50,7 @@ add_task(async function test_selectRemove() {
let settingsDialogClosePromise = null;
// Test the initial state
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Cancel" button
settingsDialogClosePromise = promiseSettingsDialogClose();
@ -59,7 +61,7 @@ add_task(async function test_selectRemove() {
cancelBtn.doCommand();
await settingsDialogClosePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button but cancelling save
let cancelPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel");
@ -74,7 +76,7 @@ add_task(async function test_selectRemove() {
cancelBtn.doCommand();
await settingsDialogClosePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button and accepting save
let acceptPromise = BrowserTestUtils.promiseAlertDialogOpen("accept");
@ -91,7 +93,7 @@ add_task(async function test_selectRemove() {
await openSiteDataSettingsDialog();
assertAllSitesNotListed(win);
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
function removeAllSitesOneByOne() {
@ -107,8 +109,8 @@ add_task(async function test_selectRemove() {
});
// Test selecting and removing partial sites
add_task(async function test_removePartialSites() {
let hosts = await addTestData([
add_task(async function() {
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
@ -139,10 +141,15 @@ add_task(async function test_removePartialSites() {
origin: "https://127.0.0.1",
persisted: false,
},
{
usage: 1024,
origin: "https://[0:0:0:0:0:0:0:1]",
persisted: true,
},
]);
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
@ -156,18 +163,18 @@ add_task(async function test_removePartialSites() {
let settingsDialogClosePromise = null;
// Test the initial state
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Cancel" button
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
cancelBtn = frameDoc.getElementById("cancel");
await removeSelectedSite(hosts.slice(0, 2));
assertSitesListed(doc, hosts.slice(2));
removeSelectedSite(fakeHosts.slice(0, 2));
assertSitesListed(doc, fakeHosts.slice(2));
cancelBtn.doCommand();
await settingsDialogClosePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button but canceling save
removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("cancel", REMOVE_DIALOG_URL);
@ -175,49 +182,44 @@ add_task(async function test_removePartialSites() {
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
saveBtn = frameDoc.getElementById("save");
cancelBtn = frameDoc.getElementById("cancel");
await removeSelectedSite(hosts.slice(0, 2));
assertSitesListed(doc, hosts.slice(2));
removeSelectedSite(fakeHosts.slice(0, 2));
assertSitesListed(doc, fakeHosts.slice(2));
saveBtn.doCommand();
await removeDialogOpenPromise;
cancelBtn.doCommand();
await settingsDialogClosePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
// Test the "Save Changes" button and accepting save
removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
settingsDialogClosePromise = promiseSettingsDialogClose();
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
saveBtn = frameDoc.getElementById("save");
await removeSelectedSite(hosts.slice(0, 2));
assertSitesListed(doc, hosts.slice(2));
removeSelectedSite(fakeHosts.slice(0, 2));
assertSitesListed(doc, fakeHosts.slice(2));
saveBtn.doCommand();
await removeDialogOpenPromise;
await settingsDialogClosePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts.slice(2));
assertSitesListed(doc, fakeHosts.slice(2));
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
function removeSelectedSite(removeHosts) {
function removeSelectedSite(hosts) {
frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
is(removeBtn.disabled, true, "Should start with disabled removeSelected button");
let sitesList = frameDoc.getElementById("sitesList");
removeHosts.forEach(host => {
hosts.forEach(host => {
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
if (site) {
site.click();
let currentSelectedIndex = sitesList.selectedIndex;
is(removeBtn.disabled, false, "Should enable the removeSelected button");
removeBtn.doCommand();
let newSelectedIndex = sitesList.selectedIndex;
if (currentSelectedIndex >= sitesList.itemCount) {
is(newSelectedIndex, currentSelectedIndex - 1);
} else {
is(newSelectedIndex, currentSelectedIndex);
}
is(sitesList.selectedIndex, currentSelectedIndex);
} else {
ok(false, `Should not select and remove inexistent site of ${host}`);
}
@ -227,7 +229,7 @@ add_task(async function test_removePartialSites() {
// Test searching and then removing only visible sites
add_task(async function() {
let hosts = await addTestData([
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
@ -249,9 +251,9 @@ add_task(async function() {
persisted: false,
},
]);
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
@ -263,7 +265,7 @@ add_task(async function() {
let searchBox = frameDoc.getElementById("searchBox");
searchBox.value = "xyz";
searchBox.doCommand();
assertSitesListed(doc, hosts.filter(host => host.includes("xyz")));
assertSitesListed(doc, fakeHosts.filter(host => host.includes("xyz")));
// Test only removing all visible sites listed
updatePromise = promiseSiteDataManagerSitesUpdated();
@ -277,15 +279,15 @@ add_task(async function() {
await settingsDialogClosePromise;
await updatePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts.filter(host => !host.includes("xyz")));
assertSitesListed(doc, fakeHosts.filter(host => !host.includes("xyz")));
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test dynamically clearing all site data
add_task(async function() {
let hosts = await addTestData([
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
@ -297,28 +299,28 @@ add_task(async function() {
persisted: false,
},
]);
let updatePromise = promiseSiteDataManagerSitesUpdated();
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
// Test the initial state
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
let doc = gBrowser.selectedBrowser.contentDocument;
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
await addTestData([
{
usage: 1024,
origin: "http://cinema.bar.com",
persisted: true,
},
{
usage: 1024,
origin: "http://email.bar.com",
persisted: false,
},
]);
// Add more sites dynamically
mockSiteDataManager.fakeSites.push({
usage: 1024,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
persisted: true,
}, {
usage: 1024,
principal: Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin("http://email.bar.com"),
persisted: false,
});
// Test clearing all site data dynamically
let win = gBrowser.selectedBrowser.contentWindow;
@ -336,6 +338,6 @@ add_task(async function() {
await openSiteDataSettingsDialog();
assertAllSitesNotListed(win);
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

View File

@ -1,8 +1,8 @@
"use strict";
// Test not displaying sites which store 0 byte and don't have persistent storage.
add_task(async function test_exclusions() {
let hosts = await addTestData([
add_task(async function() {
mockSiteDataManager.register(SiteDataManager, [
{
usage: 0,
origin: "https://account.xyz.com",
@ -30,22 +30,23 @@ add_task(async function test_exclusions() {
persisted: false,
},
]);
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
let updatePromise = promiseSiteDataManagerSitesUpdated();
let doc = gBrowser.selectedBrowser.contentDocument;
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts.filter(host => host != "shopping.xyz.com"));
assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com"));
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test grouping and listing sites across scheme, port and origin attributes by host
add_task(async function test_grouping() {
let quotaUsage = 7000000;
await addTestData([
add_task(async function() {
const quotaUsage = 1024;
mockSiteDataManager.register(SiteDataManager, [
{
usage: quotaUsage,
origin: "https://account.xyz.com^userContextId=1",
@ -90,51 +91,40 @@ add_task(async function test_grouping() {
is(columns[1].value, "5", "Should group cookies across scheme, port and origin attributes");
let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * 4);
let l10nAttributes = frameDoc.l10n.getAttributes(columns[2]);
is(l10nAttributes.id, "site-usage-persistent",
"Should show the site as persistent if one origin is persistent.");
// The shown quota can be slightly larger than the raw data we put in (though it should
// never be smaller), but that doesn't really matter to us since we only want to test that
// the site data dialog accumulates this into a single column.
ok(parseFloat(l10nAttributes.args.value) >= parseFloat(value),
"Should show the correct accumulated quota size.");
is(l10nAttributes.args.unit, unit, "Should show the correct quota size unit.");
let [value, unit] = DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length);
Assert.deepEqual(frameDoc.l10n.getAttributes(columns[2]), {
id: "site-usage-persistent",
args: { value, unit },
}, "Should sum up usages across scheme, port, origin attributes and persistent status");
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test sorting
add_task(async function test_sorting() {
let testData = [
add_task(async function() {
mockSiteDataManager.register(SiteDataManager, [
{
baseDomain: "xyz.com",
usage: 1024,
origin: "https://account.xyz.com",
cookies: 6,
persisted: true,
},
{
baseDomain: "foo.com",
usage: 1024 * 2,
origin: "https://books.foo.com",
cookies: 0,
persisted: false,
},
{
baseDomain: "bar.com",
usage: 1024 * 3,
origin: "http://cinema.bar.com",
cookies: 3,
persisted: true,
},
];
await addTestData(testData);
]);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
@ -145,42 +135,146 @@ add_task(async function test_sorting() {
let hostCol = frameDoc.getElementById("hostCol");
let usageCol = frameDoc.getElementById("usageCol");
let cookiesCol = frameDoc.getElementById("cookiesCol");
let lastAccessedCol = frameDoc.getElementById("lastAccessedCol");
let sitesList = frameDoc.getElementById("sitesList");
function getHostOrder() {
let siteItems = sitesList.getElementsByTagName("richlistitem");
return Array.from(siteItems).map(item => item.getAttribute("host"));
}
// Test default sorting by usage, descending.
Assert.deepEqual(getHostOrder(),
["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage");
// Test default sorting
assertSortByUsage("descending");
// Test sorting on the usage column
usageCol.click();
Assert.deepEqual(getHostOrder(),
["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted ascending by usage");
assertSortByUsage("ascending");
usageCol.click();
Assert.deepEqual(getHostOrder(),
["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted descending by usage");
assertSortByUsage("descending");
// Test sorting on the host column
hostCol.click();
Assert.deepEqual(getHostOrder(),
["cinema.bar.com", "books.foo.com", "account.xyz.com"], "Has sorted ascending by base domain");
assertSortByBaseDomain("ascending");
hostCol.click();
Assert.deepEqual(getHostOrder(),
["account.xyz.com", "books.foo.com", "cinema.bar.com"], "Has sorted descending by base domain");
assertSortByBaseDomain("descending");
// Test sorting on the cookies column
cookiesCol.click();
Assert.deepEqual(getHostOrder(),
["books.foo.com", "cinema.bar.com", "account.xyz.com"], "Has sorted ascending by cookies");
assertSortByCookies("ascending");
cookiesCol.click();
Assert.deepEqual(getHostOrder(),
["account.xyz.com", "cinema.bar.com", "books.foo.com"], "Has sorted descending by cookies");
assertSortByCookies("descending");
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
function assertSortByBaseDomain(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.baseDomain.localeCompare(b.baseDomain);
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host");
}
}
}
function assertSortByUsage(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.usage - b.usage;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage");
}
}
}
function assertSortByCookies(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.cookies.length - b.cookies.length;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies");
}
}
}
function findSiteByHost(host) {
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
}
});
// Test sorting based on access date (separate from cookies for simplicity,
// since cookies access date affects this as well, but we don't mock our cookies)
add_task(async function() {
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
persisted: true,
lastAccessed: (Date.now() - 120 * 1000) * 1000,
},
{
usage: 1024 * 2,
origin: "https://books.foo.com",
persisted: false,
lastAccessed: (Date.now() - 240 * 1000) * 1000,
},
{
usage: 1024 * 3,
origin: "http://cinema.bar.com",
persisted: true,
lastAccessed: Date.now() * 1000,
},
]);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatePromise;
await openSiteDataSettingsDialog();
let dialog = content.gSubDialog._topDialog;
let dialogFrame = dialog._frame;
let frameDoc = dialogFrame.contentDocument;
let lastAccessedCol = frameDoc.getElementById("lastAccessedCol");
let sitesList = frameDoc.getElementById("sitesList");
// Test sorting on the date column
lastAccessedCol.click();
assertSortByDate("ascending");
lastAccessedCol.click();
assertSortByDate("descending");
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
function assertSortByDate(order) {
let siteItems = sitesList.getElementsByTagName("richlistitem");
for (let i = 0; i < siteItems.length - 1; ++i) {
let aHost = siteItems[i].getAttribute("host");
let bHost = siteItems[i + 1].getAttribute("host");
let a = findSiteByHost(aHost);
let b = findSiteByHost(bHost);
let result = a.lastAccessed - b.lastAccessed;
if (order == "ascending") {
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by date");
} else {
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order date");
}
}
}
function findSiteByHost(host) {
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
}
});

View File

@ -2,40 +2,44 @@
// Test selecting and removing partial sites
add_task(async function() {
await SiteDataTestUtils.clear();
let hosts = await addTestData([
mockSiteDataManager.register(SiteDataManager, [
{
usage: 1024,
origin: "https://account.xyz.com",
persisted: true,
},
{
usage: 1024,
origin: "https://shopping.xyz.com",
persisted: false,
},
{
usage: 1024,
origin: "http://cinema.bar.com",
persisted: true,
},
{
usage: 1024,
origin: "http://email.bar.com",
persisted: false,
},
{
usage: 1024,
origin: "https://s3-us-west-2.amazonaws.com",
persisted: true,
},
{
usage: 1024,
origin: "https://127.0.0.1",
persisted: false,
},
{
usage: 1024 * 4,
origin: "http://cinema.bar.com",
usage: 1024,
origin: "https://[0:0:0:0:0:0:0:1]",
persisted: true,
},
{
usage: 1024 * 3,
origin: "http://email.bar.com",
persisted: false,
},
{
usage: 1024 * 2,
origin: "https://s3-us-west-2.amazonaws.com",
persisted: true,
},
{
usage: 1024 * 6,
origin: "https://account.xyz.com",
persisted: true,
},
{
usage: 1024 * 5,
origin: "https://shopping.xyz.com",
persisted: false,
},
]);
let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
let updatePromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
@ -45,21 +49,18 @@ add_task(async function() {
let doc = gBrowser.selectedBrowser.contentDocument;
// Test the initial state
assertSitesListed(doc, hosts);
assertSitesListed(doc, fakeHosts);
let win = gBrowser.selectedBrowser.contentWindow;
let frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
let removeBtn = frameDoc.getElementById("removeSelected");
is(removeBtn.disabled, true, "Should start with disabled removeSelected button");
let hostCol = frameDoc.getElementById("hostCol");
hostCol.click();
let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
let settingsDialogClosePromise = promiseSettingsDialogClose();
// Select some sites to remove.
let sitesList = frameDoc.getElementById("sitesList");
hosts.slice(0, 2).forEach(host => {
fakeHosts.slice(0, 2).forEach(host => {
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
sitesList.addItemToSelection(site);
});
@ -67,10 +68,10 @@ add_task(async function() {
is(removeBtn.disabled, false, "Should enable the removeSelected button");
removeBtn.doCommand();
is(sitesList.selectedIndex, 0, "Should select next item");
assertSitesListed(doc, hosts.slice(2));
assertSitesListed(doc, fakeHosts.slice(2));
// Select some other sites to remove with Delete.
hosts.slice(2, 4).forEach(host => {
fakeHosts.slice(2, 4).forEach(host => {
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
sitesList.addItemToSelection(site);
});
@ -78,21 +79,17 @@ add_task(async function() {
is(removeBtn.disabled, false, "Should enable the removeSelected button");
EventUtils.synthesizeKey("VK_DELETE");
is(sitesList.selectedIndex, 0, "Should select next item");
assertSitesListed(doc, hosts.slice(4));
assertSitesListed(doc, fakeHosts.slice(4));
updatePromise = promiseSiteDataManagerSitesUpdated();
let saveBtn = frameDoc.getElementById("save");
saveBtn.doCommand();
await removeDialogOpenPromise;
await settingsDialogClosePromise;
await updatePromise;
await openSiteDataSettingsDialog();
assertSitesListed(doc, hosts.slice(4));
assertSitesListed(doc, fakeHosts.slice(4));
await SiteDataTestUtils.clear();
await mockSiteDataManager.unregister();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

View File

@ -127,29 +127,66 @@ function assertSitesListed(doc, hosts) {
is(removeAllBtn.disabled, false, "Should enable the removeAllBtn button");
}
async function addTestData(data) {
let hosts = [];
const mockSiteDataManager = {
for (let site of data) {
is(typeof site.origin, "string", "Passed an origin string into addTestData.");
if (site.persisted) {
await SiteDataTestUtils.persist(site.origin);
_SiteDataManager: null,
_originalQMS: null,
_originalRemoveQuotaUsage: null,
getUsage(onUsageResult) {
let result = this.fakeSites.map(site => ({
origin: site.principal.origin,
usage: site.usage,
persisted: site.persisted,
lastAccessed: site.lastAccessed,
}));
onUsageResult({ result, resultCode: Cr.NS_OK });
},
_removeQuotaUsage(site) {
var target = site.principals[0].URI.host;
this.fakeSites = this.fakeSites.filter(fakeSite => {
return fakeSite.principal.URI.host != target;
});
},
register(siteDataManager, fakeSites) {
this._SiteDataManager = siteDataManager;
this._originalQMS = this._SiteDataManager._qms;
this._SiteDataManager._qms = this;
this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage;
this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this);
// Add some fake data.
this.fakeSites = fakeSites;
for (let site of fakeSites) {
if (!site.principal) {
site.principal = Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin(site.origin);
}
let uri = site.principal.URI;
try {
site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host);
} catch (e) {
site.baseDomain = uri.host;
}
// Add some cookies if needed.
for (let i = 0; i < (site.cookies || 0); i++) {
Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i,
false, false, false, Date.now() + 1000 * 60 * 60, {},
Ci.nsICookie2.SAMESITE_UNSET);
}
}
},
if (site.usage) {
await SiteDataTestUtils.addToIndexedDB(site.origin, site.usage);
}
for (let i = 0; i < (site.cookies || 0); i++) {
SiteDataTestUtils.addToCookies(site.origin, Cu.now());
}
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(site.origin);
hosts.push(principal.URI.host);
}
return hosts;
}
async unregister() {
await this._SiteDataManager.removeAll();
this.fakeSites = null;
this._SiteDataManager._qms = this._originalQMS;
this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage;
},
};
function promiseCookiesCleared() {
return TestUtils.topicObserved("cookie-changed", (subj, data) => {

View File

@ -3,6 +3,11 @@
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "OfflineAppCacheHelper",
"resource://gre/modules/offlineAppCache.jsm");
ChromeUtils.defineModuleGetter(this, "ServiceWorkerCleanUp",
"resource://gre/modules/ServiceWorkerCleanUp.jsm");
var EXPORTED_SYMBOLS = [
"SiteDataManager",
];
@ -320,23 +325,6 @@ var SiteDataManager = {
site.cookies = [];
},
// Returns a list of permissions from the permission manager that
// we consider part of "site data and cookies".
_getDeletablePermissions() {
let perms = [];
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
if (permission.type == "persistent-storage" ||
permission.type == "storage-access") {
perms.push(permission);
}
}
return perms;
},
/**
* Removes all site data for the specified list of hosts.
*
@ -345,28 +333,35 @@ var SiteDataManager = {
* manager has been updated.
*/
async remove(hosts) {
let perms = this._getDeletablePermissions();
// Make sure we have up-to-date information.
await this._getQuotaUsage();
this._updateAppCache();
let unknownHost = "";
let promises = [];
for (let host of hosts) {
promises.push(new Promise(function(resolve) {
Services.clearData.deleteDataFromHost(host, true,
Ci.nsIClearDataService.CLEAR_COOKIES |
Ci.nsIClearDataService.CLEAR_DOM_STORAGES |
Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS |
Ci.nsIClearDataService.CLEAR_PLUGIN_DATA |
Ci.nsIClearDataService.CLEAR_EME |
Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve);
}));
for (let perm of perms) {
if (Services.eTLD.hasRootDomain(perm.principal.URI.host, host)) {
Services.perms.removePermission(perm);
}
let site = this._sites.get(host);
if (site) {
// Clear localStorage & sessionStorage
Services.obs.notifyObservers(null, "extension:purge-localStorage", host);
Services.obs.notifyObservers(null, "browser:purge-sessionStorage", host);
this._removePermission(site);
this._removeAppCache(site);
this._removeCookies(site);
promises.push(ServiceWorkerCleanUp.removeFromHost(host));
promises.push(this._removeQuotaUsage(site));
} else {
unknownHost = host;
break;
}
}
await Promise.all(promises);
if (unknownHost) {
throw `SiteDataManager: removing unknown site of ${unknownHost}`;
}
return this.updateSites();
},
@ -410,41 +405,54 @@ var SiteDataManager = {
* @returns a Promise that resolves when the data is cleared.
*/
async removeAll() {
await this.removeCache();
this.removeCache();
return this.removeSiteData();
},
/**
* Clears all caches.
*
* @returns a Promise that resolves when the data is cleared.
* Clears the entire network cache.
*/
removeCache() {
return new Promise(function(resolve) {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL_CACHES, resolve);
});
Services.cache2.clear();
},
/**
* Clears all site data, but not cache, because the UI offers
* that functionality separately.
* Clears all site data, which currently means
* - Cookies
* - AppCache
* - LocalStorage
* - ServiceWorkers
* - Quota Managed Storage
* - persistent-storage permissions
*
* @returns a Promise that resolves when the data is cleared.
* @returns a Promise that resolves with the cache size on disk in bytes
*/
async removeSiteData() {
await new Promise(function(resolve) {
Services.clearData.deleteData(
Ci.nsIClearDataService.CLEAR_COOKIES |
Ci.nsIClearDataService.CLEAR_DOM_STORAGES |
Ci.nsIClearDataService.CLEAR_SECURITY_SETTINGS |
Ci.nsIClearDataService.CLEAR_EME |
Ci.nsIClearDataService.CLEAR_PLUGIN_DATA, resolve);
});
// LocalStorage
Services.obs.notifyObservers(null, "extension:purge-localStorage");
for (let permission of this._getDeletablePermissions()) {
Services.perms.removePermission(permission);
Services.cookies.removeAll();
OfflineAppCacheHelper.clear();
await ServiceWorkerCleanUp.removeAll();
// Refresh sites using quota usage again.
// This is for the case:
// 1. User goes to the about:preferences Site Data section.
// 2. With the about:preferences opened, user visits another website.
// 3. The website saves to quota usage, like indexedDB.
// 4. User goes back to the Site Data section and commands to clear all site data.
// For this case, we should refresh the site list so not to miss the website in the step 3.
// We don't do "Clear All" on the quota manager like the cookie, appcache, http cache above
// because that would clear browser data as well too,
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1312361#c9
this._sites.clear();
await this._getQuotaUsage();
let promises = [];
for (let site of this._sites.values()) {
this._removePermission(site);
promises.push(this._removeQuotaUsage(site));
}
return this.updateSites();
return Promise.all(promises).then(() => this.updateSites());
},
};

View File

@ -1,148 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
const EXAMPLE_ORIGIN = "https://www.example.com";
const EXAMPLE_ORIGIN_2 = "https://example.org";
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {SiteDataManager} = ChromeUtils.import("resource:///modules/SiteDataManager.jsm");
const {SiteDataTestUtils} = ChromeUtils.import("resource://testing-common/SiteDataTestUtils.jsm");
ChromeUtils.defineModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm");
ChromeUtils.defineModuleGetter(this, "TestUtils", "resource://testing-common/TestUtils.jsm");
add_task(function setup() {
do_get_profile();
});
add_task(async function testGetSites() {
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
await SiteDataManager.updateSites();
let sites = await SiteDataManager.getSites();
let site1 = sites.find((site) => site.baseDomain == "example.com");
let site2 = sites.find((site) => site.baseDomain == "example.org");
Assert.equal(site1.baseDomain, "example.com", "Has the correct base domain for example.com");
Assert.equal(site1.host, "www.example.com", "Has the correct host for example.com");
Assert.greater(site1.usage, 4096, "Has correct usage for example.com");
Assert.equal(site1.persisted, false, "example.com is not persisted");
Assert.equal(site1.cookies.length, 2, "Has correct number of cookies for example.com");
Assert.ok(typeof site1.lastAccessed.getDate == "function", "lastAccessed for example.com is a Date");
Assert.ok(site1.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.com happened recently");
Assert.equal(site2.baseDomain, "example.org", "Has the correct base domain for example.org");
Assert.equal(site2.host, "example.org", "Has the correct host for example.org");
Assert.greater(site2.usage, 2048, "Has correct usage for example.org");
Assert.equal(site2.persisted, true, "example.org is persisted");
Assert.equal(site2.cookies.length, 1, "Has correct number of cookies for example.org");
Assert.ok(typeof site2.lastAccessed.getDate == "function", "lastAccessed for example.org is a Date");
Assert.ok(site2.lastAccessed > Date.now() - 60 * 1000, "lastAccessed for example.org happened recently");
await SiteDataTestUtils.clear();
});
add_task(async function testGetTotalUsage() {
await SiteDataManager.updateSites();
let sites = await SiteDataManager.getSites();
Assert.equal(sites.length, 0, "SiteDataManager is empty");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
await SiteDataManager.updateSites();
let usage = await SiteDataManager.getTotalUsage();
Assert.greater(usage, 4096 + 2048, "Has the correct total usage.");
await SiteDataTestUtils.clear();
});
add_task(async function testRemove() {
await SiteDataManager.updateSites();
let uri = Services.io.newURI(EXAMPLE_ORIGIN);
Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
await SiteDataManager.updateSites();
let sites = await SiteDataManager.getSites();
Assert.equal(sites.length, 2, "Has two sites.");
await SiteDataManager.remove(["www.example.com"]);
sites = await SiteDataManager.getSites();
Assert.equal(sites.length, 1, "Has one site.");
Assert.equal(sites[0].host, "example.org", "Has not cleared data for example.org");
let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN);
Assert.equal(usage, 0, "Has cleared quota usage for example.com");
let cookies = Services.cookies.countCookiesFromHost("example.com");
Assert.equal(cookies, 0, "Has cleared cookies for example.com");
let perm = Services.perms.testPermission(uri, "persistent-storage");
Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission.");
perm = Services.perms.testPermission(uri, "camera");
Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions.");
Services.perms.remove(uri, "camera");
});
add_task(async function testRemoveSiteData() {
let uri = Services.io.newURI(EXAMPLE_ORIGIN);
Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
await SiteDataManager.updateSites();
let sites = await SiteDataManager.getSites();
Assert.equal(sites.length, 2, "Has two sites.");
await SiteDataManager.removeSiteData();
sites = await SiteDataManager.getSites();
Assert.equal(sites.length, 0, "Has no sites.");
let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN);
Assert.equal(usage, 0, "Has cleared quota usage for example.com");
usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN_2);
Assert.equal(usage, 0, "Has cleared quota usage for example.org");
let cookies = Services.cookies.countCookiesFromHost("example.org");
Assert.equal(cookies, 0, "Has cleared cookies for example.org");
let perm = Services.perms.testPermission(uri, "persistent-storage");
Assert.equal(perm, Services.perms.UNKNOWN_ACTION, "Cleared the persistent-storage permission.");
perm = Services.perms.testPermission(uri, "camera");
Assert.equal(perm, Services.perms.ALLOW_ACTION, "Did not clear other permissions.");
Services.perms.remove(uri, "camera");
});

View File

@ -8,6 +8,5 @@ skip-if = toolkit == 'android'
[test_LiveBookmarkMigrator.js]
[test_Sanitizer_interrupted.js]
[test_SitePermissions.js]
[test_SiteDataManager.js]
[test_LaterRun.js]
[test_discovery.js]