Bug 1509047 - Part 6: Add an automated test for the heuristics for the automatic grants of temporary access in the storage access API; r=baku
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 25 Nov 2018 16:13:58 -0500
changeset 507894 e54c1b4fa9c653c03d90600d7dd7d04279c1f889
parent 507893 cb7e6dc0469e54273fb84beb92ac20d4c7656b62
child 507895 d99bf39f5223abe554a629a947eee344c3e9e29e
child 507930 df022f193cb4b6d8f87504223adc2a2f8789be31
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1509047
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 1509047 - Part 6: Add an automated test for the heuristics for the automatic grants of temporary access in the storage access API; r=baku Differential Revision: https://phabricator.services.mozilla.com/D12867
toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
toolkit/components/antitracking/test/browser/head.js
--- a/toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
@@ -1,41 +1,56 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
 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}`);
+const BLOCK = 0;
+const ALLOW = 1;
+const ALLOW_ON_ANY_SITE = 2;
+
+async function testDoorHanger(choice, showPrompt, topPage, maxConcurrent) {
+  info(`Running doorhanger test with choice #${choice}, showPrompt: ${showPrompt} and ` +
+       `topPage: ${topPage}, maxConcurrent: ${maxConcurrent}`);
+
+  if (!showPrompt) {
+    is(choice, ALLOW, "When not showing a prompt, we can only auto-grant");
+  }
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.allowlist.annotations.enabled", true],
     ["browser.contentblocking.allowlist.storage.enabled", true],
     [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
-    ["dom.storage_access.auto_grants", false],
+    ["dom.storage_access.auto_grants", true],
     ["dom.storage_access.enabled", true],
+    ["dom.storage_access.max_concurrent_auto_grants", maxConcurrent],
     ["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);
+  let tab = BrowserTestUtils.addTab(gBrowser, topPage);
   gBrowser.selectedTab = tab;
 
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   async function runChecks() {
+    // We need to repeat this constant here since runChecks is stringified
+    // and sent to the content process.
+    const BLOCK = 0;
+
     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);
@@ -57,72 +72,78 @@ async function testDoorHanger(choice) {
       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) {
+    if (choice == BLOCK) {
       // 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 permChanged = TestUtils.topicObserved("perm-changed",
+    (subject, data) => {
+      let result;
+      if (choice == ALLOW) {
+        result = subject &&
+                 subject.QueryInterface(Ci.nsIPermission)
+                        .type.startsWith("3rdPartyStorage^") &&
+                 subject.principal.origin == (new URL(topPage)).origin &&
+                 data == "added";
+      } else if (choice == ALLOW_ON_ANY_SITE) {
+        result = subject &&
+                 subject.QueryInterface(Ci.nsIPermission)
+                        .type == "cookie" &&
+                 subject.principal.origin == "https://tracking.example.org" &&
+                 data == "added";
+      }
+      return result;
+    });
   let shownPromise =
     BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
   shownPromise.then(async _ => {
-    let notification =
-      PopupNotifications.getNotification("storage-access", browser);
+    if (topPage != gBrowser.currentURI.spec) {
+      return;
+    }
+    ok(showPrompt, "We shouldn't show the prompt when we don't intend to");
+    let notification = await new Promise(function poll(resolve) {
+      let notification =
+        PopupNotifications.getNotification("storage-access", browser);
+      if (notification) {
+        resolve(notification);
+        return;
+      }
+      setTimeout(poll, 10);
+    });
     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) {
+    if (choice == BLOCK) {
       await clickMainAction();
-    } else if (choice == 1) {
+    } else if (choice == ALLOW) {
       await clickSecondaryAction(choice - 1);
-    } else if (choice == 2) {
+    } else if (choice == ALLOW_ON_ANY_SITE) {
       await clickSecondaryAction(choice - 1);
     }
-    if (choice != 0) {
+    if (choice != BLOCK) {
       await permChanged;
     }
   });
 
-  let url;
-  if (choice == 2) {
-    url = TEST_3RD_PARTY_PAGE + "?disableWaitUntilPermission";
-  } else {
-    url = TEST_3RD_PARTY_PAGE;
-  }
+  let url = TEST_3RD_PARTY_PAGE + "?disableWaitUntilPermission";
   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");
@@ -155,32 +176,150 @@ async function testDoorHanger(choice) {
 
         ok(false, "Unknown message");
       });
 
       content.document.body.appendChild(ifr);
       ifr.src = obj.page;
     });
   });
-  await Promise.all([ct, shownPromise]);
+  if (showPrompt) {
+    await Promise.all([ct, shownPromise]);
+  } else {
+    await Promise.all([ct, permChanged]);
+  }
 
   BrowserTestUtils.removeTab(tab);
 
   UrlClassifierTestUtils.cleanupTestTrackers();
 }
 
+async function preparePermissionsFromOtherSites(topPage) {
+  info("Faking permissions from other sites");
+  let type = "3rdPartyStorage^https://tracking.example.org";
+  let permission = Services.perms.ALLOW_ACTION;
+  let expireType = Services.perms.EXPIRE_SESSION;
+  if (topPage == TEST_TOP_PAGE) {
+    // For the first page, don't do anything
+  } else if (topPage == TEST_TOP_PAGE_2) {
+    // For the second page, only add the permission from the first page
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+  } else if (topPage == TEST_TOP_PAGE_3) {
+    // For the third page, add the permissions from the first two pages
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_2),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+  } else if (topPage == TEST_TOP_PAGE_4) {
+    // For the fourth page, add the permissions from the first three pages
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_2),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_3),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+  } else if (topPage == TEST_TOP_PAGE_5) {
+    // For the fifth page, add the permissions from the first four pages
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_2),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_3),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_4),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+  } else if (topPage == TEST_TOP_PAGE_6) {
+    // For the sixth page, add the permissions from the first five pages
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_2),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_3),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_4),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+    Services.perms.add(Services.io.newURI(TEST_DOMAIN_5),
+                       type,
+                       permission,
+                       expireType,
+                       0);
+  } else {
+    ok(false, "Unexpected top page: " + topPage);
+  }
+}
+
 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);
+async function runRound(topPage, showPrompt, maxConcurrent) {
+  if (showPrompt) {
+    await preparePermissionsFromOtherSites(topPage);
+    await testDoorHanger(BLOCK, showPrompt, topPage, maxConcurrent);
+    await cleanUp();
+    await preparePermissionsFromOtherSites(topPage);
+    await testDoorHanger(ALLOW, showPrompt, topPage, maxConcurrent);
+    await cleanUp();
+    await preparePermissionsFromOtherSites(topPage);
+    await testDoorHanger(ALLOW_ON_ANY_SITE, showPrompt, topPage, maxConcurrent);
+  } else {
+    await preparePermissionsFromOtherSites(topPage);
+    await testDoorHanger(ALLOW, showPrompt, topPage, maxConcurrent);
+  }
   await cleanUp();
 }
 
 add_task(async function() {
-  await runRound(0);
-  await runRound(1);
-  await runRound(2);
+  await runRound(TEST_TOP_PAGE, false, 1);
+  await runRound(TEST_TOP_PAGE_2, true, 1);
+  await runRound(TEST_TOP_PAGE, false, 5);
+  await runRound(TEST_TOP_PAGE_2, false, 5);
+  await runRound(TEST_TOP_PAGE_3, false, 5);
+  await runRound(TEST_TOP_PAGE_4, false, 5);
+  await runRound(TEST_TOP_PAGE_5, false, 5);
+  await runRound(TEST_TOP_PAGE_6, true, 5);
 });
--- a/toolkit/components/antitracking/test/browser/head.js
+++ b/toolkit/components/antitracking/test/browser/head.js
@@ -1,17 +1,27 @@
 const TEST_DOMAIN = "http://example.net";
+const TEST_DOMAIN_2 = "http://xn--exmple-cua.test";
+const TEST_DOMAIN_3 = "https://xn--hxajbheg2az3al.xn--jxalpdlp";
+const TEST_DOMAIN_4 = "http://prefixexample.com";
+const TEST_DOMAIN_5 = "http://test";
+const TEST_DOMAIN_6 = "http://mochi.test:8888";
 const TEST_3RD_PARTY_DOMAIN = "https://tracking.example.org";
 const TEST_3RD_PARTY_DOMAIN_TP = "https://tracking.example.com";
 const TEST_4TH_PARTY_DOMAIN = "http://not-tracking.example.com";
 const TEST_ANOTHER_3RD_PARTY_DOMAIN = "https://another-tracking.example.net";
 
 const TEST_PATH = "/browser/toolkit/components/antitracking/test/browser/";
 
 const TEST_TOP_PAGE = TEST_DOMAIN + TEST_PATH + "page.html";
+const TEST_TOP_PAGE_2 = TEST_DOMAIN_2 + TEST_PATH + "page.html";
+const TEST_TOP_PAGE_3 = TEST_DOMAIN_3 + TEST_PATH + "page.html";
+const TEST_TOP_PAGE_4 = TEST_DOMAIN_4 + TEST_PATH + "page.html";
+const TEST_TOP_PAGE_5 = TEST_DOMAIN_5 + TEST_PATH + "page.html";
+const TEST_TOP_PAGE_6 = TEST_DOMAIN_6 + TEST_PATH + "page.html";
 const TEST_EMBEDDER_PAGE = TEST_DOMAIN + TEST_PATH + "embedder.html";
 const TEST_POPUP_PAGE = TEST_DOMAIN + TEST_PATH + "popup.html";
 const TEST_3RD_PARTY_PAGE = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdParty.html";
 const TEST_3RD_PARTY_PAGE_WO = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartyWO.html";
 const TEST_3RD_PARTY_PAGE_UI = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartyUI.html";
 const TEST_3RD_PARTY_PAGE_WITH_SVG = TEST_3RD_PARTY_DOMAIN + TEST_PATH + "3rdPartySVG.html";
 const TEST_4TH_PARTY_PAGE = TEST_4TH_PARTY_DOMAIN + TEST_PATH + "3rdParty.html";
 const TEST_ANOTHER_3RD_PARTY_PAGE = TEST_ANOTHER_3RD_PARTY_DOMAIN + TEST_PATH + "3rdParty.html";