@duckduckgo/autoconsent 1.0.6 → 2.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/.eslintrc.cjs +14 -0
- package/.vscode/settings.json +7 -0
- package/Jenkinsfile +68 -39
- package/api.md +104 -0
- package/dist/autoconsent.cjs.js +1 -1371
- package/dist/autoconsent.esm.js +1 -1363
- package/dist/autoconsent.playwright.js +1 -0
- package/dist/autoconsent.standalone.js +1 -0
- package/lib/cmps/all.ts +15 -10
- package/lib/cmps/base.ts +91 -91
- package/lib/cmps/consentmanager.ts +31 -19
- package/lib/cmps/consentomatic.ts +89 -0
- package/lib/cmps/cookiebot.ts +62 -53
- package/lib/cmps/evidon.ts +29 -18
- package/lib/cmps/onetrust.ts +37 -19
- package/lib/cmps/sourcepoint-frame.ts +102 -0
- package/lib/cmps/sourcepoint-top.ts +47 -0
- package/lib/cmps/trustarc-frame.ts +115 -0
- package/lib/cmps/trustarc-top.ts +91 -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 +283 -74
- package/package.json +17 -14
- package/playwright/content.ts +27 -0
- package/playwright/runner.ts +131 -0
- package/playwright/standalone.ts +36 -0
- package/playwright.config.ts +7 -0
- package/readme.md +57 -47
- package/rollup.config.js +23 -15
- package/rules/autoconsent/192.json +17 -0
- package/rules/autoconsent/ausopen.json +7 -0
- package/rules/autoconsent/aws-amazon.json +1 -1
- package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
- package/rules/autoconsent/bing.json +14 -0
- package/rules/autoconsent/bundesregierung-de.json +6 -2
- package/rules/autoconsent/cc-banner.json +0 -1
- package/rules/autoconsent/cookie-notice.json +0 -1
- package/rules/autoconsent/cookieconsent.json +5 -6
- package/rules/autoconsent/destatis-de.json +0 -1
- package/rules/autoconsent/dunelm.json +18 -0
- package/rules/autoconsent/etsy.json +3 -2
- package/rules/autoconsent/eu-cookie-compliance.json +0 -1
- package/rules/autoconsent/gov-uk.json +10 -0
- package/rules/autoconsent/hl-co-uk.json +8 -9
- package/rules/autoconsent/johnlewis.json +5 -2
- package/rules/autoconsent/marksandspencer.json +7 -0
- package/rules/autoconsent/notice-cookie.json +0 -1
- package/rules/autoconsent/osano.json +0 -1
- package/rules/autoconsent/{paypal-de.json → paypal.json} +6 -2
- package/rules/autoconsent/tealium.json +4 -5
- package/rules/autoconsent/uswitch.json +8 -0
- package/rules/autoconsent/waitrose.json +28 -0
- package/rules/autoconsent/wetransfer.json +7 -0
- package/rules/rules.json +314 -39
- package/tests/192.spec.ts +7 -0
- package/tests/arzt-auskunft.spec.ts +1 -1
- package/tests/asus.spec.ts +1 -1
- package/tests/ausopen.spec.ts +7 -0
- 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 -1
- 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 +6 -2
- package/tests/drupal.spec.ts +8 -0
- package/tests/dunelm.spec.ts +7 -0
- package/tests/etsy.spec.ts +1 -1
- package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
- package/tests/evidon.spec.ts +1 -1
- package/tests/fundingchoices.spec.ts +2 -1
- package/tests/gov-uk.spec.ts +9 -0
- 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 +7 -0
- 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 +1 -1
- package/tests/onetrust.spec.ts +10 -1
- package/tests/osano.spec.ts +1 -1
- package/tests/otto.spec.ts +1 -1
- package/tests/paypal.spec.ts +8 -6
- package/tests/quantcast.spec.ts +4 -1
- package/tests/snigel.spec.ts +1 -1
- package/tests/sourcepoint.spec.ts +8 -8
- package/tests/springer.spec.ts +1 -1
- 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 +25 -3
- package/tests/usercentrics-1.spec.ts +1 -1
- package/tests/uswitch.spec.ts +7 -0
- package/tests/vodafone.spec.ts +1 -1
- package/tests/waitrose.spec.ts +7 -0
- package/tests/wetransfer.spec.ts +7 -0
- package/tests/wordpressgdpr.spec.ts +1 -1
- package/tests/xing.spec.ts +1 -1
- package/tsconfig.json +2 -2
- package/.eslintrc +0 -12
- package/cosmetics/rules.json +0 -110
- package/dist/autoconsent.puppet.js +0 -1072
- 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 -73
- package/lib/cmps/evidon.js +0 -26
- package/lib/cmps/onetrust.js +0 -32
- 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.js +0 -188
- package/lib/web/consentomatic/index.ts +0 -249
- package/lib/web/consentomatic/tools.js +0 -177
- package/lib/web/content-utils.js +0 -29
- package/lib/web/content-utils.ts +0 -31
- package/lib/web/content.js +0 -79
- package/lib/web/content.ts +0 -71
- 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
package/lib/puppet/tab.ts
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { waitFor } from '../cmps/base';
|
|
2
|
-
import { TabActor } from '../types';
|
|
3
|
-
import Tools from '../web/consentomatic/tools';
|
|
4
|
-
import { matches } from '../web/consentomatic/index';
|
|
5
|
-
import { HideMethod } from '../messages';
|
|
6
|
-
import { hideElementsUtil, getStyleElementUtil } from '../web/content-utils';
|
|
7
|
-
|
|
8
|
-
const DEBUG = false;
|
|
9
|
-
|
|
10
|
-
export default class Tab implements TabActor {
|
|
11
|
-
// puppeteer doesn't have tab IDs
|
|
12
|
-
id = 1
|
|
13
|
-
page: any
|
|
14
|
-
url: any
|
|
15
|
-
frames: { [id: number]: any }
|
|
16
|
-
frame: {
|
|
17
|
-
type: string
|
|
18
|
-
id: number
|
|
19
|
-
url: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
_utilsSnippet: string // serialized RPC functions borrowed from content script
|
|
23
|
-
|
|
24
|
-
constructor(page: any, url: string, frames: { [id: number]: any }) {
|
|
25
|
-
this.page = page;
|
|
26
|
-
this.url = url;
|
|
27
|
-
this.frames = frames;
|
|
28
|
-
this._utilsSnippet = `
|
|
29
|
-
${getStyleElementUtil.toString()}
|
|
30
|
-
${hideElementsUtil.toString()}
|
|
31
|
-
`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async elementExists(selector: string, frameId = 0) {
|
|
35
|
-
const elements = await this.frames[frameId].$$(selector)
|
|
36
|
-
DEBUG && console.log('[exists]', selector, elements.length > 0);
|
|
37
|
-
return elements.length > 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async clickElement(selector: string, frameId = 0) {
|
|
41
|
-
if (await this.elementExists(selector, frameId)) {
|
|
42
|
-
try {
|
|
43
|
-
const result = await this.frames[frameId].evaluate((s: string) => {
|
|
44
|
-
try {
|
|
45
|
-
(document.querySelector(s) as HTMLElement).click();
|
|
46
|
-
return true;
|
|
47
|
-
} catch (e) {
|
|
48
|
-
return e.toString();
|
|
49
|
-
}
|
|
50
|
-
}, selector);
|
|
51
|
-
DEBUG && console.log('[click]', selector, result);
|
|
52
|
-
return result;
|
|
53
|
-
} catch (e) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async clickElements(selector: string, frameId = 0) {
|
|
61
|
-
const elements = await this.frames[frameId].$$(selector);
|
|
62
|
-
DEBUG && console.log('[click all]', selector);
|
|
63
|
-
await this.frames[frameId].evaluate((s: string) => {
|
|
64
|
-
const elem = document.querySelectorAll<HTMLElement>(s);
|
|
65
|
-
elem.forEach(e => e.click());
|
|
66
|
-
}, selector)
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async elementsAreVisible(selector: string, check: 'all' | 'any' | 'none', frameId = 0) {
|
|
71
|
-
if (!await this.elementExists(selector, frameId)) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
const visible: boolean[] = await this.frames[frameId].$$eval(selector, (nodes: any) => nodes.map((n: any) => n.offsetParent !== null || window.getComputedStyle(n).display !== "none"));
|
|
75
|
-
DEBUG && console.log('[visible]', selector, check, visible);
|
|
76
|
-
if (visible.length === 0) {
|
|
77
|
-
return false;
|
|
78
|
-
} else if (check === 'any') {
|
|
79
|
-
return visible.some(r => r);
|
|
80
|
-
} else if (check === 'none') {
|
|
81
|
-
return visible.every(r => !r);
|
|
82
|
-
}
|
|
83
|
-
return visible.every(r => r);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async getAttribute(selector: string, attribute: string, frameId = 0) {
|
|
87
|
-
const elem = await this.frames[frameId].$(selector);
|
|
88
|
-
if (elem) {
|
|
89
|
-
return (await elem.getProperty(attribute)).jsonValue();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async eval(script: string, frameId = 0) {
|
|
94
|
-
const result = await this.frames[frameId].evaluate(script);
|
|
95
|
-
DEBUG && console.log('[eval]', script, result);
|
|
96
|
-
return result
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async waitForElement(selector: string, timeout: number, frameId = 0) {
|
|
100
|
-
const interval = 200;
|
|
101
|
-
const times = Math.ceil(timeout / interval);
|
|
102
|
-
return waitFor(() => this.elementExists(selector, frameId), times, interval);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async waitForThenClick(selector: string, timeout: number, frameId = 0) {
|
|
106
|
-
if (await this.waitForElement(selector, timeout, frameId)) {
|
|
107
|
-
return await this.clickElement(selector, frameId);
|
|
108
|
-
}
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async hideElements(selectors: string[], frameId = 0, method: HideMethod = 'display') {
|
|
113
|
-
return await this.frames[frameId].evaluate(`(() => {
|
|
114
|
-
${this._utilsSnippet}
|
|
115
|
-
return hideElementsUtil(${JSON.stringify(selectors)}, '${method}');
|
|
116
|
-
})()`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
undoHideElements(frameId?: number): Promise<boolean> {
|
|
120
|
-
return Promise.resolve(true)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async goto(url: string) {
|
|
124
|
-
return this.page.goto(url);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
wait(ms: number): Promise<true> {
|
|
128
|
-
return new Promise((resolve) => {
|
|
129
|
-
setTimeout(() => resolve(true), ms);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
matches(options: any): Promise<boolean> {
|
|
134
|
-
const script = `(() => {
|
|
135
|
-
const Tools = ${Tools.toString()};
|
|
136
|
-
const matches = ${matches.toString()};
|
|
137
|
-
return matches(${JSON.stringify(options)})
|
|
138
|
-
})();
|
|
139
|
-
`
|
|
140
|
-
return this.frames[0].evaluate(script)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
executeAction(config: any, param?: any): Promise<boolean> {
|
|
144
|
-
throw new Error("Method not implemented.");
|
|
145
|
-
}
|
|
146
|
-
}
|
package/lib/rules.d.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export type AutoConsentCMPRule = {
|
|
3
|
-
name: string
|
|
4
|
-
prehideSelectors?: string[]
|
|
5
|
-
isHidingRule?: boolean
|
|
6
|
-
detectCmp: AutoConsentRuleStep[]
|
|
7
|
-
detectPopup: AutoConsentRuleStep[]
|
|
8
|
-
frame?: string
|
|
9
|
-
optOut: AutoConsentRuleStep[]
|
|
10
|
-
optIn: AutoConsentRuleStep[]
|
|
11
|
-
openCmp?: AutoConsentRuleStep[]
|
|
12
|
-
test?: AutoConsentRuleStep[]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type AutoConsentRuleStep = { frame?: boolean; optional?: boolean } & Partial<
|
|
16
|
-
ElementExistsRule
|
|
17
|
-
> &
|
|
18
|
-
Partial<ElementVisibleRule> &
|
|
19
|
-
Partial<EvalRule> &
|
|
20
|
-
Partial<WaitForRule> &
|
|
21
|
-
Partial<ClickRule> &
|
|
22
|
-
Partial<WaitForThenClickRule> &
|
|
23
|
-
Partial<WaitRule> &
|
|
24
|
-
Partial<UrlRule> &
|
|
25
|
-
Partial<GotoUrlRule> &
|
|
26
|
-
Partial<HideRule> &
|
|
27
|
-
Partial<UndoHideRule> &
|
|
28
|
-
Partial<WaitForFrameRule>;
|
|
29
|
-
|
|
30
|
-
type ElementExistsRule = {
|
|
31
|
-
exists: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type ElementVisibleRule = {
|
|
35
|
-
visible: string;
|
|
36
|
-
check?: "any" | "all" | "none";
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
type EvalRule = {
|
|
40
|
-
eval: string;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
type WaitForRule = {
|
|
44
|
-
waitFor: string;
|
|
45
|
-
timeout?: number;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
type ClickRule = {
|
|
49
|
-
click: string;
|
|
50
|
-
all?: boolean;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
type WaitForThenClickRule = {
|
|
54
|
-
waitForThenClick: string;
|
|
55
|
-
timeout?: number;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
type WaitRule = {
|
|
59
|
-
wait: number;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
type UrlRule = {
|
|
63
|
-
url: string;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
type GotoUrlRule = {
|
|
67
|
-
goto: string;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
type HideRule = {
|
|
71
|
-
hide: string[];
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
type UndoHideRule = {
|
|
75
|
-
undoHide: boolean;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
type WaitForFrameRule = {
|
|
79
|
-
waitForFrame: true
|
|
80
|
-
};
|
package/lib/tabwrapper.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { enableLogs } from './config';
|
|
2
|
-
export default class TabConsent {
|
|
3
|
-
constructor(tab, ruleCheckPromise) {
|
|
4
|
-
this.tab = tab;
|
|
5
|
-
this.optOutStatus = null;
|
|
6
|
-
this.checked = ruleCheckPromise;
|
|
7
|
-
ruleCheckPromise.then(rule => this.rule = rule);
|
|
8
|
-
}
|
|
9
|
-
getCMPName() {
|
|
10
|
-
if (this.rule) {
|
|
11
|
-
return this.rule.name;
|
|
12
|
-
}
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
async isPopupOpen(retries = 1, interval = 1000) {
|
|
16
|
-
enableLogs && console.log('checking if popup is open...', this.tab.id, this.rule.name);
|
|
17
|
-
const isOpen = await this.rule.detectPopup(this.tab);
|
|
18
|
-
if (!isOpen && retries > 0) {
|
|
19
|
-
return new Promise((resolve) => setTimeout(() => resolve(this.isPopupOpen(retries - 1, interval)), interval));
|
|
20
|
-
}
|
|
21
|
-
enableLogs && console.log(`popup is ${isOpen ? 'open' : 'not open'}`);
|
|
22
|
-
return isOpen;
|
|
23
|
-
}
|
|
24
|
-
async doOptOut() {
|
|
25
|
-
try {
|
|
26
|
-
enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
|
|
27
|
-
this.optOutStatus = await this.rule.optOut(this.tab);
|
|
28
|
-
return this.optOutStatus;
|
|
29
|
-
}
|
|
30
|
-
catch (e) {
|
|
31
|
-
console.error('error during opt out', e);
|
|
32
|
-
this.optOutStatus = e;
|
|
33
|
-
throw e;
|
|
34
|
-
}
|
|
35
|
-
finally {
|
|
36
|
-
if (!this.rule.isHidingRule) {
|
|
37
|
-
enableLogs && console.log('unhiding elements');
|
|
38
|
-
if (this.getCMPName().startsWith('com_')) {
|
|
39
|
-
this.tab.wait(5000).then(() => this.tab.undoHideElements());
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
await this.tab.undoHideElements();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
async doOptIn() {
|
|
48
|
-
try {
|
|
49
|
-
return this.rule.optIn(this.tab);
|
|
50
|
-
}
|
|
51
|
-
finally {
|
|
52
|
-
if (!this.rule.isHidingRule) {
|
|
53
|
-
await this.tab.undoHideElements();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
hasTest() {
|
|
58
|
-
return !!this.rule.hasSelfTest;
|
|
59
|
-
}
|
|
60
|
-
async testOptOutWorked() {
|
|
61
|
-
return this.rule.test(this.tab);
|
|
62
|
-
}
|
|
63
|
-
async applyCosmetics(selectors) {
|
|
64
|
-
const hidden = await this.tab.hideElements(selectors);
|
|
65
|
-
return hidden;
|
|
66
|
-
}
|
|
67
|
-
}
|
package/lib/tabwrapper.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { enableLogs } from './config';
|
|
2
|
-
import { AutoCMP, TabActor } from './types';
|
|
3
|
-
|
|
4
|
-
export default class TabConsent {
|
|
5
|
-
checked: Promise<AutoCMP>
|
|
6
|
-
rule: AutoCMP
|
|
7
|
-
optOutStatus: boolean | Error = null
|
|
8
|
-
|
|
9
|
-
constructor(public tab: TabActor, ruleCheckPromise: Promise<AutoCMP>) {
|
|
10
|
-
this.checked = ruleCheckPromise;
|
|
11
|
-
ruleCheckPromise.then(rule => this.rule = rule);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
getCMPName() {
|
|
15
|
-
if (this.rule) {
|
|
16
|
-
return this.rule.name;
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async isPopupOpen(retries = 1, interval = 1000): Promise<boolean> {
|
|
22
|
-
enableLogs && console.log('checking if popup is open...', this.tab.id, this.rule.name);
|
|
23
|
-
const isOpen = await this.rule.detectPopup(this.tab);
|
|
24
|
-
if (!isOpen && retries > 0) {
|
|
25
|
-
return new Promise((resolve) => setTimeout(() => resolve(this.isPopupOpen(retries - 1, interval)), interval));
|
|
26
|
-
}
|
|
27
|
-
enableLogs && console.log(`popup is ${isOpen ? 'open' : 'not open'}`);
|
|
28
|
-
return isOpen;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async doOptOut() {
|
|
32
|
-
try {
|
|
33
|
-
enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
|
|
34
|
-
this.optOutStatus = await this.rule.optOut(this.tab);
|
|
35
|
-
return this.optOutStatus;
|
|
36
|
-
} catch (e) {
|
|
37
|
-
console.error('error during opt out', e);
|
|
38
|
-
this.optOutStatus = e;
|
|
39
|
-
throw e;
|
|
40
|
-
} finally {
|
|
41
|
-
if (!this.rule.isHidingRule) {
|
|
42
|
-
enableLogs && console.log('unhiding elements');
|
|
43
|
-
if (this.getCMPName().startsWith('com_')) {
|
|
44
|
-
this.tab.wait(5000).then(() => this.tab.undoHideElements())
|
|
45
|
-
} else {
|
|
46
|
-
await this.tab.undoHideElements();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async doOptIn() {
|
|
53
|
-
try {
|
|
54
|
-
return this.rule.optIn(this.tab);
|
|
55
|
-
} finally {
|
|
56
|
-
if (!this.rule.isHidingRule) {
|
|
57
|
-
await this.tab.undoHideElements();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
hasTest() {
|
|
63
|
-
return !!this.rule.hasSelfTest
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async testOptOutWorked() {
|
|
67
|
-
return this.rule.test(this.tab);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async applyCosmetics(selectors: string[]) {
|
|
71
|
-
const hidden = await this.tab.hideElements(selectors);
|
|
72
|
-
return hidden;
|
|
73
|
-
}
|
|
74
|
-
}
|
package/lib/types.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { ContentScriptMessage, HideMethod } from "./messages";
|
|
2
|
-
|
|
3
|
-
type Tab = {
|
|
4
|
-
url: string
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
type BrowserTabs = {
|
|
8
|
-
get(tabId: number): Promise<Tab>
|
|
9
|
-
update(tabId: number, options: any): Promise<void>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type Browser = {
|
|
13
|
-
tabs: BrowserTabs,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface TabActor {
|
|
17
|
-
frame?: {
|
|
18
|
-
id: number
|
|
19
|
-
url: string
|
|
20
|
-
}
|
|
21
|
-
id: number
|
|
22
|
-
elementExists(selector: string, frameId?: number): Promise<boolean>
|
|
23
|
-
clickElement(selector: string, frameId?: number): Promise<boolean>
|
|
24
|
-
clickElements(selector: string, frameId?: number): Promise<boolean>
|
|
25
|
-
elementsAreVisible(selector: string, check?: 'all' | 'any' | 'none', frameId?: number): Promise<boolean>
|
|
26
|
-
getAttribute(selector: string, attribute: string, frameId?: number): Promise<string>
|
|
27
|
-
eval(script: string, frameId?: number): Promise<boolean>
|
|
28
|
-
waitForElement(selector: string, timeout: number, frameId?: number): Promise<boolean>
|
|
29
|
-
waitForThenClick(selector: string, timeout?: number, frameId?: number): Promise<boolean>
|
|
30
|
-
hideElements(selectors: string[], frameId?: number, method?: HideMethod): Promise<boolean>
|
|
31
|
-
undoHideElements(frameId?: number): Promise<boolean>
|
|
32
|
-
goto(url: string): Promise<void>
|
|
33
|
-
wait(ms: number): Promise<true>
|
|
34
|
-
|
|
35
|
-
// Consent-O-Matic methods
|
|
36
|
-
matches(matcherConfig: any): Promise<boolean>
|
|
37
|
-
executeAction(actionConfig: any, param?: any): Promise<boolean>
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type MessageSender<ResultType = any> = (tabId: number, message: ContentScriptMessage, options?: { frameId: number }) => Promise<ResultType>;
|
|
41
|
-
|
|
42
|
-
export interface AutoCMP {
|
|
43
|
-
name: string
|
|
44
|
-
hasSelfTest: boolean
|
|
45
|
-
prehideSelectors?: string[]
|
|
46
|
-
isHidingRule?: boolean
|
|
47
|
-
detectCmp(tab: TabActor): Promise<boolean>
|
|
48
|
-
detectPopup(tab: TabActor): Promise<boolean>
|
|
49
|
-
optOut(tab:TabActor): Promise<boolean>
|
|
50
|
-
optIn(tab: TabActor): Promise<boolean>
|
|
51
|
-
openCmp(tab: TabActor): Promise<boolean>
|
|
52
|
-
test(tab: TabActor): Promise<boolean>
|
|
53
|
-
detectFrame(tab: TabActor, frame: { url: string }): boolean
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
type FindResult = {
|
|
57
|
-
parent?: any
|
|
58
|
-
target?: {
|
|
59
|
-
checked: boolean
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import Tools from "./tools";
|
|
2
|
-
export function matches(config) {
|
|
3
|
-
const result = Tools.find(config);
|
|
4
|
-
if (config.type === "css") {
|
|
5
|
-
return !!result.target;
|
|
6
|
-
}
|
|
7
|
-
else if (config.type === "checkbox") {
|
|
8
|
-
return !!result.target && result.target.checked;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
export async function executeAction(config, param) {
|
|
12
|
-
switch (config.type) {
|
|
13
|
-
case "click":
|
|
14
|
-
return clickAction(config);
|
|
15
|
-
case "list":
|
|
16
|
-
return listAction(config, param);
|
|
17
|
-
case "consent":
|
|
18
|
-
return consentAction(config, param);
|
|
19
|
-
case "ifcss":
|
|
20
|
-
return ifCssAction(config, param);
|
|
21
|
-
case "waitcss":
|
|
22
|
-
return waitCssAction(config);
|
|
23
|
-
case "foreach":
|
|
24
|
-
return forEachAction(config, param);
|
|
25
|
-
case "hide":
|
|
26
|
-
return hideAction(config);
|
|
27
|
-
case "slide":
|
|
28
|
-
return slideAction(config);
|
|
29
|
-
case "close":
|
|
30
|
-
return closeAction(config);
|
|
31
|
-
case "wait":
|
|
32
|
-
return waitAction(config);
|
|
33
|
-
case "eval":
|
|
34
|
-
return evalAction(config);
|
|
35
|
-
default:
|
|
36
|
-
throw "Unknown action type: " + config.type;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const STEP_TIMEOUT = 0;
|
|
40
|
-
function waitTimeout(timeout) {
|
|
41
|
-
return new Promise(resolve => {
|
|
42
|
-
setTimeout(() => {
|
|
43
|
-
resolve();
|
|
44
|
-
}, timeout);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
async function clickAction(config) {
|
|
48
|
-
const result = Tools.find(config);
|
|
49
|
-
if (result.target != null) {
|
|
50
|
-
result.target.click();
|
|
51
|
-
}
|
|
52
|
-
return waitTimeout(STEP_TIMEOUT);
|
|
53
|
-
}
|
|
54
|
-
async function listAction(config, param) {
|
|
55
|
-
for (let action of config.actions) {
|
|
56
|
-
await executeAction(action, param);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async function consentAction(config, consentTypes) {
|
|
60
|
-
for (const consentConfig of config.consents) {
|
|
61
|
-
const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
|
|
62
|
-
if (consentConfig.matcher && consentConfig.toggleAction) {
|
|
63
|
-
const isEnabled = matches(consentConfig.matcher);
|
|
64
|
-
if (isEnabled !== shouldEnable) {
|
|
65
|
-
await executeAction(consentConfig.toggleAction);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
if (shouldEnable) {
|
|
70
|
-
await executeAction(consentConfig.trueAction);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
await executeAction(consentConfig.falseAction);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
async function ifCssAction(config, param) {
|
|
79
|
-
const result = Tools.find(config);
|
|
80
|
-
if (!result.target) {
|
|
81
|
-
if (config.trueAction) {
|
|
82
|
-
await executeAction(config.trueAction, param);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
if (config.falseAction) {
|
|
87
|
-
await executeAction(config.falseAction, param);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
async function waitCssAction(config) {
|
|
92
|
-
await new Promise(resolve => {
|
|
93
|
-
let numRetries = config.retries || 10;
|
|
94
|
-
const waitTime = config.waitTime || 250;
|
|
95
|
-
const checkCss = () => {
|
|
96
|
-
const result = Tools.find(config);
|
|
97
|
-
if ((config.negated && result.target) ||
|
|
98
|
-
(!config.negated && !result.target)) {
|
|
99
|
-
if (numRetries > 0) {
|
|
100
|
-
numRetries -= 1;
|
|
101
|
-
setTimeout(checkCss, waitTime);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
resolve();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
resolve();
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
checkCss();
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
async function forEachAction(config, param) {
|
|
115
|
-
const results = Tools.find(config, true);
|
|
116
|
-
const oldBase = Tools.base;
|
|
117
|
-
for (const result of results) {
|
|
118
|
-
if (result.target) {
|
|
119
|
-
Tools.setBase(result.target);
|
|
120
|
-
await executeAction(config.action, param);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
Tools.setBase(oldBase);
|
|
124
|
-
}
|
|
125
|
-
async function hideAction(config) {
|
|
126
|
-
const result = Tools.find(config);
|
|
127
|
-
if (result.target) {
|
|
128
|
-
result.target.classList.add("Autoconsent-Hidden");
|
|
129
|
-
// result.target.setAttribute("style", "display: none;");
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async function slideAction(config) {
|
|
133
|
-
const result = Tools.find(config);
|
|
134
|
-
const dragResult = Tools.find(config.dragTarget);
|
|
135
|
-
if (result.target) {
|
|
136
|
-
let targetBounds = result.target.getBoundingClientRect();
|
|
137
|
-
let dragTargetBounds = dragResult.target.getBoundingClientRect();
|
|
138
|
-
let yDiff = dragTargetBounds.top - targetBounds.top;
|
|
139
|
-
let xDiff = dragTargetBounds.left - targetBounds.left;
|
|
140
|
-
if (this.config.axis.toLowerCase() === "y") {
|
|
141
|
-
xDiff = 0;
|
|
142
|
-
}
|
|
143
|
-
if (this.config.axis.toLowerCase() === "x") {
|
|
144
|
-
yDiff = 0;
|
|
145
|
-
}
|
|
146
|
-
let screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
|
|
147
|
-
let screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
|
|
148
|
-
let clientX = targetBounds.left + targetBounds.width / 2.0;
|
|
149
|
-
let clientY = targetBounds.top + targetBounds.height / 2.0;
|
|
150
|
-
let mouseDown = document.createEvent("MouseEvents");
|
|
151
|
-
mouseDown.initMouseEvent("mousedown", true, true, window, 0, screenX, screenY, clientX, clientY, false, false, false, false, 0, result.target);
|
|
152
|
-
let mouseMove = document.createEvent("MouseEvents");
|
|
153
|
-
mouseMove.initMouseEvent("mousemove", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
|
|
154
|
-
let mouseUp = document.createEvent("MouseEvents");
|
|
155
|
-
mouseUp.initMouseEvent("mouseup", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
|
|
156
|
-
result.target.dispatchEvent(mouseDown);
|
|
157
|
-
await this.waitTimeout(10);
|
|
158
|
-
result.target.dispatchEvent(mouseMove);
|
|
159
|
-
await this.waitTimeout(10);
|
|
160
|
-
result.target.dispatchEvent(mouseUp);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
async function waitAction(config) {
|
|
164
|
-
await waitTimeout(config.waitTime);
|
|
165
|
-
}
|
|
166
|
-
async function closeAction(config) {
|
|
167
|
-
window.close();
|
|
168
|
-
}
|
|
169
|
-
async function evalAction(config) {
|
|
170
|
-
console.log("eval!", config.code);
|
|
171
|
-
return new Promise(resolve => {
|
|
172
|
-
try {
|
|
173
|
-
if (config.async) {
|
|
174
|
-
window.eval(config.code);
|
|
175
|
-
setTimeout(() => {
|
|
176
|
-
resolve(window.eval("window.__consentCheckResult"));
|
|
177
|
-
}, config.timeout || 250);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
resolve(window.eval(config.code));
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch (e) {
|
|
184
|
-
console.warn("eval error", e, config.code);
|
|
185
|
-
resolve(false);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
}
|