Bug 1477046 - Part 2: Add FastBlock iframe tests. r=mayhemer a=test-only
authorLiang-Heng Chen <xeonchen@gmail.com>
Thu, 13 Sep 2018 21:30:39 +0000
changeset 492563 73a1d6086193470df4b3015fab66972aa1d32f05
parent 492562 bcc215e21646e7452c579dee5b11086f68dadbdf
child 492564 6dea608bdf6b262cad68f588037d99c4d3f25972
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, test-only
bugs1477046
milestone63.0
Bug 1477046 - Part 2: Add FastBlock iframe tests. r=mayhemer a=test-only Differential Revision: https://phabricator.services.mozilla.com/D4770
toolkit/components/url-classifier/tests/mochitest/chrome.ini
toolkit/components/url-classifier/tests/mochitest/fastblock.html
toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html
toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html
--- a/toolkit/components/url-classifier/tests/mochitest/chrome.ini
+++ b/toolkit/components/url-classifier/tests/mochitest/chrome.ini
@@ -8,16 +8,17 @@ support-files =
   bug_1281083.html
   report.sjs
   gethash.sjs
   classifierCommon.js
   classifierHelper.js
   head.js
   threathit.sjs
   fastblock.html
+  fastblock_iframe.html
   !/toolkit/components/url-classifier/tests/mochitest/classifierFrame.html
   !/toolkit/components/url-classifier/tests/mochitest/cleanWorker.js
   !/toolkit/components/url-classifier/tests/mochitest/good.js
   !/toolkit/components/url-classifier/tests/mochitest/evil.css
   !/toolkit/components/url-classifier/tests/mochitest/evil.css^headers^
   !/toolkit/components/url-classifier/tests/mochitest/evil.js
   !/toolkit/components/url-classifier/tests/mochitest/evil.js^headers^
   !/toolkit/components/url-classifier/tests/mochitest/evilWorker.js
--- a/toolkit/components/url-classifier/tests/mochitest/fastblock.html
+++ b/toolkit/components/url-classifier/tests/mochitest/fastblock.html
@@ -1,18 +1,19 @@
 <!DOCTYPE html>
 <html>
 <head>
   <title></title>
 </head>
 <body>
+  <!-- Tracking iframe contains some trackers -->
+  <iframe id="fastIFrame" data-touched="not sure" src="http://tracking.example.org/chrome/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></iframe>
 
   <!-- Tracking URL -->
   <script id="goodScript" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
 
   <!-- Tracking Annotation -->
   <script id="fastScript" data-touched="not sure" src="http://tracking.example.org/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
 
   <!-- Tracking Annotation -->
   <script id="slowScript" data-touched="not sure" src="http://tracking.example.org/tests/toolkit/components/url-classifier/tests/mochitest/trackingRequest.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
-
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title></title>
+</head>
+<body>
+
+  <!-- Tracking URL -->
+  <script id="goodIFrameScript" data-touched="not sure" src="http://example.com/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
+
+  <!-- Tracking Annotation -->
+  <script id="fastIFrameScript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
+
+  <!-- Tracking Annotation -->
+  <script id="slowIFrameScript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/trackingRequest.js" onload="this.dataset.touched='yes';" onerror="this.dataset.touched='no';"></script>
+
+</body>
+</html>
--- a/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html
@@ -6,16 +6,34 @@ https://bugzilla.mozilla.org/show_bug.cg
 ------------------------------------------
 | ID               | Tracker | FastBlock |
 -------------------+---------+------------
 | fastblock.html   | No      | N/A       |
 -------------------+---------+------------
 | goodScript       | No      | N/A       |
 | fastScript       | Yes     | No        |
 | slowScript       | Yes     | Yes       |
+-------------------+---------+------------
+| fastIFrame       | Yes     | No        |
+-------------------+---------+------------
+| goodIFrameScript | No      | N/A       |
+| fastIFrameScript | Yes     | No        |
+| slowIFrameScript | Yes     | Yes       |
+-------------------+---------+------------
+| badIFrame        | Yes     | Yes       |
+-------------------+---------+------------
+| goodIFrameScript | N/A     | N/A       |
+| fastIFrameScript | N/A     | N/A       |
+| slowIFrameScript | N/A     | N/A       |
+-------------------+---------+------------
+| goodIFrame       | No      | N/A       |
+-------------------+---------+------------
+| goodIFrameScript | No      | N/A       |
+| fastIFrameScript | Yes     | Yes       |
+| slowIFrameScript | Yes     | Yes       |
 ------------------------------------------
 
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1477046</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
@@ -35,18 +53,23 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/ContentTask.jsm");
 ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 
 const gContentPage =
   "http://example.com/chrome/toolkit/components/url-classifier/tests/mochitest/fastblock.html";
+const gGoodIFramePage =
+  "http://example.com/chrome/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html";
+const gBadIFramePage =
+  "http://itisatracker.org/chrome/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html";
 const gSlowTrackers = [
   "http://tracking.example.org/tests/toolkit/components/url-classifier/tests/mochitest/trackingRequest.js",
+  "http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/trackingRequest.js",
 ];
 const gInfiniteTimeout = 300000;
 const gDebug = false;
 
 function log(aMsg) {
   if (gDebug) {
     info("[FastBlock] " + aMsg + "\n");
   }
@@ -239,65 +262,244 @@ async function runTest(aPrefs, aFunction
   });
 }
 
 async function finishTest() {
   log("finishTest()");
   SimpleTest.finish();
 }
 
+async function addIFrame(aWindow, aUrl, aId) {
+  let monitor = new ChannelUnifier();
+  monitor.init();
+
+  let loadIFramePromise = new Promise(resolve => {
+    let onStopRequest = aSubject => {
+      let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+      if (channel.name == aUrl) {
+        try {
+          is(channel.responseStatus, 200, "the channel is loaded");
+          resolve(true);
+        } catch (e) {
+          is(e.name, "NS_ERROR_NOT_AVAILABLE", "the channel is canceled");
+          resolve(false);
+        } finally {
+          SpecialPowers.removeObserver(onStopRequest, "http-on-stop-request");
+        }
+      }
+    };
+    SpecialPowers.addObserver(onStopRequest, "http-on-stop-request");
+  });
+
+  let loadIFrameContentPromise = ContentTask.spawn(aWindow.gBrowser.selectedBrowser,
+                                                   [aUrl, aId],
+                                                   async function([url, id]) {
+    return new Promise((resolve, err) => {
+      let iframe = content.document.createElement("iframe");
+      iframe.id = id;
+      iframe.src = url;
+
+      // onload/onerror are triggered only when the iframe is not blocked
+      iframe.dataset.touched = "no";
+      iframe.onload = function() {
+        this.dataset.touched = "yes";
+        resolve();
+      };
+      content.document.body.appendChild(iframe);
+    });
+  });
+
+  let isIFrameLoaded = await loadIFramePromise; // wait until page load finish
+  if (isIFrameLoaded) {
+    // make sure all content are also loaded, this promise will never be resolved
+    // for the case it's blocked.
+    await loadIFrameContentPromise;
+  }
+
+  monitor.close();
+  return isIFrameLoaded;
+}
+
 async function testFastBlock(aWindow) {
   let browser = aWindow.gBrowser.selectedBrowser;
   let results = await ContentTask.spawn(browser, {}, () => {
+    let iframe = content.document.getElementById("fastIFrame").contentDocument;
     return {
       goodScript: content.document.getElementById("goodScript").dataset.touched,
       fastScript: content.document.getElementById("fastScript").dataset.touched,
       slowScript: content.document.getElementById("slowScript").dataset.touched,
+      fastIFrame: content.document.getElementById("fastIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript").dataset.touched,
+      fastIFrameScript: iframe.getElementById("fastIFrameScript").dataset.touched,
+      slowIFrameScript: iframe.getElementById("slowIFrameScript").dataset.touched,
+      numTrackersFound: content.document.numTrackersFound,
+      numTrackersBlocked: content.document.numTrackersBlocked,
+    };
+  });
+
+  let { goodScript,
+        fastScript,
+        slowScript,
+        fastIFrame,
+        goodIFrameScript,
+        fastIFrameScript,
+        slowIFrameScript,
+        numTrackersFound,
+        numTrackersBlocked,
+  } = results;
+
+  is(goodScript, "yes", "is not a tracker");
+  is(fastScript, "yes", "is a fast tracker");
+  is(slowScript, "no", "is a blocked tracker");
+  is(fastIFrame, "yes", "fast iframe loaded");
+  is(goodIFrameScript, "yes", "is not a tracker");
+  is(fastIFrameScript, "yes", "is a fast tracker");
+  is(slowIFrameScript, "no", "is a blocked tracker");
+  is(numTrackersFound, 5, "5 trackers found");
+  is(numTrackersBlocked, 2, "2 tracker blocked");
+
+  let badIFrameLoaded = await addIFrame(aWindow, gBadIFramePage, "badIFrame");
+  ok(!badIFrameLoaded, "tracking iframe is blocked");
+
+  results = await ContentTask.spawn(browser, {}, () => {
+    let iframe = content.document.getElementById("badIFrame").contentDocument;
+    return {
+      badIFrame: content.document.getElementById("badIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript"),
+      fastIFrameScript: iframe.getElementById("fastIFrameScript"),
+      slowIFrameScript: iframe.getElementById("slowIFrameScript"),
       numTrackersFound: content.document.numTrackersFound,
       numTrackersBlocked: content.document.numTrackersBlocked,
     };
   });
 
-  let { goodScript, fastScript, slowScript, numTrackersFound, numTrackersBlocked } = results;
+  is(results.badIFrame, "no", "bad iframe blocked");
+  ok(!results.goodIFrameScript, "iframe is not loaded");
+  ok(!results.fastIFrameScript, "iframe is not loaded");
+  ok(!results.slowIFrameScript, "iframe is not loaded");
+
+  is(results.numTrackersFound, 6, "6 trackers found");
+  is(results.numTrackersBlocked, 3, "3 tracker blocked");
+
+  let goodIFrameLoaded = await addIFrame(aWindow, gGoodIFramePage, "goodIFrame");
+  ok(goodIFrameLoaded, "non tracking iframe is loaded");
 
-  is(goodScript, "yes", "is not a tracker");
-  is(fastScript, "yes", "is a tracker before timeout");
-  is(slowScript, "no", "is a blocked tracker");
-  is(numTrackersFound, 2, "2 trackers found");
-  is(numTrackersBlocked, 1, "1 tracker blocked");
+  results = await ContentTask.spawn(browser, {}, () => {
+    let iframe = content.document.getElementById("goodIFrame").contentDocument;
+    return {
+      goodIFrame: content.document.getElementById("goodIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript").dataset.touched,
+      fastIFrameScript: iframe.getElementById("fastIFrameScript").dataset.touched,
+      slowIFrameScript: iframe.getElementById("slowIFrameScript").dataset.touched,
+      numTrackersFound: content.document.numTrackersFound,
+      numTrackersBlocked: content.document.numTrackersBlocked,
+    };
+  });
+
+  is(results.goodIFrame, "yes", "non tracking iframe is loaded");
+  is(results.goodIFrameScript, "yes", "is not a tracker");
+  is(results.fastIFrameScript, "no", "is a blocked tracker");
+  is(results.slowIFrameScript, "no", "is a blocked tracker");
+
+  is(results.numTrackersFound, 8, "8 trackers found");
+  is(results.numTrackersBlocked, 5, "5 tracker blocked");
 }
 
 async function testNoFastBlock(aWindow) {
   let browser = aWindow.gBrowser.selectedBrowser;
   let results = await ContentTask.spawn(browser, {}, () => {
+    let iframe = content.document.getElementById("fastIFrame").contentDocument;
     return {
       goodScript: content.document.getElementById("goodScript").dataset.touched,
       fastScript: content.document.getElementById("fastScript").dataset.touched,
       slowScript: content.document.getElementById("slowScript").dataset.touched,
+      fastIFrame: content.document.getElementById("fastIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript").dataset.touched,
+      fastIFrameScript: iframe.getElementById("fastIFrameScript").dataset.touched,
+      slowIFrameScript: iframe.getElementById("slowIFrameScript").dataset.touched,
       numTrackersFound: content.document.numTrackersFound,
       numTrackersBlocked: content.document.numTrackersBlocked,
     };
   });
 
-  let { goodScript, fastScript, slowScript, numTrackersFound, numTrackersBlocked } = results;
+  let { goodScript,
+        fastScript,
+        slowScript,
+        fastIFrame,
+        goodIFrameScript,
+        fastIFrameScript,
+        slowIFrameScript,
+        numTrackersFound,
+        numTrackersBlocked,
+  } = results;
 
   is(goodScript, "yes", "is not a tracker");
-  is(fastScript, "yes", "is a non-blocked tracker");
-  is(slowScript, "yes", "is a non-blocked tracker");
-  is(numTrackersFound, 2, "2 trackers found");
+  is(fastScript, "yes", "FastBlock is disabled");
+  is(slowScript, "yes", "FastBlock is disabled");
+  is(fastIFrame, "yes", "fast iframe loaded");
+  is(goodIFrameScript, "yes", "is not a tracker");
+  is(fastIFrameScript, "yes", "FastBlock is disabled");
+  is(slowIFrameScript, "yes", "FastBlock is disabled");
+  is(numTrackersFound, 5, "5 trackers found");
   is(numTrackersBlocked, 0, "no tracker blocked");
+
+  let iframeLoaded = await addIFrame(aWindow, gBadIFramePage, "badIFrame");
+  ok(iframeLoaded, "tracking iframe is loaded");
+
+  results = await ContentTask.spawn(browser, log, (LOG) => {
+    let iframe = content.document.getElementById("badIFrame").contentDocument;
+    return {
+      badIFrame: content.document.getElementById("badIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript").dataset.touched,
+      fastIFrameScript: iframe.getElementById("fastIFrameScript").dataset.touched,
+      slowIFrameScript: iframe.getElementById("slowIFrameScript").dataset.touched,
+      numTrackersFound: content.document.numTrackersFound,
+      numTrackersBlocked: content.document.numTrackersBlocked,
+    };
+  });
+
+  is(results.badIFrame, "yes", "FastBlock is disabled");
+  is(results.goodIFrameScript, "yes", "is not a tracker");
+  is(results.fastIFrameScript, "yes", "FastBlock is disabled");
+  is(results.slowIFrameScript, "yes", "FastBlock is disabled");
+
+  is(results.numTrackersFound, 8, "8 trackers found");
+  is(results.numTrackersBlocked, 0, "0 tracker blocked");
+
+  let goodIFrameLoaded = await addIFrame(aWindow, gGoodIFramePage, "goodIFrame");
+  ok(goodIFrameLoaded, "non tracking iframe is loaded");
+
+  results = await ContentTask.spawn(browser, {}, () => {
+    let iframe = content.document.getElementById("goodIFrame").contentDocument;
+    return {
+      goodIFrame: content.document.getElementById("goodIFrame").dataset.touched,
+      goodIFrameScript: iframe.getElementById("goodIFrameScript").dataset.touched,
+      fastIFrameScript: iframe.getElementById("fastIFrameScript").dataset.touched,
+      slowIFrameScript: iframe.getElementById("slowIFrameScript").dataset.touched,
+      numTrackersFound: content.document.numTrackersFound,
+      numTrackersBlocked: content.document.numTrackersBlocked,
+    };
+  });
+
+  is(results.goodIFrame, "yes", "non tracking iframe is loaded");
+  is(results.goodIFrameScript, "yes", "is not a tracker");
+  is(results.fastIFrameScript, "yes", "FastBlock is disabled");
+  is(results.slowIFrameScript, "yes", "FastBlock is disabled");
+
+  is(results.numTrackersFound, 10, "10 trackers found");
+  is(results.numTrackersBlocked, 0, "0 tracker blocked");
 }
 
 async function testPrefsSwitch() {
   // FastBlock ON
   await runTest({
     "set": [
       ["browser.contentblocking.enabled", true],
       ["browser.fastblock.enabled", true],
-    ]}, testFastBlock, 3); // // fastblock.html, good.js, evil.js
+    ]}, testFastBlock, 6);
 
   // FastBlock OFF
   await runTest({
     "set": [
       ["browser.contentblocking.enabled", false],
       ["browser.fastblock.enabled", true],
       ["browser.fastblock.timeout", 1],
     ]}, testNoFastBlock, 0);
@@ -309,17 +511,19 @@ async function testPrefsSwitch() {
       ["browser.fastblock.enabled", false],
       ["browser.fastblock.timeout", 1],
     ]}, testNoFastBlock, 0);
 }
 
 async function test() {
   await setupTest();
 
-  await runTest(null, testFastBlock, 3); // fastblock.html, good.js, evil.js
+  await runTest(null,
+                testFastBlock,
+                6);
 
   // A long-timeout that FastBlock never happens
   await runTest({ "set": [["browser.fastblock.timeout", gInfiniteTimeout]]},
                 testNoFastBlock, 0);
 
   await testPrefsSwitch();
 
   await finishTest();