@duckduckgo/autoconsent 14.97.0 → 15.0.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/CHANGELOG.md +18 -0
- package/dist/addon-firefox/background.bundle.js +10 -1
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/content.bundle.js +142 -33
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/popup.bundle.js +10 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/background.bundle.js +10 -1
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/content.bundle.js +142 -33
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/popup.bundle.js +10 -1
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +142 -33
- package/dist/autoconsent.esm.js +142 -33
- package/dist/autoconsent.extra.cjs.js +142 -33
- package/dist/autoconsent.extra.esm.js +142 -33
- package/dist/autoconsent.playwright.js +142 -33
- package/dist/types/cmps/base.d.ts +4 -2
- package/dist/types/heuristic-patterns.d.ts +3 -0
- package/dist/types/heuristics.d.ts +4 -7
- package/dist/types/types.d.ts +18 -2
- package/lib/cmps/base.ts +20 -7
- package/lib/heuristic-patterns.ts +68 -1
- package/lib/heuristics.ts +76 -27
- package/lib/types.ts +20 -2
- package/lib/utils.ts +2 -1
- package/lib/web.ts +3 -1
- package/package.json +1 -1
- package/rules/autoconsent/twitch.json +1 -1
- package/rules/compact-rules.json +1 -1
- package/rules/rules.json +1 -1
- package/tests-wtr/heuristics/get-actionable-popups.html +16 -0
- package/tests-wtr/heuristics/get-actionable-popups.ts +85 -6
- package/tests-wtr/heuristics/heuristic-cmp.html +69 -0
- package/tests-wtr/heuristics/heuristic-cmp.ts +178 -0
- package/tests-wtr/heuristics/heuristics-utils.test.ts +96 -28
- package/tests-wtr/lifecycle/find-cmp.html +14 -0
- package/tests-wtr/lifecycle/find-cmp.ts +44 -2
package/dist/autoconsent.cjs.js
CHANGED
|
@@ -435,6 +435,14 @@ async function evalAction(config) {
|
|
|
435
435
|
});
|
|
436
436
|
}
|
|
437
437
|
|
|
438
|
+
// lib/types.ts
|
|
439
|
+
var PopupHandlingModes = {
|
|
440
|
+
None: -1,
|
|
441
|
+
Reject: 0,
|
|
442
|
+
Tier1: 1,
|
|
443
|
+
Tier2: 2
|
|
444
|
+
};
|
|
445
|
+
|
|
438
446
|
// lib/random.ts
|
|
439
447
|
function getRandomID() {
|
|
440
448
|
if (crypto && typeof crypto.randomUUID !== "undefined") {
|
|
@@ -744,7 +752,8 @@ function normalizeConfig(providedConfig) {
|
|
|
744
752
|
waits: false
|
|
745
753
|
},
|
|
746
754
|
performanceLoggingEnabled: false,
|
|
747
|
-
heuristicPopupSearchTimeout: 100
|
|
755
|
+
heuristicPopupSearchTimeout: 100,
|
|
756
|
+
heuristicMode: PopupHandlingModes.Reject
|
|
748
757
|
};
|
|
749
758
|
const updatedConfig = copyObject(defaultConfig);
|
|
750
759
|
for (const key of Object.keys(defaultConfig)) {
|
|
@@ -911,12 +920,17 @@ var REJECT_PATTERNS_ENGLISH = [
|
|
|
911
920
|
/^\s*(use|accept|allow|continue\s+with)?\s*only\s*(strictly)?\s*(necessary|essentials?|required)?\s*(cookies)?\s*$/is,
|
|
912
921
|
// e.g. "do not sell or share my personal information", "do not sell my personal information"
|
|
913
922
|
// often used in CCPA
|
|
914
|
-
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*
|
|
923
|
+
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*info(rmation)?\s*$/is,
|
|
915
924
|
"allow selection",
|
|
916
|
-
"disagree and close"
|
|
925
|
+
"disagree and close",
|
|
917
926
|
// These are impactful, but look error-prone
|
|
927
|
+
// // e.g. "disagree"
|
|
928
|
+
/^(i)?\s*disagree\s*(and\s+close)?$/i,
|
|
918
929
|
// // e.g. "i do not agree"
|
|
919
930
|
// /^\s*(i\s+)?do\s+not\s+agree\s*$/i,
|
|
931
|
+
"no",
|
|
932
|
+
/^no,? thanks$/is,
|
|
933
|
+
/^opt[ -]out$/is
|
|
920
934
|
];
|
|
921
935
|
var REJECT_PATTERNS_DUTCH = [
|
|
922
936
|
"weigeren",
|
|
@@ -1492,6 +1506,64 @@ var NEVER_MATCH_PATTERNS = [
|
|
|
1492
1506
|
/sostienici/is,
|
|
1493
1507
|
/suscribir/is
|
|
1494
1508
|
];
|
|
1509
|
+
var SETTINGS_PATTERNS = [
|
|
1510
|
+
"settings",
|
|
1511
|
+
"preferences",
|
|
1512
|
+
/customi(s|z)e/is,
|
|
1513
|
+
"show details",
|
|
1514
|
+
"more options",
|
|
1515
|
+
/(manage|configure) (my|your) (preferences|choices|cookies)/is,
|
|
1516
|
+
"manage choices",
|
|
1517
|
+
/(cookie )?preference center/is,
|
|
1518
|
+
"change settings",
|
|
1519
|
+
"configure",
|
|
1520
|
+
"change my preferences",
|
|
1521
|
+
"cookie manager",
|
|
1522
|
+
"cookie preference",
|
|
1523
|
+
"let me choose",
|
|
1524
|
+
"cookieconsent preferences",
|
|
1525
|
+
/privacy choices/is,
|
|
1526
|
+
/(privacy|cookie|custom) settings/is,
|
|
1527
|
+
/cookies? (settings|preferences|setting)/is,
|
|
1528
|
+
/(manage|customize|customise|opt-out|edit).*(cookies|preferences|settings|options)/is,
|
|
1529
|
+
"cookie consent options",
|
|
1530
|
+
"privacy controls",
|
|
1531
|
+
"show purposes",
|
|
1532
|
+
// German
|
|
1533
|
+
"einstellungen"
|
|
1534
|
+
];
|
|
1535
|
+
var ACCEPT_PATTERNS = [
|
|
1536
|
+
/^(accept|allow)( all)?( cookies)?$/is,
|
|
1537
|
+
/i (accept|allow)( all)?/is,
|
|
1538
|
+
"yes",
|
|
1539
|
+
/^(i )?agree$/is,
|
|
1540
|
+
"continue with all",
|
|
1541
|
+
"accept and continue",
|
|
1542
|
+
/accept all above/is,
|
|
1543
|
+
/^(accept|agree) and close/is,
|
|
1544
|
+
"accept continue",
|
|
1545
|
+
"agree proceed",
|
|
1546
|
+
"allow and continue",
|
|
1547
|
+
"close and accept",
|
|
1548
|
+
/accept all$/is,
|
|
1549
|
+
"im ok with that",
|
|
1550
|
+
"accept optional cookies",
|
|
1551
|
+
/^alle (cookies )?akzeptieren$/is
|
|
1552
|
+
];
|
|
1553
|
+
var ACKNOWLEDGE_PATTERNS = [
|
|
1554
|
+
"ok",
|
|
1555
|
+
"close",
|
|
1556
|
+
"continue",
|
|
1557
|
+
"x",
|
|
1558
|
+
/^got it!?$/,
|
|
1559
|
+
"i understand",
|
|
1560
|
+
"dismiss",
|
|
1561
|
+
"okay",
|
|
1562
|
+
"acknowledge",
|
|
1563
|
+
/^close (banner|cookie notification)$/is,
|
|
1564
|
+
/understood$/is,
|
|
1565
|
+
"confirm my choices"
|
|
1566
|
+
];
|
|
1495
1567
|
|
|
1496
1568
|
// lib/heuristics.ts
|
|
1497
1569
|
var BUTTON_LIKE_ELEMENT_SELECTOR = 'button, input[type="button"], input[type="submit"], a, [role="button"], [class*="button"]';
|
|
@@ -1510,48 +1582,61 @@ function checkHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
|
1510
1582
|
}
|
|
1511
1583
|
return { patterns, snippets: snippets2 };
|
|
1512
1584
|
}
|
|
1513
|
-
function getActionablePopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1585
|
+
function getActionablePopups(mode = PopupHandlingModes.Reject, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1514
1586
|
const popups = getPotentialPopups(timeout);
|
|
1515
1587
|
const result = popups.reduce((acc, popup) => {
|
|
1516
1588
|
const popupText = popup.text?.trim();
|
|
1517
1589
|
if (popupText) {
|
|
1518
1590
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1519
1591
|
if (patterns.length > 0) {
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
otherButtons
|
|
1526
|
-
});
|
|
1527
|
-
}
|
|
1592
|
+
classifyButtons(popup.buttons);
|
|
1593
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1594
|
+
acc.push({
|
|
1595
|
+
...popup
|
|
1596
|
+
});
|
|
1528
1597
|
}
|
|
1529
1598
|
}
|
|
1530
1599
|
return acc;
|
|
1531
1600
|
}, []);
|
|
1532
|
-
return result
|
|
1601
|
+
return result.filter(
|
|
1602
|
+
(popup) => popup.regexClassification !== void 0 && popup.regexClassification !== PopupHandlingModes.None && popup.regexClassification <= mode
|
|
1603
|
+
).sort((a, b) => (a.regexClassification ?? 0) - (b.regexClassification ?? 0));
|
|
1533
1604
|
}
|
|
1534
1605
|
function classifyButtons(buttons) {
|
|
1535
|
-
const rejectButtons = [];
|
|
1536
|
-
const otherButtons = [];
|
|
1537
1606
|
for (const button of buttons) {
|
|
1538
|
-
|
|
1539
|
-
rejectButtons.push(button);
|
|
1540
|
-
} else {
|
|
1541
|
-
otherButtons.push(button);
|
|
1542
|
-
}
|
|
1607
|
+
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1543
1608
|
}
|
|
1544
|
-
return {
|
|
1545
|
-
rejectButtons,
|
|
1546
|
-
otherButtons
|
|
1547
|
-
};
|
|
1548
1609
|
}
|
|
1549
|
-
function
|
|
1610
|
+
function classifyPopup(buttons) {
|
|
1611
|
+
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1612
|
+
(acc, button) => {
|
|
1613
|
+
if (button.regexClassification && button.regexClassification !== "other") {
|
|
1614
|
+
acc[button.regexClassification]++;
|
|
1615
|
+
}
|
|
1616
|
+
return acc;
|
|
1617
|
+
},
|
|
1618
|
+
{ reject: 0, settings: 0, accept: 0, acknowledge: 0 }
|
|
1619
|
+
);
|
|
1620
|
+
if (reject > 0) {
|
|
1621
|
+
return PopupHandlingModes.Reject;
|
|
1622
|
+
}
|
|
1623
|
+
if (settings > 0) {
|
|
1624
|
+
return PopupHandlingModes.None;
|
|
1625
|
+
}
|
|
1626
|
+
if (acknowledge > 0) {
|
|
1627
|
+
return PopupHandlingModes.Tier1;
|
|
1628
|
+
}
|
|
1629
|
+
if (accept > 0) {
|
|
1630
|
+
return accept === 1 ? PopupHandlingModes.Tier2 : PopupHandlingModes.None;
|
|
1631
|
+
}
|
|
1632
|
+
return PopupHandlingModes.None;
|
|
1633
|
+
}
|
|
1634
|
+
function testButtonMatches(buttonText, matchPatterns, neverMatchPatterns) {
|
|
1550
1635
|
if (!buttonText) {
|
|
1551
1636
|
return false;
|
|
1552
1637
|
}
|
|
1553
1638
|
const cleanedButtonText = cleanButtonText(buttonText);
|
|
1554
|
-
return !neverMatchPatterns.some((p) => p.test(cleanedButtonText)) &&
|
|
1639
|
+
return !neverMatchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText) && matchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText);
|
|
1555
1640
|
}
|
|
1556
1641
|
function cleanButtonText(buttonText) {
|
|
1557
1642
|
let result = buttonText.toLowerCase();
|
|
@@ -1565,6 +1650,21 @@ function cleanButtonText(buttonText) {
|
|
|
1565
1650
|
result = result.trim();
|
|
1566
1651
|
return result;
|
|
1567
1652
|
}
|
|
1653
|
+
function classifyButtonTextRegex(buttonText) {
|
|
1654
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1655
|
+
return "reject";
|
|
1656
|
+
}
|
|
1657
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1658
|
+
return "settings";
|
|
1659
|
+
}
|
|
1660
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1661
|
+
return "accept";
|
|
1662
|
+
}
|
|
1663
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1664
|
+
return "acknowledge";
|
|
1665
|
+
}
|
|
1666
|
+
return "other";
|
|
1667
|
+
}
|
|
1568
1668
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1569
1669
|
const isFramed = !isTopFrame();
|
|
1570
1670
|
if (isFramed && window.parent && window.parent !== window.top) {
|
|
@@ -2010,7 +2110,7 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
|
|
|
2010
2110
|
}
|
|
2011
2111
|
};
|
|
2012
2112
|
var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
2013
|
-
constructor(autoconsentInstance) {
|
|
2113
|
+
constructor(autoconsentInstance, mode = PopupHandlingModes.Reject) {
|
|
2014
2114
|
super(autoconsentInstance);
|
|
2015
2115
|
this.popups = [];
|
|
2016
2116
|
this.name = "HEURISTIC";
|
|
@@ -2019,6 +2119,7 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
2019
2119
|
frame: false
|
|
2020
2120
|
// do not run in iframes for security reasons
|
|
2021
2121
|
};
|
|
2122
|
+
this.mode = mode;
|
|
2022
2123
|
}
|
|
2023
2124
|
get hasSelfTest() {
|
|
2024
2125
|
return true;
|
|
@@ -2032,25 +2133,33 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
2032
2133
|
async detectCmp() {
|
|
2033
2134
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2034
2135
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorStart");
|
|
2035
|
-
this.popups = getActionablePopups(this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2136
|
+
this.popups = getActionablePopups(this.mode, this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2036
2137
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorEnd");
|
|
2037
2138
|
this.autoconsent.config.performanceLoggingEnabled && performance.measure("heuristicDetector", "heuristicDetectorStart", "heuristicDetectorEnd");
|
|
2038
2139
|
if (this.popups.length > 0) {
|
|
2140
|
+
this.name = `HEURISTIC-TIER${this.popups[0].regexClassification}`;
|
|
2039
2141
|
return Promise.resolve(true);
|
|
2040
2142
|
}
|
|
2041
2143
|
return Promise.resolve(false);
|
|
2042
2144
|
}
|
|
2043
2145
|
async detectPopup() {
|
|
2044
2146
|
if (this.popups.length > 0) {
|
|
2045
|
-
if (this.popups.length > 1
|
|
2046
|
-
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple
|
|
2147
|
+
if (this.popups.length > 1) {
|
|
2148
|
+
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple popups");
|
|
2047
2149
|
}
|
|
2048
2150
|
return true;
|
|
2049
2151
|
}
|
|
2050
2152
|
return false;
|
|
2051
2153
|
}
|
|
2154
|
+
getTargetButton() {
|
|
2155
|
+
const popup = this.popups[0];
|
|
2156
|
+
const level = popup.regexClassification;
|
|
2157
|
+
const buttons = popup.buttons;
|
|
2158
|
+
const targetButtonType = level === PopupHandlingModes.Reject ? "reject" : level === PopupHandlingModes.Tier1 ? "acknowledge" : "accept";
|
|
2159
|
+
return buttons.find((button) => button.regexClassification === targetButtonType);
|
|
2160
|
+
}
|
|
2052
2161
|
optOut() {
|
|
2053
|
-
const button = this.
|
|
2162
|
+
const button = this.getTargetButton();
|
|
2054
2163
|
if (button) {
|
|
2055
2164
|
return this.clickElement(button.element);
|
|
2056
2165
|
}
|
|
@@ -2063,7 +2172,7 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
2063
2172
|
throw new Error("Not Implemented");
|
|
2064
2173
|
}
|
|
2065
2174
|
async test() {
|
|
2066
|
-
const button = this.
|
|
2175
|
+
const button = this.getTargetButton();
|
|
2067
2176
|
if (button) {
|
|
2068
2177
|
await this.wait(500);
|
|
2069
2178
|
return !isElementVisible(button.element);
|
|
@@ -3765,7 +3874,7 @@ var AutoConsent = class {
|
|
|
3765
3874
|
}
|
|
3766
3875
|
}
|
|
3767
3876
|
});
|
|
3768
|
-
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this)] : [];
|
|
3877
|
+
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)] : [];
|
|
3769
3878
|
const rulesPriorityStages = [
|
|
3770
3879
|
["site-specific", siteSpecificRules],
|
|
3771
3880
|
["generic", genericRules],
|
package/dist/autoconsent.esm.js
CHANGED
|
@@ -405,6 +405,14 @@ async function evalAction(config) {
|
|
|
405
405
|
});
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
+
// lib/types.ts
|
|
409
|
+
var PopupHandlingModes = {
|
|
410
|
+
None: -1,
|
|
411
|
+
Reject: 0,
|
|
412
|
+
Tier1: 1,
|
|
413
|
+
Tier2: 2
|
|
414
|
+
};
|
|
415
|
+
|
|
408
416
|
// lib/random.ts
|
|
409
417
|
function getRandomID() {
|
|
410
418
|
if (crypto && typeof crypto.randomUUID !== "undefined") {
|
|
@@ -714,7 +722,8 @@ function normalizeConfig(providedConfig) {
|
|
|
714
722
|
waits: false
|
|
715
723
|
},
|
|
716
724
|
performanceLoggingEnabled: false,
|
|
717
|
-
heuristicPopupSearchTimeout: 100
|
|
725
|
+
heuristicPopupSearchTimeout: 100,
|
|
726
|
+
heuristicMode: PopupHandlingModes.Reject
|
|
718
727
|
};
|
|
719
728
|
const updatedConfig = copyObject(defaultConfig);
|
|
720
729
|
for (const key of Object.keys(defaultConfig)) {
|
|
@@ -881,12 +890,17 @@ var REJECT_PATTERNS_ENGLISH = [
|
|
|
881
890
|
/^\s*(use|accept|allow|continue\s+with)?\s*only\s*(strictly)?\s*(necessary|essentials?|required)?\s*(cookies)?\s*$/is,
|
|
882
891
|
// e.g. "do not sell or share my personal information", "do not sell my personal information"
|
|
883
892
|
// often used in CCPA
|
|
884
|
-
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*
|
|
893
|
+
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*info(rmation)?\s*$/is,
|
|
885
894
|
"allow selection",
|
|
886
|
-
"disagree and close"
|
|
895
|
+
"disagree and close",
|
|
887
896
|
// These are impactful, but look error-prone
|
|
897
|
+
// // e.g. "disagree"
|
|
898
|
+
/^(i)?\s*disagree\s*(and\s+close)?$/i,
|
|
888
899
|
// // e.g. "i do not agree"
|
|
889
900
|
// /^\s*(i\s+)?do\s+not\s+agree\s*$/i,
|
|
901
|
+
"no",
|
|
902
|
+
/^no,? thanks$/is,
|
|
903
|
+
/^opt[ -]out$/is
|
|
890
904
|
];
|
|
891
905
|
var REJECT_PATTERNS_DUTCH = [
|
|
892
906
|
"weigeren",
|
|
@@ -1462,6 +1476,64 @@ var NEVER_MATCH_PATTERNS = [
|
|
|
1462
1476
|
/sostienici/is,
|
|
1463
1477
|
/suscribir/is
|
|
1464
1478
|
];
|
|
1479
|
+
var SETTINGS_PATTERNS = [
|
|
1480
|
+
"settings",
|
|
1481
|
+
"preferences",
|
|
1482
|
+
/customi(s|z)e/is,
|
|
1483
|
+
"show details",
|
|
1484
|
+
"more options",
|
|
1485
|
+
/(manage|configure) (my|your) (preferences|choices|cookies)/is,
|
|
1486
|
+
"manage choices",
|
|
1487
|
+
/(cookie )?preference center/is,
|
|
1488
|
+
"change settings",
|
|
1489
|
+
"configure",
|
|
1490
|
+
"change my preferences",
|
|
1491
|
+
"cookie manager",
|
|
1492
|
+
"cookie preference",
|
|
1493
|
+
"let me choose",
|
|
1494
|
+
"cookieconsent preferences",
|
|
1495
|
+
/privacy choices/is,
|
|
1496
|
+
/(privacy|cookie|custom) settings/is,
|
|
1497
|
+
/cookies? (settings|preferences|setting)/is,
|
|
1498
|
+
/(manage|customize|customise|opt-out|edit).*(cookies|preferences|settings|options)/is,
|
|
1499
|
+
"cookie consent options",
|
|
1500
|
+
"privacy controls",
|
|
1501
|
+
"show purposes",
|
|
1502
|
+
// German
|
|
1503
|
+
"einstellungen"
|
|
1504
|
+
];
|
|
1505
|
+
var ACCEPT_PATTERNS = [
|
|
1506
|
+
/^(accept|allow)( all)?( cookies)?$/is,
|
|
1507
|
+
/i (accept|allow)( all)?/is,
|
|
1508
|
+
"yes",
|
|
1509
|
+
/^(i )?agree$/is,
|
|
1510
|
+
"continue with all",
|
|
1511
|
+
"accept and continue",
|
|
1512
|
+
/accept all above/is,
|
|
1513
|
+
/^(accept|agree) and close/is,
|
|
1514
|
+
"accept continue",
|
|
1515
|
+
"agree proceed",
|
|
1516
|
+
"allow and continue",
|
|
1517
|
+
"close and accept",
|
|
1518
|
+
/accept all$/is,
|
|
1519
|
+
"im ok with that",
|
|
1520
|
+
"accept optional cookies",
|
|
1521
|
+
/^alle (cookies )?akzeptieren$/is
|
|
1522
|
+
];
|
|
1523
|
+
var ACKNOWLEDGE_PATTERNS = [
|
|
1524
|
+
"ok",
|
|
1525
|
+
"close",
|
|
1526
|
+
"continue",
|
|
1527
|
+
"x",
|
|
1528
|
+
/^got it!?$/,
|
|
1529
|
+
"i understand",
|
|
1530
|
+
"dismiss",
|
|
1531
|
+
"okay",
|
|
1532
|
+
"acknowledge",
|
|
1533
|
+
/^close (banner|cookie notification)$/is,
|
|
1534
|
+
/understood$/is,
|
|
1535
|
+
"confirm my choices"
|
|
1536
|
+
];
|
|
1465
1537
|
|
|
1466
1538
|
// lib/heuristics.ts
|
|
1467
1539
|
var BUTTON_LIKE_ELEMENT_SELECTOR = 'button, input[type="button"], input[type="submit"], a, [role="button"], [class*="button"]';
|
|
@@ -1480,48 +1552,61 @@ function checkHeuristicPatterns(allText, detectPatterns = DETECT_PATTERNS) {
|
|
|
1480
1552
|
}
|
|
1481
1553
|
return { patterns, snippets: snippets2 };
|
|
1482
1554
|
}
|
|
1483
|
-
function getActionablePopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1555
|
+
function getActionablePopups(mode = PopupHandlingModes.Reject, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1484
1556
|
const popups = getPotentialPopups(timeout);
|
|
1485
1557
|
const result = popups.reduce((acc, popup) => {
|
|
1486
1558
|
const popupText = popup.text?.trim();
|
|
1487
1559
|
if (popupText) {
|
|
1488
1560
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1489
1561
|
if (patterns.length > 0) {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
otherButtons
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1562
|
+
classifyButtons(popup.buttons);
|
|
1563
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1564
|
+
acc.push({
|
|
1565
|
+
...popup
|
|
1566
|
+
});
|
|
1498
1567
|
}
|
|
1499
1568
|
}
|
|
1500
1569
|
return acc;
|
|
1501
1570
|
}, []);
|
|
1502
|
-
return result
|
|
1571
|
+
return result.filter(
|
|
1572
|
+
(popup) => popup.regexClassification !== void 0 && popup.regexClassification !== PopupHandlingModes.None && popup.regexClassification <= mode
|
|
1573
|
+
).sort((a, b) => (a.regexClassification ?? 0) - (b.regexClassification ?? 0));
|
|
1503
1574
|
}
|
|
1504
1575
|
function classifyButtons(buttons) {
|
|
1505
|
-
const rejectButtons = [];
|
|
1506
|
-
const otherButtons = [];
|
|
1507
1576
|
for (const button of buttons) {
|
|
1508
|
-
|
|
1509
|
-
rejectButtons.push(button);
|
|
1510
|
-
} else {
|
|
1511
|
-
otherButtons.push(button);
|
|
1512
|
-
}
|
|
1577
|
+
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1513
1578
|
}
|
|
1514
|
-
return {
|
|
1515
|
-
rejectButtons,
|
|
1516
|
-
otherButtons
|
|
1517
|
-
};
|
|
1518
1579
|
}
|
|
1519
|
-
function
|
|
1580
|
+
function classifyPopup(buttons) {
|
|
1581
|
+
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1582
|
+
(acc, button) => {
|
|
1583
|
+
if (button.regexClassification && button.regexClassification !== "other") {
|
|
1584
|
+
acc[button.regexClassification]++;
|
|
1585
|
+
}
|
|
1586
|
+
return acc;
|
|
1587
|
+
},
|
|
1588
|
+
{ reject: 0, settings: 0, accept: 0, acknowledge: 0 }
|
|
1589
|
+
);
|
|
1590
|
+
if (reject > 0) {
|
|
1591
|
+
return PopupHandlingModes.Reject;
|
|
1592
|
+
}
|
|
1593
|
+
if (settings > 0) {
|
|
1594
|
+
return PopupHandlingModes.None;
|
|
1595
|
+
}
|
|
1596
|
+
if (acknowledge > 0) {
|
|
1597
|
+
return PopupHandlingModes.Tier1;
|
|
1598
|
+
}
|
|
1599
|
+
if (accept > 0) {
|
|
1600
|
+
return accept === 1 ? PopupHandlingModes.Tier2 : PopupHandlingModes.None;
|
|
1601
|
+
}
|
|
1602
|
+
return PopupHandlingModes.None;
|
|
1603
|
+
}
|
|
1604
|
+
function testButtonMatches(buttonText, matchPatterns, neverMatchPatterns) {
|
|
1520
1605
|
if (!buttonText) {
|
|
1521
1606
|
return false;
|
|
1522
1607
|
}
|
|
1523
1608
|
const cleanedButtonText = cleanButtonText(buttonText);
|
|
1524
|
-
return !neverMatchPatterns.some((p) => p.test(cleanedButtonText)) &&
|
|
1609
|
+
return !neverMatchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText) && matchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText);
|
|
1525
1610
|
}
|
|
1526
1611
|
function cleanButtonText(buttonText) {
|
|
1527
1612
|
let result = buttonText.toLowerCase();
|
|
@@ -1535,6 +1620,21 @@ function cleanButtonText(buttonText) {
|
|
|
1535
1620
|
result = result.trim();
|
|
1536
1621
|
return result;
|
|
1537
1622
|
}
|
|
1623
|
+
function classifyButtonTextRegex(buttonText) {
|
|
1624
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1625
|
+
return "reject";
|
|
1626
|
+
}
|
|
1627
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1628
|
+
return "settings";
|
|
1629
|
+
}
|
|
1630
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1631
|
+
return "accept";
|
|
1632
|
+
}
|
|
1633
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1634
|
+
return "acknowledge";
|
|
1635
|
+
}
|
|
1636
|
+
return "other";
|
|
1637
|
+
}
|
|
1538
1638
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1539
1639
|
const isFramed = !isTopFrame();
|
|
1540
1640
|
if (isFramed && window.parent && window.parent !== window.top) {
|
|
@@ -1980,7 +2080,7 @@ var AutoConsentCMP = class extends AutoConsentCMPBase {
|
|
|
1980
2080
|
}
|
|
1981
2081
|
};
|
|
1982
2082
|
var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
1983
|
-
constructor(autoconsentInstance) {
|
|
2083
|
+
constructor(autoconsentInstance, mode = PopupHandlingModes.Reject) {
|
|
1984
2084
|
super(autoconsentInstance);
|
|
1985
2085
|
this.popups = [];
|
|
1986
2086
|
this.name = "HEURISTIC";
|
|
@@ -1989,6 +2089,7 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
1989
2089
|
frame: false
|
|
1990
2090
|
// do not run in iframes for security reasons
|
|
1991
2091
|
};
|
|
2092
|
+
this.mode = mode;
|
|
1992
2093
|
}
|
|
1993
2094
|
get hasSelfTest() {
|
|
1994
2095
|
return true;
|
|
@@ -2002,25 +2103,33 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
2002
2103
|
async detectCmp() {
|
|
2003
2104
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2004
2105
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorStart");
|
|
2005
|
-
this.popups = getActionablePopups(this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2106
|
+
this.popups = getActionablePopups(this.mode, this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2006
2107
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorEnd");
|
|
2007
2108
|
this.autoconsent.config.performanceLoggingEnabled && performance.measure("heuristicDetector", "heuristicDetectorStart", "heuristicDetectorEnd");
|
|
2008
2109
|
if (this.popups.length > 0) {
|
|
2110
|
+
this.name = `HEURISTIC-TIER${this.popups[0].regexClassification}`;
|
|
2009
2111
|
return Promise.resolve(true);
|
|
2010
2112
|
}
|
|
2011
2113
|
return Promise.resolve(false);
|
|
2012
2114
|
}
|
|
2013
2115
|
async detectPopup() {
|
|
2014
2116
|
if (this.popups.length > 0) {
|
|
2015
|
-
if (this.popups.length > 1
|
|
2016
|
-
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple
|
|
2117
|
+
if (this.popups.length > 1) {
|
|
2118
|
+
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple popups");
|
|
2017
2119
|
}
|
|
2018
2120
|
return true;
|
|
2019
2121
|
}
|
|
2020
2122
|
return false;
|
|
2021
2123
|
}
|
|
2124
|
+
getTargetButton() {
|
|
2125
|
+
const popup = this.popups[0];
|
|
2126
|
+
const level = popup.regexClassification;
|
|
2127
|
+
const buttons = popup.buttons;
|
|
2128
|
+
const targetButtonType = level === PopupHandlingModes.Reject ? "reject" : level === PopupHandlingModes.Tier1 ? "acknowledge" : "accept";
|
|
2129
|
+
return buttons.find((button) => button.regexClassification === targetButtonType);
|
|
2130
|
+
}
|
|
2022
2131
|
optOut() {
|
|
2023
|
-
const button = this.
|
|
2132
|
+
const button = this.getTargetButton();
|
|
2024
2133
|
if (button) {
|
|
2025
2134
|
return this.clickElement(button.element);
|
|
2026
2135
|
}
|
|
@@ -2033,7 +2142,7 @@ var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
|
2033
2142
|
throw new Error("Not Implemented");
|
|
2034
2143
|
}
|
|
2035
2144
|
async test() {
|
|
2036
|
-
const button = this.
|
|
2145
|
+
const button = this.getTargetButton();
|
|
2037
2146
|
if (button) {
|
|
2038
2147
|
await this.wait(500);
|
|
2039
2148
|
return !isElementVisible(button.element);
|
|
@@ -3735,7 +3844,7 @@ var AutoConsent = class {
|
|
|
3735
3844
|
}
|
|
3736
3845
|
}
|
|
3737
3846
|
});
|
|
3738
|
-
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this)] : [];
|
|
3847
|
+
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)] : [];
|
|
3739
3848
|
const rulesPriorityStages = [
|
|
3740
3849
|
["site-specific", siteSpecificRules],
|
|
3741
3850
|
["generic", genericRules],
|