@duckduckgo/autoconsent 16.59.0 → 16.61.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/.agents/lib/regional-testing/harness.mjs +4 -172
- package/.agents/skills/oxylabs-testing/SKILL.md +4 -4
- package/.agents/skills/oxylabs-testing/scripts/oxylabs.mjs +17 -164
- package/.agents/skills/oxylabs-testing/scripts/oxylabs.test.mjs +6 -3
- package/.agents/skills/verify-pr/SKILL.md +1 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +107 -0
- package/Jenkinsfile +36 -1
- package/dist/addon-firefox/background.bundle.js +21 -0
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +253 -93
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rule-index.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/background.bundle.js +21 -0
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/content.bundle.js +253 -93
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/rule-index.json +1 -1
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +253 -93
- package/dist/autoconsent.esm.js +253 -93
- package/dist/autoconsent.playwright.js +253 -93
- package/dist/autoconsent.standalone.js +254 -94
- package/dist/heuristics.cjs.js +29 -3
- package/dist/heuristics.mjs +28 -3
- package/dist/types/cmps/onetrust.d.ts +1 -0
- package/dist/types/eval-snippets.d.ts +3 -0
- package/dist/types/heuristic-classify.d.ts +1 -0
- package/dist/types/heuristics.d.ts +10 -1
- package/lib/cmps/onetrust.ts +15 -0
- package/lib/eval-snippets.ts +21 -0
- package/lib/heuristic-classify.ts +6 -0
- package/lib/heuristic-patterns.ts +26 -1
- package/lib/heuristics.ts +256 -104
- package/package.json +1 -1
- package/playwright/isolated-world.mjs +217 -0
- package/playwright/oxylabs.mjs +196 -0
- package/playwright/runner.ts +183 -39
- package/playwright.config.ts +4 -1
- package/rules/autoconsent/aeolservice.json +39 -0
- package/rules/autoconsent/airbnb.json +32 -0
- package/rules/autoconsent/amazon-music.json +13 -0
- package/rules/autoconsent/annunci69.json +19 -0
- package/rules/autoconsent/appconsent.json +6 -1
- package/rules/autoconsent/arbeidsplassen-nav-no.json +33 -0
- package/rules/autoconsent/att.json +36 -0
- package/rules/autoconsent/auctionet.json +39 -0
- package/rules/autoconsent/autodoc.json +18 -0
- package/rules/autoconsent/bbc.com-orb-cosmetic.json +34 -0
- package/rules/autoconsent/bbc.com.json +8 -5
- package/rules/autoconsent/bokadirekt.se.json +50 -0
- package/rules/autoconsent/bouvet-cookiepanel.json +29 -0
- package/rules/autoconsent/com-consent-layer.json +10 -0
- package/rules/autoconsent/consent-studio.json +25 -13
- package/rules/autoconsent/cookielegit.json +21 -0
- package/rules/autoconsent/cookieprompter.json +21 -0
- package/rules/autoconsent/cookiereports.json +10 -0
- package/rules/autoconsent/cookietractor.json +37 -0
- package/rules/autoconsent/de-volksbank.json +14 -0
- package/rules/autoconsent/dpgmedia-nl.json +20 -8
- package/rules/autoconsent/eon.pl.json +18 -0
- package/rules/autoconsent/eroticiracconti-it.json +13 -0
- package/rules/autoconsent/ersatzteile-24.json +49 -0
- package/rules/autoconsent/fastweb-cookie-center.json +13 -0
- package/rules/autoconsent/futurabolzano-it.json +35 -0
- package/rules/autoconsent/gobasic.json +10 -0
- package/rules/autoconsent/gravito.json +23 -16
- package/rules/autoconsent/hacon-next-gen.json +41 -0
- package/rules/autoconsent/ing-de.json +31 -0
- package/rules/autoconsent/interia.json +1 -4
- package/rules/autoconsent/intesasanpaolo.json +37 -0
- package/rules/autoconsent/jobindex.json +40 -0
- package/rules/autoconsent/kaspersky-cookies-notification.json +9 -0
- package/rules/autoconsent/lantmateriet.json +13 -0
- package/rules/autoconsent/livsmedelsverket.json +18 -0
- package/rules/autoconsent/mainichi.json +39 -0
- package/rules/autoconsent/mango.json +56 -0
- package/rules/autoconsent/nederlandseloterij.json +35 -0
- package/rules/autoconsent/newsbreak.json +16 -0
- package/rules/autoconsent/nhsapp.json +10 -0
- package/rules/autoconsent/nordea.json +21 -0
- package/rules/autoconsent/nordnet.json +33 -0
- package/rules/autoconsent/ok.json +4 -12
- package/rules/autoconsent/onlineradiobox.json +35 -0
- package/rules/autoconsent/pe-cookies.json +30 -0
- package/rules/autoconsent/pensionsmyndigheten.json +13 -0
- package/rules/autoconsent/pro-euclp-cookies-box.json +31 -0
- package/rules/autoconsent/pubfactory.json +45 -0
- package/rules/autoconsent/puesc-gov-pl.json +37 -0
- package/rules/autoconsent/rambler.json +30 -0
- package/rules/autoconsent/rejestr-io.json +36 -0
- package/rules/autoconsent/sas.json +6 -6
- package/rules/autoconsent/scb.se.json +13 -0
- package/rules/autoconsent/schumacher.com.json +53 -0
- package/rules/autoconsent/sitevision.json +18 -1
- package/rules/autoconsent/skatteverket-se.json +33 -0
- package/rules/autoconsent/smile-insurances.json +13 -0
- package/rules/autoconsent/studentapan.json +16 -0
- package/rules/autoconsent/svt.se.json +7 -7
- package/rules/autoconsent/temu.json +12 -16
- package/rules/autoconsent/thecode.json +21 -0
- package/rules/autoconsent/tv2reg-cookie-notice.json +39 -0
- package/rules/autoconsent/uk-parliament.json +19 -0
- package/rules/autoconsent/wirtualna-polska.json +13 -10
- package/rules/autoconsent/xenforo-cookie-consent.json +62 -0
- package/rules/autoconsent/zorginstituut-cookiewarning.json +33 -0
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/aeolservice.spec.ts +5 -0
- package/tests/airbnb.spec.ts +3 -0
- package/tests/amazon-music.spec.ts +9 -0
- package/tests/annunci69.spec.ts +5 -0
- package/tests/appconsent.spec.ts +6 -0
- package/tests/arbeidsplassen-nav-no.spec.ts +3 -0
- package/tests/att.spec.ts +3 -0
- package/tests/auctionet.spec.ts +3 -0
- package/tests/autodoc.spec.ts +8 -0
- package/tests/bbc.com-orb-cosmetic.spec.ts +8 -0
- package/tests/bbc.com.spec.ts +11 -9
- package/tests/bokadirekt.se.spec.ts +3 -0
- package/tests/bouvet-cookiepanel.spec.ts +9 -0
- package/tests/com-consent-layer.spec.ts +6 -0
- package/tests/consent-studio.spec.ts +5 -0
- package/tests/cookiebot.spec.ts +1 -0
- package/tests/cookielegit.spec.ts +3 -0
- package/tests/cookieprompter.spec.ts +9 -0
- package/tests/cookiereports.spec.ts +13 -0
- package/tests/cookietractor.spec.ts +12 -0
- package/tests/de-volksbank.spec.ts +5 -0
- package/tests/dpgmedia-nl.spec.ts +15 -1
- package/tests/eon.pl.spec.ts +3 -0
- package/tests/eroticiracconti-it.spec.ts +3 -0
- package/tests/ersatzteile-24.spec.ts +6 -0
- package/tests/fastweb-cookie-center.spec.ts +3 -0
- package/tests/futurabolzano-it.spec.ts +3 -0
- package/tests/gobasic.spec.ts +3 -0
- package/tests/gravito.spec.ts +7 -1
- package/tests/hacon-next-gen.spec.ts +6 -0
- package/tests/ing-de.spec.ts +3 -0
- package/tests/interia.spec.ts +1 -1
- package/tests/intesasanpaolo.spec.ts +3 -0
- package/tests/jobindex.spec.ts +3 -0
- package/tests/kaspersky-cookies-notification.spec.ts +8 -0
- package/tests/lantmateriet.spec.ts +3 -0
- package/tests/livsmedelsverket.spec.ts +5 -0
- package/tests/mainichi.spec.ts +10 -0
- package/tests/mango.spec.ts +3 -0
- package/tests/nederlandseloterij.spec.ts +9 -0
- package/tests/newsbreak.spec.ts +3 -0
- package/tests/nhsapp.spec.ts +3 -0
- package/tests/nordea.spec.ts +6 -0
- package/tests/nordnet.spec.ts +8 -0
- package/tests/onlineradiobox.spec.ts +5 -0
- package/tests/pe-cookies.spec.ts +6 -0
- package/tests/pensionsmyndigheten.spec.ts +3 -0
- package/tests/pro-euclp-cookies-box.spec.ts +8 -0
- package/tests/pubfactory.spec.ts +10 -0
- package/tests/puesc-gov-pl.spec.ts +3 -0
- package/tests/rambler.spec.ts +3 -0
- package/tests/rejestr-io.spec.ts +3 -0
- package/tests/sas.spec.ts +1 -1
- package/tests/scb.se.spec.ts +4 -0
- package/tests/schumacher.com.spec.ts +6 -0
- package/tests/sitevision-cookie-consent.spec.ts +1 -0
- package/tests/sitevision.spec.ts +7 -0
- package/tests/skatteverket-se.spec.ts +3 -0
- package/tests/smile-insurances.spec.ts +6 -0
- package/tests/studentapan.spec.ts +3 -0
- package/tests/svt.se.spec.ts +1 -3
- package/tests/temu.spec.ts +3 -1
- package/tests/thecode.spec.ts +3 -0
- package/tests/tv2reg-cookie-notice.spec.ts +16 -0
- package/tests/uk-parliament.spec.ts +8 -0
- package/tests/wirtualna-polska.spec.ts +6 -1
- package/tests/xenforo-cookie-consent.spec.ts +6 -0
- package/tests/zorginstituut-cookiewarning.spec.ts +10 -0
- package/tests-wtr/heuristics/get-potential-popups.test.ts +330 -9
- package/tests-wtr/heuristics/heuristics-utils.test.ts +98 -0
- package/rules/autoconsent/twitter.json +0 -34
- package/rules/generated/auto_AU_flysas.com_r1s.json +0 -40
- package/rules/generated/auto_CH_airbnb.de_83z.json +0 -40
- package/rules/generated/auto_CH_autodoc.de_krd.json +0 -40
- package/rules/generated/auto_CH_svtplay.se_d39.json +0 -40
- package/rules/generated/auto_GB_parliamentlive.tv_r3v.json +0 -28
- package/rules/generated/auto_NL_asnbank.nl_e28.json +0 -40
- package/rules/generated/auto_NL_eurojackpot.nederlandseloterij.nl_7hr.json +0 -40
- package/rules/generated/auto_NL_lotto.nederlandseloterij.nl_7c8.json +0 -40
- package/rules/generated/auto_NL_nederlandseloterij.nl_b60.json +0 -40
- package/rules/generated/auto_NL_staatsloterij.nederlandseloterij.nl_197.json +0 -40
- package/rules/generated/auto_NO_arronet.se_vo5.json +0 -40
- package/rules/generated/auto_NO_liseberg.se_qy4.json +0 -40
- package/rules/generated/auto_NO_nordnet.se_2en.json +0 -40
- package/rules/generated/auto_NO_regeringen.se_uhv.json +0 -40
- package/rules/generated/auto_NO_svtplay.se_ujn.json +0 -40
- package/rules/generated/auto_NO_uu.se_eea.json +0 -40
- package/rules/generated/auto_US_newsbreak.com_0.json +0 -28
- package/tests/generated/auto_AU_flysas.com_r1s.spec.ts +0 -2
- package/tests/generated/auto_CH_airbnb.de_83z.spec.ts +0 -2
- package/tests/generated/auto_CH_autodoc.de_krd.spec.ts +0 -2
- package/tests/generated/auto_CH_svtplay.se_d39.spec.ts +0 -2
- package/tests/generated/auto_GB_parliamentlive.tv_r3v.spec.ts +0 -6
- package/tests/generated/auto_NL_asnbank.nl_e28.spec.ts +0 -6
- package/tests/generated/auto_NL_eurojackpot.nederlandseloterij.nl_7hr.spec.ts +0 -6
- package/tests/generated/auto_NL_lotto.nederlandseloterij.nl_7c8.spec.ts +0 -6
- package/tests/generated/auto_NL_nederlandseloterij.nl_b60.spec.ts +0 -6
- package/tests/generated/auto_NL_staatsloterij.nederlandseloterij.nl_197.spec.ts +0 -6
- package/tests/generated/auto_NO_arronet.se_vo5.spec.ts +0 -2
- package/tests/generated/auto_NO_liseberg.se_qy4.spec.ts +0 -2
- package/tests/generated/auto_NO_nordnet.se_2en.spec.ts +0 -2
- package/tests/generated/auto_NO_regeringen.se_uhv.spec.ts +0 -6
- package/tests/generated/auto_NO_svtplay.se_ujn.spec.ts +0 -2
- package/tests/generated/auto_NO_uu.se_eea.spec.ts +0 -2
- package/tests/generated/auto_US_newsbreak.com_0.spec.ts +0 -2
- package/tests/twitter.spec.ts +0 -10
|
@@ -336,6 +336,27 @@
|
|
|
336
336
|
EVAL_COOKIEFIRST_1: () => document.querySelectorAll("button[data-cookiefirst-accent-color=true][role=checkbox]:not([disabled])").forEach((i) => i.getAttribute("aria-checked") === "true" && i.click()) || true,
|
|
337
337
|
EVAL_COOKIEINFORMATION_0: () => CookieInformation.declineAllCategories() || true,
|
|
338
338
|
EVAL_COOKIEINFORMATION_1: () => CookieInformation.submitAllCategories() || true,
|
|
339
|
+
// banner button order and meaning are configurable per site, so set the consent levels through the public API
|
|
340
|
+
EVAL_COOKIEREPORTS_OPT_OUT: () => {
|
|
341
|
+
const cr = window._cookiereports;
|
|
342
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
343
|
+
cr.saveConsent({ 1: true, 2: false, 3: false, 4: false, 5: false });
|
|
344
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
345
|
+
cr.hideBanner();
|
|
346
|
+
return true;
|
|
347
|
+
},
|
|
348
|
+
EVAL_COOKIEREPORTS_OPT_IN: () => {
|
|
349
|
+
const cr = window._cookiereports;
|
|
350
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
351
|
+
cr.saveConsent({ 1: true, 2: true, 3: true, 4: true, 5: true });
|
|
352
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
353
|
+
cr.hideBanner();
|
|
354
|
+
return true;
|
|
355
|
+
},
|
|
356
|
+
EVAL_COOKIEREPORTS_TEST: () => {
|
|
357
|
+
const levels = window._cookiereports?.loadConsent?.();
|
|
358
|
+
return !!levels && Object.keys(levels).length > 0 && Object.values(levels).every((v) => !v);
|
|
359
|
+
},
|
|
339
360
|
// turn the single-button form into a decline submission, same fields as the CMP's own decline form
|
|
340
361
|
EVAL_EE_CONSENT_DECLINE_0: () => document.querySelectorAll('#cookieConsentFormAccept input[name^="ee:cookies_"]').forEach((i) => i.value = "n") || true,
|
|
341
362
|
EVAL_ETSY_0: () => document.querySelectorAll(".gdpr-overlay-body input").forEach((toggle) => {
|
|
@@ -586,10 +607,20 @@
|
|
|
586
607
|
// "файлы cookie" / "cookie-файлы" / "куки-файлы" in any phrasing
|
|
587
608
|
/(?:файл[а-яё]*[\s-]+(?:cookie|куки)|(?:cookie|куки)[\s-]+файл[а-яё]*)/gi,
|
|
588
609
|
// Italian (IT)
|
|
589
|
-
|
|
610
|
+
// e.g. "usiamo i cookie", "utilizziamo cookie tecnici", "questo sito utilizza i cookie", "noi e i nostri partner utilizziamo i cookie"
|
|
611
|
+
/(?:usiamo|utilizziamo).{0,20}cookie/gi,
|
|
612
|
+
/sito.{0,50}(?:usa|utilizza).{0,20}cookie/gi,
|
|
613
|
+
/noi e i nostri.{0,20}partner.{0,100}cookie/gi,
|
|
614
|
+
/(?:archiviare|memorizzare) e\/o accedere a informazioni su un dispositivo/gi,
|
|
615
|
+
// Swedish (SV)
|
|
616
|
+
// e.g. "vi använder cookies", "vi använder spårningstekniker såsom cookies", "webbplatsen använder kakor"
|
|
617
|
+
/(?:vi|webbplatsen|webbplats|sajten|sidan)\s+använder.{0,60}(?:cookies|kakor)/gi,
|
|
590
618
|
// Japanese (JA)
|
|
591
619
|
// e.g. "当サイトはCookieを使用しています", "クッキー(Cookie)を利用しています"
|
|
592
|
-
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi
|
|
620
|
+
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi,
|
|
621
|
+
// Danish (DA)
|
|
622
|
+
// e.g. "vi bruger cookies", "hjemmesiden bruger cookies til at ..."
|
|
623
|
+
/bruger cookies/gi
|
|
593
624
|
];
|
|
594
625
|
var REJECT_PATTERNS_ENGLISH = [
|
|
595
626
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
@@ -723,6 +754,14 @@
|
|
|
723
754
|
"till\xE5t inte cookies",
|
|
724
755
|
"jag accepterar endast grundl\xE4ggande kakor"
|
|
725
756
|
];
|
|
757
|
+
var REJECT_PATTERNS_DANISH = [
|
|
758
|
+
// afvis / afvis alle / afvis alle cookies (reject verbs)
|
|
759
|
+
/(^|\s)afvis/is,
|
|
760
|
+
// (accept/allow) only necessary cookies
|
|
761
|
+
/^(accepter\s+|tillad\s+)?(kun|udelukkende)\s+(strengt\s+)?nødvendige( cookies)?$/is,
|
|
762
|
+
// "nej tak" (no thanks)
|
|
763
|
+
/^nej(,?\s+tak)?$/is
|
|
764
|
+
];
|
|
726
765
|
var REJECT_PATTERNS_CATALAN = [/(^|\s)rebutj/is, "no accepto", "no, gr\xE0cies"];
|
|
727
766
|
var REJECT_PATTERNS_GALICIAN = [/(^|\s)rexeitar/is];
|
|
728
767
|
var REJECT_PATTERNS_BASQUE = [/(^|\s)(baztertu|ukatu)/is];
|
|
@@ -769,6 +808,7 @@
|
|
|
769
808
|
...REJECT_PATTERNS_BRAZILIAN_PORTUGUESE,
|
|
770
809
|
...REJECT_PATTERNS_SPANISH,
|
|
771
810
|
...REJECT_PATTERNS_SWEDISH,
|
|
811
|
+
...REJECT_PATTERNS_DANISH,
|
|
772
812
|
...REJECT_PATTERNS_CATALAN,
|
|
773
813
|
...REJECT_PATTERNS_GALICIAN,
|
|
774
814
|
...REJECT_PATTERNS_BASQUE,
|
|
@@ -1118,7 +1158,8 @@
|
|
|
1118
1158
|
"kabul et",
|
|
1119
1159
|
// Italian (IT)
|
|
1120
1160
|
"accetta",
|
|
1121
|
-
"accetta tutti i cookie"
|
|
1161
|
+
"accetta tutti i cookie",
|
|
1162
|
+
"accetto tutti i cookie"
|
|
1122
1163
|
];
|
|
1123
1164
|
var ACKNOWLEDGE_PATTERNS = [
|
|
1124
1165
|
// close / dismiss the banner/dialog/message (multilingual). The negative lookahead avoids
|
|
@@ -1194,6 +1235,10 @@
|
|
|
1194
1235
|
}
|
|
1195
1236
|
return { patterns, snippets: snippets2 };
|
|
1196
1237
|
}
|
|
1238
|
+
function hasHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
1239
|
+
const text = allText.slice(0, TEXT_LIMIT);
|
|
1240
|
+
return detectPatterns.some((p) => text.search(p) !== -1);
|
|
1241
|
+
}
|
|
1197
1242
|
function classifyButtons(buttons) {
|
|
1198
1243
|
for (const button of buttons) {
|
|
1199
1244
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
@@ -1270,57 +1315,135 @@
|
|
|
1270
1315
|
var POPUP_SEARCH_MAX_TIME = 100;
|
|
1271
1316
|
function getActionablePopups(mode = "reject", timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1272
1317
|
const acceptedLevels = mode === "tier2" ? ["reject", "tier1", "tier2"] : mode === "tier1" ? ["reject", "tier1"] : ["reject"];
|
|
1273
|
-
|
|
1274
|
-
return [];
|
|
1275
|
-
}
|
|
1276
|
-
const popups = getPotentialPopups(timeout);
|
|
1277
|
-
const result = popups.reduce((acc, popup) => {
|
|
1318
|
+
const popups = getPotentialPopups(timeout).filter((popup) => {
|
|
1278
1319
|
const popupText = popup.text?.trim();
|
|
1279
|
-
if (popupText) {
|
|
1280
|
-
|
|
1281
|
-
return acc;
|
|
1282
|
-
}
|
|
1283
|
-
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1284
|
-
if (patterns.length > 0) {
|
|
1285
|
-
classifyButtons(popup.buttons);
|
|
1286
|
-
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1287
|
-
acc.push({
|
|
1288
|
-
...popup
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1320
|
+
if (!popupText || isExcludedPopup(popupText) || !hasHeuristicPatterns(popupText)) {
|
|
1321
|
+
return false;
|
|
1291
1322
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1323
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1324
|
+
return popup.regexClassification !== void 0 && acceptedLevels.includes(popup.regexClassification);
|
|
1325
|
+
});
|
|
1326
|
+
return popups.sort((a, b) => (a.regexClassification ?? "") > (b.regexClassification ?? "") ? 1 : -1);
|
|
1295
1327
|
}
|
|
1296
1328
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
}
|
|
1301
|
-
return collectPotentialPopups(isFramed, timeout);
|
|
1302
|
-
}
|
|
1303
|
-
function collectPotentialPopups(isFramed, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1304
|
-
let elements = [];
|
|
1305
|
-
if (!isFramed) {
|
|
1306
|
-
elements = getPopupLikeElements(timeout);
|
|
1307
|
-
} else {
|
|
1308
|
-
const doc = document.body || document.documentElement;
|
|
1309
|
-
if (doc && isElementVisible(doc) && doc.innerText) {
|
|
1310
|
-
elements.push(doc);
|
|
1329
|
+
if (!isTopFrame()) {
|
|
1330
|
+
if (window.parent && window.parent !== window.top) {
|
|
1331
|
+
return [];
|
|
1311
1332
|
}
|
|
1333
|
+
const frameElement = getFramePopupElement(document);
|
|
1334
|
+
const popup = frameElement && toPopupData(frameElement);
|
|
1335
|
+
return popup ? [popup] : [];
|
|
1312
1336
|
}
|
|
1337
|
+
const deadline = performance.now() + timeout;
|
|
1338
|
+
const { elements, shadowHosts } = getPopupLikeElements(deadline);
|
|
1313
1339
|
const potentialPopups = [];
|
|
1340
|
+
const expanded = [];
|
|
1314
1341
|
for (const el of elements) {
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1342
|
+
const popup = toPopupData(el, shadowHosts);
|
|
1343
|
+
if (!popup) {
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
const root = performance.now() > deadline ? popup : expandPopupFragment(popup, shadowHosts);
|
|
1347
|
+
if (potentialPopups.some((p) => p.element === root.element)) {
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
if (root !== popup) {
|
|
1351
|
+
expanded.push(root.element);
|
|
1352
|
+
}
|
|
1353
|
+
potentialPopups.push(root);
|
|
1354
|
+
}
|
|
1355
|
+
return potentialPopups.filter((p) => !expanded.some((root) => root !== p.element && composedContains(root, p.element)));
|
|
1356
|
+
}
|
|
1357
|
+
function toPopupData(el, shadowHosts, text = getElementText(el)) {
|
|
1358
|
+
if (!text) {
|
|
1359
|
+
return null;
|
|
1360
|
+
}
|
|
1361
|
+
const buttons = getButtonData(el, shadowHosts);
|
|
1362
|
+
classifyButtons(buttons);
|
|
1363
|
+
return { text, element: el, buttons };
|
|
1364
|
+
}
|
|
1365
|
+
function hasPopupButtons(text, buttons) {
|
|
1366
|
+
return !isOnlyButtonText(text, buttons) && buttons.some((b) => b.regexClassification !== "other");
|
|
1367
|
+
}
|
|
1368
|
+
function isOnlyButtonText(text, buttons) {
|
|
1369
|
+
let rest = text;
|
|
1370
|
+
for (const button of buttons) {
|
|
1371
|
+
rest = rest.replace(button.text, "");
|
|
1372
|
+
}
|
|
1373
|
+
return rest.replace(/\s+/g, "").length < 10;
|
|
1374
|
+
}
|
|
1375
|
+
var MAX_FRAGMENT_EXPANSION_DEPTH = 6;
|
|
1376
|
+
function expandPopupFragment(popup, shadowHosts) {
|
|
1377
|
+
if (hasHeuristicPatterns(popup.text) && hasPopupButtons(popup.text, popup.buttons)) {
|
|
1378
|
+
return popup;
|
|
1379
|
+
}
|
|
1380
|
+
let el = getComposedParent(popup.element);
|
|
1381
|
+
for (let depth = 0; el && depth < MAX_FRAGMENT_EXPANSION_DEPTH; depth++, el = getComposedParent(el)) {
|
|
1382
|
+
if (el === document.body || el === document.documentElement || el.getBoundingClientRect().height > window.innerHeight) {
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
const text = getElementText(el);
|
|
1386
|
+
if (!text || !hasHeuristicPatterns(text)) {
|
|
1387
|
+
continue;
|
|
1388
|
+
}
|
|
1389
|
+
const root = toPopupData(el, shadowHosts, text);
|
|
1390
|
+
if (root && hasPopupButtons(text, root.buttons)) {
|
|
1391
|
+
return root;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return popup;
|
|
1395
|
+
}
|
|
1396
|
+
function getComposedParent(el) {
|
|
1397
|
+
if (el.parentElement) {
|
|
1398
|
+
return el.parentElement;
|
|
1399
|
+
}
|
|
1400
|
+
const parent = el.parentNode;
|
|
1401
|
+
return parent instanceof ShadowRoot && parent.host instanceof HTMLElement ? parent.host : null;
|
|
1402
|
+
}
|
|
1403
|
+
function getFramePopupElement(doc) {
|
|
1404
|
+
const el = doc.body || doc.documentElement;
|
|
1405
|
+
const win = doc.defaultView;
|
|
1406
|
+
if (!el || !win || win.innerWidth === 0 || win.innerHeight === 0 || !isStyleVisible(el)) {
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
return getElementText(el).trim() ? el : null;
|
|
1410
|
+
}
|
|
1411
|
+
function isStyleVisible(el) {
|
|
1412
|
+
return typeof el.checkVisibility !== "function" || el.checkVisibility({ checkVisibilityCSS: true });
|
|
1413
|
+
}
|
|
1414
|
+
function getElementText(el) {
|
|
1415
|
+
const text = el.innerText || "";
|
|
1416
|
+
if (!el.shadowRoot) {
|
|
1417
|
+
return text;
|
|
1418
|
+
}
|
|
1419
|
+
const shadowTexts = Array.from(el.shadowRoot.children, (child) => isRenderedTextElement(child) ? getElementText(child) : "");
|
|
1420
|
+
return [text, ...shadowTexts].filter((t) => t.trim()).join("\n");
|
|
1421
|
+
}
|
|
1422
|
+
function isRenderedTextElement(el) {
|
|
1423
|
+
return el instanceof HTMLElement && !["STYLE", "SCRIPT", "TEMPLATE", "NOSCRIPT", "LINK", "SLOT"].includes(el.tagName) && window.getComputedStyle(el).display !== "none";
|
|
1424
|
+
}
|
|
1425
|
+
function composedContains(container, node) {
|
|
1426
|
+
if (container.contains(node)) {
|
|
1427
|
+
return true;
|
|
1428
|
+
}
|
|
1429
|
+
let root = node.getRootNode();
|
|
1430
|
+
while (root instanceof ShadowRoot) {
|
|
1431
|
+
if (container.contains(root.host)) {
|
|
1432
|
+
return true;
|
|
1321
1433
|
}
|
|
1434
|
+
root = root.host.getRootNode();
|
|
1435
|
+
}
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
function isPopupCandidateVisible(el) {
|
|
1439
|
+
return isElementVisible(el) && isStyleVisible(el) && isOnScreen(el);
|
|
1440
|
+
}
|
|
1441
|
+
function isOnScreen(el) {
|
|
1442
|
+
const rect = el.getBoundingClientRect();
|
|
1443
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
1444
|
+
return window.getComputedStyle(el).overflow === "visible" && Array.from(el.children).some((child) => isOnScreen(child));
|
|
1322
1445
|
}
|
|
1323
|
-
return
|
|
1446
|
+
return rect.bottom > 0 && rect.right > 0 && rect.top < window.innerHeight && rect.left < window.innerWidth;
|
|
1324
1447
|
}
|
|
1325
1448
|
function isDialogLikeElement(node) {
|
|
1326
1449
|
if (node.tagName === "DIALOG" && node.hasAttribute("open")) {
|
|
@@ -1331,72 +1454,95 @@
|
|
|
1331
1454
|
}
|
|
1332
1455
|
return false;
|
|
1333
1456
|
}
|
|
1334
|
-
function getPopupLikeElements(
|
|
1335
|
-
const
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1457
|
+
function getPopupLikeElements(deadline) {
|
|
1458
|
+
const found = [];
|
|
1459
|
+
const shadowHosts = [];
|
|
1460
|
+
const roots = [document.documentElement];
|
|
1461
|
+
for (let i = 0; i < roots.length; i++) {
|
|
1462
|
+
if (i > 0 && performance.now() > deadline) {
|
|
1463
|
+
break;
|
|
1464
|
+
}
|
|
1465
|
+
const walker = document.createTreeWalker(
|
|
1466
|
+
roots[i],
|
|
1467
|
+
NodeFilter.SHOW_ELEMENT,
|
|
1468
|
+
// visit only element nodes
|
|
1469
|
+
{
|
|
1470
|
+
acceptNode(node) {
|
|
1471
|
+
if (node.shadowRoot) {
|
|
1472
|
+
shadowHosts.push(node);
|
|
1473
|
+
roots.push(node.shadowRoot);
|
|
1474
|
+
}
|
|
1475
|
+
if (node.tagName === "BODY") {
|
|
1476
|
+
return NodeFilter.FILTER_SKIP;
|
|
1349
1477
|
}
|
|
1350
|
-
|
|
1478
|
+
const style = window.getComputedStyle(node);
|
|
1479
|
+
if (style.display === "none") {
|
|
1480
|
+
return NodeFilter.FILTER_REJECT;
|
|
1481
|
+
}
|
|
1482
|
+
const cssPosition = style.position;
|
|
1483
|
+
if ((cssPosition === "fixed" || cssPosition === "sticky" || isDialogLikeElement(node)) && isPopupCandidateVisible(node)) {
|
|
1351
1484
|
return NodeFilter.FILTER_ACCEPT;
|
|
1352
1485
|
}
|
|
1486
|
+
if (performance.now() > deadline) {
|
|
1487
|
+
return NodeFilter.FILTER_REJECT;
|
|
1488
|
+
}
|
|
1489
|
+
return NodeFilter.FILTER_SKIP;
|
|
1353
1490
|
}
|
|
1354
|
-
if (performance.now() - startTime > timeout) {
|
|
1355
|
-
return NodeFilter.FILTER_REJECT;
|
|
1356
|
-
}
|
|
1357
|
-
return NodeFilter.FILTER_SKIP;
|
|
1358
1491
|
}
|
|
1492
|
+
);
|
|
1493
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1494
|
+
found.push(node);
|
|
1359
1495
|
}
|
|
1360
|
-
);
|
|
1361
|
-
const found = [];
|
|
1362
|
-
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1363
|
-
found.push(node);
|
|
1364
1496
|
}
|
|
1365
|
-
return excludeContainers(found.filter((element) => element.
|
|
1497
|
+
return { elements: excludeContainers(found.filter((element) => getElementText(element).trim())), shadowHosts };
|
|
1366
1498
|
}
|
|
1367
|
-
function getButtonData(el) {
|
|
1368
|
-
const
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
text
|
|
1374
|
-
|
|
1375
|
-
|
|
1499
|
+
function getButtonData(el, shadowHosts) {
|
|
1500
|
+
const buttons = [];
|
|
1501
|
+
for (const b of excludeContainers(getButtonLikeElements(el, shadowHosts))) {
|
|
1502
|
+
if (!isElementVisible(b) || isDisabled(b)) {
|
|
1503
|
+
continue;
|
|
1504
|
+
}
|
|
1505
|
+
const text = getElementText(b).trim() || // <input> values do not appear in innerText
|
|
1506
|
+
(b instanceof HTMLInputElement && ["submit", "button"].includes(b.type) ? b.value?.trim() : "");
|
|
1507
|
+
if (text) {
|
|
1508
|
+
buttons.push({ text, element: b });
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
return buttons;
|
|
1376
1512
|
}
|
|
1377
|
-
function getButtonLikeElements(el) {
|
|
1378
|
-
|
|
1513
|
+
function getButtonLikeElements(el, shadowHosts = findShadowHosts(el)) {
|
|
1514
|
+
const buttons = Array.from(el.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1515
|
+
for (const host of shadowHosts) {
|
|
1516
|
+
if (composedContains(el, host)) {
|
|
1517
|
+
buttons.push(...host.shadowRoot.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return buttons;
|
|
1521
|
+
}
|
|
1522
|
+
function findShadowHosts(root) {
|
|
1523
|
+
const hosts = [];
|
|
1524
|
+
const candidates = root instanceof HTMLElement ? [root, ...root.querySelectorAll("*")] : root.querySelectorAll("*");
|
|
1525
|
+
for (const el of candidates) {
|
|
1526
|
+
if (el.shadowRoot) {
|
|
1527
|
+
hosts.push(el, ...findShadowHosts(el.shadowRoot));
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
return hosts;
|
|
1379
1531
|
}
|
|
1380
1532
|
function isDisabled(el) {
|
|
1381
1533
|
return "disabled" in el && Boolean(el.disabled) || el.hasAttribute("disabled");
|
|
1382
1534
|
}
|
|
1383
1535
|
function excludeContainers(elements) {
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
container = true;
|
|
1391
|
-
break;
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
if (!container) {
|
|
1395
|
-
results.push(elements[i]);
|
|
1536
|
+
const candidates = new Set(elements);
|
|
1537
|
+
const containers = /* @__PURE__ */ new Set();
|
|
1538
|
+
for (const el of elements) {
|
|
1539
|
+
for (let node = el.parentNode; node; node = node.parentNode || (node instanceof ShadowRoot ? node.host : null)) {
|
|
1540
|
+
if (candidates.has(node)) {
|
|
1541
|
+
containers.add(node);
|
|
1396
1542
|
}
|
|
1397
1543
|
}
|
|
1398
1544
|
}
|
|
1399
|
-
return
|
|
1545
|
+
return elements.filter((el) => !containers.has(el)).reverse();
|
|
1400
1546
|
}
|
|
1401
1547
|
|
|
1402
1548
|
// lib/cmps/base.ts
|
|
@@ -2190,6 +2336,18 @@
|
|
|
2190
2336
|
get isCosmetic() {
|
|
2191
2337
|
return false;
|
|
2192
2338
|
}
|
|
2339
|
+
// Some sites pre-render the banner before the SDK loads, and clicks before then may be lost.
|
|
2340
|
+
// Sites that copy the markup without the SDK never get #onetrust-style, so only wait when the page loads the SDK.
|
|
2341
|
+
async waitForSdk() {
|
|
2342
|
+
if (this.elementExists("#onetrust-style")) {
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
const sdkRef = /cookielaw\.org|otSDKStub|otBannerSdk/;
|
|
2346
|
+
const sdkExpected = Array.from(document.scripts).some((s) => sdkRef.test(s.src) || !s.src && sdkRef.test(s.textContent || ""));
|
|
2347
|
+
if (sdkExpected) {
|
|
2348
|
+
await this.waitForElement("#onetrust-style", 1e4);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2193
2351
|
async detectCmp() {
|
|
2194
2352
|
return this.elementExists("#onetrust-banner-sdk") || this.elementVisible("#onetrust-pc-sdk", "any");
|
|
2195
2353
|
}
|
|
@@ -2198,6 +2356,7 @@
|
|
|
2198
2356
|
}
|
|
2199
2357
|
async optOut() {
|
|
2200
2358
|
await this.wait(500);
|
|
2359
|
+
await this.waitForSdk();
|
|
2201
2360
|
if (this.elementVisible("#onetrust-reject-all-handler", "any")) {
|
|
2202
2361
|
return await this.click("#onetrust-reject-all-handler");
|
|
2203
2362
|
}
|
|
@@ -2237,6 +2396,7 @@
|
|
|
2237
2396
|
return true;
|
|
2238
2397
|
}
|
|
2239
2398
|
async optIn() {
|
|
2399
|
+
await this.waitForSdk();
|
|
2240
2400
|
return await this.click("#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies");
|
|
2241
2401
|
}
|
|
2242
2402
|
async test() {
|