diff --git a/toolkit/components/url-classifier/tests/mochitest/chrome.ini b/toolkit/components/url-classifier/tests/mochitest/chrome.ini index 090cacbf327d..ca879f7ba1ca 100644 --- a/toolkit/components/url-classifier/tests/mochitest/chrome.ini +++ b/toolkit/components/url-classifier/tests/mochitest/chrome.ini @@ -13,6 +13,7 @@ support-files = 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 diff --git a/toolkit/components/url-classifier/tests/mochitest/fastblock.html b/toolkit/components/url-classifier/tests/mochitest/fastblock.html index a2555ec305d3..4d7aa0952cfa 100644 --- a/toolkit/components/url-classifier/tests/mochitest/fastblock.html +++ b/toolkit/components/url-classifier/tests/mochitest/fastblock.html @@ -4,6 +4,8 @@ + + @@ -13,6 +15,5 @@ - diff --git a/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html b/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html new file mode 100644 index 000000000000..76ee5467965e --- /dev/null +++ b/toolkit/components/url-classifier/tests/mochitest/fastblock_iframe.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html b/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html index 69403b78e39b..c9495338a58b 100644 --- a/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html +++ b/toolkit/components/url-classifier/tests/mochitest/test_fastblock_bug1477046.html @@ -11,6 +11,24 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1477046 | 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 | ------------------------------------------ --> @@ -40,8 +58,13 @@ 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; @@ -244,46 +267,225 @@ async function 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, 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 tracker before timeout"); + is(fastScript, "yes", "is a fast tracker"); is(slowScript, "no", "is a blocked tracker"); - is(numTrackersFound, 2, "2 trackers found"); - is(numTrackersBlocked, 1, "1 tracker blocked"); + 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, + }; + }); + + 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"); + + 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() { @@ -292,7 +494,7 @@ async function testPrefsSwitch() { "set": [ ["browser.contentblocking.enabled", true], ["browser.fastblock.enabled", true], - ]}, testFastBlock, 3); // // fastblock.html, good.js, evil.js + ]}, testFastBlock, 6); // FastBlock OFF await runTest({ @@ -314,7 +516,9 @@ async function testPrefsSwitch() { 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]]},