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