1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import unittest
import pbtest
from time import sleep
from selenium.common.exceptions import (
NoSuchElementException,
StaleElementReferenceException,
TimeoutException
)
from selenium.webdriver.common.keys import Keys
class WidgetsTest(pbtest.PBSeleniumTest):
FIXTURES_URL = "https://efforg.github.io/privacybadger-test-fixtures/html/"
BASIC_FIXTURE_URL = FIXTURES_URL + "widget_basic.html"
DYNAMIC_FIXTURE_URL = FIXTURES_URL + "widget_dynamic.html"
THIRD_PARTY_DOMAIN = "privacybadger-tests.eff.org"
TYPE3_WIDGET_NAME = "Type 3 Widget"
TYPE4_WIDGET_NAME = "Type 4 Widget"
TYPE4_WIDGET_CLASS = "pb-type4-test-widget"
def setUp(self):
self.set_up_widgets()
def set_up_widgets(self):
"""Reinitializes Privacy Badger's widget replacement definitions."""
widgetsJson = {
self.TYPE3_WIDGET_NAME: {
"domain": self.THIRD_PARTY_DOMAIN,
"buttonSelectors": [
"iframe#pb-type3-test-widget"
],
"replacementButton": {
"unblockDomains": [
self.THIRD_PARTY_DOMAIN
],
"type": 3
}
},
self.TYPE4_WIDGET_NAME: {
"domains": [
self.THIRD_PARTY_DOMAIN
],
"buttonSelectors": [
"div." + self.TYPE4_WIDGET_CLASS
],
"scriptSelectors": [
"script." + self.TYPE4_WIDGET_CLASS
],
"replacementButton": {
"unblockDomains": [
self.THIRD_PARTY_DOMAIN
],
"type": 4
}
}
}
# reinitialize widgets using above JSON
self.load_url(self.options_url)
self.js((
"(function (widgetsJson) {"
" let bg = chrome.extension.getBackgroundPage();"
" bg.badger.widgetList = bg.widgetLoader.initializeWidgets(widgetsJson);"
"}(arguments[0]));"
), widgetsJson)
def switch_to_frame(self, selector):
self.wait_for_and_switch_to_frame(selector, timeout=1)
def assert_widget(self, kind="type3"):
if kind == "type3":
self._assert_type3_widget()
elif kind == "type4":
self._assert_type4_widget()
else:
self.fail("Unknown widget type")
def _assert_type3_widget(self):
try:
self.switch_to_frame('iframe[src]')
except (StaleElementReferenceException, TimeoutException):
self.fail("Unable to find widget frame")
try:
self.wait_for_text('body', "Hello world!")
except TimeoutException:
self.fail("Unable to find expected widget text")
self.driver.switch_to.default_content()
def _assert_type4_widget(self):
try:
self.wait_for_text('div.' + self.TYPE4_WIDGET_CLASS,
"A third-party widget script was here")
except TimeoutException:
self.fail("Unable to find expected widget output")
def assert_replacement(self, widget_name=None):
if not widget_name:
widget_name = self.TYPE3_WIDGET_NAME
try:
self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
except (StaleElementReferenceException, TimeoutException):
self.fail("Unable to find widget placeholder frame")
try:
self.find_el_by_css("button[id^='btn-once-']")
self.find_el_by_css("button[id^='btn-site-']")
except TimeoutException:
self.fail("Unable to find expected widget placeholder buttons")
self.driver.switch_to.default_content()
def assert_widget_blocked(self):
try:
self.switch_to_frame('iframe[src]')
except TimeoutException:
self.fail("Widget frame should still be here")
self.assertFalse(
self.txt_by_css('body'), "Widget frame should be empty")
self.driver.switch_to.default_content()
def assert_no_widget(self):
try:
self.switch_to_frame('iframe[src]')
self.fail("Widget frame should be missing")
except TimeoutException:
pass
self.driver.switch_to.default_content()
def assert_no_replacement(self, widget_name=None):
if not widget_name:
widget_name = self.TYPE3_WIDGET_NAME
try:
self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
self.fail("Widget placeholder frame should be missing")
except TimeoutException:
pass
self.driver.switch_to.default_content()
def activate_widget(self, widget_name=None, once=True):
if not widget_name:
widget_name = self.TYPE3_WIDGET_NAME
id_prefix = 'btn-once' if once else 'btn-site'
self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
self.find_el_by_css("button[id^='%s']" % id_prefix).click()
self.driver.switch_to.default_content()
def test_replacement_basic(self):
# visit the basic widget fixture
self.load_url(self.BASIC_FIXTURE_URL)
# verify the widget is present
self.assert_widget()
# block the test widget's domain
self.block_domain(self.THIRD_PARTY_DOMAIN)
# revisit the fixture
self.load_url(self.BASIC_FIXTURE_URL)
# verify the widget got replaced
self.assert_replacement()
def test_replacement_dynamic(self):
# visit the dynamic widget fixture
self.load_url(self.DYNAMIC_FIXTURE_URL)
# verify the widget is initially missing
self.assert_no_widget()
# verify the widget shows up once you click on the trigger element
self.find_el_by_css('#widget-trigger').click()
self.assert_widget()
# block the test widget's domain
self.block_domain(self.THIRD_PARTY_DOMAIN)
# revisit the fixture
self.load_url(self.DYNAMIC_FIXTURE_URL)
# click on the trigger element
self.find_el_by_css('#widget-trigger').click()
# verify the widget got replaced
self.assert_replacement()
def test_activation(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_replacement()
# click the "allow once" button
self.activate_widget()
# verify the original widget is restored
self.assert_widget()
# verify the type 4 widget is still replaced
try:
self.driver.find_element_by_css_selector(
'div.' + self.TYPE4_WIDGET_CLASS)
self.fail("Widget output container div should be missing")
except NoSuchElementException:
pass
self.assert_replacement(self.TYPE4_WIDGET_NAME)
self.activate_widget(self.TYPE4_WIDGET_NAME)
# assert all script attributes were copied
script_el = self.driver.find_element_by_css_selector(
'script.' + self.TYPE4_WIDGET_CLASS)
self.assertEqual(script_el.get_attribute('async'), "true")
self.assertEqual(script_el.get_attribute('data-foo'), "bar")
self.assert_widget("type4")
def test_activation_site(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_replacement()
# click the "allow once" button
self.activate_widget()
# verify the original widget is restored
self.assert_widget()
# open a new window (to get around widget activation caching)
self.open_window()
self.load_url(self.BASIC_FIXTURE_URL)
# verify the widget got replaced
self.assert_replacement()
# click the "allow on site" button
self.activate_widget(once=False)
# verify the original widget is restored
self.assert_widget()
# open a new window (to get around widget activation caching)
self.open_window()
self.load_url(self.BASIC_FIXTURE_URL)
# verify basic widget is neither replaced nor blocked
self.assert_no_replacement()
self.assert_widget()
def test_disabling_site(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)
self.disable_badger_on_site(self.BASIC_FIXTURE_URL)
# verify basic widget is neither replaced nor blocked
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_widget()
# type 4 replacement should also be missing
self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
# while the type 4 widget script should have executed
self.assert_widget("type4")
# verify dynamic widget is neither replaced nor blocked
self.load_url(self.DYNAMIC_FIXTURE_URL)
self.find_el_by_css('#widget-trigger').click()
self.assert_no_replacement()
self.assert_widget()
def test_disabling_all_replacement(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)
# disable widget replacement
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
self.driver.find_element_by_id('replace-widgets-checkbox').click()
# verify basic widget is no longer replaced
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_widget_blocked()
# type 4 replacement should also be missing
self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
# type 4 widget should also have gotten blocked
try:
widget_div = self.driver.find_element_by_css_selector(
'div.pb-type4-test-widget')
except NoSuchElementException:
self.fail("Widget div should still be here")
# check the div's text a few times to make sure it stays empty
for _ in range(3):
self.assertFalse(widget_div.text,
"Widget output container should remain empty")
sleep(1)
# verify dynamic widget is no longer replaced
self.load_url(self.DYNAMIC_FIXTURE_URL)
self.find_el_by_css('#widget-trigger').click()
self.assert_no_replacement()
self.assert_widget_blocked()
def test_disabling_replacement_for_one_widget(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)
# add the widget to the list of exceptions
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
self.find_el_by_css('input[type="search"]').send_keys(
self.TYPE3_WIDGET_NAME, Keys.ENTER)
# verify basic widget is no longer replaced
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_widget_blocked()
# verify the type 4 widget is still replaced
self.assert_replacement(self.TYPE4_WIDGET_NAME)
# verify dynamic widget is no longer replaced
self.load_url(self.DYNAMIC_FIXTURE_URL)
self.find_el_by_css('#widget-trigger').click()
self.assert_no_replacement()
self.assert_widget_blocked()
def test_no_replacement_when_cookieblocked(self):
self.cookieblock_domain(self.THIRD_PARTY_DOMAIN)
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
self.assert_widget()
self.assert_widget("type4")
if __name__ == "__main__":
unittest.main()
|