Source code
Revision control
Copy as Markdown
Other Tools
const ANNOTATION_TABLE_NAME = "mochitest1-track-simple";
const ANNOTATION_TABLE_PREF = "urlclassifier.trackingAnnotationTable";
const ANNOTATION_ENTITYLIST_TABLE_NAME = "mochitest1-trackwhite-simple";
const ANNOTATION_ENTITYLIST_TABLE_PREF =
"urlclassifier.trackingAnnotationWhitelistTable";
const TRACKING_TABLE_NAME = "mochitest2-track-simple";
const TRACKING_TABLE_PREF = "urlclassifier.trackingTable";
const ENTITYLIST_TABLE_NAME = "mochitest2-trackwhite-simple";
const ENTITYLIST_TABLE_PREF = "urlclassifier.trackingWhitelistTable";
const SOCIAL_ANNOTATION_TABLE_NAME = "mochitest3-track-simple";
const SOCIAL_ANNOTATION_TABLE_PREF =
"urlclassifier.features.socialtracking.annotate.blacklistTables";
const SOCIAL_TRACKING_TABLE_NAME = "mochitest4-track-simple";
const SOCIAL_TRACKING_TABLE_PREF =
"urlclassifier.features.socialtracking.blacklistTables";
const EMAIL_TRACKING_TABLE_NAME = "mochitest5-track-simple";
const EMAIL_TRACKING_TABLE_PREF =
"urlclassifier.features.emailtracking.blocklistTables";
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
export var UrlClassifierTestUtils = {
addTestTrackers() {
// Add some URLs to the tracking databases
let annotationURL1 = "tracking.example.org/"; // only for annotations
let annotationURL2 = "itisatracker.org/";
let annotationURL3 = "trackertest.org/";
let annotationURL4 = "another-tracking.example.net/";
let annotationURL5 = "tlsresumptiontest.example.org/";
let annotationEntitylistedURL = "itisatrap.org/?resource=example.org";
let trackingURL1 = "tracking.example.com/"; // only for TP
let trackingURL2 = "itisatracker.org/";
let trackingURL3 = "trackertest.org/";
let entitylistedURL = "itisatrap.org/?resource=itisatracker.org";
let socialTrackingURL = "social-tracking.example.org/";
let emailTrackingURL = "email-tracking.example.org/";
let annotationUpdate =
"n:1000\ni:" +
ANNOTATION_TABLE_NAME +
"\nad:5\n" +
"a:1:32:" +
annotationURL1.length +
"\n" +
annotationURL1 +
"\n" +
"a:2:32:" +
annotationURL2.length +
"\n" +
annotationURL2 +
"\n" +
"a:3:32:" +
annotationURL3.length +
"\n" +
annotationURL3 +
"\n" +
"a:4:32:" +
annotationURL4.length +
"\n" +
annotationURL4 +
"\n" +
"a:5:32:" +
annotationURL5.length +
"\n" +
annotationURL5 +
"\n";
let socialAnnotationUpdate =
"n:1000\ni:" +
SOCIAL_ANNOTATION_TABLE_NAME +
"\nad:1\n" +
"a:1:32:" +
socialTrackingURL.length +
"\n" +
socialTrackingURL +
"\n";
let annotationEntitylistUpdate =
"n:1000\ni:" +
ANNOTATION_ENTITYLIST_TABLE_NAME +
"\nad:1\n" +
"a:1:32:" +
annotationEntitylistedURL.length +
"\n" +
annotationEntitylistedURL +
"\n";
let trackingUpdate =
"n:1000\ni:" +
TRACKING_TABLE_NAME +
"\nad:3\n" +
"a:1:32:" +
trackingURL1.length +
"\n" +
trackingURL1 +
"\n" +
"a:2:32:" +
trackingURL2.length +
"\n" +
trackingURL2 +
"\n" +
"a:3:32:" +
trackingURL3.length +
"\n" +
trackingURL3 +
"\n";
let socialTrackingUpdate =
"n:1000\ni:" +
SOCIAL_TRACKING_TABLE_NAME +
"\nad:1\n" +
"a:1:32:" +
socialTrackingURL.length +
"\n" +
socialTrackingURL +
"\n";
let emailTrackingUpdate =
"n:1000\ni:" +
EMAIL_TRACKING_TABLE_NAME +
"\nad:1\n" +
"a:1:32:" +
emailTrackingURL.length +
"\n" +
emailTrackingURL +
"\n";
let entitylistUpdate =
"n:1000\ni:" +
ENTITYLIST_TABLE_NAME +
"\nad:1\n" +
"a:1:32:" +
entitylistedURL.length +
"\n" +
entitylistedURL +
"\n";
var tables = [
{
pref: ANNOTATION_TABLE_PREF,
name: ANNOTATION_TABLE_NAME,
update: annotationUpdate,
},
{
pref: SOCIAL_ANNOTATION_TABLE_PREF,
name: SOCIAL_ANNOTATION_TABLE_NAME,
update: socialAnnotationUpdate,
},
{
pref: ANNOTATION_ENTITYLIST_TABLE_PREF,
name: ANNOTATION_ENTITYLIST_TABLE_NAME,
update: annotationEntitylistUpdate,
},
{
pref: TRACKING_TABLE_PREF,
name: TRACKING_TABLE_NAME,
update: trackingUpdate,
},
{
pref: SOCIAL_TRACKING_TABLE_PREF,
name: SOCIAL_TRACKING_TABLE_NAME,
update: socialTrackingUpdate,
},
{
pref: EMAIL_TRACKING_TABLE_PREF,
name: EMAIL_TRACKING_TABLE_NAME,
update: emailTrackingUpdate,
},
{
pref: ENTITYLIST_TABLE_PREF,
name: ENTITYLIST_TABLE_NAME,
update: entitylistUpdate,
},
];
let tableIndex = 0;
let doOneUpdate = () => {
if (tableIndex == tables.length) {
return Promise.resolve();
}
return this.useTestDatabase(tables[tableIndex]).then(
() => {
tableIndex++;
return doOneUpdate();
},
aErrMsg => {
dump("Rejected: " + aErrMsg + ". Retry later.\n");
return new Promise(resolve => {
timer.initWithCallback(resolve, 100, Ci.nsITimer.TYPE_ONE_SHOT);
}).then(doOneUpdate);
}
);
};
return doOneUpdate();
},
cleanupTestTrackers() {
Services.prefs.clearUserPref(ANNOTATION_TABLE_PREF);
Services.prefs.clearUserPref(SOCIAL_ANNOTATION_TABLE_PREF);
Services.prefs.clearUserPref(ANNOTATION_ENTITYLIST_TABLE_PREF);
Services.prefs.clearUserPref(TRACKING_TABLE_PREF);
Services.prefs.clearUserPref(SOCIAL_TRACKING_TABLE_PREF);
Services.prefs.clearUserPref(EMAIL_TRACKING_TABLE_PREF);
Services.prefs.clearUserPref(ENTITYLIST_TABLE_PREF);
},
/**
* Add some entries to a test tracking protection database, and resets
* back to the default database after the test ends.
*
* @return {Promise}
*/
useTestDatabase(table) {
Services.prefs.setCharPref(table.pref, table.name);
return new Promise((resolve, reject) => {
let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(
Ci.nsIUrlClassifierDBService
);
let listener = {
QueryInterface: iid => {
if (
iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIUrlClassifierUpdateObserver)
) {
return listener;
}
throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
},
updateUrlRequested: () => {},
streamFinished: () => {},
updateError: () => {
reject("Got updateError when updating " + table.name);
},
updateSuccess: () => {
resolve();
},
};
try {
dbService.beginUpdate(listener, table.name, "");
dbService.beginStream("", "");
dbService.updateStream(table.update);
dbService.finishStream();
dbService.finishUpdate();
} catch (e) {
reject("Failed to update with dbService: " + table.name);
}
});
},
/**
* Handle the next "urlclassifier-before-block-channel" event.
* @param {Object} options
* @param {String} [options.filterOrigin] - Only handle event for channels
* with matching origin.
* @param {function} [options.onBeforeBlockChannel] - Optional callback for
* the event. Called before acting on the channel.
* @param {("allow"|"replace")} [options.action] - Whether to allow or replace
* the channel.
* @returns {Promise} - Resolves once event has been handled.
*/
handleBeforeBlockChannel({
filterOrigin = null,
onBeforeBlockChannel,
action,
}) {
if (action && action != "allow" && action != "replace") {
throw new Error("Invalid action " + action);
}
let channelClassifierService = Cc[
"@mozilla.org/url-classifier/channel-classifier-service;1"
].getService(Ci.nsIChannelClassifierService);
let resolver;
let promise = new Promise(resolve => {
resolver = resolve;
});
let observer = {
observe(subject, topic) {
if (topic != "urlclassifier-before-block-channel") {
return;
}
let channel = subject.QueryInterface(Ci.nsIUrlClassifierBlockedChannel);
if (filterOrigin) {
let { url } = channel;
let { origin } = new URL(url);
if (filterOrigin != origin) {
return;
}
}
if (onBeforeBlockChannel) {
onBeforeBlockChannel(channel);
}
if (action) {
channel[action]();
}
channelClassifierService.removeListener(observer);
resolver();
},
};
channelClassifierService.addListener(observer);
return promise;
},
};