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
☠☠ backed out by 0f4be93319f6 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 28 Nov 2018 22:02:52 +0000
changeset 507869 53f6c4e1f112024f662351dd346a966f0fb77f8e
parent 507868 7bfa4179a341674e066171c33a8bad746b68cd92
child 507870 0f4be93319f6df5739f29fed76288e0861a5b7d1
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 Depends on D12866 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,58 @@
+/* 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 these constants here since runChecks is stringified
+    // and sent to the content process.
+    const BLOCK = 0;
+    const ALLOW = 1;
+    const ALLOW_ON_ANY_SITE = 2;
+
     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 +74,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 +178,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";