fune/netwerk/test/unit/test_trackingProtection_annotateChannels.js
Francois Marier 309a23afc3 Bug 1482950 - Use the correct 3rdparty check in tracking annotations. r=dimi,Ehsan,mayhemer!,ehsan!
The mIsTrackingResource flag on nsIHttpChannel was split into two separate
flags depending on whether or not the resource is third-party. The correct
flag will be set by the channel classifier. Similarly, a new function was
introduced, GetIsThirdPartyTrackingResource(), for those consumers (like TP)
who only care about third-party trackers.

The existing function, GetIsTracking(), will continue to look at both
first-party and third-party trackers (the behavior since first party
tracking was added to annotations in bug 1476324).

The OverrideTrackingResource() function now allows nsHTMLDocument to
override both mIsFirstPartyTrackingResource and
mIsThirdPartyTrackingResource, but since this function is a little dangerous
and only has a single user, I added an assert to make future callers think
twice about using it to opt out of tracking annotations.

Currently, only the default storage restrictions need to look at first-party
trackers so every other consumer has been moved to
mIsThirdPartyTrackingResource or GetIsThirdPartyTrackingResource().

This effectively reverts the third-party checks added in bug 1476715 and
replaces them with the more complicated check that was added in bug 1108017.
It follows the approach that Ehsan initially suggested in bug 1476715. It
also reverts the changes in the expected values of the tracking annotation
test since these were, in hindsight, a warning about this regression.

Depends on D3722

Differential Revision: https://phabricator.services.mozilla.com/D3723

--HG--
extra : moz-landing-system : lando
2018-08-20 23:53:45 +00:00

322 lines
12 KiB
JavaScript

ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://testing-common/httpd.js");
// This test supports both e10s and non-e10s mode. In non-e10s mode, this test
// drives itself by creating a profile directory, setting up the URL classifier
// test tables and adjusting the prefs which are necessary to do the testing.
// In e10s mode however, some of these operations such as creating a profile
// directory, setting up the URL classifier test tables and setting prefs
// aren't supported in the content process, so we split the test into two
// parts, the part testing the normal priority case by setting both prefs to
// false (test_trackingProtection_annotateChannels_wrap1.js), and the part
// testing the lowest priority case by setting both prefs to true
// (test_trackingProtection_annotateChannels_wrap2.js). These wrapper scripts
// are also in charge of creating the profile directory and setting up the URL
// classifier test tables.
//
// Below where we need to take different actions based on the process type we're
// in, we use runtime.processType to take the correct actions.
const runtime = Services.appinfo;
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
do_get_profile();
}
const defaultTopWindowURI = NetUtil.newURI("http://www.example.com/");
function listener(tracking, priority, throttleable, nextTest) {
this._tracking = tracking;
this._priority = priority;
this._throttleable = throttleable;
this._nextTest = nextTest;
}
listener.prototype = {
onStartRequest: function(request, context) {
Assert.equal(request.QueryInterface(Ci.nsIHttpChannel).isTrackingResource,
this._tracking, "tracking flag");
Assert.equal(request.QueryInterface(Ci.nsISupportsPriority).priority,
this._priority, "channel priority");
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT && this._tracking) {
Assert.equal(!!(request.QueryInterface(Ci.nsIClassOfService).classFlags &
Ci.nsIClassOfService.Throttleable),
this._throttleable, "throttleable flag");
}
request.cancel(Cr.NS_ERROR_ABORT);
this._nextTest();
},
onDataAvailable: (request, context, stream, offset, count) => {},
onStopRequest: (request, context, status) => {},
};
var httpServer;
var normalOrigin, trackingOrigin;
var testPriorityMap;
var currentTest;
// When this test is running in e10s mode, the parent process is in charge of
// setting the prefs for us, so here we merely read our prefs, and if they have
// been set we skip the normal priority test and only test the lowest priority
// case, and if it they have not been set we skip the lowest priority test and
// only test the normal priority case.
// In non-e10s mode, both of these will remain false and we adjust the prefs
// ourselves and test both of the cases in one go.
var skipNormalPriority = false, skipLowestPriority = false;
function setup_test() {
httpServer = new HttpServer();
httpServer.start(-1);
httpServer.identity.setPrimary("http", "tracking.example.org", httpServer.identity.primaryPort);
httpServer.identity.add("http", "example.org", httpServer.identity.primaryPort);
normalOrigin = "http://localhost:" + httpServer.identity.primaryPort;
trackingOrigin = "http://tracking.example.org:" + httpServer.identity.primaryPort;
if (runtime.processType == runtime.PROCESS_TYPE_CONTENT) {
if (Services.prefs.getBoolPref("privacy.trackingprotection.annotate_channels") &&
Services.prefs.getBoolPref("privacy.trackingprotection.lower_network_priority")) {
skipNormalPriority = true;
} else {
skipLowestPriority = true;
}
}
runTests();
}
function doPriorityTest() {
if (!testPriorityMap.length) {
runTests();
return;
}
currentTest = testPriorityMap.shift();
// Let's be explicit about what we're testing!
Assert.ok("loadingPrincipal" in currentTest, "check for incomplete test case");
Assert.ok("topWindowURI" in currentTest, "check for incomplete test case");
var channel = makeChannel(currentTest.path, currentTest.loadingPrincipal, currentTest.topWindowURI);
channel.asyncOpen2(new listener(currentTest.expectedTracking,
currentTest.expectedPriority,
currentTest.expectedThrottleable,
doPriorityTest));
}
function makeChannel(path, loadingPrincipal, topWindowURI) {
var chan;
if (loadingPrincipal) {
chan = NetUtil.newChannel({
uri: path,
loadingPrincipal,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
});
} else {
chan = NetUtil.newChannel({
uri: path,
loadUsingSystemPrincipal: true,
});
}
chan.QueryInterface(Ci.nsIHttpChannel);
chan.requestMethod = "GET";
chan.loadFlags |= Ci.nsIChannel.LOAD_CLASSIFY_URI;
if (topWindowURI) {
chan.QueryInterface(Ci.nsIHttpChannelInternal).setTopWindowURIIfUnknown(topWindowURI);
}
return chan;
}
var tests = [
// Create the HTTP server.
setup_test,
// Add the test table into tracking protection table.
function addTestTrackers() {
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
UrlClassifierTestUtils.addTestTrackers().then(() => {
runTests();
});
} else {
runTests();
}
},
// Annotations OFF, normal loading principal, topWinURI of example.com
// => trackers should not be de-prioritized
function setupAnnotationsOff() {
if (skipNormalPriority) {
runTests();
return;
}
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
Services.prefs.setBoolPref("privacy.trackingprotection.annotate_channels", false);
Services.prefs.setBoolPref("privacy.trackingprotection.lower_network_priority", false);
}
var principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(normalOrigin);
testPriorityMap = [
{
path: normalOrigin + "/innocent.css",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: normalOrigin + "/innocent.js",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: trackingOrigin + "/evil.css",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: trackingOrigin + "/evil.js",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
];
// We add the doPriorityTest test here so that it only gets injected in the
// test list if we're not skipping over this test.
tests.unshift(doPriorityTest);
runTests();
},
// Annotations ON, normal loading principal, topWinURI of example.com
// => trackers should be de-prioritized
function setupAnnotationsOn() {
if (skipLowestPriority) {
runTests();
return;
}
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
Services.prefs.setBoolPref("privacy.trackingprotection.annotate_channels", true);
Services.prefs.setBoolPref("privacy.trackingprotection.lower_network_priority", true);
}
var principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(normalOrigin);
testPriorityMap = [
{
path: normalOrigin + "/innocent.css",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: normalOrigin + "/innocent.js",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: trackingOrigin + "/evil.css",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
expectedThrottleable: true,
},
{
path: trackingOrigin + "/evil.js",
loadingPrincipal: principal,
topWindowURI: defaultTopWindowURI,
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
expectedThrottleable: true,
},
];
// We add the doPriorityTest test here so that it only gets injected in the
// test list if we're not skipping over this test.
tests.unshift(doPriorityTest);
runTests();
},
// Annotations ON, system loading principal, topWinURI of example.com
// => trackers should be de-prioritized
function setupAnnotationsOnSystemPrincipal() {
if (skipLowestPriority) {
runTests();
return;
}
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
Services.prefs.setBoolPref("privacy.trackingprotection.annotate_channels", true);
Services.prefs.setBoolPref("privacy.trackingprotection.lower_network_priority", true);
}
testPriorityMap = [
{
path: normalOrigin + "/innocent.css",
loadingPrincipal: null, // system principal
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: normalOrigin + "/innocent.js",
loadingPrincipal: null, // system principal
topWindowURI: defaultTopWindowURI,
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL,
expectedThrottleable: false, // ignored since tracking==false
},
{
path: trackingOrigin + "/evil.css",
loadingPrincipal: null, // system principal
topWindowURI: defaultTopWindowURI,
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
expectedThrottleable: true,
},
{
path: trackingOrigin + "/evil.js",
loadingPrincipal: null, // system principal
topWindowURI: defaultTopWindowURI,
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST,
expectedThrottleable: true,
},
];
// We add the doPriorityTest test here so that it only gets injected in the
// test list if we're not skipping over this test.
tests.unshift(doPriorityTest);
runTests();
},
function cleanUp() {
httpServer.stop(do_test_finished);
if (runtime.processType == runtime.PROCESS_TYPE_DEFAULT) {
UrlClassifierTestUtils.cleanupTestTrackers();
}
runTests();
}
];
function runTests() {
if (!tests.length) {
do_test_finished();
return;
}
var test = tests.shift();
test();
}
function run_test() {
runTests();
do_test_pending();
}