Bug 1490811 - Part 3: Add an automated end-to-end integration test for the functionality of the storage access prompt r=baku
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 26 Nov 2018 21:23:20 +0000
changeset 504564 0c537d7bf40a6dff095bf73dfa1a7455ef02956f
parent 504563 f2bf86926c655278bd1d0319b70eef55450bcee5
child 504565 d3b46f3a0306aaf4dda9f47fb4f02bc66f3ba562
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1490811
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1490811 - Part 3: Add an automated end-to-end integration test for the functionality of the storage access prompt r=baku This test checks the functionality of the prompt using the utilities of the antitracking test suite. It provides a complete end-to-end test for the functionality of the prompts integrated with the API, including the necessity to interact with a tracker and implicitly ensuring we do not show a prompt in that case too. Depends on D12507 Differential Revision: https://phabricator.services.mozilla.com/D12723
toolkit/components/antitracking/test/browser/browser.ini
toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
--- a/toolkit/components/antitracking/test/browser/browser.ini
+++ b/toolkit/components/antitracking/test/browser/browser.ini
@@ -51,16 +51,17 @@ skip-if = serviceworker_e10s
 skip-if = serviceworker_e10s
 [browser_siteSpecificWorkArounds.js]
 [browser_subResources.js]
 skip-if = serviceworker_e10s
 support-files = subResources.sjs
 [browser_script.js]
 support-files = tracker.js
 [browser_userInteraction.js]
+[browser_storageAccessDoorHanger.js]
 [browser_storageAccessPrivateWindow.js]
 skip-if = serviceworker_e10s
 [browser_storageAccessPromiseResolveHandlerUserInteraction.js]
 [browser_storageAccessRemovalNavigateSubframe.js]
 skip-if = serviceworker_e10s
 [browser_storageAccessSandboxed.js]
 skip-if = serviceworker_e10s
 [browser_storageAccessWithHeuristics.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
@@ -0,0 +1,186 @@
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const CHROME_BASE = "chrome://mochitests/content/browser/browser/modules/test/browser/";
+Services.scriptloader.loadSubScript(CHROME_BASE + "head.js", this);
+/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
+
+async function testDoorHanger(choice) {
+  info(`Running doorhanger test with choice #${choice}`);
+
+  await SpecialPowers.flushPrefEnv();
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["browser.contentblocking.allowlist.annotations.enabled", true],
+    ["browser.contentblocking.allowlist.storage.enabled", true],
+    [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
+    ["browser.fastblock.enabled", false],
+    ["dom.storage_access.enabled", true],
+    ["dom.storage_access.prompt.testing", false],
+    ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
+    ["privacy.trackingprotection.enabled", false],
+    ["privacy.trackingprotection.pbmode.enabled", false],
+    ["privacy.trackingprotection.annotate_channels", true],
+    ["privacy.restrict3rdpartystorage.userInteractionRequiredForHosts", "tracking.example.com,tracking.example.org"],
+  ]});
+
+  await UrlClassifierTestUtils.addTestTrackers();
+
+  let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
+  gBrowser.selectedTab = tab;
+
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  async function runChecks() {
+    await new Promise(resolve => {
+      addEventListener("message", function onMessage(e) {
+        if (e.data.startsWith("choice:")) {
+          window.choice = e.data.split(":")[1];
+          removeEventListener("message", onMessage);
+          resolve();
+        }
+      }, false);
+      parent.postMessage("getchoice", "*");
+    });
+
+    /* import-globals-from storageAccessAPIHelpers.js */
+    await noStorageAccessInitially();
+
+    is(document.cookie, "", "No cookies for me");
+    document.cookie = "name=value";
+    is(document.cookie, "", "No cookies for me");
+
+    await fetch("server.sjs").then(r => r.text()).then(text => {
+      is(text, "cookie-not-present", "We should not have cookies");
+    });
+    // Let's do it twice.
+    await fetch("server.sjs").then(r => r.text()).then(text => {
+      is(text, "cookie-not-present", "We should not have cookies");
+    });
+
+    is(document.cookie, "", "Still no cookies for me");
+
+    /* import-globals-from storageAccessAPIHelpers.js */
+    await callRequestStorageAccess();
+
+    if (choice == 0) {
+      // We've said no, so cookies are still blocked
+      is(document.cookie, "", "Still no cookies for me");
+      document.cookie = "name=value";
+      is(document.cookie, "", "No cookies for me");
+    } else {
+      // We've said yes, so cookies are allowed now
+      is(document.cookie, "", "No cookies for me");
+      document.cookie = "name=value";
+      is(document.cookie, "name=value", "I have the cookies!");
+    }
+  }
+
+  let shownPromise =
+    BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
+  shownPromise.then(async _ => {
+    let notification =
+      PopupNotifications.getNotification("storage-access", browser);
+    Assert.ok(notification, "Should have gotten the notification");
+
+    let permChanged = TestUtils.topicObserved("perm-changed",
+      (subject, data) => {
+        let result;
+        if (choice == 1) {
+          result = subject &&
+                   subject.QueryInterface(Ci.nsIPermission)
+                          .type.startsWith("3rdPartyStorage^") &&
+                   subject.principal.origin == "http://example.net" &&
+                   data == "added";
+        } else if (choice == 2) {
+          result = subject &&
+                   subject.QueryInterface(Ci.nsIPermission)
+                          .type == "cookie" &&
+                   subject.principal.origin == "https://tracking.example.org" &&
+                   data == "added";
+        }
+        return result;
+      });
+    if (choice == 0) {
+      await clickMainAction();
+    } else if (choice == 1) {
+      await clickSecondaryAction(choice - 1);
+    } else if (choice == 2) {
+      await clickSecondaryAction(choice - 1);
+    }
+    if (choice != 0) {
+      await permChanged;
+    }
+  });
+
+  let url;
+  if (choice == 2) {
+    url = TEST_3RD_PARTY_PAGE + "?disableWaitUntilPermission";
+  } else {
+    url = TEST_3RD_PARTY_PAGE;
+  }
+  let ct = ContentTask.spawn(browser,
+                             { page: url,
+                               callback: runChecks.toString(),
+                               choice,
+                             },
+                             async function(obj) {
+    await new content.Promise(resolve => {
+      let ifr = content.document.createElement("iframe");
+      ifr.onload = function() {
+        info("Sending code to the 3rd party content");
+        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;
+        }
+
+        if (event.data == "getchoice") {
+          ifr.contentWindow.postMessage("choice:" + obj.choice, "*");
+          return;
+        }
+
+        ok(false, "Unknown message");
+      });
+
+      content.document.body.appendChild(ifr);
+      ifr.src = obj.page;
+    });
+  });
+  await Promise.all([ct, shownPromise]);
+
+  BrowserTestUtils.removeTab(tab);
+
+  UrlClassifierTestUtils.cleanupTestTrackers();
+}
+
+async function cleanUp() {
+  info("Cleaning up.");
+  await new Promise(resolve => {
+    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
+  });
+}
+
+async function runRound(n) {
+  await testDoorHanger(n);
+  await cleanUp();
+}
+
+add_task(async function() {
+  await runRound(0);
+  await runRound(1);
+  await runRound(2);
+});
--- a/toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
+++ b/toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
@@ -93,16 +93,17 @@ async function callRequestStorageAccess(
     rejected = true;
   }
 
   success = !threw && !rejected;
   let hasAccess = await document.hasStorageAccess();
   is(hasAccess, success,
      "Should " + (success ? "" : "not ") + "have storage access now");
   if (success && rejectTrackers &&
+      window.location.search != "?disableWaitUntilPermission" &&
       origin != "https://another-tracking.example.net") {
     // Wait until the permission is visible in our process to avoid race
     // conditions.
     await waitUntilPermission("http://example.net/browser/toolkit/components/antitracking/test/browser/page.html",
                               "3rdPartyStorage^https://tracking.example.org");
   }
 
   return [threw, rejected];