@duckduckgo/autoconsent 15.0.0 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/.github/dependabot.yml +0 -3
  2. package/.github/workflows/release.yml +0 -4
  3. package/AGENTS.md +3 -3
  4. package/CHANGELOG.md +32 -0
  5. package/build.sh +3 -2
  6. package/dist/addon-firefox/background.bundle.js +8 -24
  7. package/dist/addon-firefox/compact-rules.json +1 -1
  8. package/dist/addon-firefox/content.bundle.js +184 -686
  9. package/dist/addon-firefox/manifest.json +1 -1
  10. package/dist/addon-firefox/popup.bundle.js +196 -25
  11. package/dist/addon-firefox/popup.html +98 -5
  12. package/dist/addon-firefox/rule-index.json +1 -0
  13. package/dist/addon-firefox/rules.json +1 -1
  14. package/dist/addon-mv3/background.bundle.js +8 -24
  15. package/dist/addon-mv3/compact-rules.json +1 -1
  16. package/dist/addon-mv3/content.bundle.js +184 -686
  17. package/dist/addon-mv3/manifest.json +1 -1
  18. package/dist/addon-mv3/popup.bundle.js +196 -25
  19. package/dist/addon-mv3/popup.html +98 -5
  20. package/dist/addon-mv3/rule-index.json +1 -0
  21. package/dist/addon-mv3/rules.json +1 -1
  22. package/dist/autoconsent.cjs.js +184 -685
  23. package/dist/autoconsent.esm.js +184 -685
  24. package/dist/autoconsent.playwright.js +185 -689
  25. package/dist/autoconsent.standalone.js +3625 -0
  26. package/dist/types/cmps/base.d.ts +3 -3
  27. package/dist/types/cmps/trustarc-top.d.ts +1 -1
  28. package/dist/types/eval-handler.d.ts +3 -3
  29. package/dist/types/heuristics.d.ts +2 -2
  30. package/dist/types/types.d.ts +10 -23
  31. package/dist/types/web.d.ts +0 -9
  32. package/docs/api.md +1 -8
  33. package/docs/puppeteer.md +1 -3
  34. package/docs/rule-syntax.md +0 -17
  35. package/eslint.config.mjs +1 -1
  36. package/lib/cmps/base.ts +5 -6
  37. package/lib/cmps/conversant.ts +7 -4
  38. package/lib/cmps/trustarc-top.ts +1 -1
  39. package/lib/cmps/uniconsent.ts +4 -4
  40. package/lib/eval-handler.ts +6 -3
  41. package/lib/heuristics.ts +15 -15
  42. package/lib/types.ts +9 -21
  43. package/lib/utils.ts +13 -9
  44. package/lib/web.ts +3 -53
  45. package/package.json +4 -17
  46. package/playwright/content.ts +1 -2
  47. package/readme.md +3 -6
  48. package/rules/autoconsent/dreamlab-cmp.json +13 -0
  49. package/rules/build.ts +4 -23
  50. package/rules/compact-rules.json +1 -1
  51. package/rules/rule-index-builder.ts +58 -0
  52. package/rules/rule-index.json +1 -0
  53. package/rules/rules.json +1 -1
  54. package/standalone/content.ts +101 -0
  55. package/tests/dreamlab-cmp.spec.ts +3 -0
  56. package/tests/quantcast.spec.ts +0 -6
  57. package/tests-wtr/heuristics/get-actionable-popups.ts +13 -13
  58. package/tests-wtr/heuristics/heuristic-cmp.ts +32 -33
  59. package/tests-wtr/lifecycle/find-cmp.ts +5 -8
  60. package/tests-wtr/web/do-opt-in.test.ts +0 -1
  61. package/tests-wtr/web/do-opt-out.test.ts +0 -1
  62. package/tests-wtr/web/do-self-test.test.ts +0 -1
  63. package/tests-wtr/web/filter-cmps.test.ts +0 -1
  64. package/tests-wtr/web/receive-message-callback.test.ts +1 -2
  65. package/tests-wtr/web/update-state.test.ts +1 -3
  66. package/tsconfig.build.json +1 -1
  67. package/.github/workflows/update-filterlist.yml +0 -42
  68. package/dist/autoconsent.extra.cjs.js +0 -15709
  69. package/dist/autoconsent.extra.esm.js +0 -15641
  70. package/dist/types/cmps/consentomatic.d.ts +0 -34
  71. package/dist/types/consentomatic/index.d.ts +0 -2
  72. package/dist/types/consentomatic/tools.d.ts +0 -10
  73. package/dist/types/filterlist-engine.d.ts +0 -2
  74. package/dist/types/filterlist-utils.d.ts +0 -4
  75. package/dist/types/web-extra.d.ts +0 -11
  76. package/lib/cmps/consentomatic.ts +0 -97
  77. package/lib/consentomatic/index.ts +0 -252
  78. package/lib/consentomatic/tools.ts +0 -199
  79. package/lib/filterlist-engine.ts +0 -5
  80. package/lib/filterlist-utils.ts +0 -45
  81. package/lib/web-extra.ts +0 -116
  82. package/rules/consentomatic.json +0 -1
  83. package/rules/filterlist.txt +0 -18440
  84. package/rules/filterlists/overrides.txt +0 -4
  85. package/scripts/compile-filterlist.mjs +0 -63
  86. package/scripts/fetch-easylist.sh +0 -25
  87. package/scripts/rebuild-filterlist.mjs +0 -216
  88. package/tests/oil.spec.ts +0 -7
  89. package/tests/springer.spec.ts +0 -7
  90. package/tests/wordpressgdpr.spec.ts +0 -6
package/lib/web.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { MessageSender, AutoCMP, RuleBundle, Config, ConsentState } from './types';
2
- import { ConsentOMaticCMP, ConsentOMaticConfig } from './cmps/consentomatic';
3
2
  import { AutoConsentCMPRule, SUPPORTED_RULE_STEP_VERSION } from './rules';
4
3
  import { BackgroundMessage, InitMessage } from './messages';
5
4
  import { evalState, resolveEval } from './eval-handler';
@@ -8,7 +7,6 @@ import { dynamicCMPs } from './cmps/all';
8
7
  import { AutoConsentCMP, AutoConsentHeuristicCMP } from './cmps/base';
9
8
  import { DomActions } from './dom-actions';
10
9
  import { isTopFrame, normalizeConfig, scheduleWhenIdle } from './utils';
11
- import { FiltersEngine } from '@ghostery/adblocker';
12
10
  import { checkHeuristicPatterns } from './heuristics';
13
11
  import { decodeRules } from './encoding';
14
12
 
@@ -36,8 +34,6 @@ export default class AutoConsent {
36
34
  #config?: Config;
37
35
  foundCmp?: AutoCMP;
38
36
  state: ConsentState = {
39
- cosmeticFiltersOn: false,
40
- filterListReported: false,
41
37
  lifecycle: 'loading',
42
38
  prehideOn: false,
43
39
  findCmpAttempts: 0,
@@ -51,9 +47,7 @@ export default class AutoConsent {
51
47
  endTime: 0,
52
48
  };
53
49
  domActions: DomActions;
54
- filtersEngine?: FiltersEngine;
55
50
  sendContentMessage: MessageSender;
56
- protected cosmeticStyleSheet?: CSSStyleSheet;
57
51
  protected focusedElement?: HTMLElement;
58
52
 
59
53
  constructor(sendContentMessage: MessageSender, config: Partial<Config> | null = null, declarativeRules: RuleBundle | null = null) {
@@ -100,9 +94,6 @@ export default class AutoConsent {
100
94
  this.parseDeclarativeRules(declarativeRules);
101
95
  }
102
96
 
103
- if (config.enableFilterList) {
104
- this.initializeFilterList();
105
- }
106
97
  this.rules = filterCMPs(this.rules, normalizedConfig);
107
98
 
108
99
  if (this.shouldPrehide) {
@@ -131,10 +122,6 @@ export default class AutoConsent {
131
122
  this.updateState({ lifecycle: 'initialized' });
132
123
  }
133
124
 
134
- initializeFilterList() {
135
- // no-op by default
136
- }
137
-
138
125
  get shouldPrehide() {
139
126
  return this.config.enablePrehide && !this.config.visualTest;
140
127
  }
@@ -167,11 +154,6 @@ export default class AutoConsent {
167
154
  parseDeclarativeRules(declarativeRules: RuleBundle) {
168
155
  const perfEnabled = this.#config?.performanceLoggingEnabled;
169
156
  perfEnabled && performance.mark('parseDeclarativeRulesStart');
170
- if (declarativeRules.consentomatic) {
171
- for (const [name, rule] of Object.entries(declarativeRules.consentomatic)) {
172
- this.addConsentomaticCMP(name, rule);
173
- }
174
- }
175
157
 
176
158
  if (declarativeRules.autoconsent) {
177
159
  declarativeRules.autoconsent.forEach((ruleset) => {
@@ -198,10 +180,6 @@ export default class AutoConsent {
198
180
  }
199
181
  }
200
182
 
201
- addConsentomaticCMP(name: string, config: ConsentOMaticConfig) {
202
- this.rules.push(new ConsentOMaticCMP(`com_${name}`, config));
203
- }
204
-
205
183
  // start the detection process, possibly with a delay
206
184
  start() {
207
185
  scheduleWhenIdle(() => this._start());
@@ -222,7 +200,8 @@ export default class AutoConsent {
222
200
  this.undoPrehide();
223
201
  }
224
202
 
225
- return this.filterListFallback();
203
+ this.updateState({ lifecycle: 'nothingDetected' });
204
+ return false;
226
205
  }
227
206
 
228
207
  this.updateState({ lifecycle: 'cmpDetected' });
@@ -296,7 +275,7 @@ export default class AutoConsent {
296
275
  });
297
276
  // heuristic CMP is only run in the top frame and only if heuristic action is enabled and retries is odd
298
277
  const heuristicRules =
299
- isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0
278
+ isTop && this.config.heuristicMode !== 'off' && this.state.findCmpAttempts % 2 === 0
300
279
  ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)]
301
280
  : [];
302
281
 
@@ -436,11 +415,6 @@ export default class AutoConsent {
436
415
  // prehide might have timeouted by this time, apply it again
437
416
  this.prehideElements();
438
417
  }
439
- if (this.state.cosmeticFiltersOn) {
440
- // cancel cosmetic filters if we have a rule for this popup
441
- this.undoCosmetics();
442
- }
443
-
444
418
  this.foundCmp = cmp;
445
419
 
446
420
  if (this.config.autoAction === 'optOut') {
@@ -631,30 +605,6 @@ export default class AutoConsent {
631
605
  this.domActions.undoPrehide();
632
606
  }
633
607
 
634
- undoCosmetics() {
635
- // no-op by default
636
- }
637
-
638
- reportFilterlist() {
639
- this.sendContentMessage({
640
- type: 'cmpDetected',
641
- url: location.href,
642
- cmp: 'filterList',
643
- });
644
- this.sendContentMessage({
645
- type: 'popupFound',
646
- cmp: 'filterList',
647
- url: location.href,
648
- });
649
- this.updateState({ filterListReported: true });
650
- }
651
-
652
- filterListFallback() {
653
- // no-op by default
654
- this.updateState({ lifecycle: 'nothingDetected' });
655
- return false;
656
- }
657
-
658
608
  updateState(change: Partial<ConsentState>) {
659
609
  Object.assign(this.state, change);
660
610
  this.sendContentMessage({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckduckgo/autoconsent",
3
- "version": "15.0.0",
3
+ "version": "16.0.0",
4
4
  "description": "",
5
5
  "types": "./dist/types/web.d.ts",
6
6
  "exports": {
@@ -9,13 +9,7 @@
9
9
  "import": "./dist/autoconsent.esm.js",
10
10
  "require": "./dist/autoconsent.cjs.js"
11
11
  },
12
- "./extra": {
13
- "types": "./dist/types/web-extra.d.ts",
14
- "import": "./dist/autoconsent.extra.esm.js",
15
- "require": "./dist/autoconsent.extra.cjs.js"
16
- },
17
12
  "./rules/rules.json": "./rules/rules.json",
18
- "./rules/consentomatic.json": "./rules/consentomatic.json",
19
13
  "./rules/compact-rules.json": "./rules/compact-rules.json"
20
14
  },
21
15
  "directories": {
@@ -27,7 +21,7 @@
27
21
  "lint-fix": "eslint . --fix && prettier . --write && npm run rule-syntax-check",
28
22
  "bundle": "./build.sh",
29
23
  "rule-syntax-check": "node scripts/validate-json-rules.js",
30
- "watch": "npm run prepublish && chokidar \"lib\" \"addon\" \"rules/autoconsent\" \"rules/generated\" \"rules/filterlist.txt\" --ignore 'lib/filterlist-engine.ts' -c \"npm run prepublish\"",
24
+ "watch": "npm run prepublish && chokidar \"lib\" \"addon\" \"rules/autoconsent\" \"rules/generated\" -c \"npm run prepublish\"",
31
25
  "create-rule": "node rules/create-rule.mjs",
32
26
  "test": "playwright test",
33
27
  "test:webkit": "playwright test --project webkit",
@@ -35,14 +29,10 @@
35
29
  "test:chrome": "playwright test --project chrome",
36
30
  "test:lib": "web-test-runner",
37
31
  "test:sample": "playwright test tests/_sample-test.spec.ts --project webkit",
38
- "fetch-easylist": "scripts/fetch-easylist.sh",
39
- "rebuild-filterlist": "node scripts/rebuild-filterlist.mjs",
40
- "update-easylist": "npm run fetch-easylist && npm run rebuild-filterlist",
41
- "compile-filterlist": "node scripts/compile-filterlist.mjs",
42
32
  "build-rules": "ts-node rules/build.ts",
43
33
  "version": "node update_version.js && git add addon/manifest.*.json",
44
34
  "vendor-copy": "mkdir -p addon/vendor && cp node_modules/mocha/mocha.* addon/vendor/ && cp node_modules/chai/chai.js addon/vendor/",
45
- "prepublish": "npm run compile-filterlist && npm run build-rules && npm run bundle",
35
+ "prepublish": "npm run build-rules && npm run bundle",
46
36
  "launch:firefox": "web-ext run -s dist/addon-firefox",
47
37
  "release": "auto shipit",
48
38
  "get-text-for-xpath": "ts-node scripts/get-text-for-xpath.ts",
@@ -68,7 +58,6 @@
68
58
  "bulma": "^1.0.2",
69
59
  "chai": "^6.0.1",
70
60
  "chokidar-cli": "^3.0.0",
71
- "csv-parse": "^6.0.0",
72
61
  "esbuild": "^0.28.0",
73
62
  "eslint": "^10.0.3",
74
63
  "globals": "^17.4.0",
@@ -92,8 +81,6 @@
92
81
  ]
93
82
  },
94
83
  "dependencies": {
95
- "@ghostery/adblocker": "^2.0.4",
96
- "@ghostery/adblocker-content": "^2.0.4",
97
- "tldts-experimental": "^7.0.4"
84
+ "tldts-experimental": "^7.4.3"
98
85
  }
99
86
  }
@@ -1,7 +1,6 @@
1
1
  import AutoConsent from '../lib/web';
2
2
  import { BackgroundMessage } from '../lib/messages';
3
3
  import { MessageSender, RuleBundle } from '../lib/types';
4
- import { consentomatic } from '../rules/consentomatic.json';
5
4
 
6
5
  declare global {
7
6
  interface Window {
@@ -11,7 +10,7 @@ declare global {
11
10
  }
12
11
 
13
12
  if (!window.autoconsentReceiveMessage) {
14
- const consent = new AutoConsent(window.autoconsentSendMessage, null, <RuleBundle>{ autoconsent: [], consentomatic });
13
+ const consent = new AutoConsent(window.autoconsentSendMessage, null, <RuleBundle>{ autoconsent: [] });
15
14
 
16
15
  window.autoconsentReceiveMessage = (message: BackgroundMessage) => {
17
16
  return Promise.resolve(consent.receiveMessageCallback(message));
package/readme.md CHANGED
@@ -11,14 +11,13 @@ Autoconsent is meant to be used in browser apps and extensions. [DuckDuckGo brow
11
11
  To integrate Autoconsent, you'll need to instantiate the main `AutoConsent` class in a content script (running in isolated page context), and implement some configuration hooks in a background script. See [this document](docs/api.md) for more details on internal APIs and data flows.
12
12
 
13
13
  ```javascript
14
- import AutoConsent from '@duckduckgo/autoconsent'; // or '@duckduckgo/autoconsent/extra' for the version with filterlists
14
+ import AutoConsent from '@duckduckgo/autoconsent';
15
15
  import { autoconsent } from '@duckduckgo/autoconsent/rules/rules.json';
16
- import { consentomatic } from '@duckduckgo/autoconsent/rules/consentomatic.json'
17
16
 
18
17
  const autoconsent = new AutoConsent(
19
18
  chrome.runtime.sendMessage, // provide a callback to send messages to the background script
20
19
  null, // optionally provide a config object here if you don't want to implement a background script
21
- { autoconsent, consentomatic },
20
+ { autoconsent },
22
21
  );
23
22
 
24
23
  // connect the message receiver callback to handle messages from the background script
@@ -76,13 +75,11 @@ that are installed on multiple sites. Each CMP ruleset defines:
76
75
  * Steps to specify an 'opt-in' or 'opt-out' consent for the CMP.
77
76
  * Optionally, a test if the consent was correctly applied.
78
77
 
79
- There are currently three ways of implementing a CMP:
78
+ There are currently two ways of implementing a CMP:
80
79
 
81
80
  1. As a [JSON ruleset](./rules/autoconsent/), intepreted by the `AutoConsent` class.
82
81
  1. As a class implementing the `AutoCMP` interface. This enables more complex logic than the linear AutoConsent
83
82
  rulesets allow.
84
- 3. As a [Consent-O-Matic](https://github.com/cavi-au/Consent-O-Matic) rule. The `ConsentOMaticCMP` class implements
85
- compability with rules written for the Consent-O-Matic extension.
86
83
 
87
84
  For more details on rule types, see [Rule Syntax Reference](docs/rule-syntax.md).
88
85
 
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "dreamlab-cmp",
3
+ "vendorUrl": "https://cmp.dreamlab.pl/",
4
+ "prehideSelectors": [".cmp-popup_popup"],
5
+ "detectCmp": [{ "exists": ".cmp-app_gdpr" }],
6
+ "detectPopup": [{ "visible": ".cmp-popup_popup" }],
7
+ "optIn": [{ "waitForThenClick": ".cmp-popup_popup .cmp-intro_acceptAll" }],
8
+ "optOut": [
9
+ { "waitForThenClick": ".cmp-popup_popup .cmp-intro_rejectAll" },
10
+ { "waitForThenClick": ".cmp-popup_popup .cmp-details_rejectAll" }
11
+ ],
12
+ "test": [{ "cookieContains": "lpubconsent=" }]
13
+ }
package/rules/build.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
- import https from 'https';
5
4
  import { encodeRules, deduplicateRules } from '../lib/encoding';
6
5
  import { AutoConsentCMPRule } from '../lib/rules';
6
+ import { buildRuleIndex } from './rule-index-builder';
7
7
 
8
8
  export const rulesDir = __dirname;
9
9
 
@@ -28,30 +28,9 @@ export async function buildAutoconsentRules(): Promise<AutoConsentCMPRule[]> {
28
28
  return deduplicateRules([...normalRules, ...generatedRules]);
29
29
  }
30
30
 
31
- export async function buildConsentOMaticRules() {
32
- // fetch ConsentOMatic rule set and merge with our custom rules
33
- const consentOMaticCommit = '7d7fd2bd6bf2b662350b0eaeca74db6eba155efe';
34
- const consentOMaticUrl = `https://raw.githubusercontent.com/cavi-au/Consent-O-Matic/${consentOMaticCommit}/Rules.json`;
35
- const consentOMaticInclude = ['oil', 'optanon', 'quantcast2', 'springer', 'wordpressgdpr'];
36
- const comRules: Record<string, object> = {};
37
- const allComRules: Record<string, object> = await new Promise((resolve) => {
38
- https.get(consentOMaticUrl, (res) => {
39
- res.setEncoding('utf-8');
40
- let content = '';
41
- res.on('data', (data) => (content += data));
42
- res.on('end', () => resolve(JSON.parse(content)));
43
- });
44
- });
45
- consentOMaticInclude.forEach((name) => {
46
- comRules[name] = allComRules[name];
47
- });
48
- return comRules;
49
- }
50
-
51
31
  (async () => {
52
32
  const stringify = (rules: object) => JSON.stringify(rules);
53
33
  const autoconsent = await buildAutoconsentRules();
54
- const consentomatic = await buildConsentOMaticRules();
55
34
 
56
35
  const compactRulesPath = path.join(rulesDir, 'compact-rules.json');
57
36
  let existingCompactRules = null;
@@ -60,7 +39,9 @@ export async function buildConsentOMaticRules() {
60
39
  }
61
40
 
62
41
  fs.writeFile(path.join(rulesDir, 'rules.json'), stringify({ autoconsent }), () => console.log('Written rules.json'));
63
- fs.writeFile(path.join(rulesDir, 'consentomatic.json'), stringify({ consentomatic }), () => console.log('Written consentomatic.json'));
42
+ fs.writeFile(path.join(rulesDir, 'rule-index.json'), stringify(buildRuleIndex(autoconsent)), () =>
43
+ console.log('Written rule-index.json'),
44
+ );
64
45
  fs.writeFile(compactRulesPath, stringify(encodeRules(autoconsent, existingCompactRules)), () =>
65
46
  console.log('Written compact-rules.json'),
66
47
  );