import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,8 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/mochitest/mochitest.eslintrc.js",
"../../../../../testing/mochitest/chrome.eslintrc.js"
]
};

View file

@ -0,0 +1,144 @@
<html>
<head>
<title></title>
<script type="text/javascript">
// Modified by evil.js
var scriptItem;
var scriptItem1 = "untouched";
var imageItem1 = "untouched";
var frameItem1 = "untouched";
var scriptItem2 = "untouched";
var imageItem2 = "untouched";
var frameItem2 = "untouched";
var xhrItem = "untouched";
var fetchItem = "untouched";
var mediaItem1 = "untouched";
function checkLoads() {
window.parent.is(scriptItem1, "spoiled", "Should not block tracking js 1");
window.parent.is(scriptItem2, "spoiled", "Should not block tracking js 2");
window.parent.is(imageItem1, "spoiled", "Should not block tracking img 1");
window.parent.is(imageItem2, "spoiled", "Should not block tracking img 2");
window.parent.is(frameItem1, "spoiled", "Should not block tracking iframe 1");
window.parent.is(frameItem2, "spoiled", "Should not block tracking iframe 2");
window.parent.is(mediaItem1, "loaded", "Should not block tracking video");
window.parent.is(xhrItem, "loaded", "Should not block tracking XHR");
window.parent.is(fetchItem, "loaded", "Should not block fetches from tracking domains");
window.parent.is(window.document.blockedTrackingNodeCount, 0,
"No elements should be blocked");
// End (parent) test.
window.parent.clearPermissions();
window.parent.SimpleTest.finish();
}
var onloadCalled = false;
var xhrFinished = false;
var fetchFinished = false;
var videoLoaded = false;
function loaded(type) {
if (type === "onload") {
onloadCalled = true;
} else if (type === "xhr") {
xhrFinished = true;
} else if (type === "fetch") {
fetchFinished = true;
} else if (type === "video") {
videoLoaded = true;
}
if (onloadCalled && xhrFinished && fetchFinished && videoLoaded) {
checkLoads();
}
}
</script>
</head>
<body onload="loaded('onload')">
<!-- Try loading from a tracking script URI (1) -->
<script id="badscript1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="scriptItem1 = 'spoiled';"></script>
<!-- Try loading from a tracking image URI (1) -->
<img id="badimage1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg" onload="imageItem1 = 'spoiled';"/>
<!-- Try loading from a tracking frame URI (1) -->
<iframe id="badframe1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/track.html" onload="frameItem1 = 'spoiled';"></iframe>
<!-- Try loading from a tracking video URI -->
<video id="badmedia1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/vp9.webm"></video>
<script>
var v = document.getElementById("badmedia1");
v.addEventListener("loadedmetadata", function() {
mediaItem1 = "loaded";
loaded("video");
}, true);
v.addEventListener("error", function() {
mediaItem1 = "error";
loaded("video");
}, true);
// Try loading from a tracking script URI (2) - The loader may follow a
// different path depending on whether the resource is loaded from JS or HTML.
var newScript = document.createElement("script");
newScript.id = "badscript2";
newScript.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js";
newScript.addEventListener("load", function onload() {scriptItem2 = 'spoiled';});
document.body.appendChild(newScript);
/// Try loading from a tracking image URI (2)
var newImage = document.createElement("img");
newImage.id = "badimage2";
newImage.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg";
newImage.addEventListener("load", function onload() {imageItem2 = 'spoiled'});
document.body.appendChild(newImage);
// Try loading from a tracking iframe URI (2)
var newFrame = document.createElement("iframe");
newFrame.id = "badframe2";
newFrame.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/track.html"
newFrame.addEventListener("load", function onload() {frameItem2 = 'spoiled'});
document.body.appendChild(newFrame);
// Try doing an XHR against a tracking domain (bug 1216793)
function reqListener() {
xhrItem = "loaded";
loaded("xhr");
}
function transferFailed() {
xhrItem = "failed";
loaded("xhr");
}
function transferCanceled() {
xhrItem = "canceled";
loaded("xhr");
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.open("GET", "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js");
oReq.send();
// Fetch from a tracking domain
fetch("http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js").then(function(response) {
if(response.ok) {
fetchItem = "loaded";
loaded("fetch");
} else {
fetchItem = "badresponse";
loaded("fetch");
}
}).catch(function(error) {
fetchItem = "error";
loaded("fetch");
});
</script>
</body>
</html>

View file

@ -0,0 +1 @@
#styleBad { visibility: hidden; }

View file

@ -0,0 +1 @@
Cache-Control: no-store

View file

@ -0,0 +1,27 @@
WEBVTT
Region: id=testOne lines=2 width=30%
Region: id=testTwo lines=4 width=20%
1
00:00.500 --> 00:00.700 region:testOne
This
2
00:01.200 --> 00:02.400 region:testTwo
Is
2.5
00:02.000 --> 00:03.500 region:testOne
(Over here?!)
3
00:02.710 --> 00:02.910
A
4
00:03.217 --> 00:03.989
Test
5
00:03.217 --> 00:03.989
And more!

View file

@ -0,0 +1 @@
Access-Control-Allow-Origin: *

View file

@ -0,0 +1,35 @@
<html>
<head>
<title></title>
<script type="text/javascript">
var scriptItem = "untouched";
function checkLoads() {
// Make sure the javascript did not load.
window.parent.is(scriptItem, "untouched", "Should not load bad javascript");
// Call parent.loadTestFrame again to test classification metadata in HTTP
// cache entries.
if (window.parent.firstLoad) {
window.parent.info("Reloading from cache...");
window.parent.firstLoad = false;
window.parent.loadTestFrame();
return;
}
// End (parent) test.
window.parent.SimpleTest.finish();
}
</script>
<!-- Try loading from a malware javascript URI -->
<script type="text/javascript" src="http://bug1281083.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js"></script>
</head>
<body onload="checkLoads()">
</body>
</html>

View file

@ -0,0 +1,23 @@
[DEFAULT]
skip-if = os == 'android'
support-files =
allowlistAnnotatedFrame.html
classifiedAnnotatedFrame.html
classifiedAnnotatedPBFrame.html
bug_1281083.html
[test_lookup_system_principal.html]
[test_classified_annotations.html]
tags = trackingprotection
skip-if = os == 'linux' && asan # Bug 1202548
[test_allowlisted_annotations.html]
tags = trackingprotection
[test_privatebrowsing_trackingprotection.html]
tags = trackingprotection
[test_trackingprotection_bug1157081.html]
tags = trackingprotection
[test_trackingprotection_whitelist.html]
tags = trackingprotection
[test_safebrowsing_bug1272239.html]
[test_donottrack.html]
[test_classifier_changetablepref.html]

View file

@ -0,0 +1,213 @@
<html>
<head>
<title></title>
<script type="text/javascript">
"use strict";
var scriptItem = "untouched";
var scriptItem1 = "untouched";
var scriptItem2 = "untouched";
var imageItem1 = "untouched";
var imageItem2 = "untouched";
var frameItem1 = "untouched";
var frameItem2 = "untouched";
var xhrItem = "untouched";
var fetchItem = "untouched";
var mediaItem1 = "untouched";
var badids = [
"badscript1",
"badscript2",
"badimage1",
"badimage2",
"badframe1",
"badframe2",
"badmedia1",
"badcss"
];
function checkLoads() {
window.parent.is(
scriptItem1, "untouched", "Should not load tracking javascript");
window.parent.is(
scriptItem2, "untouched", "Should not load tracking javascript (2)");
window.parent.is(
imageItem1, "untouched", "Should not load tracking images");
window.parent.is(
imageItem2, "untouched", "Should not load tracking images (2)");
window.parent.is(
frameItem1, "untouched", "Should not load tracking iframes");
window.parent.is(
frameItem2, "untouched", "Should not load tracking iframes (2)");
window.parent.is(
mediaItem1, "error", "Should not load tracking videos");
window.parent.is(
xhrItem, "failed", "Should not load tracking XHRs");
window.parent.is(
fetchItem, "error", "Should not fetch from tracking URLs");
var elt = document.getElementById("styleCheck");
var style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(
style.visibility, "hidden", "Should not load tracking css");
window.parent.is(window.document.blockedTrackingNodeCount, badids.length,
"Should identify all tracking elements");
var blockedTrackingNodes = window.document.blockedTrackingNodes;
// Make sure that every node in blockedTrackingNodes exists in the tree
// (that may not always be the case but do not expect any nodes to disappear
// from the tree here)
var allNodeMatch = true;
for (var i = 0; i < blockedTrackingNodes.length; i++) {
var nodeMatch = false;
for (var j = 0; j < badids.length && !nodeMatch; j++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == document.getElementById(badids[j]));
}
allNodeMatch = allNodeMatch && nodeMatch;
}
window.parent.ok(allNodeMatch,
"All annotated nodes are expected in the tree");
// Make sure that every node with a badid (see badids) is found in the
// blockedTrackingNodes. This tells us if we are neglecting to annotate
// some nodes
allNodeMatch = true;
for (var j = 0; j < badids.length; j++) {
var nodeMatch = false;
for (var i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == document.getElementById(badids[j]));
}
if (!nodeMatch) {
console.log(badids[j] + " was not found in blockedTrackingNodes");
}
allNodeMatch = allNodeMatch && nodeMatch;
}
window.parent.ok(allNodeMatch,
"All tracking nodes are expected to be annotated as such");
// Unset prefs, etc.
window.parent.cleanup();
// End (parent) test.
window.parent.SimpleTest.finish();
}
var onloadCalled = false;
var xhrFinished = false;
var fetchFinished = false;
var videoLoaded = false;
function loaded(type) {
if (type === "onload") {
onloadCalled = true;
} else if (type === "xhr") {
xhrFinished = true;
} else if (type === "fetch") {
fetchFinished = true;
} else if (type === "video") {
videoLoaded = true;
}
if (onloadCalled && xhrFinished && fetchFinished && videoLoaded) {
checkLoads();
}
}
</script>
<!-- Try loading from a tracking CSS URI -->
<link id="badcss" rel="stylesheet" type="text/css" href="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
</head>
<body onload="loaded('onload')">
<!-- Try loading from a tracking script URI (1): evil.js onload will have updated the scriptItem variable -->
<script id="badscript1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="scriptItem1 = scriptItem;"></script>
<!-- Try loading from a tracking image URI (1) -->
<img id="badimage1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg?reload=true" onload="imageItem1 = 'spoiled';"/>
<!-- Try loading from a tracking frame URI (1) -->
<iframe id="badframe1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/track.html" onload="frameItem1 = 'spoiled';"></iframe>
<!-- Try loading from a tracking video URI -->
<video id="badmedia1" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/vp9.webm?reload=true"></video>
<script>
var v = document.getElementById("badmedia1");
v.addEventListener("loadedmetadata", function() {
mediaItem1 = "loaded";
loaded("video");
}, true);
v.addEventListener("error", function() {
mediaItem1 = "error";
loaded("video");
}, true);
// Try loading from a tracking script URI (2) - The loader may follow a different path depending on whether the resource is loaded from JS or HTML.
var newScript = document.createElement("script");
newScript.id = "badscript2";
newScript.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js";
newScript.addEventListener("load", function() {scriptItem2 = scriptItem;});
document.body.appendChild(newScript);
/// Try loading from a tracking image URI (2)
var newImage = document.createElement("img");
newImage.id = "badimage2";
newImage.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg?reload=true";
newImage.addEventListener("load", function() {imageItem2 = 'spoiled'});
document.body.appendChild(newImage);
// Try loading from a tracking iframe URI (2)
var newFrame = document.createElement("iframe");
newFrame.id = "badframe2";
newFrame.src = "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/track.html"
newFrame.addEventListener("load", function() {frameItem2 = 'spoiled'});
document.body.appendChild(newFrame);
// Try doing an XHR against a tracking domain (bug 1216793)
function reqListener() {
xhrItem = "loaded";
loaded("xhr");
}
function transferFailed() {
xhrItem = "failed";
loaded("xhr");
}
function transferCanceled() {
xhrItem = "canceled";
loaded("xhr");
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.open("GET", "http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js");
oReq.send();
// Fetch from a tracking domain
fetch("http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js").then(function(response) {
if(response.ok) {
fetchItem = "loaded";
loaded("fetch");
} else {
fetchItem = "badresponse";
loaded("fetch");
}
}).catch(function(error) {
fetchItem = "error";
loaded("fetch");
});
</script>
The following should not be hidden:
<div id="styleCheck">STYLE TEST</div>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<title></title>
<link id="badcss" rel="stylesheet" type="text/css" href="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
</head>
<body>
<script id="badscript" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
<script id="goodscript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
<!-- The image cache can cache JS handlers, so make sure we use a different URL for raptor.jpg each time -->
<img id="badimage" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg?pbmode=test" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"/>
The following should not be hidden:
<div id="styleCheck">STYLE TEST</div>
</body>
</html>

View file

@ -0,0 +1,112 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const { classes: Cc, interfaces: Ci, results: Cr } = Components;
var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
var timer;
function setTimeout(callback, delay) {
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback({ notify: callback },
delay,
Ci.nsITimer.TYPE_ONE_SHOT);
}
function doUpdate(update) {
let listener = {
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIUrlClassifierUpdateObserver))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
updateUrlRequested: function(url) { },
streamFinished: function(status) { },
updateError: function(errorCode) {
sendAsyncMessage("updateError", errorCode);
},
updateSuccess: function(requestedTimeout) {
sendAsyncMessage("updateSuccess");
}
};
let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
try {
dbService.beginUpdate(listener, "test-malware-simple,test-unwanted-simple", "");
dbService.beginStream("", "");
dbService.updateStream(update);
dbService.finishStream();
dbService.finishUpdate();
} catch(e) {
// beginUpdate may fail if there's an existing update in progress
// retry until success or testcase timeout.
setTimeout(() => { doUpdate(update); }, 1000);
}
}
function doReload() {
dbService.reloadDatabase();
sendAsyncMessage("reloadSuccess");
}
// SafeBrowsing.jsm is initialized after mozEntries are added. Add observer
// to receive "finished" event. For the case when this function is called
// after the event had already been notified, we lookup entries to see if
// they are already added to database.
function waitForInit() {
let observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(function() {
sendAsyncMessage("safeBrowsingInited");
}, "mozentries-update-finished", false);
// This url must sync with the table, url in SafeBrowsing.jsm addMozEntries
const table = "test-phish-simple";
const url = "http://itisatrap.org/firefox/its-a-trap.html";
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
let iosvc = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let principal = secMan.createCodebasePrincipal(
iosvc.newURI(url, null, null), {});
let listener = {
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIUrlClassifierUpdateObserver))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
handleEvent: function(value)
{
if (value === table) {
sendAsyncMessage("safeBrowsingInited");
}
},
};
dbService.lookup(principal, table, listener);
}
addMessageListener("doUpdate", ({ testUpdate }) => {
doUpdate(testUpdate);
});
addMessageListener("doReload", () => {
doReload();
});
addMessageListener("waitForInit", () => {
waitForInit();
});

View file

@ -0,0 +1,57 @@
<html>
<head>
<title></title>
<script type="text/javascript">
var scriptItem = "untouched";
function checkLoads() {
// Make sure the javascript did not load.
window.parent.is(scriptItem, "untouched", "Should not load bad javascript");
// Make sure the css did not load.
var elt = document.getElementById("styleCheck");
var style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(style.visibility, "hidden", "Should not load bad css");
elt = document.getElementById("styleBad");
style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(style.visibility, "hidden", "Should not load bad css");
elt = document.getElementById("styleImport");
style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(style.visibility, "visible", "Should import clean css");
// Call parent.loadTestFrame again to test classification metadata in HTTP
// cache entries.
if (window.parent.firstLoad) {
window.parent.info("Reloading from cache...");
window.parent.firstLoad = false;
window.parent.loadTestFrame();
return;
}
// End (parent) test.
window.parent.SimpleTest.finish();
}
</script>
<!-- Try loading from a malware javascript URI -->
<script type="text/javascript" src="http://malware.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js"></script>
<!-- Try loading from an uwanted software css URI -->
<link rel="stylesheet" type="text/css" href="http://unwanted.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
<!-- Try loading a marked-as-malware css through an @import from a clean URI -->
<link rel="stylesheet" type="text/css" href="import.css"></link>
</head>
<body onload="checkLoads()">
The following should not be hidden:
<div id="styleCheck">STYLE TEST</div>
<div id="styleBad">STYLE BAD</div>
<div id="styleImport">STYLE IMPORT</div>
</body>
</html>

View file

@ -0,0 +1,201 @@
if (typeof(classifierHelper) == "undefined") {
var classifierHelper = {};
}
const CLASSIFIER_COMMON_URL = SimpleTest.getTestFileURL("classifierCommon.js");
var gScript = SpecialPowers.loadChromeScript(CLASSIFIER_COMMON_URL);
const ADD_CHUNKNUM = 524;
const SUB_CHUNKNUM = 523;
const HASHLEN = 32;
const PREFS = {
PROVIDER_LISTS : "browser.safebrowsing.provider.mozilla.lists",
DISALLOW_COMPLETIONS : "urlclassifier.disallow_completions",
PROVIDER_GETHASHURL : "browser.safebrowsing.provider.mozilla.gethashURL"
};
// addUrlToDB & removeUrlFromDB are asynchronous, queue the task to ensure
// the callback follow correct order.
classifierHelper._updates = [];
// Keep urls added to database, those urls should be automatically
// removed after test complete.
classifierHelper._updatesToCleanup = [];
classifierHelper._initsCB = [];
// This function return a Promise, promise is resolved when SafeBrowsing.jsm
// is initialized.
classifierHelper.waitForInit = function() {
return new Promise(function(resolve, reject) {
classifierHelper._initsCB.push(resolve);
gScript.sendAsyncMessage("waitForInit");
});
}
// This function is used to allow completion for specific "list",
// some lists like "test-malware-simple" is default disabled to ask for complete.
// "list" is the db we would like to allow it
// "url" is the completion server
classifierHelper.allowCompletion = function(lists, url) {
for (var list of lists) {
// Add test db to provider
var pref = SpecialPowers.getCharPref(PREFS.PROVIDER_LISTS);
pref += "," + list;
SpecialPowers.setCharPref(PREFS.PROVIDER_LISTS, pref);
// Rename test db so we will not disallow it from completions
pref = SpecialPowers.getCharPref(PREFS.DISALLOW_COMPLETIONS);
pref = pref.replace(list, list + "-backup");
SpecialPowers.setCharPref(PREFS.DISALLOW_COMPLETIONS, pref);
}
// Set get hash url
SpecialPowers.setCharPref(PREFS.PROVIDER_GETHASHURL, url);
}
// Pass { url: ..., db: ... } to add url to database,
// onsuccess/onerror will be called when update complete.
classifierHelper.addUrlToDB = function(updateData) {
return new Promise(function(resolve, reject) {
var testUpdate = "";
for (var update of updateData) {
var LISTNAME = update.db;
var CHUNKDATA = update.url;
var CHUNKLEN = CHUNKDATA.length;
var HASHLEN = update.len ? update.len : 32;
classifierHelper._updatesToCleanup.push(update);
testUpdate +=
"n:1000\n" +
"i:" + LISTNAME + "\n" +
"ad:1\n" +
"a:" + ADD_CHUNKNUM + ":" + HASHLEN + ":" + CHUNKLEN + "\n" +
CHUNKDATA;
}
classifierHelper._update(testUpdate, resolve, reject);
});
}
// Pass { url: ..., db: ... } to remove url from database,
// onsuccess/onerror will be called when update complete.
classifierHelper.removeUrlFromDB = function(updateData) {
return new Promise(function(resolve, reject) {
var testUpdate = "";
for (var update of updateData) {
var LISTNAME = update.db;
var CHUNKDATA = ADD_CHUNKNUM + ":" + update.url;
var CHUNKLEN = CHUNKDATA.length;
var HASHLEN = update.len ? update.len : 32;
testUpdate +=
"n:1000\n" +
"i:" + LISTNAME + "\n" +
"s:" + SUB_CHUNKNUM + ":" + HASHLEN + ":" + CHUNKLEN + "\n" +
CHUNKDATA;
}
classifierHelper._updatesToCleanup =
classifierHelper._updatesToCleanup.filter((v) => {
return updateData.indexOf(v) == -1;
});
classifierHelper._update(testUpdate, resolve, reject);
});
};
// This API is used to expire all add/sub chunks we have updated
// by using addUrlToDB and removeUrlFromDB.
classifierHelper.resetDB = function() {
return new Promise(function(resolve, reject) {
var testUpdate = "";
for (var update of classifierHelper._updatesToCleanup) {
if (testUpdate.includes(update.db))
continue;
testUpdate +=
"n:1000\n" +
"i:" + update.db + "\n" +
"ad:" + ADD_CHUNKNUM + "\n" +
"sd:" + SUB_CHUNKNUM + "\n"
}
classifierHelper._update(testUpdate, resolve, reject);
});
};
classifierHelper.reloadDatabase = function() {
return new Promise(function(resolve, reject) {
gScript.addMessageListener("reloadSuccess", function handler() {
gScript.removeMessageListener('reloadSuccess', handler);
resolve();
});
gScript.sendAsyncMessage("doReload");
});
}
classifierHelper._update = function(testUpdate, onsuccess, onerror) {
// Queue the task if there is still an on-going update
classifierHelper._updates.push({"data": testUpdate,
"onsuccess": onsuccess,
"onerror": onerror});
if (classifierHelper._updates.length != 1) {
return;
}
gScript.sendAsyncMessage("doUpdate", { testUpdate });
};
classifierHelper._updateSuccess = function() {
var update = classifierHelper._updates.shift();
update.onsuccess();
if (classifierHelper._updates.length) {
var testUpdate = classifierHelper._updates[0].data;
gScript.sendAsyncMessage("doUpdate", { testUpdate });
}
};
classifierHelper._updateError = function(errorCode) {
var update = classifierHelper._updates.shift();
update.onerror(errorCode);
if (classifierHelper._updates.length) {
var testUpdate = classifierHelper._updates[0].data;
gScript.sendAsyncMessage("doUpdate", { testUpdate });
}
};
classifierHelper._inited = function() {
classifierHelper._initsCB.forEach(function (cb) {
cb();
});
classifierHelper._initsCB = [];
};
classifierHelper._setup = function() {
gScript.addMessageListener("updateSuccess", classifierHelper._updateSuccess);
gScript.addMessageListener("updateError", classifierHelper._updateError);
gScript.addMessageListener("safeBrowsingInited", classifierHelper._inited);
// cleanup will be called at end of each testcase to remove all the urls added to database.
SimpleTest.registerCleanupFunction(classifierHelper._cleanup);
};
classifierHelper._cleanup = function() {
// clean all the preferences may touch by helper
for (var pref in PREFS) {
SpecialPowers.clearUserPref(pref);
}
if (!classifierHelper._updatesToCleanup) {
return Promise.resolve();
}
return classifierHelper.resetDB();
};
classifierHelper._setup();

View file

@ -0,0 +1,10 @@
onmessage = function() {
try {
importScripts("evilWorker.js");
} catch(ex) {
postMessage("success");
return;
}
postMessage("failure");
};

View file

@ -0,0 +1,31 @@
<html>
<head>
<title></title>
<script type="text/javascript">
function makeXHR(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function() {
callback(xhr.response);
};
xhr.send();
}
function loaded(type) {
window.parent.postMessage("navigator.doNotTrack=" + navigator.doNotTrack, "*");
makeXHR("dnt.sjs", (res) => {
window.parent.postMessage("DNT=" + res, "*");
window.parent.postMessage("finish", "*");
});
}
</script>
</head>
<body onload="loaded('onload')">
</body>
</html>

View file

@ -0,0 +1,9 @@
function handleRequest(request, response) {
var dnt = "unspecified";
if (request.hasHeader("DNT")) {
dnt = "1";
}
response.setHeader("Content-Type", "text/plain", false);
response.write(dnt);
}

View file

@ -0,0 +1 @@
#styleCheck { visibility: hidden; }

View file

@ -0,0 +1 @@
Cache-Control: no-store

View file

@ -0,0 +1 @@
scriptItem = "loaded malware javascript!";

View file

@ -0,0 +1,2 @@
Access-Control-Allow-Origin: *
Cache-Control: no-store

View file

@ -0,0 +1,3 @@
onmessage = function() {
postMessage("loaded bad file");
}

View file

@ -0,0 +1,130 @@
const CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var idx = val.indexOf('=');
query[val.slice(0, idx)] = unescape(val.slice(idx + 1));
});
var responseBody;
// Store fullhash in the server side.
if ("list" in query && "fullhash" in query) {
// In the server side we will store:
// 1. All the full hashes for a given list
// 2. All the lists we have right now
// data is separate by '\n'
let list = query["list"];
let hashes = getState(list);
let hash = base64ToString(query["fullhash"]);
hashes += hash + "\n";
setState(list, hashes);
let lists = getState("lists");
if (lists.indexOf(list) == -1) {
lists += list + "\n";
setState("lists", lists);
}
return;
// gethash count return how many gethash request received.
// This is used by client to know if a gethash request is triggered by gecko
} else if ("gethashcount" == request.queryString) {
var counter = getState("counter");
responseBody = counter == "" ? "0" : counter;
} else {
var body = new BinaryInputStream(request.bodyInputStream);
var avail;
var bytes = [];
while ((avail = body.available()) > 0) {
Array.prototype.push.apply(bytes, body.readByteArray(avail));
}
var counter = getState("counter");
counter = counter == "" ? "1" : (parseInt(counter) + 1).toString();
setState("counter", counter);
responseBody = parseV2Request(bytes);
}
response.setHeader("Content-Type", "text/plain", false);
response.write(responseBody);
}
function parseV2Request(bytes) {
var request = String.fromCharCode.apply(this, bytes);
var [HEADER, PREFIXES] = request.split("\n");
var [PREFIXSIZE, LENGTH] = HEADER.split(":").map(val => {
return parseInt(val);
});
var ret = "";
for(var start = 0; start < LENGTH; start += PREFIXSIZE) {
getState("lists").split("\n").forEach(function(list) {
var completions = getState(list).split("\n");
for (var completion of completions) {
if (completion.indexOf(PREFIXES.substr(start, PREFIXSIZE)) == 0) {
ret += list + ":" + "1" + ":" + "32" + "\n";
ret += completion;
}
}
});
}
return ret;
}
/* Convert Base64 data to a string */
const toBinaryTable = [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
];
const base64Pad = '=';
function base64ToString(data) {
var result = '';
var leftbits = 0; // number of bits decoded, but yet to be appended
var leftdata = 0; // bits decoded, but yet to be appended
// Convert one by one.
for (var i = 0; i < data.length; i++) {
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
var padding = (data[i] == base64Pad);
// Skip illegal characters and whitespace
if (c == -1) continue;
// Collect data into leftdata, update bitcount
leftdata = (leftdata << 6) | c;
leftbits += 6;
// If we have 8 or more bits, append 8 bits to the result
if (leftbits >= 8) {
leftbits -= 8;
// Append if not padding.
if (!padding)
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
leftdata &= (1 << leftbits) - 1;
}
}
// If there are any bits left, the base64 string was corrupted
if (leftbits)
throw Components.Exception('Corrupted base64 string');
return result;
}

View file

@ -0,0 +1,62 @@
<html>
<head>
<title></title>
<script type="text/javascript">
var scriptItem = "untouched";
function checkLoads() {
var title = document.getElementById("title");
title.innerHTML = window.parent.shouldLoad ?
"The following should be hidden:" :
"The following should not be hidden:"
if (window.parent.shouldLoad) {
window.parent.is(scriptItem, "loaded malware javascript!", "Should load bad javascript");
} else {
window.parent.is(scriptItem, "untouched", "Should not load bad javascript");
}
var elt = document.getElementById("styleImport");
var style = document.defaultView.getComputedStyle(elt, "");
window.parent.isnot(style.visibility, "visible", "Should load clean css");
// Make sure the css did not load.
elt = document.getElementById("styleCheck");
style = document.defaultView.getComputedStyle(elt, "");
if (window.parent.shouldLoad) {
window.parent.isnot(style.visibility, "visible", "Should load bad css");
} else {
window.parent.isnot(style.visibility, "hidden", "Should not load bad css");
}
elt = document.getElementById("styleBad");
style = document.defaultView.getComputedStyle(elt, "");
if (window.parent.shouldLoad) {
window.parent.isnot(style.visibility, "visible", "Should import bad css");
} else {
window.parent.isnot(style.visibility, "hidden", "Should not import bad css");
}
}
</script>
<!-- Try loading from a malware javascript URI -->
<script type="text/javascript" src="http://malware.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js"></script>
<!-- Try loading from an uwanted software css URI -->
<link rel="stylesheet" type="text/css" href="http://unwanted.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
<!-- Try loading a marked-as-malware css through an @import from a clean URI -->
<link rel="stylesheet" type="text/css" href="import.css"></link>
</head>
<body onload="checkLoads()">
<div id="title"></div>
<div id="styleCheck">STYLE EVIL</div>
<div id="styleBad">STYLE BAD</div>
<div id="styleImport">STYLE IMPORT</div>
</body>
</html>

View file

@ -0,0 +1 @@
scriptItem = "loaded whitelisted javascript!";

View file

@ -0,0 +1,3 @@
/* malware.example.com is in the malware database. */
@import url("http://malware.example.com/tests/toolkit/components/url-classifier/tests/mochitest/bad.css");
#styleImport { visibility: hidden; }

View file

@ -0,0 +1,39 @@
[DEFAULT]
support-files =
classifiedAnnotatedPBFrame.html
classifierCommon.js
classifierFrame.html
classifierHelper.js
cleanWorker.js
good.js
evil.css
evil.css^headers^
evil.js
evil.js^headers^
evilWorker.js
import.css
raptor.jpg
track.html
unwantedWorker.js
vp9.webm
whitelistFrame.html
workerFrame.html
ping.sjs
basic.vtt
basic.vtt^headers^
dnt.html
dnt.sjs
update.sjs
bad.css
bad.css^headers^
gethash.sjs
gethashFrame.html
seek.webm
[test_classifier.html]
skip-if = (os == 'linux' && debug) #Bug 1199778
[test_classifier_worker.html]
[test_classify_ping.html]
[test_classify_track.html]
[test_gethash.html]
[test_bug1254766.html]

View file

@ -0,0 +1,16 @@
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
if (request.method == "POST") {
setState(query["id"], "ping");
} else {
var value = getState(query["id"]);
response.setHeader("Content-Type", "text/plain", false);
response.write(value);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the URI Classifier</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
// Add https://allowlisted.example.com to the permissions manager
SpecialPowers.addPermission("trackingprotection",
Ci.nsIPermissionManager.ALLOW_ACTION,
{ url: "https://allowlisted.example.com" });
function clearPermissions() {
SpecialPowers.removePermission("trackingprotection",
{ url: "https://allowlisted.example.com" });
ok(!SpecialPowers.testPermission("trackingprotection",
Ci.nsIPermissionManager.ALLOW_ACTION,
{ url: "https://allowlisted.example.com" }));
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", "test-track-simple"],
["privacy.trackingprotection.enabled", true],
["channelclassifier.allowlist_example", true]]},
test);
function test() {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
UrlClassifierTestUtils.addTestTrackers().then(() => {
document.getElementById("testFrame").src = "allowlistAnnotatedFrame.html";
});
}
// Expected finish() call is in "allowlistedAnnotatedFrame.html".
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,305 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1272239 - Test gethash.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const MALWARE_LIST = "test-malware-simple";
const MALWARE_HOST1 = "malware.example.com/";
const MALWARE_HOST2 = "test1.example.com/";
const UNWANTED_LIST = "test-unwanted-simple";
const UNWANTED_HOST1 = "unwanted.example.com/";
const UNWANTED_HOST2 = "test2.example.com/";
const UNUSED_MALWARE_HOST = "unused.malware.com/";
const UNUSED_UNWANTED_HOST = "unused.unwanted.com/";
const GETHASH_URL =
"http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/gethash.sjs";
var gPreGethashCounter = 0;
var gCurGethashCounter = 0;
var expectLoad = false;
function loadTestFrame() {
return new Promise(function(resolve, reject) {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "gethashFrame.html");
document.body.appendChild(iframe);
iframe.onload = function() {
document.body.removeChild(iframe);
resolve();
};
}).then(getGethashCounter);
}
function getGethashCounter() {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.open("PUT", GETHASH_URL + "?gethashcount");
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
gPreGethashCounter = gCurGethashCounter;
gCurGethashCounter = parseInt(xhr.response);
resolve();
}
};
xhr.send();
});
}
// calculate the fullhash and send it to gethash server
function addCompletionToServer(list, url) {
return new Promise(function(resolve, reject) {
var listParam = "list=" + list;
var fullhashParam = "fullhash=" + hash(url);
var xhr = new XMLHttpRequest;
xhr.open("PUT", GETHASH_URL + "?" + listParam + "&" + fullhashParam, true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
resolve();
}
};
xhr.send();
});
}
function hash(str) {
function bytesFromString(str) {
var converter =
SpecialPowers.Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(SpecialPowers.Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
return converter.convertToByteArray(str);
}
var hasher = SpecialPowers.Cc["@mozilla.org/security/hash;1"]
.createInstance(SpecialPowers.Ci.nsICryptoHash);
var data = bytesFromString(str);
hasher.init(hasher.SHA256);
hasher.update(data, data.length);
return hasher.finish(true);
}
// setup function allows classifier send gethash request for test database
// also it calculate to fullhash for url and store those hashes in gethash sjs.
function setup() {
classifierHelper.allowCompletion([MALWARE_LIST, UNWANTED_LIST], GETHASH_URL);
return Promise.all([
addCompletionToServer(MALWARE_LIST, MALWARE_HOST1),
addCompletionToServer(MALWARE_LIST, MALWARE_HOST2),
addCompletionToServer(UNWANTED_LIST, UNWANTED_HOST1),
addCompletionToServer(UNWANTED_LIST, UNWANTED_HOST2),
]);
}
// Reset function in helper try to simulate the behavior we restart firefox
function reset() {
return classifierHelper.resetDB()
.catch(err => {
ok(false, "Couldn't update classifier. Error code: " + errorCode);
// Abort test.
SimpleTest.finish();
});
}
function updateUnusedUrl() {
var testData = [
{ url: UNUSED_MALWARE_HOST, db: MALWARE_LIST },
{ url: UNUSED_UNWANTED_HOST, db: UNWANTED_LIST }
];
return classifierHelper.addUrlToDB(testData)
.catch(err => {
ok(false, "Couldn't update classifier. Error code: " + err);
// Abort test.
SimpleTest.finish();
});
}
function addPrefixToDB() {
return update(true);
}
function addCompletionToDB() {
return update(false);
}
function update(prefix = false) {
var length = prefix ? 4 : 32;
var testData = [
{ url: MALWARE_HOST1, db: MALWARE_LIST, len: length },
{ url: MALWARE_HOST2, db: MALWARE_LIST, len: length },
{ url: UNWANTED_HOST1, db: UNWANTED_LIST, len: length },
{ url: UNWANTED_HOST2, db: UNWANTED_LIST, len: length }
];
return classifierHelper.addUrlToDB(testData)
.catch(err => {
ok(false, "Couldn't update classifier. Error code: " + errorCode);
// Abort test.
SimpleTest.finish();
});
}
// This testcase is to make sure gethash works:
// 1. Add prefixes to DB.
// 2. Load test frame contains malware & unwanted url, those urls should be blocked.
// 3. The second step should also trigger a gethash request since completions is not in
// either cache or DB.
// 4. Load test frame again, since completions is stored in cache now, no gethash
// request should be triggered.
function testGethash() {
return Promise.resolve()
.then(addPrefixToDB)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered."); })
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(reset);
}
// This testcase is to make sure an update request will clear completion cache:
// 1. Add prefixes to DB.
// 2. Load test frame, this should trigger a gethash request
// 3. Trigger an update, completion cache should be cleared now.
// 4. Load test frame again, since cache is cleared now, gethash request should be triggered.
function testUpdateClearCache() {
return Promise.resolve()
.then(addPrefixToDB)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered."); })
.then(updateUnusedUrl)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered."); })
.then(reset);
}
// This testcae is to make sure completions in update works:
// 1. Add completions to DB.
// 2. Load test frame, since completions is stored in DB, gethash request should
// not be triggered.
function testUpdate() {
return Promise.resolve()
.then(addCompletionToDB)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(reset);
}
// This testcase is to make sure an update request will not clear completions in DB:
// 1. Add completions to DB.
// 2. Load test frame to make sure completions is stored in database, in this case, gethash
// should not be triggered.
// 3. Trigger an update, cache is cleared, but completions in DB should still remain.
// 4. Load test frame again, since completions is in DB, gethash request should not be triggered.
function testUpdateNotClearCompletions() {
return Promise.resolve()
.then(addCompletionToDB)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(updateUnusedUrl)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(reset);
}
// This testcase is to make sure completion store in DB will properly load after restarting.
// 1. Add completions to DB.
// 2. Simulate firefox restart by calling reloadDatabase.
// 3. Load test frame, since completions should be loaded from DB, no gethash request should
// be triggered.
function testUpdateCompletionsAfterReload() {
return Promise.resolve()
.then(addCompletionToDB)
.then(classifierHelper.reloadDatabase)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(reset);
}
// This testcase is to make sure cache will be cleared after restarting
// 1. Add prefixes to DB.
// 2. Load test frame, this should trigger a gethash request and completions will be stored in
// cache.
// 3. Load test frame again, no gethash should be triggered because of cache.
// 4. Simulate firefox restart by calling reloadDatabase.
// 5. Load test frame again, since cache is cleared, gethash request should be triggered.
function testGethashCompletionsAfterReload() {
return Promise.resolve()
.then(addPrefixToDB)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered."); })
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter == gPreGethashCounter, "Gethash request is not triggered."); })
.then(classifierHelper.reloadDatabase)
.then(loadTestFrame)
.then(() => {
ok(gCurGethashCounter > gPreGethashCounter, "Gethash request is triggered."); })
.then(reset);
}
function runTest() {
Promise.resolve()
.then(classifierHelper.waitForInit)
.then(setup)
.then(testGethash)
.then(testUpdateClearCache)
.then(testUpdate)
.then(testUpdateNotClearCompletions)
.then(testUpdateCompletionsAfterReload)
.then(testGethashCompletionsAfterReload)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
// 'network.predictor.enabled' is disabled because if other testcase load
// evil.js, evil.css ...etc resources, it may cause we load them from cache
// directly and bypass classifier check
SpecialPowers.pushPrefEnv({"set": [
["browser.safebrowsing.malware.enabled", true],
["network.predictor.enabled", false],
["urlclassifier.gethash.timeout_ms", 30000],
]}, runTest);
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the URI Classifier</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
function cleanup() {
SpecialPowers.clearUserPref("privacy.trackingprotection.enabled");
SpecialPowers.clearUserPref("channelclassifier.allowlist_example");
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", "test-track-simple"]]},
test);
function test() {
UrlClassifierTestUtils.addTestTrackers().then(() => {
SpecialPowers.setBoolPref("privacy.trackingprotection.enabled", true);
// Make sure chrome:// URIs are processed. This does not white-list
// any URIs unless 'https://allowlisted.example.com' is added in the
// permission manager (see test_allowlisted_annotations.html)
SpecialPowers.setBoolPref("channelclassifier.allowlist_example", true);
document.getElementById("testFrame").src = "classifiedAnnotatedFrame.html";
});
}
// Expected finish() call is in "classifiedAnnotatedFrame.html".
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the URI Classifier</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var firstLoad = true;
// Add some URLs to the malware database.
var testData = [
{ url: "malware.example.com/",
db: "test-malware-simple"
},
{ url: "unwanted.example.com/",
db: "test-unwanted-simple"
}
];
function loadTestFrame() {
document.getElementById("testFrame").src = "classifierFrame.html";
}
// Expected finish() call is in "classifierFrame.html".
SimpleTest.waitForExplicitFinish();
function updateSuccess() {
SpecialPowers.pushPrefEnv(
{"set" : [["browser.safebrowsing.malware.enabled", true]]},
loadTestFrame);
}
function updateError(errorCode) {
ok(false, "Couldn't update classifier. Error code: " + errorCode);
// Abort test.
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
["urlclassifier.phishTable", "test-phish-simple"]]},
function() {
classifierHelper.waitForInit()
.then(() => classifierHelper.addUrlToDB(testData))
.then(updateSuccess)
.catch(err => {
updateError(err);
});
});
</script>
</pre>
<iframe id="testFrame" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,149 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1281083 - Changing the urlclassifier.*Table prefs doesn't take effect before the next browser restart.</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const testTable = "moz-track-digest256";
const UPDATE_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/update.sjs";
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
var timer = Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
// If default preference contain the table we want to test,
// We should change test table to a different one.
var trackingTables = SpecialPowers.getCharPref("urlclassifier.trackingTable").split(",");
ok(!trackingTables.includes(testTable), "test table should not be in the preference");
var listmanager = Cc["@mozilla.org/url-classifier/listmanager;1"].
getService(Ci.nsIUrlListManager);
is(listmanager.getGethashUrl(testTable), "",
"gethash url for test table should be empty before setting to preference");
function loadTestFrame() {
// gethash url of test table "moz-track-digest256" should be updated
// after setting preference.
var url = listmanager.getGethashUrl(testTable);
var expected = SpecialPowers.getCharPref("browser.safebrowsing.provider.mozilla.gethashURL");
is(url, expected, testTable + " matches its gethash url");
// Trigger update
listmanager.disableUpdate(testTable);
listmanager.enableUpdate(testTable);
listmanager.maybeToggleUpdateChecking();
// We wait until "nextupdattime" was set as a signal that update is complete.
waitForUpdateSuccess(function() {
document.getElementById("testFrame").src = "bug_1281083.html";
});
}
function waitForUpdateSuccess(callback) {
let nextupdatetime =
SpecialPowers.getCharPref("browser.safebrowsing.provider.mozilla.nextupdatetime");
if (nextupdatetime !== "1") {
callback();
return;
}
timer.initWithCallback(function() {
waitForUpdateSuccess(callback);
}, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}
function addCompletionToServer(list, url) {
return new Promise(function(resolve, reject) {
var listParam = "list=" + list;
var fullhashParam = "fullhash=" + hash(url);
var xhr = new XMLHttpRequest;
xhr.open("PUT", UPDATE_URL + "?" +
listParam + "&" +
fullhashParam, true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
resolve();
}
};
xhr.send();
});
}
function hash(str) {
function bytesFromString(str) {
var converter =
SpecialPowers.Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(SpecialPowers.Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
return converter.convertToByteArray(str);
}
var hasher = SpecialPowers.Cc["@mozilla.org/security/hash;1"]
.createInstance(SpecialPowers.Ci.nsICryptoHash);
var data = bytesFromString(str);
hasher.init(hasher.SHA256);
hasher.update(data, data.length);
return hasher.finish(true);
}
function runTest() {
/**
* In this test we try to modify only urlclassifier.*Table preference to see if
* url specified in the table will be blocked after update.
*/
var pushPrefPromise = SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", testTable]]});
// To make sure url is not blocked by an already blocked url.
// Here we use non-tracking.example.com as a tracked url.
// Since this table is only used in this bug, so it won't affect other testcases.
var addCompletePromise =
addCompletionToServer(testTable, "bug1281083.example.com/");
Promise.all([pushPrefPromise, addCompletePromise])
.then(() => {
loadTestFrame();
});
}
// Set nextupdatetime to 1 to trigger an update
SpecialPowers.pushPrefEnv(
{"set" : [["privacy.trackingprotection.enabled", true],
["channelclassifier.allowlist_example", true],
["browser.safebrowsing.provider.mozilla.nextupdatetime", "1"],
["browser.safebrowsing.provider.mozilla.lists", testTable],
["browser.safebrowsing.provider.mozilla.updateURL", UPDATE_URL]]},
runTest);
// Expected finish() call is in "bug_1281083.html".
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,76 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the URI Classifier</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
// Add some URLs to the malware database.
var testData = [
{ url: "example.com/tests/toolkit/components/url-classifier/tests/mochitest/evilWorker.js",
db: "test-malware-simple"
},
{ url: "example.com/tests/toolkit/components/url-classifier/tests/mochitest/unwantedWorker.js",
db: "test-unwanted-simple"
}
];
function loadTestFrame() {
document.getElementById("testFrame").src =
"http://example.com/tests/toolkit/components/url-classifier/tests/mochitest/workerFrame.html";
}
function onmessage(event)
{
var pieces = event.data.split(':');
if (pieces[0] == "finish") {
SimpleTest.finish();
return;
}
is(pieces[0], "success", pieces[1]);
}
function updateSuccess() {
SpecialPowers.pushPrefEnv(
{"set" : [["browser.safebrowsing.malware.enabled", true]]},
loadTestFrame);
}
function updateError(errorCode) {
ok(false, "Couldn't update classifier. Error code: " + errorCode);
// Abort test.
SimpleTest.finish();
};
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
["urlclassifier.phishTable", "test-phish-simple"]]},
function() {
classifierHelper.waitForInit()
.then(() => classifierHelper.addUrlToDB(testData))
.then(updateSuccess)
.catch(err => {
updateError(err);
});
});
window.addEventListener("message", onmessage, false);
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,121 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1233914 - ping doesn't honor the TP list here.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.requestFlakyTimeout("Delay to make sure ping is made prior than XHR");
const timeout = 200;
const host_nottrack = "http://not-tracking.example.com/";
const host_track = "http://trackertest.org/";
const path_ping = "tests/toolkit/components/url-classifier/tests/mochitest/ping.sjs";
const TP_ENABLE_PREF = "privacy.trackingprotection.enabled";
function testPingNonBlacklist() {
SpecialPowers.setBoolPref(TP_ENABLE_PREF, true);
var msg = "ping should reach page not in blacklist";
var expectPing = true;
var id = "1111";
ping(id, host_nottrack);
return new Promise(function(resolve, reject) {
setTimeout(function() {
isPinged(id, expectPing, msg, resolve);
}, timeout);
});
}
function testPingBlacklistSafebrowsingOff() {
SpecialPowers.setBoolPref(TP_ENABLE_PREF, false);
var msg = "ping should reach page in blacklist when tracking protection is off";
var expectPing = true;
var id = "2222";
ping(id, host_track);
return new Promise(function(resolve, reject) {
setTimeout(function() {
isPinged(id, expectPing, msg, resolve);
}, timeout);
});
}
function testPingBlacklistSafebrowsingOn() {
SpecialPowers.setBoolPref(TP_ENABLE_PREF, true);
var msg = "ping should not reach page in blacklist when tracking protection is on";
var expectPing = false;
var id = "3333";
ping(id, host_track);
return new Promise(function(resolve, reject) {
setTimeout(function() {
isPinged(id, expectPing, msg, resolve);
}, timeout);
});
}
function ping(id, host) {
var elm = document.createElement("a");
elm.setAttribute('ping', host + path_ping + "?id=" + id);
elm.setAttribute('href', "#");
document.body.appendChild(elm);
// Trigger ping.
elm.click();
document.body.removeChild(elm);
}
function isPinged(id, expected, msg, callback) {
var url = "http://mochi.test:8888/" + path_ping;
var xhr = new XMLHttpRequest();
xhr.open('GET', url + "?id=" + id);
xhr.onload = function() {
var isPinged = xhr.response === "ping";
is(expected, isPinged, msg);
callback();
};
xhr.send();
}
function cleanup() {
SpecialPowers.clearUserPref(TP_ENABLE_PREF);
}
function runTest() {
Promise.resolve()
.then(testPingNonBlacklist)
.then(testPingBlacklistSafebrowsingOff)
.then(testPingBlacklistSafebrowsingOn)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
SimpleTest.registerCleanupFunction(cleanup);
SpecialPowers.pushPrefEnv({"set": [
["browser.send_pings", true],
["urlclassifier.trackingTable", "test-track-simple"],
]}, runTest);
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,162 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1262406 - Track element doesn't use the URL classifier.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const PREF = "browser.safebrowsing.malware.enabled";
const track_path = "tests/toolkit/components/url-classifier/tests/mochitest/basic.vtt";
const malware_url = "http://malware.example.com/" + track_path;
const validtrack_url = "http://mochi.test:8888/" + track_path;
var video = document.createElement("video");
video.src = "seek.webm";
video.crossOrigin = "anonymous";
document.body.appendChild(video);
function testValidTrack() {
SpecialPowers.setBoolPref(PREF, true);
return new Promise(function(resolve, reject) {
var track = document.createElement("track");
track.src = validtrack_url;
video.appendChild(track);
function onload() {
ok(true, "Track should be loaded when url is not in blacklist");
finish();
}
function onerror() {
ok(false, "Error while loading track");
finish();
}
function finish() {
track.removeEventListener("load", onload);
track.removeEventListener("error", onerror)
resolve();
}
track.addEventListener("load", onload);
track.addEventListener("error", onerror)
});
}
function testBlacklistTrackSafebrowsingOff() {
SpecialPowers.setBoolPref(PREF, false);
return new Promise(function(resolve, reject) {
var track = document.createElement("track");
track.src = malware_url;
video.appendChild(track);
function onload() {
ok(true, "Track should be loaded when url is in blacklist and safebrowsing is off");
finish();
}
function onerror() {
ok(false, "Error while loading track");
finish();
}
function finish() {
track.removeEventListener("load", onload);
track.removeEventListener("error", onerror)
resolve();
}
track.addEventListener("load", onload);
track.addEventListener("error", onerror)
});
}
function testBlacklistTrackSafebrowsingOn() {
SpecialPowers.setBoolPref(PREF, true);
return new Promise(function(resolve, reject) {
var track = document.createElement("track");
// Add a query string parameter here to avoid url classifier bypass classify
// because of cache.
track.src = malware_url + "?testsbon";
video.appendChild(track);
function onload() {
ok(false, "Unexpected result while loading track in blacklist");
finish();
}
function onerror() {
ok(true, "Track should not be loaded when url is in blacklist and safebrowsing is on");
finish();
}
function finish() {
track.removeEventListener("load", onload);
track.removeEventListener("error", onerror)
resolve();
}
track.addEventListener("load", onload);
track.addEventListener("error", onerror)
});
}
function cleanup() {
SpecialPowers.clearUserPref(PREF);
}
function setup() {
var testData = [
{ url: "malware.example.com/",
db: "test-malware-simple"
}
];
return classifierHelper.addUrlToDB(testData)
.catch(function(err) {
ok(false, "Couldn't update classifier. Error code: " + err);
// Abort test.
SimpleTest.finish();
});
}
function runTest() {
Promise.resolve()
.then(classifierHelper.waitForInit)
.then(setup)
.then(testValidTrack)
.then(testBlacklistTrackSafebrowsingOff)
.then(testBlacklistTrackSafebrowsingOn)
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
SimpleTest.registerCleanupFunction(cleanup);
SpecialPowers.pushPrefEnv({"set": [
["media.webvtt.regions.enabled", true],
["urlclassifier.malwareTable", "test-malware-simple"],
]}, runTest);
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,150 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1258033 - Fix the DNT loophole for tracking protection</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
const tests = [
// DNT turned on and TP turned off, DNT signal sent in both private browsing
// and normal mode.
{
setting: {dntPref:true, tpPref:false, tppbPref:false, pbMode:true},
expected: {dnt: "1"},
},
{
setting: {dntPref:true, tpPref:false, tppbPref:false, pbMode:false},
expected: {dnt: "1"}
},
// DNT turned off and TP turned on globally, DNT signal sent in both private
// browsing and normal mode.
{
setting: {dntPref:false, tpPref:true, tppbPref:false, pbMode:true},
expected: {dnt: "1"}
},
{
setting: {dntPref:false, tpPref:true, tppbPref:false, pbMode:false},
expected: {dnt: "1"}
},
// DNT turned off and TP in Private Browsing only, DNT signal sent in private
// browsing mode only.
{
setting: {dntPref:false, tpPref:false, tppbPref:true, pbMode:true},
expected: {dnt: "1"}
},
{
setting: {dntPref:false, tpPref:false, tppbPref:true, pbMode:false},
expected: {dnt: "unspecified"}
},
// DNT turned off and TP turned off, DNT signal is never sent.
{
setting: {dntPref:false, tpPref:false, tppbPref:false, pbMode:true},
expected: {dnt: "unspecified"}
},
{
setting: {dntPref:false, tpPref:false, tppbPref:false, pbMode:false},
expected: {dnt: "unspecified"}
},
]
const DNT_PREF = 'privacy.donottrackheader.enabled';
const TP_PREF = 'privacy.trackingprotection.enabled';
const TP_PB_PREF = 'privacy.trackingprotection.pbmode.enabled';
const contentPage =
"http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/dnt.html";
Components.utils.import("resource://gre/modules/Services.jsm");
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {
Services.obs.removeObserver(observer, aTopic);
setTimeout(aCallback, 0);
}
}, "browser-delayed-startup-finished", false);
}
function executeTest(test) {
SpecialPowers.pushPrefEnv({"set" : [
[DNT_PREF, test.setting.dntPref],
[TP_PREF, test.setting.tpPref],
[TP_PB_PREF, test.setting.tppbPref]
]});
var win = mainWindow.OpenBrowserWindow({private: test.setting.pbMode});
return new Promise(function(resolve, reject) {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
whenDelayedStartupFinished(win, function() {
win.addEventListener("DOMContentLoaded", function onInnerLoad() {
if (win.content.location.href != contentPage) {
win.gBrowser.loadURI(contentPage);
return;
}
win.removeEventListener("DOMContentLoaded", onInnerLoad, true);
win.content.addEventListener('message', function (event) {
let [key, value] = event.data.split("=");
if (key == "finish") {
win.close();
resolve();
} else if (key == "navigator.doNotTrack") {
is(value, test.expected.dnt, "navigator.doNotTrack should be " + test.expected.dnt);
} else if (key == "DNT") {
let msg = test.expected.dnt == "1" ? "" : "not ";
is(value, test.expected.dnt, "DNT header should " + msg + "be sent");
} else {
ok(false, "unexpected message");
}
});
}, true);
SimpleTest.executeSoon(function() { win.gBrowser.loadURI(contentPage); });
});
}, true);
});
}
let loop = function loop(index) {
if (index >= tests.length) {
SimpleTest.finish();
return;
}
let test = tests[index];
let next = function next() {
loop(index + 1);
};
let result = executeTest(test);
result.then(next, next);
};
SimpleTest.waitForExplicitFinish();
loop(0);
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,157 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1272239 - Test gethash.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="classifierHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<iframe id="testFrame1" onload=""></iframe>
<iframe id="testFrame2" onload=""></iframe>
<script class="testbody" type="text/javascript">
const MALWARE_LIST = "test-malware-simple";
const MALWARE_HOST = "malware.example.com/";
const UNWANTED_LIST = "test-unwanted-simple";
const UNWANTED_HOST = "unwanted.example.com/";
const GETHASH_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/gethash.sjs";
const NOTEXIST_URL = "http://mochi.test:8888/tests/toolkit/components/url-classifier/tests/mochitest/nonexistserver.sjs";
var shouldLoad = false;
// In this testcase we store prefixes to localdb and send the fullhash to gethash server.
// When access the test page gecko should trigger gethash request to server and
// get the completion response.
function loadTestFrame(id) {
return new Promise(function(resolve, reject) {
var iframe = document.getElementById(id);
iframe.setAttribute("src", "gethashFrame.html");
iframe.onload = function() {
resolve();
};
});
}
// add 4-bytes prefixes to local database, so when we access the url,
// it will trigger gethash request.
function addPrefixToDB(list, url) {
var testData = [{ db: list, url: url, len: 4 }];
return classifierHelper.addUrlToDB(testData)
.catch(function(err) {
ok(false, "Couldn't update classifier. Error code: " + err);
// Abort test.
SimpleTest.finish();
});
}
// calculate the fullhash and send it to gethash server
function addCompletionToServer(list, url) {
return new Promise(function(resolve, reject) {
var listParam = "list=" + list;
var fullhashParam = "fullhash=" + hash(url);
var xhr = new XMLHttpRequest;
xhr.open("PUT", GETHASH_URL + "?" +
listParam + "&" +
fullhashParam, true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
resolve();
}
};
xhr.send();
});
}
function hash(str) {
function bytesFromString(str) {
var converter =
SpecialPowers.Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(SpecialPowers.Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
return converter.convertToByteArray(str);
}
var hasher = SpecialPowers.Cc["@mozilla.org/security/hash;1"]
.createInstance(SpecialPowers.Ci.nsICryptoHash);
var data = bytesFromString(str);
hasher.init(hasher.SHA256);
hasher.update(data, data.length);
return hasher.finish(true);
}
function setup404() {
shouldLoad = true;
classifierHelper.allowCompletion([MALWARE_LIST, UNWANTED_LIST], NOTEXIST_URL);
return Promise.all([
addPrefixToDB(MALWARE_LIST, MALWARE_HOST),
addPrefixToDB(UNWANTED_LIST, UNWANTED_HOST)
]);
}
function setup() {
classifierHelper.allowCompletion([MALWARE_LIST, UNWANTED_LIST], GETHASH_URL);
return Promise.all([
addPrefixToDB(MALWARE_LIST, MALWARE_HOST),
addPrefixToDB(UNWANTED_LIST, UNWANTED_HOST),
addCompletionToServer(MALWARE_LIST, MALWARE_HOST),
addCompletionToServer(UNWANTED_LIST, UNWANTED_HOST),
]);
}
// manually reset DB to make sure next test won't be affected by cache.
function reset() {
return classifierHelper.resetDB;
}
function runTest() {
Promise.resolve()
// This test resources get blocked when gethash returns successfully
.then(classifierHelper.waitForInit)
.then(setup)
.then(() => loadTestFrame("testFrame1"))
.then(reset)
// This test resources are not blocked when gethash returns an error
.then(setup404)
.then(() => loadTestFrame("testFrame2"))
.then(function() {
SimpleTest.finish();
}).catch(function(e) {
ok(false, "Some test failed with error " + e);
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
// 'network.predictor.enabled' is disabled because if other testcase load
// evil.js, evil.css ...etc resources, it may cause we load them from cache
// directly and bypass classifier check
SpecialPowers.pushPrefEnv({"set": [
["browser.safebrowsing.malware.enabled", true],
["network.predictor.enabled", false],
["urlclassifier.gethash.timeout_ms", 30000],
]}, runTest);
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that lookup() on a system principal doesn't crash</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="text/javascript">
var Cc = Components.classes;
var Ci = Components.interfaces;
var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
dbService.lookup(document.nodePrincipal, "", function(arg) {});
ok(true, "lookup() didn't crash");
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,154 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<title>Test Tracking Protection in Private Browsing mode</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var contentPage = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {
Services.obs.removeObserver(observer, aTopic);
setTimeout(aCallback, 0);
}
}, "browser-delayed-startup-finished", false);
}
function testOnWindow(aPrivate, aCallback) {
var win = mainWindow.OpenBrowserWindow({private: aPrivate});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
whenDelayedStartupFinished(win, function() {
win.addEventListener("DOMContentLoaded", function onInnerLoad() {
if (win.content.location.href != contentPage) {
win.gBrowser.loadURI(contentPage);
return;
}
win.removeEventListener("DOMContentLoaded", onInnerLoad, true);
win.content.addEventListener('load', function innerLoad2() {
win.content.removeEventListener('load', innerLoad2, false);
SimpleTest.executeSoon(function() { aCallback(win); });
}, false, true);
}, true);
SimpleTest.executeSoon(function() { win.gBrowser.loadURI(contentPage); });
});
}, true);
}
var badids = [
"badscript",
"badimage",
"badcss"
];
function checkLoads(aWindow, aBlocked) {
var win = aWindow.content;
is(win.document.getElementById("badscript").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking javascript");
is(win.document.getElementById("badimage").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking images");
is(win.document.getElementById("goodscript").dataset.touched, "yes", "Should load whitelisted tracking javascript");
var elt = win.document.getElementById("styleCheck");
var style = win.document.defaultView.getComputedStyle(elt, "");
isnot(style.visibility, aBlocked ? "hidden" : "", "Should not load tracking css");
is(win.document.blockedTrackingNodeCount, aBlocked ? badids.length : 0, "Should identify all tracking elements");
var blockedTrackingNodes = win.document.blockedTrackingNodes;
// Make sure that every node in blockedTrackingNodes exists in the tree
// (that may not always be the case but do not expect any nodes to disappear
// from the tree here)
var allNodeMatch = true;
for (var i = 0; i < blockedTrackingNodes.length; i++) {
var nodeMatch = false;
for (var j = 0; j < badids.length && !nodeMatch; j++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
}
allNodeMatch = allNodeMatch && nodeMatch;
}
is(allNodeMatch, true, "All annotated nodes are expected in the tree");
// Make sure that every node with a badid (see badids) is found in the
// blockedTrackingNodes. This tells us if we are neglecting to annotate
// some nodes
allNodeMatch = true;
for (var j = 0; j < badids.length; j++) {
var nodeMatch = false;
for (var i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
}
allNodeMatch = allNodeMatch && nodeMatch;
}
is(allNodeMatch, aBlocked, "All tracking nodes are expected to be annotated as such");
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", "test-track-simple"],
["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.pbmode.enabled", true],
["channelclassifier.allowlist_example", true]]},
test);
function test() {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
UrlClassifierTestUtils.addTestTrackers().then(() => {
// Normal mode, with the pref (trackers should be loaded)
testOnWindow(false, function(aWindow) {
checkLoads(aWindow, false);
aWindow.close();
// Private Browsing, with the pref (trackers should be blocked)
testOnWindow(true, function(aWindow) {
checkLoads(aWindow, true);
aWindow.close();
// Private Browsing, without the pref (trackers should be loaded)
SpecialPowers.setBoolPref("privacy.trackingprotection.pbmode.enabled", false);
testOnWindow(true, function(aWindow) {
checkLoads(aWindow, false);
aWindow.close();
SimpleTest.finish();
});
});
});
});
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,87 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1272239 - Only tables with provider could register gethash url in listmanager.</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
// List all the tables
const prefs = [
"urlclassifier.phishTable",
"urlclassifier.malwareTable",
"urlclassifier.downloadBlockTable",
"urlclassifier.downloadAllowTable",
"urlclassifier.trackingTable",
"urlclassifier.trackingWhitelistTable",
"urlclassifier.blockedTable"
];
var prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService);
// Get providers
var providers = {};
var branch = prefService.getBranch("browser.safebrowsing.provider.");
var children = branch.getChildList("", {});
for (var child of children) {
var prefComponents = child.split(".");
var providerName = prefComponents[0];
providers[providerName] = {};
}
// Get lists from |browser.safebrowsing.provider.PROVIDER_NAME.lists| preference.
var listsWithProvider = [];
var listsToProvider = [];
for (var provider in providers) {
var pref = "browser.safebrowsing.provider." + provider + ".lists";
var list = SpecialPowers.getCharPref(pref).split(",");
listsToProvider = listsToProvider.concat(list.map( () => { return provider; }));
listsWithProvider = listsWithProvider.concat(list);
}
// Get all the lists
var lists = [];
for (var pref of prefs) {
lists = lists.concat(SpecialPowers.getCharPref(pref).split(","));
}
var listmanager = Cc["@mozilla.org/url-classifier/listmanager;1"].
getService(Ci.nsIUrlListManager);
for (var list of lists) {
if (!list)
continue;
// For lists having a provider, it should have a correct gethash url
// For lists without a provider, for example, test-malware-simple, it should not
// have a gethash url.
var url = listmanager.getGethashUrl(list);
var index = listsWithProvider.indexOf(list);
if (index >= 0) {
var provider = listsToProvider[index];
var pref = "browser.safebrowsing.provider." + provider + ".gethashURL";
is(url, SpecialPowers.getCharPref(pref), list + " matches its gethash url");
} else {
is(url, "", list + " should not have a gethash url");
}
}
</script>
</pre>
</body>
</html>

View file

@ -0,0 +1,107 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<title>Test Tracking Protection with and without Safe Browsing (Bug #1157081)</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var contentPage = "chrome://mochitests/content/chrome/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html"
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {
Services.obs.removeObserver(observer, aTopic);
setTimeout(aCallback, 0);
}
}, "browser-delayed-startup-finished", false);
}
function testOnWindow(aCallback) {
var win = mainWindow.OpenBrowserWindow();
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
whenDelayedStartupFinished(win, function() {
win.addEventListener("DOMContentLoaded", function onInnerLoad() {
if (win.content.location.href != contentPage) {
win.gBrowser.loadURI(contentPage);
return;
}
win.removeEventListener("DOMContentLoaded", onInnerLoad, true);
win.content.addEventListener('load', function innerLoad2() {
win.content.removeEventListener('load', innerLoad2, false);
SimpleTest.executeSoon(function() { aCallback(win); });
}, false, true);
}, true);
SimpleTest.executeSoon(function() { win.gBrowser.loadURI(contentPage); });
});
}, true);
}
var badids = [
"badscript"
];
function checkLoads(aWindow, aBlocked) {
var win = aWindow.content;
is(win.document.getElementById("badscript").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking javascript");
}
SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", "test-track-simple"],
["privacy.trackingprotection.enabled", true],
["browser.safebrowsing.malware.enabled", false],
["browser.safebrowsing.phishing.enabled", false],
["channelclassifier.allowlist_example", true]]},
test);
function test() {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
UrlClassifierTestUtils.addTestTrackers().then(() => {
// Safe Browsing turned OFF, tracking protection should work nevertheless
testOnWindow(function(aWindow) {
checkLoads(aWindow, true);
aWindow.close();
// Safe Browsing turned ON, tracking protection should still work
SpecialPowers.setBoolPref("browser.safebrowsing.phishing.enabled", true);
testOnWindow(function(aWindow) {
checkLoads(aWindow, true);
aWindow.close();
SimpleTest.finish();
});
});
});
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,153 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<title>Test Tracking Protection in Private Browsing mode</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var contentPage1 = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
var contentPage2 = "http://example.com/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
function whenDelayedStartupFinished(aWindow, aCallback) {
Services.obs.addObserver(function observer(aSubject, aTopic) {
if (aWindow == aSubject) {
Services.obs.removeObserver(observer, aTopic);
setTimeout(aCallback, 0);
}
}, "browser-delayed-startup-finished", false);
}
function testOnWindow(contentPage, aCallback) {
var win = mainWindow.OpenBrowserWindow();
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
whenDelayedStartupFinished(win, function() {
win.addEventListener("DOMContentLoaded", function onInnerLoad() {
if (win.content.location.href != contentPage) {
win.gBrowser.loadURI(contentPage);
return;
}
win.removeEventListener("DOMContentLoaded", onInnerLoad, true);
win.content.addEventListener('load', function innerLoad2() {
win.content.removeEventListener('load', innerLoad2, false);
SimpleTest.executeSoon(function() { aCallback(win); });
}, false, true);
}, true);
SimpleTest.executeSoon(function() { win.gBrowser.loadURI(contentPage); });
});
}, true);
}
var alwaysbadids = [
"badscript",
];
function checkLoads(aWindow, aWhitelisted) {
var win = aWindow.content;
is(win.document.getElementById("badscript").dataset.touched, "no", "Should not load tracking javascript");
is(win.document.getElementById("goodscript").dataset.touched, aWhitelisted ? "yes" : "no", "Should load whitelisted tracking javascript");
var badids = alwaysbadids.slice();
if (!aWhitelisted) {
badids.push("goodscript");
}
is(win.document.blockedTrackingNodeCount, badids.length, "Should identify all tracking elements");
var blockedTrackingNodes = win.document.blockedTrackingNodes;
// Make sure that every node in blockedTrackingNodes exists in the tree
// (that may not always be the case but do not expect any nodes to disappear
// from the tree here)
var allNodeMatch = true;
for (var i = 0; i < blockedTrackingNodes.length; i++) {
var nodeMatch = false;
for (var j = 0; j < badids.length && !nodeMatch; j++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
}
allNodeMatch = allNodeMatch && nodeMatch;
}
is(allNodeMatch, true, "All annotated nodes are expected in the tree");
// Make sure that every node with a badid (see badids) is found in the
// blockedTrackingNodes. This tells us if we are neglecting to annotate
// some nodes
allNodeMatch = true;
for (var j = 0; j < badids.length; j++) {
var nodeMatch = false;
for (var i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
nodeMatch = nodeMatch ||
(blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
}
allNodeMatch = allNodeMatch && nodeMatch;
}
is(allNodeMatch, true, "All tracking nodes are expected to be annotated as such");
}
SpecialPowers.pushPrefEnv(
{"set" : [["privacy.trackingprotection.enabled", true],
["channelclassifier.allowlist_example", true]]},
test);
function test() {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
UrlClassifierTestUtils.addTestTrackers().then(() => {
// Load the test from a URL on the whitelist
testOnWindow(contentPage1, function(aWindow) {
checkLoads(aWindow, true);
aWindow.close();
// Load the test from a URL that's NOT on the whitelist
testOnWindow(contentPage2, function(aWindow) {
checkLoads(aWindow, false);
aWindow.close();
// Load the test from a URL on the whitelist but without the whitelist
SpecialPowers.pushPrefEnv({"set" : [["urlclassifier.trackingWhitelistTable", ""]]},
function() {
testOnWindow(contentPage1, function(aWindow) {
checkLoads(aWindow, false);
aWindow.close();
SimpleTest.finish();
});
});
});
});
});
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<iframe id="testFrame" width="100%" height="100%" onload=""></iframe>
</body>
</html>

View file

@ -0,0 +1,7 @@
<html>
<head>
</head>
<body>
<h1>Tracking Works!</h1>
</body>
</html>

View file

@ -0,0 +1,3 @@
onmessage = function() {
postMessage("loaded bad file");
}

View file

@ -0,0 +1,114 @@
const CC = Components.Constructor;
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
"setInputStream");
function handleRequest(request, response)
{
var query = {};
request.queryString.split('&').forEach(function (val) {
var idx = val.indexOf('=');
query[val.slice(0, idx)] = unescape(val.slice(idx + 1));
});
// Store fullhash in the server side.
if ("list" in query && "fullhash" in query) {
// In the server side we will store:
// 1. All the full hashes for a given list
// 2. All the lists we have right now
// data is separate by '\n'
let list = query["list"];
let hashes = getState(list);
let hash = base64ToString(query["fullhash"]);
hashes += hash + "\n";
setState(list, hashes);
let lists = getState("lists");
if (lists.indexOf(list) == -1) {
lists += list + "\n";
setState("lists", lists);
}
return;
}
var body = new BinaryInputStream(request.bodyInputStream);
var avail;
var bytes = [];
while ((avail = body.available()) > 0) {
Array.prototype.push.apply(bytes, body.readByteArray(avail));
}
var responseBody = parseV2Request(bytes);
response.setHeader("Content-Type", "text/plain", false);
response.write(responseBody);
}
function parseV2Request(bytes) {
var table = String.fromCharCode.apply(this, bytes).slice(0,-2);
var ret = "";
getState("lists").split("\n").forEach(function(list) {
if (list == table) {
var completions = getState(list).split("\n");
ret += "n:1000\n"
ret += "i:" + list + "\n";
ret += "a:1:32:" + 32*(completions.length - 1) + "\n";
for (var completion of completions) {
ret += completion;
}
}
});
return ret;
}
/* Convert Base64 data to a string */
const toBinaryTable = [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
];
const base64Pad = '=';
function base64ToString(data) {
var result = '';
var leftbits = 0; // number of bits decoded, but yet to be appended
var leftdata = 0; // bits decoded, but yet to be appended
// Convert one by one.
for (var i = 0; i < data.length; i++) {
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
var padding = (data[i] == base64Pad);
// Skip illegal characters and whitespace
if (c == -1) continue;
// Collect data into leftdata, update bitcount
leftdata = (leftdata << 6) | c;
leftbits += 6;
// If we have 8 or more bits, append 8 bits to the result
if (leftbits >= 8) {
leftbits -= 8;
// Append if not padding.
if (!padding)
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
leftdata &= (1 << leftbits) - 1;
}
}
// If there are any bits left, the base64 string was corrupted
if (leftbits)
throw Components.Exception('Corrupted base64 string');
return result;
}

View file

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<title></title>
</head>
<body>
<script id="badscript" data-touched="not sure" src="http://trackertest.org/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
<script id="goodscript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
</body>
</html>

View file

@ -0,0 +1,65 @@
<html>
<head>
<title></title>
<script type="text/javascript">
function startCleanWorker() {
var worker = new Worker("cleanWorker.js");
worker.onmessage = function(event) {
if (event.data == "success") {
window.parent.postMessage("success:blocked importScripts('evilWorker.js')", "*");
} else {
window.parent.postMessage("failure:failed to block importScripts('evilWorker.js')", "*");
}
window.parent.postMessage("finish", "*");
};
worker.onerror = function(event) {
window.parent.postmessage("failure:failed to load cleanWorker.js", "*");
window.parent.postMessage("finish", "*");
};
worker.postMessage("");
}
function startEvilWorker() {
var worker = new Worker("evilWorker.js");
worker.onmessage = function(event) {
window.parent.postMessage("failure:failed to block evilWorker.js", "*");
startUnwantedWorker();
};
worker.onerror = function(event) {
window.parent.postMessage("success:blocked evilWorker.js", "*");
startUnwantedWorker();
};
worker.postMessage("");
}
function startUnwantedWorker() {
var worker = new Worker("unwantedWorker.js");
worker.onmessage = function(event) {
window.parent.postMessage("failure:failed to block unwantedWorker.js", "*");
startCleanWorker();
};
worker.onerror = function(event) {
window.parent.postMessage("success:blocked unwantedWorker.js", "*");
startCleanWorker();
};
worker.postMessage("");
}
</script>
</head>
<body onload="startEvilWorker()">
</body>
</html>