105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
import unittest
|
|
|
|
import pbtest
|
|
|
|
from functools import partial
|
|
|
|
from pbtest import retry_until
|
|
|
|
|
|
class FingerprintingTest(pbtest.PBSeleniumTest):
|
|
"""Tests to make sure fingerprinting detection works as expected."""
|
|
|
|
def detected_fingerprinting(self, domain):
|
|
return self.js("""let tracker_origin = window.getBaseDomain("{}");
|
|
let tabData = chrome.extension.getBackgroundPage().badger.tabData;
|
|
return (
|
|
Object.keys(tabData).some(tab_id => {{
|
|
let fpData = tabData[tab_id].fpData;
|
|
return fpData &&
|
|
fpData.hasOwnProperty(tracker_origin) &&
|
|
fpData[tracker_origin].canvas &&
|
|
fpData[tracker_origin].canvas.fingerprinting === true;
|
|
}})
|
|
);""".format(domain))
|
|
|
|
def detected_tracking(self, domain, page_url):
|
|
return self.js("""let tracker_origin = window.getBaseDomain("{}"),
|
|
site_origin = window.getBaseDomain((new URI("{}")).host),
|
|
map = chrome.extension.getBackgroundPage().badger.storage.snitch_map.getItemClones();
|
|
|
|
return (
|
|
map.hasOwnProperty(tracker_origin) &&
|
|
map[tracker_origin].indexOf(site_origin) != -1
|
|
);""".format(domain, page_url))
|
|
|
|
def get_fillText_source(self):
|
|
return self.js("""
|
|
const canvas = document.getElementById("writetome");
|
|
const ctx = canvas.getContext("2d");
|
|
return ctx.fillText.toString();
|
|
""")
|
|
|
|
def setUp(self):
|
|
# enable local learning
|
|
self.load_url(self.options_url)
|
|
self.wait_for_script("return window.OPTIONS_INITIALIZED")
|
|
self.find_el_by_css('#local-learning-checkbox').click()
|
|
|
|
# TODO can fail because our content script runs too late: https://crbug.com/478183
|
|
@pbtest.repeat_if_failed(3)
|
|
def test_canvas_fingerprinting_detection(self):
|
|
FIXTURE_URL = (
|
|
"https://efforg.github.io/privacybadger-test-fixtures/html/"
|
|
"fingerprinting.html"
|
|
)
|
|
FINGERPRINTING_DOMAIN = "cdn.jsdelivr.net"
|
|
|
|
# clear pre-trained/seed tracker data
|
|
self.load_url(self.options_url)
|
|
self.js("chrome.extension.getBackgroundPage().badger.storage.clearTrackerData();")
|
|
|
|
# visit the page
|
|
self.load_url(FIXTURE_URL)
|
|
|
|
# now open a new window (to avoid clearing badger.tabData)
|
|
# and verify results
|
|
self.open_window()
|
|
|
|
# check that we detected the fingerprinting domain as a tracker
|
|
self.load_url(self.options_url)
|
|
# TODO unnecessary retrying?
|
|
self.assertTrue(
|
|
retry_until(partial(self.detected_tracking, FINGERPRINTING_DOMAIN, FIXTURE_URL)),
|
|
"Canvas fingerprinting resource was detected as a tracker.")
|
|
|
|
# check that we detected canvas fingerprinting
|
|
self.assertTrue(
|
|
self.detected_fingerprinting(FINGERPRINTING_DOMAIN),
|
|
"Canvas fingerprinting resource was detected as a fingerprinter."
|
|
)
|
|
|
|
# Privacy Badger overrides a few functions on canvas contexts to check for fingerprinting.
|
|
# In previous versions, it would restore the native function after a single call. Unfortunately,
|
|
# this would wipe out polyfills that had also overridden the same functions, such as the very
|
|
# popular "hidpi-canvas-polyfill".
|
|
def test_canvas_polyfill_clobbering(self):
|
|
FIXTURE_URL = (
|
|
"https://efforg.github.io/privacybadger-test-fixtures/html/"
|
|
"fingerprinting_canvas_hidpi.html"
|
|
)
|
|
|
|
# visit the page
|
|
self.load_url(FIXTURE_URL)
|
|
|
|
# check that we did not restore the native function (should be hipdi polyfill)
|
|
self.assertNotIn("[native code]", self.get_fillText_source(),
|
|
"Canvas context fillText is not native version (polyfill has been retained)."
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|