summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/test/browser/storage_access_head.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/antitracking/test/browser/storage_access_head.js')
-rw-r--r--toolkit/components/antitracking/test/browser/storage_access_head.js281
1 files changed, 281 insertions, 0 deletions
diff --git a/toolkit/components/antitracking/test/browser/storage_access_head.js b/toolkit/components/antitracking/test/browser/storage_access_head.js
new file mode 100644
index 0000000000..ea4f67b4fe
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/storage_access_head.js
@@ -0,0 +1,281 @@
+/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
+/* import-globals-from antitracking_head.js */
+
+async function openPageAndRunCode(
+ topPage,
+ topPageCallback,
+ embeddedPage,
+ embeddedPageCallback
+) {
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: topPage,
+ waitForLoad: true,
+ });
+ let browser = gBrowser.getBrowserForTab(tab);
+
+ await topPageCallback();
+ await SpecialPowers.spawn(
+ browser,
+ [{ page: embeddedPage, callback: embeddedPageCallback.toString() }],
+ async function (obj) {
+ await new content.Promise(resolve => {
+ let ifr = content.document.createElement("iframe");
+ ifr.onload = function () {
+ ifr.contentWindow.postMessage(obj.callback, "*");
+ };
+
+ content.addEventListener("message", function msg(event) {
+ if (event.data.type == "finish") {
+ content.removeEventListener("message", msg);
+ resolve();
+ return;
+ }
+
+ if (event.data.type == "ok") {
+ ok(event.data.what, event.data.msg);
+ return;
+ }
+
+ if (event.data.type == "info") {
+ info(event.data.msg);
+ return;
+ }
+
+ ok(false, "Unknown message");
+ });
+
+ content.document.body.appendChild(ifr);
+ ifr.src = obj.page;
+ });
+ }
+ );
+
+ await BrowserTestUtils.removeTab(tab);
+}
+
+// This function returns a function that spawns an asynchronous task to handle
+// the popup and click on the appropriate values. If that task is never executed
+// the catch case is reached and we fail the test. If for some reason that catch
+// case isn't reached, having an extra event listener at the end of the test
+// will cause the test to fail anyway.
+// Note: this means that tests that use this callback should probably be in
+// their own test file.
+function getExpectPopupAndClick(accept) {
+ return function () {
+ let shownPromise = BrowserTestUtils.waitForEvent(
+ PopupNotifications.panel,
+ "popupshown"
+ );
+ shownPromise
+ .then(async _ => {
+ // This occurs when the promise resolves on the test finishing
+ let popupNotifications = PopupNotifications.panel.childNodes;
+ if (!popupNotifications.length) {
+ ok(false, "Prompt did not show up");
+ } else if (accept == "accept") {
+ ok(true, "Prompt shows up, clicking accept.");
+ await clickMainAction();
+ } else if (accept == "reject") {
+ ok(true, "Prompt shows up, clicking reject.");
+ await clickSecondaryAction();
+ } else {
+ ok(false, "Unknown accept value for test: " + accept);
+ info("Clicking accept so that the test can finish.");
+ await clickMainAction();
+ }
+ })
+ .catch(() => {
+ ok(false, "Prompt did not show up");
+ });
+ };
+}
+
+// Click popup after a delay of {timeout} ms
+function getExpectPopupAndClickAfterDelay(accept, timeout) {
+ return function () {
+ let shownPromise = BrowserTestUtils.waitForEvent(
+ PopupNotifications.panel,
+ "popupshown"
+ );
+ shownPromise
+ .then(
+ setTimeout(async _ => {
+ // This occurs when the promise resolves on the test finishing
+ let popupNotifications = PopupNotifications.panel.childNodes;
+ if (!popupNotifications.length) {
+ ok(false, "Prompt did not show up");
+ } else if (accept == "accept") {
+ ok(true, "Prompt shows up, clicking accept.");
+ await clickMainAction();
+ } else if (accept == "reject") {
+ ok(true, "Prompt shows up, clicking reject.");
+ await clickSecondaryAction();
+ } else {
+ ok(false, "Unknown accept value for test: " + accept);
+ info("Clicking accept so that the test can finish.");
+ await clickMainAction();
+ }
+ }, timeout)
+ )
+ .catch(() => {
+ ok(false, "Prompt did not show up");
+ });
+ };
+}
+
+// This function spawns an asynchronous task that fails the test if a popup
+// appears. If that never happens, the catch case is executed on the test
+// cleanup.
+// Note: this means that tests that use this callback should probably be in
+// their own test file.
+function expectNoPopup() {
+ let shownPromise = BrowserTestUtils.waitForEvent(
+ PopupNotifications.panel,
+ "popupshown"
+ );
+ shownPromise
+ .then(async _ => {
+ // This occurs when the promise resolves on the test finishing
+ let popupNotifications = PopupNotifications.panel.childNodes;
+ if (!popupNotifications.length) {
+ ok(true, "Prompt did not show up");
+ } else {
+ ok(false, "Prompt shows up");
+ info(PopupNotifications.panel);
+ await clickSecondaryAction();
+ }
+ })
+ .catch(() => {
+ ok(true, "Prompt did not show up");
+ });
+}
+
+async function requestStorageAccessAndExpectSuccess() {
+ const aps = SpecialPowers.Services.prefs.getBoolPref(
+ "privacy.partition.always_partition_third_party_non_cookie_storage"
+ );
+
+ // When always partitioning storage, we do not clear non-cookie storage
+ // after a requestStorageAccess is accepted by the user. So here we test
+ // that indexedDB is cleared when the pref is off, but not when it is on.
+ await new Promise((resolve, reject) => {
+ const db = window.indexedDB.open("rSATest", 1);
+ db.onupgradeneeded = resolve;
+ db.success = resolve;
+ db.onerror = reject;
+ });
+
+ const hadAccessAlready = await document.hasStorageAccess();
+ const shouldClearIDB = !aps && !hadAccessAlready;
+
+ SpecialPowers.wrap(document).notifyUserGestureActivation();
+ let p = document.requestStorageAccess();
+ try {
+ await p;
+ ok(true, "gain storage access.");
+ } catch {
+ ok(false, "denied storage access.");
+ }
+
+ await new Promise((resolve, reject) => {
+ const req = window.indexedDB.open("rSATest", 1);
+ req.onerror = reject;
+ req.onupgradeneeded = () => {
+ ok(shouldClearIDB, "iDB was cleared");
+ req.onsuccess = undefined;
+ resolve();
+ };
+ req.onsuccess = () => {
+ ok(!shouldClearIDB, "iDB was not cleared");
+ resolve();
+ };
+ });
+
+ await new Promise(resolve => {
+ const req = window.indexedDB.deleteDatabase("rSATest");
+ req.onsuccess = resolve;
+ req.onerror = resolve;
+ });
+
+ SpecialPowers.wrap(document).clearUserGestureActivation();
+}
+
+async function requestStorageAccessAndExpectFailure() {
+ // When always partitioning storage, we do not clear non-cookie storage
+ // after a requestStorageAccess is accepted by the user. So here we test
+ // that indexedDB is cleared when the pref is off, but not when it is on.
+ await new Promise((resolve, reject) => {
+ const db = window.indexedDB.open("rSATest", 1);
+ db.onupgradeneeded = resolve;
+ db.success = resolve;
+ db.onerror = reject;
+ });
+
+ SpecialPowers.wrap(document).notifyUserGestureActivation();
+ let p = document.requestStorageAccess();
+ try {
+ await p;
+ ok(false, "gain storage access.");
+ } catch {
+ ok(true, "denied storage access.");
+ }
+
+ await new Promise((resolve, reject) => {
+ const req = window.indexedDB.open("rSATest", 1);
+ req.onerror = reject;
+ req.onupgradeneeded = () => {
+ ok(false, "iDB was cleared");
+ req.onsuccess = undefined;
+ resolve();
+ };
+ req.onsuccess = () => {
+ ok(true, "iDB was not cleared");
+ resolve();
+ };
+ });
+
+ await new Promise(resolve => {
+ const req = window.indexedDB.deleteDatabase("rSATest");
+ req.onsuccess = resolve;
+ req.onerror = resolve;
+ });
+
+ SpecialPowers.wrap(document).clearUserGestureActivation();
+}
+
+async function cleanUpData() {
+ await new Promise(resolve => {
+ Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
+ resolve()
+ );
+ });
+ ok(true, "Deleted all data.");
+}
+
+async function setPreferences(alwaysPartitionStorage = true) {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.storage_access.auto_grants", true],
+ ["dom.storage_access.auto_grants.delayed", false],
+ ["dom.storage_access.enabled", true],
+ ["dom.storage_access.max_concurrent_auto_grants", 0],
+ ["dom.storage_access.prompt.testing", false],
+ [
+ "network.cookie.cookieBehavior",
+ Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
+ ],
+ [
+ "network.cookie.cookieBehavior.pbmode",
+ Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
+ ],
+ [
+ "privacy.partition.always_partition_third_party_non_cookie_storage",
+ alwaysPartitionStorage,
+ ],
+ ["privacy.trackingprotection.enabled", false],
+ ["privacy.trackingprotection.pbmode.enabled", false],
+ ["privacy.trackingprotection.annotate_channels", true],
+ ],
+ });
+}