Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
"use strict";
let { UrlClassifierTestUtils } = ChromeUtils.importESModule(
);
// itisatracker.org is in mochitest2-track-simple (blocking) and is third-party
const BLOCKING_TRACKER_IMAGE =
BLOCKING_TRACKER_DOMAIN + TEST_PATH + "raptor.jpg";
// tracking.example.org is in mochitest1-track-simple (annotation only) and is
// third-party to TEST_PAGE.
const ANNOTATION_TRACKER_IMAGE =
ANNOTATION_TRACKER_DOMAIN + TEST_PATH + "raptor.jpg";
const ANY_TRACKING =
Ci.nsIClassifiedChannel.CLASSIFIED_ANY_BASIC_TRACKING |
Ci.nsIClassifiedChannel.CLASSIFIED_ANY_STRICT_TRACKING;
function captureFlagsAt(topic, expectedURL) {
return new Promise(resolve => {
function observer(subject) {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
if (!httpChannel.URI.spec.startsWith(expectedURL)) {
return;
}
let classified = subject.QueryInterface(Ci.nsIClassifiedChannel);
Services.obs.removeObserver(observer, topic);
resolve(classified.classificationFlags);
}
Services.obs.addObserver(observer, topic);
});
}
function watchExamineResponse(expectedURL) {
let observed = false;
function observer(subject) {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
if (!httpChannel.URI.spec.startsWith(expectedURL)) {
return;
}
observed = true;
Services.obs.removeObserver(observer, "http-on-examine-response");
}
Services.obs.addObserver(observer, "http-on-examine-response");
return {
didFire() {
return observed;
},
cancel() {
try {
Services.obs.removeObserver(observer, "http-on-examine-response");
} catch (e) {
// already removed
}
},
};
}
add_setup(async function () {
await UrlClassifierTestUtils.addTestTrackers();
registerCleanupFunction(function () {
UrlClassifierTestUtils.cleanupTestTrackers();
});
await SpecialPowers.pushPrefEnv({
set: [
["privacy.trackingprotection.enabled", true],
["privacy.trackingprotection.annotate_channels", true],
["privacy.trackingprotection.fingerprinting.enabled", false],
["privacy.trackingprotection.cryptomining.enabled", false],
["privacy.trackingprotection.emailtracking.enabled", false],
["privacy.trackingprotection.socialtracking.enabled", false],
["privacy.trackingprotection.antifraud.annotate_channels", false],
["privacy.trackingprotection.consentmanager.annotate_channels", false],
],
});
});
async function runScenario({ deferAnnotations }) {
await SpecialPowers.pushPrefEnv({
set: [
["privacy.trackingprotection.defer_annotation.enabled", deferAnnotations],
],
});
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
// 1. Blocking tracker: cancelled regardless of pref. Blocking is in the
// pre-connect phase under both pref values.
let blockingLoaded = await loadImage(
tab.linkedBrowser,
BLOCKING_TRACKER_IMAGE
);
ok(
!blockingLoaded,
`Blocking tracker is cancelled (deferAnnotations=${deferAnnotations})`
);
// 2. Annotation-only tracker: loads under both prefs. Flag visibility on
// http-on-modify-request differs by pref.
let examineWatch = watchExamineResponse(ANNOTATION_TRACKER_DOMAIN);
let modifyFlagsPromise = captureFlagsAt(
"http-on-modify-request",
ANNOTATION_TRACKER_DOMAIN
);
let stopFlagsPromise = captureFlagsAt(
"http-on-stop-request",
ANNOTATION_TRACKER_DOMAIN
);
let annotationLoaded = await loadImage(
tab.linkedBrowser,
ANNOTATION_TRACKER_IMAGE
);
ok(annotationLoaded, "Annotation-only tracker loads regardless of pref");
let modifyFlags = await modifyFlagsPromise;
let stopFlags = await stopFlagsPromise;
if (deferAnnotations) {
is(
modifyFlags & ANY_TRACKING,
0,
"Pref ON: annotation flag NOT set at http-on-modify-request"
);
ok(
stopFlags & ANY_TRACKING,
"Pref ON: annotation flag set by http-on-stop-request"
);
ok(
examineWatch.didFire(),
"Pref ON: http-on-examine-response observed for annotation tracker"
);
} else {
ok(
modifyFlags & ANY_TRACKING,
"Pref OFF: annotation flag set at http-on-modify-request"
);
ok(
stopFlags & ANY_TRACKING,
"Pref OFF: annotation flag still set by http-on-stop-request"
);
}
examineWatch.cancel();
// 3. Content blocking log captures both events irrespective of pref.
let log = JSON.parse(tab.linkedBrowser.getContentBlockingLog());
ok(log, "Content blocking log readable");
ok(
Object.keys(log).some(origin =>
),
"Content blocking log includes the blocking tracker origin"
);
ok(
Object.keys(log).some(origin =>
),
"Content blocking log includes the annotation tracker origin"
);
await BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
}
add_task(async function test_defer_annotation_pref_off() {
await runScenario({ deferAnnotations: false });
});
add_task(async function test_defer_annotation_pref_on() {
await runScenario({ deferAnnotations: true });
});