@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
|
@@ -344,6 +344,27 @@
|
|
|
344
344
|
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,
|
|
345
345
|
EVAL_COOKIEINFORMATION_0: () => CookieInformation.declineAllCategories() || true,
|
|
346
346
|
EVAL_COOKIEINFORMATION_1: () => CookieInformation.submitAllCategories() || true,
|
|
347
|
+
// banner button order and meaning are configurable per site, so set the consent levels through the public API
|
|
348
|
+
EVAL_COOKIEREPORTS_OPT_OUT: () => {
|
|
349
|
+
const cr = window._cookiereports;
|
|
350
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
351
|
+
cr.saveConsent({ 1: true, 2: false, 3: false, 4: false, 5: false });
|
|
352
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
353
|
+
cr.hideBanner();
|
|
354
|
+
return true;
|
|
355
|
+
},
|
|
356
|
+
EVAL_COOKIEREPORTS_OPT_IN: () => {
|
|
357
|
+
const cr = window._cookiereports;
|
|
358
|
+
if (typeof cr?.saveConsent !== "function") return false;
|
|
359
|
+
cr.saveConsent({ 1: true, 2: true, 3: true, 4: true, 5: true });
|
|
360
|
+
cr.processConsent("banner", { trigger: "ok" });
|
|
361
|
+
cr.hideBanner();
|
|
362
|
+
return true;
|
|
363
|
+
},
|
|
364
|
+
EVAL_COOKIEREPORTS_TEST: () => {
|
|
365
|
+
const levels = window._cookiereports?.loadConsent?.();
|
|
366
|
+
return !!levels && Object.keys(levels).length > 0 && Object.values(levels).every((v) => !v);
|
|
367
|
+
},
|
|
347
368
|
// turn the single-button form into a decline submission, same fields as the CMP's own decline form
|
|
348
369
|
EVAL_EE_CONSENT_DECLINE_0: () => document.querySelectorAll('#cookieConsentFormAccept input[name^="ee:cookies_"]').forEach((i) => i.value = "n") || true,
|
|
349
370
|
EVAL_ETSY_0: () => document.querySelectorAll(".gdpr-overlay-body input").forEach((toggle) => {
|
|
@@ -594,10 +615,20 @@
|
|
|
594
615
|
// "файлы cookie" / "cookie-файлы" / "куки-файлы" in any phrasing
|
|
595
616
|
/(?:файл[а-яё]*[\s-]+(?:cookie|куки)|(?:cookie|куки)[\s-]+файл[а-яё]*)/gi,
|
|
596
617
|
// Italian (IT)
|
|
597
|
-
|
|
618
|
+
// e.g. "usiamo i cookie", "utilizziamo cookie tecnici", "questo sito utilizza i cookie", "noi e i nostri partner utilizziamo i cookie"
|
|
619
|
+
/(?:usiamo|utilizziamo).{0,20}cookie/gi,
|
|
620
|
+
/sito.{0,50}(?:usa|utilizza).{0,20}cookie/gi,
|
|
621
|
+
/noi e i nostri.{0,20}partner.{0,100}cookie/gi,
|
|
622
|
+
/(?:archiviare|memorizzare) e\/o accedere a informazioni su un dispositivo/gi,
|
|
623
|
+
// Swedish (SV)
|
|
624
|
+
// e.g. "vi använder cookies", "vi använder spårningstekniker såsom cookies", "webbplatsen använder kakor"
|
|
625
|
+
/(?:vi|webbplatsen|webbplats|sajten|sidan)\s+använder.{0,60}(?:cookies|kakor)/gi,
|
|
598
626
|
// Japanese (JA)
|
|
599
627
|
// e.g. "当サイトはCookieを使用しています", "クッキー(Cookie)を利用しています"
|
|
600
|
-
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi
|
|
628
|
+
/(?:cookie|クッキー).{0,10}を(?:使用|利用)/gi,
|
|
629
|
+
// Danish (DA)
|
|
630
|
+
// e.g. "vi bruger cookies", "hjemmesiden bruger cookies til at ..."
|
|
631
|
+
/bruger cookies/gi
|
|
601
632
|
];
|
|
602
633
|
var REJECT_PATTERNS_ENGLISH = [
|
|
603
634
|
// e.g. "reject", "reject all", "reject all cookies", "deny all", "refuse cookies", "decline",
|
|
@@ -731,6 +762,14 @@
|
|
|
731
762
|
"till\xE5t inte cookies",
|
|
732
763
|
"jag accepterar endast grundl\xE4ggande kakor"
|
|
733
764
|
];
|
|
765
|
+
var REJECT_PATTERNS_DANISH = [
|
|
766
|
+
// afvis / afvis alle / afvis alle cookies (reject verbs)
|
|
767
|
+
/(^|\s)afvis/is,
|
|
768
|
+
// (accept/allow) only necessary cookies
|
|
769
|
+
/^(accepter\s+|tillad\s+)?(kun|udelukkende)\s+(strengt\s+)?nødvendige( cookies)?$/is,
|
|
770
|
+
// "nej tak" (no thanks)
|
|
771
|
+
/^nej(,?\s+tak)?$/is
|
|
772
|
+
];
|
|
734
773
|
var REJECT_PATTERNS_CATALAN = [/(^|\s)rebutj/is, "no accepto", "no, gr\xE0cies"];
|
|
735
774
|
var REJECT_PATTERNS_GALICIAN = [/(^|\s)rexeitar/is];
|
|
736
775
|
var REJECT_PATTERNS_BASQUE = [/(^|\s)(baztertu|ukatu)/is];
|
|
@@ -777,6 +816,7 @@
|
|
|
777
816
|
...REJECT_PATTERNS_BRAZILIAN_PORTUGUESE,
|
|
778
817
|
...REJECT_PATTERNS_SPANISH,
|
|
779
818
|
...REJECT_PATTERNS_SWEDISH,
|
|
819
|
+
...REJECT_PATTERNS_DANISH,
|
|
780
820
|
...REJECT_PATTERNS_CATALAN,
|
|
781
821
|
...REJECT_PATTERNS_GALICIAN,
|
|
782
822
|
...REJECT_PATTERNS_BASQUE,
|
|
@@ -1126,7 +1166,8 @@
|
|
|
1126
1166
|
"kabul et",
|
|
1127
1167
|
// Italian (IT)
|
|
1128
1168
|
"accetta",
|
|
1129
|
-
"accetta tutti i cookie"
|
|
1169
|
+
"accetta tutti i cookie",
|
|
1170
|
+
"accetto tutti i cookie"
|
|
1130
1171
|
];
|
|
1131
1172
|
var ACKNOWLEDGE_PATTERNS = [
|
|
1132
1173
|
// close / dismiss the banner/dialog/message (multilingual). The negative lookahead avoids
|
|
@@ -1202,6 +1243,10 @@
|
|
|
1202
1243
|
}
|
|
1203
1244
|
return { patterns, snippets: snippets2 };
|
|
1204
1245
|
}
|
|
1246
|
+
function hasHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
1247
|
+
const text = allText.slice(0, TEXT_LIMIT);
|
|
1248
|
+
return detectPatterns.some((p) => text.search(p) !== -1);
|
|
1249
|
+
}
|
|
1205
1250
|
function classifyButtons(buttons) {
|
|
1206
1251
|
for (const button of buttons) {
|
|
1207
1252
|
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
@@ -1278,57 +1323,135 @@
|
|
|
1278
1323
|
var POPUP_SEARCH_MAX_TIME = 100;
|
|
1279
1324
|
function getActionablePopups(mode = "reject", timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1280
1325
|
const acceptedLevels = mode === "tier2" ? ["reject", "tier1", "tier2"] : mode === "tier1" ? ["reject", "tier1"] : ["reject"];
|
|
1281
|
-
|
|
1282
|
-
return [];
|
|
1283
|
-
}
|
|
1284
|
-
const popups = getPotentialPopups(timeout);
|
|
1285
|
-
const result = popups.reduce((acc, popup) => {
|
|
1326
|
+
const popups = getPotentialPopups(timeout).filter((popup) => {
|
|
1286
1327
|
const popupText = popup.text?.trim();
|
|
1287
|
-
if (popupText) {
|
|
1288
|
-
|
|
1289
|
-
return acc;
|
|
1290
|
-
}
|
|
1291
|
-
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1292
|
-
if (patterns.length > 0) {
|
|
1293
|
-
classifyButtons(popup.buttons);
|
|
1294
|
-
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1295
|
-
acc.push({
|
|
1296
|
-
...popup
|
|
1297
|
-
});
|
|
1298
|
-
}
|
|
1328
|
+
if (!popupText || isExcludedPopup(popupText) || !hasHeuristicPatterns(popupText)) {
|
|
1329
|
+
return false;
|
|
1299
1330
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1331
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1332
|
+
return popup.regexClassification !== void 0 && acceptedLevels.includes(popup.regexClassification);
|
|
1333
|
+
});
|
|
1334
|
+
return popups.sort((a, b) => (a.regexClassification ?? "") > (b.regexClassification ?? "") ? 1 : -1);
|
|
1303
1335
|
}
|
|
1304
1336
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
}
|
|
1309
|
-
return collectPotentialPopups(isFramed, timeout);
|
|
1310
|
-
}
|
|
1311
|
-
function collectPotentialPopups(isFramed, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1312
|
-
let elements = [];
|
|
1313
|
-
if (!isFramed) {
|
|
1314
|
-
elements = getPopupLikeElements(timeout);
|
|
1315
|
-
} else {
|
|
1316
|
-
const doc = document.body || document.documentElement;
|
|
1317
|
-
if (doc && isElementVisible(doc) && doc.innerText) {
|
|
1318
|
-
elements.push(doc);
|
|
1337
|
+
if (!isTopFrame()) {
|
|
1338
|
+
if (window.parent && window.parent !== window.top) {
|
|
1339
|
+
return [];
|
|
1319
1340
|
}
|
|
1341
|
+
const frameElement = getFramePopupElement(document);
|
|
1342
|
+
const popup = frameElement && toPopupData(frameElement);
|
|
1343
|
+
return popup ? [popup] : [];
|
|
1320
1344
|
}
|
|
1345
|
+
const deadline = performance.now() + timeout;
|
|
1346
|
+
const { elements, shadowHosts } = getPopupLikeElements(deadline);
|
|
1321
1347
|
const potentialPopups = [];
|
|
1348
|
+
const expanded = [];
|
|
1322
1349
|
for (const el of elements) {
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1350
|
+
const popup = toPopupData(el, shadowHosts);
|
|
1351
|
+
if (!popup) {
|
|
1352
|
+
continue;
|
|
1353
|
+
}
|
|
1354
|
+
const root = performance.now() > deadline ? popup : expandPopupFragment(popup, shadowHosts);
|
|
1355
|
+
if (potentialPopups.some((p) => p.element === root.element)) {
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
if (root !== popup) {
|
|
1359
|
+
expanded.push(root.element);
|
|
1360
|
+
}
|
|
1361
|
+
potentialPopups.push(root);
|
|
1362
|
+
}
|
|
1363
|
+
return potentialPopups.filter((p) => !expanded.some((root) => root !== p.element && composedContains(root, p.element)));
|
|
1364
|
+
}
|
|
1365
|
+
function toPopupData(el, shadowHosts, text = getElementText(el)) {
|
|
1366
|
+
if (!text) {
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
const buttons = getButtonData(el, shadowHosts);
|
|
1370
|
+
classifyButtons(buttons);
|
|
1371
|
+
return { text, element: el, buttons };
|
|
1372
|
+
}
|
|
1373
|
+
function hasPopupButtons(text, buttons) {
|
|
1374
|
+
return !isOnlyButtonText(text, buttons) && buttons.some((b) => b.regexClassification !== "other");
|
|
1375
|
+
}
|
|
1376
|
+
function isOnlyButtonText(text, buttons) {
|
|
1377
|
+
let rest = text;
|
|
1378
|
+
for (const button of buttons) {
|
|
1379
|
+
rest = rest.replace(button.text, "");
|
|
1380
|
+
}
|
|
1381
|
+
return rest.replace(/\s+/g, "").length < 10;
|
|
1382
|
+
}
|
|
1383
|
+
var MAX_FRAGMENT_EXPANSION_DEPTH = 6;
|
|
1384
|
+
function expandPopupFragment(popup, shadowHosts) {
|
|
1385
|
+
if (hasHeuristicPatterns(popup.text) && hasPopupButtons(popup.text, popup.buttons)) {
|
|
1386
|
+
return popup;
|
|
1387
|
+
}
|
|
1388
|
+
let el = getComposedParent(popup.element);
|
|
1389
|
+
for (let depth = 0; el && depth < MAX_FRAGMENT_EXPANSION_DEPTH; depth++, el = getComposedParent(el)) {
|
|
1390
|
+
if (el === document.body || el === document.documentElement || el.getBoundingClientRect().height > window.innerHeight) {
|
|
1391
|
+
break;
|
|
1392
|
+
}
|
|
1393
|
+
const text = getElementText(el);
|
|
1394
|
+
if (!text || !hasHeuristicPatterns(text)) {
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
const root = toPopupData(el, shadowHosts, text);
|
|
1398
|
+
if (root && hasPopupButtons(text, root.buttons)) {
|
|
1399
|
+
return root;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
return popup;
|
|
1403
|
+
}
|
|
1404
|
+
function getComposedParent(el) {
|
|
1405
|
+
if (el.parentElement) {
|
|
1406
|
+
return el.parentElement;
|
|
1407
|
+
}
|
|
1408
|
+
const parent = el.parentNode;
|
|
1409
|
+
return parent instanceof ShadowRoot && parent.host instanceof HTMLElement ? parent.host : null;
|
|
1410
|
+
}
|
|
1411
|
+
function getFramePopupElement(doc) {
|
|
1412
|
+
const el = doc.body || doc.documentElement;
|
|
1413
|
+
const win = doc.defaultView;
|
|
1414
|
+
if (!el || !win || win.innerWidth === 0 || win.innerHeight === 0 || !isStyleVisible(el)) {
|
|
1415
|
+
return null;
|
|
1416
|
+
}
|
|
1417
|
+
return getElementText(el).trim() ? el : null;
|
|
1418
|
+
}
|
|
1419
|
+
function isStyleVisible(el) {
|
|
1420
|
+
return typeof el.checkVisibility !== "function" || el.checkVisibility({ checkVisibilityCSS: true });
|
|
1421
|
+
}
|
|
1422
|
+
function getElementText(el) {
|
|
1423
|
+
const text = el.innerText || "";
|
|
1424
|
+
if (!el.shadowRoot) {
|
|
1425
|
+
return text;
|
|
1426
|
+
}
|
|
1427
|
+
const shadowTexts = Array.from(el.shadowRoot.children, (child) => isRenderedTextElement(child) ? getElementText(child) : "");
|
|
1428
|
+
return [text, ...shadowTexts].filter((t) => t.trim()).join("\n");
|
|
1429
|
+
}
|
|
1430
|
+
function isRenderedTextElement(el) {
|
|
1431
|
+
return el instanceof HTMLElement && !["STYLE", "SCRIPT", "TEMPLATE", "NOSCRIPT", "LINK", "SLOT"].includes(el.tagName) && window.getComputedStyle(el).display !== "none";
|
|
1432
|
+
}
|
|
1433
|
+
function composedContains(container, node) {
|
|
1434
|
+
if (container.contains(node)) {
|
|
1435
|
+
return true;
|
|
1436
|
+
}
|
|
1437
|
+
let root = node.getRootNode();
|
|
1438
|
+
while (root instanceof ShadowRoot) {
|
|
1439
|
+
if (container.contains(root.host)) {
|
|
1440
|
+
return true;
|
|
1329
1441
|
}
|
|
1442
|
+
root = root.host.getRootNode();
|
|
1443
|
+
}
|
|
1444
|
+
return false;
|
|
1445
|
+
}
|
|
1446
|
+
function isPopupCandidateVisible(el) {
|
|
1447
|
+
return isElementVisible(el) && isStyleVisible(el) && isOnScreen(el);
|
|
1448
|
+
}
|
|
1449
|
+
function isOnScreen(el) {
|
|
1450
|
+
const rect = el.getBoundingClientRect();
|
|
1451
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
1452
|
+
return window.getComputedStyle(el).overflow === "visible" && Array.from(el.children).some((child) => isOnScreen(child));
|
|
1330
1453
|
}
|
|
1331
|
-
return
|
|
1454
|
+
return rect.bottom > 0 && rect.right > 0 && rect.top < window.innerHeight && rect.left < window.innerWidth;
|
|
1332
1455
|
}
|
|
1333
1456
|
function isDialogLikeElement(node) {
|
|
1334
1457
|
if (node.tagName === "DIALOG" && node.hasAttribute("open")) {
|
|
@@ -1339,72 +1462,95 @@
|
|
|
1339
1462
|
}
|
|
1340
1463
|
return false;
|
|
1341
1464
|
}
|
|
1342
|
-
function getPopupLikeElements(
|
|
1343
|
-
const
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1465
|
+
function getPopupLikeElements(deadline) {
|
|
1466
|
+
const found = [];
|
|
1467
|
+
const shadowHosts = [];
|
|
1468
|
+
const roots = [document.documentElement];
|
|
1469
|
+
for (let i = 0; i < roots.length; i++) {
|
|
1470
|
+
if (i > 0 && performance.now() > deadline) {
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
const walker = document.createTreeWalker(
|
|
1474
|
+
roots[i],
|
|
1475
|
+
NodeFilter.SHOW_ELEMENT,
|
|
1476
|
+
// visit only element nodes
|
|
1477
|
+
{
|
|
1478
|
+
acceptNode(node) {
|
|
1479
|
+
if (node.shadowRoot) {
|
|
1480
|
+
shadowHosts.push(node);
|
|
1481
|
+
roots.push(node.shadowRoot);
|
|
1482
|
+
}
|
|
1483
|
+
if (node.tagName === "BODY") {
|
|
1484
|
+
return NodeFilter.FILTER_SKIP;
|
|
1357
1485
|
}
|
|
1358
|
-
|
|
1486
|
+
const style = window.getComputedStyle(node);
|
|
1487
|
+
if (style.display === "none") {
|
|
1488
|
+
return NodeFilter.FILTER_REJECT;
|
|
1489
|
+
}
|
|
1490
|
+
const cssPosition = style.position;
|
|
1491
|
+
if ((cssPosition === "fixed" || cssPosition === "sticky" || isDialogLikeElement(node)) && isPopupCandidateVisible(node)) {
|
|
1359
1492
|
return NodeFilter.FILTER_ACCEPT;
|
|
1360
1493
|
}
|
|
1494
|
+
if (performance.now() > deadline) {
|
|
1495
|
+
return NodeFilter.FILTER_REJECT;
|
|
1496
|
+
}
|
|
1497
|
+
return NodeFilter.FILTER_SKIP;
|
|
1361
1498
|
}
|
|
1362
|
-
if (performance.now() - startTime > timeout) {
|
|
1363
|
-
return NodeFilter.FILTER_REJECT;
|
|
1364
|
-
}
|
|
1365
|
-
return NodeFilter.FILTER_SKIP;
|
|
1366
1499
|
}
|
|
1500
|
+
);
|
|
1501
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1502
|
+
found.push(node);
|
|
1367
1503
|
}
|
|
1368
|
-
);
|
|
1369
|
-
const found = [];
|
|
1370
|
-
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
1371
|
-
found.push(node);
|
|
1372
1504
|
}
|
|
1373
|
-
return excludeContainers(found.filter((element) => element.
|
|
1505
|
+
return { elements: excludeContainers(found.filter((element) => getElementText(element).trim())), shadowHosts };
|
|
1374
1506
|
}
|
|
1375
|
-
function getButtonData(el) {
|
|
1376
|
-
const
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
text
|
|
1382
|
-
|
|
1383
|
-
|
|
1507
|
+
function getButtonData(el, shadowHosts) {
|
|
1508
|
+
const buttons = [];
|
|
1509
|
+
for (const b of excludeContainers(getButtonLikeElements(el, shadowHosts))) {
|
|
1510
|
+
if (!isElementVisible(b) || isDisabled(b)) {
|
|
1511
|
+
continue;
|
|
1512
|
+
}
|
|
1513
|
+
const text = getElementText(b).trim() || // <input> values do not appear in innerText
|
|
1514
|
+
(b instanceof HTMLInputElement && ["submit", "button"].includes(b.type) ? b.value?.trim() : "");
|
|
1515
|
+
if (text) {
|
|
1516
|
+
buttons.push({ text, element: b });
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return buttons;
|
|
1384
1520
|
}
|
|
1385
|
-
function getButtonLikeElements(el) {
|
|
1386
|
-
|
|
1521
|
+
function getButtonLikeElements(el, shadowHosts = findShadowHosts(el)) {
|
|
1522
|
+
const buttons = Array.from(el.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1523
|
+
for (const host of shadowHosts) {
|
|
1524
|
+
if (composedContains(el, host)) {
|
|
1525
|
+
buttons.push(...host.shadowRoot.querySelectorAll(BUTTON_LIKE_ELEMENT_SELECTOR));
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return buttons;
|
|
1529
|
+
}
|
|
1530
|
+
function findShadowHosts(root) {
|
|
1531
|
+
const hosts = [];
|
|
1532
|
+
const candidates = root instanceof HTMLElement ? [root, ...root.querySelectorAll("*")] : root.querySelectorAll("*");
|
|
1533
|
+
for (const el of candidates) {
|
|
1534
|
+
if (el.shadowRoot) {
|
|
1535
|
+
hosts.push(el, ...findShadowHosts(el.shadowRoot));
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
return hosts;
|
|
1387
1539
|
}
|
|
1388
1540
|
function isDisabled(el) {
|
|
1389
1541
|
return "disabled" in el && Boolean(el.disabled) || el.hasAttribute("disabled");
|
|
1390
1542
|
}
|
|
1391
1543
|
function excludeContainers(elements) {
|
|
1392
|
-
const
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
container = true;
|
|
1399
|
-
break;
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
if (!container) {
|
|
1403
|
-
results.push(elements[i]);
|
|
1544
|
+
const candidates = new Set(elements);
|
|
1545
|
+
const containers = /* @__PURE__ */ new Set();
|
|
1546
|
+
for (const el of elements) {
|
|
1547
|
+
for (let node = el.parentNode; node; node = node.parentNode || (node instanceof ShadowRoot ? node.host : null)) {
|
|
1548
|
+
if (candidates.has(node)) {
|
|
1549
|
+
containers.add(node);
|
|
1404
1550
|
}
|
|
1405
1551
|
}
|
|
1406
1552
|
}
|
|
1407
|
-
return
|
|
1553
|
+
return elements.filter((el) => !containers.has(el)).reverse();
|
|
1408
1554
|
}
|
|
1409
1555
|
|
|
1410
1556
|
// lib/cmps/base.ts
|
|
@@ -2198,6 +2344,18 @@
|
|
|
2198
2344
|
get isCosmetic() {
|
|
2199
2345
|
return false;
|
|
2200
2346
|
}
|
|
2347
|
+
// Some sites pre-render the banner before the SDK loads, and clicks before then may be lost.
|
|
2348
|
+
// Sites that copy the markup without the SDK never get #onetrust-style, so only wait when the page loads the SDK.
|
|
2349
|
+
async waitForSdk() {
|
|
2350
|
+
if (this.elementExists("#onetrust-style")) {
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
const sdkRef = /cookielaw\.org|otSDKStub|otBannerSdk/;
|
|
2354
|
+
const sdkExpected = Array.from(document.scripts).some((s) => sdkRef.test(s.src) || !s.src && sdkRef.test(s.textContent || ""));
|
|
2355
|
+
if (sdkExpected) {
|
|
2356
|
+
await this.waitForElement("#onetrust-style", 1e4);
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2201
2359
|
async detectCmp() {
|
|
2202
2360
|
return this.elementExists("#onetrust-banner-sdk") || this.elementVisible("#onetrust-pc-sdk", "any");
|
|
2203
2361
|
}
|
|
@@ -2206,6 +2364,7 @@
|
|
|
2206
2364
|
}
|
|
2207
2365
|
async optOut() {
|
|
2208
2366
|
await this.wait(500);
|
|
2367
|
+
await this.waitForSdk();
|
|
2209
2368
|
if (this.elementVisible("#onetrust-reject-all-handler", "any")) {
|
|
2210
2369
|
return await this.click("#onetrust-reject-all-handler");
|
|
2211
2370
|
}
|
|
@@ -2245,6 +2404,7 @@
|
|
|
2245
2404
|
return true;
|
|
2246
2405
|
}
|
|
2247
2406
|
async optIn() {
|
|
2407
|
+
await this.waitForSdk();
|
|
2248
2408
|
return await this.click("#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies");
|
|
2249
2409
|
}
|
|
2250
2410
|
async test() {
|