Skip to content

Commit 289872f

Browse files
authored
Refactor TDS list loading (duckduckgo#2309)
* Refactor TDS Storage Move trackers global initialization to component Re-add getSerializableList to tdsStorage (for devtools) Remove global updateLists alarm - these are now handled by individual resource loaders Implement onUpdate and stub it out in tdsStorage Fix stubs for unit-tests Comments Fix lint Move resources into a single tds component Make sure trackers update whenever tds changes Allow tests to mock tdsStorage Properly type tdsstorage Fix return of getSerializableList Fix devtools Fix some flaky MV3 tests More MV3 test fixes Tidy up Resource-loader unit-tests Fix merge * Update component types * Log load date on startup - for better debugging SW restarts * Use createAlarm wrapper * Use EventTarget on ResourceLoader for event dispatch * Move forDynamicDNRRulesLoaded helper to backgroundWait * afterUpdate event: emitted when the promises from all onUpdate listeners have resolved. * Add comments and types for ready and allLoadingFinished promises.
1 parent 09f8b35 commit 289872f

File tree

15 files changed

+582
-418
lines changed

15 files changed

+582
-418
lines changed

integration-test/data/staticcdn/trackerblocking/config/v4/extension-chromemv3-config.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6854,5 +6854,12 @@
68546854
"hash": "728493ef7a1488e4781656d3f9db84aa"
68556855
}
68566856
},
6857-
"unprotectedTemporary": []
6857+
"unprotectedTemporary": [
6858+
{
6859+
"domain": "localhost"
6860+
},
6861+
{
6862+
"domain": "127.0.0.1"
6863+
}
6864+
]
68586865
}

integration-test/helpers/backgroundWait.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,20 @@ export async function forExtensionLoaded (context) {
8989
}))
9090
}
9191

92+
export async function forDynamicDNRRulesLoaded (backgroundPage) {
93+
// The 'allLoadingFinished' promise on a ResourceLoader signifies that the resource was loaded
94+
// at least once, and all subscribed listeners received and processed that resource.
95+
await backgroundPage.evaluate(async () => {
96+
await Promise.all([
97+
globalThis.components.tds.config.allLoadingFinished,
98+
globalThis.components.tds.tds.allLoadingFinished
99+
])
100+
})
101+
}
102+
92103
export default {
93104
forSetting,
94105
forAllConfiguration,
95-
forExtensionLoaded
106+
forExtensionLoaded,
107+
forDynamicDNRRulesLoaded
96108
}

integration-test/request-blocking.spec.js

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test, expect } from './helpers/playwrightHarness'
2-
import { forAllConfiguration, forExtensionLoaded } from './helpers/backgroundWait'
2+
import { forAllConfiguration, forExtensionLoaded, forDynamicDNRRulesLoaded } from './helpers/backgroundWait'
33
import { overridePrivacyConfig } from './helpers/testConfig'
44
import { TEST_SERVER_ORIGIN } from './helpers/testPages'
55

@@ -43,10 +43,13 @@ async function runRequestBlockingTest (page, url = testSite) {
4343
}
4444

4545
test.describe('Test request blocking', () => {
46-
test('Should block all the test tracking requests', async ({ page, backgroundPage, context, backgroundNetworkContext }) => {
46+
test('Should block all the test tracking requests', async ({ page, backgroundPage, context, backgroundNetworkContext, manifestVersion }) => {
4747
await overridePrivacyConfig(backgroundNetworkContext, 'serviceworker-blocking.json')
4848
await forExtensionLoaded(context)
4949
await forAllConfiguration(backgroundPage)
50+
if (manifestVersion === 3) {
51+
await forDynamicDNRRulesLoaded(backgroundPage)
52+
}
5053
const [testCount, pageRequests] = await runRequestBlockingTest(page)
5154

5255
// Verify that no logged requests were allowed.
@@ -97,20 +100,22 @@ test.describe('Test request blocking', () => {
97100
await page.close()
98101
})
99102

100-
test('serviceworkerInitiatedRequests exceptions should disable service worker blocking', async ({ page, backgroundPage, context, backgroundNetworkContext }) => {
103+
test('serviceworkerInitiatedRequests exceptions should disable service worker blocking', async ({ page, backgroundPage, context, backgroundNetworkContext, manifestVersion }) => {
101104
await overridePrivacyConfig(backgroundNetworkContext, 'serviceworker-blocking.json')
102105
await forExtensionLoaded(context)
103106
await forAllConfiguration(backgroundPage)
107+
if (manifestVersion === 3) {
108+
await forDynamicDNRRulesLoaded(backgroundPage)
109+
}
104110
await backgroundPage.evaluate(async (domain) => {
105-
/* global dbg */
106-
const { data: config } = dbg.getListContents('config')
107-
config.features.serviceworkerInitiatedRequests.exceptions.push({
108-
domain,
109-
reason: 'test'
110-
})
111-
await dbg.setListContents({
112-
name: 'config',
113-
value: config
111+
/** @type {import('../shared/js/background/components/resource-loader').default} */
112+
const configLoader = globalThis.components.tds.config
113+
await configLoader.modify((config) => {
114+
config.features.serviceworkerInitiatedRequests.exceptions.push({
115+
domain,
116+
reason: 'test'
117+
})
118+
return config
114119
})
115120
}, testHost)
116121
const [, pageRequests] = await runRequestBlockingTest(page)
@@ -151,6 +156,7 @@ test.describe('Test request blocking', () => {
151156
if (localhostRules.length > 0) {
152157
break
153158
}
159+
await new Promise(resolve => setTimeout(resolve, 100))
154160
}
155161
}
156162

@@ -173,6 +179,9 @@ test.describe('Test request blocking', () => {
173179
await overridePrivacyConfig(backgroundNetworkContext, 'serviceworker-blocking.json')
174180
await forExtensionLoaded(context)
175181
await forAllConfiguration(backgroundPage)
182+
if (manifestVersion === 3) {
183+
await forDynamicDNRRulesLoaded(backgroundPage)
184+
}
176185

177186
// load with protection enabled
178187
await runRequestBlockingTest(page)
@@ -187,6 +196,7 @@ test.describe('Test request blocking', () => {
187196

188197
// disable protection on the page and rerun the test
189198
await backgroundPage.evaluate(async (domain) => {
199+
/* global dbg */
190200
dbg.tabManager.setList({ list: 'allowlisted', domain, value: true })
191201
}, testHost)
192202
await runRequestBlockingTest(page)

integration-test/storage-blocking.spec.js

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,14 @@ test.describe('Storage blocking Tests', () => {
138138

139139
test('excludedCookieDomains disables cookie blocking for that domain', async ({ page, backgroundPage }) => {
140140
await backgroundPage.evaluate(async (domain) => {
141-
const { data: config } = dbg.getListContents('config')
142-
config.features.cookie.settings.excludedCookieDomains.push({
143-
domain,
144-
reason: 'test'
145-
})
146-
await dbg.setListContents({
147-
name: 'config',
148-
value: config
141+
/** @type {import('../shared/js/background/components/resource-loader').default} */
142+
const configLoader = globalThis.components.tds.config
143+
await configLoader.modify((config) => {
144+
config.features.cookie.settings.excludedCookieDomains.push({
145+
domain,
146+
reason: 'test'
147+
})
148+
return config
149149
})
150150
}, thirdPartyTracker)
151151
const results = await runStorageTest(page, `https://${testPageDomain}`)
@@ -154,14 +154,14 @@ test.describe('Storage blocking Tests', () => {
154154

155155
test('feature exception disables all cookie blocking for the site', async ({ page, backgroundPage }) => {
156156
await backgroundPage.evaluate(async (domain) => {
157-
const { data: config } = dbg.getListContents('config')
158-
config.features.cookie.exceptions.push({
159-
domain,
160-
reason: 'test'
161-
})
162-
await dbg.setListContents({
163-
name: 'config',
164-
value: config
157+
/** @type {import('../shared/js/background/components/resource-loader').default} */
158+
const configLoader = globalThis.components.tds.config
159+
await configLoader.modify((config) => {
160+
config.features.cookie.exceptions.push({
161+
domain,
162+
reason: 'test'
163+
})
164+
return config
165165
})
166166
}, testPageDomain)
167167
const results = await runStorageTest(page, `https://${testPageDomain}`)
@@ -170,14 +170,14 @@ test.describe('Storage blocking Tests', () => {
170170

171171
test('unprotected temporary disables all cookie blocking for the site', async ({ page, backgroundPage }) => {
172172
await backgroundPage.evaluate(async (domain) => {
173-
const { data: config } = dbg.getListContents('config')
174-
config.unprotectedTemporary.push({
175-
domain,
176-
reason: 'test'
177-
})
178-
await dbg.setListContents({
179-
name: 'config',
180-
value: config
173+
/** @type {import('../shared/js/background/components/resource-loader').default} */
174+
const configLoader = globalThis.components.tds.config
175+
await configLoader.modify((config) => {
176+
config.unprotectedTemporary.push({
177+
domain,
178+
reason: 'test'
179+
})
180+
return config
181181
})
182182
}, testPageDomain)
183183
const results = await runStorageTest(page, `https://${testPageDomain}`)
@@ -191,14 +191,14 @@ test.describe('Storage blocking Tests', () => {
191191
domain,
192192
value: true
193193
})
194-
const { data: config } = dbg.getListContents('config')
195-
config.unprotectedTemporary.push({
196-
domain,
197-
reason: 'test'
198-
})
199-
await dbg.setListContents({
200-
name: 'config',
201-
value: config
194+
/** @type {import('../shared/js/background/components/resource-loader').default} */
195+
const configLoader = globalThis.components.tds.config
196+
await configLoader.modify((config) => {
197+
config.unprotectedTemporary.push({
198+
domain,
199+
reason: 'test'
200+
})
201+
return config
202202
})
203203
}, testPageDomain)
204204
// await page.waitForTimeout(500)

shared/js/background/background.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import MV3ContentScriptInjection from './components/mv3-content-script-injection
2222
import EmailAutofill from './components/email-autofill'
2323
import OmniboxSearch from './components/omnibox-search'
2424
import InternalUserDetector from './components/internal-user-detector'
25+
import TDSStorage from './components/tds'
26+
import TrackersGlobal from './components/trackers'
2527
import initDebugBuild from './devbuild'
2628
import initReloader from './devbuild-reloader'
2729
import tabManager from './tab-manager'
@@ -37,16 +39,25 @@ settings.ready().then(() => {
3739
onStartup()
3840
})
3941

42+
const tds = new TDSStorage({ settings })
4043
/**
4144
* @type {{
45+
* autofill: EmailAutofill;
46+
* omnibox: OmniboxSearch;
4247
* fireButton?: FireButton;
48+
* internalUser: InternalUserDetector;
49+
* tds: TDSStorage;
50+
* tabTracking: TabTracker;
51+
* trackers: TrackersGlobal;
4352
* }}
4453
*/
4554
const components = {
46-
tabTracking: new TabTracker({ tabManager }),
4755
autofill: new EmailAutofill({ settings }),
4856
omnibox: new OmniboxSearch(),
49-
internalUser: new InternalUserDetector({ settings })
57+
internalUser: new InternalUserDetector({ settings }),
58+
tabTracking: new TabTracker({ tabManager }),
59+
tds,
60+
trackers: new TrackersGlobal({ tds })
5061
}
5162

5263
// Chrome-only components
@@ -57,7 +68,7 @@ if (BUILD_TARGET === 'chrome' || BUILD_TARGET === 'chrome-mv3') {
5768
if (BUILD_TARGET === 'chrome-mv3') {
5869
components.scriptInjection = new MV3ContentScriptInjection()
5970
}
60-
console.log('Loaded components:', components)
71+
console.log(new Date(), 'Loaded components:', components)
6172
// @ts-ignore
6273
self.components = components
6374

0 commit comments

Comments
 (0)