@duckduckgo/autoconsent 14.97.0 → 15.1.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 +30 -0
- package/build.sh +3 -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 +157 -40
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/popup.bundle.js +190 -14
- package/dist/addon-firefox/popup.html +93 -8
- package/dist/addon-firefox/rule-index.json +1 -0
- 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 +157 -40
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/popup.bundle.js +190 -14
- package/dist/addon-mv3/popup.html +93 -8
- package/dist/addon-mv3/rule-index.json +1 -0
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.cjs.js +157 -40
- package/dist/autoconsent.esm.js +157 -40
- package/dist/autoconsent.extra.cjs.js +157 -40
- package/dist/autoconsent.extra.esm.js +157 -40
- package/dist/autoconsent.playwright.js +157 -40
- package/dist/autoconsent.standalone.js +4138 -0
- package/dist/types/cmps/base.d.ts +4 -2
- package/dist/types/cmps/trustarc-top.d.ts +1 -1
- package/dist/types/eval-handler.d.ts +3 -3
- 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/cmps/conversant.ts +7 -4
- package/lib/cmps/trustarc-top.ts +1 -1
- package/lib/cmps/uniconsent.ts +4 -4
- package/lib/eval-handler.ts +6 -3
- package/lib/heuristic-patterns.ts +68 -1
- package/lib/heuristics.ts +76 -27
- package/lib/types.ts +20 -2
- package/lib/utils.ts +13 -6
- package/lib/web.ts +3 -1
- package/package.json +1 -1
- package/rules/autoconsent/twitch.json +1 -1
- package/rules/build.ts +4 -0
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index-builder.ts +63 -0
- package/rules/rule-index.json +1 -0
- package/rules/rules.json +1 -1
- package/standalone/content.ts +103 -0
- 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
|
@@ -407,6 +407,14 @@
|
|
|
407
407
|
});
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
// lib/types.ts
|
|
411
|
+
var PopupHandlingModes = {
|
|
412
|
+
None: -1,
|
|
413
|
+
Reject: 0,
|
|
414
|
+
Tier1: 1,
|
|
415
|
+
Tier2: 2
|
|
416
|
+
};
|
|
417
|
+
|
|
410
418
|
// lib/random.ts
|
|
411
419
|
function getRandomID() {
|
|
412
420
|
if (crypto && typeof crypto.randomUUID !== "undefined") {
|
|
@@ -433,6 +441,9 @@
|
|
|
433
441
|
sendContentMessage: null
|
|
434
442
|
};
|
|
435
443
|
function requestEval(code, snippetId) {
|
|
444
|
+
if (!evalState.sendContentMessage) {
|
|
445
|
+
return Promise.reject(new Error("AutoConsent is not initialized yet"));
|
|
446
|
+
}
|
|
436
447
|
const id = getRandomID();
|
|
437
448
|
evalState.sendContentMessage({
|
|
438
449
|
type: "eval",
|
|
@@ -716,7 +727,8 @@
|
|
|
716
727
|
waits: false
|
|
717
728
|
},
|
|
718
729
|
performanceLoggingEnabled: false,
|
|
719
|
-
heuristicPopupSearchTimeout: 100
|
|
730
|
+
heuristicPopupSearchTimeout: 100,
|
|
731
|
+
heuristicMode: PopupHandlingModes.Reject
|
|
720
732
|
};
|
|
721
733
|
const updatedConfig = copyObject(defaultConfig);
|
|
722
734
|
for (const key of Object.keys(defaultConfig)) {
|
|
@@ -734,12 +746,13 @@
|
|
|
734
746
|
}
|
|
735
747
|
}
|
|
736
748
|
function highlightNode(node) {
|
|
749
|
+
const highlightedNode = node;
|
|
737
750
|
if (!node.style) return;
|
|
738
|
-
if (
|
|
751
|
+
if (highlightedNode.__oldStyles !== void 0) {
|
|
739
752
|
return;
|
|
740
753
|
}
|
|
741
754
|
if (node.hasAttribute("style")) {
|
|
742
|
-
|
|
755
|
+
highlightedNode.__oldStyles = node.style.cssText;
|
|
743
756
|
}
|
|
744
757
|
node.style.animation = "pulsate .5s infinite";
|
|
745
758
|
node.style.outline = "solid red";
|
|
@@ -767,10 +780,11 @@
|
|
|
767
780
|
document.head.appendChild(styleTag);
|
|
768
781
|
}
|
|
769
782
|
function unhighlightNode(node) {
|
|
783
|
+
const highlightedNode = node;
|
|
770
784
|
if (!node.style || !node.hasAttribute("style")) return;
|
|
771
|
-
if (
|
|
772
|
-
node.style.cssText =
|
|
773
|
-
delete
|
|
785
|
+
if (highlightedNode.__oldStyles !== void 0) {
|
|
786
|
+
node.style.cssText = highlightedNode.__oldStyles;
|
|
787
|
+
delete highlightedNode.__oldStyles;
|
|
774
788
|
} else {
|
|
775
789
|
node.removeAttribute("style");
|
|
776
790
|
}
|
|
@@ -883,12 +897,17 @@
|
|
|
883
897
|
/^\s*(use|accept|allow|continue\s+with)?\s*only\s*(strictly)?\s*(necessary|essentials?|required)?\s*(cookies)?\s*$/is,
|
|
884
898
|
// e.g. "do not sell or share my personal information", "do not sell my personal information"
|
|
885
899
|
// often used in CCPA
|
|
886
|
-
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*
|
|
900
|
+
/^\s*do\s+not\s+sell(\s+or\s+share)?\s*my\s*personal\s*info(rmation)?\s*$/is,
|
|
887
901
|
"allow selection",
|
|
888
|
-
"disagree and close"
|
|
902
|
+
"disagree and close",
|
|
889
903
|
// These are impactful, but look error-prone
|
|
904
|
+
// // e.g. "disagree"
|
|
905
|
+
/^(i)?\s*disagree\s*(and\s+close)?$/i,
|
|
890
906
|
// // e.g. "i do not agree"
|
|
891
907
|
// /^\s*(i\s+)?do\s+not\s+agree\s*$/i,
|
|
908
|
+
"no",
|
|
909
|
+
/^no,? thanks$/is,
|
|
910
|
+
/^opt[ -]out$/is
|
|
892
911
|
];
|
|
893
912
|
var REJECT_PATTERNS_DUTCH = [
|
|
894
913
|
"weigeren",
|
|
@@ -1464,6 +1483,64 @@
|
|
|
1464
1483
|
/sostienici/is,
|
|
1465
1484
|
/suscribir/is
|
|
1466
1485
|
];
|
|
1486
|
+
var SETTINGS_PATTERNS = [
|
|
1487
|
+
"settings",
|
|
1488
|
+
"preferences",
|
|
1489
|
+
/customi(s|z)e/is,
|
|
1490
|
+
"show details",
|
|
1491
|
+
"more options",
|
|
1492
|
+
/(manage|configure) (my|your) (preferences|choices|cookies)/is,
|
|
1493
|
+
"manage choices",
|
|
1494
|
+
/(cookie )?preference center/is,
|
|
1495
|
+
"change settings",
|
|
1496
|
+
"configure",
|
|
1497
|
+
"change my preferences",
|
|
1498
|
+
"cookie manager",
|
|
1499
|
+
"cookie preference",
|
|
1500
|
+
"let me choose",
|
|
1501
|
+
"cookieconsent preferences",
|
|
1502
|
+
/privacy choices/is,
|
|
1503
|
+
/(privacy|cookie|custom) settings/is,
|
|
1504
|
+
/cookies? (settings|preferences|setting)/is,
|
|
1505
|
+
/(manage|customize|customise|opt-out|edit).*(cookies|preferences|settings|options)/is,
|
|
1506
|
+
"cookie consent options",
|
|
1507
|
+
"privacy controls",
|
|
1508
|
+
"show purposes",
|
|
1509
|
+
// German
|
|
1510
|
+
"einstellungen"
|
|
1511
|
+
];
|
|
1512
|
+
var ACCEPT_PATTERNS = [
|
|
1513
|
+
/^(accept|allow)( all)?( cookies)?$/is,
|
|
1514
|
+
/i (accept|allow)( all)?/is,
|
|
1515
|
+
"yes",
|
|
1516
|
+
/^(i )?agree$/is,
|
|
1517
|
+
"continue with all",
|
|
1518
|
+
"accept and continue",
|
|
1519
|
+
/accept all above/is,
|
|
1520
|
+
/^(accept|agree) and close/is,
|
|
1521
|
+
"accept continue",
|
|
1522
|
+
"agree proceed",
|
|
1523
|
+
"allow and continue",
|
|
1524
|
+
"close and accept",
|
|
1525
|
+
/accept all$/is,
|
|
1526
|
+
"im ok with that",
|
|
1527
|
+
"accept optional cookies",
|
|
1528
|
+
/^alle (cookies )?akzeptieren$/is
|
|
1529
|
+
];
|
|
1530
|
+
var ACKNOWLEDGE_PATTERNS = [
|
|
1531
|
+
"ok",
|
|
1532
|
+
"close",
|
|
1533
|
+
"continue",
|
|
1534
|
+
"x",
|
|
1535
|
+
/^got it!?$/,
|
|
1536
|
+
"i understand",
|
|
1537
|
+
"dismiss",
|
|
1538
|
+
"okay",
|
|
1539
|
+
"acknowledge",
|
|
1540
|
+
/^close (banner|cookie notification)$/is,
|
|
1541
|
+
/understood$/is,
|
|
1542
|
+
"confirm my choices"
|
|
1543
|
+
];
|
|
1467
1544
|
|
|
1468
1545
|
// lib/heuristics.ts
|
|
1469
1546
|
var BUTTON_LIKE_ELEMENT_SELECTOR = 'button, input[type="button"], input[type="submit"], a, [role="button"], [class*="button"]';
|
|
@@ -1482,48 +1559,61 @@
|
|
|
1482
1559
|
}
|
|
1483
1560
|
return { patterns, snippets: snippets2 };
|
|
1484
1561
|
}
|
|
1485
|
-
function getActionablePopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1562
|
+
function getActionablePopups(mode = PopupHandlingModes.Reject, timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1486
1563
|
const popups = getPotentialPopups(timeout);
|
|
1487
1564
|
const result = popups.reduce((acc, popup) => {
|
|
1488
1565
|
const popupText = popup.text?.trim();
|
|
1489
1566
|
if (popupText) {
|
|
1490
1567
|
const { patterns } = checkHeuristicPatterns(popupText);
|
|
1491
1568
|
if (patterns.length > 0) {
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
otherButtons
|
|
1498
|
-
});
|
|
1499
|
-
}
|
|
1569
|
+
classifyButtons(popup.buttons);
|
|
1570
|
+
popup.regexClassification = classifyPopup(popup.buttons);
|
|
1571
|
+
acc.push({
|
|
1572
|
+
...popup
|
|
1573
|
+
});
|
|
1500
1574
|
}
|
|
1501
1575
|
}
|
|
1502
1576
|
return acc;
|
|
1503
1577
|
}, []);
|
|
1504
|
-
return result
|
|
1578
|
+
return result.filter(
|
|
1579
|
+
(popup) => popup.regexClassification !== void 0 && popup.regexClassification !== PopupHandlingModes.None && popup.regexClassification <= mode
|
|
1580
|
+
).sort((a, b) => (a.regexClassification ?? 0) - (b.regexClassification ?? 0));
|
|
1505
1581
|
}
|
|
1506
1582
|
function classifyButtons(buttons) {
|
|
1507
|
-
const rejectButtons = [];
|
|
1508
|
-
const otherButtons = [];
|
|
1509
1583
|
for (const button of buttons) {
|
|
1510
|
-
|
|
1511
|
-
rejectButtons.push(button);
|
|
1512
|
-
} else {
|
|
1513
|
-
otherButtons.push(button);
|
|
1514
|
-
}
|
|
1584
|
+
button.regexClassification = classifyButtonTextRegex(button.text);
|
|
1515
1585
|
}
|
|
1516
|
-
return {
|
|
1517
|
-
rejectButtons,
|
|
1518
|
-
otherButtons
|
|
1519
|
-
};
|
|
1520
1586
|
}
|
|
1521
|
-
function
|
|
1587
|
+
function classifyPopup(buttons) {
|
|
1588
|
+
const { reject, settings, accept, acknowledge } = buttons.reduce(
|
|
1589
|
+
(acc, button) => {
|
|
1590
|
+
if (button.regexClassification && button.regexClassification !== "other") {
|
|
1591
|
+
acc[button.regexClassification]++;
|
|
1592
|
+
}
|
|
1593
|
+
return acc;
|
|
1594
|
+
},
|
|
1595
|
+
{ reject: 0, settings: 0, accept: 0, acknowledge: 0 }
|
|
1596
|
+
);
|
|
1597
|
+
if (reject > 0) {
|
|
1598
|
+
return PopupHandlingModes.Reject;
|
|
1599
|
+
}
|
|
1600
|
+
if (settings > 0) {
|
|
1601
|
+
return PopupHandlingModes.None;
|
|
1602
|
+
}
|
|
1603
|
+
if (acknowledge > 0) {
|
|
1604
|
+
return PopupHandlingModes.Tier1;
|
|
1605
|
+
}
|
|
1606
|
+
if (accept > 0) {
|
|
1607
|
+
return accept === 1 ? PopupHandlingModes.Tier2 : PopupHandlingModes.None;
|
|
1608
|
+
}
|
|
1609
|
+
return PopupHandlingModes.None;
|
|
1610
|
+
}
|
|
1611
|
+
function testButtonMatches(buttonText, matchPatterns, neverMatchPatterns) {
|
|
1522
1612
|
if (!buttonText) {
|
|
1523
1613
|
return false;
|
|
1524
1614
|
}
|
|
1525
1615
|
const cleanedButtonText = cleanButtonText(buttonText);
|
|
1526
|
-
return !neverMatchPatterns.some((p) => p.test(cleanedButtonText)) &&
|
|
1616
|
+
return !neverMatchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText) && matchPatterns.some((p) => p instanceof RegExp && p.test(cleanedButtonText) || p === cleanedButtonText);
|
|
1527
1617
|
}
|
|
1528
1618
|
function cleanButtonText(buttonText) {
|
|
1529
1619
|
let result = buttonText.toLowerCase();
|
|
@@ -1537,6 +1627,21 @@
|
|
|
1537
1627
|
result = result.trim();
|
|
1538
1628
|
return result;
|
|
1539
1629
|
}
|
|
1630
|
+
function classifyButtonTextRegex(buttonText) {
|
|
1631
|
+
if (testButtonMatches(buttonText, REJECT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1632
|
+
return "reject";
|
|
1633
|
+
}
|
|
1634
|
+
if (testButtonMatches(buttonText, SETTINGS_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1635
|
+
return "settings";
|
|
1636
|
+
}
|
|
1637
|
+
if (testButtonMatches(buttonText, ACCEPT_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1638
|
+
return "accept";
|
|
1639
|
+
}
|
|
1640
|
+
if (testButtonMatches(buttonText, ACKNOWLEDGE_PATTERNS, NEVER_MATCH_PATTERNS)) {
|
|
1641
|
+
return "acknowledge";
|
|
1642
|
+
}
|
|
1643
|
+
return "other";
|
|
1644
|
+
}
|
|
1540
1645
|
function getPotentialPopups(timeout = POPUP_SEARCH_MAX_TIME) {
|
|
1541
1646
|
const isFramed = !isTopFrame();
|
|
1542
1647
|
if (isFramed && window.parent && window.parent !== window.top) {
|
|
@@ -1982,7 +2087,7 @@
|
|
|
1982
2087
|
}
|
|
1983
2088
|
};
|
|
1984
2089
|
var AutoConsentHeuristicCMP = class extends AutoConsentCMPBase {
|
|
1985
|
-
constructor(autoconsentInstance) {
|
|
2090
|
+
constructor(autoconsentInstance, mode = PopupHandlingModes.Reject) {
|
|
1986
2091
|
super(autoconsentInstance);
|
|
1987
2092
|
this.popups = [];
|
|
1988
2093
|
this.name = "HEURISTIC";
|
|
@@ -1991,6 +2096,7 @@
|
|
|
1991
2096
|
frame: false
|
|
1992
2097
|
// do not run in iframes for security reasons
|
|
1993
2098
|
};
|
|
2099
|
+
this.mode = mode;
|
|
1994
2100
|
}
|
|
1995
2101
|
get hasSelfTest() {
|
|
1996
2102
|
return true;
|
|
@@ -2004,25 +2110,33 @@
|
|
|
2004
2110
|
async detectCmp() {
|
|
2005
2111
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2006
2112
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorStart");
|
|
2007
|
-
this.popups = getActionablePopups(this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2113
|
+
this.popups = getActionablePopups(this.mode, this.autoconsent.config.heuristicPopupSearchTimeout);
|
|
2008
2114
|
this.autoconsent.config.performanceLoggingEnabled && performance.mark("heuristicDetectorEnd");
|
|
2009
2115
|
this.autoconsent.config.performanceLoggingEnabled && performance.measure("heuristicDetector", "heuristicDetectorStart", "heuristicDetectorEnd");
|
|
2010
2116
|
if (this.popups.length > 0) {
|
|
2117
|
+
this.name = `HEURISTIC-TIER${this.popups[0].regexClassification}`;
|
|
2011
2118
|
return Promise.resolve(true);
|
|
2012
2119
|
}
|
|
2013
2120
|
return Promise.resolve(false);
|
|
2014
2121
|
}
|
|
2015
2122
|
async detectPopup() {
|
|
2016
2123
|
if (this.popups.length > 0) {
|
|
2017
|
-
if (this.popups.length > 1
|
|
2018
|
-
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple
|
|
2124
|
+
if (this.popups.length > 1) {
|
|
2125
|
+
this.autoconsent.config.logs.errors && console.warn("Heuristic found multiple popups");
|
|
2019
2126
|
}
|
|
2020
2127
|
return true;
|
|
2021
2128
|
}
|
|
2022
2129
|
return false;
|
|
2023
2130
|
}
|
|
2131
|
+
getTargetButton() {
|
|
2132
|
+
const popup = this.popups[0];
|
|
2133
|
+
const level = popup.regexClassification;
|
|
2134
|
+
const buttons = popup.buttons;
|
|
2135
|
+
const targetButtonType = level === PopupHandlingModes.Reject ? "reject" : level === PopupHandlingModes.Tier1 ? "acknowledge" : "accept";
|
|
2136
|
+
return buttons.find((button) => button.regexClassification === targetButtonType);
|
|
2137
|
+
}
|
|
2024
2138
|
optOut() {
|
|
2025
|
-
const button = this.
|
|
2139
|
+
const button = this.getTargetButton();
|
|
2026
2140
|
if (button) {
|
|
2027
2141
|
return this.clickElement(button.element);
|
|
2028
2142
|
}
|
|
@@ -2035,7 +2149,7 @@
|
|
|
2035
2149
|
throw new Error("Not Implemented");
|
|
2036
2150
|
}
|
|
2037
2151
|
async test() {
|
|
2038
|
-
const button = this.
|
|
2152
|
+
const button = this.getTargetButton();
|
|
2039
2153
|
if (button) {
|
|
2040
2154
|
await this.wait(500);
|
|
2041
2155
|
return !isElementVisible(button.element);
|
|
@@ -2716,7 +2830,7 @@
|
|
|
2716
2830
|
async optOut() {
|
|
2717
2831
|
await this.waitForElement(".unic button", 1e3);
|
|
2718
2832
|
document.querySelectorAll(".unic button").forEach((button) => {
|
|
2719
|
-
const text = button.textContent;
|
|
2833
|
+
const text = button.textContent || "";
|
|
2720
2834
|
if (text.includes("Manage Options") || text.includes("Optionen verwalten")) {
|
|
2721
2835
|
button.click();
|
|
2722
2836
|
}
|
|
@@ -2729,7 +2843,7 @@
|
|
|
2729
2843
|
}
|
|
2730
2844
|
});
|
|
2731
2845
|
for (const b of document.querySelectorAll(".unic button")) {
|
|
2732
|
-
const text = b.textContent;
|
|
2846
|
+
const text = b.textContent || "";
|
|
2733
2847
|
for (const pattern of ["Confirm Choices", "Save Choices", "Auswahl speichern"]) {
|
|
2734
2848
|
if (text.includes(pattern)) {
|
|
2735
2849
|
b.click();
|
|
@@ -2786,6 +2900,9 @@
|
|
|
2786
2900
|
item.querySelector(".cmp-accordion-item-title").click();
|
|
2787
2901
|
await waitFor(() => !!item.querySelector(".cmp-accordion-item-content.cmp-active"), 10, 50);
|
|
2788
2902
|
const content = item.querySelector(".cmp-accordion-item-content.cmp-active");
|
|
2903
|
+
if (!content) {
|
|
2904
|
+
return false;
|
|
2905
|
+
}
|
|
2789
2906
|
content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e) => e.click());
|
|
2790
2907
|
content.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e) => e.click());
|
|
2791
2908
|
}
|
|
@@ -3505,7 +3622,7 @@
|
|
|
3505
3622
|
}
|
|
3506
3623
|
}
|
|
3507
3624
|
});
|
|
3508
|
-
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this)] : [];
|
|
3625
|
+
const heuristicRules = isTop && this.config.enableHeuristicAction && this.state.findCmpAttempts % 2 === 0 ? [new AutoConsentHeuristicCMP(this, this.config.heuristicMode)] : [];
|
|
3509
3626
|
const rulesPriorityStages = [
|
|
3510
3627
|
["site-specific", siteSpecificRules],
|
|
3511
3628
|
["generic", genericRules],
|