@@ -6,6 +6,9 @@ import constants from '../../../data/constants';
6
6
* @typedef {import('./remote-config.js').default } RemoteConfig
7
7
*/
8
8
9
+ const TDS_OVERRIDE_SETTINGS_KEY = 'tdsOverride' ;
10
+ const CONTENT_BLOCKING = 'contentBlocking' ;
11
+
9
12
export default class TDSStorage {
10
13
/**
11
14
* @param {{
@@ -14,6 +17,7 @@ export default class TDSStorage {
14
17
* }} opts
15
18
*/
16
19
constructor ( { settings, remoteConfig } ) {
20
+ this . settings = settings ;
17
21
this . remoteConfig = remoteConfig ;
18
22
/** @deprecated config is an alias of remoteConfig */
19
23
this . config = this . remoteConfig ;
@@ -28,14 +32,52 @@ export default class TDSStorage {
28
32
this . tds = new ResourceLoader (
29
33
{
30
34
name : 'tds' ,
31
- remoteUrl : constants . tdsLists [ 1 ] . url ,
35
+ remoteUrl : this . getTDSUrl . bind ( this ) ,
32
36
updateIntervalMinutes : 15 ,
33
37
} ,
34
38
{ settings } ,
35
39
) ;
40
+ this . remoteConfig . onUpdate ( this . checkShouldOverrideTDS . bind ( this ) ) ;
36
41
}
37
42
38
43
ready ( ) {
39
44
return Promise . all ( [ this . tds . ready , this . surrogates . ready , this . remoteConfig . ready ] ) ;
40
45
}
46
+
47
+ async getTDSUrl ( ) {
48
+ await this . config . ready ;
49
+ const overridePath = this . settings . getSetting ( TDS_OVERRIDE_SETTINGS_KEY ) ;
50
+ if ( overridePath ) {
51
+ return `https://staticcdn.duckduckgo.com/trackerblocking/${ overridePath } ` ;
52
+ }
53
+ return constants . tdsLists [ 1 ] . url ;
54
+ }
55
+
56
+ checkShouldOverrideTDS ( ) {
57
+ const contentBlockingSubFeatures = this . config . config ?. features [ CONTENT_BLOCKING ] . features || { } ;
58
+ const enabledBlocklistOverrides = Object . keys ( contentBlockingSubFeatures ) . filter (
59
+ ( k ) => k . startsWith ( 'TDS' ) && this . config . isSubFeatureEnabled ( CONTENT_BLOCKING , k ) ,
60
+ ) ;
61
+ if ( enabledBlocklistOverrides . length > 0 ) {
62
+ const subFeatureName = enabledBlocklistOverrides [ 0 ]
63
+ const overrideSubFeature = contentBlockingSubFeatures [ subFeatureName ]
64
+ // If this is enabled via an experiment, the override URL is defined as `${cohortName}Url`, otherwise, for a normal rollout use `nextUrl`.
65
+ const settingsKey = `${ this . remoteConfig . getCohortName ( CONTENT_BLOCKING , subFeatureName ) || 'next' } Url`
66
+ const overridePath = overrideSubFeature . settings && overrideSubFeature . settings [ settingsKey ]
67
+ if ( ! overridePath ) {
68
+ console . warn ( `Couldn't find TDS override path in subfeature settings.` )
69
+ return
70
+ }
71
+ if ( overridePath !== this . settings . getSetting ( TDS_OVERRIDE_SETTINGS_KEY ) ) {
72
+ console . log ( 'TDS URL override changed to ' , overridePath ) ;
73
+ this . settings . updateSetting ( TDS_OVERRIDE_SETTINGS_KEY , overridePath ) ;
74
+ this . tds . checkForUpdates ( true ) ;
75
+ }
76
+ this . remoteConfig . markExperimentEnrolled ( CONTENT_BLOCKING , subFeatureName )
77
+ } else if ( this . settings . getSetting ( TDS_OVERRIDE_SETTINGS_KEY ) ) {
78
+ // User removed from experiment/rollout, reset TDS override and fetch default list
79
+ this . settings . removeSetting ( TDS_OVERRIDE_SETTINGS_KEY )
80
+ this . tds . checkForUpdates ( true ) ;
81
+ }
82
+ }
41
83
}
0 commit comments