1
0
Fork 0
privacybadger/tests/selenium/dnt_test.py
Daniel Baumann 51333c7ef4
Adding upstream version 2020.10.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 23:00:13 +02:00

324 lines
12 KiB
Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import json
import unittest
import pbtest
from functools import partial
from selenium.common.exceptions import NoSuchElementException
from pbtest import retry_until
class DntTest(pbtest.PBSeleniumTest):
"""Tests to make sure DNT policy checking works as expected."""
CHECK_FOR_DNT_POLICY_JS = (
"chrome.extension.getBackgroundPage()."
"badger.checkForDNTPolicy("
" arguments[0],"
" r => window.DNT_CHECK_RESULT = r"
");"
)
# TODO switch to non-delayed version
# https://gist.github.com/ghostwords/9fc6900566a2f93edd8e4a1e48bbaa28
# once race condition (https://crbug.com/478183) is fixed
NAVIGATOR_DNT_TEST_URL = (
"https://efforg.github.io/privacybadger-test-fixtures/html/"
"navigator_donottrack_delayed.html"
)
def get_first_party_headers(self, url):
self.load_url(url)
text = self.driver.find_element_by_tag_name('body').text
try:
headers = json.loads(text)['headers']
except ValueError:
print("\nFailed to parse JSON from {}".format(repr(text)))
return None
return headers
def domain_was_recorded(self, domain):
return self.js(
"return (Object.keys("
" chrome.extension.getBackgroundPage()."
" badger.storage.action_map.getItemClones()"
").indexOf(arguments[0]) != -1);",
domain
)
def domain_was_detected(self, domain):
return self.js(
"return (Object.keys(chrome.extension.getBackgroundPage().badger.tabData).some(tab_id => {"
" let origins = chrome.extension.getBackgroundPage().badger.tabData[tab_id].origins;"
" return origins.hasOwnProperty(arguments[0]);"
"}));",
domain
)
def domain_was_blocked(self, domain):
return self.js(
"return (Object.keys(chrome.extension.getBackgroundPage().badger.tabData).some(tab_id => {"
" let origins = chrome.extension.getBackgroundPage().badger.tabData[tab_id].origins;"
" return ("
" origins.hasOwnProperty(arguments[0]) &&"
" chrome.extension.getBackgroundPage().constants.BLOCKED_ACTIONS.has(origins[arguments[0]])"
" );"
"}));",
domain
)
@pbtest.repeat_if_failed(3)
def test_dnt_policy_check_should_happen_for_blocked_domains(self):
PAGE_URL = (
"https://efforg.github.io/privacybadger-test-fixtures/html/"
"dnt.html"
)
DNT_DOMAIN = "www.eff.org"
# mark a DNT-compliant domain for blocking
self.block_domain(DNT_DOMAIN)
# visit a page that loads a resource from that DNT-compliant domain
self.open_window()
self.load_url(PAGE_URL)
# switch back to Badger's options page
self.switch_to_window_with_url(self.options_url)
# verify that the domain is blocked
self.assertTrue(self.domain_was_detected(DNT_DOMAIN),
msg="Domain should have been detected.")
self.assertTrue(self.domain_was_blocked(DNT_DOMAIN),
msg="DNT-compliant resource should have been blocked at first.")
def reload_and_see_if_unblocked():
# switch back to the page with the DNT-compliant resource
self.switch_to_window_with_url(PAGE_URL)
# reload it
self.load_url(PAGE_URL)
# switch back to Badger's options page
self.switch_to_window_with_url(self.options_url)
return (
self.domain_was_detected(DNT_DOMAIN) and
self.domain_was_blocked(DNT_DOMAIN)
)
# verify that the domain is allowed
was_blocked = retry_until(
reload_and_see_if_unblocked,
tester=lambda x: not x,
msg="Waiting a bit for DNT check to complete and retrying ...")
self.assertFalse(was_blocked,
msg="DNT-compliant resource should have gotten unblocked.")
def test_dnt_policy_check_should_not_set_cookies(self):
TEST_DOMAIN = "dnt-test.trackersimulator.org"
TEST_URL = "https://{}/".format(TEST_DOMAIN)
# verify that the domain itself doesn't set cookies
self.load_url(TEST_URL)
self.assertEqual(len(self.driver.get_cookies()), 0,
"No cookies initially")
# directly visit a DNT policy URL known to set cookies
self.load_url(TEST_URL + ".well-known/dnt-policy.txt")
self.assertEqual(len(self.driver.get_cookies()), 1,
"DNT policy URL set a cookie")
# verify we got a cookie
self.load_url(TEST_URL)
self.assertEqual(len(self.driver.get_cookies()), 1,
"We still have just one cookie")
# clear cookies and verify
self.driver.delete_all_cookies()
self.load_url(TEST_URL)
self.assertEqual(len(self.driver.get_cookies()), 0,
"No cookies again")
self.load_url(self.options_url)
# perform a DNT policy check
self.js(DntTest.CHECK_FOR_DNT_POLICY_JS, TEST_DOMAIN)
# wait until checkForDNTPolicy completed
self.wait_for_script("return window.DNT_CHECK_RESULT === false")
# check that we didn't get cookied by the DNT URL
self.load_url(TEST_URL)
self.assertEqual(len(self.driver.get_cookies()), 0,
"Shouldn't have any cookies after the DNT check")
def test_dnt_policy_check_should_not_send_cookies(self):
TEST_DOMAIN = "dnt-request-cookies-test.trackersimulator.org"
TEST_URL = "https://{}/".format(TEST_DOMAIN)
# directly visit a DNT policy URL known to set cookies
self.load_url(TEST_URL + ".well-known/dnt-policy.txt")
self.assertEqual(len(self.driver.get_cookies()), 1,
"DNT policy URL set a cookie")
# how to check we didn't send a cookie along with request?
# the DNT policy URL used by this test returns "cookies=X"
# where X is the number of cookies it got
# MEGAHACK: make sha1 of "cookies=0" a valid DNT hash
self.load_url(self.options_url)
self.js(
"chrome.extension.getBackgroundPage()."
"badger.storage.updateDntHashes({"
" 'cookies=0 test policy': 'f63ee614ebd77f8634b92633c6bb809a64b9a3d7'"
"});"
)
# perform a DNT policy check
self.js(DntTest.CHECK_FOR_DNT_POLICY_JS, TEST_DOMAIN)
# wait until checkForDNTPolicy completed
self.wait_for_script("return typeof window.DNT_CHECK_RESULT != 'undefined';")
# get the result
result = self.js("return window.DNT_CHECK_RESULT;")
self.assertTrue(result, "No cookies were sent")
def test_should_not_record_nontracking_domains(self):
FIXTURE_URL = (
"https://efforg.github.io/privacybadger-test-fixtures/html/"
"recording_nontracking_domains.html"
)
TRACKING_DOMAIN = "dnt-request-cookies-test.trackersimulator.org"
NON_TRACKING_DOMAIN = "www.eff.org"
# clear pre-trained/seed tracker data
self.load_url(self.options_url)
self.js("chrome.extension.getBackgroundPage().badger.storage.clearTrackerData();")
# enable local learning
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('#local-learning-checkbox').click()
# visit a page containing two third-party resources,
# one from a cookie-tracking domain
# and one from a non-tracking domain
self.load_url(FIXTURE_URL)
# verify both domains are present on the page
try:
selector = "iframe[src*='%s']" % TRACKING_DOMAIN
self.driver.find_element_by_css_selector(selector)
except NoSuchElementException:
self.fail("Unable to find the tracking domain on the page")
try:
selector = "img[src*='%s']" % NON_TRACKING_DOMAIN
self.driver.find_element_by_css_selector(selector)
except NoSuchElementException:
self.fail("Unable to find the non-tracking domain on the page")
self.load_url(self.options_url)
# verify that the cookie-tracking domain was recorded
self.assertTrue(
self.domain_was_recorded(TRACKING_DOMAIN),
"Tracking domain should have gotten recorded"
)
# verify that the non-tracking domain was not recorded
self.assertFalse(
self.domain_was_recorded(NON_TRACKING_DOMAIN),
"Non-tracking domain should not have gotten recorded"
)
def test_first_party_dnt_header(self):
TEST_URL = "https://httpbin.org/get"
headers = retry_until(partial(self.get_first_party_headers, TEST_URL),
times=8)
self.assertTrue(headers is not None, "It seems we failed to get headers")
self.assertIn('Dnt', headers, "DNT header should have been present")
self.assertIn('Sec-Gpc', headers, "GPC header should have been present")
self.assertEqual(headers['Dnt'], "1",
'DNT header should have been set to "1"')
self.assertEqual(headers['Sec-Gpc'], "1",
'Sec-Gpc header should have been set to "1"')
def test_no_dnt_header_when_disabled_on_site(self):
TEST_URL = "https://httpbin.org/get"
self.disable_badger_on_site(TEST_URL)
headers = retry_until(partial(self.get_first_party_headers, TEST_URL),
times=8)
self.assertTrue(headers is not None, "It seems we failed to get headers")
self.assertNotIn('Dnt', headers, "DNT header should have been missing")
self.assertNotIn('Sec-Gpc', headers, "GPC header should have been missing")
def test_no_dnt_header_when_dnt_disabled(self):
TEST_URL = "https://httpbin.org/get"
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('#enable_dnt_checkbox').click()
headers = retry_until(partial(self.get_first_party_headers, TEST_URL),
times=8)
self.assertTrue(headers is not None, "It seems we failed to get headers")
self.assertNotIn('Dnt', headers, "DNT header should have been missing")
self.assertNotIn('Sec-Gpc', headers, "GPC header should have been missing")
def test_navigator_object(self):
self.load_url(DntTest.NAVIGATOR_DNT_TEST_URL, wait_for_body_text=True)
self.assertEqual(
self.driver.find_element_by_tag_name('body').text,
'no tracking (navigator.doNotTrack="1")',
"navigator.DoNotTrack should have been set to \"1\""
)
self.assertEqual(
self.js("return navigator.globalPrivacyControl"),
"1",
"navigator.globalPrivacyControl should have been set to \"1\""
)
def test_navigator_unmodified_when_disabled_on_site(self):
self.disable_badger_on_site(DntTest.NAVIGATOR_DNT_TEST_URL)
self.load_url(DntTest.NAVIGATOR_DNT_TEST_URL, wait_for_body_text=True)
# navigator.doNotTrack defaults to null in Chrome, "unspecified" in Firefox
self.assertEqual(
self.driver.find_element_by_tag_name('body').text[0:5],
'unset',
"navigator.DoNotTrack should have been left unset"
)
self.assertEqual(
self.js("return navigator.globalPrivacyControl"),
None,
"navigator.globalPrivacyControl should have been left unset"
)
def test_navigator_unmodified_when_dnt_disabled(self):
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('#enable_dnt_checkbox').click()
self.load_url(DntTest.NAVIGATOR_DNT_TEST_URL, wait_for_body_text=True)
# navigator.doNotTrack defaults to null in Chrome, "unspecified" in Firefox
self.assertEqual(
self.driver.find_element_by_tag_name('body').text[0:5],
'unset',
"navigator.DoNotTrack should have been left unset"
)
self.assertEqual(
self.js("return navigator.globalPrivacyControl"),
None,
"navigator.globalPrivacyControl should have been left unset"
)
if __name__ == "__main__":
unittest.main()