@duckduckgo/autoconsent 14.0.1 → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/actions/setup-release-scripts/action.yml +1 -1
- package/.github/workflows/checks.yml +4 -4
- package/.github/workflows/release.yml +2 -2
- package/.github/workflows/update-filterlist.yml +2 -2
- package/CHANGELOG.md +43 -0
- package/api.md +1 -0
- package/dist/addon-firefox/background.bundle.js +11 -2
- package/dist/addon-firefox/content.bundle.js +510 -347
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/background.bundle.js +11 -2
- package/dist/addon-mv3/content.bundle.js +510 -347
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/popup.bundle.js +19 -1
- package/dist/addon-mv3/popup.html +14 -0
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +353 -219
- package/dist/autoconsent.esm.js +354 -219
- package/dist/autoconsent.extra.cjs.js +519 -347
- package/dist/autoconsent.extra.esm.js +520 -347
- package/dist/autoconsent.playwright.js +520 -348
- package/lib/cmps/admiral.ts +6 -6
- package/lib/cmps/base.ts +43 -8
- package/lib/cmps/consentmanager.ts +8 -7
- package/lib/cmps/cookiebot.ts +4 -4
- package/lib/cmps/evidon.ts +2 -2
- package/lib/cmps/klaro.ts +8 -8
- package/lib/cmps/onetrust.ts +6 -6
- package/lib/cmps/sourcepoint-frame.ts +12 -12
- package/lib/cmps/tiktok.ts +3 -3
- package/lib/cmps/trustarc-frame.ts +11 -11
- package/lib/cmps/trustarc-top.ts +2 -6
- package/lib/dom-actions.ts +6 -6
- package/lib/eval-snippets.ts +6 -1
- package/lib/filterlist-engine.ts +2 -2
- package/lib/messages.ts +6 -0
- package/lib/types.ts +3 -2
- package/lib/utils.ts +49 -0
- package/lib/web.ts +50 -37
- package/package.json +2 -2
- package/playwright/runner.ts +1 -1
- package/readme.md +1 -1
- package/rules/autoconsent/cookie-law-info.json +16 -5
- package/rules/autoconsent/cookiehub.json +61 -0
- package/rules/autoconsent/eu-cookie-compliance.json +13 -12
- package/rules/compact-rules.json +1 -1
- package/rules/filterlist.txt +221 -202
- package/rules/rules.json +1 -1
- package/tests/{cookielawinfo.spec.ts → cookie-law-info.spec.ts} +4 -1
- package/tests/cookiehub.spec.ts +8 -0
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests-wtr/dom-actions/dom-actions.click.ts +14 -14
- package/tests-wtr/utils/highlight.test.ts +166 -0
package/lib/cmps/admiral.ts
CHANGED
|
@@ -31,7 +31,7 @@ export default class Admiral extends AutoConsentCMPBase {
|
|
|
31
31
|
"xpath///button[contains(., 'Afvis alle') or contains(., 'Reject all') or contains(., 'Odbaci sve') or contains(., 'Rechazar todo') or contains(., 'Atmesti visus') or contains(., 'Odmítnout vše') or contains(., 'Απόρριψη όλων') or contains(., 'Rejeitar tudo') or contains(., 'Tümünü reddet') or contains(., 'Отклонить все') or contains(., 'Noraidīt visu') or contains(., 'Avvisa alla') or contains(., 'Odrzuć wszystkie') or contains(., 'Alles afwijzen') or contains(., 'Отхвърляне на всички') or contains(., 'Rifiuta tutto') or contains(., 'Zavrni vse') or contains(., 'Az összes elutasítása') or contains(., 'Respingeți tot') or contains(., 'Alles ablehnen') or contains(., 'Tout rejeter') or contains(., 'Odmietnuť všetko') or contains(., 'Lükka kõik tagasi') or contains(., 'Hylkää kaikki')]";
|
|
32
32
|
|
|
33
33
|
if (await this.waitForElement(rejectAllSelector, 500)) {
|
|
34
|
-
return this.click(rejectAllSelector);
|
|
34
|
+
return await this.click(rejectAllSelector);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const purposesButtonSelector =
|
|
@@ -41,18 +41,18 @@ export default class Admiral extends AutoConsentCMPBase {
|
|
|
41
41
|
"xpath///button[contains(., 'Spara & avsluta') or contains(., 'Save & exit') or contains(., 'Uložit a ukončit') or contains(., 'Enregistrer et quitter') or contains(., 'Speichern & Verlassen') or contains(., 'Tallenna ja poistu') or contains(., 'Išsaugoti ir išeiti') or contains(., 'Opslaan & afsluiten') or contains(., 'Guardar y salir') or contains(., 'Shrani in zapri') or contains(., 'Uložiť a ukončiť') or contains(., 'Kaydet ve çıkış yap') or contains(., 'Сохранить и выйти') or contains(., 'Salvesta ja välju') or contains(., 'Salva ed esci') or contains(., 'Gem & afslut') or contains(., 'Αποθήκευση και έξοδος') or contains(., 'Saglabāt un iziet') or contains(., 'Mentés és kilépés') or contains(., 'Guardar e sair') or contains(., 'Zapisz & zakończ') or contains(., 'Salvare și ieșire') or contains(., 'Spremi i izađi') or contains(., 'Запазване и изход')]";
|
|
42
42
|
|
|
43
43
|
if ((await this.waitForThenClick(purposesButtonSelector)) && (await this.waitForVisible(saveAndExitSelector))) {
|
|
44
|
-
const popupBody = this.elementSelector(saveAndExitSelector)[0].parentElement
|
|
45
|
-
const checkboxes = popupBody
|
|
46
|
-
checkboxes
|
|
44
|
+
const popupBody = this.elementSelector(saveAndExitSelector)[0].parentElement?.parentElement;
|
|
45
|
+
const checkboxes = popupBody?.querySelectorAll<HTMLElement>('input[type=checkbox]:checked');
|
|
46
|
+
checkboxes?.forEach((checkbox) => checkbox.click());
|
|
47
47
|
|
|
48
|
-
return this.click(saveAndExitSelector);
|
|
48
|
+
return await this.click(saveAndExitSelector);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
async optIn() {
|
|
55
|
-
return this.click(
|
|
55
|
+
return await this.click(
|
|
56
56
|
"xpath///button[contains(., 'Sprejmi vse') or contains(., 'Prihvati sve') or contains(., 'Godkänn alla') or contains(., 'Prijať všetko') or contains(., 'Принять все') or contains(., 'Aceptar todo') or contains(., 'Αποδοχή όλων') or contains(., 'Zaakceptuj wszystkie') or contains(., 'Accetta tutto') or contains(., 'Priimti visus') or contains(., 'Pieņemt visu') or contains(., 'Tümünü kabul et') or contains(., 'Az összes elfogadása') or contains(., 'Accept all') or contains(., 'Приемане на всички') or contains(., 'Accepter alle') or contains(., 'Hyväksy kaikki') or contains(., 'Tout accepter') or contains(., 'Alles accepteren') or contains(., 'Aktsepteeri kõik') or contains(., 'Přijmout vše') or contains(., 'Alles akzeptieren') or contains(., 'Aceitar tudo') or contains(., 'Acceptați tot')]",
|
|
57
57
|
);
|
|
58
58
|
}
|
package/lib/cmps/base.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AutoConsentCMPRule, AutoConsentRuleStep, ElementSelector, HideMethod, R
|
|
|
3
3
|
import { requestEval } from '../eval-handler';
|
|
4
4
|
import AutoConsent from '../web';
|
|
5
5
|
import { getFunctionBody, snippets } from '../eval-snippets';
|
|
6
|
+
import { highlightNode, unhighlightNode } from '../utils';
|
|
6
7
|
|
|
7
8
|
export async function success(action: Promise<boolean>): Promise<boolean> {
|
|
8
9
|
const result = await action;
|
|
@@ -19,7 +20,7 @@ export const defaultRunContext: RunContext = {
|
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
22
|
-
name: string;
|
|
23
|
+
name: string = 'BASERULE';
|
|
23
24
|
runContext: RunContext = defaultRunContext;
|
|
24
25
|
autoconsent: AutoConsent;
|
|
25
26
|
|
|
@@ -94,7 +95,7 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
hasMatchingUrlPattern(): boolean {
|
|
97
|
-
return this.runContext?.urlPattern &&
|
|
98
|
+
return Boolean(this.runContext?.urlPattern && window.location.href.match(this.runContext.urlPattern));
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
detectCmp(): Promise<boolean> {
|
|
@@ -122,8 +123,35 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
122
123
|
return Promise.resolve(true);
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
async highlightElements(selector: ElementSelector, all = false, delayTimeout = 2000) {
|
|
127
|
+
let elements = this.elementSelector(selector);
|
|
128
|
+
if (elements.length === 0) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!all) {
|
|
132
|
+
elements = [elements[0]];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.autoconsent.sendContentMessage({
|
|
136
|
+
type: 'visualDelay',
|
|
137
|
+
timeout: delayTimeout,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
for (const el of elements) {
|
|
141
|
+
this.autoconsent.config.logs.rulesteps && console.log('highlighting', el);
|
|
142
|
+
highlightNode(el);
|
|
143
|
+
}
|
|
144
|
+
await this.wait(delayTimeout);
|
|
145
|
+
for (const el of elements) {
|
|
146
|
+
unhighlightNode(el);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
125
150
|
// Implementing DomActionsProvider below:
|
|
126
|
-
click(selector: ElementSelector, all = false) {
|
|
151
|
+
async click(selector: ElementSelector, all = false) {
|
|
152
|
+
if (this.autoconsent.config.visualTest) {
|
|
153
|
+
await this.highlightElements(selector, all);
|
|
154
|
+
}
|
|
127
155
|
return this.autoconsent.domActions.click(selector, all);
|
|
128
156
|
}
|
|
129
157
|
|
|
@@ -131,7 +159,7 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
131
159
|
return this.autoconsent.domActions.elementExists(selector);
|
|
132
160
|
}
|
|
133
161
|
|
|
134
|
-
elementVisible(selector: ElementSelector, check
|
|
162
|
+
elementVisible(selector: ElementSelector, check?: VisibilityCheck) {
|
|
135
163
|
return this.autoconsent.domActions.elementVisible(selector, check);
|
|
136
164
|
}
|
|
137
165
|
|
|
@@ -143,7 +171,10 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
143
171
|
return this.autoconsent.domActions.waitForVisible(selector, timeout, check);
|
|
144
172
|
}
|
|
145
173
|
|
|
146
|
-
waitForThenClick(selector: ElementSelector, timeout?: number, all?: boolean) {
|
|
174
|
+
async waitForThenClick(selector: ElementSelector, timeout?: number, all?: boolean) {
|
|
175
|
+
if (this.autoconsent.config.visualTest) {
|
|
176
|
+
await this.highlightElements(selector, all);
|
|
177
|
+
}
|
|
147
178
|
return this.autoconsent.domActions.waitForThenClick(selector, timeout, all);
|
|
148
179
|
}
|
|
149
180
|
|
|
@@ -151,7 +182,7 @@ export default class AutoConsentCMPBase implements AutoCMP, DomActionsProvider {
|
|
|
151
182
|
return this.autoconsent.domActions.wait(ms);
|
|
152
183
|
}
|
|
153
184
|
|
|
154
|
-
hide(selector: string, method
|
|
185
|
+
hide(selector: string, method?: HideMethod) {
|
|
155
186
|
return this.autoconsent.domActions.hide(selector, method);
|
|
156
187
|
}
|
|
157
188
|
|
|
@@ -207,7 +238,7 @@ export class AutoConsentCMP extends AutoConsentCMPBase {
|
|
|
207
238
|
}
|
|
208
239
|
|
|
209
240
|
get prehideSelectors(): string[] {
|
|
210
|
-
return this.rule.prehideSelectors;
|
|
241
|
+
return this.rule.prehideSelectors || [];
|
|
211
242
|
}
|
|
212
243
|
|
|
213
244
|
async detectCmp() {
|
|
@@ -250,7 +281,7 @@ export class AutoConsentCMP extends AutoConsentCMPBase {
|
|
|
250
281
|
}
|
|
251
282
|
|
|
252
283
|
async test() {
|
|
253
|
-
if (this.hasSelfTest) {
|
|
284
|
+
if (this.hasSelfTest && this.rule.test) {
|
|
254
285
|
return this._runRulesSequentially(this.rule.test, this.autoconsent.config.logs.rulesteps);
|
|
255
286
|
}
|
|
256
287
|
return super.test();
|
|
@@ -295,6 +326,10 @@ export class AutoConsentCMP extends AutoConsentCMPBase {
|
|
|
295
326
|
console.error('invalid conditional rule', rule.if);
|
|
296
327
|
return false;
|
|
297
328
|
}
|
|
329
|
+
if (!rule.then) {
|
|
330
|
+
console.error('invalid conditional rule, missing "then" step', rule.if);
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
298
333
|
const condition = await this.evaluateRuleStep(rule.if);
|
|
299
334
|
logsConfig.rulesteps && console.log('Condition is', condition);
|
|
300
335
|
if (condition) {
|
|
@@ -45,20 +45,20 @@ export default class ConsentManager extends AutoConsentCMPBase {
|
|
|
45
45
|
return await this.mainWorldEval('EVAL_CONSENTMANAGER_3');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
if (this.click('.cmpboxbtnno')) {
|
|
48
|
+
if (await this.click('.cmpboxbtnno')) {
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (this.elementExists('.cmpwelcomeprpsbtn')) {
|
|
53
|
-
this.click('.cmpwelcomeprpsbtn > a[aria-checked=true]', true);
|
|
54
|
-
this.click('.cmpboxbtnsave');
|
|
53
|
+
await this.click('.cmpwelcomeprpsbtn > a[aria-checked=true]', true);
|
|
54
|
+
await this.click('.cmpboxbtnsave');
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
this.click('.cmpboxbtncustom');
|
|
58
|
+
await this.click('.cmpboxbtncustom');
|
|
59
59
|
await this.waitForElement('.cmptblbox', 2000);
|
|
60
|
-
this.click('.cmptdchoice > a[aria-checked=true]', true);
|
|
61
|
-
this.click('.cmpboxbtnyescustomchoices');
|
|
60
|
+
await this.click('.cmptdchoice > a[aria-checked=true]', true);
|
|
61
|
+
await this.click('.cmpboxbtnyescustomchoices');
|
|
62
62
|
|
|
63
63
|
this.hide('#cmpwrapper,#cmpbox', 'display');
|
|
64
64
|
return true;
|
|
@@ -68,12 +68,13 @@ export default class ConsentManager extends AutoConsentCMPBase {
|
|
|
68
68
|
if (this.apiAvailable) {
|
|
69
69
|
return await this.mainWorldEval('EVAL_CONSENTMANAGER_4');
|
|
70
70
|
}
|
|
71
|
-
return this.click('.cmpboxbtnyes');
|
|
71
|
+
return await this.click('.cmpboxbtnyes');
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async test() {
|
|
75
75
|
if (this.apiAvailable) {
|
|
76
76
|
return await this.mainWorldEval('EVAL_CONSENTMANAGER_5');
|
|
77
77
|
}
|
|
78
|
+
return false;
|
|
78
79
|
}
|
|
79
80
|
}
|
package/lib/cmps/cookiebot.ts
CHANGED
|
@@ -36,12 +36,12 @@ export default class Cookiebot extends AutoConsentCMPBase {
|
|
|
36
36
|
|
|
37
37
|
async optIn() {
|
|
38
38
|
if (this.elementExists('#dtcookie-container')) {
|
|
39
|
-
return this.click('.h-dtcookie-accept');
|
|
39
|
+
return await this.click('.h-dtcookie-accept');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
this.click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
|
|
43
|
-
this.click('#CybotCookiebotDialogBodyLevelButtonAccept');
|
|
44
|
-
this.click('#CybotCookiebotDialogBodyButtonAccept');
|
|
42
|
+
await this.click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
|
|
43
|
+
await this.click('#CybotCookiebotDialogBodyLevelButtonAccept');
|
|
44
|
+
await this.click('#CybotCookiebotDialogBodyButtonAccept');
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
47
|
|
package/lib/cmps/evidon.ts
CHANGED
|
@@ -25,7 +25,7 @@ export default class Evidon extends AutoConsentCMPBase {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
async optOut() {
|
|
28
|
-
if (this.click('#_evidon-decline-button')) {
|
|
28
|
+
if (await this.click('#_evidon-decline-button')) {
|
|
29
29
|
return true;
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -40,6 +40,6 @@ export default class Evidon extends AutoConsentCMPBase {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async optIn() {
|
|
43
|
-
return this.click('#_evidon-accept-button');
|
|
43
|
+
return await this.click('#_evidon-accept-button');
|
|
44
44
|
}
|
|
45
45
|
}
|
package/lib/cmps/klaro.ts
CHANGED
|
@@ -36,33 +36,33 @@ export default class Klaro extends AutoConsentCMPBase {
|
|
|
36
36
|
}
|
|
37
37
|
// if the API is broken for some reason, try clicking instead
|
|
38
38
|
|
|
39
|
-
if (this.click('.klaro .cn-decline')) {
|
|
39
|
+
if (await this.click('.klaro .cn-decline')) {
|
|
40
40
|
return true;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// open popup via Javascript API
|
|
44
44
|
await this.mainWorldEval('EVAL_KLARO_OPEN_POPUP');
|
|
45
45
|
|
|
46
|
-
if (this.click('.klaro .cn-decline')) {
|
|
46
|
+
if (await this.click('.klaro .cn-decline')) {
|
|
47
47
|
return true;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
this.click(
|
|
50
|
+
await this.click(
|
|
51
51
|
'.cm-purpose:not(.cm-toggle-all) > input:not(.half-checked,.required,.only-required),.cm-purpose:not(.cm-toggle-all) > div > input:not(.half-checked,.required,.only-required)',
|
|
52
52
|
true,
|
|
53
53
|
);
|
|
54
|
-
return this.click('.cm-btn-accept,.cm-button');
|
|
54
|
+
return await this.click('.cm-btn-accept,.cm-button');
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
async optIn() {
|
|
58
|
-
if (this.click('.klaro .cm-btn-accept-all')) {
|
|
58
|
+
if (await this.click('.klaro .cm-btn-accept-all')) {
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
61
|
if (this.settingsOpen) {
|
|
62
|
-
this.click('.cm-purpose:not(.cm-toggle-all) > input.half-checked', true);
|
|
63
|
-
return this.click('.cm-btn-accept');
|
|
62
|
+
await this.click('.cm-purpose:not(.cm-toggle-all) > input.half-checked', true);
|
|
63
|
+
return await this.click('.cm-btn-accept');
|
|
64
64
|
}
|
|
65
|
-
return this.click('.klaro .cookie-notice .cm-btn-success');
|
|
65
|
+
return await this.click('.klaro .cookie-notice .cm-btn-success');
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
async test() {
|
package/lib/cmps/onetrust.ts
CHANGED
|
@@ -28,24 +28,24 @@ export default class Onetrust extends AutoConsentCMPBase {
|
|
|
28
28
|
async optOut() {
|
|
29
29
|
if (this.elementVisible('#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies', 'any')) {
|
|
30
30
|
// 'reject all' shortcut
|
|
31
|
-
return this.click('#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies');
|
|
31
|
+
return await this.click('#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies');
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
if (this.elementExists('#onetrust-pc-btn-handler')) {
|
|
35
35
|
// "show purposes" button inside a popup
|
|
36
|
-
this.click('#onetrust-pc-btn-handler');
|
|
36
|
+
await this.click('#onetrust-pc-btn-handler');
|
|
37
37
|
} else {
|
|
38
38
|
// otherwise look for a generic "show settings" button
|
|
39
|
-
this.click('.ot-sdk-show-settings,button.js-cookie-settings');
|
|
39
|
+
await this.click('.ot-sdk-show-settings,button.js-cookie-settings');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
await this.waitForElement('#onetrust-consent-sdk', 2000);
|
|
43
43
|
await this.wait(1000); // ideally we want to wait for popup visivility, but it's tricky on e.g. stackoverflow.com
|
|
44
|
-
this.click('#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked', true); // optional step
|
|
44
|
+
await this.click('#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked', true); // optional step
|
|
45
45
|
|
|
46
46
|
await this.wait(1000); // ideally we want to wait for popup visivility, but it's tricky on e.g. stackoverflow.com
|
|
47
47
|
await this.waitForElement('.save-preference-btn-handler,.js-consent-save', 2000);
|
|
48
|
-
this.click('.save-preference-btn-handler,.js-consent-save');
|
|
48
|
+
await this.click('.save-preference-btn-handler,.js-consent-save');
|
|
49
49
|
|
|
50
50
|
// popup doesn't disappear immediately
|
|
51
51
|
await this.waitForVisible('#onetrust-banner-sdk', 5000, 'none');
|
|
@@ -53,7 +53,7 @@ export default class Onetrust extends AutoConsentCMPBase {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
async optIn() {
|
|
56
|
-
return this.click('#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies');
|
|
56
|
+
return await this.click('#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
async test() {
|
|
@@ -62,11 +62,11 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
62
62
|
|
|
63
63
|
async optIn() {
|
|
64
64
|
await this.waitForElement('.sp_choice_type_11,.sp_choice_type_ACCEPT_ALL', 2000);
|
|
65
|
-
if (this.click('.sp_choice_type_11')) {
|
|
65
|
+
if (await this.click('.sp_choice_type_11')) {
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
if (this.click('.sp_choice_type_ACCEPT_ALL')) {
|
|
69
|
+
if (await this.click('.sp_choice_type_ACCEPT_ALL')) {
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
72
72
|
return false;
|
|
@@ -96,20 +96,20 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
96
96
|
for (const t of switches) {
|
|
97
97
|
t.click();
|
|
98
98
|
}
|
|
99
|
-
return this.click('.priv-save-btn');
|
|
99
|
+
return await this.click('.priv-save-btn');
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// sometimes there's a "Save and Exit" / "Essential cookies" button
|
|
103
103
|
if (this.elementVisible('.sp_choice_type_SE', 'any')) {
|
|
104
104
|
// click the "Do Not Sell" toggle if it exists
|
|
105
|
-
this.click(
|
|
105
|
+
await this.click(
|
|
106
106
|
[
|
|
107
107
|
"xpath///div[contains(., 'Do not share my personal information') and contains(@class, 'switch-container')]",
|
|
108
108
|
'.pm-switch[aria-checked=false] .slider',
|
|
109
109
|
],
|
|
110
110
|
false,
|
|
111
111
|
);
|
|
112
|
-
return this.click('.sp_choice_type_SE');
|
|
112
|
+
return await this.click('.sp_choice_type_SE');
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
if (!this.isManagerOpen()) {
|
|
@@ -120,10 +120,10 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
120
120
|
|
|
121
121
|
if (!this.elementExists('.sp_choice_type_12,[data-choice="1739968508799"]')) {
|
|
122
122
|
// do not sell button
|
|
123
|
-
return this.click('.sp_choice_type_13');
|
|
123
|
+
return await this.click('.sp_choice_type_13');
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
this.click('.sp_choice_type_12,[data-choice="1739968508799"]');
|
|
126
|
+
await this.click('.sp_choice_type_12,[data-choice="1739968508799"]');
|
|
127
127
|
// the page may navigate at this point but that's okay
|
|
128
128
|
await waitFor(() => this.isManagerOpen(), 200, 100);
|
|
129
129
|
}
|
|
@@ -148,18 +148,18 @@ export default class SourcePoint extends AutoConsentCMPBase {
|
|
|
148
148
|
|
|
149
149
|
if (path === 0) {
|
|
150
150
|
await this.waitForVisible(rejectSelector1);
|
|
151
|
-
return this.click(rejectSelector1);
|
|
151
|
+
return await this.click(rejectSelector1);
|
|
152
152
|
} else if (path === 1) {
|
|
153
|
-
this.click(rejectSelector2);
|
|
153
|
+
await this.click(rejectSelector2);
|
|
154
154
|
} else if (path === 2) {
|
|
155
155
|
await this.waitForElement('.pm-features', 10000);
|
|
156
|
-
this.click('.checked > span', true);
|
|
157
|
-
this.click('.chevron');
|
|
156
|
+
await this.click('.checked > span', true);
|
|
157
|
+
await this.click('.chevron');
|
|
158
158
|
}
|
|
159
159
|
} catch (e) {
|
|
160
160
|
logsConfig.errors && console.warn(e);
|
|
161
161
|
}
|
|
162
162
|
// TODO: race condition: if the reject button was clicked, the popup disappears very quickly, so the background script may not receive a success report.
|
|
163
|
-
return this.click('.sp_choice_type_SAVE_AND_EXIT');
|
|
163
|
+
return await this.click('.sp_choice_type_SAVE_AND_EXIT');
|
|
164
164
|
}
|
|
165
165
|
}
|
package/lib/cmps/tiktok.ts
CHANGED
|
@@ -34,13 +34,13 @@ export default class Tiktok extends AutoConsentCMPBase {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
async detectPopup() {
|
|
37
|
-
const banner = this.getShadowRoot()
|
|
37
|
+
const banner = this.getShadowRoot()?.querySelector('.tiktok-cookie-banner') as HTMLElement;
|
|
38
38
|
return isElementVisible(banner);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
async optOut() {
|
|
42
42
|
const logsConfig = this.autoconsent.config.logs;
|
|
43
|
-
const declineButton = this.getShadowRoot()
|
|
43
|
+
const declineButton = this.getShadowRoot()?.querySelector('.button-wrapper button:first-child') as HTMLElement;
|
|
44
44
|
if (declineButton) {
|
|
45
45
|
logsConfig.rulesteps && console.log('[clicking]', declineButton);
|
|
46
46
|
declineButton.click();
|
|
@@ -53,7 +53,7 @@ export default class Tiktok extends AutoConsentCMPBase {
|
|
|
53
53
|
|
|
54
54
|
async optIn() {
|
|
55
55
|
const logsConfig = this.autoconsent.config.logs;
|
|
56
|
-
const acceptButton = this.getShadowRoot()
|
|
56
|
+
const acceptButton = this.getShadowRoot()?.querySelector('.button-wrapper button:last-child') as HTMLElement;
|
|
57
57
|
if (acceptButton) {
|
|
58
58
|
logsConfig.rulesteps && console.log('[clicking]', acceptButton);
|
|
59
59
|
acceptButton.click();
|
|
@@ -45,14 +45,14 @@ export default class TrustArcFrame extends AutoConsentCMPBase {
|
|
|
45
45
|
);
|
|
46
46
|
// splash screen -> hit more information
|
|
47
47
|
if (this.elementExists('.shp')) {
|
|
48
|
-
this.click('.shp');
|
|
48
|
+
await this.click('.shp');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
await this.waitForElement('.prefPanel', 5000);
|
|
52
52
|
|
|
53
53
|
// go to advanced settings if not yet shown
|
|
54
54
|
if (this.elementVisible('.advance', 'any')) {
|
|
55
|
-
this.click('.advance');
|
|
55
|
+
await this.click('.advance');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// takes a while to load the opt-in/opt-out buttons
|
|
@@ -74,7 +74,7 @@ export default class TrustArcFrame extends AutoConsentCMPBase {
|
|
|
74
74
|
await waitFor(() => document.readyState === 'complete', 20, 100);
|
|
75
75
|
await this.waitForElement('.mainContent[aria-hidden=false]', timeout);
|
|
76
76
|
|
|
77
|
-
if (this.click('.rejectAll')) {
|
|
77
|
+
if (await this.click('.rejectAll')) {
|
|
78
78
|
return true;
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -82,22 +82,22 @@ export default class TrustArcFrame extends AutoConsentCMPBase {
|
|
|
82
82
|
await this.waitForElement('.prefPanel[style="visibility: visible;"]', timeout);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
if (this.click('#catDetails0')) {
|
|
86
|
-
this.click('.submit');
|
|
85
|
+
if (await this.click('#catDetails0')) {
|
|
86
|
+
await this.click('.submit');
|
|
87
87
|
this.waitForThenClick('#gwt-debug-close_id', timeout);
|
|
88
88
|
return true;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
if (this.click('.required')) {
|
|
91
|
+
if (await this.click('.required')) {
|
|
92
92
|
this.waitForThenClick('#gwt-debug-close_id', timeout);
|
|
93
93
|
return true;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
await this.navigateToSettings();
|
|
97
97
|
|
|
98
|
-
this.click('.switch span:nth-child(1):not(.active)', true);
|
|
98
|
+
await this.click('.switch span:nth-child(1):not(.active)', true);
|
|
99
99
|
|
|
100
|
-
this.click('.submit');
|
|
100
|
+
await this.click('.submit');
|
|
101
101
|
|
|
102
102
|
// at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
|
|
103
103
|
this.waitForThenClick('#gwt-debug-close_id', timeout * 10);
|
|
@@ -106,13 +106,13 @@ export default class TrustArcFrame extends AutoConsentCMPBase {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async optIn() {
|
|
109
|
-
if (this.click('.call')) {
|
|
109
|
+
if (await this.click('.call')) {
|
|
110
110
|
return true;
|
|
111
111
|
}
|
|
112
112
|
await this.navigateToSettings();
|
|
113
|
-
this.click('.switch span:nth-child(2)', true);
|
|
113
|
+
await this.click('.switch span:nth-child(2)', true);
|
|
114
114
|
|
|
115
|
-
this.click('.submit');
|
|
115
|
+
await this.click('.submit');
|
|
116
116
|
|
|
117
117
|
// at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
|
|
118
118
|
this.waitForElement('#gwt-debug-close_id', 300000).then(() => {
|
package/lib/cmps/trustarc-top.ts
CHANGED
|
@@ -56,10 +56,6 @@ export default class TrustArcTop extends AutoConsentCMPBase {
|
|
|
56
56
|
return this.elementVisible(`${popupContent},${bannerOverlay},${bannerContainer}`, 'any');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
openFrame() {
|
|
60
|
-
this.click(cookieSettingsButton);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
59
|
async optOut() {
|
|
64
60
|
if (this._shortcutButton) {
|
|
65
61
|
this._shortcutButton.click();
|
|
@@ -68,7 +64,7 @@ export default class TrustArcTop extends AutoConsentCMPBase {
|
|
|
68
64
|
|
|
69
65
|
// hide elements permanently, so user doesn't see the popup
|
|
70
66
|
hideElements(getStyleElement(), `.truste_popframe, .truste_overlay, .truste_box_overlay, ${bannerContainer}`);
|
|
71
|
-
this.click(cookieSettingsButton);
|
|
67
|
+
await this.click(cookieSettingsButton);
|
|
72
68
|
|
|
73
69
|
// schedule cleanup
|
|
74
70
|
setTimeout(() => {
|
|
@@ -80,7 +76,7 @@ export default class TrustArcTop extends AutoConsentCMPBase {
|
|
|
80
76
|
|
|
81
77
|
async optIn() {
|
|
82
78
|
this._optInDone = true; // just a hack to force autoconsentDone
|
|
83
|
-
return this.click(shortcutOptIn);
|
|
79
|
+
return await this.click(shortcutOptIn);
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
async openCmp() {
|
package/lib/dom-actions.ts
CHANGED
|
@@ -7,7 +7,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
7
7
|
// eslint-disable-next-line no-useless-constructor
|
|
8
8
|
constructor(public autoconsentInstance: AutoConsent) {}
|
|
9
9
|
|
|
10
|
-
click(selector: ElementSelector, all = false): boolean {
|
|
10
|
+
async click(selector: ElementSelector, all = false): Promise<boolean> {
|
|
11
11
|
const elem = this.elementSelector(selector);
|
|
12
12
|
this.autoconsentInstance.config.logs.rulesteps && console.log('[click]', selector, all, elem);
|
|
13
13
|
if (elem.length > 0) {
|
|
@@ -25,7 +25,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
25
25
|
return exists;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
elementVisible(selector: ElementSelector, check: VisibilityCheck): boolean {
|
|
28
|
+
elementVisible(selector: ElementSelector, check: VisibilityCheck = 'all'): boolean {
|
|
29
29
|
const elem = this.elementSelector(selector);
|
|
30
30
|
const results = new Array(elem.length);
|
|
31
31
|
elem.forEach((e, i) => {
|
|
@@ -59,7 +59,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
59
59
|
|
|
60
60
|
async waitForThenClick(selector: ElementSelector, timeout = 10000, all = false): Promise<boolean> {
|
|
61
61
|
await this.waitForElement(selector, timeout);
|
|
62
|
-
return this.click(selector, all);
|
|
62
|
+
return await this.click(selector, all);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
wait(ms: number): Promise<true> {
|
|
@@ -76,7 +76,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
76
76
|
return document.cookie.includes(substring);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
hide(selector: string, method
|
|
79
|
+
hide(selector: string, method?: HideMethod): boolean {
|
|
80
80
|
this.autoconsentInstance.config.logs.rulesteps && console.log('[hide]', selector);
|
|
81
81
|
const styleEl = getStyleElement();
|
|
82
82
|
return hideElements(styleEl, selector, method);
|
|
@@ -118,7 +118,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
118
118
|
if (selector.startsWith('xpath/')) {
|
|
119
119
|
const xpath = selector.slice(6);
|
|
120
120
|
const result = document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
|
|
121
|
-
let node: Node = null;
|
|
121
|
+
let node: Node | null = null;
|
|
122
122
|
const elements: HTMLElement[] = [];
|
|
123
123
|
while ((node = result.iterateNext())) {
|
|
124
124
|
elements.push(node as HTMLElement);
|
|
@@ -142,7 +142,7 @@ export class DomActions implements DomActionsProvider {
|
|
|
142
142
|
|
|
143
143
|
querySelectorChain(selectors: string[]): HTMLElement[] {
|
|
144
144
|
let parent: ParentNode = document;
|
|
145
|
-
let matches: HTMLElement[];
|
|
145
|
+
let matches: HTMLElement[] = [];
|
|
146
146
|
for (const selector of selectors) {
|
|
147
147
|
matches = this.querySingleReplySelector(selector, parent);
|
|
148
148
|
if (matches.length === 0) {
|
package/lib/eval-snippets.ts
CHANGED
|
@@ -79,7 +79,12 @@ export const snippets = {
|
|
|
79
79
|
EVAL_COINBASE_0: () =>
|
|
80
80
|
JSON.parse(decodeURIComponent(document.cookie.match(/cm_(eu|default)_preferences=([0-9a-zA-Z\\{\\}\\[\\]%:]*);?/)[2])).consent
|
|
81
81
|
.length <= 1,
|
|
82
|
-
EVAL_COOKIE_LAW_INFO_0: () =>
|
|
82
|
+
EVAL_COOKIE_LAW_INFO_0: () => {
|
|
83
|
+
if (CLI.disableAllCookies) CLI.disableAllCookies();
|
|
84
|
+
if (CLI.reject_close) CLI.reject_close();
|
|
85
|
+
document.body.classList.remove('cli-barmodal-open');
|
|
86
|
+
return true;
|
|
87
|
+
},
|
|
83
88
|
EVAL_COOKIE_LAW_INFO_DETECT: () => !!window.CLI,
|
|
84
89
|
EVAL_COOKIE_MANAGER_POPUP_0: () =>
|
|
85
90
|
JSON.parse(
|