@duckduckgo/autoconsent 5.0.0 → 5.0.1

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.
@@ -1,1967 +1,2009 @@
1
- (function () {
2
- 'use strict';
1
+ (() => {
2
+ // lib/config.ts
3
+ var enableLogs = false;
3
4
 
4
- const enableLogs = false; // change this to enable debug logs
5
+ // lib/random.ts
6
+ function getRandomID() {
7
+ if (crypto && typeof crypto.randomUUID !== "undefined") {
8
+ return crypto.randomUUID();
9
+ }
10
+ return Math.random().toString();
11
+ }
5
12
 
6
- function getRandomID() {
7
- if (crypto && typeof crypto.randomUUID !== "undefined") {
8
- return crypto.randomUUID();
9
- }
10
- return Math.random().toString();
13
+ // lib/eval-handler.ts
14
+ var Deferred = class {
15
+ constructor(id, timeout = 1e3) {
16
+ this.id = id;
17
+ this.promise = new Promise((resolve, reject) => {
18
+ this.resolve = resolve;
19
+ this.reject = reject;
20
+ });
21
+ this.timer = window.setTimeout(() => {
22
+ this.reject(new Error("timeout"));
23
+ }, timeout);
24
+ }
25
+ };
26
+ var evalState = {
27
+ pending: /* @__PURE__ */ new Map(),
28
+ sendContentMessage: null
29
+ };
30
+ function requestEval(code) {
31
+ const id = getRandomID();
32
+ evalState.sendContentMessage({
33
+ type: "eval",
34
+ id,
35
+ code
36
+ });
37
+ const deferred = new Deferred(id);
38
+ evalState.pending.set(deferred.id, deferred);
39
+ return deferred.promise;
40
+ }
41
+ function resolveEval(id, value) {
42
+ const deferred = evalState.pending.get(id);
43
+ if (deferred) {
44
+ evalState.pending.delete(id);
45
+ deferred.timer && window.clearTimeout(deferred.timer);
46
+ deferred.resolve(value);
47
+ } else {
48
+ console.warn("no eval #", id);
11
49
  }
50
+ }
12
51
 
13
- class Deferred {
14
- constructor(id, timeout = 1000) {
15
- this.id = id;
16
- this.promise = new Promise((resolve, reject) => {
17
- this.resolve = resolve;
18
- this.reject = reject;
19
- });
20
- this.timer = window.setTimeout(() => {
21
- this.reject(new Error("timeout"));
22
- }, timeout);
23
- }
52
+ // lib/utils.ts
53
+ function getStyleElement(styleOverrideElementId = "autoconsent-css-rules") {
54
+ const styleSelector = `style#${styleOverrideElementId}`;
55
+ const existingElement = document.querySelector(styleSelector);
56
+ if (existingElement && existingElement instanceof HTMLStyleElement) {
57
+ return existingElement;
58
+ } else {
59
+ const parent = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
60
+ const css = document.createElement("style");
61
+ css.id = styleOverrideElementId;
62
+ parent.appendChild(css);
63
+ return css;
24
64
  }
25
- const evalState = {
26
- pending: new Map(),
27
- sendContentMessage: null,
28
- };
29
- function requestEval(code) {
30
- const id = getRandomID();
31
- evalState.sendContentMessage({
32
- type: 'eval',
33
- id,
34
- code,
35
- });
36
- const deferred = new Deferred(id);
37
- evalState.pending.set(deferred.id, deferred);
38
- return deferred.promise;
39
- }
40
- function resolveEval(id, value) {
41
- const deferred = evalState.pending.get(id);
42
- if (deferred) {
43
- evalState.pending.delete(id);
44
- deferred.timer && window.clearTimeout(deferred.timer);
45
- deferred.resolve(value);
46
- }
47
- else {
48
- console.warn('no eval #', id);
49
- }
65
+ }
66
+ function hideElements(styleEl, selectors, method = "display") {
67
+ const hidingSnippet = method === "opacity" ? `opacity: 0` : `display: none`;
68
+ const rule = `${selectors.join(
69
+ ","
70
+ )} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
71
+ if (styleEl instanceof HTMLStyleElement) {
72
+ styleEl.innerText += rule;
73
+ return selectors.length > 0;
74
+ }
75
+ return false;
76
+ }
77
+ async function waitFor(predicate, maxTimes, interval) {
78
+ const result = await predicate();
79
+ if (!result && maxTimes > 0) {
80
+ return new Promise((resolve) => {
81
+ setTimeout(async () => {
82
+ resolve(waitFor(predicate, maxTimes - 1, interval));
83
+ }, interval);
84
+ });
85
+ }
86
+ return Promise.resolve(result);
87
+ }
88
+ function isElementVisible(elem) {
89
+ if (!elem) {
90
+ return false;
50
91
  }
92
+ if (elem.offsetParent !== null) {
93
+ return true;
94
+ } else {
95
+ const css = window.getComputedStyle(elem);
96
+ if (css.position === "fixed" && css.display !== "none") {
97
+ return true;
98
+ }
99
+ }
100
+ return false;
101
+ }
51
102
 
52
- // get or create a style container for CSS overrides
53
- function getStyleElement(styleOverrideElementId = "autoconsent-css-rules") {
54
- const styleSelector = `style#${styleOverrideElementId}`;
55
- const existingElement = document.querySelector(styleSelector);
56
- if (existingElement && existingElement instanceof HTMLStyleElement) {
57
- return existingElement;
58
- }
59
- else {
60
- const parent = document.head ||
61
- document.getElementsByTagName("head")[0] ||
62
- document.documentElement;
63
- const css = document.createElement("style");
64
- css.id = styleOverrideElementId;
65
- parent.appendChild(css);
66
- return css;
67
- }
103
+ // lib/rule-executors.ts
104
+ function doEval(expr) {
105
+ return requestEval(expr).catch((e) => {
106
+ enableLogs && console.error("error evaluating rule", expr, e);
107
+ return false;
108
+ });
109
+ }
110
+ function click(selector, all = false) {
111
+ const elem = elementSelector(selector);
112
+ enableLogs && console.log("[click]", selector, all, elem);
113
+ if (elem.length > 0) {
114
+ if (all) {
115
+ elem.forEach((e) => e.click());
116
+ } else {
117
+ elem[0].click();
118
+ }
68
119
  }
69
- // hide elements with a CSS rule
70
- function hideElements(styleEl, selectors, method = 'display') {
71
- const hidingSnippet = method === "opacity" ? `opacity: 0` : `display: none`; // use display by default
72
- const rule = `${selectors.join(",")} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
73
- if (styleEl instanceof HTMLStyleElement) {
74
- styleEl.innerText += rule;
75
- return selectors.length > 0;
76
- }
120
+ return elem.length > 0;
121
+ }
122
+ function elementExists(selector) {
123
+ const exists = elementSelector(selector).length > 0;
124
+ return exists;
125
+ }
126
+ function elementVisible(selector, check) {
127
+ const elem = elementSelector(selector);
128
+ const results = new Array(elem.length);
129
+ elem.forEach((e, i) => {
130
+ results[i] = isElementVisible(e);
131
+ });
132
+ if (check === "none") {
133
+ return results.every((r) => !r);
134
+ } else if (results.length === 0) {
135
+ return false;
136
+ } else if (check === "any") {
137
+ return results.some((r) => r);
138
+ }
139
+ return results.every((r) => r);
140
+ }
141
+ function waitForElement(selector, timeout = 1e4) {
142
+ const interval = 200;
143
+ const times = Math.ceil(timeout / interval);
144
+ return waitFor(
145
+ () => elementSelector(selector).length > 0,
146
+ times,
147
+ interval
148
+ );
149
+ }
150
+ function waitForVisible(selector, timeout = 1e4, check = "any") {
151
+ const interval = 200;
152
+ const times = Math.ceil(timeout / interval);
153
+ return waitFor(
154
+ () => elementVisible(selector, check),
155
+ times,
156
+ interval
157
+ );
158
+ }
159
+ async function waitForThenClick(selector, timeout = 1e4, all = false) {
160
+ await waitForElement(selector, timeout);
161
+ return click(selector, all);
162
+ }
163
+ function wait(ms) {
164
+ return new Promise((resolve) => {
165
+ setTimeout(() => {
166
+ resolve(true);
167
+ }, ms);
168
+ });
169
+ }
170
+ function hide(selectors, method) {
171
+ const styleEl = getStyleElement();
172
+ return hideElements(styleEl, selectors, method);
173
+ }
174
+ function prehide(selectors) {
175
+ const styleEl = getStyleElement("autoconsent-prehide");
176
+ enableLogs && console.log("[prehide]", styleEl, location.href);
177
+ return hideElements(styleEl, selectors, "opacity");
178
+ }
179
+ function undoPrehide() {
180
+ const existingElement = getStyleElement("autoconsent-prehide");
181
+ enableLogs && console.log("[undoprehide]", existingElement, location.href);
182
+ if (existingElement) {
183
+ existingElement.remove();
184
+ }
185
+ return !!existingElement;
186
+ }
187
+ function querySingleReplySelector(selector, parent = document) {
188
+ if (selector.startsWith("aria/")) {
189
+ return [];
190
+ }
191
+ if (selector.startsWith("xpath/")) {
192
+ const xpath = selector.slice(6);
193
+ const result = document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
194
+ let node = null;
195
+ const elements = [];
196
+ while (node = result.iterateNext()) {
197
+ elements.push(node);
198
+ }
199
+ return elements;
200
+ }
201
+ if (selector.startsWith("text/")) {
202
+ return [];
203
+ }
204
+ if (selector.startsWith("pierce/")) {
205
+ return [];
206
+ }
207
+ if (parent.shadowRoot) {
208
+ return Array.from(parent.shadowRoot.querySelectorAll(selector));
209
+ }
210
+ return Array.from(parent.querySelectorAll(selector));
211
+ }
212
+ function querySelectorChain(selectors) {
213
+ let parent = document;
214
+ let matches2;
215
+ for (const selector of selectors) {
216
+ matches2 = querySingleReplySelector(selector, parent);
217
+ if (matches2.length === 0) {
218
+ return [];
219
+ }
220
+ parent = matches2[0];
221
+ }
222
+ return matches2;
223
+ }
224
+ function elementSelector(selector) {
225
+ if (typeof selector === "string") {
226
+ return querySingleReplySelector(selector);
227
+ }
228
+ return querySelectorChain(selector);
229
+ }
230
+
231
+ // lib/cmps/base.ts
232
+ var defaultRunContext = {
233
+ main: true,
234
+ frame: false,
235
+ urlPattern: ""
236
+ };
237
+ var AutoConsentCMPBase = class {
238
+ constructor(name) {
239
+ this.runContext = defaultRunContext;
240
+ this.name = name;
241
+ }
242
+ get hasSelfTest() {
243
+ throw new Error("Not Implemented");
244
+ }
245
+ get isIntermediate() {
246
+ throw new Error("Not Implemented");
247
+ }
248
+ get isCosmetic() {
249
+ throw new Error("Not Implemented");
250
+ }
251
+ checkRunContext() {
252
+ const runCtx = {
253
+ ...defaultRunContext,
254
+ ...this.runContext
255
+ };
256
+ const isTop = window.top === window;
257
+ if (isTop && !runCtx.main) {
77
258
  return false;
259
+ }
260
+ if (!isTop && !runCtx.frame) {
261
+ return false;
262
+ }
263
+ if (runCtx.urlPattern && !window.location.href.match(runCtx.urlPattern)) {
264
+ return false;
265
+ }
266
+ return true;
78
267
  }
79
- async function waitFor(predicate, maxTimes, interval) {
80
- const result = await predicate();
81
- if (!result && maxTimes > 0) {
82
- return new Promise((resolve) => {
83
- setTimeout(async () => {
84
- resolve(waitFor(predicate, maxTimes - 1, interval));
85
- }, interval);
86
- });
87
- }
88
- return Promise.resolve(result);
268
+ detectCmp() {
269
+ throw new Error("Not Implemented");
89
270
  }
90
- function isElementVisible(elem) {
91
- if (!elem) {
92
- return false;
93
- }
94
- if (elem.offsetParent !== null) {
95
- return true;
96
- }
97
- else {
98
- const css = window.getComputedStyle(elem);
99
- if (css.position === 'fixed' && css.display !== "none") { // fixed elements may be visible even if the parent is not
100
- return true;
101
- }
271
+ async detectPopup() {
272
+ return false;
273
+ }
274
+ optOut() {
275
+ throw new Error("Not Implemented");
276
+ }
277
+ optIn() {
278
+ throw new Error("Not Implemented");
279
+ }
280
+ openCmp() {
281
+ throw new Error("Not Implemented");
282
+ }
283
+ async test() {
284
+ return Promise.resolve(true);
285
+ }
286
+ };
287
+ async function evaluateRuleStep(rule) {
288
+ const results = [];
289
+ if (rule.exists) {
290
+ results.push(elementExists(rule.exists));
291
+ }
292
+ if (rule.visible) {
293
+ results.push(elementVisible(rule.visible, rule.check));
294
+ }
295
+ if (rule.eval) {
296
+ const res = doEval(rule.eval);
297
+ results.push(res);
298
+ }
299
+ if (rule.waitFor) {
300
+ results.push(waitForElement(rule.waitFor, rule.timeout));
301
+ }
302
+ if (rule.waitForVisible) {
303
+ results.push(waitForVisible(rule.waitForVisible, rule.timeout, rule.check));
304
+ }
305
+ if (rule.click) {
306
+ results.push(click(rule.click, rule.all));
307
+ }
308
+ if (rule.waitForThenClick) {
309
+ results.push(waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
310
+ }
311
+ if (rule.wait) {
312
+ results.push(wait(rule.wait));
313
+ }
314
+ if (rule.hide) {
315
+ results.push(hide(rule.hide, rule.method));
316
+ }
317
+ if (rule.if) {
318
+ if (!rule.if.exists && !rule.if.visible) {
319
+ console.error("invalid conditional rule", rule.if);
320
+ return false;
321
+ }
322
+ const condition = await evaluateRuleStep(rule.if);
323
+ enableLogs && console.log("Condition is", condition);
324
+ if (condition) {
325
+ results.push(_runRulesSequentially(rule.then));
326
+ } else if (rule.else) {
327
+ results.push(_runRulesSequentially(rule.else));
328
+ }
329
+ }
330
+ if (rule.any) {
331
+ for (const step of rule.any) {
332
+ if (await evaluateRuleStep(step)) {
333
+ return true;
102
334
  }
335
+ }
336
+ return false;
337
+ }
338
+ if (results.length === 0) {
339
+ enableLogs && console.warn("Unrecognized rule", rule);
340
+ return false;
341
+ }
342
+ const all = await Promise.all(results);
343
+ return all.reduce((a, b) => a && b, true);
344
+ }
345
+ async function _runRulesParallel(rules3) {
346
+ const results = rules3.map((rule) => evaluateRuleStep(rule));
347
+ const detections = await Promise.all(results);
348
+ return detections.every((r) => !!r);
349
+ }
350
+ async function _runRulesSequentially(rules3) {
351
+ for (const rule of rules3) {
352
+ enableLogs && console.log("Running rule...", rule);
353
+ const result = await evaluateRuleStep(rule);
354
+ enableLogs && console.log("...rule result", result);
355
+ if (!result && !rule.optional) {
103
356
  return false;
357
+ }
104
358
  }
105
-
106
- function doEval(expr) {
107
- return requestEval(expr).catch((e) => {
108
- return false;
109
- });
359
+ return true;
360
+ }
361
+ var AutoConsentCMP = class extends AutoConsentCMPBase {
362
+ constructor(config) {
363
+ super(config.name);
364
+ this.config = config;
365
+ this.runContext = config.runContext || defaultRunContext;
110
366
  }
111
- function click(selector, all = false) {
112
- const elem = elementSelector(selector);
113
- if (elem.length > 0) {
114
- if (all) {
115
- elem.forEach((e) => e.click());
116
- }
117
- else {
118
- elem[0].click();
119
- }
120
- }
121
- return elem.length > 0;
122
- }
123
- function elementExists(selector) {
124
- const exists = elementSelector(selector).length > 0;
125
- // enableLogs && console.log("[exists?]", selector, exists);
126
- return exists;
127
- }
128
- function elementVisible(selector, check) {
129
- const elem = elementSelector(selector);
130
- const results = new Array(elem.length);
131
- elem.forEach((e, i) => {
132
- // check for display: none
133
- results[i] = isElementVisible(e);
134
- });
135
- // enableLogs && console.log("[visible?]", selector, check, elem, results);
136
- if (check === "none") {
137
- return results.every(r => !r);
138
- }
139
- else if (results.length === 0) {
140
- return false;
141
- }
142
- else if (check === "any") {
143
- return results.some(r => r);
144
- }
145
- // all
146
- return results.every(r => r);
147
- }
148
- function waitForElement(selector, timeout = 10000) {
149
- const interval = 200;
150
- const times = Math.ceil((timeout) / interval);
151
- // enableLogs && console.log("[waitFor]", ruleStep.waitFor);
152
- return waitFor(() => elementSelector(selector).length > 0, times, interval);
153
- }
154
- function waitForVisible(selector, timeout = 10000, check = 'any') {
155
- const interval = 200;
156
- const times = Math.ceil((timeout) / interval);
157
- // enableLogs && console.log("[waitForVisible]", ruleStep.waitFor);
158
- return waitFor(() => elementVisible(selector, check), times, interval);
159
- }
160
- async function waitForThenClick(selector, timeout = 10000, all = false) {
161
- // enableLogs && console.log("[waitForThenClick]", ruleStep.waitForThenClick);
162
- await waitForElement(selector, timeout);
163
- return click(selector, all);
164
- }
165
- function wait(ms) {
166
- // enableLogs && console.log(`waiting for ${ruleStep.wait}ms`);
167
- return new Promise(resolve => {
168
- setTimeout(() => {
169
- // enableLogs && console.log(`done waiting`);
170
- resolve(true);
171
- }, ms);
172
- });
367
+ get hasSelfTest() {
368
+ return !!this.config.test;
173
369
  }
174
- function hide(selectors, method) {
175
- // enableLogs && console.log("[hide]", ruleStep.hide, ruleStep.method);
176
- const styleEl = getStyleElement();
177
- return hideElements(styleEl, selectors, method);
370
+ get isIntermediate() {
371
+ return !!this.config.intermediate;
178
372
  }
179
- function prehide(selectors) {
180
- const styleEl = getStyleElement('autoconsent-prehide');
181
- return hideElements(styleEl, selectors, "opacity");
373
+ get isCosmetic() {
374
+ return !!this.config.cosmetic;
182
375
  }
183
- function undoPrehide() {
184
- const existingElement = getStyleElement('autoconsent-prehide');
185
- if (existingElement) {
186
- existingElement.remove();
187
- }
188
- return !!existingElement;
376
+ get prehideSelectors() {
377
+ return this.config.prehideSelectors;
189
378
  }
190
- function querySingleReplySelector(selector, parent = document) {
191
- if (selector.startsWith('aria/')) {
192
- return [];
193
- }
194
- if (selector.startsWith('xpath/')) {
195
- const xpath = selector.slice(6);
196
- const result = document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
197
- let node = null;
198
- const elements = [];
199
- // eslint-disable-next-line no-cond-assign
200
- while (node = result.iterateNext()) {
201
- elements.push(node);
202
- }
203
- return elements;
204
- }
205
- if (selector.startsWith('text/')) {
206
- return [];
207
- }
208
- if (selector.startsWith('pierce/')) {
209
- return [];
210
- }
211
- if (parent.shadowRoot) {
212
- return Array.from(parent.shadowRoot.querySelectorAll(selector));
213
- }
214
- return Array.from(parent.querySelectorAll(selector));
215
- }
216
- function querySelectorChain(selectors) {
217
- let parent = document;
218
- let matches;
219
- for (const selector of selectors) {
220
- matches = querySingleReplySelector(selector, parent);
221
- if (matches.length === 0) {
222
- return [];
223
- }
224
- parent = matches[0];
225
- }
226
- return matches;
379
+ async detectCmp() {
380
+ if (this.config.detectCmp) {
381
+ return _runRulesParallel(this.config.detectCmp);
382
+ }
383
+ return false;
227
384
  }
228
- function elementSelector(selector) {
229
- if (typeof selector === 'string') {
230
- return querySingleReplySelector(selector);
231
- }
232
- return querySelectorChain(selector);
385
+ async detectPopup() {
386
+ if (this.config.detectPopup) {
387
+ return _runRulesSequentially(this.config.detectPopup);
388
+ }
389
+ return false;
390
+ }
391
+ async optOut() {
392
+ if (this.config.optOut) {
393
+ enableLogs && console.log("Initiated optOut()", this.config.optOut);
394
+ return _runRulesSequentially(this.config.optOut);
395
+ }
396
+ return false;
397
+ }
398
+ async optIn() {
399
+ if (this.config.optIn) {
400
+ enableLogs && console.log("Initiated optIn()", this.config.optIn);
401
+ return _runRulesSequentially(this.config.optIn);
402
+ }
403
+ return false;
233
404
  }
405
+ async openCmp() {
406
+ if (this.config.openCmp) {
407
+ return _runRulesSequentially(this.config.openCmp);
408
+ }
409
+ return false;
410
+ }
411
+ async test() {
412
+ if (this.hasSelfTest) {
413
+ return _runRulesSequentially(this.config.test);
414
+ }
415
+ return super.test();
416
+ }
417
+ };
234
418
 
235
- /* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
236
- const defaultRunContext = {
419
+ // lib/cmps/trustarc-top.ts
420
+ var cookieSettingsButton = "#truste-show-consent";
421
+ var shortcutOptOut = "#truste-consent-required";
422
+ var shortcutOptIn = "#truste-consent-button";
423
+ var popupContent = "#truste-consent-content";
424
+ var bannerOverlay = "#trustarc-banner-overlay";
425
+ var bannerContainer = "#truste-consent-track";
426
+ var TrustArcTop = class extends AutoConsentCMPBase {
427
+ constructor() {
428
+ super("TrustArc-top");
429
+ this.prehideSelectors = [
430
+ ".trustarc-banner-container",
431
+ `.truste_popframe,.truste_overlay,.truste_box_overlay,${bannerContainer}`
432
+ ];
433
+ this.runContext = {
237
434
  main: true,
238
- frame: false,
239
- urlPattern: "",
240
- };
241
- class AutoConsentCMPBase {
242
- constructor(name) {
243
- this.runContext = defaultRunContext;
244
- this.name = name;
245
- }
246
- get hasSelfTest() {
247
- throw new Error('Not Implemented');
248
- }
249
- get isIntermediate() {
250
- throw new Error('Not Implemented');
251
- }
252
- get isCosmetic() {
253
- throw new Error('Not Implemented');
254
- }
255
- checkRunContext() {
256
- const runCtx = {
257
- ...defaultRunContext,
258
- ...this.runContext,
259
- };
260
- const isTop = window.top === window;
261
- if (isTop && !runCtx.main) {
262
- return false;
263
- }
264
- if (!isTop && !runCtx.frame) {
265
- return false;
266
- }
267
- if (runCtx.urlPattern && !window.location.href.match(runCtx.urlPattern)) {
268
- return false;
269
- }
270
- return true;
271
- }
272
- detectCmp() {
273
- throw new Error('Not Implemented');
274
- }
275
- async detectPopup() {
276
- return false;
277
- }
278
- optOut() {
279
- throw new Error('Not Implemented');
280
- }
281
- optIn() {
282
- throw new Error('Not Implemented');
283
- }
284
- openCmp() {
285
- throw new Error('Not Implemented');
286
- }
287
- async test() {
288
- // try IAB by default
289
- return Promise.resolve(true);
290
- }
435
+ frame: false
436
+ };
437
+ this._shortcutButton = null;
438
+ this._optInDone = false;
291
439
  }
292
- async function evaluateRuleStep(rule) {
293
- const results = [];
294
- if (rule.exists) {
295
- results.push(elementExists(rule.exists));
296
- }
297
- if (rule.visible) {
298
- results.push(elementVisible(rule.visible, rule.check));
299
- }
300
- if (rule.eval) {
301
- const res = doEval(rule.eval);
302
- results.push(res);
303
- }
304
- if (rule.waitFor) {
305
- results.push(waitForElement(rule.waitFor, rule.timeout));
306
- }
307
- if (rule.waitForVisible) {
308
- results.push(waitForVisible(rule.waitForVisible, rule.timeout, rule.check));
309
- }
310
- if (rule.click) {
311
- results.push(click(rule.click, rule.all));
312
- }
313
- if (rule.waitForThenClick) {
314
- results.push(waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
315
- }
316
- if (rule.wait) {
317
- results.push(wait(rule.wait));
318
- }
319
- if (rule.hide) {
320
- results.push(hide(rule.hide, rule.method));
321
- }
322
- if (rule.if) {
323
- if (!rule.if.exists && !rule.if.visible) {
324
- console.error('invalid conditional rule', rule.if);
325
- return false;
326
- }
327
- const condition = await evaluateRuleStep(rule.if);
328
- if (condition) {
329
- results.push(_runRulesSequentially(rule.then));
330
- }
331
- else if (rule.else) {
332
- results.push(_runRulesSequentially(rule.else));
333
- }
334
- }
335
- if (rule.any) {
336
- for (const step of rule.any) {
337
- if (await evaluateRuleStep(step)) {
338
- return true;
339
- }
340
- }
341
- return false;
342
- }
343
- if (results.length === 0) {
344
- return false;
345
- }
346
- // boolean and of results
347
- const all = await Promise.all(results);
348
- return all.reduce((a, b) => a && b, true);
349
- }
350
- async function _runRulesParallel(rules) {
351
- const results = rules.map(rule => evaluateRuleStep(rule));
352
- const detections = await Promise.all(results);
353
- return detections.every(r => !!r);
354
- }
355
- async function _runRulesSequentially(rules) {
356
- for (const rule of rules) {
357
- const result = await evaluateRuleStep(rule);
358
- if (!result && !rule.optional) {
359
- return false;
360
- }
361
- }
440
+ get hasSelfTest() {
441
+ return false;
442
+ }
443
+ get isIntermediate() {
444
+ if (this._optInDone) {
445
+ return false;
446
+ }
447
+ return !this._shortcutButton;
448
+ }
449
+ get isCosmetic() {
450
+ return false;
451
+ }
452
+ async detectCmp() {
453
+ const result = elementExists(`${cookieSettingsButton},${bannerContainer}`);
454
+ if (result) {
455
+ this._shortcutButton = document.querySelector(shortcutOptOut);
456
+ }
457
+ return result;
458
+ }
459
+ async detectPopup() {
460
+ return elementVisible(`${popupContent},${bannerOverlay},${bannerContainer}`, "all");
461
+ }
462
+ openFrame() {
463
+ click(cookieSettingsButton);
464
+ }
465
+ async optOut() {
466
+ if (this._shortcutButton) {
467
+ this._shortcutButton.click();
362
468
  return true;
469
+ }
470
+ hideElements(
471
+ getStyleElement(),
472
+ [".truste_popframe", ".truste_overlay", ".truste_box_overlay", bannerContainer]
473
+ );
474
+ click(cookieSettingsButton);
475
+ setTimeout(() => {
476
+ getStyleElement().remove();
477
+ }, 1e4);
478
+ return true;
363
479
  }
364
- class AutoConsentCMP extends AutoConsentCMPBase {
365
- constructor(config) {
366
- super(config.name);
367
- this.config = config;
368
- this.runContext = config.runContext || defaultRunContext;
369
- }
370
- get hasSelfTest() {
371
- return !!this.config.test;
372
- }
373
- get isIntermediate() {
374
- return !!this.config.intermediate;
375
- }
376
- get isCosmetic() {
377
- return !!this.config.cosmetic;
378
- }
379
- get prehideSelectors() {
380
- return this.config.prehideSelectors;
381
- }
382
- async detectCmp() {
383
- if (this.config.detectCmp) {
384
- return _runRulesParallel(this.config.detectCmp);
385
- }
386
- return false;
387
- }
388
- async detectPopup() {
389
- if (this.config.detectPopup) {
390
- return _runRulesSequentially(this.config.detectPopup);
391
- }
392
- return false;
393
- }
394
- async optOut() {
395
- if (this.config.optOut) {
396
- return _runRulesSequentially(this.config.optOut);
397
- }
398
- return false;
399
- }
400
- async optIn() {
401
- if (this.config.optIn) {
402
- return _runRulesSequentially(this.config.optIn);
403
- }
404
- return false;
405
- }
406
- async openCmp() {
407
- if (this.config.openCmp) {
408
- return _runRulesSequentially(this.config.openCmp);
409
- }
410
- return false;
411
- }
412
- async test() {
413
- if (this.hasSelfTest) {
414
- return _runRulesSequentially(this.config.test);
415
- }
416
- return super.test();
417
- }
480
+ async optIn() {
481
+ this._optInDone = true;
482
+ return click(shortcutOptIn);
418
483
  }
419
-
420
- const cookieSettingsButton = "#truste-show-consent";
421
- const shortcutOptOut = '#truste-consent-required';
422
- const shortcutOptIn = '#truste-consent-button';
423
- const popupContent = '#truste-consent-content';
424
- const bannerOverlay = '#trustarc-banner-overlay';
425
- const bannerContainer = '#truste-consent-track';
426
- class TrustArcTop extends AutoConsentCMPBase {
427
- constructor() {
428
- super("TrustArc-top");
429
- this.prehideSelectors = [
430
- ".trustarc-banner-container",
431
- `.truste_popframe,.truste_overlay,.truste_box_overlay,${bannerContainer}`,
432
- ];
433
- this.runContext = {
434
- main: true,
435
- frame: false,
436
- };
437
- this._shortcutButton = null; // indicates if the "reject all" button is detected
438
- this._optInDone = false;
439
- }
440
- get hasSelfTest() {
441
- return false;
442
- }
443
- get isIntermediate() {
444
- if (this._optInDone) {
445
- return false;
446
- }
447
- return !this._shortcutButton;
448
- }
449
- get isCosmetic() {
450
- return false;
451
- }
452
- async detectCmp() {
453
- const result = elementExists(`${cookieSettingsButton},${bannerContainer}`);
454
- if (result) {
455
- // additionally detect the opt-out button
456
- this._shortcutButton = document.querySelector(shortcutOptOut);
457
- }
458
- return result;
459
- }
460
- async detectPopup() {
461
- // not every element should exist, but if it does, it's a popup
462
- return elementVisible(`${popupContent},${bannerOverlay},${bannerContainer}`, 'all');
463
- }
464
- openFrame() {
465
- click(cookieSettingsButton);
466
- }
467
- async optOut() {
468
- if (this._shortcutButton) {
469
- this._shortcutButton.click();
470
- return true;
471
- }
472
- // hide elements permanently, so user doesn't see the popup
473
- hideElements(getStyleElement(), [".truste_popframe", ".truste_overlay", ".truste_box_overlay", bannerContainer]);
474
- click(cookieSettingsButton);
475
- // schedule cleanup
476
- setTimeout(() => {
477
- getStyleElement().remove();
478
- }, 10000);
479
- return true;
480
- }
481
- async optIn() {
482
- this._optInDone = true; // just a hack to force autoconsentDone
483
- return click(shortcutOptIn);
484
- }
485
- async openCmp() {
486
- // await tab.eval("truste.eu.clickListener()");
487
- return true;
488
- }
489
- async test() {
490
- //Test JS variable to check the user's preference
491
- //PrefCookie = undefined means no consent is set, PrefCookie = '0' means consent is set to required only
492
- return await doEval("window && window.truste && window.truste.eu.bindMap.prefCookie === '0'");
493
- }
484
+ async openCmp() {
485
+ return true;
494
486
  }
495
-
496
- class TrustArcFrame extends AutoConsentCMPBase {
497
- constructor() {
498
- super("TrustArc-frame");
499
- this.runContext = {
500
- main: false,
501
- frame: true,
502
- urlPattern: "^https://consent-pref\\.trustarc\\.com/\\?",
503
- };
504
- }
505
- get hasSelfTest() {
506
- return false;
507
- }
508
- get isIntermediate() {
509
- return false;
510
- }
511
- get isCosmetic() {
512
- return false;
513
- }
514
- async detectCmp() {
515
- return true;
516
- }
517
- async detectPopup() {
518
- // we're already inside the popup
519
- return elementVisible("#defaultpreferencemanager", 'any') && elementVisible(".mainContent", 'any');
520
- }
521
- async navigateToSettings() {
522
- // wait for it to load
523
- await waitFor(async () => {
524
- return (elementExists(".shp") ||
525
- elementVisible(".advance", 'any') ||
526
- elementExists(".switch span:first-child"));
527
- }, 10, 500);
528
- // splash screen -> hit more information
529
- if (elementExists(".shp")) {
530
- click(".shp");
531
- }
532
- await waitForElement(".prefPanel", 5000);
533
- // go to advanced settings if not yet shown
534
- if (elementVisible(".advance", 'any')) {
535
- click(".advance");
536
- }
537
- // takes a while to load the opt-in/opt-out buttons
538
- return await waitFor(() => elementVisible(".switch span:first-child", 'any'), 5, 1000);
539
- }
540
- async optOut() {
541
- await waitFor(() => document.readyState === 'complete', 20, 100);
542
- await waitForElement(".mainContent[aria-hidden=false]", 5000);
543
- if (click(".rejectAll")) {
544
- return true;
545
- }
546
- if (elementExists('.prefPanel')) {
547
- await waitForElement('.prefPanel[style="visibility: visible;"]', 3000);
548
- }
549
- if (click("#catDetails0")) {
550
- click(".submit");
551
- return true;
552
- }
553
- if (click(".required")) {
554
- return true;
555
- }
556
- await this.navigateToSettings();
557
- click(".switch span:nth-child(1):not(.active)", true);
558
- click(".submit");
559
- // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
560
- waitForElement("#gwt-debug-close_id", 300000).then(() => {
561
- click("#gwt-debug-close_id");
562
- });
563
- return true;
564
- }
565
- async optIn() {
566
- if (click('.call')) {
567
- return true;
568
- }
569
- await this.navigateToSettings();
570
- click(".switch span:nth-child(2)", true);
571
- click(".submit");
572
- // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
573
- waitForElement("#gwt-debug-close_id", 300000).then(() => {
574
- click("#gwt-debug-close_id");
575
- });
576
- return true;
577
- }
487
+ async test() {
488
+ return await doEval("window && window.truste && window.truste.eu.bindMap.prefCookie === '0'");
578
489
  }
490
+ };
579
491
 
580
- class Cookiebot extends AutoConsentCMPBase {
581
- constructor() {
582
- super('Cybotcookiebot');
583
- this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"];
584
- }
585
- get hasSelfTest() {
586
- return true;
587
- }
588
- get isIntermediate() {
589
- return false;
590
- }
591
- get isCosmetic() {
592
- return false;
593
- }
594
- async detectCmp() {
595
- return elementExists('#CybotCookiebotDialogBodyLevelButtonPreferences');
596
- }
597
- async detectPopup() {
598
- return elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
599
- }
600
- async optOut() {
601
- if (click('.cookie-alert-extended-detail-link')) {
602
- await waitForElement('.cookie-alert-configuration', 2000);
603
- click('.cookie-alert-configuration-input:checked', true);
604
- click('.cookie-alert-extended-button-secondary');
605
- return true;
606
- }
607
- if (elementExists('#dtcookie-container')) {
608
- return click('.h-dtcookie-decline');
609
- }
610
- if (click('.cookiebot__button--settings')) {
611
- return true;
612
- }
613
- if (click('#CybotCookiebotDialogBodyButtonDecline')) {
614
- return true;
615
- }
616
- click('.cookiebanner__link--details');
617
- click('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled', true);
618
- click('#CybotCookiebotDialogBodyButtonDecline');
619
- click('input[id^=CybotCookiebotDialogBodyLevelButton]:checked', true);
620
- if (elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
621
- click('#CybotCookiebotDialogBodyButtonAcceptSelected');
622
- }
623
- else {
624
- click('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection', true);
625
- }
626
- // some sites have custom submit buttons with no obvious selectors. In this case we just call the submitConsent API.
627
- if (await doEval('window.CookieConsent.hasResponse !== true')) {
628
- await doEval('window.Cookiebot.dialog.submitConsent()');
629
- await wait(500);
630
- }
631
- // site with 3rd confirm settings modal
632
- if (elementExists('#cb-confirmedSettings')) {
633
- await doEval('endCookieProcess()');
634
- }
635
- return true;
636
- }
637
- async optIn() {
638
- if (elementExists('#dtcookie-container')) {
639
- return click('.h-dtcookie-accept');
640
- }
641
- click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
642
- click('#CybotCookiebotDialogBodyLevelButtonAccept');
643
- click('#CybotCookiebotDialogBodyButtonAccept');
644
- return true;
645
- }
646
- async test() {
647
- return doEval('window.CookieConsent.declined === true');
648
- }
492
+ // lib/cmps/trustarc-frame.ts
493
+ var TrustArcFrame = class extends AutoConsentCMPBase {
494
+ constructor() {
495
+ super("TrustArc-frame");
496
+ this.runContext = {
497
+ main: false,
498
+ frame: true,
499
+ urlPattern: "^https://consent-pref\\.trustarc\\.com/\\?"
500
+ };
501
+ }
502
+ get hasSelfTest() {
503
+ return false;
504
+ }
505
+ get isIntermediate() {
506
+ return false;
649
507
  }
508
+ get isCosmetic() {
509
+ return false;
510
+ }
511
+ async detectCmp() {
512
+ return true;
513
+ }
514
+ async detectPopup() {
515
+ return elementVisible("#defaultpreferencemanager", "any") && elementVisible(".mainContent", "any");
516
+ }
517
+ async navigateToSettings() {
518
+ await waitFor(
519
+ async () => {
520
+ return elementExists(".shp") || elementVisible(".advance", "any") || elementExists(".switch span:first-child");
521
+ },
522
+ 10,
523
+ 500
524
+ );
525
+ if (elementExists(".shp")) {
526
+ click(".shp");
527
+ }
528
+ await waitForElement(".prefPanel", 5e3);
529
+ if (elementVisible(".advance", "any")) {
530
+ click(".advance");
531
+ }
532
+ return await waitFor(
533
+ () => elementVisible(".switch span:first-child", "any"),
534
+ 5,
535
+ 1e3
536
+ );
537
+ }
538
+ async optOut() {
539
+ await waitFor(() => document.readyState === "complete", 20, 100);
540
+ await waitForElement(".mainContent[aria-hidden=false]", 5e3);
541
+ if (click(".rejectAll")) {
542
+ return true;
543
+ }
544
+ if (elementExists(".prefPanel")) {
545
+ await waitForElement('.prefPanel[style="visibility: visible;"]', 3e3);
546
+ }
547
+ if (click("#catDetails0")) {
548
+ click(".submit");
549
+ return true;
550
+ }
551
+ if (click(".required")) {
552
+ return true;
553
+ }
554
+ await this.navigateToSettings();
555
+ click(".switch span:nth-child(1):not(.active)", true);
556
+ click(".submit");
557
+ waitForElement("#gwt-debug-close_id", 3e5).then(() => {
558
+ click("#gwt-debug-close_id");
559
+ });
560
+ return true;
561
+ }
562
+ async optIn() {
563
+ if (click(".call")) {
564
+ return true;
565
+ }
566
+ await this.navigateToSettings();
567
+ click(".switch span:nth-child(2)", true);
568
+ click(".submit");
569
+ waitForElement("#gwt-debug-close_id", 3e5).then(() => {
570
+ click("#gwt-debug-close_id");
571
+ });
572
+ return true;
573
+ }
574
+ };
650
575
 
651
- class SourcePoint extends AutoConsentCMPBase {
652
- constructor() {
653
- super("Sourcepoint-frame");
654
- this.prehideSelectors = ["div[id^='sp_message_container_'],.message-overlay", '#sp_privacy_manager_container'];
655
- this.ccpaNotice = false;
656
- this.ccpaPopup = false;
657
- this.runContext = {
658
- main: false,
659
- frame: true,
660
- };
661
- }
662
- get hasSelfTest() {
663
- return false; // self-test is done by parent frame
664
- }
665
- get isIntermediate() {
666
- return false;
667
- }
668
- get isCosmetic() {
669
- return false;
670
- }
671
- async detectCmp() {
672
- const url = new URL(location.href);
673
- if (url.searchParams.has('message_id') && url.hostname === 'ccpa-notice.sp-prod.net') {
674
- this.ccpaNotice = true;
675
- return true;
676
- }
677
- if (url.hostname === 'ccpa-pm.sp-prod.net') {
678
- this.ccpaPopup = true;
679
- return true;
680
- }
681
- return (url.pathname === '/index.html' || url.pathname === '/privacy-manager/index.html')
682
- && (url.searchParams.has('message_id') || url.searchParams.has('requestUUID') || url.searchParams.has('consentUUID'));
683
- }
684
- async detectPopup() {
685
- if (this.ccpaNotice) {
686
- return true;
687
- }
688
- if (this.ccpaPopup) {
689
- return await waitForElement('.priv-save-btn', 2000);
690
- }
691
- // check for the paywall button, and bail if it exists to prevent broken opt out
692
- await waitForElement(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL", 2000);
693
- return !elementExists('.sp_choice_type_9');
694
- }
695
- async optIn() {
696
- await waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL", 2000);
697
- if (click(".sp_choice_type_11")) {
698
- return true;
699
- }
700
- if (click('.sp_choice_type_ACCEPT_ALL')) {
701
- return true;
702
- }
703
- return false;
704
- }
705
- isManagerOpen() {
706
- return location.pathname === "/privacy-manager/index.html";
707
- }
708
- async optOut() {
709
- if (this.ccpaPopup) {
710
- // toggles with 2 buttons
711
- const toggles = document.querySelectorAll('.priv-purpose-container .sp-switch-arrow-block a.neutral.on .right');
712
- for (const t of toggles) {
713
- t.click();
714
- }
715
- // switch toggles
716
- const switches = document.querySelectorAll('.priv-purpose-container .sp-switch-arrow-block a.switch-bg.on');
717
- for (const t of switches) {
718
- t.click();
719
- }
720
- return click('.priv-save-btn');
721
- }
722
- if (!this.isManagerOpen()) {
723
- const actionable = await waitForElement('.sp_choice_type_12,.sp_choice_type_13');
724
- if (!actionable) {
725
- return false;
726
- }
727
- if (!elementExists(".sp_choice_type_12")) {
728
- // do not sell button
729
- return click(".sp_choice_type_13");
730
- }
731
- click(".sp_choice_type_12");
732
- // the page may navigate at this point but that's okay
733
- await waitFor(() => this.isManagerOpen(), 200, 100);
734
- }
735
- await waitForElement('.type-modal', 20000);
736
- // reject all button is offered by some sites
737
- try {
738
- const rejectSelector1 = '.sp_choice_type_REJECT_ALL';
739
- const rejectSelector2 = '.reject-toggle';
740
- const path = await Promise.race([
741
- waitForElement(rejectSelector1, 2000).then(success => success ? 0 : -1),
742
- waitForElement(rejectSelector2, 2000).then(success => success ? 1 : -1),
743
- waitForElement('.pm-features', 2000).then(success => success ? 2 : -1),
744
- ]);
745
- if (path === 0) {
746
- await wait(1000);
747
- return click(rejectSelector1);
748
- }
749
- else if (path === 1) {
750
- click(rejectSelector2);
751
- }
752
- else if (path === 2) {
753
- await waitForElement('.pm-features', 10000);
754
- click('.checked > span', true);
755
- click('.chevron');
756
- }
757
- }
758
- catch (e) {
759
- }
760
- // TODO: race condition: the popup disappears very quickly, so the background script may not receive a success report.
761
- return click('.sp_choice_type_SAVE_AND_EXIT');
762
- }
576
+ // lib/cmps/cookiebot.ts
577
+ var Cookiebot = class extends AutoConsentCMPBase {
578
+ constructor() {
579
+ super("Cybotcookiebot");
580
+ this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"];
581
+ }
582
+ get hasSelfTest() {
583
+ return true;
584
+ }
585
+ get isIntermediate() {
586
+ return false;
587
+ }
588
+ get isCosmetic() {
589
+ return false;
763
590
  }
591
+ async detectCmp() {
592
+ return elementExists("#CybotCookiebotDialogBodyLevelButtonPreferences");
593
+ }
594
+ async detectPopup() {
595
+ return elementExists("#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner");
596
+ }
597
+ async optOut() {
598
+ if (click(".cookie-alert-extended-detail-link")) {
599
+ await waitForElement(".cookie-alert-configuration", 2e3);
600
+ click(".cookie-alert-configuration-input:checked", true);
601
+ click(".cookie-alert-extended-button-secondary");
602
+ return true;
603
+ }
604
+ if (elementExists("#dtcookie-container")) {
605
+ return click(".h-dtcookie-decline");
606
+ }
607
+ if (click(".cookiebot__button--settings")) {
608
+ return true;
609
+ }
610
+ if (click("#CybotCookiebotDialogBodyButtonDecline")) {
611
+ return true;
612
+ }
613
+ click(".cookiebanner__link--details");
614
+ click('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled', true);
615
+ click("#CybotCookiebotDialogBodyButtonDecline");
616
+ click("input[id^=CybotCookiebotDialogBodyLevelButton]:checked", true);
617
+ if (elementExists("#CybotCookiebotDialogBodyButtonAcceptSelected")) {
618
+ click("#CybotCookiebotDialogBodyButtonAcceptSelected");
619
+ } else {
620
+ click("#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection", true);
621
+ }
622
+ if (await doEval("window.CookieConsent.hasResponse !== true")) {
623
+ await doEval("window.Cookiebot.dialog.submitConsent()");
624
+ await wait(500);
625
+ }
626
+ if (elementExists("#cb-confirmedSettings")) {
627
+ await doEval("endCookieProcess()");
628
+ }
629
+ return true;
630
+ }
631
+ async optIn() {
632
+ if (elementExists("#dtcookie-container")) {
633
+ return click(".h-dtcookie-accept");
634
+ }
635
+ click(".CybotCookiebotDialogBodyLevelButton:not(:checked):enabled", true);
636
+ click("#CybotCookiebotDialogBodyLevelButtonAccept");
637
+ click("#CybotCookiebotDialogBodyButtonAccept");
638
+ return true;
639
+ }
640
+ async test() {
641
+ return doEval("window.CookieConsent.declined === true");
642
+ }
643
+ };
764
644
 
765
- // Note: JS API is also available:
766
- // https://help.consentmanager.net/books/cmp/page/javascript-api
767
- class ConsentManager extends AutoConsentCMPBase {
768
- get hasSelfTest() {
769
- return this.apiAvailable;
770
- }
771
- get isIntermediate() {
772
- return false;
773
- }
774
- get isCosmetic() {
775
- return false;
776
- }
777
- constructor() {
778
- super("consentmanager.net");
779
- this.prehideSelectors = ["#cmpbox,#cmpbox2"];
780
- this.apiAvailable = false;
781
- }
782
- async detectCmp() {
783
- this.apiAvailable = await doEval('window.__cmp && typeof __cmp("getCMPData") === "object"');
784
- if (!this.apiAvailable) {
785
- return elementExists("#cmpbox");
786
- }
787
- else {
788
- return true;
789
- }
790
- }
791
- async detectPopup() {
792
- if (this.apiAvailable) {
793
- // wait before making this check because early in the page lifecycle this may incorrectly return
794
- // true, causing an opt-out when it is not needed.
795
- await wait(500);
796
- return await doEval("!__cmp('consentStatus').userChoiceExists");
797
- }
798
- return elementVisible("#cmpbox .cmpmore", 'any');
799
- }
800
- async optOut() {
801
- await wait(500);
802
- if (this.apiAvailable) {
803
- return await doEval("__cmp('setConsent', 0)");
804
- }
805
- if (click(".cmpboxbtnno")) {
806
- return true;
807
- }
808
- if (elementExists(".cmpwelcomeprpsbtn")) {
809
- click(".cmpwelcomeprpsbtn > a[aria-checked=true]", true);
810
- click(".cmpboxbtnsave");
811
- return true;
812
- }
813
- click(".cmpboxbtncustom");
814
- await waitForElement(".cmptblbox", 2000);
815
- click(".cmptdchoice > a[aria-checked=true]", true);
816
- click(".cmpboxbtnyescustomchoices");
817
- return true;
818
- }
819
- async optIn() {
820
- if (this.apiAvailable) {
821
- return await doEval("__cmp('setConsent', 1)");
822
- }
823
- return click(".cmpboxbtnyes");
824
- }
825
- async test() {
826
- if (this.apiAvailable) {
827
- return await doEval("__cmp('consentStatus').userChoiceExists");
828
- }
829
- }
645
+ // lib/cmps/sourcepoint-frame.ts
646
+ var SourcePoint = class extends AutoConsentCMPBase {
647
+ constructor() {
648
+ super("Sourcepoint-frame");
649
+ this.prehideSelectors = ["div[id^='sp_message_container_'],.message-overlay", "#sp_privacy_manager_container"];
650
+ this.ccpaNotice = false;
651
+ this.ccpaPopup = false;
652
+ this.runContext = {
653
+ main: false,
654
+ frame: true
655
+ };
656
+ }
657
+ get hasSelfTest() {
658
+ return false;
659
+ }
660
+ get isIntermediate() {
661
+ return false;
662
+ }
663
+ get isCosmetic() {
664
+ return false;
665
+ }
666
+ async detectCmp() {
667
+ const url = new URL(location.href);
668
+ if (url.searchParams.has("message_id") && url.hostname === "ccpa-notice.sp-prod.net") {
669
+ this.ccpaNotice = true;
670
+ return true;
671
+ }
672
+ if (url.hostname === "ccpa-pm.sp-prod.net") {
673
+ this.ccpaPopup = true;
674
+ return true;
675
+ }
676
+ return (url.pathname === "/index.html" || url.pathname === "/privacy-manager/index.html") && (url.searchParams.has("message_id") || url.searchParams.has("requestUUID") || url.searchParams.has("consentUUID"));
830
677
  }
678
+ async detectPopup() {
679
+ if (this.ccpaNotice) {
680
+ return true;
681
+ }
682
+ if (this.ccpaPopup) {
683
+ return await waitForElement(".priv-save-btn", 2e3);
684
+ }
685
+ await waitForElement(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL", 2e3);
686
+ return !elementExists(".sp_choice_type_9");
687
+ }
688
+ async optIn() {
689
+ await waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL", 2e3);
690
+ if (click(".sp_choice_type_11")) {
691
+ return true;
692
+ }
693
+ if (click(".sp_choice_type_ACCEPT_ALL")) {
694
+ return true;
695
+ }
696
+ return false;
697
+ }
698
+ isManagerOpen() {
699
+ return location.pathname === "/privacy-manager/index.html";
700
+ }
701
+ async optOut() {
702
+ if (this.ccpaPopup) {
703
+ const toggles = document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.neutral.on .right");
704
+ for (const t of toggles) {
705
+ t.click();
706
+ }
707
+ const switches = document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.switch-bg.on");
708
+ for (const t of switches) {
709
+ t.click();
710
+ }
711
+ return click(".priv-save-btn");
712
+ }
713
+ if (!this.isManagerOpen()) {
714
+ const actionable = await waitForElement(".sp_choice_type_12,.sp_choice_type_13");
715
+ if (!actionable) {
716
+ return false;
717
+ }
718
+ if (!elementExists(".sp_choice_type_12")) {
719
+ return click(".sp_choice_type_13");
720
+ }
721
+ click(".sp_choice_type_12");
722
+ await waitFor(
723
+ () => this.isManagerOpen(),
724
+ 200,
725
+ 100
726
+ );
727
+ }
728
+ await waitForElement(".type-modal", 2e4);
729
+ try {
730
+ const rejectSelector1 = ".sp_choice_type_REJECT_ALL";
731
+ const rejectSelector2 = ".reject-toggle";
732
+ const path = await Promise.race([
733
+ waitForElement(rejectSelector1, 2e3).then((success) => success ? 0 : -1),
734
+ waitForElement(rejectSelector2, 2e3).then((success) => success ? 1 : -1),
735
+ waitForElement(".pm-features", 2e3).then((success) => success ? 2 : -1)
736
+ ]);
737
+ if (path === 0) {
738
+ await wait(1e3);
739
+ return click(rejectSelector1);
740
+ } else if (path === 1) {
741
+ click(rejectSelector2);
742
+ } else if (path === 2) {
743
+ await waitForElement(".pm-features", 1e4);
744
+ click(".checked > span", true);
745
+ click(".chevron");
746
+ }
747
+ } catch (e) {
748
+ enableLogs && console.warn(e);
749
+ }
750
+ return click(".sp_choice_type_SAVE_AND_EXIT");
751
+ }
752
+ };
831
753
 
832
- class Evidon extends AutoConsentCMPBase {
833
- constructor() {
834
- super("Evidon");
835
- }
836
- get hasSelfTest() {
837
- return false;
838
- }
839
- get isIntermediate() {
840
- return false;
841
- }
842
- get isCosmetic() {
843
- return false;
844
- }
845
- async detectCmp() {
846
- return elementExists("#_evidon_banner");
847
- }
848
- async detectPopup() {
849
- return elementVisible("#_evidon_banner", 'any');
850
- }
851
- async optOut() {
852
- if (click("#_evidon-decline-button")) {
853
- return true;
854
- }
855
- hideElements(getStyleElement(), ["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"]);
856
- click("#_evidon-option-button");
857
- await waitForElement("#evidon-prefdiag-overlay", 5000);
858
- click("#evidon-prefdiag-decline");
859
- return true;
860
- }
861
- async optIn() {
862
- return click("#_evidon-accept-button");
863
- }
754
+ // lib/cmps/consentmanager.ts
755
+ var ConsentManager = class extends AutoConsentCMPBase {
756
+ constructor() {
757
+ super("consentmanager.net");
758
+ this.prehideSelectors = ["#cmpbox,#cmpbox2"];
759
+ this.apiAvailable = false;
760
+ }
761
+ get hasSelfTest() {
762
+ return this.apiAvailable;
763
+ }
764
+ get isIntermediate() {
765
+ return false;
766
+ }
767
+ get isCosmetic() {
768
+ return false;
769
+ }
770
+ async detectCmp() {
771
+ this.apiAvailable = await doEval('window.__cmp && typeof __cmp("getCMPData") === "object"');
772
+ if (!this.apiAvailable) {
773
+ return elementExists("#cmpbox");
774
+ } else {
775
+ return true;
776
+ }
777
+ }
778
+ async detectPopup() {
779
+ if (this.apiAvailable) {
780
+ await wait(500);
781
+ return await doEval("!__cmp('consentStatus').userChoiceExists");
782
+ }
783
+ return elementVisible("#cmpbox .cmpmore", "any");
864
784
  }
785
+ async optOut() {
786
+ await wait(500);
787
+ if (this.apiAvailable) {
788
+ return await doEval("__cmp('setConsent', 0)");
789
+ }
790
+ if (click(".cmpboxbtnno")) {
791
+ return true;
792
+ }
793
+ if (elementExists(".cmpwelcomeprpsbtn")) {
794
+ click(".cmpwelcomeprpsbtn > a[aria-checked=true]", true);
795
+ click(".cmpboxbtnsave");
796
+ return true;
797
+ }
798
+ click(".cmpboxbtncustom");
799
+ await waitForElement(".cmptblbox", 2e3);
800
+ click(".cmptdchoice > a[aria-checked=true]", true);
801
+ click(".cmpboxbtnyescustomchoices");
802
+ return true;
803
+ }
804
+ async optIn() {
805
+ if (this.apiAvailable) {
806
+ return await doEval("__cmp('setConsent', 1)");
807
+ }
808
+ return click(".cmpboxbtnyes");
809
+ }
810
+ async test() {
811
+ if (this.apiAvailable) {
812
+ return await doEval("__cmp('consentStatus').userChoiceExists");
813
+ }
814
+ }
815
+ };
865
816
 
866
- class Onetrust extends AutoConsentCMPBase {
867
- constructor() {
868
- super("Onetrust");
869
- this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"];
870
- this.runContext = {
871
- urlPattern: '^(?!.*https://www\\.nba\\.com/)'
872
- };
873
- }
874
- get hasSelfTest() {
875
- return true;
876
- }
877
- get isIntermediate() {
878
- return false;
879
- }
880
- get isCosmetic() {
881
- return false;
882
- }
883
- async detectCmp() {
884
- return elementExists("#onetrust-banner-sdk");
885
- }
886
- async detectPopup() {
887
- return elementVisible("#onetrust-banner-sdk", 'all');
888
- }
889
- async optOut() {
890
- if (elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
891
- click("#onetrust-pc-btn-handler");
892
- }
893
- else { // otherwise look for a generic "show settings" button
894
- click(".ot-sdk-show-settings,button.js-cookie-settings");
895
- }
896
- await waitForElement('#onetrust-consent-sdk', 2000);
897
- await wait(1000);
898
- click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked", true); // optional step
899
- await wait(1000);
900
- await waitForElement(".save-preference-btn-handler,.js-consent-save", 2000);
901
- click(".save-preference-btn-handler,.js-consent-save");
902
- // popup doesn't disappear immediately
903
- await waitFor(() => elementVisible("#onetrust-banner-sdk", 'none'), 10, 500);
904
- return true;
905
- }
906
- async optIn() {
907
- return click("#onetrust-accept-btn-handler,.js-accept-cookies");
908
- }
909
- async test() {
910
- return await doEval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
911
- }
817
+ // lib/cmps/evidon.ts
818
+ var Evidon = class extends AutoConsentCMPBase {
819
+ constructor() {
820
+ super("Evidon");
821
+ }
822
+ get hasSelfTest() {
823
+ return false;
824
+ }
825
+ get isIntermediate() {
826
+ return false;
827
+ }
828
+ get isCosmetic() {
829
+ return false;
830
+ }
831
+ async detectCmp() {
832
+ return elementExists("#_evidon_banner");
833
+ }
834
+ async detectPopup() {
835
+ return elementVisible("#_evidon_banner", "any");
912
836
  }
837
+ async optOut() {
838
+ if (click("#_evidon-decline-button")) {
839
+ return true;
840
+ }
841
+ hideElements(getStyleElement(), ["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"]);
842
+ click("#_evidon-option-button");
843
+ await waitForElement("#evidon-prefdiag-overlay", 5e3);
844
+ click("#evidon-prefdiag-decline");
845
+ return true;
846
+ }
847
+ async optIn() {
848
+ return click("#_evidon-accept-button");
849
+ }
850
+ };
913
851
 
914
- class Klaro extends AutoConsentCMPBase {
915
- constructor() {
916
- super("Klaro");
917
- this.prehideSelectors = [".klaro"];
918
- this.settingsOpen = false;
919
- }
920
- get hasSelfTest() {
921
- return true;
922
- }
923
- get isIntermediate() {
924
- return false;
925
- }
926
- get isCosmetic() {
927
- return false;
928
- }
929
- async detectCmp() {
930
- if (elementExists('.klaro > .cookie-modal')) {
931
- this.settingsOpen = true;
932
- return true;
933
- }
934
- return elementExists(".klaro > .cookie-notice");
935
- }
936
- async detectPopup() {
937
- return elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal", 'any');
938
- }
939
- async optOut() {
940
- if (click('.klaro .cn-decline')) {
941
- return true;
942
- }
943
- if (!this.settingsOpen) {
944
- click('.klaro .cn-learn-more');
945
- await waitForElement('.klaro > .cookie-modal', 2000);
946
- this.settingsOpen = true;
947
- }
948
- if (click('.klaro .cn-decline')) {
949
- return true;
950
- }
951
- click('.cm-purpose:not(.cm-toggle-all) > input:not(.half-checked)', true);
952
- return click('.cm-btn-accept');
953
- }
954
- async optIn() {
955
- if (click('.klaro .cm-btn-accept-all')) {
956
- return true;
957
- }
958
- if (this.settingsOpen) {
959
- click('.cm-purpose:not(.cm-toggle-all) > input.half-checked', true);
960
- return click('.cm-btn-accept');
961
- }
962
- return click('.klaro .cookie-notice .cm-btn-success');
963
- }
964
- async test() {
965
- return await doEval('klaro.getManager().config.services.every(c => c.required || !klaro.getManager().consents[c.name])');
966
- }
852
+ // lib/cmps/onetrust.ts
853
+ var Onetrust = class extends AutoConsentCMPBase {
854
+ constructor() {
855
+ super("Onetrust");
856
+ this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"];
857
+ this.runContext = {
858
+ urlPattern: "^(?!.*https://www\\.nba\\.com/)"
859
+ };
860
+ }
861
+ get hasSelfTest() {
862
+ return true;
863
+ }
864
+ get isIntermediate() {
865
+ return false;
866
+ }
867
+ get isCosmetic() {
868
+ return false;
967
869
  }
870
+ async detectCmp() {
871
+ return elementExists("#onetrust-banner-sdk");
872
+ }
873
+ async detectPopup() {
874
+ return elementVisible("#onetrust-banner-sdk", "all");
875
+ }
876
+ async optOut() {
877
+ if (elementExists("#onetrust-pc-btn-handler")) {
878
+ click("#onetrust-pc-btn-handler");
879
+ } else {
880
+ click(".ot-sdk-show-settings,button.js-cookie-settings");
881
+ }
882
+ await waitForElement("#onetrust-consent-sdk", 2e3);
883
+ await wait(1e3);
884
+ click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked", true);
885
+ await wait(1e3);
886
+ await waitForElement(".save-preference-btn-handler,.js-consent-save", 2e3);
887
+ click(".save-preference-btn-handler,.js-consent-save");
888
+ await waitFor(
889
+ () => elementVisible("#onetrust-banner-sdk", "none"),
890
+ 10,
891
+ 500
892
+ );
893
+ return true;
894
+ }
895
+ async optIn() {
896
+ return click("#onetrust-accept-btn-handler,.js-accept-cookies");
897
+ }
898
+ async test() {
899
+ return await doEval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
900
+ }
901
+ };
968
902
 
969
- class Uniconsent extends AutoConsentCMPBase {
970
- constructor() {
971
- super("Uniconsent");
972
- }
973
- get prehideSelectors() {
974
- return ['.unic', '.modal:has(.unic)'];
975
- }
976
- get hasSelfTest() {
977
- return true;
978
- }
979
- get isIntermediate() {
980
- return false;
981
- }
982
- get isCosmetic() {
983
- return false;
984
- }
985
- async detectCmp() {
986
- return elementExists(".unic .unic-box,.unic .unic-bar");
987
- }
988
- async detectPopup() {
989
- return elementVisible(".unic .unic-box,.unic .unic-bar", 'any');
990
- }
991
- async optOut() {
992
- await waitForElement(".unic button", 1000);
993
- document.querySelectorAll(".unic button").forEach((button) => {
994
- const text = button.textContent;
995
- if (text.includes('Manage Options') || text.includes('Optionen verwalten')) {
996
- button.click();
997
- }
998
- });
999
- if (await waitForElement('.unic input[type=checkbox]', 1000)) {
1000
- await waitForElement('.unic button', 1000);
1001
- document.querySelectorAll('.unic input[type=checkbox]').forEach((c) => {
1002
- if (c.checked) {
1003
- c.click();
1004
- }
1005
- });
1006
- for (const b of document.querySelectorAll('.unic button')) {
1007
- const text = b.textContent;
1008
- for (const pattern of ['Confirm Choices', 'Save Choices', 'Auswahl speichern']) {
1009
- if (text.includes(pattern)) {
1010
- b.click();
1011
- await wait(500); // give it some time to close the popup
1012
- return true;
1013
- }
1014
- }
1015
- }
1016
- }
1017
- return false;
1018
- }
1019
- async optIn() {
1020
- return waitForThenClick(".unic #unic-agree");
1021
- }
1022
- async test() {
1023
- await wait(1000);
1024
- const res = elementExists(".unic .unic-box,.unic .unic-bar");
1025
- return !res;
1026
- }
903
+ // lib/cmps/klaro.ts
904
+ var Klaro = class extends AutoConsentCMPBase {
905
+ constructor() {
906
+ super("Klaro");
907
+ this.prehideSelectors = [".klaro"];
908
+ this.settingsOpen = false;
909
+ }
910
+ get hasSelfTest() {
911
+ return true;
912
+ }
913
+ get isIntermediate() {
914
+ return false;
915
+ }
916
+ get isCosmetic() {
917
+ return false;
1027
918
  }
919
+ async detectCmp() {
920
+ if (elementExists(".klaro > .cookie-modal")) {
921
+ this.settingsOpen = true;
922
+ return true;
923
+ }
924
+ return elementExists(".klaro > .cookie-notice");
925
+ }
926
+ async detectPopup() {
927
+ return elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal", "any");
928
+ }
929
+ async optOut() {
930
+ if (click(".klaro .cn-decline")) {
931
+ return true;
932
+ }
933
+ if (!this.settingsOpen) {
934
+ click(".klaro .cn-learn-more");
935
+ await waitForElement(".klaro > .cookie-modal", 2e3);
936
+ this.settingsOpen = true;
937
+ }
938
+ if (click(".klaro .cn-decline")) {
939
+ return true;
940
+ }
941
+ click(".cm-purpose:not(.cm-toggle-all) > input:not(.half-checked)", true);
942
+ return click(".cm-btn-accept");
943
+ }
944
+ async optIn() {
945
+ if (click(".klaro .cm-btn-accept-all")) {
946
+ return true;
947
+ }
948
+ if (this.settingsOpen) {
949
+ click(".cm-purpose:not(.cm-toggle-all) > input.half-checked", true);
950
+ return click(".cm-btn-accept");
951
+ }
952
+ return click(".klaro .cookie-notice .cm-btn-success");
953
+ }
954
+ async test() {
955
+ return await doEval("klaro.getManager().config.services.every(c => c.required || !klaro.getManager().consents[c.name])");
956
+ }
957
+ };
1028
958
 
1029
- class Conversant extends AutoConsentCMPBase {
1030
- constructor() {
1031
- super("Conversant");
1032
- this.prehideSelectors = [".cmp-root"];
1033
- }
1034
- get hasSelfTest() {
1035
- return true;
1036
- }
1037
- get isIntermediate() {
1038
- return false;
1039
- }
1040
- get isCosmetic() {
1041
- return false;
1042
- }
1043
- async detectCmp() {
1044
- return elementExists(".cmp-root .cmp-receptacle");
1045
- }
1046
- async detectPopup() {
1047
- return elementVisible(".cmp-root .cmp-receptacle", 'any');
1048
- }
1049
- async optOut() {
1050
- if (!(await waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)"))) {
1051
- return false;
1052
- }
1053
- if (!(await waitForElement(".cmp-view-tab-tabs"))) {
1054
- return false;
1055
- }
1056
- await waitForThenClick(".cmp-view-tab-tabs > :first-child");
1057
- await waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");
1058
- for (const item of Array.from(document.querySelectorAll('.cmp-accordion-item'))) {
1059
- item.querySelector('.cmp-accordion-item-title').click();
1060
- await waitFor(() => !!item.querySelector('.cmp-accordion-item-content.cmp-active'), 10, 50);
1061
- const content = item.querySelector('.cmp-accordion-item-content.cmp-active');
1062
- content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)').forEach((e) => e.click());
1063
- content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)').forEach((e) => e.click());
1064
- // await waitFor(() => !item.querySelector('.cmp-toggle-deny--active,.cmp-toggle-checkbox--active'), 5, 50); // this may take a long time
1065
- }
1066
- await click(".cmp-main-button:not(.cmp-main-button--primary)");
1067
- return true;
1068
- }
1069
- async optIn() {
1070
- return waitForThenClick(".cmp-main-button.cmp-main-button--primary");
1071
- }
1072
- async test() {
1073
- return document.cookie.includes('cmp-data=0');
1074
- }
959
+ // lib/cmps/uniconsent.ts
960
+ var Uniconsent = class extends AutoConsentCMPBase {
961
+ constructor() {
962
+ super("Uniconsent");
963
+ }
964
+ get prehideSelectors() {
965
+ return [".unic", ".modal:has(.unic)"];
966
+ }
967
+ get hasSelfTest() {
968
+ return true;
969
+ }
970
+ get isIntermediate() {
971
+ return false;
1075
972
  }
973
+ get isCosmetic() {
974
+ return false;
975
+ }
976
+ async detectCmp() {
977
+ return elementExists(".unic .unic-box,.unic .unic-bar");
978
+ }
979
+ async detectPopup() {
980
+ return elementVisible(".unic .unic-box,.unic .unic-bar", "any");
981
+ }
982
+ async optOut() {
983
+ await waitForElement(".unic button", 1e3);
984
+ document.querySelectorAll(".unic button").forEach((button) => {
985
+ const text = button.textContent;
986
+ if (text.includes("Manage Options") || text.includes("Optionen verwalten")) {
987
+ button.click();
988
+ }
989
+ });
990
+ if (await waitForElement(".unic input[type=checkbox]", 1e3)) {
991
+ await waitForElement(".unic button", 1e3);
992
+ document.querySelectorAll(".unic input[type=checkbox]").forEach((c) => {
993
+ if (c.checked) {
994
+ c.click();
995
+ }
996
+ });
997
+ for (const b of document.querySelectorAll(".unic button")) {
998
+ const text = b.textContent;
999
+ for (const pattern of ["Confirm Choices", "Save Choices", "Auswahl speichern"]) {
1000
+ if (text.includes(pattern)) {
1001
+ b.click();
1002
+ await wait(500);
1003
+ return true;
1004
+ }
1005
+ }
1006
+ }
1007
+ }
1008
+ return false;
1009
+ }
1010
+ async optIn() {
1011
+ return waitForThenClick(".unic #unic-agree");
1012
+ }
1013
+ async test() {
1014
+ await wait(1e3);
1015
+ const res = elementExists(".unic .unic-box,.unic .unic-bar");
1016
+ return !res;
1017
+ }
1018
+ };
1076
1019
 
1077
- class Tiktok extends AutoConsentCMPBase {
1078
- constructor() {
1079
- super("tiktok.com");
1080
- this.runContext = {
1081
- urlPattern: 'tiktok'
1082
- };
1083
- }
1084
- get hasSelfTest() {
1085
- return true;
1086
- }
1087
- get isIntermediate() {
1088
- return false;
1089
- }
1090
- get isCosmetic() {
1091
- return false;
1092
- }
1093
- getShadowRoot() {
1094
- const container = document.querySelector('tiktok-cookie-banner');
1095
- if (!container) {
1096
- return null;
1097
- }
1098
- return container.shadowRoot;
1099
- }
1100
- async detectCmp() {
1101
- return elementExists("tiktok-cookie-banner");
1102
- }
1103
- async detectPopup() {
1104
- const banner = this.getShadowRoot().querySelector('.tiktok-cookie-banner');
1105
- return isElementVisible(banner);
1106
- }
1107
- async optOut() {
1108
- const declineButton = this.getShadowRoot().querySelector('.button-wrapper button:first-child');
1109
- if (declineButton) {
1110
- declineButton.click();
1111
- return true;
1112
- }
1113
- else {
1114
- return false;
1115
- }
1116
- }
1117
- async optIn() {
1118
- const acceptButton = this.getShadowRoot().querySelector('.button-wrapper button:last-child');
1119
- if (acceptButton) {
1120
- acceptButton.click();
1121
- return true;
1122
- }
1123
- else {
1124
- return false;
1125
- }
1126
- }
1127
- async test() {
1128
- const match = document.cookie.match(/cookie-consent=([^;]+)/);
1129
- if (!match) {
1130
- return false;
1131
- }
1132
- const value = JSON.parse(decodeURIComponent(match[1]));
1133
- return Object.values(value).every(x => typeof x !== 'boolean' || x === false);
1134
- }
1020
+ // lib/cmps/conversant.ts
1021
+ var Conversant = class extends AutoConsentCMPBase {
1022
+ constructor() {
1023
+ super("Conversant");
1024
+ this.prehideSelectors = [".cmp-root"];
1025
+ }
1026
+ get hasSelfTest() {
1027
+ return true;
1135
1028
  }
1029
+ get isIntermediate() {
1030
+ return false;
1031
+ }
1032
+ get isCosmetic() {
1033
+ return false;
1034
+ }
1035
+ async detectCmp() {
1036
+ return elementExists(".cmp-root .cmp-receptacle");
1037
+ }
1038
+ async detectPopup() {
1039
+ return elementVisible(".cmp-root .cmp-receptacle", "any");
1040
+ }
1041
+ async optOut() {
1042
+ if (!await waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)")) {
1043
+ return false;
1044
+ }
1045
+ if (!await waitForElement(".cmp-view-tab-tabs")) {
1046
+ return false;
1047
+ }
1048
+ await waitForThenClick(".cmp-view-tab-tabs > :first-child");
1049
+ await waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");
1050
+ for (const item of Array.from(document.querySelectorAll(".cmp-accordion-item"))) {
1051
+ item.querySelector(".cmp-accordion-item-title").click();
1052
+ await waitFor(() => !!item.querySelector(".cmp-accordion-item-content.cmp-active"), 10, 50);
1053
+ const content = item.querySelector(".cmp-accordion-item-content.cmp-active");
1054
+ content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e) => e.click());
1055
+ content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e) => e.click());
1056
+ }
1057
+ await click(".cmp-main-button:not(.cmp-main-button--primary)");
1058
+ return true;
1059
+ }
1060
+ async optIn() {
1061
+ return waitForThenClick(".cmp-main-button.cmp-main-button--primary");
1062
+ }
1063
+ async test() {
1064
+ return document.cookie.includes("cmp-data=0");
1065
+ }
1066
+ };
1136
1067
 
1137
- class Airbnb extends AutoConsentCMPBase {
1138
- constructor() {
1139
- super("airbnb");
1140
- this.runContext = {
1141
- urlPattern: '^https://(www\\.)?airbnb\\.[^/]+/'
1142
- };
1143
- this.prehideSelectors = [
1144
- "div[data-testid=main-cookies-banner-container]",
1145
- "div:has(> div:first-child):has(> div:last-child):has(> section [data-testid=\"strictly-necessary-cookies\"])"
1146
- ];
1147
- }
1148
- get hasSelfTest() {
1149
- return true;
1150
- }
1151
- get isIntermediate() {
1152
- return false;
1153
- }
1154
- get isCosmetic() {
1155
- return false;
1156
- }
1157
- async detectCmp() {
1158
- return elementExists('div[data-testid=main-cookies-banner-container]');
1159
- }
1160
- async detectPopup() {
1161
- return elementVisible('div[data-testid=main-cookies-banner-container', 'any');
1162
- }
1163
- async optOut() {
1164
- await waitForThenClick('div[data-testid=main-cookies-banner-container] button._snbhip0');
1165
- let check;
1166
- // eslint-disable-next-line no-cond-assign
1167
- while (check = document.querySelector('[data-testid=modal-container] button[aria-checked=true]:not([disabled])')) { // each click may toggle multiple checkboxes
1168
- check.click();
1169
- }
1170
- return waitForThenClick('button[data-testid=save-btn]');
1171
- }
1172
- async optIn() {
1173
- return waitForThenClick('div[data-testid=main-cookies-banner-container] button._148dgdpk');
1174
- }
1175
- async test() {
1176
- return await waitFor(() => !!document.cookie.match('OptanonAlertBoxClosed'), 20, 200);
1177
- }
1068
+ // lib/cmps/tiktok.ts
1069
+ var Tiktok = class extends AutoConsentCMPBase {
1070
+ constructor() {
1071
+ super("tiktok.com");
1072
+ this.runContext = {
1073
+ urlPattern: "tiktok"
1074
+ };
1075
+ }
1076
+ get hasSelfTest() {
1077
+ return true;
1078
+ }
1079
+ get isIntermediate() {
1080
+ return false;
1081
+ }
1082
+ get isCosmetic() {
1083
+ return false;
1084
+ }
1085
+ getShadowRoot() {
1086
+ const container = document.querySelector("tiktok-cookie-banner");
1087
+ if (!container) {
1088
+ return null;
1089
+ }
1090
+ return container.shadowRoot;
1091
+ }
1092
+ async detectCmp() {
1093
+ return elementExists("tiktok-cookie-banner");
1094
+ }
1095
+ async detectPopup() {
1096
+ const banner = this.getShadowRoot().querySelector(".tiktok-cookie-banner");
1097
+ return isElementVisible(banner);
1098
+ }
1099
+ async optOut() {
1100
+ const declineButton = this.getShadowRoot().querySelector(".button-wrapper button:first-child");
1101
+ if (declineButton) {
1102
+ enableLogs && console.log("[clicking]", declineButton);
1103
+ declineButton.click();
1104
+ return true;
1105
+ } else {
1106
+ enableLogs && console.log("no decline button found");
1107
+ return false;
1108
+ }
1109
+ }
1110
+ async optIn() {
1111
+ const acceptButton = this.getShadowRoot().querySelector(".button-wrapper button:last-child");
1112
+ if (acceptButton) {
1113
+ enableLogs && console.log("[clicking]", acceptButton);
1114
+ acceptButton.click();
1115
+ return true;
1116
+ } else {
1117
+ enableLogs && console.log("no accept button found");
1118
+ return false;
1119
+ }
1120
+ }
1121
+ async test() {
1122
+ const match = document.cookie.match(/cookie-consent=([^;]+)/);
1123
+ if (!match) {
1124
+ return false;
1125
+ }
1126
+ const value = JSON.parse(decodeURIComponent(match[1]));
1127
+ return Object.values(value).every((x) => typeof x !== "boolean" || x === false);
1178
1128
  }
1129
+ };
1179
1130
 
1180
- const rules$1 = [
1181
- new TrustArcTop(),
1182
- new TrustArcFrame(),
1183
- new Cookiebot(),
1184
- new SourcePoint(),
1185
- new ConsentManager(),
1186
- new Evidon(),
1187
- new Onetrust(),
1188
- new Klaro(),
1189
- new Uniconsent(),
1190
- new Conversant(),
1191
- new Tiktok(),
1192
- new Airbnb(),
1193
- ];
1194
- function createAutoCMP(config) {
1195
- return new AutoConsentCMP(config);
1131
+ // lib/cmps/airbnb.ts
1132
+ var Airbnb = class extends AutoConsentCMPBase {
1133
+ constructor() {
1134
+ super("airbnb");
1135
+ this.runContext = {
1136
+ urlPattern: "^https://(www\\.)?airbnb\\.[^/]+/"
1137
+ };
1138
+ this.prehideSelectors = [
1139
+ "div[data-testid=main-cookies-banner-container]",
1140
+ 'div:has(> div:first-child):has(> div:last-child):has(> section [data-testid="strictly-necessary-cookies"])'
1141
+ ];
1142
+ }
1143
+ get hasSelfTest() {
1144
+ return true;
1145
+ }
1146
+ get isIntermediate() {
1147
+ return false;
1148
+ }
1149
+ get isCosmetic() {
1150
+ return false;
1151
+ }
1152
+ async detectCmp() {
1153
+ return elementExists("div[data-testid=main-cookies-banner-container]");
1154
+ }
1155
+ async detectPopup() {
1156
+ return elementVisible("div[data-testid=main-cookies-banner-container", "any");
1157
+ }
1158
+ async optOut() {
1159
+ await waitForThenClick("div[data-testid=main-cookies-banner-container] button._snbhip0");
1160
+ let check;
1161
+ while (check = document.querySelector("[data-testid=modal-container] button[aria-checked=true]:not([disabled])")) {
1162
+ check.click();
1163
+ }
1164
+ return waitForThenClick("button[data-testid=save-btn]");
1165
+ }
1166
+ async optIn() {
1167
+ return waitForThenClick("div[data-testid=main-cookies-banner-container] button._148dgdpk");
1196
1168
  }
1169
+ async test() {
1170
+ return await waitFor(
1171
+ () => !!document.cookie.match("OptanonAlertBoxClosed"),
1172
+ 20,
1173
+ 200
1174
+ );
1175
+ }
1176
+ };
1197
1177
 
1198
- const rules = rules$1;
1178
+ // lib/cmps/all.ts
1179
+ var rules = [
1180
+ new TrustArcTop(),
1181
+ new TrustArcFrame(),
1182
+ new Cookiebot(),
1183
+ new SourcePoint(),
1184
+ new ConsentManager(),
1185
+ new Evidon(),
1186
+ new Onetrust(),
1187
+ new Klaro(),
1188
+ new Uniconsent(),
1189
+ new Conversant(),
1190
+ new Tiktok(),
1191
+ new Airbnb()
1192
+ ];
1193
+ function createAutoCMP(config) {
1194
+ return new AutoConsentCMP(config);
1195
+ }
1196
+ var all_default = rules;
1199
1197
 
1200
- /**
1201
- * This code is in most parts copied from https://github.com/cavi-au/Consent-O-Matic/blob/master/Extension/Tools.js
1202
- * which is licened under the MIT.
1203
- */
1204
- class Tools {
1205
- static setBase(base) {
1206
- Tools.base = base;
1207
- }
1208
- static findElement(options, parent = null, multiple = false) {
1209
- let possibleTargets = null;
1210
- if (parent != null) {
1211
- possibleTargets = Array.from(parent.querySelectorAll(options.selector));
1212
- }
1213
- else {
1214
- if (Tools.base != null) {
1215
- possibleTargets = Array.from(Tools.base.querySelectorAll(options.selector));
1216
- }
1217
- else {
1218
- possibleTargets = Array.from(document.querySelectorAll(options.selector));
1219
- }
1220
- }
1221
- if (options.textFilter != null) {
1222
- possibleTargets = possibleTargets.filter(possibleTarget => {
1223
- const textContent = possibleTarget.textContent.toLowerCase();
1224
- if (Array.isArray(options.textFilter)) {
1225
- let foundText = false;
1226
- for (const text of options.textFilter) {
1227
- if (textContent.indexOf(text.toLowerCase()) !== -1) {
1228
- foundText = true;
1229
- break;
1230
- }
1231
- }
1232
- return foundText;
1233
- }
1234
- else if (options.textFilter != null) {
1235
- return textContent.indexOf(options.textFilter.toLowerCase()) !== -1;
1236
- }
1237
- });
1238
- }
1239
- if (options.styleFilters != null) {
1240
- possibleTargets = possibleTargets.filter(possibleTarget => {
1241
- const styles = window.getComputedStyle(possibleTarget);
1242
- let keep = true;
1243
- for (const styleFilter of options.styleFilters) {
1244
- const option = styles[styleFilter.option];
1245
- if (styleFilter.negated) {
1246
- keep = keep && option !== styleFilter.value;
1247
- }
1248
- else {
1249
- keep = keep && option === styleFilter.value;
1250
- }
1251
- }
1252
- return keep;
1253
- });
1254
- }
1255
- if (options.displayFilter != null) {
1256
- possibleTargets = possibleTargets.filter(possibleTarget => {
1257
- if (options.displayFilter) {
1258
- //We should be displayed
1259
- return possibleTarget.offsetHeight !== 0;
1260
- }
1261
- else {
1262
- //We should not be displayed
1263
- return possibleTarget.offsetHeight === 0;
1264
- }
1265
- });
1266
- }
1267
- if (options.iframeFilter != null) {
1268
- possibleTargets = possibleTargets.filter(( /* possibleTarget */) => {
1269
- if (options.iframeFilter) {
1270
- //We should be inside an iframe
1271
- return window.location !== window.parent.location;
1272
- }
1273
- else {
1274
- //We should not be inside an iframe
1275
- return window.location === window.parent.location;
1276
- }
1198
+ // lib/index.ts
1199
+ var rules2 = all_default;
1200
+
1201
+ // lib/consentomatic/tools.ts
1202
+ var Tools = class _Tools {
1203
+ static {
1204
+ this.base = null;
1205
+ }
1206
+ static setBase(base) {
1207
+ _Tools.base = base;
1208
+ }
1209
+ static findElement(options, parent = null, multiple = false) {
1210
+ let possibleTargets = null;
1211
+ if (parent != null) {
1212
+ possibleTargets = Array.from(parent.querySelectorAll(options.selector));
1213
+ } else {
1214
+ if (_Tools.base != null) {
1215
+ possibleTargets = Array.from(
1216
+ _Tools.base.querySelectorAll(options.selector)
1217
+ );
1218
+ } else {
1219
+ possibleTargets = Array.from(
1220
+ document.querySelectorAll(options.selector)
1221
+ );
1222
+ }
1223
+ }
1224
+ if (options.textFilter != null) {
1225
+ possibleTargets = possibleTargets.filter((possibleTarget) => {
1226
+ const textContent = possibleTarget.textContent.toLowerCase();
1227
+ if (Array.isArray(options.textFilter)) {
1228
+ let foundText = false;
1229
+ for (const text of options.textFilter) {
1230
+ if (textContent.indexOf(text.toLowerCase()) !== -1) {
1231
+ foundText = true;
1232
+ break;
1233
+ }
1234
+ }
1235
+ return foundText;
1236
+ } else if (options.textFilter != null) {
1237
+ return textContent.indexOf(options.textFilter.toLowerCase()) !== -1;
1238
+ }
1239
+ });
1240
+ }
1241
+ if (options.styleFilters != null) {
1242
+ possibleTargets = possibleTargets.filter((possibleTarget) => {
1243
+ const styles = window.getComputedStyle(possibleTarget);
1244
+ let keep = true;
1245
+ for (const styleFilter of options.styleFilters) {
1246
+ const option = styles[styleFilter.option];
1247
+ if (styleFilter.negated) {
1248
+ keep = keep && option !== styleFilter.value;
1249
+ } else {
1250
+ keep = keep && option === styleFilter.value;
1251
+ }
1252
+ }
1253
+ return keep;
1254
+ });
1255
+ }
1256
+ if (options.displayFilter != null) {
1257
+ possibleTargets = possibleTargets.filter((possibleTarget) => {
1258
+ if (options.displayFilter) {
1259
+ return possibleTarget.offsetHeight !== 0;
1260
+ } else {
1261
+ return possibleTarget.offsetHeight === 0;
1262
+ }
1263
+ });
1264
+ }
1265
+ if (options.iframeFilter != null) {
1266
+ possibleTargets = possibleTargets.filter(() => {
1267
+ if (options.iframeFilter) {
1268
+ return window.location !== window.parent.location;
1269
+ } else {
1270
+ return window.location === window.parent.location;
1271
+ }
1272
+ });
1273
+ }
1274
+ if (options.childFilter != null) {
1275
+ possibleTargets = possibleTargets.filter((possibleTarget) => {
1276
+ const oldBase = _Tools.base;
1277
+ _Tools.setBase(possibleTarget);
1278
+ const childResults = _Tools.find(options.childFilter);
1279
+ _Tools.setBase(oldBase);
1280
+ return childResults.target != null;
1281
+ });
1282
+ }
1283
+ if (multiple) {
1284
+ return possibleTargets;
1285
+ } else {
1286
+ if (possibleTargets.length > 1) {
1287
+ console.warn(
1288
+ "Multiple possible targets: ",
1289
+ possibleTargets,
1290
+ options,
1291
+ parent
1292
+ );
1293
+ }
1294
+ return possibleTargets[0];
1295
+ }
1296
+ }
1297
+ static find(options, multiple = false) {
1298
+ const results = [];
1299
+ if (options.parent != null) {
1300
+ const parent = _Tools.findElement(options.parent, null, multiple);
1301
+ if (parent != null) {
1302
+ if (parent instanceof Array) {
1303
+ parent.forEach((p) => {
1304
+ const targets = _Tools.findElement(options.target, p, multiple);
1305
+ if (targets instanceof Array) {
1306
+ targets.forEach((target) => {
1307
+ results.push({
1308
+ parent: p,
1309
+ target
1310
+ });
1277
1311
  });
1278
- }
1279
- if (options.childFilter != null) {
1280
- possibleTargets = possibleTargets.filter(possibleTarget => {
1281
- const oldBase = Tools.base;
1282
- Tools.setBase(possibleTarget);
1283
- const childResults = Tools.find(options.childFilter);
1284
- Tools.setBase(oldBase);
1285
- return childResults.target != null;
1312
+ } else {
1313
+ results.push({
1314
+ parent: p,
1315
+ target: targets
1286
1316
  });
1287
- }
1288
- if (multiple) {
1289
- return possibleTargets;
1290
- }
1291
- else {
1292
- if (possibleTargets.length > 1) {
1293
- console.warn("Multiple possible targets: ", possibleTargets, options, parent);
1294
- }
1295
- return possibleTargets[0];
1296
- }
1297
- }
1298
- static find(options, multiple = false) {
1299
- const results = [];
1300
- if (options.parent != null) {
1301
- const parent = Tools.findElement(options.parent, null, multiple);
1302
- if (parent != null) {
1303
- if (parent instanceof Array) {
1304
- parent.forEach(p => {
1305
- const targets = Tools.findElement(options.target, p, multiple);
1306
- if (targets instanceof Array) {
1307
- targets.forEach(target => {
1308
- results.push({
1309
- parent: p,
1310
- target: target
1311
- });
1312
- });
1313
- }
1314
- else {
1315
- results.push({
1316
- parent: p,
1317
- target: targets
1318
- });
1319
- }
1320
- });
1321
- return results;
1322
- }
1323
- else {
1324
- const targets = Tools.findElement(options.target, parent, multiple);
1325
- if (targets instanceof Array) {
1326
- targets.forEach(target => {
1327
- results.push({
1328
- parent: parent,
1329
- target: target
1330
- });
1331
- });
1332
- }
1333
- else {
1334
- results.push({
1335
- parent: parent,
1336
- target: targets
1337
- });
1338
- }
1339
- }
1340
- }
1341
- }
1342
- else {
1343
- const targets = Tools.findElement(options.target, null, multiple);
1344
- if (targets instanceof Array) {
1345
- targets.forEach(target => {
1346
- results.push({
1347
- parent: null,
1348
- target: target
1349
- });
1350
- });
1351
- }
1352
- else {
1353
- results.push({
1354
- parent: null,
1355
- target: targets
1356
- });
1357
- }
1358
- }
1359
- if (results.length === 0) {
1317
+ }
1318
+ });
1319
+ return results;
1320
+ } else {
1321
+ const targets = _Tools.findElement(options.target, parent, multiple);
1322
+ if (targets instanceof Array) {
1323
+ targets.forEach((target) => {
1360
1324
  results.push({
1361
- parent: null,
1362
- target: null
1325
+ parent,
1326
+ target
1363
1327
  });
1364
- }
1365
- if (multiple) {
1366
- return results;
1367
- }
1368
- else {
1369
- if (results.length !== 1) {
1370
- console.warn("Multiple results found, even though multiple false", results);
1371
- }
1372
- return results[0];
1373
- }
1374
- }
1328
+ });
1329
+ } else {
1330
+ results.push({
1331
+ parent,
1332
+ target: targets
1333
+ });
1334
+ }
1335
+ }
1336
+ }
1337
+ } else {
1338
+ const targets = _Tools.findElement(options.target, null, multiple);
1339
+ if (targets instanceof Array) {
1340
+ targets.forEach((target) => {
1341
+ results.push({
1342
+ parent: null,
1343
+ target
1344
+ });
1345
+ });
1346
+ } else {
1347
+ results.push({
1348
+ parent: null,
1349
+ target: targets
1350
+ });
1351
+ }
1352
+ }
1353
+ if (results.length === 0) {
1354
+ results.push({
1355
+ parent: null,
1356
+ target: null
1357
+ });
1358
+ }
1359
+ if (multiple) {
1360
+ return results;
1361
+ } else {
1362
+ if (results.length !== 1) {
1363
+ console.warn(
1364
+ "Multiple results found, even though multiple false",
1365
+ results
1366
+ );
1367
+ }
1368
+ return results[0];
1369
+ }
1375
1370
  }
1376
- Tools.base = null;
1371
+ };
1377
1372
 
1378
- function matches(config) {
1379
- const result = Tools.find(config);
1380
- if (config.type === "css") {
1381
- return !!result.target;
1382
- }
1383
- else if (config.type === "checkbox") {
1384
- return !!result.target && result.target.checked;
1385
- }
1373
+ // lib/consentomatic/index.ts
1374
+ function matches(config) {
1375
+ const result = Tools.find(config);
1376
+ if (config.type === "css") {
1377
+ return !!result.target;
1378
+ } else if (config.type === "checkbox") {
1379
+ return !!result.target && result.target.checked;
1386
1380
  }
1387
- async function executeAction(config, param) {
1388
- switch (config.type) {
1389
- case "click":
1390
- return clickAction(config);
1391
- case "list":
1392
- return listAction(config, param);
1393
- case "consent":
1394
- return consentAction(config, param);
1395
- case "ifcss":
1396
- return ifCssAction(config, param);
1397
- case "waitcss":
1398
- return waitCssAction(config);
1399
- case "foreach":
1400
- return forEachAction(config, param);
1401
- case "hide":
1402
- return hideAction(config);
1403
- case "slide":
1404
- return slideAction(config);
1405
- case "close":
1406
- return closeAction();
1407
- case "wait":
1408
- return waitAction(config);
1409
- case "eval":
1410
- return evalAction(config);
1411
- default:
1412
- throw "Unknown action type: " + config.type;
1413
- }
1381
+ }
1382
+ async function executeAction(config, param) {
1383
+ switch (config.type) {
1384
+ case "click":
1385
+ return clickAction(config);
1386
+ case "list":
1387
+ return listAction(config, param);
1388
+ case "consent":
1389
+ return consentAction(config, param);
1390
+ case "ifcss":
1391
+ return ifCssAction(config, param);
1392
+ case "waitcss":
1393
+ return waitCssAction(config);
1394
+ case "foreach":
1395
+ return forEachAction(config, param);
1396
+ case "hide":
1397
+ return hideAction(config);
1398
+ case "slide":
1399
+ return slideAction(config);
1400
+ case "close":
1401
+ return closeAction();
1402
+ case "wait":
1403
+ return waitAction(config);
1404
+ case "eval":
1405
+ return evalAction(config);
1406
+ default:
1407
+ throw "Unknown action type: " + config.type;
1414
1408
  }
1415
- const STEP_TIMEOUT = 0;
1416
- function waitTimeout(timeout) {
1417
- return new Promise(resolve => {
1418
- setTimeout(() => {
1419
- resolve();
1420
- }, timeout);
1421
- });
1409
+ }
1410
+ var STEP_TIMEOUT = 0;
1411
+ function waitTimeout(timeout) {
1412
+ return new Promise((resolve) => {
1413
+ setTimeout(() => {
1414
+ resolve();
1415
+ }, timeout);
1416
+ });
1417
+ }
1418
+ async function clickAction(config) {
1419
+ const result = Tools.find(config);
1420
+ if (result.target != null) {
1421
+ result.target.click();
1422
1422
  }
1423
- async function clickAction(config) {
1424
- const result = Tools.find(config);
1425
- if (result.target != null) {
1426
- result.target.click();
1427
- }
1428
- return waitTimeout(STEP_TIMEOUT);
1423
+ return waitTimeout(STEP_TIMEOUT);
1424
+ }
1425
+ async function listAction(config, param) {
1426
+ for (const action of config.actions) {
1427
+ await executeAction(action, param);
1429
1428
  }
1430
- async function listAction(config, param) {
1431
- for (const action of config.actions) {
1432
- await executeAction(action, param);
1433
- }
1429
+ }
1430
+ async function consentAction(config, consentTypes) {
1431
+ for (const consentConfig of config.consents) {
1432
+ const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
1433
+ if (consentConfig.matcher && consentConfig.toggleAction) {
1434
+ const isEnabled = matches(consentConfig.matcher);
1435
+ if (isEnabled !== shouldEnable) {
1436
+ await executeAction(consentConfig.toggleAction);
1437
+ }
1438
+ } else {
1439
+ if (shouldEnable) {
1440
+ await executeAction(consentConfig.trueAction);
1441
+ } else {
1442
+ await executeAction(consentConfig.falseAction);
1443
+ }
1444
+ }
1434
1445
  }
1435
- async function consentAction(config, consentTypes) {
1436
- for (const consentConfig of config.consents) {
1437
- const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
1438
- if (consentConfig.matcher && consentConfig.toggleAction) {
1439
- const isEnabled = matches(consentConfig.matcher);
1440
- if (isEnabled !== shouldEnable) {
1441
- await executeAction(consentConfig.toggleAction);
1442
- }
1443
- }
1444
- else {
1445
- if (shouldEnable) {
1446
- await executeAction(consentConfig.trueAction);
1447
- }
1448
- else {
1449
- await executeAction(consentConfig.falseAction);
1450
- }
1451
- }
1452
- }
1446
+ }
1447
+ async function ifCssAction(config, param) {
1448
+ const result = Tools.find(config);
1449
+ if (!result.target) {
1450
+ if (config.trueAction) {
1451
+ await executeAction(config.trueAction, param);
1452
+ }
1453
+ } else {
1454
+ if (config.falseAction) {
1455
+ await executeAction(config.falseAction, param);
1456
+ }
1453
1457
  }
1454
- async function ifCssAction(config, param) {
1458
+ }
1459
+ async function waitCssAction(config) {
1460
+ await new Promise((resolve) => {
1461
+ let numRetries = config.retries || 10;
1462
+ const waitTime = config.waitTime || 250;
1463
+ const checkCss = () => {
1455
1464
  const result = Tools.find(config);
1456
- if (!result.target) {
1457
- if (config.trueAction) {
1458
- await executeAction(config.trueAction, param);
1459
- }
1460
- }
1461
- else {
1462
- if (config.falseAction) {
1463
- await executeAction(config.falseAction, param);
1464
- }
1465
- }
1465
+ if (config.negated && result.target || !config.negated && !result.target) {
1466
+ if (numRetries > 0) {
1467
+ numRetries -= 1;
1468
+ setTimeout(checkCss, waitTime);
1469
+ } else {
1470
+ resolve();
1471
+ }
1472
+ } else {
1473
+ resolve();
1474
+ }
1475
+ };
1476
+ checkCss();
1477
+ });
1478
+ }
1479
+ async function forEachAction(config, param) {
1480
+ const results = Tools.find(config, true);
1481
+ const oldBase = Tools.base;
1482
+ for (const result of results) {
1483
+ if (result.target) {
1484
+ Tools.setBase(result.target);
1485
+ await executeAction(config.action, param);
1486
+ }
1466
1487
  }
1467
- async function waitCssAction(config) {
1468
- await new Promise(resolve => {
1469
- let numRetries = config.retries || 10;
1470
- const waitTime = config.waitTime || 250;
1471
- const checkCss = () => {
1472
- const result = Tools.find(config);
1473
- if ((config.negated && result.target) ||
1474
- (!config.negated && !result.target)) {
1475
- if (numRetries > 0) {
1476
- numRetries -= 1;
1477
- setTimeout(checkCss, waitTime);
1478
- }
1479
- else {
1480
- resolve();
1481
- }
1482
- }
1483
- else {
1484
- resolve();
1485
- }
1486
- };
1487
- checkCss();
1488
- });
1488
+ Tools.setBase(oldBase);
1489
+ }
1490
+ async function hideAction(config) {
1491
+ const result = Tools.find(config);
1492
+ if (result.target) {
1493
+ result.target.classList.add("Autoconsent-Hidden");
1489
1494
  }
1490
- async function forEachAction(config, param) {
1491
- const results = Tools.find(config, true);
1492
- const oldBase = Tools.base;
1493
- for (const result of results) {
1494
- if (result.target) {
1495
- Tools.setBase(result.target);
1496
- await executeAction(config.action, param);
1497
- }
1498
- }
1499
- Tools.setBase(oldBase);
1495
+ }
1496
+ async function slideAction(config) {
1497
+ const result = Tools.find(config);
1498
+ const dragResult = Tools.find(config.dragTarget);
1499
+ if (result.target) {
1500
+ const targetBounds = result.target.getBoundingClientRect();
1501
+ const dragTargetBounds = dragResult.target.getBoundingClientRect();
1502
+ let yDiff = dragTargetBounds.top - targetBounds.top;
1503
+ let xDiff = dragTargetBounds.left - targetBounds.left;
1504
+ if (this.config.axis.toLowerCase() === "y") {
1505
+ xDiff = 0;
1506
+ }
1507
+ if (this.config.axis.toLowerCase() === "x") {
1508
+ yDiff = 0;
1509
+ }
1510
+ const screenX = window.screenX + targetBounds.left + targetBounds.width / 2;
1511
+ const screenY = window.screenY + targetBounds.top + targetBounds.height / 2;
1512
+ const clientX = targetBounds.left + targetBounds.width / 2;
1513
+ const clientY = targetBounds.top + targetBounds.height / 2;
1514
+ const mouseDown = document.createEvent("MouseEvents");
1515
+ mouseDown.initMouseEvent(
1516
+ "mousedown",
1517
+ true,
1518
+ true,
1519
+ window,
1520
+ 0,
1521
+ screenX,
1522
+ screenY,
1523
+ clientX,
1524
+ clientY,
1525
+ false,
1526
+ false,
1527
+ false,
1528
+ false,
1529
+ 0,
1530
+ result.target
1531
+ );
1532
+ const mouseMove = document.createEvent("MouseEvents");
1533
+ mouseMove.initMouseEvent(
1534
+ "mousemove",
1535
+ true,
1536
+ true,
1537
+ window,
1538
+ 0,
1539
+ screenX + xDiff,
1540
+ screenY + yDiff,
1541
+ clientX + xDiff,
1542
+ clientY + yDiff,
1543
+ false,
1544
+ false,
1545
+ false,
1546
+ false,
1547
+ 0,
1548
+ result.target
1549
+ );
1550
+ const mouseUp = document.createEvent("MouseEvents");
1551
+ mouseUp.initMouseEvent(
1552
+ "mouseup",
1553
+ true,
1554
+ true,
1555
+ window,
1556
+ 0,
1557
+ screenX + xDiff,
1558
+ screenY + yDiff,
1559
+ clientX + xDiff,
1560
+ clientY + yDiff,
1561
+ false,
1562
+ false,
1563
+ false,
1564
+ false,
1565
+ 0,
1566
+ result.target
1567
+ );
1568
+ result.target.dispatchEvent(mouseDown);
1569
+ await this.waitTimeout(10);
1570
+ result.target.dispatchEvent(mouseMove);
1571
+ await this.waitTimeout(10);
1572
+ result.target.dispatchEvent(mouseUp);
1500
1573
  }
1501
- async function hideAction(config) {
1502
- const result = Tools.find(config);
1503
- if (result.target) {
1504
- result.target.classList.add("Autoconsent-Hidden");
1505
- // result.target.setAttribute("style", "display: none;");
1506
- }
1574
+ }
1575
+ async function waitAction(config) {
1576
+ await waitTimeout(config.waitTime);
1577
+ }
1578
+ async function closeAction() {
1579
+ window.close();
1580
+ }
1581
+ async function evalAction(config) {
1582
+ console.log("eval!", config.code);
1583
+ return new Promise((resolve) => {
1584
+ try {
1585
+ if (config.async) {
1586
+ window.eval(config.code);
1587
+ setTimeout(() => {
1588
+ resolve(window.eval("window.__consentCheckResult"));
1589
+ }, config.timeout || 250);
1590
+ } else {
1591
+ resolve(window.eval(config.code));
1592
+ }
1593
+ } catch (e) {
1594
+ console.warn("eval error", e, config.code);
1595
+ resolve(false);
1596
+ }
1597
+ });
1598
+ }
1599
+
1600
+ // lib/cmps/consentomatic.ts
1601
+ var ConsentOMaticCMP = class {
1602
+ constructor(name, config) {
1603
+ this.name = name;
1604
+ this.config = config;
1605
+ this.methods = /* @__PURE__ */ new Map();
1606
+ this.runContext = defaultRunContext;
1607
+ this.isCosmetic = false;
1608
+ config.methods.forEach((methodConfig) => {
1609
+ if (methodConfig.action) {
1610
+ this.methods.set(methodConfig.name, methodConfig.action);
1611
+ }
1612
+ });
1613
+ this.hasSelfTest = false;
1507
1614
  }
1508
- async function slideAction(config) {
1509
- const result = Tools.find(config);
1510
- const dragResult = Tools.find(config.dragTarget);
1511
- if (result.target) {
1512
- const targetBounds = result.target.getBoundingClientRect();
1513
- const dragTargetBounds = dragResult.target.getBoundingClientRect();
1514
- let yDiff = dragTargetBounds.top - targetBounds.top;
1515
- let xDiff = dragTargetBounds.left - targetBounds.left;
1516
- if (this.config.axis.toLowerCase() === "y") {
1517
- xDiff = 0;
1518
- }
1519
- if (this.config.axis.toLowerCase() === "x") {
1520
- yDiff = 0;
1521
- }
1522
- const screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
1523
- const screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
1524
- const clientX = targetBounds.left + targetBounds.width / 2.0;
1525
- const clientY = targetBounds.top + targetBounds.height / 2.0;
1526
- const mouseDown = document.createEvent("MouseEvents");
1527
- mouseDown.initMouseEvent("mousedown", true, true, window, 0, screenX, screenY, clientX, clientY, false, false, false, false, 0, result.target);
1528
- const mouseMove = document.createEvent("MouseEvents");
1529
- mouseMove.initMouseEvent("mousemove", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
1530
- const mouseUp = document.createEvent("MouseEvents");
1531
- mouseUp.initMouseEvent("mouseup", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
1532
- result.target.dispatchEvent(mouseDown);
1533
- await this.waitTimeout(10);
1534
- result.target.dispatchEvent(mouseMove);
1535
- await this.waitTimeout(10);
1536
- result.target.dispatchEvent(mouseUp);
1537
- }
1615
+ get isIntermediate() {
1616
+ return false;
1538
1617
  }
1539
- async function waitAction(config) {
1540
- await waitTimeout(config.waitTime);
1541
- }
1542
- async function closeAction() {
1543
- window.close();
1544
- }
1545
- async function evalAction(config) {
1546
- console.log("eval!", config.code);
1547
- return new Promise(resolve => {
1548
- try {
1549
- if (config.async) {
1550
- window.eval(config.code);
1551
- setTimeout(() => {
1552
- resolve(window.eval("window.__consentCheckResult"));
1553
- }, config.timeout || 250);
1554
- }
1555
- else {
1556
- resolve(window.eval(config.code));
1557
- }
1558
- }
1559
- catch (e) {
1560
- console.warn("eval error", e, config.code);
1561
- resolve(false);
1562
- }
1563
- });
1618
+ checkRunContext() {
1619
+ return true;
1564
1620
  }
1565
-
1566
- class ConsentOMaticCMP {
1567
- constructor(name, config) {
1568
- this.name = name;
1569
- this.config = config;
1570
- this.methods = new Map();
1571
- this.runContext = defaultRunContext;
1572
- this.isCosmetic = false;
1573
- config.methods.forEach(methodConfig => {
1574
- if (methodConfig.action) {
1575
- this.methods.set(methodConfig.name, methodConfig.action);
1576
- }
1577
- });
1578
- this.hasSelfTest = false;
1579
- }
1580
- get isIntermediate() {
1581
- return false; // TODO: support UTILITY rules
1582
- }
1583
- checkRunContext() {
1584
- return true;
1585
- }
1586
- async detectCmp() {
1587
- const matchResults = this.config.detectors.map(detectorConfig => matches(detectorConfig.presentMatcher));
1588
- return matchResults.some(r => !!r);
1589
- }
1590
- async detectPopup() {
1591
- const matchResults = this.config.detectors.map(detectorConfig => matches(detectorConfig.showingMatcher));
1592
- return matchResults.some(r => !!r);
1593
- }
1594
- async executeAction(method, param) {
1595
- if (this.methods.has(method)) {
1596
- return executeAction(this.methods.get(method), param);
1597
- }
1598
- return true;
1599
- }
1600
- async optOut() {
1601
- await this.executeAction("HIDE_CMP");
1602
- await this.executeAction("OPEN_OPTIONS");
1603
- await this.executeAction("HIDE_CMP");
1604
- await this.executeAction("DO_CONSENT", []);
1605
- await this.executeAction("SAVE_CONSENT");
1606
- return true;
1607
- }
1608
- async optIn() {
1609
- await this.executeAction("HIDE_CMP");
1610
- await this.executeAction("OPEN_OPTIONS");
1611
- await this.executeAction("HIDE_CMP");
1612
- await this.executeAction("DO_CONSENT", ['D', 'A', 'B', 'E', 'F', 'X']);
1613
- await this.executeAction("SAVE_CONSENT");
1614
- return true;
1615
- }
1616
- async openCmp() {
1617
- await this.executeAction("HIDE_CMP");
1618
- await this.executeAction("OPEN_OPTIONS");
1619
- return true;
1620
- }
1621
- async test() {
1622
- return true;
1623
- }
1621
+ async detectCmp() {
1622
+ const matchResults = this.config.detectors.map(
1623
+ (detectorConfig) => matches(detectorConfig.presentMatcher)
1624
+ );
1625
+ return matchResults.some((r) => !!r);
1626
+ }
1627
+ async detectPopup() {
1628
+ const matchResults = this.config.detectors.map(
1629
+ (detectorConfig) => matches(detectorConfig.showingMatcher)
1630
+ );
1631
+ return matchResults.some((r) => !!r);
1632
+ }
1633
+ async executeAction(method, param) {
1634
+ if (this.methods.has(method)) {
1635
+ return executeAction(this.methods.get(method), param);
1636
+ }
1637
+ return true;
1624
1638
  }
1639
+ async optOut() {
1640
+ await this.executeAction("HIDE_CMP");
1641
+ await this.executeAction("OPEN_OPTIONS");
1642
+ await this.executeAction("HIDE_CMP");
1643
+ await this.executeAction("DO_CONSENT", []);
1644
+ await this.executeAction("SAVE_CONSENT");
1645
+ return true;
1646
+ }
1647
+ async optIn() {
1648
+ await this.executeAction("HIDE_CMP");
1649
+ await this.executeAction("OPEN_OPTIONS");
1650
+ await this.executeAction("HIDE_CMP");
1651
+ await this.executeAction("DO_CONSENT", ["D", "A", "B", "E", "F", "X"]);
1652
+ await this.executeAction("SAVE_CONSENT");
1653
+ return true;
1654
+ }
1655
+ async openCmp() {
1656
+ await this.executeAction("HIDE_CMP");
1657
+ await this.executeAction("OPEN_OPTIONS");
1658
+ return true;
1659
+ }
1660
+ async test() {
1661
+ return true;
1662
+ }
1663
+ };
1625
1664
 
1626
- function filterCMPs(rules, config) {
1627
- return rules.filter((cmp) => {
1628
- return ((!config.disabledCmps || !config.disabledCmps.includes(cmp.name)) // CMP is not disabled
1629
- &&
1630
- (config.enableCosmeticRules || !cmp.isCosmetic) // CMP is not cosmetic or cosmetic rules are enabled
1631
- );
1632
- });
1665
+ // lib/web.ts
1666
+ function filterCMPs(rules3, config) {
1667
+ return rules3.filter((cmp) => {
1668
+ return (!config.disabledCmps || !config.disabledCmps.includes(cmp.name)) && (config.enableCosmeticRules || !cmp.isCosmetic);
1669
+ });
1670
+ }
1671
+ var AutoConsent = class {
1672
+ constructor(sendContentMessage, config = null, declarativeRules = null) {
1673
+ this.id = getRandomID();
1674
+ this.rules = [];
1675
+ this.foundCmp = null;
1676
+ this.state = {
1677
+ lifecycle: "loading",
1678
+ prehideOn: false,
1679
+ findCmpAttempts: 0,
1680
+ detectedCmps: [],
1681
+ detectedPopups: [],
1682
+ selfTest: null
1683
+ };
1684
+ evalState.sendContentMessage = sendContentMessage;
1685
+ this.sendContentMessage = sendContentMessage;
1686
+ this.rules = [...rules2];
1687
+ enableLogs && console.log("autoconsent init", window.location.href);
1688
+ this.updateState({ lifecycle: "loading" });
1689
+ if (config) {
1690
+ this.initialize(config, declarativeRules);
1691
+ } else {
1692
+ if (declarativeRules) {
1693
+ this.parseRules(declarativeRules);
1694
+ }
1695
+ const initMsg = {
1696
+ type: "init",
1697
+ url: window.location.href
1698
+ };
1699
+ sendContentMessage(initMsg);
1700
+ this.updateState({ lifecycle: "waitingForInitResponse" });
1701
+ }
1633
1702
  }
1634
- class AutoConsent {
1635
- constructor(sendContentMessage, config = null, declarativeRules = null) {
1636
- this.id = getRandomID();
1637
- this.rules = [];
1638
- this.foundCmp = null;
1639
- this.state = {
1640
- lifecycle: 'loading',
1641
- prehideOn: false,
1642
- findCmpAttempts: 0,
1643
- detectedCmps: [],
1644
- detectedPopups: [],
1645
- selfTest: null,
1646
- };
1647
- evalState.sendContentMessage = sendContentMessage;
1648
- this.sendContentMessage = sendContentMessage;
1649
- this.rules = [...rules];
1650
- this.updateState({ lifecycle: 'loading' });
1651
- if (config) {
1652
- this.initialize(config, declarativeRules);
1653
- }
1654
- else {
1655
- if (declarativeRules) {
1656
- this.parseRules(declarativeRules);
1657
- }
1658
- const initMsg = {
1659
- type: "init",
1660
- url: window.location.href,
1661
- };
1662
- sendContentMessage(initMsg);
1663
- this.updateState({ lifecycle: 'waitingForInitResponse' });
1664
- }
1665
- }
1666
- initialize(config, declarativeRules) {
1667
- this.config = config;
1668
- if (!config.enabled) {
1669
- return;
1670
- }
1671
- if (declarativeRules) {
1672
- this.parseRules(declarativeRules);
1673
- }
1674
- this.rules = filterCMPs(this.rules, config);
1675
- if (config.enablePrehide) {
1676
- if (document.documentElement) {
1677
- this.prehideElements(); // prehide as early as possible to prevent flickering
1678
- }
1679
- else {
1680
- // we're injected really early
1681
- const delayedPrehide = () => {
1682
- window.removeEventListener('DOMContentLoaded', delayedPrehide);
1683
- this.prehideElements();
1684
- };
1685
- window.addEventListener('DOMContentLoaded', delayedPrehide);
1686
- }
1687
- }
1688
- // start detection
1689
- if (document.readyState === 'loading') {
1690
- const onReady = () => {
1691
- window.removeEventListener('DOMContentLoaded', onReady);
1692
- this.start();
1693
- };
1694
- window.addEventListener('DOMContentLoaded', onReady);
1695
- }
1696
- else {
1697
- this.start();
1698
- }
1699
- this.updateState({ lifecycle: 'initialized' });
1700
- }
1701
- parseRules(declarativeRules) {
1702
- Object.keys(declarativeRules.consentomatic).forEach((name) => {
1703
- this.addConsentomaticCMP(name, declarativeRules.consentomatic[name]);
1704
- });
1705
- declarativeRules.autoconsent.forEach((rule) => {
1706
- this.addCMP(rule);
1707
- });
1708
- }
1709
- addCMP(config) {
1710
- this.rules.push(createAutoCMP(config));
1711
- }
1712
- addConsentomaticCMP(name, config) {
1713
- this.rules.push(new ConsentOMaticCMP(`com_${name}`, config));
1714
- }
1715
- // start the detection process, possibly with a delay
1716
- start() {
1717
- if (window.requestIdleCallback) {
1718
- window.requestIdleCallback(() => this._start(), { timeout: 500 });
1719
- }
1720
- else {
1721
- this._start();
1722
- }
1723
- }
1724
- async _start() {
1725
- this.updateState({ lifecycle: 'started' });
1726
- const foundCmps = await this.findCmp(this.config.detectRetries);
1727
- this.updateState({ detectedCmps: foundCmps.map(c => c.name) });
1728
- if (foundCmps.length === 0) {
1729
- if (this.config.enablePrehide) {
1730
- this.undoPrehide();
1731
- }
1732
- this.updateState({ lifecycle: 'nothingDetected' });
1733
- return false;
1734
- }
1735
- this.updateState({ lifecycle: 'cmpDetected' });
1736
- // we resort to cosmetic rules only if no non-cosmetic rules are found
1737
- let foundPopups = await this.detectPopups(foundCmps.filter(r => !r.isCosmetic));
1738
- if (foundPopups.length === 0) {
1739
- foundPopups = await this.detectPopups(foundCmps.filter(r => r.isCosmetic));
1740
- }
1741
- if (foundPopups.length === 0) {
1742
- if (this.config.enablePrehide) {
1743
- this.undoPrehide();
1744
- }
1745
- return false;
1746
- }
1747
- this.updateState({ lifecycle: 'openPopupDetected' });
1748
- if (foundPopups.length > 1) {
1749
- const errorDetails = {
1750
- msg: `Found multiple CMPs, check the detection rules.`,
1751
- cmps: foundPopups.map((cmp) => cmp.name),
1752
- };
1753
- this.sendContentMessage({
1754
- type: 'autoconsentError',
1755
- details: errorDetails,
1756
- });
1757
- }
1758
- this.foundCmp = foundPopups[0];
1759
- if (this.config.autoAction === 'optOut') {
1760
- return await this.doOptOut();
1761
- }
1762
- else if (this.config.autoAction === 'optIn') {
1763
- return await this.doOptIn();
1764
- }
1765
- else {
1766
- return true;
1767
- }
1768
- }
1769
- async findCmp(retries) {
1770
- this.updateState({ findCmpAttempts: this.state.findCmpAttempts + 1 });
1771
- const foundCMPs = [];
1772
- for (const cmp of this.rules) {
1773
- try {
1774
- if (!cmp.checkRunContext()) {
1775
- continue;
1776
- }
1777
- const result = await cmp.detectCmp();
1778
- if (result) {
1779
- enableLogs && console.log(`Found CMP: ${cmp.name} ${window.location.href}`);
1780
- this.sendContentMessage({
1781
- type: 'cmpDetected',
1782
- url: location.href,
1783
- cmp: cmp.name,
1784
- }); // notify the browser
1785
- foundCMPs.push(cmp);
1786
- }
1787
- }
1788
- catch (e) {
1789
- }
1790
- }
1791
- if (foundCMPs.length === 0 && retries > 0) {
1792
- await wait(500);
1793
- return this.findCmp(retries - 1);
1794
- }
1795
- return foundCMPs;
1796
- }
1797
- async detectPopups(cmps) {
1798
- const result = [];
1799
- const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
1800
- if (isOpen) {
1801
- this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
1802
- this.sendContentMessage({
1803
- type: 'popupFound',
1804
- cmp: cmp.name,
1805
- url: location.href,
1806
- }); // notify the browser
1807
- result.push(cmp);
1808
- }
1809
- }).catch(() => null));
1810
- await Promise.all(popupLookups);
1811
- return result;
1812
- }
1813
- async doOptOut() {
1814
- this.updateState({ lifecycle: 'runningOptOut' });
1815
- let optOutResult;
1816
- if (!this.foundCmp) {
1817
- optOutResult = false;
1818
- }
1819
- else {
1820
- optOutResult = await this.foundCmp.optOut();
1821
- }
1822
- if (this.config.enablePrehide) {
1823
- this.undoPrehide();
1824
- }
1825
- this.sendContentMessage({
1826
- type: 'optOutResult',
1827
- cmp: this.foundCmp ? this.foundCmp.name : 'none',
1828
- result: optOutResult,
1829
- scheduleSelfTest: this.foundCmp && this.foundCmp.hasSelfTest,
1830
- url: location.href,
1831
- });
1832
- if (optOutResult && !this.foundCmp.isIntermediate) {
1833
- this.sendContentMessage({
1834
- type: 'autoconsentDone',
1835
- cmp: this.foundCmp.name,
1836
- isCosmetic: this.foundCmp.isCosmetic,
1837
- url: location.href,
1838
- });
1839
- this.updateState({ lifecycle: 'done' });
1840
- }
1841
- else {
1842
- this.updateState({ lifecycle: optOutResult ? 'optOutSucceeded' : 'optOutFailed' });
1843
- }
1844
- return optOutResult;
1845
- }
1846
- async doOptIn() {
1847
- this.updateState({ lifecycle: 'runningOptIn' });
1848
- let optInResult;
1849
- if (!this.foundCmp) {
1850
- optInResult = false;
1851
- }
1852
- else {
1853
- optInResult = await this.foundCmp.optIn();
1854
- }
1855
- if (this.config.enablePrehide) {
1856
- this.undoPrehide();
1857
- }
1858
- this.sendContentMessage({
1859
- type: 'optInResult',
1860
- cmp: this.foundCmp ? this.foundCmp.name : 'none',
1861
- result: optInResult,
1862
- scheduleSelfTest: false,
1863
- url: location.href,
1864
- });
1865
- if (optInResult && !this.foundCmp.isIntermediate) {
1866
- this.sendContentMessage({
1867
- type: 'autoconsentDone',
1868
- cmp: this.foundCmp.name,
1869
- isCosmetic: this.foundCmp.isCosmetic,
1870
- url: location.href,
1871
- });
1872
- this.updateState({ lifecycle: 'done' });
1873
- }
1874
- else {
1875
- this.updateState({ lifecycle: optInResult ? 'optInSucceeded' : 'optInFailed' });
1876
- }
1877
- return optInResult;
1878
- }
1879
- async doSelfTest() {
1880
- let selfTestResult;
1881
- if (!this.foundCmp) {
1882
- selfTestResult = false;
1883
- }
1884
- else {
1885
- selfTestResult = await this.foundCmp.test();
1886
- }
1887
- this.sendContentMessage({
1888
- type: 'selfTestResult',
1889
- cmp: this.foundCmp ? this.foundCmp.name : 'none',
1890
- result: selfTestResult,
1891
- url: location.href,
1892
- });
1893
- this.updateState({ selfTest: selfTestResult });
1894
- return selfTestResult;
1895
- }
1896
- async waitForPopup(cmp, retries = 5, interval = 500) {
1897
- const isOpen = await cmp.detectPopup();
1898
- if (!isOpen && retries > 0) {
1899
- await wait(interval);
1900
- return this.waitForPopup(cmp, retries - 1, interval);
1901
- }
1902
- return isOpen;
1903
- }
1904
- prehideElements() {
1905
- // hide rules not specific to a single CMP rule
1906
- const globalHidden = [
1907
- "#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium",
1908
- ];
1909
- const selectors = this.rules.reduce((selectorList, rule) => {
1910
- if (rule.prehideSelectors) {
1911
- return [...selectorList, ...rule.prehideSelectors];
1912
- }
1913
- return selectorList;
1914
- }, globalHidden);
1915
- this.updateState({ prehideOn: true });
1916
- setTimeout(() => {
1917
- // unhide things if we are still looking for a pop-up
1918
- if (this.config.enablePrehide &&
1919
- this.state.prehideOn &&
1920
- !['runningOptOut', 'runningOptIn'].includes(this.state.lifecycle)) {
1921
- this.undoPrehide();
1922
- }
1923
- }, this.config.prehideTimeout || 2000);
1924
- return prehide(selectors);
1925
- }
1926
- undoPrehide() {
1927
- this.updateState({ prehideOn: false });
1928
- return undoPrehide();
1703
+ initialize(config, declarativeRules) {
1704
+ this.config = config;
1705
+ if (!config.enabled) {
1706
+ enableLogs && console.log("autoconsent is disabled");
1707
+ return;
1708
+ }
1709
+ if (declarativeRules) {
1710
+ this.parseRules(declarativeRules);
1711
+ }
1712
+ this.rules = filterCMPs(this.rules, config);
1713
+ if (config.enablePrehide) {
1714
+ if (document.documentElement) {
1715
+ this.prehideElements();
1716
+ } else {
1717
+ const delayedPrehide = () => {
1718
+ window.removeEventListener("DOMContentLoaded", delayedPrehide);
1719
+ this.prehideElements();
1720
+ };
1721
+ window.addEventListener("DOMContentLoaded", delayedPrehide);
1722
+ }
1723
+ }
1724
+ if (document.readyState === "loading") {
1725
+ const onReady = () => {
1726
+ window.removeEventListener("DOMContentLoaded", onReady);
1727
+ this.start();
1728
+ };
1729
+ window.addEventListener("DOMContentLoaded", onReady);
1730
+ } else {
1731
+ this.start();
1732
+ }
1733
+ this.updateState({ lifecycle: "initialized" });
1734
+ }
1735
+ parseRules(declarativeRules) {
1736
+ Object.keys(declarativeRules.consentomatic).forEach((name) => {
1737
+ this.addConsentomaticCMP(name, declarativeRules.consentomatic[name]);
1738
+ });
1739
+ declarativeRules.autoconsent.forEach((rule) => {
1740
+ this.addCMP(rule);
1741
+ });
1742
+ enableLogs && console.log("added rules", this.rules);
1743
+ }
1744
+ addCMP(config) {
1745
+ this.rules.push(createAutoCMP(config));
1746
+ }
1747
+ addConsentomaticCMP(name, config) {
1748
+ this.rules.push(new ConsentOMaticCMP(`com_${name}`, config));
1749
+ }
1750
+ // start the detection process, possibly with a delay
1751
+ start() {
1752
+ if (window.requestIdleCallback) {
1753
+ window.requestIdleCallback(() => this._start(), { timeout: 500 });
1754
+ } else {
1755
+ this._start();
1756
+ }
1757
+ }
1758
+ async _start() {
1759
+ enableLogs && console.log(`Detecting CMPs on ${window.location.href}`);
1760
+ this.updateState({ lifecycle: "started" });
1761
+ const foundCmps = await this.findCmp(this.config.detectRetries);
1762
+ this.updateState({ detectedCmps: foundCmps.map((c) => c.name) });
1763
+ if (foundCmps.length === 0) {
1764
+ enableLogs && console.log("no CMP found", location.href);
1765
+ if (this.config.enablePrehide) {
1766
+ this.undoPrehide();
1767
+ }
1768
+ this.updateState({ lifecycle: "nothingDetected" });
1769
+ return false;
1770
+ }
1771
+ this.updateState({ lifecycle: "cmpDetected" });
1772
+ let foundPopups = await this.detectPopups(foundCmps.filter((r) => !r.isCosmetic));
1773
+ if (foundPopups.length === 0) {
1774
+ foundPopups = await this.detectPopups(foundCmps.filter((r) => r.isCosmetic));
1775
+ }
1776
+ if (foundPopups.length === 0) {
1777
+ enableLogs && console.log("no popup found");
1778
+ if (this.config.enablePrehide) {
1779
+ this.undoPrehide();
1929
1780
  }
1930
- updateState(change) {
1931
- Object.assign(this.state, change);
1781
+ return false;
1782
+ }
1783
+ this.updateState({ lifecycle: "openPopupDetected" });
1784
+ if (foundPopups.length > 1) {
1785
+ const errorDetails = {
1786
+ msg: `Found multiple CMPs, check the detection rules.`,
1787
+ cmps: foundPopups.map((cmp) => cmp.name)
1788
+ };
1789
+ enableLogs && console.warn(errorDetails.msg, errorDetails.cmps);
1790
+ this.sendContentMessage({
1791
+ type: "autoconsentError",
1792
+ details: errorDetails
1793
+ });
1794
+ }
1795
+ this.foundCmp = foundPopups[0];
1796
+ if (this.config.autoAction === "optOut") {
1797
+ return await this.doOptOut();
1798
+ } else if (this.config.autoAction === "optIn") {
1799
+ return await this.doOptIn();
1800
+ } else {
1801
+ enableLogs && console.log("waiting for opt-out signal...", location.href);
1802
+ return true;
1803
+ }
1804
+ }
1805
+ async findCmp(retries) {
1806
+ this.updateState({ findCmpAttempts: this.state.findCmpAttempts + 1 });
1807
+ const foundCMPs = [];
1808
+ for (const cmp of this.rules) {
1809
+ try {
1810
+ if (!cmp.checkRunContext()) {
1811
+ continue;
1812
+ }
1813
+ const result = await cmp.detectCmp();
1814
+ if (result) {
1815
+ enableLogs && console.log(`Found CMP: ${cmp.name} ${window.location.href}`);
1932
1816
  this.sendContentMessage({
1933
- type: 'report',
1934
- instanceId: this.id,
1935
- url: window.location.href,
1936
- mainFrame: window.top === window.self,
1937
- state: this.state,
1817
+ type: "cmpDetected",
1818
+ url: location.href,
1819
+ cmp: cmp.name
1938
1820
  });
1939
- }
1940
- async receiveMessageCallback(message) {
1941
- switch (message.type) {
1942
- case 'initResp':
1943
- this.initialize(message.config, message.rules);
1944
- break;
1945
- case 'optIn':
1946
- await this.doOptIn();
1947
- break;
1948
- case 'optOut':
1949
- await this.doOptOut();
1950
- break;
1951
- case 'selfTest':
1952
- await this.doSelfTest();
1953
- break;
1954
- case 'evalResp':
1955
- resolveEval(message.id, message.result);
1956
- break;
1957
- }
1958
- }
1821
+ foundCMPs.push(cmp);
1822
+ }
1823
+ } catch (e) {
1824
+ enableLogs && console.warn(`error detecting ${cmp.name}`, e);
1825
+ }
1826
+ }
1827
+ if (foundCMPs.length === 0 && retries > 0) {
1828
+ await wait(500);
1829
+ return this.findCmp(retries - 1);
1830
+ }
1831
+ return foundCMPs;
1959
1832
  }
1833
+ async detectPopups(cmps) {
1834
+ const result = [];
1835
+ const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
1836
+ if (isOpen) {
1837
+ this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
1838
+ this.sendContentMessage({
1839
+ type: "popupFound",
1840
+ cmp: cmp.name,
1841
+ url: location.href
1842
+ });
1843
+ result.push(cmp);
1844
+ }
1845
+ }).catch(() => null));
1846
+ await Promise.all(popupLookups);
1847
+ return result;
1848
+ }
1849
+ async doOptOut() {
1850
+ this.updateState({ lifecycle: "runningOptOut" });
1851
+ let optOutResult;
1852
+ if (!this.foundCmp) {
1853
+ enableLogs && console.log("no CMP to opt out");
1854
+ optOutResult = false;
1855
+ } else {
1856
+ enableLogs && console.log(`CMP ${this.foundCmp.name}: opt out on ${window.location.href}`);
1857
+ optOutResult = await this.foundCmp.optOut();
1858
+ enableLogs && console.log(`${this.foundCmp.name}: opt out result ${optOutResult}`);
1859
+ }
1860
+ if (this.config.enablePrehide) {
1861
+ this.undoPrehide();
1862
+ }
1863
+ this.sendContentMessage({
1864
+ type: "optOutResult",
1865
+ cmp: this.foundCmp ? this.foundCmp.name : "none",
1866
+ result: optOutResult,
1867
+ scheduleSelfTest: this.foundCmp && this.foundCmp.hasSelfTest,
1868
+ url: location.href
1869
+ });
1870
+ if (optOutResult && !this.foundCmp.isIntermediate) {
1871
+ this.sendContentMessage({
1872
+ type: "autoconsentDone",
1873
+ cmp: this.foundCmp.name,
1874
+ isCosmetic: this.foundCmp.isCosmetic,
1875
+ url: location.href
1876
+ });
1877
+ this.updateState({ lifecycle: "done" });
1878
+ } else {
1879
+ this.updateState({ lifecycle: optOutResult ? "optOutSucceeded" : "optOutFailed" });
1880
+ }
1881
+ return optOutResult;
1882
+ }
1883
+ async doOptIn() {
1884
+ this.updateState({ lifecycle: "runningOptIn" });
1885
+ let optInResult;
1886
+ if (!this.foundCmp) {
1887
+ enableLogs && console.log("no CMP to opt in");
1888
+ optInResult = false;
1889
+ } else {
1890
+ enableLogs && console.log(`CMP ${this.foundCmp.name}: opt in on ${window.location.href}`);
1891
+ optInResult = await this.foundCmp.optIn();
1892
+ enableLogs && console.log(`${this.foundCmp.name}: opt in result ${optInResult}`);
1893
+ }
1894
+ if (this.config.enablePrehide) {
1895
+ this.undoPrehide();
1896
+ }
1897
+ this.sendContentMessage({
1898
+ type: "optInResult",
1899
+ cmp: this.foundCmp ? this.foundCmp.name : "none",
1900
+ result: optInResult,
1901
+ scheduleSelfTest: false,
1902
+ // self-tests are only for opt-out at the moment
1903
+ url: location.href
1904
+ });
1905
+ if (optInResult && !this.foundCmp.isIntermediate) {
1906
+ this.sendContentMessage({
1907
+ type: "autoconsentDone",
1908
+ cmp: this.foundCmp.name,
1909
+ isCosmetic: this.foundCmp.isCosmetic,
1910
+ url: location.href
1911
+ });
1912
+ this.updateState({ lifecycle: "done" });
1913
+ } else {
1914
+ this.updateState({ lifecycle: optInResult ? "optInSucceeded" : "optInFailed" });
1915
+ }
1916
+ return optInResult;
1917
+ }
1918
+ async doSelfTest() {
1919
+ let selfTestResult;
1920
+ if (!this.foundCmp) {
1921
+ enableLogs && console.log("no CMP to self test");
1922
+ selfTestResult = false;
1923
+ } else {
1924
+ enableLogs && console.log(`CMP ${this.foundCmp.name}: self-test on ${window.location.href}`);
1925
+ selfTestResult = await this.foundCmp.test();
1926
+ }
1927
+ this.sendContentMessage({
1928
+ type: "selfTestResult",
1929
+ cmp: this.foundCmp ? this.foundCmp.name : "none",
1930
+ result: selfTestResult,
1931
+ url: location.href
1932
+ });
1933
+ this.updateState({ selfTest: selfTestResult });
1934
+ return selfTestResult;
1935
+ }
1936
+ async waitForPopup(cmp, retries = 5, interval = 500) {
1937
+ enableLogs && console.log("checking if popup is open...", cmp.name);
1938
+ const isOpen = await cmp.detectPopup();
1939
+ if (!isOpen && retries > 0) {
1940
+ await wait(interval);
1941
+ return this.waitForPopup(cmp, retries - 1, interval);
1942
+ }
1943
+ enableLogs && console.log(cmp.name, `popup is ${isOpen ? "open" : "not open"}`);
1944
+ return isOpen;
1945
+ }
1946
+ prehideElements() {
1947
+ const globalHidden = [
1948
+ "#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium"
1949
+ ];
1950
+ const selectors = this.rules.reduce((selectorList, rule) => {
1951
+ if (rule.prehideSelectors) {
1952
+ return [...selectorList, ...rule.prehideSelectors];
1953
+ }
1954
+ return selectorList;
1955
+ }, globalHidden);
1956
+ this.updateState({ prehideOn: true });
1957
+ setTimeout(() => {
1958
+ if (this.config.enablePrehide && this.state.prehideOn && !["runningOptOut", "runningOptIn"].includes(this.state.lifecycle)) {
1959
+ enableLogs && console.log("Process is taking too long, unhiding elements");
1960
+ this.undoPrehide();
1961
+ }
1962
+ }, this.config.prehideTimeout || 2e3);
1963
+ return prehide(selectors);
1964
+ }
1965
+ undoPrehide() {
1966
+ this.updateState({ prehideOn: false });
1967
+ return undoPrehide();
1968
+ }
1969
+ updateState(change) {
1970
+ Object.assign(this.state, change);
1971
+ this.sendContentMessage({
1972
+ type: "report",
1973
+ instanceId: this.id,
1974
+ url: window.location.href,
1975
+ mainFrame: window.top === window.self,
1976
+ state: this.state
1977
+ });
1978
+ }
1979
+ async receiveMessageCallback(message) {
1980
+ if (enableLogs && ["evalResp", "report"].includes(message.type)) {
1981
+ console.log("received from background", message, window.location.href);
1982
+ }
1983
+ switch (message.type) {
1984
+ case "initResp":
1985
+ this.initialize(message.config, message.rules);
1986
+ break;
1987
+ case "optIn":
1988
+ await this.doOptIn();
1989
+ break;
1990
+ case "optOut":
1991
+ await this.doOptOut();
1992
+ break;
1993
+ case "selfTest":
1994
+ await this.doSelfTest();
1995
+ break;
1996
+ case "evalResp":
1997
+ resolveEval(message.id, message.result);
1998
+ break;
1999
+ }
2000
+ }
2001
+ };
1960
2002
 
1961
- const consent = new AutoConsent(chrome.runtime.sendMessage);
1962
- chrome.runtime.onMessage.addListener((message) => {
1963
- return Promise.resolve(consent.receiveMessageCallback(message));
1964
- });
1965
- chrome.runtime.connect({ name: `instance-${consent.id}` });
1966
-
2003
+ // addon/content.ts
2004
+ var consent = new AutoConsent(chrome.runtime.sendMessage);
2005
+ chrome.runtime.onMessage.addListener((message) => {
2006
+ return Promise.resolve(consent.receiveMessageCallback(message));
2007
+ });
2008
+ chrome.runtime.connect({ name: `instance-${consent.id}` });
1967
2009
  })();