@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
@@ -1,34 +0,0 @@
1
- import { AutoCMP } from '../types';
2
- import { RunContext } from '../rules';
3
- export type DetectorConfig = {
4
- presentMatcher: any;
5
- showingMatcher: any;
6
- };
7
- export type MethodConfig = {
8
- action?: any;
9
- name: string;
10
- };
11
- export type ConsentOMaticConfig = {
12
- detectors: DetectorConfig[];
13
- methods: MethodConfig[];
14
- };
15
- export declare class ConsentOMaticCMP implements AutoCMP {
16
- name: string;
17
- config: ConsentOMaticConfig;
18
- methods: Map<string, any>;
19
- hasSelfTest: boolean;
20
- runContext: RunContext;
21
- isCosmetic: boolean;
22
- constructor(name: string, config: ConsentOMaticConfig);
23
- get isIntermediate(): boolean;
24
- checkRunContext(): boolean;
25
- checkFrameContext(isTop: boolean): boolean;
26
- hasMatchingUrlPattern(): boolean;
27
- detectCmp(): Promise<boolean>;
28
- detectPopup(): Promise<boolean>;
29
- executeAction(method: string, param?: any): Promise<boolean | void>;
30
- optOut(): Promise<boolean>;
31
- optIn(): Promise<boolean>;
32
- openCmp(): Promise<boolean>;
33
- test(): Promise<boolean>;
34
- }
@@ -1,2 +0,0 @@
1
- export declare function matches(config: any): any;
2
- export declare function executeAction(config: any, param?: any): Promise<boolean | void>;
@@ -1,10 +0,0 @@
1
- /**
2
- * This code is in most parts copied from https://github.com/cavi-au/Consent-O-Matic/blob/master/Extension/Tools.js
3
- * which is licened under the MIT.
4
- */
5
- export default class Tools {
6
- static base: HTMLElement;
7
- static setBase(base: HTMLElement): void;
8
- static findElement(options: any, parent?: any, multiple?: boolean): HTMLElement[] | HTMLElement;
9
- static find(options: any, multiple?: boolean): any;
10
- }
@@ -1,2 +0,0 @@
1
- declare const serializedEngine: Uint8Array<ArrayBuffer>;
2
- export default serializedEngine;
@@ -1,4 +0,0 @@
1
- import { FiltersEngine } from '@ghostery/adblocker';
2
- export declare function deserializeFilterList(serializedEngine: Uint8Array): FiltersEngine;
3
- export declare function getCosmeticStylesheet(engine: FiltersEngine): string;
4
- export declare function getFilterlistSelectors(styles: string): string;
@@ -1,11 +0,0 @@
1
- import AutoConsent from './web';
2
- export default class AutoConsentExtra extends AutoConsent {
3
- initializeFilterList(): void;
4
- undoCosmetics(): void;
5
- filterListFallback(): boolean;
6
- /**
7
- * Apply cosmetic filters
8
- * @returns true if the filters were applied, false otherwise
9
- */
10
- applyCosmeticFilters(styles?: string): Promise<boolean>;
11
- }
@@ -1,97 +0,0 @@
1
- import { AutoCMP } from '../types';
2
- import { executeAction, matches } from '../consentomatic';
3
- import { RunContext } from '../rules';
4
- import { defaultRunContext } from './base';
5
-
6
- export type DetectorConfig = {
7
- presentMatcher: any;
8
- showingMatcher: any;
9
- };
10
- export type MethodConfig = {
11
- action?: any;
12
- name: string;
13
- };
14
-
15
- export type ConsentOMaticConfig = {
16
- detectors: DetectorConfig[];
17
- methods: MethodConfig[];
18
- };
19
-
20
- export class ConsentOMaticCMP implements AutoCMP {
21
- methods = new Map<string, any>();
22
- hasSelfTest: boolean;
23
- runContext: RunContext = defaultRunContext;
24
- isCosmetic = false;
25
-
26
- constructor(
27
- public name: string,
28
- public config: ConsentOMaticConfig,
29
- ) {
30
- config.methods.forEach((methodConfig) => {
31
- if (methodConfig.action) {
32
- this.methods.set(methodConfig.name, methodConfig.action);
33
- }
34
- });
35
- this.hasSelfTest = false;
36
- }
37
-
38
- get isIntermediate(): boolean {
39
- return false; // TODO: support UTILITY rules
40
- }
41
-
42
- checkRunContext(): boolean {
43
- return true;
44
- }
45
-
46
- checkFrameContext(isTop: boolean): boolean {
47
- return true;
48
- }
49
-
50
- hasMatchingUrlPattern(): boolean {
51
- return false;
52
- }
53
-
54
- async detectCmp(): Promise<boolean> {
55
- const matchResults = this.config.detectors.map((detectorConfig) => matches(detectorConfig.presentMatcher));
56
- return matchResults.some((r) => !!r);
57
- }
58
-
59
- async detectPopup(): Promise<boolean> {
60
- const matchResults = this.config.detectors.map((detectorConfig) => matches(detectorConfig.showingMatcher));
61
- return matchResults.some((r) => !!r);
62
- }
63
-
64
- async executeAction(method: string, param?: any) {
65
- if (this.methods.has(method)) {
66
- return executeAction(this.methods.get(method), param);
67
- }
68
- return true;
69
- }
70
-
71
- async optOut(): Promise<boolean> {
72
- await this.executeAction('HIDE_CMP');
73
- await this.executeAction('OPEN_OPTIONS');
74
- await this.executeAction('HIDE_CMP');
75
- await this.executeAction('DO_CONSENT', []);
76
- await this.executeAction('SAVE_CONSENT');
77
- return true;
78
- }
79
-
80
- async optIn(): Promise<boolean> {
81
- await this.executeAction('HIDE_CMP');
82
- await this.executeAction('OPEN_OPTIONS');
83
- await this.executeAction('HIDE_CMP');
84
- await this.executeAction('DO_CONSENT', ['D', 'A', 'B', 'E', 'F', 'X']);
85
- await this.executeAction('SAVE_CONSENT');
86
- return true;
87
- }
88
- async openCmp(): Promise<boolean> {
89
- await this.executeAction('HIDE_CMP');
90
- await this.executeAction('OPEN_OPTIONS');
91
- return true;
92
- }
93
-
94
- async test(): Promise<boolean> {
95
- return true;
96
- }
97
- }
@@ -1,252 +0,0 @@
1
- import Tools from "./tools";
2
-
3
- export function matches(config: any) {
4
- const result = Tools.find(config);
5
- if (config.type === "css") {
6
- return !!result.target;
7
- } else if (config.type === "checkbox") {
8
- return !!result.target && result.target.checked;
9
- }
10
- }
11
-
12
- export async function executeAction(config: any, param?: any): Promise<boolean | void> {
13
- switch (config.type) {
14
- case "click":
15
- return clickAction(config);
16
- case "list":
17
- return listAction(config, param);
18
- case "consent":
19
- return consentAction(config, param);
20
- case "ifcss":
21
- return ifCssAction(config, param);
22
- case "waitcss":
23
- return waitCssAction(config);
24
- case "foreach":
25
- return forEachAction(config, param);
26
- case "hide":
27
- return hideAction(config);
28
- case "slide":
29
- return slideAction(config);
30
- case "close":
31
- return closeAction();
32
- case "wait":
33
- return waitAction(config);
34
- case "eval":
35
- return evalAction(config);
36
- default:
37
- throw new Error("Unknown action type: " + config.type);
38
- }
39
- }
40
-
41
- const STEP_TIMEOUT = 0;
42
-
43
- function waitTimeout(timeout: number): Promise<void> {
44
- return new Promise(resolve => {
45
- setTimeout(() => {
46
- resolve();
47
- }, timeout);
48
- });
49
- }
50
-
51
- async function clickAction(config: any) {
52
- const result = Tools.find(config);
53
- if (result.target != null) {
54
- result.target.click();
55
- }
56
- return waitTimeout(STEP_TIMEOUT);
57
- }
58
-
59
- async function listAction(config: any, param: any) {
60
- for (const action of config.actions) {
61
- await executeAction(action, param);
62
- }
63
- }
64
-
65
- async function consentAction(config: any, consentTypes: any) {
66
- for (const consentConfig of config.consents) {
67
- const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
68
- if (consentConfig.matcher && consentConfig.toggleAction) {
69
- const isEnabled = matches(consentConfig.matcher);
70
- if (isEnabled !== shouldEnable) {
71
- await executeAction(consentConfig.toggleAction);
72
- }
73
- } else {
74
- if (shouldEnable) {
75
- await executeAction(consentConfig.trueAction);
76
- } else {
77
- await executeAction(consentConfig.falseAction);
78
- }
79
- }
80
- }
81
- }
82
-
83
- async function ifCssAction(config: any, param: any) {
84
- const result = Tools.find(config);
85
- if (!result.target) {
86
- if (config.trueAction) {
87
- await executeAction(config.trueAction, param);
88
- }
89
- } else {
90
- if (config.falseAction) {
91
- await executeAction(config.falseAction, param);
92
- }
93
- }
94
- }
95
-
96
- async function waitCssAction(config: any) {
97
- await new Promise<void>(resolve => {
98
- let numRetries = config.retries || 10;
99
- const waitTime = config.waitTime || 250;
100
- const checkCss = () => {
101
- const result = Tools.find(config);
102
- if (
103
- (config.negated && result.target) ||
104
- (!config.negated && !result.target)
105
- ) {
106
- if (numRetries > 0) {
107
- numRetries -= 1;
108
- setTimeout(checkCss, waitTime);
109
- } else {
110
- resolve();
111
- }
112
- } else {
113
- resolve();
114
- }
115
- };
116
- checkCss();
117
- });
118
- }
119
-
120
- async function forEachAction(config: any, param: any) {
121
- const results = Tools.find(config, true);
122
- const oldBase = Tools.base;
123
- for (const result of results) {
124
- if (result.target) {
125
- Tools.setBase(result.target);
126
- await executeAction(config.action, param);
127
- }
128
- }
129
- Tools.setBase(oldBase);
130
- }
131
-
132
- async function hideAction(config: any) {
133
- const result = Tools.find(config);
134
- if (result.target) {
135
- result.target.classList.add("Autoconsent-Hidden");
136
- // result.target.setAttribute("style", "display: none;");
137
- }
138
- }
139
-
140
- async function slideAction(config: any) {
141
- const result = Tools.find(config);
142
- const dragResult = Tools.find(config.dragTarget);
143
- if (result.target) {
144
- const targetBounds = result.target.getBoundingClientRect();
145
- const dragTargetBounds = dragResult.target.getBoundingClientRect();
146
-
147
- let yDiff = dragTargetBounds.top - targetBounds.top;
148
- let xDiff = dragTargetBounds.left - targetBounds.left;
149
-
150
- if (this.config.axis.toLowerCase() === "y") {
151
- xDiff = 0;
152
- }
153
- if (this.config.axis.toLowerCase() === "x") {
154
- yDiff = 0;
155
- }
156
-
157
- const screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
158
- const screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
159
- const clientX = targetBounds.left + targetBounds.width / 2.0;
160
- const clientY = targetBounds.top + targetBounds.height / 2.0;
161
-
162
- const mouseDown = document.createEvent("MouseEvents");
163
- mouseDown.initMouseEvent(
164
- "mousedown",
165
- true,
166
- true,
167
- window,
168
- 0,
169
- screenX,
170
- screenY,
171
- clientX,
172
- clientY,
173
- false,
174
- false,
175
- false,
176
- false,
177
- 0,
178
- result.target
179
- );
180
- const mouseMove = document.createEvent("MouseEvents");
181
- mouseMove.initMouseEvent(
182
- "mousemove",
183
- true,
184
- true,
185
- window,
186
- 0,
187
- screenX + xDiff,
188
- screenY + yDiff,
189
- clientX + xDiff,
190
- clientY + yDiff,
191
- false,
192
- false,
193
- false,
194
- false,
195
- 0,
196
- result.target
197
- );
198
- const mouseUp = document.createEvent("MouseEvents");
199
- mouseUp.initMouseEvent(
200
- "mouseup",
201
- true,
202
- true,
203
- window,
204
- 0,
205
- screenX + xDiff,
206
- screenY + yDiff,
207
- clientX + xDiff,
208
- clientY + yDiff,
209
- false,
210
- false,
211
- false,
212
- false,
213
- 0,
214
- result.target
215
- );
216
- result.target.dispatchEvent(mouseDown);
217
- await this.waitTimeout(10);
218
- result.target.dispatchEvent(mouseMove);
219
- await this.waitTimeout(10);
220
- result.target.dispatchEvent(mouseUp);
221
- }
222
- }
223
-
224
- async function waitAction(config: any) {
225
- await waitTimeout(config.waitTime);
226
- }
227
-
228
- async function closeAction() {
229
- window.close();
230
- }
231
-
232
- async function evalAction(config: any): Promise<boolean> {
233
- console.log("eval!", config.code);
234
- return new Promise(resolve => {
235
- try {
236
- if (config.async) {
237
- // eslint-disable-next-line no-eval
238
- window.eval(config.code);
239
- setTimeout(() => {
240
- // eslint-disable-next-line no-eval
241
- resolve(window.eval("window.__consentCheckResult"));
242
- }, config.timeout || 250);
243
- } else {
244
- // eslint-disable-next-line no-eval
245
- resolve(window.eval(config.code));
246
- }
247
- } catch (e) {
248
- console.warn("eval error", e, config.code);
249
- resolve(false);
250
- }
251
- });
252
- }
@@ -1,199 +0,0 @@
1
- /**
2
- * This code is in most parts copied from https://github.com/cavi-au/Consent-O-Matic/blob/master/Extension/Tools.js
3
- * which is licened under the MIT.
4
- */
5
- export default class Tools {
6
- static base: HTMLElement = null;
7
-
8
- static setBase(base: HTMLElement) {
9
- Tools.base = base;
10
- }
11
-
12
- static findElement(options: any, parent: any = null, multiple = false): HTMLElement[] | HTMLElement {
13
- let possibleTargets = null;
14
-
15
- if (parent != null) {
16
- possibleTargets = Array.from(parent.querySelectorAll(options.selector));
17
- } else {
18
- if (Tools.base != null) {
19
- possibleTargets = Array.from(
20
- Tools.base.querySelectorAll(options.selector)
21
- );
22
- } else {
23
- possibleTargets = Array.from(
24
- document.querySelectorAll(options.selector)
25
- );
26
- }
27
- }
28
-
29
- if (options.textFilter != null) {
30
- possibleTargets = possibleTargets.filter(possibleTarget => {
31
- const textContent = possibleTarget.textContent.toLowerCase();
32
-
33
- if (Array.isArray(options.textFilter)) {
34
- let foundText = false;
35
-
36
- for (const text of options.textFilter) {
37
- if (textContent.indexOf(text.toLowerCase()) !== -1) {
38
- foundText = true;
39
- break;
40
- }
41
- }
42
-
43
- return foundText;
44
- } else if (options.textFilter != null) {
45
- return textContent.indexOf(options.textFilter.toLowerCase()) !== -1;
46
- }
47
- return false;
48
- });
49
- }
50
-
51
- if (options.styleFilters != null) {
52
- possibleTargets = possibleTargets.filter(possibleTarget => {
53
- const styles = window.getComputedStyle(possibleTarget);
54
-
55
- let keep = true;
56
-
57
- for (const styleFilter of options.styleFilters) {
58
- const option = styles[styleFilter.option];
59
-
60
- if (styleFilter.negated) {
61
- keep = keep && option !== styleFilter.value;
62
- } else {
63
- keep = keep && option === styleFilter.value;
64
- }
65
- }
66
-
67
- return keep;
68
- });
69
- }
70
-
71
- if (options.displayFilter != null) {
72
- possibleTargets = possibleTargets.filter(possibleTarget => {
73
- if (options.displayFilter) {
74
- // We should be displayed
75
- return possibleTarget.offsetHeight !== 0;
76
- } else {
77
- // We should not be displayed
78
- return possibleTarget.offsetHeight === 0;
79
- }
80
- });
81
- }
82
-
83
- if (options.iframeFilter != null) {
84
- possibleTargets = possibleTargets.filter((/* possibleTarget */) => {
85
- if (options.iframeFilter) {
86
- // We should be inside an iframe
87
- return window.location !== window.parent.location;
88
- } else {
89
- // We should not be inside an iframe
90
- return window.location === window.parent.location;
91
- }
92
- });
93
- }
94
-
95
- if (options.childFilter != null) {
96
- possibleTargets = possibleTargets.filter(possibleTarget => {
97
- const oldBase = Tools.base;
98
- Tools.setBase(possibleTarget);
99
- const childResults = Tools.find(options.childFilter);
100
- Tools.setBase(oldBase);
101
- return childResults.target != null;
102
- });
103
- }
104
-
105
- if (multiple) {
106
- return possibleTargets;
107
- } else {
108
- if (possibleTargets.length > 1) {
109
- console.warn(
110
- "Multiple possible targets: ",
111
- possibleTargets,
112
- options,
113
- parent
114
- );
115
- }
116
-
117
- return possibleTargets[0];
118
- }
119
- }
120
-
121
- static find(options: any, multiple = false) {
122
- const results: any[] = [];
123
- if (options.parent != null) {
124
- const parent = Tools.findElement(options.parent, null, multiple);
125
- if (parent != null) {
126
- if (parent instanceof Array) {
127
- parent.forEach(p => {
128
- const targets = Tools.findElement(options.target, p, multiple);
129
- if (targets instanceof Array) {
130
- targets.forEach(target => {
131
- results.push({
132
- parent: p,
133
- target
134
- });
135
- });
136
- } else {
137
- results.push({
138
- parent: p,
139
- target: targets
140
- });
141
- }
142
- });
143
-
144
- return results;
145
- } else {
146
- const targets = Tools.findElement(options.target, parent, multiple);
147
- if (targets instanceof Array) {
148
- targets.forEach(target => {
149
- results.push({
150
- parent,
151
- target
152
- });
153
- });
154
- } else {
155
- results.push({
156
- parent,
157
- target: targets
158
- });
159
- }
160
- }
161
- }
162
- } else {
163
- const targets = Tools.findElement(options.target, null, multiple);
164
- if (targets instanceof Array) {
165
- targets.forEach(target => {
166
- results.push({
167
- parent: null,
168
- target
169
- });
170
- });
171
- } else {
172
- results.push({
173
- parent: null,
174
- target: targets
175
- });
176
- }
177
- }
178
-
179
- if (results.length === 0) {
180
- results.push({
181
- parent: null,
182
- target: null
183
- });
184
- }
185
-
186
- if (multiple) {
187
- return results;
188
- } else {
189
- if (results.length !== 1) {
190
- console.warn(
191
- "Multiple results found, even though multiple false",
192
- results
193
- );
194
- }
195
-
196
- return results[0];
197
- }
198
- }
199
- }