@duckduckgo/autoconsent 1.0.8 → 2.1.1
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/.eslintrc.cjs +14 -0
- package/.vscode/.idea/.vscode.iml +9 -0
- package/.vscode/.idea/modules.xml +8 -0
- package/.vscode/.idea/workspace.xml +28 -0
- package/.vscode/settings.json +7 -0
- package/Jenkinsfile +68 -39
- package/api.md +104 -0
- package/dist/addon-firefox/background.bundle.js +1 -0
- package/dist/addon-firefox/content.bundle.js +1 -0
- package/dist/addon-firefox/icons/cog.png +0 -0
- package/dist/addon-firefox/icons/cookie-idle.png +0 -0
- package/dist/addon-firefox/icons/cookie.png +0 -0
- package/dist/addon-firefox/icons/party.png +0 -0
- package/dist/addon-firefox/icons/tick.png +0 -0
- package/dist/addon-firefox/icons/verified.png +0 -0
- package/dist/addon-firefox/manifest.json +32 -0
- package/dist/addon-firefox/rules.json +4167 -0
- package/dist/addon-mv3/background.bundle.js +1 -0
- package/dist/addon-mv3/content.bundle.js +1 -0
- package/dist/addon-mv3/icons/cog.png +0 -0
- package/dist/addon-mv3/icons/cookie-idle.png +0 -0
- package/dist/addon-mv3/icons/cookie.png +0 -0
- package/dist/addon-mv3/icons/party.png +0 -0
- package/dist/addon-mv3/icons/tick.png +0 -0
- package/dist/addon-mv3/icons/verified.png +0 -0
- package/dist/addon-mv3/manifest.json +34 -0
- package/dist/addon-mv3/rules.json +4167 -0
- package/dist/autoconsent.cjs.js +1 -1387
- package/dist/autoconsent.esm.js +1 -1379
- package/dist/autoconsent.playwright.js +1 -0
- package/lib/cmps/all.ts +15 -10
- package/lib/cmps/base.ts +95 -90
- package/lib/cmps/consentmanager.ts +31 -19
- package/lib/cmps/consentomatic.ts +89 -0
- package/lib/cmps/cookiebot.ts +58 -55
- package/lib/cmps/evidon.ts +29 -18
- package/lib/cmps/onetrust.ts +32 -20
- package/lib/cmps/sourcepoint-frame.ts +104 -0
- package/lib/cmps/sourcepoint-top.ts +47 -0
- package/lib/cmps/trustarc-frame.ts +115 -0
- package/lib/cmps/trustarc-top.ts +97 -0
- package/lib/consentomatic/index.ts +233 -70
- package/lib/{web/consentomatic → consentomatic}/tools.ts +0 -0
- package/lib/eval-handler.ts +58 -0
- package/lib/index.ts +0 -2
- package/lib/messages.ts +100 -0
- package/lib/rule-executors.ts +108 -0
- package/lib/rules.ts +82 -0
- package/lib/types.ts +35 -0
- package/lib/utils.ts +64 -0
- package/lib/web.ts +288 -74
- package/package.json +20 -16
- package/playwright/content.ts +21 -0
- package/playwright/runner.ts +162 -0
- package/playwright.config.ts +7 -0
- package/readme.md +61 -47
- package/rollup.config.js +38 -16
- package/rules/autoconsent/ausopen.json +2 -1
- package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
- package/rules/autoconsent/bundesregierung-de.json +5 -1
- package/rules/autoconsent/cc-banner.json +0 -1
- package/rules/autoconsent/cookie-law-info.json +1 -1
- package/rules/autoconsent/cookie-notice.json +1 -2
- package/rules/autoconsent/cookieconsent.json +5 -6
- package/rules/autoconsent/destatis-de.json +2 -2
- package/rules/autoconsent/dunelm.json +1 -1
- package/rules/autoconsent/etsy.json +4 -3
- package/rules/autoconsent/eu-cookie-compliance.json +0 -1
- package/rules/autoconsent/hl-co-uk.json +8 -9
- package/rules/autoconsent/johnlewis.json +5 -2
- package/rules/autoconsent/marksandspencer.json +2 -1
- package/rules/autoconsent/mediamarkt-de.json +1 -1
- package/rules/autoconsent/microsoft.json +1 -1
- package/rules/autoconsent/notice-cookie.json +0 -1
- package/rules/autoconsent/osano.json +4 -2
- package/rules/autoconsent/snigel.json +2 -1
- package/rules/autoconsent/tealium.json +4 -5
- package/rules/autoconsent/thefreedictionary.json +1 -1
- package/rules/rules.json +79 -45
- package/tests/192.spec.ts +1 -1
- package/tests/arzt-auskunft.spec.ts +1 -1
- package/tests/asus.spec.ts +1 -1
- package/tests/ausopen.spec.ts +1 -1
- package/tests/aws.amazon.spec.ts +1 -1
- package/tests/baden-wuerttemberg.spec.ts +1 -1
- package/tests/borlabs.spec.ts +1 -1
- package/tests/bundesregierung.spec.ts +5 -2
- package/tests/ccbanner.spec.ts +1 -1
- package/tests/consentmanager.spec.ts +3 -3
- package/tests/cookiebot.spec.ts +8 -2
- package/tests/cookieconsent.spec.ts +1 -1
- package/tests/cookielawinfo.spec.ts +1 -1
- package/tests/cookienotice.spec.ts +1 -1
- package/tests/corona-in-zahlen.spec.ts +1 -1
- package/tests/deepl.spec.ts +1 -1
- package/tests/destatis.spec.ts +1 -1
- package/tests/didomi.spec.ts +7 -3
- package/tests/drupal.spec.ts +8 -0
- package/tests/dunelm.spec.ts +1 -1
- package/tests/etsy.spec.ts +1 -1
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests/evidon.spec.ts +7 -2
- package/tests/fundingchoices.spec.ts +2 -1
- package/tests/gov-uk.spec.ts +1 -1
- package/tests/hl-co-uk.spec.ts +1 -1
- package/tests/hubspot.spec.ts +1 -1
- package/tests/ionos.spec.ts +1 -1
- package/tests/johnlewis.spec.ts +2 -2
- package/tests/klaro.spec.ts +1 -1
- package/tests/marksandspencer.spec.ts +1 -1
- package/tests/mediamarkt.spec.ts +1 -1
- package/tests/metoffice-gov-uk.spec.ts +1 -1
- package/tests/microsoft.spec.ts +1 -1
- package/tests/moneysavingexpert.spec.ts +1 -1
- package/tests/motor-talk.spec.ts +1 -1
- package/tests/national-lottery.spec.ts +1 -1
- package/tests/netflix.spec.ts +1 -1
- package/tests/nhs.spec.ts +1 -1
- package/tests/notice-cookie.spec.ts +1 -1
- package/tests/obi.spec.ts +1 -1
- package/tests/oil.spec.ts +2 -2
- package/tests/onetrust.spec.ts +27 -2
- package/tests/osano.spec.ts +1 -1
- package/tests/otto.spec.ts +1 -1
- package/tests/paypal.spec.ts +1 -1
- package/tests/quantcast.spec.ts +5 -2
- package/tests/snigel.spec.ts +1 -1
- package/tests/sourcepoint.spec.ts +8 -8
- package/tests/springer.spec.ts +2 -2
- package/tests/steampowered.spec.ts +1 -1
- package/tests/tealium.spec.ts +1 -1
- package/tests/testcmp.spec.ts +1 -1
- package/tests/thalia.spec.ts +1 -1
- package/tests/thefreedictionary.spec.ts +1 -1
- package/tests/trustarc.spec.ts +26 -4
- package/tests/usercentrics-1.spec.ts +1 -1
- package/tests/uswitch.spec.ts +1 -1
- package/tests/vodafone.spec.ts +1 -1
- package/tests/waitrose.spec.ts +1 -1
- package/tests/wetransfer.spec.ts +1 -1
- package/tests/wordpressgdpr.spec.ts +2 -2
- package/tests/xing.spec.ts +1 -1
- package/tsconfig.json +2 -2
- package/update_version.js +10 -6
- package/.eslintrc +0 -12
- package/cosmetics/rules.json +0 -110
- package/dist/autoconsent.puppet.js +0 -1078
- package/lib/cmps/all.js +0 -19
- package/lib/cmps/base.js +0 -174
- package/lib/cmps/consentmanager.js +0 -31
- package/lib/cmps/cookiebot.js +0 -77
- package/lib/cmps/evidon.js +0 -26
- package/lib/cmps/onetrust.js +0 -34
- package/lib/cmps/sourcepoint.js +0 -82
- package/lib/cmps/sourcepoint.ts +0 -95
- package/lib/cmps/trustarc.js +0 -106
- package/lib/cmps/trustarc.ts +0 -147
- package/lib/config.js +0 -1
- package/lib/consentomatic/index.js +0 -52
- package/lib/detector.js +0 -33
- package/lib/detector.ts +0 -34
- package/lib/hider.js +0 -13
- package/lib/hider.ts +0 -16
- package/lib/index.js +0 -4
- package/lib/messages.d.ts +0 -61
- package/lib/node.js +0 -35
- package/lib/node.ts +0 -43
- package/lib/puppet/tab.js +0 -121
- package/lib/puppet/tab.ts +0 -146
- package/lib/rules.d.ts +0 -80
- package/lib/tabwrapper.js +0 -67
- package/lib/tabwrapper.ts +0 -74
- package/lib/types.d.ts +0 -61
- package/lib/web/consentomatic/index.ts +0 -249
- package/lib/web/content-utils.js +0 -29
- package/lib/web/content-utils.ts +0 -31
- package/lib/web/content.js +0 -89
- package/lib/web/content.ts +0 -80
- package/lib/web/tab.js +0 -112
- package/lib/web/tab.ts +0 -178
- package/lib/web.js +0 -95
- package/tests/runner.ts +0 -61
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { click, elementExists, elementVisible } from "../rule-executors";
|
|
2
|
+
import { RunContext } from "../rules";
|
|
3
|
+
import { getStyleElement, hideElements } from "../utils";
|
|
4
|
+
import AutoConsentCMPBase from "./base";
|
|
5
|
+
|
|
6
|
+
const cookieSettingsButton = "#truste-show-consent";
|
|
7
|
+
const shortcutOptOut = '#truste-consent-required';
|
|
8
|
+
const shortcutOptIn = '#truste-consent-button';
|
|
9
|
+
const popupContent = '#truste-consent-content';
|
|
10
|
+
const bannerOverlay = '#trustarc-banner-overlay';
|
|
11
|
+
const bannerContainer = '#truste-consent-track';
|
|
12
|
+
|
|
13
|
+
export default class TrustArcTop extends AutoConsentCMPBase {
|
|
14
|
+
|
|
15
|
+
prehideSelectors = [
|
|
16
|
+
".trustarc-banner-container",
|
|
17
|
+
`.truste_popframe,.truste_overlay,.truste_box_overlay,${bannerContainer}`,
|
|
18
|
+
]
|
|
19
|
+
runContext: RunContext = {
|
|
20
|
+
main: true,
|
|
21
|
+
frame: false,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_shortcutButton: HTMLElement;
|
|
25
|
+
_optInDone: boolean;
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super("TrustArc-top");
|
|
29
|
+
this._shortcutButton = null; // indicates if the "reject all" button is detected
|
|
30
|
+
this._optInDone = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get hasSelfTest(): boolean {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get isIntermediate(): boolean {
|
|
38
|
+
if (this._optInDone) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return !this._shortcutButton;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async detectCmp() {
|
|
45
|
+
const result = elementExists(`${cookieSettingsButton},${bannerContainer}`);
|
|
46
|
+
if (result) {
|
|
47
|
+
// additionally detect the opt-out button
|
|
48
|
+
this._shortcutButton = document.querySelector(shortcutOptOut);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async detectPopup() {
|
|
54
|
+
// not every element should exist, but if it does, it's a popup
|
|
55
|
+
return elementVisible(`${popupContent},${bannerOverlay},${bannerContainer}`, 'all');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
openFrame() {
|
|
59
|
+
click(cookieSettingsButton);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async optOut() {
|
|
63
|
+
if (this._shortcutButton) {
|
|
64
|
+
this._shortcutButton.click();
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// hide elements permanently, so user doesn't see the popup
|
|
69
|
+
hideElements(
|
|
70
|
+
getStyleElement(),
|
|
71
|
+
[".truste_popframe", ".truste_overlay", ".truste_box_overlay", bannerContainer],
|
|
72
|
+
);
|
|
73
|
+
click(cookieSettingsButton);
|
|
74
|
+
|
|
75
|
+
// schedule cleanup
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
getStyleElement().remove();
|
|
78
|
+
}, 10000);
|
|
79
|
+
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async optIn() {
|
|
84
|
+
this._optInDone = true; // just a hack to force autoconsentDone
|
|
85
|
+
return click(shortcutOptIn);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async openCmp() {
|
|
89
|
+
// await tab.eval("truste.eu.clickListener()");
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async test() {
|
|
94
|
+
// TODO: find out how to test TrustArc
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -1,86 +1,249 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
name: string;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type ConsentOMaticConfig = {
|
|
13
|
-
detectors: DetectorConfig[];
|
|
14
|
-
methods: MethodConfig[];
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export class ConsentOMaticCMP implements AutoCMP {
|
|
18
|
-
methods = new Map<string, {}>();
|
|
19
|
-
hasSelfTest: boolean;
|
|
20
|
-
|
|
21
|
-
constructor(public name: string, public config: ConsentOMaticConfig) {
|
|
22
|
-
config.methods.forEach(methodConfig => {
|
|
23
|
-
if (methodConfig.action) {
|
|
24
|
-
this.methods.set(methodConfig.name, methodConfig.action);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
this.hasSelfTest = this.methods.has("TEST_CONSENT");
|
|
1
|
+
import Tools from "./tools";
|
|
2
|
+
|
|
3
|
+
export function matches(config: any) {
|
|
4
|
+
const result = Tools.find(config);
|
|
5
|
+
if (config.type === "css") {
|
|
6
|
+
return !!result.target;
|
|
7
|
+
} else if (config.type === "checkbox") {
|
|
8
|
+
return !!result.target && result.target.checked;
|
|
28
9
|
}
|
|
10
|
+
}
|
|
29
11
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
12
|
+
export async function executeAction(config: any, param?: any): Promise<boolean | void> {
|
|
13
|
+
switch (config.type) {
|
|
14
|
+
case "click":
|
|
15
|
+
return clickAction(config);
|
|
16
|
+
case "list":
|
|
17
|
+
return listAction(config, param);
|
|
18
|
+
case "consent":
|
|
19
|
+
return consentAction(config, param);
|
|
20
|
+
case "ifcss":
|
|
21
|
+
return ifCssAction(config, param);
|
|
22
|
+
case "waitcss":
|
|
23
|
+
return waitCssAction(config);
|
|
24
|
+
case "foreach":
|
|
25
|
+
return forEachAction(config, param);
|
|
26
|
+
case "hide":
|
|
27
|
+
return hideAction(config);
|
|
28
|
+
case "slide":
|
|
29
|
+
return slideAction(config);
|
|
30
|
+
case "close":
|
|
31
|
+
return closeAction(config);
|
|
32
|
+
case "wait":
|
|
33
|
+
return waitAction(config);
|
|
34
|
+
case "eval":
|
|
35
|
+
return evalAction(config);
|
|
36
|
+
default:
|
|
37
|
+
throw "Unknown action type: " + config.type;
|
|
38
38
|
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const STEP_TIMEOUT = 0;
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
function waitTimeout(timeout: number): Promise<void> {
|
|
44
|
+
return new Promise(resolve => {
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
resolve();
|
|
47
|
+
}, timeout);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function clickAction(config: any) {
|
|
52
|
+
const result = Tools.find(config);
|
|
53
|
+
if (result.target != null) {
|
|
54
|
+
result.target.click();
|
|
48
55
|
}
|
|
56
|
+
return waitTimeout(STEP_TIMEOUT);
|
|
57
|
+
}
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
59
|
+
async function listAction(config: any, param: any) {
|
|
60
|
+
for (let action of config.actions) {
|
|
61
|
+
await executeAction(action, param);
|
|
55
62
|
}
|
|
63
|
+
}
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
async function consentAction(config: any, consentTypes: any) {
|
|
66
|
+
for (const consentConfig of config.consents) {
|
|
67
|
+
const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
|
|
68
|
+
if (consentConfig.matcher && consentConfig.toggleAction) {
|
|
69
|
+
const isEnabled = matches(consentConfig.matcher);
|
|
70
|
+
if (isEnabled !== shouldEnable) {
|
|
71
|
+
await executeAction(consentConfig.toggleAction);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
if (shouldEnable) {
|
|
75
|
+
await executeAction(consentConfig.trueAction);
|
|
76
|
+
} else {
|
|
77
|
+
await executeAction(consentConfig.falseAction);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
64
80
|
}
|
|
81
|
+
}
|
|
65
82
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
async function ifCssAction(config: any, param: any) {
|
|
84
|
+
const result = Tools.find(config);
|
|
85
|
+
if (!result.target) {
|
|
86
|
+
if (config.trueAction) {
|
|
87
|
+
await executeAction(config.trueAction, param);
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
if (config.falseAction) {
|
|
91
|
+
await executeAction(config.falseAction, param);
|
|
92
|
+
}
|
|
73
93
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function waitCssAction(config: any) {
|
|
97
|
+
await new Promise<void>(resolve => {
|
|
98
|
+
let numRetries = config.retries || 10;
|
|
99
|
+
const waitTime = config.waitTime || 250;
|
|
100
|
+
const checkCss = () => {
|
|
101
|
+
const result = Tools.find(config);
|
|
102
|
+
if (
|
|
103
|
+
(config.negated && result.target) ||
|
|
104
|
+
(!config.negated && !result.target)
|
|
105
|
+
) {
|
|
106
|
+
if (numRetries > 0) {
|
|
107
|
+
numRetries -= 1;
|
|
108
|
+
setTimeout(checkCss, waitTime);
|
|
109
|
+
} else {
|
|
110
|
+
resolve();
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
resolve();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
checkCss();
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function forEachAction(config: any, param: any) {
|
|
121
|
+
const results = Tools.find(config, true);
|
|
122
|
+
const oldBase = Tools.base;
|
|
123
|
+
for (const result of results) {
|
|
124
|
+
if (result.target) {
|
|
125
|
+
Tools.setBase(result.target);
|
|
126
|
+
await executeAction(config.action, param);
|
|
127
|
+
}
|
|
78
128
|
}
|
|
129
|
+
Tools.setBase(oldBase);
|
|
130
|
+
}
|
|
79
131
|
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
async function hideAction(config: any) {
|
|
133
|
+
const result = Tools.find(config);
|
|
134
|
+
if (result.target) {
|
|
135
|
+
result.target.classList.add("Autoconsent-Hidden");
|
|
136
|
+
// result.target.setAttribute("style", "display: none;");
|
|
82
137
|
}
|
|
83
|
-
|
|
84
|
-
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function slideAction(config: any) {
|
|
141
|
+
const result = Tools.find(config);
|
|
142
|
+
const dragResult = Tools.find(config.dragTarget);
|
|
143
|
+
if (result.target) {
|
|
144
|
+
let targetBounds = result.target.getBoundingClientRect();
|
|
145
|
+
let dragTargetBounds = dragResult.target.getBoundingClientRect();
|
|
146
|
+
|
|
147
|
+
let yDiff = dragTargetBounds.top - targetBounds.top;
|
|
148
|
+
let xDiff = dragTargetBounds.left - targetBounds.left;
|
|
149
|
+
|
|
150
|
+
if (this.config.axis.toLowerCase() === "y") {
|
|
151
|
+
xDiff = 0;
|
|
152
|
+
}
|
|
153
|
+
if (this.config.axis.toLowerCase() === "x") {
|
|
154
|
+
yDiff = 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
|
|
158
|
+
let screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
|
|
159
|
+
let clientX = targetBounds.left + targetBounds.width / 2.0;
|
|
160
|
+
let clientY = targetBounds.top + targetBounds.height / 2.0;
|
|
161
|
+
|
|
162
|
+
let mouseDown = document.createEvent("MouseEvents");
|
|
163
|
+
mouseDown.initMouseEvent(
|
|
164
|
+
"mousedown",
|
|
165
|
+
true,
|
|
166
|
+
true,
|
|
167
|
+
window,
|
|
168
|
+
0,
|
|
169
|
+
screenX,
|
|
170
|
+
screenY,
|
|
171
|
+
clientX,
|
|
172
|
+
clientY,
|
|
173
|
+
false,
|
|
174
|
+
false,
|
|
175
|
+
false,
|
|
176
|
+
false,
|
|
177
|
+
0,
|
|
178
|
+
result.target
|
|
179
|
+
);
|
|
180
|
+
let mouseMove = document.createEvent("MouseEvents");
|
|
181
|
+
mouseMove.initMouseEvent(
|
|
182
|
+
"mousemove",
|
|
183
|
+
true,
|
|
184
|
+
true,
|
|
185
|
+
window,
|
|
186
|
+
0,
|
|
187
|
+
screenX + xDiff,
|
|
188
|
+
screenY + yDiff,
|
|
189
|
+
clientX + xDiff,
|
|
190
|
+
clientY + yDiff,
|
|
191
|
+
false,
|
|
192
|
+
false,
|
|
193
|
+
false,
|
|
194
|
+
false,
|
|
195
|
+
0,
|
|
196
|
+
result.target
|
|
197
|
+
);
|
|
198
|
+
let mouseUp = document.createEvent("MouseEvents");
|
|
199
|
+
mouseUp.initMouseEvent(
|
|
200
|
+
"mouseup",
|
|
201
|
+
true,
|
|
202
|
+
true,
|
|
203
|
+
window,
|
|
204
|
+
0,
|
|
205
|
+
screenX + xDiff,
|
|
206
|
+
screenY + yDiff,
|
|
207
|
+
clientX + xDiff,
|
|
208
|
+
clientY + yDiff,
|
|
209
|
+
false,
|
|
210
|
+
false,
|
|
211
|
+
false,
|
|
212
|
+
false,
|
|
213
|
+
0,
|
|
214
|
+
result.target
|
|
215
|
+
);
|
|
216
|
+
result.target.dispatchEvent(mouseDown);
|
|
217
|
+
await this.waitTimeout(10);
|
|
218
|
+
result.target.dispatchEvent(mouseMove);
|
|
219
|
+
await this.waitTimeout(10);
|
|
220
|
+
result.target.dispatchEvent(mouseUp);
|
|
85
221
|
}
|
|
86
222
|
}
|
|
223
|
+
|
|
224
|
+
async function waitAction(config: any) {
|
|
225
|
+
await waitTimeout(config.waitTime);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function closeAction(config: any) {
|
|
229
|
+
window.close();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function evalAction(config: any): Promise<boolean> {
|
|
233
|
+
console.log("eval!", config.code);
|
|
234
|
+
return new Promise(resolve => {
|
|
235
|
+
try {
|
|
236
|
+
if (config.async) {
|
|
237
|
+
window.eval(config.code);
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
resolve(window.eval("window.__consentCheckResult"));
|
|
240
|
+
}, config.timeout || 250);
|
|
241
|
+
} else {
|
|
242
|
+
resolve(window.eval(config.code));
|
|
243
|
+
}
|
|
244
|
+
} catch (e) {
|
|
245
|
+
console.warn("eval error", e, config.code);
|
|
246
|
+
resolve(false);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ContentScriptMessage } from "./messages";
|
|
2
|
+
|
|
3
|
+
class Deferred<T> {
|
|
4
|
+
id: string;
|
|
5
|
+
promise: Promise<T>;
|
|
6
|
+
resolve: (value?: T) => void;
|
|
7
|
+
reject: (reason?: any) => void;
|
|
8
|
+
timer: number;
|
|
9
|
+
|
|
10
|
+
constructor(id: string, timeout = 1000) {
|
|
11
|
+
this.id = id;
|
|
12
|
+
this.promise = new Promise((resolve, reject) => {
|
|
13
|
+
this.resolve = resolve;
|
|
14
|
+
this.reject = reject;
|
|
15
|
+
});
|
|
16
|
+
this.timer = window.setTimeout(() => {
|
|
17
|
+
this.reject(new Error("timeout"));
|
|
18
|
+
}, timeout);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type EvalState = {
|
|
23
|
+
pending: Map<string, Deferred<boolean>>;
|
|
24
|
+
sendContentMessage: (message: ContentScriptMessage) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const evalState: EvalState = {
|
|
28
|
+
pending: new Map(),
|
|
29
|
+
sendContentMessage: null,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function requestEval(code: string): Promise<boolean> {
|
|
33
|
+
let id;
|
|
34
|
+
if (crypto && typeof crypto.randomUUID !== 'undefined') {
|
|
35
|
+
id = crypto.randomUUID();
|
|
36
|
+
} else {
|
|
37
|
+
id = Math.random().toString();
|
|
38
|
+
}
|
|
39
|
+
evalState.sendContentMessage({
|
|
40
|
+
type: 'eval',
|
|
41
|
+
id,
|
|
42
|
+
code,
|
|
43
|
+
});
|
|
44
|
+
const deferred = new Deferred<boolean>(id);
|
|
45
|
+
evalState.pending.set(deferred.id, deferred);
|
|
46
|
+
return deferred.promise;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function resolveEval(id: string, value: boolean) {
|
|
50
|
+
const deferred = evalState.pending.get(id);
|
|
51
|
+
if (deferred) {
|
|
52
|
+
evalState.pending.delete(id);
|
|
53
|
+
deferred.timer && window.clearTimeout(deferred.timer);
|
|
54
|
+
deferred.resolve(value);
|
|
55
|
+
} else {
|
|
56
|
+
console.warn('no eval #', id);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/lib/index.ts
CHANGED
package/lib/messages.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Config, RuleBundle } from "./types";
|
|
2
|
+
|
|
3
|
+
export type BackgroundMessage =
|
|
4
|
+
InitResponseMessage
|
|
5
|
+
| EvalResponseMessage
|
|
6
|
+
| OptOutMessage
|
|
7
|
+
| OptInMessage
|
|
8
|
+
| SelfTestMessage;
|
|
9
|
+
|
|
10
|
+
export type ContentScriptMessage =
|
|
11
|
+
InitMessage
|
|
12
|
+
| EvalMessage
|
|
13
|
+
| DetectedMessage
|
|
14
|
+
| FoundMessage
|
|
15
|
+
| OptOutResultMessage
|
|
16
|
+
| OptInResultMessage
|
|
17
|
+
| SelfTestResultMessage
|
|
18
|
+
| DoneMessage
|
|
19
|
+
| ErrorMessage;
|
|
20
|
+
|
|
21
|
+
export type InitMessage = {
|
|
22
|
+
type: "init";
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type EvalMessage = {
|
|
27
|
+
type: "eval";
|
|
28
|
+
id: string;
|
|
29
|
+
code: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type DetectedMessage = {
|
|
33
|
+
type: "cmpDetected";
|
|
34
|
+
cmp: string;
|
|
35
|
+
url: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type FoundMessage = {
|
|
39
|
+
type: "popupFound";
|
|
40
|
+
cmp: string;
|
|
41
|
+
url: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type OptOutResultMessage = {
|
|
45
|
+
type: "optOutResult";
|
|
46
|
+
cmp: string;
|
|
47
|
+
result: boolean;
|
|
48
|
+
scheduleSelfTest: boolean;
|
|
49
|
+
url: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type OptInResultMessage = {
|
|
53
|
+
type: "optInResult";
|
|
54
|
+
cmp: string;
|
|
55
|
+
result: boolean;
|
|
56
|
+
scheduleSelfTest: boolean;
|
|
57
|
+
url: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type SelfTestResultMessage = {
|
|
61
|
+
type: "selfTestResult";
|
|
62
|
+
cmp: string;
|
|
63
|
+
result: boolean;
|
|
64
|
+
url: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type DoneMessage = {
|
|
68
|
+
type: "autoconsentDone";
|
|
69
|
+
cmp: string;
|
|
70
|
+
url: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type ErrorMessage = {
|
|
74
|
+
type: "autoconsentError";
|
|
75
|
+
details: any;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type InitResponseMessage = {
|
|
79
|
+
type: "initResp";
|
|
80
|
+
rules: RuleBundle;
|
|
81
|
+
config: Config;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type EvalResponseMessage = {
|
|
85
|
+
type: "evalResp";
|
|
86
|
+
id: string;
|
|
87
|
+
result: any;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type OptOutMessage = {
|
|
91
|
+
type: "optOut";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type OptInMessage = {
|
|
95
|
+
type: "optIn";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type SelfTestMessage = {
|
|
99
|
+
type: "selfTest";
|
|
100
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { enableLogs } from "./config";
|
|
2
|
+
import { requestEval } from "./eval-handler";
|
|
3
|
+
import { HideMethod, VisibilityCheck } from "./rules";
|
|
4
|
+
import { getStyleElement, hideElements, isElementVisible, waitFor } from "./utils";
|
|
5
|
+
|
|
6
|
+
export function doEval(expr: string): Promise<boolean> {
|
|
7
|
+
return requestEval(expr).catch((e) => {
|
|
8
|
+
enableLogs && console.error('error evaluating rule', expr, e);
|
|
9
|
+
return false;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function click(selector: string, all = false): boolean {
|
|
14
|
+
const elem = document.querySelectorAll<HTMLElement>(selector);
|
|
15
|
+
enableLogs && console.log("[click]", selector, all, elem);
|
|
16
|
+
if (elem.length > 0) {
|
|
17
|
+
if (all) {
|
|
18
|
+
elem.forEach((e) => e.click());
|
|
19
|
+
} else {
|
|
20
|
+
elem[0].click();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return elem.length > 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function elementExists(selector: string): boolean {
|
|
27
|
+
const exists = document.querySelector(selector) !== null;
|
|
28
|
+
// enableLogs && console.log("[exists?]", selector, exists);
|
|
29
|
+
return exists;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function elementVisible(selector: string, check: VisibilityCheck): boolean {
|
|
33
|
+
const elem = document.querySelectorAll<HTMLElement>(selector);
|
|
34
|
+
const results = new Array(elem.length);
|
|
35
|
+
elem.forEach((e, i) => {
|
|
36
|
+
// check for display: none
|
|
37
|
+
results[i] = isElementVisible(e);
|
|
38
|
+
});
|
|
39
|
+
// enableLogs && console.log("[visible?]", selector, check, elem, results);
|
|
40
|
+
if (results.length === 0) {
|
|
41
|
+
return false;
|
|
42
|
+
} else if (check === "any") {
|
|
43
|
+
return results.some(r => r);
|
|
44
|
+
} else if (check === "none") {
|
|
45
|
+
return results.every(r => !r);
|
|
46
|
+
}
|
|
47
|
+
// all
|
|
48
|
+
return results.every(r => r);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function waitForElement(selector: string, timeout = 10000): Promise<boolean> {
|
|
52
|
+
const interval = 200;
|
|
53
|
+
const times = Math.ceil((timeout) / interval);
|
|
54
|
+
// enableLogs && console.log("[waitFor]", ruleStep.waitFor);
|
|
55
|
+
return waitFor(
|
|
56
|
+
() => document.querySelector(selector) !== null,
|
|
57
|
+
times,
|
|
58
|
+
interval
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function waitForVisible(selector: string, timeout = 10000, check: VisibilityCheck = 'any'): Promise<boolean> {
|
|
63
|
+
const interval = 200;
|
|
64
|
+
const times = Math.ceil((timeout) / interval);
|
|
65
|
+
// enableLogs && console.log("[waitForVisible]", ruleStep.waitFor);
|
|
66
|
+
return waitFor(
|
|
67
|
+
() => elementVisible(selector, check),
|
|
68
|
+
times,
|
|
69
|
+
interval
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function waitForThenClick(selector: string, timeout = 10000, all = false): Promise<boolean> {
|
|
74
|
+
// enableLogs && console.log("[waitForThenClick]", ruleStep.waitForThenClick);
|
|
75
|
+
await waitForElement(selector, timeout);
|
|
76
|
+
return click(selector, all);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function wait(ms: number): Promise<true> {
|
|
80
|
+
// enableLogs && console.log(`waiting for ${ruleStep.wait}ms`);
|
|
81
|
+
return new Promise(resolve => {
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
// enableLogs && console.log(`done waiting`);
|
|
84
|
+
resolve(true);
|
|
85
|
+
}, ms);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function hide(selectors: string[], method: HideMethod): boolean {
|
|
90
|
+
// enableLogs && console.log("[hide]", ruleStep.hide, ruleStep.method);
|
|
91
|
+
const styleEl = getStyleElement();
|
|
92
|
+
return hideElements(styleEl, selectors, method);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function prehide(selectors: string[]): boolean {
|
|
96
|
+
const styleEl = getStyleElement('autoconsent-prehide');
|
|
97
|
+
enableLogs && console.log("[prehide]", styleEl, location.href);
|
|
98
|
+
return hideElements(styleEl, selectors, "opacity");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function undoPrehide(): boolean {
|
|
102
|
+
const existingElement = getStyleElement('autoconsent-prehide');
|
|
103
|
+
enableLogs && console.log("[undoprehide]", existingElement, location.href);
|
|
104
|
+
if (existingElement) {
|
|
105
|
+
existingElement.remove();
|
|
106
|
+
}
|
|
107
|
+
return !!existingElement;
|
|
108
|
+
}
|