Bug 1487227 draft diag-assert-7227
authorAndrew Sutherland <asutherland@asutherland.org>
Wed, 19 Sep 2018 07:02:00 -0400
changeset 474304 29b554618eb7c07708c58b875d4516c771e94864
parent 474303 9bb0f7fc73ad2109e4ea777e9ba65a16a6acc9cd
push id9
push userbugmail@asutherland.org
push dateWed, 19 Sep 2018 11:04:43 +0000
bugs1487227
milestone64.0a1
Bug 1487227
dom/serviceworkers/test/mochitest.ini
dom/serviceworkers/test/test_third_party_iframes.html
dom/serviceworkers/test/thirdparty/nofetch-sw.js
dom/serviceworkers/test/thirdparty/thirdparty_chromeScript.js
--- a/dom/serviceworkers/test/mochitest.ini
+++ b/dom/serviceworkers/test/mochitest.ini
@@ -159,16 +159,17 @@ support-files =
   sw_clients/refresher_cached_compressed.html
   sw_clients/refresher_cached_compressed.html^headers^
   strict_mode_warning.js
   skip_waiting_installed_worker.js
   skip_waiting_scope/index.html
   thirdparty/iframe1.html
   thirdparty/iframe2.html
   thirdparty/register.html
+  thirdparty/thirdparty_chromeScript.js
   thirdparty/unregister.html
   thirdparty/sw.js
   thirdparty/worker.js
   register_https.html
   gzip_redirect_worker.js
   sw_clients/navigator.html
   eval_worker.js
   test_eval_allowed.html^headers^
--- a/dom/serviceworkers/test/test_third_party_iframes.html
+++ b/dom/serviceworkers/test/test_third_party_iframes.html
@@ -36,17 +36,19 @@ function next() {
   }
 }
 
 onload = next;
 
 let iframe;
 let basePath = "/tests/dom/serviceworkers/test/thirdparty/";
 let origin = window.location.protocol + "//" + window.location.host;
-let thirdPartyOrigin = "https://example.com";
+// This origin is chosen because UrlClassifierTestUtils.jsm marks it at a
+// tracker URL.
+let thirdPartyOrigin = "https://tracking.example.com";
 
 function testIframeLoaded() {
   ok(true, "Iframe loaded");
   iframe.removeEventListener("load", testIframeLoaded);
   let message = {
     source: "parent",
     href: origin + basePath + "iframe2.html"
   };
@@ -56,19 +58,20 @@ function testIframeLoaded() {
 function loadThirdPartyIframe() {
   let message = {
     source: "parent",
     href: thirdPartyOrigin + basePath + "iframe2.html"
   }
   iframe.contentWindow.postMessage(message.toSource(), "*");
 }
 
-function runTest(aExpectedResponses) {
+function runTest(aExpectedResponses, searchSuffix) {
   iframe = document.querySelector("iframe");
-  iframe.src = thirdPartyOrigin + basePath + "register.html";
+  iframe.src = thirdPartyOrigin + basePath + "register.html" +
+               (searchSuffix || '');
   let responsesIndex = 0;
   window.onmessage = function(e) {
     let status = e.data.status;
     let expected = aExpectedResponses[responsesIndex];
     if (status == expected.status) {
       ok(true, "Received expected " + expected.status);
       if (expected.next) {
         expected.next();
@@ -78,16 +81,18 @@ function runTest(aExpectedResponses) {
     }
     responsesIndex++;
   };
 }
 
 // Verify that we can register and intercept a 3rd party iframe with
 // the given cookie policy.
 function testShouldIntercept(behavior, lifetime, done) {
+  info("should intercept: " +
+       `behavior: ${BEHAVIORS[behavior]}   lifetime: ${LIFETIMES[lifetime]}`);
   SpecialPowers.pushPrefEnv({"set": [
       ["network.cookie.cookieBehavior", behavior],
       ["network.cookie.lifetimePolicy", lifetime],
   ]}, function() {
     runTest([{
       status: "ok"
     }, {
       status: "registrationdone",
@@ -118,16 +123,18 @@ function testShouldIntercept(behavior, l
       }
     }]);
   });
 }
 
 // Verify that we cannot register a service worker in a 3rd party
 // iframe with the given cookie policy.
 function testShouldNotRegister(behavior, lifetime, done) {
+  info("should NOT register: " +
+       `behavior: ${BEHAVIORS[behavior]}   lifetime: ${LIFETIMES[lifetime]}`);
   SpecialPowers.pushPrefEnv({"set": [
       ["network.cookie.cookieBehavior", behavior],
       ["network.cookie.lifetimePolicy", lifetime],
   ]}, function() {
     runTest([{
       status: "registrationfailed",
       next: function() {
         iframe.addEventListener("load", testIframeLoaded);
@@ -150,16 +157,18 @@ function testShouldNotRegister(behavior,
     }]);
   });
 }
 
 // Verify that if a service worker is already registered a 3rd
 // party iframe will still not be intercepted with the given cookie
 // policy.
 function testShouldNotIntercept(behavior, lifetime, done) {
+  info("should NOT intercept: " +
+       `behavior: ${BEHAVIORS[behavior]}   lifetime: ${LIFETIMES[lifetime]}`);
   SpecialPowers.pushPrefEnv({"set": [
     ["network.cookie.cookieBehavior", BEHAVIOR_ACCEPT],
     ["network.cookie.lifetimePolicy", LIFETIME_EXPIRE],
   ]}, function() {
     runTest([{
       status: "ok"
     }, {
       status: "registrationdone",
@@ -204,59 +213,102 @@ function testShouldNotIntercept(behavior
         window.onmessage = null;
         ok(true, "Test finished successfully");
         done();
       }
     }]);
   });
 }
 
+// This is like testShouldIntercept but using nofetch-sw.js that does not
+// implement a "fetch" listener.  This happens for cases where push
+// notifications are used with a scope that covers the entire origin.
+function testNoFetchOptimization() {
+
+}
+
+// This is like testShouldNotIntercept but using nofetch-sw.js that does not
+// implement a "fetch" listener.  We register the SW before setting the
+// behavior.
+function testBlockedNoFetchOptimization(behavior, lifetime, done) {
+
+}
+
 const BEHAVIOR_ACCEPT        = 0;
 const BEHAVIOR_REJECTFOREIGN = 1;
 const BEHAVIOR_REJECT        = 2;
 const BEHAVIOR_LIMITFOREIGN  = 3;
+const BEHAVIOR_REJECT_TRACKER = 4
 
-const LIFETIME_EXPIRE        = 0;
-const LIFETIME_SESSION       = 2;
+const BEHAVIORS = ["accept", "reject foreign", "reject", "limit foreign",
+                   "reject tracker"];
+
+const LIFETIME_EXPIRE        = 0; // nsICookieService.ACCEPT_NORMALLY
+const LIFETIME_SESSION       = 2; // nsICookieService.ACCEPT_SESSION
+
+const LIFETIMES = ["expire", "NOT TESTED", "session"];
 
 let steps = [() => {
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
     ["browser.dom.window.dump.enabled", true],
     ["network.cookie.cookieBehavior", BEHAVIOR_ACCEPT],
     ["network.cookie.lifetimePolicy", LIFETIME_EXPIRE],
   ]}, next);
 }, () => {
+  // Initialize the anti-tracking settings for testing purposes.  These only
+  // take effect when BEHAVIOR_REJECT_TRACKER is active.
+  let antiTrackingChromescript = SpecialPowers.loadChromeScript(
+    SimpleTest.getTestFileURL("thirdparty/thirdparty_chromeScript.js"));
+  antiTrackingChromescript.addMessageListener("addedTestTrackers", next);
+  antiTrackingChromescript.sendAsyncMessage("addTestTrackers");
+
+  SimpleTest.registerCleanupFunction(() => {
+    antiTrackingChromescript.sendAsyncMessage("cleanupTestTrackers");
+    antiTrackingChromescript.destroy();
+  });
+}, () => {
   testShouldIntercept(BEHAVIOR_ACCEPT, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_REJECTFOREIGN, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_REJECTFOREIGN, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_REJECT, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_REJECT, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_LIMITFOREIGN, LIFETIME_EXPIRE, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_LIMITFOREIGN, LIFETIME_EXPIRE, next);
 }, () => {
+  // TODO: This does not work because the channel check is wrong...
+  //testShouldNotRegister(BEHAVIOR_REJECT_TRACKER, LIFETIME_EXPIRE, next);
+  next();
+}, () => {
+  //testShouldNotIntercept(BEHAVIOR_REJECT_TRACKER, LIFETIME_EXPIRE, next);
+  next();
+}, () => {
   testShouldNotIntercept(BEHAVIOR_ACCEPT, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_REJECTFOREIGN, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_REJECTFOREIGN, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_REJECT, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_REJECT, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotRegister(BEHAVIOR_LIMITFOREIGN, LIFETIME_SESSION, next);
 }, () => {
   testShouldNotIntercept(BEHAVIOR_LIMITFOREIGN, LIFETIME_SESSION, next);
+}, () => {
+  testShouldNotRegister(BEHAVIOR_REJECT_TRACKER, LIFETIME_SESSION, next);
+}, () => {
+  testShouldNotIntercept(BEHAVIOR_REJECT_TRACKER, LIFETIME_SESSION, next);
 }];
 
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/serviceworkers/test/thirdparty/nofetch-sw.js
@@ -0,0 +1,1 @@
+// This is a specialized SW that does not register a fetch event.
new file mode 100644
--- /dev/null
+++ b/dom/serviceworkers/test/thirdparty/thirdparty_chromeScript.js
@@ -0,0 +1,17 @@
+// This file provides support for our mochitest to use UrlClassifierTestUtils
+// so that tracking protection will treat "tracking.example.com" as a tracker.
+
+let {UrlClassifierTestUtils} =
+ ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
+
+addMessageListener("addTestTrackers", async function() {
+  await UrlClassifierTestUtils.addTestTrackers();
+  sendAsyncMessage("addedTestTrackers", {});
+});
+
+addMessageListener("cleanupTestTrackers", async function() {
+  UrlClassifierTestUtils.cleanupTestTrackers();
+  sendAsyncMessage("cleanedUpTestTrackers", {});
+});
+
+sendAsyncMessage("ready", {});