summaryrefslogtreecommitdiffstats
path: root/src/tests/tests/background.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/tests/background.js')
-rw-r--r--src/tests/tests/background.js467
1 files changed, 467 insertions, 0 deletions
diff --git a/src/tests/tests/background.js b/src/tests/tests/background.js
new file mode 100644
index 0000000..149db42
--- /dev/null
+++ b/src/tests/tests/background.js
@@ -0,0 +1,467 @@
+/* globals badger:false */
+
+(function () {
+
+const DNT_COMPLIANT_DOMAIN = 'eff.org',
+ DNT_DOMAINS = [
+ DNT_COMPLIANT_DOMAIN,
+ 'dnt2.example',
+ 'dnt3.example',
+ 'dnt4.example',
+ 'dnt5.example',
+ ],
+ POLICY_URL = chrome.runtime.getURL('data/dnt-policy.txt');
+
+let utils = require('utils'),
+ constants = require('constants'),
+ migrations = require('migrations').Migrations,
+ mdfp = require('multiDomainFP');
+
+let clock,
+ server,
+ xhrSpy,
+ dnt_policy_txt;
+
+function setupBadgerStorage(badger) {
+ // add foo.com, allowed as seen tracking on only one site
+ badger.storage.action_map.setItem('foo.com', {
+ dnt: false,
+ heuristicAction: constants.ALLOW,
+ nextUpdateTime: 100,
+ userAction: ""
+ });
+ badger.storage.snitch_map.setItem('foo.com', ['a.co']);
+
+ // add sub.bar.com,
+ // blocked after having been recorded tracking on three sites
+ badger.storage.action_map.setItem('bar.com', {
+ dnt: false,
+ heuristicAction: constants.BLOCK,
+ nextUpdateTime: 100,
+ userAction: ""
+ });
+ badger.storage.action_map.setItem('sub.bar.com', {
+ dnt: false,
+ heuristicAction: constants.BLOCK,
+ nextUpdateTime: 100,
+ userAction: ""
+ });
+ badger.storage.snitch_map.setItem('bar.com', ['a.co', 'b.co', 'c.co']);
+}
+
+QUnit.module("Background", {
+ before: (assert) => {
+ let done = assert.async();
+
+ // fetch locally stored DNT policy
+ utils.xhrRequest(POLICY_URL, function (err, data) {
+ dnt_policy_txt = data;
+
+ // set up fake server to simulate XMLHttpRequests
+ server = sinon.fakeServer.create({
+ respondImmediately: true
+ });
+ DNT_DOMAINS.forEach(domain => {
+ server.respondWith(
+ "GET",
+ "https://" + domain + "/.well-known/dnt-policy.txt",
+ [200, {}, dnt_policy_txt]
+ );
+ });
+
+ // set up fake timers to simulate window.setTimeout and co.
+ clock = sinon.useFakeTimers(+new Date());
+
+ done();
+ });
+ },
+
+ beforeEach: (/*assert*/) => {
+ // spy on utils.xhrRequest
+ xhrSpy = sinon.spy(utils, "xhrRequest");
+ },
+
+ afterEach: (/*assert*/) => {
+ // reset call counts, etc. after each test
+ utils.xhrRequest.restore();
+ },
+
+ after: (/*assert*/) => {
+ clock.restore();
+ server.restore();
+ }
+});
+
+QUnit.test("DNT policy checking", (assert) => {
+ const NUM_TESTS = 2,
+ done = assert.async(NUM_TESTS);
+
+ assert.expect(NUM_TESTS);
+
+ badger.checkForDNTPolicy(DNT_COMPLIANT_DOMAIN, function (successStatus) {
+ assert.ok(successStatus, "Domain returns good DNT policy");
+ done();
+ });
+
+ badger.checkForDNTPolicy('ecorp.example', function (successStatus) {
+ assert.notOk(successStatus, "Domain returns 200 but no valid policy");
+ done();
+ });
+
+ // advance the clock enough to trigger all rate-limited calls
+ clock.tick(constants.DNT_POLICY_CHECK_INTERVAL * NUM_TESTS);
+});
+
+QUnit.test("Several checks for same domain resolve to one XHR", (assert) => {
+ const NUM_CHECKS = 5;
+
+ // set recheck time to now
+ badger.storage.touchDNTRecheckTime(DNT_COMPLIANT_DOMAIN, +new Date());
+
+ for (let i = 0; i < NUM_CHECKS; i++) {
+ badger.checkForDNTPolicy(DNT_COMPLIANT_DOMAIN);
+ }
+
+ // advance the clock
+ clock.tick(constants.DNT_POLICY_CHECK_INTERVAL * NUM_CHECKS);
+
+ assert.equal(xhrSpy.callCount, 1, "XHR method gets called exactly once");
+ assert.equal(
+ xhrSpy.getCall(0).args[0],
+ "https://" + DNT_COMPLIANT_DOMAIN + "/.well-known/dnt-policy.txt",
+ "XHR method gets called with expected DNT URL"
+ );
+});
+
+QUnit.test("DNT checking is rate limited", (assert) => {
+ const NUM_TESTS = DNT_DOMAINS.length;
+
+ let done = assert.async(NUM_TESTS);
+
+ assert.expect(NUM_TESTS);
+
+ for (let i = 0; i < NUM_TESTS; i++) {
+ badger.checkForDNTPolicy(
+ DNT_DOMAINS[i],
+ function () { // eslint-disable-line no-loop-func
+ assert.equal(xhrSpy.callCount, i+1);
+ clock.tick(constants.DNT_POLICY_CHECK_INTERVAL);
+ done();
+ }
+ );
+ }
+});
+
+QUnit.test("DNT checking obeys user setting", (assert) => {
+ const NUM_TESTS = DNT_DOMAINS.length;
+
+ let done = assert.async(NUM_TESTS);
+ let old_dnt_check_func = badger.isCheckingDNTPolicyEnabled;
+
+ assert.expect(NUM_TESTS);
+ badger.isCheckingDNTPolicyEnabled = () => false;
+
+ for (let i = 0; i < NUM_TESTS; i++) {
+ badger.checkForDNTPolicy(DNT_DOMAINS[i]);
+ clock.tick(constants.DNT_POLICY_CHECK_INTERVAL);
+ assert.equal(xhrSpy.callCount, 0);
+ done();
+ }
+
+ badger.isCheckingDNTPolicyEnabled = old_dnt_check_func;
+});
+
+// test #1972
+QUnit.test("mergeUserData does not unblock formerly blocked domains", (assert) => {
+ setupBadgerStorage(badger);
+
+ const SITE_DOMAINS = ['a.co', 'b.co', 'c.co'],
+ USER_DATA = {
+ action_map: {
+ 'foo.com': {
+ dnt: false,
+ heuristicAction: constants.BLOCK,
+ nextUpdateTime: 100,
+ userAction: ""
+ }
+ },
+ snitch_map: {
+ 'foo.com': SITE_DOMAINS
+ },
+ settings_map: {
+ migrationLevel: 0
+ }
+ };
+
+ badger.mergeUserData(USER_DATA);
+
+ assert.equal(
+ badger.storage.action_map.getItem('foo.com').heuristicAction,
+ constants.BLOCK,
+ "foo.com was blocked"
+ );
+ assert.deepEqual(
+ badger.storage.snitch_map.getItem('foo.com'),
+ SITE_DOMAINS,
+ "snitch map was migrated"
+ );
+
+ badger.runMigrations();
+
+ assert.equal(
+ badger.storage.action_map.getItem('foo.com').heuristicAction,
+ constants.BLOCK,
+ "foo.com is still blocked after running migrations"
+ );
+});
+
+QUnit.test("user-blocked domains keep their tracking history", (assert) => {
+ const SITE_DOMAINS = ['a.co', 'b.co'],
+ USER_DATA = {
+ action_map: {
+ 'foo.com': {
+ dnt: false,
+ heuristicAction: constants.ALLOW,
+ nextUpdateTime: 100,
+ userAction: constants.USER_BLOCK
+ }
+ },
+ snitch_map: {
+ 'foo.com': SITE_DOMAINS
+ }
+ };
+
+ badger.mergeUserData(USER_DATA);
+
+ assert.equal(
+ badger.storage.getAction('foo.com'),
+ constants.USER_BLOCK,
+ "foo.com was blocked"
+ );
+ assert.deepEqual(
+ badger.storage.snitch_map.getItem('foo.com'),
+ SITE_DOMAINS,
+ "snitch map was migrated"
+ );
+});
+
+QUnit.test("merging snitch maps results in a blocked domain", (assert) => {
+ setupBadgerStorage(badger);
+
+ // https://github.com/EFForg/privacybadger/pull/2082#issuecomment-401942070
+ const USER_DATA = {
+ action_map: {
+ 'foo.com': {
+ dnt: false,
+ heuristicAction: constants.ALLOW,
+ nextUpdateTime: 100,
+ userAction: ""
+ }
+ },
+ snitch_map: {'foo.com': ['b.co', 'c.co']},
+ };
+
+ badger.mergeUserData(USER_DATA);
+
+ assert.equal(
+ badger.storage.action_map.getItem('foo.com').heuristicAction,
+ constants.BLOCK,
+ "foo.com was blocked"
+ );
+ assert.deepEqual(
+ badger.storage.snitch_map.getItem('foo.com'),
+ ['a.co', 'b.co', 'c.co'],
+ "snitch map was combined"
+ );
+});
+
+QUnit.test("subdomain that is not blocked does not override subdomain that is", (assert) => {
+ setupBadgerStorage(badger);
+
+ const USER_DATA = {
+ action_map: {
+ 'sub.bar.com': {
+ dnt: false,
+ heuristicAction: constants.ALLOW,
+ nextUpdateTime: 100,
+ userAction: ""
+ }
+ },
+ snitch_map: {'bar.com': ['a.co']}
+ };
+
+ badger.mergeUserData(USER_DATA);
+
+ assert.equal(
+ badger.storage.action_map.getItem('sub.bar.com').heuristicAction,
+ constants.BLOCK,
+ "sub.bar.com is still blocked"
+ );
+ assert.deepEqual(
+ badger.storage.snitch_map.getItem('bar.com'),
+ ['a.co', 'b.co', 'c.co'],
+ "snitch map was preserved"
+ );
+});
+
+QUnit.test("subdomains on the yellowlist are preserved", (assert) => {
+ const DOMAIN = "example.com",
+ SUBDOMAIN = "cdn.example.com",
+ USER_DATA = {
+ action_map: {
+ [DOMAIN]: {
+ dnt: false,
+ heuristicAction: constants.BLOCK,
+ nextUpdateTime: 100,
+ userAction: ''
+ },
+ [SUBDOMAIN]: {
+ dnt: false,
+ heuristicAction: constants.ALLOW,
+ nextUpdateTime: 0,
+ userAction: ''
+ }
+ },
+ snitch_map: {
+ [DOMAIN]: ['a.co', 'b.co', 'c.co'],
+ }
+ };
+
+ const actionMap = badger.storage.getStore('action_map'),
+ snitchMap = badger.storage.getStore('snitch_map');
+
+ // merge in a blocked parent domain and a subdomain
+ badger.mergeUserData(USER_DATA);
+
+ assert.notOk(actionMap.getItem(SUBDOMAIN),
+ SUBDOMAIN + " should have been discarded during merge"
+ );
+
+ // clean up
+ actionMap.deleteItem(DOMAIN);
+ actionMap.deleteItem(SUBDOMAIN);
+ snitchMap.deleteItem(DOMAIN);
+
+ // now add subdomain to yellowlist
+ badger.storage.getStore('cookieblock_list')
+ .setItem(SUBDOMAIN, true);
+
+ // and do the merge again
+ badger.mergeUserData(USER_DATA);
+
+ assert.ok(actionMap.getItem(SUBDOMAIN),
+ SUBDOMAIN + " should be present in action_map"
+ );
+ assert.equal(
+ actionMap.getItem(SUBDOMAIN).heuristicAction,
+ constants.COOKIEBLOCK,
+ SUBDOMAIN + " should be cookieblocked"
+ );
+});
+
+QUnit.test("forgetFirstPartySnitches migration properly handles snitch entries with no MDFP entries", (assert) => {
+ const actionMap = badger.storage.getStore('action_map'),
+ snitchMap = badger.storage.getStore('snitch_map');
+
+ let snitchNoMDFP = {
+ 'amazon.com': ['amazonads.com', 'amazing.com', 'amazonrainforest.com']
+ };
+
+ let actionNoMDFP = {
+ 'amazon.com': {
+ heuristicAction: "cookieblock",
+ userAction: "",
+ dnt: false,
+ nextUpdateTime: 0,
+ }
+ };
+
+ snitchMap.updateObject(snitchNoMDFP);
+ actionMap.updateObject(actionNoMDFP);
+ migrations.forgetFirstPartySnitches(badger);
+
+ assert.deepEqual(
+ actionMap.getItem('amazon.com'),
+ actionNoMDFP['amazon.com'],
+ "action map preserved for domain with no MDFP snitch entries"
+ );
+
+ assert.deepEqual(
+ snitchMap.getItem('amazon.com'),
+ snitchNoMDFP['amazon.com'],
+ "snitch map entry with no MDFP domains remains the same after migration runs"
+ );
+});
+
+QUnit.test("forgetFirstPartySnitches migration properly handles snitch entries with some MDFP entries", (assert) => {
+ const actionMap = badger.storage.getStore('action_map'),
+ snitchMap = badger.storage.getStore('snitch_map');
+
+ let snitchSomeMDFP = {
+ 'amazon.com': ['amazon.ca', 'amazon.co.jp', 'amazing.com']
+ };
+
+ let actionSomeMDFP = {
+ 'amazon.com': {
+ heuristicAction: "cookieblock",
+ userAction: "",
+ dnt: false,
+ nextUpdateTime: 0,
+ }
+ };
+
+ snitchMap.updateObject(snitchSomeMDFP);
+ actionMap.updateObject(actionSomeMDFP);
+ migrations.forgetFirstPartySnitches(badger);
+
+ assert.equal(
+ badger.storage.getAction('amazon.com'),
+ constants.ALLOW,
+ "Action downgraded for partial MDFP domain"
+ );
+
+ assert.deepEqual(snitchMap.getItem('amazon.com'),
+ ["amazing.com"],
+ 'forget first party migration properly removes MDFP domains and leaves regular domains');
+});
+
+QUnit.test("forgetFirstPartySnitches migration properly handles snitch entries with all MDFP entries", (assert) => {
+ const actionMap = badger.storage.getStore('action_map'),
+ snitchMap = badger.storage.getStore('snitch_map');
+
+ let snitchAllMDFP = {
+ 'amazon.com': ['amazon.ca', 'amazon.co.jp', 'amazon.es']
+ };
+
+ let actionAllMDFP = {
+ 'amazon.com': {
+ heuristicAction: "cookieblock",
+ userAction: "",
+ dnt: false,
+ nextUpdateTime: 0,
+ }
+ };
+
+ // confirm all entries are MDFP
+ snitchAllMDFP["amazon.com"].forEach((domain) => {
+ assert.ok(
+ mdfp.isMultiDomainFirstParty('amazon.com', domain),
+ domain + " is indeed MDFP to amazon.com"
+ );
+ });
+
+ snitchMap.updateObject(snitchAllMDFP);
+ actionMap.updateObject(actionAllMDFP);
+ migrations.forgetFirstPartySnitches(badger);
+
+ assert.notOk(snitchMap.getItem('amazon.com'),
+ 'forget first party migration properly removes a snitch map entry with all MDFP domains attributed to it');
+
+ assert.equal(
+ badger.storage.getAction('amazon.com'),
+ constants.NO_TRACKING,
+ "Action downgraded for all MDFP domain"
+ );
+});
+
+}());