@duckduckgo/autoconsent 1.0.8 → 2.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.
- package/.eslintrc.cjs +14 -0
- package/.vscode/settings.json +7 -0
- package/Jenkinsfile +68 -39
- package/api.md +104 -0
- package/dist/autoconsent.cjs.js +1 -1387
- package/dist/autoconsent.esm.js +1 -1379
- package/dist/autoconsent.playwright.js +1 -0
- package/dist/autoconsent.standalone.js +1 -0
- package/lib/cmps/all.ts +15 -10
- package/lib/cmps/base.ts +91 -91
- package/lib/cmps/consentmanager.ts +31 -19
- package/lib/cmps/consentomatic.ts +89 -0
- package/lib/cmps/cookiebot.ts +58 -55
- package/lib/cmps/evidon.ts +29 -18
- package/lib/cmps/onetrust.ts +32 -20
- package/lib/cmps/sourcepoint-frame.ts +102 -0
- package/lib/cmps/sourcepoint-top.ts +47 -0
- package/lib/cmps/trustarc-frame.ts +115 -0
- package/lib/cmps/trustarc-top.ts +91 -0
- package/lib/consentomatic/index.ts +233 -70
- package/lib/{web/consentomatic → consentomatic}/tools.ts +0 -0
- package/lib/eval-handler.ts +58 -0
- package/lib/index.ts +0 -2
- package/lib/messages.ts +100 -0
- package/lib/rule-executors.ts +108 -0
- package/lib/rules.ts +82 -0
- package/lib/types.ts +35 -0
- package/lib/utils.ts +64 -0
- package/lib/web.ts +283 -74
- package/package.json +17 -14
- package/playwright/content.ts +27 -0
- package/playwright/runner.ts +131 -0
- package/playwright/standalone.ts +36 -0
- package/playwright.config.ts +7 -0
- package/readme.md +57 -47
- package/rollup.config.js +23 -15
- package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
- package/rules/autoconsent/bundesregierung-de.json +5 -1
- package/rules/autoconsent/cc-banner.json +0 -1
- package/rules/autoconsent/cookie-notice.json +0 -1
- package/rules/autoconsent/cookieconsent.json +5 -6
- package/rules/autoconsent/destatis-de.json +0 -1
- package/rules/autoconsent/etsy.json +3 -2
- package/rules/autoconsent/eu-cookie-compliance.json +0 -1
- package/rules/autoconsent/hl-co-uk.json +8 -9
- package/rules/autoconsent/johnlewis.json +5 -2
- package/rules/autoconsent/notice-cookie.json +0 -1
- package/rules/autoconsent/osano.json +0 -1
- package/rules/autoconsent/tealium.json +4 -5
- package/rules/rules.json +44 -37
- package/tests/192.spec.ts +1 -1
- package/tests/arzt-auskunft.spec.ts +1 -1
- package/tests/asus.spec.ts +1 -1
- package/tests/ausopen.spec.ts +1 -1
- package/tests/aws.amazon.spec.ts +1 -1
- package/tests/baden-wuerttemberg.spec.ts +1 -1
- package/tests/borlabs.spec.ts +1 -1
- package/tests/bundesregierung.spec.ts +5 -2
- package/tests/ccbanner.spec.ts +1 -1
- package/tests/consentmanager.spec.ts +3 -3
- package/tests/cookiebot.spec.ts +8 -2
- package/tests/cookieconsent.spec.ts +1 -1
- package/tests/cookielawinfo.spec.ts +1 -1
- package/tests/cookienotice.spec.ts +1 -1
- package/tests/corona-in-zahlen.spec.ts +1 -1
- package/tests/deepl.spec.ts +1 -1
- package/tests/destatis.spec.ts +1 -1
- package/tests/didomi.spec.ts +6 -2
- package/tests/drupal.spec.ts +8 -0
- package/tests/dunelm.spec.ts +1 -1
- package/tests/etsy.spec.ts +1 -1
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests/evidon.spec.ts +1 -1
- package/tests/fundingchoices.spec.ts +2 -1
- package/tests/gov-uk.spec.ts +1 -1
- package/tests/hl-co-uk.spec.ts +1 -1
- package/tests/hubspot.spec.ts +1 -1
- package/tests/ionos.spec.ts +1 -1
- package/tests/johnlewis.spec.ts +2 -2
- package/tests/klaro.spec.ts +1 -1
- package/tests/marksandspencer.spec.ts +1 -1
- package/tests/mediamarkt.spec.ts +1 -1
- package/tests/metoffice-gov-uk.spec.ts +1 -1
- package/tests/microsoft.spec.ts +1 -1
- package/tests/moneysavingexpert.spec.ts +1 -1
- package/tests/motor-talk.spec.ts +1 -1
- package/tests/national-lottery.spec.ts +1 -1
- package/tests/netflix.spec.ts +1 -1
- package/tests/nhs.spec.ts +1 -1
- package/tests/notice-cookie.spec.ts +1 -1
- package/tests/obi.spec.ts +1 -1
- package/tests/oil.spec.ts +1 -1
- package/tests/onetrust.spec.ts +10 -1
- package/tests/osano.spec.ts +1 -1
- package/tests/otto.spec.ts +1 -1
- package/tests/paypal.spec.ts +1 -1
- package/tests/quantcast.spec.ts +4 -1
- package/tests/snigel.spec.ts +1 -1
- package/tests/sourcepoint.spec.ts +8 -8
- package/tests/springer.spec.ts +1 -1
- package/tests/steampowered.spec.ts +1 -1
- package/tests/tealium.spec.ts +1 -1
- package/tests/testcmp.spec.ts +1 -1
- package/tests/thalia.spec.ts +1 -1
- package/tests/thefreedictionary.spec.ts +1 -1
- package/tests/trustarc.spec.ts +25 -4
- package/tests/usercentrics-1.spec.ts +1 -1
- package/tests/uswitch.spec.ts +1 -1
- package/tests/vodafone.spec.ts +1 -1
- package/tests/waitrose.spec.ts +1 -1
- package/tests/wetransfer.spec.ts +1 -1
- package/tests/wordpressgdpr.spec.ts +1 -1
- package/tests/xing.spec.ts +1 -1
- package/tsconfig.json +2 -2
- package/.eslintrc +0 -12
- package/cosmetics/rules.json +0 -110
- package/dist/autoconsent.puppet.js +0 -1078
- package/lib/cmps/all.js +0 -19
- package/lib/cmps/base.js +0 -174
- package/lib/cmps/consentmanager.js +0 -31
- package/lib/cmps/cookiebot.js +0 -77
- package/lib/cmps/evidon.js +0 -26
- package/lib/cmps/onetrust.js +0 -34
- package/lib/cmps/sourcepoint.js +0 -82
- package/lib/cmps/sourcepoint.ts +0 -95
- package/lib/cmps/trustarc.js +0 -106
- package/lib/cmps/trustarc.ts +0 -147
- package/lib/config.js +0 -1
- package/lib/consentomatic/index.js +0 -52
- package/lib/detector.js +0 -33
- package/lib/detector.ts +0 -34
- package/lib/hider.js +0 -13
- package/lib/hider.ts +0 -16
- package/lib/index.js +0 -4
- package/lib/messages.d.ts +0 -61
- package/lib/node.js +0 -35
- package/lib/node.ts +0 -43
- package/lib/puppet/tab.js +0 -121
- package/lib/puppet/tab.ts +0 -146
- package/lib/rules.d.ts +0 -80
- package/lib/tabwrapper.js +0 -67
- package/lib/tabwrapper.ts +0 -74
- package/lib/types.d.ts +0 -61
- package/lib/web/consentomatic/index.js +0 -188
- package/lib/web/consentomatic/index.ts +0 -249
- package/lib/web/consentomatic/tools.js +0 -177
- package/lib/web/content-utils.js +0 -29
- package/lib/web/content-utils.ts +0 -31
- package/lib/web/content.js +0 -89
- package/lib/web/content.ts +0 -80
- package/lib/web/tab.js +0 -112
- package/lib/web/tab.ts +0 -178
- package/lib/web.js +0 -95
- package/tests/runner.ts +0 -61
|
@@ -1,86 +1,249 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
name: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type ConsentOMaticConfig = {
|
|
13
|
-
detectors: DetectorConfig[];
|
|
14
|
-
methods: MethodConfig[];
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export class ConsentOMaticCMP implements AutoCMP {
|
|
18
|
-
methods = new Map<string, {}>();
|
|
19
|
-
hasSelfTest: boolean;
|
|
20
|
-
|
|
21
|
-
constructor(public name: string, public config: ConsentOMaticConfig) {
|
|
22
|
-
config.methods.forEach(methodConfig => {
|
|
23
|
-
if (methodConfig.action) {
|
|
24
|
-
this.methods.set(methodConfig.name, methodConfig.action);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
this.hasSelfTest = this.methods.has("TEST_CONSENT");
|
|
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;
|
|
28
9
|
}
|
|
10
|
+
}
|
|
29
11
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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(config);
|
|
32
|
+
case "wait":
|
|
33
|
+
return waitAction(config);
|
|
34
|
+
case "eval":
|
|
35
|
+
return evalAction(config);
|
|
36
|
+
default:
|
|
37
|
+
throw "Unknown action type: " + config.type;
|
|
38
38
|
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const STEP_TIMEOUT = 0;
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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();
|
|
48
55
|
}
|
|
56
|
+
return waitTimeout(STEP_TIMEOUT);
|
|
57
|
+
}
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
59
|
+
async function listAction(config: any, param: any) {
|
|
60
|
+
for (let action of config.actions) {
|
|
61
|
+
await executeAction(action, param);
|
|
55
62
|
}
|
|
63
|
+
}
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
}
|
|
64
80
|
}
|
|
81
|
+
}
|
|
65
82
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
+
}
|
|
73
93
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
+
}
|
|
78
128
|
}
|
|
129
|
+
Tools.setBase(oldBase);
|
|
130
|
+
}
|
|
79
131
|
|
|
80
|
-
|
|
81
|
-
|
|
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;");
|
|
82
137
|
}
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
let targetBounds = result.target.getBoundingClientRect();
|
|
145
|
+
let 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
|
+
let screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
|
|
158
|
+
let screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
|
|
159
|
+
let clientX = targetBounds.left + targetBounds.width / 2.0;
|
|
160
|
+
let clientY = targetBounds.top + targetBounds.height / 2.0;
|
|
161
|
+
|
|
162
|
+
let 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
|
+
let 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
|
+
let 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);
|
|
85
221
|
}
|
|
86
222
|
}
|
|
223
|
+
|
|
224
|
+
async function waitAction(config: any) {
|
|
225
|
+
await waitTimeout(config.waitTime);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function closeAction(config: any) {
|
|
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
|
+
window.eval(config.code);
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
resolve(window.eval("window.__consentCheckResult"));
|
|
240
|
+
}, config.timeout || 250);
|
|
241
|
+
} else {
|
|
242
|
+
resolve(window.eval(config.code));
|
|
243
|
+
}
|
|
244
|
+
} catch (e) {
|
|
245
|
+
console.warn("eval error", e, config.code);
|
|
246
|
+
resolve(false);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ContentScriptMessage } from "./messages";
|
|
2
|
+
|
|
3
|
+
class Deferred<T> {
|
|
4
|
+
id: string;
|
|
5
|
+
promise: Promise<T>;
|
|
6
|
+
resolve: (value?: T) => void;
|
|
7
|
+
reject: (reason?: any) => void;
|
|
8
|
+
timer: number;
|
|
9
|
+
|
|
10
|
+
constructor(id: string, timeout = 1000) {
|
|
11
|
+
this.id = id;
|
|
12
|
+
this.promise = new Promise((resolve, reject) => {
|
|
13
|
+
this.resolve = resolve;
|
|
14
|
+
this.reject = reject;
|
|
15
|
+
});
|
|
16
|
+
this.timer = window.setTimeout(() => {
|
|
17
|
+
this.reject(new Error("timeout"));
|
|
18
|
+
}, timeout);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type EvalState = {
|
|
23
|
+
pending: Map<string, Deferred<boolean>>;
|
|
24
|
+
sendContentMessage: (message: ContentScriptMessage) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const evalState: EvalState = {
|
|
28
|
+
pending: new Map(),
|
|
29
|
+
sendContentMessage: null,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function requestEval(code: string): Promise<boolean> {
|
|
33
|
+
let id;
|
|
34
|
+
if (crypto && typeof crypto.randomUUID !== 'undefined') {
|
|
35
|
+
id = crypto.randomUUID();
|
|
36
|
+
} else {
|
|
37
|
+
id = Math.random().toString();
|
|
38
|
+
}
|
|
39
|
+
evalState.sendContentMessage({
|
|
40
|
+
type: 'eval',
|
|
41
|
+
id,
|
|
42
|
+
code,
|
|
43
|
+
});
|
|
44
|
+
const deferred = new Deferred<boolean>(id);
|
|
45
|
+
evalState.pending.set(deferred.id, deferred);
|
|
46
|
+
return deferred.promise;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function resolveEval(id: string, value: boolean) {
|
|
50
|
+
const deferred = evalState.pending.get(id);
|
|
51
|
+
if (deferred) {
|
|
52
|
+
evalState.pending.delete(id);
|
|
53
|
+
deferred.timer && window.clearTimeout(deferred.timer);
|
|
54
|
+
deferred.resolve(value);
|
|
55
|
+
} else {
|
|
56
|
+
console.warn('no eval #', id);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/lib/index.ts
CHANGED
package/lib/messages.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Config, RuleBundle } from "./types";
|
|
2
|
+
|
|
3
|
+
export type BackgroundMessage =
|
|
4
|
+
InitResponseMessage
|
|
5
|
+
| EvalResponseMessage
|
|
6
|
+
| OptOutMessage
|
|
7
|
+
| OptInMessage
|
|
8
|
+
| SelfTestMessage;
|
|
9
|
+
|
|
10
|
+
export type ContentScriptMessage =
|
|
11
|
+
InitMessage
|
|
12
|
+
| EvalMessage
|
|
13
|
+
| DetectedMessage
|
|
14
|
+
| FoundMessage
|
|
15
|
+
| OptOutResultMessage
|
|
16
|
+
| OptInResultMessage
|
|
17
|
+
| SelfTestResultMessage
|
|
18
|
+
| DoneMessage
|
|
19
|
+
| ErrorMessage;
|
|
20
|
+
|
|
21
|
+
export type InitMessage = {
|
|
22
|
+
type: "init";
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type EvalMessage = {
|
|
27
|
+
type: "eval";
|
|
28
|
+
id: string;
|
|
29
|
+
code: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type DetectedMessage = {
|
|
33
|
+
type: "cmpDetected";
|
|
34
|
+
cmp: string;
|
|
35
|
+
url: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type FoundMessage = {
|
|
39
|
+
type: "popupFound";
|
|
40
|
+
cmp: string;
|
|
41
|
+
url: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type OptOutResultMessage = {
|
|
45
|
+
type: "optOutResult";
|
|
46
|
+
cmp: string;
|
|
47
|
+
result: boolean;
|
|
48
|
+
scheduleSelfTest: boolean;
|
|
49
|
+
url: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type OptInResultMessage = {
|
|
53
|
+
type: "optInResult";
|
|
54
|
+
cmp: string;
|
|
55
|
+
result: boolean;
|
|
56
|
+
scheduleSelfTest: boolean;
|
|
57
|
+
url: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type SelfTestResultMessage = {
|
|
61
|
+
type: "selfTestResult";
|
|
62
|
+
cmp: string;
|
|
63
|
+
result: boolean;
|
|
64
|
+
url: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type DoneMessage = {
|
|
68
|
+
type: "autoconsentDone";
|
|
69
|
+
cmp: string;
|
|
70
|
+
url: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type ErrorMessage = {
|
|
74
|
+
type: "autoconsentError";
|
|
75
|
+
details: any;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type InitResponseMessage = {
|
|
79
|
+
type: "initResp";
|
|
80
|
+
rules: RuleBundle;
|
|
81
|
+
config: Config;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type EvalResponseMessage = {
|
|
85
|
+
type: "evalResp";
|
|
86
|
+
id: string;
|
|
87
|
+
result: any;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type OptOutMessage = {
|
|
91
|
+
type: "optOut";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type OptInMessage = {
|
|
95
|
+
type: "optIn";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type SelfTestMessage = {
|
|
99
|
+
type: "selfTest";
|
|
100
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { enableLogs } from "./config";
|
|
2
|
+
import { requestEval } from "./eval-handler";
|
|
3
|
+
import { HideMethod, VisibilityCheck } from "./rules";
|
|
4
|
+
import { getStyleElement, hideElements, isElementVisible, waitFor } from "./utils";
|
|
5
|
+
|
|
6
|
+
export function doEval(expr: string): Promise<boolean> {
|
|
7
|
+
return requestEval(expr).catch((e) => {
|
|
8
|
+
enableLogs && console.error('error evaluating rule', expr, e);
|
|
9
|
+
return false;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function click(selector: string, all = false): boolean {
|
|
14
|
+
const elem = document.querySelectorAll<HTMLElement>(selector);
|
|
15
|
+
enableLogs && console.log("[click]", selector, all, elem);
|
|
16
|
+
if (elem.length > 0) {
|
|
17
|
+
if (all) {
|
|
18
|
+
elem.forEach((e) => e.click());
|
|
19
|
+
} else {
|
|
20
|
+
elem[0].click();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return elem.length > 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function elementExists(selector: string): boolean {
|
|
27
|
+
const exists = document.querySelector(selector) !== null;
|
|
28
|
+
// enableLogs && console.log("[exists?]", selector, exists);
|
|
29
|
+
return exists;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function elementVisible(selector: string, check: VisibilityCheck): boolean {
|
|
33
|
+
const elem = document.querySelectorAll<HTMLElement>(selector);
|
|
34
|
+
const results = new Array(elem.length);
|
|
35
|
+
elem.forEach((e, i) => {
|
|
36
|
+
// check for display: none
|
|
37
|
+
results[i] = isElementVisible(e);
|
|
38
|
+
});
|
|
39
|
+
// enableLogs && console.log("[visible?]", selector, check, elem, results);
|
|
40
|
+
if (results.length === 0) {
|
|
41
|
+
return false;
|
|
42
|
+
} else if (check === "any") {
|
|
43
|
+
return results.some(r => r);
|
|
44
|
+
} else if (check === "none") {
|
|
45
|
+
return results.every(r => !r);
|
|
46
|
+
}
|
|
47
|
+
// all
|
|
48
|
+
return results.every(r => r);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function waitForElement(selector: string, timeout = 10000): Promise<boolean> {
|
|
52
|
+
const interval = 200;
|
|
53
|
+
const times = Math.ceil((timeout) / interval);
|
|
54
|
+
// enableLogs && console.log("[waitFor]", ruleStep.waitFor);
|
|
55
|
+
return waitFor(
|
|
56
|
+
() => document.querySelector(selector) !== null,
|
|
57
|
+
times,
|
|
58
|
+
interval
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function waitForVisible(selector: string, timeout = 10000, check: VisibilityCheck = 'any'): Promise<boolean> {
|
|
63
|
+
const interval = 200;
|
|
64
|
+
const times = Math.ceil((timeout) / interval);
|
|
65
|
+
// enableLogs && console.log("[waitForVisible]", ruleStep.waitFor);
|
|
66
|
+
return waitFor(
|
|
67
|
+
() => elementVisible(selector, check),
|
|
68
|
+
times,
|
|
69
|
+
interval
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function waitForThenClick(selector: string, timeout = 10000, all = false): Promise<boolean> {
|
|
74
|
+
// enableLogs && console.log("[waitForThenClick]", ruleStep.waitForThenClick);
|
|
75
|
+
await waitForElement(selector, timeout);
|
|
76
|
+
return click(selector, all);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function wait(ms: number): Promise<true> {
|
|
80
|
+
// enableLogs && console.log(`waiting for ${ruleStep.wait}ms`);
|
|
81
|
+
return new Promise(resolve => {
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
// enableLogs && console.log(`done waiting`);
|
|
84
|
+
resolve(true);
|
|
85
|
+
}, ms);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function hide(selectors: string[], method: HideMethod): boolean {
|
|
90
|
+
// enableLogs && console.log("[hide]", ruleStep.hide, ruleStep.method);
|
|
91
|
+
const styleEl = getStyleElement();
|
|
92
|
+
return hideElements(styleEl, selectors, method);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function prehide(selectors: string[]): boolean {
|
|
96
|
+
const styleEl = getStyleElement('autoconsent-prehide');
|
|
97
|
+
enableLogs && console.log("[prehide]", styleEl, location.href);
|
|
98
|
+
return hideElements(styleEl, selectors, "opacity");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function undoPrehide(): boolean {
|
|
102
|
+
const existingElement = getStyleElement('autoconsent-prehide');
|
|
103
|
+
enableLogs && console.log("[undoprehide]", existingElement, location.href);
|
|
104
|
+
if (existingElement) {
|
|
105
|
+
existingElement.remove();
|
|
106
|
+
}
|
|
107
|
+
return !!existingElement;
|
|
108
|
+
}
|
package/lib/rules.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export type AutoConsentCMPRule = {
|
|
2
|
+
name: string
|
|
3
|
+
prehideSelectors?: string[]
|
|
4
|
+
runContext?: RunContext,
|
|
5
|
+
intermediate?: boolean
|
|
6
|
+
detectCmp: AutoConsentRuleStep[]
|
|
7
|
+
detectPopup: AutoConsentRuleStep[]
|
|
8
|
+
optOut: AutoConsentRuleStep[]
|
|
9
|
+
optIn: AutoConsentRuleStep[]
|
|
10
|
+
openCmp?: AutoConsentRuleStep[]
|
|
11
|
+
test?: AutoConsentRuleStep[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type RunContext = {
|
|
15
|
+
main?: boolean,
|
|
16
|
+
frame?: boolean,
|
|
17
|
+
url?: string,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type AutoConsentRuleStep = { optional?: boolean } & Partial<
|
|
21
|
+
ElementExistsRule
|
|
22
|
+
> &
|
|
23
|
+
Partial<ElementVisibleRule> &
|
|
24
|
+
Partial<EvalRule> &
|
|
25
|
+
Partial<WaitForRule> &
|
|
26
|
+
Partial<WaitForVisibleRule> &
|
|
27
|
+
Partial<ClickRule> &
|
|
28
|
+
Partial<WaitForThenClickRule> &
|
|
29
|
+
Partial<WaitRule> &
|
|
30
|
+
Partial<UrlRule> &
|
|
31
|
+
Partial<HideRule>;
|
|
32
|
+
|
|
33
|
+
export type ElementExistsRule = {
|
|
34
|
+
exists: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type VisibilityCheck = "any" | "all" | "none";
|
|
38
|
+
|
|
39
|
+
export type ElementVisibleRule = {
|
|
40
|
+
visible: string;
|
|
41
|
+
check?: VisibilityCheck;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type EvalRule = {
|
|
45
|
+
eval: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type WaitForRule = {
|
|
49
|
+
waitFor: string;
|
|
50
|
+
timeout?: number;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type WaitForVisibleRule = {
|
|
54
|
+
waitForVisible: string;
|
|
55
|
+
timeout?: number;
|
|
56
|
+
check?: VisibilityCheck;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type ClickRule = {
|
|
60
|
+
click: string;
|
|
61
|
+
all?: boolean;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type WaitForThenClickRule = {
|
|
65
|
+
waitForThenClick: string;
|
|
66
|
+
timeout?: number;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type WaitRule = {
|
|
70
|
+
wait: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type UrlRule = {
|
|
74
|
+
url: string;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type HideMethod = 'display' | 'opacity';
|
|
78
|
+
|
|
79
|
+
export type HideRule = {
|
|
80
|
+
hide: string[];
|
|
81
|
+
method?: HideMethod;
|
|
82
|
+
};
|