fune/browser/components/preferences/in-content/tests/browser_siteData.js
Coroiu Cristina fe07e42eba Backed out 1 changesets (bug 1428844) on request from johannh
Backed out changeset 44239d2b430a (bug 1428844)
2018-01-23 14:02:25 +02:00

342 lines
14 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/* global sinon */
Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js");
const TEST_QUOTA_USAGE_HOST = "example.com";
const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/site_data_test.html";
const TEST_OFFLINE_HOST = "example.org";
const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/offline/offline.html";
const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/service_worker_test.html";
const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const { DownloadUtils } = Cu.import("resource://gre/modules/DownloadUtils.jsm", {});
const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {});
const { OfflineAppCacheHelper } = Cu.import("resource:///modules/offlineAppCache.jsm", {});
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager");
const mockOfflineAppCacheHelper = {
clear: null,
originalClear: null,
register() {
this.originalClear = OfflineAppCacheHelper.clear;
this.clear = sinon.spy();
OfflineAppCacheHelper.clear = this.clear;
},
unregister() {
OfflineAppCacheHelper.clear = this.originalClear;
}
};
function getPersistentStoragePermStatus(origin) {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
return Services.perms.testExactPermissionFromPrincipal(principal, "persistent-storage");
}
function getQuotaUsage(origin) {
return new Promise(resolve => {
let uri = NetUtil.newURI(origin);
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
});
}
// XXX: The intermittent bug 1331851
// The implementation of nsICacheStorageConsumptionObserver must be passed as weak referenced,
// so we must hold this observer here well. If we didn't, there would be a chance that
// in Linux debug test run the observer was released before the operation at gecko was completed
// (may be because of a relatively quicker GC cycle or a relatively slower operation).
// As a result of that, we would never get the cache usage we want so the test would fail from timeout.
const cacheUsageGetter = {
_promise: null,
_resolve: null,
get() {
if (!this._promise) {
this._promise = new Promise(resolve => {
this._resolve = resolve;
Services.cache2.asyncGetDiskConsumption(this);
});
}
return this._promise;
},
// nsICacheStorageConsumptionObserver implementations
onNetworkCacheDiskConsumption(usage) {
cacheUsageGetter._promise = null;
cacheUsageGetter._resolve(usage);
},
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.nsICacheStorageConsumptionObserver,
Components.interfaces.nsISupportsWeakReference
]),
};
function promiseCookiesCleared() {
return TestUtils.topicObserved("cookie-changed", (subj, data) => {
return data === "cleared";
});
}
async function loadServiceWorkerTestPage(url) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
await BrowserTestUtils.waitForCondition(() => {
return ContentTask.spawn(tab.linkedBrowser, {}, () =>
content.document.body.getAttribute("data-test-service-worker-registered") === "true");
}, `Fail to load service worker test ${url}`);
await BrowserTestUtils.removeTab(tab);
}
function promiseServiceWorkerRegisteredFor(url) {
return BrowserTestUtils.waitForCondition(() => {
try {
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(url);
let sw = serviceWorkerManager.getRegistrationByPrincipal(principal, principal.URI.spec);
if (sw) {
ok(true, `Found the service worker registered for ${url}`);
return true;
}
} catch (e) {}
return false;
}, `Should register service worker for ${url}`);
}
function promiseServiceWorkersCleared() {
return BrowserTestUtils.waitForCondition(() => {
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
if (serviceWorkers.length == 0) {
ok(true, "Cleared all service workers");
return true;
}
return false;
}, "Should clear all service workers");
}
registerCleanupFunction(function() {
delete window.sinon;
mockOfflineAppCacheHelper.unregister();
});
// Test listing site using quota usage or site using appcache
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Open a test site which would save into appcache
await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_OFFLINE_URL);
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Open a test site which would save into quota manager
await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL);
// eslint-disable-next-line mozilla/no-cpows-in-tests
await waitForEvent(gBrowser.selectedBrowser.contentWindowAsCPOW, "test-indexedDB-done");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
let updatedPromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatedPromise;
await openSiteDataSettingsDialog();
// eslint-disable-next-line mozilla/no-cpows-in-tests
let dialog = content.gSubDialog._topDialog;
let dialogFrame = dialog._frame;
let frameDoc = dialogFrame.contentDocument;
let siteItems = frameDoc.getElementsByTagName("richlistitem");
is(siteItems.length, 2, "Should list sites using quota usage or appcache");
let appcacheSite = frameDoc.querySelector(`richlistitem[host="${TEST_OFFLINE_HOST}"]`);
ok(appcacheSite, "Should list site using appcache");
let qoutaUsageSite = frameDoc.querySelector(`richlistitem[host="${TEST_QUOTA_USAGE_HOST}"]`);
ok(qoutaUsageSite, "Should list site using quota usage");
// Always remember to clean up
OfflineAppCacheHelper.clear();
await new Promise(resolve => {
let principal = Services.scriptSecurityManager
.createCodebasePrincipalFromOrigin(TEST_QUOTA_USAGE_ORIGIN);
let request = Services.qms.clearStoragesForPrincipal(principal, null, true);
request.callback = resolve;
});
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test buttons are disabled and loading message shown while updating sites
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
let updatedPromise = promiseSiteDataManagerSitesUpdated();
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
await updatedPromise;
let actual = null;
let expected = null;
let doc = gBrowser.selectedBrowser.contentDocument;
let clearBtn = doc.getElementById("clearSiteDataButton");
let settingsButton = doc.getElementById("siteDataSettings");
let prefStrBundle = doc.getElementById("bundlePreferences");
let totalSiteDataSizeLabel = doc.getElementById("totalSiteDataSize");
is(clearBtn.disabled, false, "Should enable clear button after sites updated");
is(settingsButton.disabled, false, "Should enable settings button after sites updated");
await SiteDataManager.getTotalUsage()
.then(usage => {
actual = totalSiteDataSizeLabel.textContent;
expected = prefStrBundle.getFormattedString(
"totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
is(actual, expected, "Should show the right total site data size");
});
Services.obs.notifyObservers(null, "sitedatamanager:updating-sites");
is(clearBtn.disabled, true, "Should disable clear button while updating sites");
is(settingsButton.disabled, true, "Should disable settings button while updating sites");
actual = totalSiteDataSizeLabel.textContent;
expected = prefStrBundle.getString("loadingSiteDataSize");
is(actual, expected, "Should show the loading message while updating");
Services.obs.notifyObservers(null, "sitedatamanager:sites-updated");
is(clearBtn.disabled, false, "Should enable clear button after sites updated");
is(settingsButton.disabled, false, "Should enable settings button after sites updated");
await SiteDataManager.getTotalUsage()
.then(usage => {
actual = totalSiteDataSizeLabel.textContent;
expected = prefStrBundle.getFormattedString(
"totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
is(actual, expected, "Should show the right total site data size");
});
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test the function of the "Clear All Data" button
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
addPersistentStoragePerm(TEST_QUOTA_USAGE_ORIGIN);
await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL);
// eslint-disable-next-line mozilla/no-cpows-in-tests
await waitForEvent(gBrowser.selectedBrowser.contentWindowAsCPOW, "test-indexedDB-done");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
// Test the initial states
let cacheUsage = await cacheUsageGetter.get();
let quotaUsage = await getQuotaUsage(TEST_QUOTA_USAGE_ORIGIN);
let totalUsage = await SiteDataManager.getTotalUsage();
Assert.greater(cacheUsage, 0, "The cache usage should not be 0");
Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
Assert.greater(totalUsage, 0, "The total usage should not be 0");
// Test cancelling "Clear All Data"
// Click "Clear All Data" button and then cancel
let doc = gBrowser.selectedBrowser.contentDocument;
let cancelPromise = promiseAlertDialogOpen("cancel");
let clearBtn = doc.getElementById("clearSiteDataButton");
clearBtn.doCommand();
await cancelPromise;
// Test the items are not removed
let status = getPersistentStoragePermStatus(TEST_QUOTA_USAGE_ORIGIN);
is(status, Ci.nsIPermissionManager.ALLOW_ACTION, "Should not remove permission");
cacheUsage = await cacheUsageGetter.get();
quotaUsage = await getQuotaUsage(TEST_QUOTA_USAGE_ORIGIN);
totalUsage = await SiteDataManager.getTotalUsage();
Assert.greater(cacheUsage, 0, "The cache usage should not be 0");
Assert.greater(quotaUsage, 0, "The quota usage should not be 0");
Assert.greater(totalUsage, 0, "The total usage should not be 0");
// Test cancelling "Clear All Data" ends
// Test accepting "Clear All Data"
// Click "Clear All Data" button and then accept
let acceptPromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
let cookiesClearedPromise = promiseCookiesCleared();
mockOfflineAppCacheHelper.register();
clearBtn.doCommand();
await acceptPromise;
await updatePromise;
mockOfflineAppCacheHelper.unregister();
// Test all the items are removed
await cookiesClearedPromise;
ok(mockOfflineAppCacheHelper.clear.calledOnce, "Should clear app cache");
status = getPersistentStoragePermStatus(TEST_QUOTA_USAGE_ORIGIN);
is(status, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Should remove permission");
cacheUsage = await cacheUsageGetter.get();
quotaUsage = await getQuotaUsage(TEST_QUOTA_USAGE_ORIGIN);
totalUsage = await SiteDataManager.getTotalUsage();
is(cacheUsage, 0, "The cache usage should be removed");
is(quotaUsage, 0, "The quota usage should be removed");
is(totalUsage, 0, "The total usage should be removed");
// Test accepting "Clear All Data" ends
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test clearing service wroker through the "Clear All" button
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Register a test service
await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
// Test the initial states
await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);
// Click the "Clear All" button
let doc = gBrowser.selectedBrowser.contentDocument;
let clearBtn = doc.getElementById("clearSiteDataButton");
let acceptPromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
clearBtn.doCommand();
await acceptPromise;
await updatePromise;
await promiseServiceWorkersCleared();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Test clearing service wroker through the settings panel
add_task(async function() {
await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
// Register a test service worker
await loadServiceWorkerTestPage(TEST_SERVICE_WORKER_URL);
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
// Test the initial states
await promiseServiceWorkerRegisteredFor(TEST_SERVICE_WORKER_URL);
// Open the Site Data Settings panel and remove the site
await openSiteDataSettingsDialog();
let acceptRemovePromise = promiseAlertDialogOpen("accept");
let updatePromise = promiseSiteDataManagerSitesUpdated();
ContentTask.spawn(gBrowser.selectedBrowser, { TEST_OFFLINE_HOST }, args => {
let host = args.TEST_OFFLINE_HOST;
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
let sitesList = frameDoc.getElementById("sitesList");
let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
if (site) {
let removeBtn = frameDoc.getElementById("removeSelected");
let saveBtn = frameDoc.getElementById("save");
site.click();
removeBtn.doCommand();
saveBtn.doCommand();
} else {
ok(false, `Should have one site of ${host}`);
}
});
await acceptRemovePromise;
await updatePromise;
await promiseServiceWorkersCleared();
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});