summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/sanitize/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/sanitize/head.js')
-rw-r--r--browser/base/content/test/sanitize/head.js366
1 files changed, 366 insertions, 0 deletions
diff --git a/browser/base/content/test/sanitize/head.js b/browser/base/content/test/sanitize/head.js
index f5a6031b84..30d96c69f6 100644
--- a/browser/base/content/test/sanitize/head.js
+++ b/browser/base/content/test/sanitize/head.js
@@ -3,10 +3,34 @@ ChromeUtils.defineESModuleGetters(this, {
FormHistory: "resource://gre/modules/FormHistory.sys.mjs",
PermissionTestUtils: "resource://testing-common/PermissionTestUtils.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
+ FileTestUtils: "resource://testing-common/FileTestUtils.sys.mjs",
Sanitizer: "resource:///modules/Sanitizer.sys.mjs",
SiteDataTestUtils: "resource://testing-common/SiteDataTestUtils.sys.mjs",
});
+const kMsecPerMin = 60 * 1000;
+const kUsecPerMin = kMsecPerMin * 1000;
+let today = Date.now() - new Date().setHours(0, 0, 0, 0);
+let nowMSec = Date.now();
+let nowUSec = nowMSec * 1000;
+const TEST_TARGET_FILE_NAME = "test-download.txt";
+const TEST_QUOTA_USAGE_HOST = "example.com";
+const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
+const TEST_QUOTA_USAGE_URL =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ TEST_QUOTA_USAGE_ORIGIN
+ ) + "site_data_test.html";
+const SITE_ORIGINS = [
+ "https://www.example.com",
+ "https://example.org",
+ "http://localhost:8000",
+ "http://localhost:3000",
+];
+
+let fileURL;
+
function createIndexedDB(host, originAttributes) {
let uri = Services.io.newURI("https://" + host);
let principal = Services.scriptSecurityManager.createContentPrincipal(
@@ -369,3 +393,345 @@ async function createDummyDataForHost(host) {
await SiteDataTestUtils.addToIndexedDB(origin);
await SiteDataTestUtils.addServiceWorker(dummySWURL);
}
+
+/**
+ * Helper function to create file URL to open
+ *
+ * @returns {Object} a file URL
+ */
+function createFileURL() {
+ if (!fileURL) {
+ let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ file.append("foo.txt");
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
+ fileURL = Services.io.newFileURI(file);
+ }
+ return fileURL;
+}
+
+/**
+ * Removes all history visits, downloads, and form entries.
+ */
+async function blankSlate() {
+ let publicList = await Downloads.getList(Downloads.PUBLIC);
+ let downloads = await publicList.getAll();
+ for (let download of downloads) {
+ await publicList.remove(download);
+ await download.finalize(true);
+ }
+
+ await FormHistory.update({ op: "remove" });
+ await PlacesUtils.history.clear();
+}
+
+/**
+ * Adds multiple downloads to the PUBLIC download list
+ */
+async function addToDownloadList() {
+ const url = createFileURL();
+ const downloadsList = await Downloads.getList(Downloads.PUBLIC);
+ let timeOptions = [1, 2, 4, 24, 128, 128];
+ let buffer = 100000;
+
+ for (let i = 0; i < timeOptions.length; i++) {
+ let timeDownloaded = 60 * kMsecPerMin * timeOptions[i];
+ if (timeOptions[i] === 24) {
+ timeDownloaded = today;
+ }
+
+ let download = await Downloads.createDownload({
+ source: { url: url.spec, isPrivate: false },
+ target: { path: FileTestUtils.getTempFile(TEST_TARGET_FILE_NAME).path },
+ startTime: {
+ getTime: _ => {
+ return nowMSec - timeDownloaded + buffer;
+ },
+ },
+ });
+
+ Assert.ok(!!download);
+ downloadsList.add(download);
+ }
+ let items = await downloadsList.getAll();
+ Assert.equal(items.length, 6, "Items were added to the list");
+}
+
+async function addToSiteUsage() {
+ // Fill indexedDB with test data.
+ // Don't wait for the page to load, to register the content event handler as quickly as possible.
+ // If this test goes intermittent, we might have to tell the page to wait longer before
+ // firing the event.
+ BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_QUOTA_USAGE_URL, false);
+ await BrowserTestUtils.waitForContentEvent(
+ gBrowser.selectedBrowser,
+ "test-indexedDB-done",
+ false,
+ null,
+ true
+ );
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+ let siteLastAccessed = [1, 2, 4, 24];
+
+ let staticUsage = 4096 * 6;
+ // Add a time buffer so the site access falls within the time range
+ const buffer = 10000;
+
+ // Change lastAccessed of sites
+ for (let index = 0; index < siteLastAccessed.length; index++) {
+ let lastAccessedTime = 60 * kMsecPerMin * siteLastAccessed[index];
+ if (siteLastAccessed[index] === 24) {
+ lastAccessedTime = today;
+ }
+
+ let site = SiteDataManager._testInsertSite(SITE_ORIGINS[index], {
+ quotaUsage: staticUsage,
+ lastAccessed: (nowMSec - lastAccessedTime + buffer) * 1000,
+ });
+ Assert.ok(site, "Site added successfully");
+ }
+}
+
+function promiseSanitizationComplete() {
+ return TestUtils.topicObserved("sanitizer-sanitization-complete");
+}
+
+/**
+ * This wraps the dialog and provides some convenience methods for interacting
+ * with it.
+ *
+ * @param {Window} browserWin (optional)
+ * The browser window that the dialog is expected to open in. If not
+ * supplied, the initial browser window of the test run is used.
+ * @param {Object} {mode, checkingDataSizes}
+ * mode: context to open the dialog in
+ * One of
+ * clear on shutdown settings context ("clearOnShutdown"),
+ * clear site data settings context ("clearSiteData"),
+ * clear history context ("clearHistory"),
+ * browser context ("browser")
+ * "browser" by default
+ * checkingDataSizes: boolean check if we should wait for the data sizes
+ * to load
+ *
+ */
+function ClearHistoryDialogHelper({
+ mode = "browser",
+ checkingDataSizes = false,
+} = {}) {
+ this._browserWin = window;
+ this.win = null;
+ this._mode = mode;
+ this._checkingDataSizes = checkingDataSizes;
+ this.promiseClosed = new Promise(resolve => {
+ this._resolveClosed = resolve;
+ });
+}
+
+ClearHistoryDialogHelper.prototype = {
+ /**
+ * "Presses" the dialog's OK button.
+ */
+ acceptDialog() {
+ let dialogEl = this.win.document.querySelector("dialog");
+ is(
+ dialogEl.getButton("accept").disabled,
+ false,
+ "Dialog's OK button should not be disabled"
+ );
+ dialogEl.acceptDialog();
+ },
+
+ /**
+ * "Presses" the dialog's Cancel button.
+ */
+ cancelDialog() {
+ this.win.document.querySelector("dialog").cancelDialog();
+ },
+
+ /**
+ * (Un)checks a history scope checkbox (browser & download history,
+ * form history, etc.).
+ *
+ * @param aPrefName
+ * The final portion of the checkbox's privacy.cpd.* preference name
+ * @param aCheckState
+ * True if the checkbox should be checked, false otherwise
+ */
+ checkPrefCheckbox(aPrefName, aCheckState) {
+ var cb = this.win.document.querySelectorAll(
+ "checkbox[id='" + aPrefName + "']"
+ );
+ is(cb.length, 1, "found checkbox for " + aPrefName + " id");
+ if (cb[0].checked != aCheckState) {
+ cb[0].click();
+ }
+ },
+
+ /**
+ * @param {String} aCheckboxId
+ * The checkbox id name
+ * @param {Boolean} aCheckState
+ * True if the checkbox should be checked, false otherwise
+ */
+ validateCheckbox(aCheckboxId, aCheckState) {
+ let cb = this.win.document.querySelectorAll(
+ "checkbox[id='" + aCheckboxId + "']"
+ );
+ is(cb.length, 1, `found checkbox for id=${aCheckboxId}`);
+ is(
+ cb[0].checked,
+ aCheckState,
+ `checkbox for ${aCheckboxId} is ${aCheckState}`
+ );
+ },
+
+ /**
+ * Makes sure all the checkboxes are checked.
+ */
+ _checkAllCheckboxesCustom(check) {
+ var cb = this.win.document.querySelectorAll(".clearingItemCheckbox");
+ ok(cb.length, "found checkboxes for ids");
+ for (var i = 0; i < cb.length; ++i) {
+ if (cb[i].checked != check) {
+ cb[i].click();
+ }
+ }
+ },
+
+ checkAllCheckboxes() {
+ this._checkAllCheckboxesCustom(true);
+ },
+
+ uncheckAllCheckboxes() {
+ this._checkAllCheckboxesCustom(false);
+ },
+
+ /**
+ * @return The dialog's duration dropdown
+ */
+ getDurationDropdown() {
+ return this.win.document.getElementById("sanitizeDurationChoice");
+ },
+
+ /**
+ * @return The clear-everything warning box
+ */
+ getWarningPanel() {
+ return this.win.document.getElementById("sanitizeEverythingWarningBox");
+ },
+
+ /**
+ * @return True if the "Everything" warning panel is visible (as opposed to
+ * the tree)
+ */
+ isWarningPanelVisible() {
+ return !this.getWarningPanel().hidden;
+ },
+
+ /**
+ * Opens the clear recent history dialog. Before calling this, set
+ * this.onload to a function to execute onload. It should close the dialog
+ * when done so that the tests may continue. Set this.onunload to a function
+ * to execute onunload. this.onunload is optional. If it returns true, the
+ * caller is expected to call promiseAsyncUpdates at some point; if false is
+ * returned, promiseAsyncUpdates is called automatically.
+ */
+ async open() {
+ let dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
+ null,
+ "chrome://browser/content/sanitize_v2.xhtml",
+ {
+ isSubDialog: true,
+ }
+ );
+
+ // We want to simulate opening the dialog inside preferences for clear history
+ // and clear site data
+ if (this._mode != "browser") {
+ await openPreferencesViaOpenPreferencesAPI("privacy", {
+ leaveOpen: true,
+ });
+ let tabWindow = gBrowser.selectedBrowser.contentWindow;
+ let clearDialogOpenButtonId = this._mode + "Button";
+ // the id for clear on shutdown is of a different format
+ if (this._mode == "clearOnShutdown") {
+ // set always clear to true to enable the clear on shutdown dialog
+ let enableSettingsCheckbox =
+ tabWindow.document.getElementById("alwaysClear");
+ if (!enableSettingsCheckbox.checked) {
+ enableSettingsCheckbox.click();
+ }
+ clearDialogOpenButtonId = "clearDataSettings";
+ }
+ // open dialog
+ tabWindow.document.getElementById(clearDialogOpenButtonId).click();
+ }
+ // We open the dialog in the chrome context in other cases
+ else {
+ executeSoon(() => {
+ Sanitizer.showUI(this._browserWin, this._mode);
+ });
+ }
+
+ this.win = await dialogPromise;
+ this.win.addEventListener(
+ "load",
+ () => {
+ // Run onload on next tick so that gSanitizePromptDialog.init can run first.
+ executeSoon(async () => {
+ if (this._checkingDataSizes) {
+ // we wait for the data sizes to load to avoid async errors when validating sizes
+ await this.win.gSanitizePromptDialog
+ .dataSizesFinishedUpdatingPromise;
+ }
+ this.onload();
+ });
+ },
+ { once: true }
+ );
+ this.win.addEventListener(
+ "unload",
+ () => {
+ // Some exceptions that reach here don't reach the test harness, but
+ // ok()/is() do...
+ (async () => {
+ if (this.onunload) {
+ await this.onunload();
+ }
+ if (this._mode != "browser") {
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+ await PlacesTestUtils.promiseAsyncUpdates();
+ this._resolveClosed();
+ this.win = null;
+ })();
+ },
+ { once: true }
+ );
+ },
+
+ /**
+ * Selects a duration in the duration dropdown.
+ *
+ * @param aDurVal
+ * One of the Sanitizer.TIMESPAN_* values
+ */
+ selectDuration(aDurVal) {
+ this.getDurationDropdown().value = aDurVal;
+ if (aDurVal === Sanitizer.TIMESPAN_EVERYTHING) {
+ is(
+ this.isWarningPanelVisible(),
+ true,
+ "Warning panel should be visible for TIMESPAN_EVERYTHING"
+ );
+ } else {
+ is(
+ this.isWarningPanelVisible(),
+ false,
+ "Warning panel should not be visible for non-TIMESPAN_EVERYTHING"
+ );
+ }
+ },
+};