@duckduckgo/autoconsent 1.0.5 → 1.0.8
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/dist/autoconsent.cjs.js +105 -34
- package/dist/autoconsent.esm.js +105 -34
- package/dist/autoconsent.puppet.js +109 -11
- package/lib/cmps/all.js +2 -0
- package/lib/cmps/all.ts +2 -0
- package/lib/cmps/base.js +5 -1
- package/lib/cmps/base.ts +5 -1
- package/lib/cmps/cookiebot.js +6 -2
- package/lib/cmps/cookiebot.ts +8 -2
- package/lib/cmps/onetrust.js +34 -0
- package/lib/cmps/onetrust.ts +47 -0
- package/lib/cmps/trustarc.js +2 -2
- package/lib/cmps/trustarc.ts +2 -2
- package/lib/config.js +1 -0
- package/lib/config.ts +1 -0
- package/lib/detector.js +4 -0
- package/lib/detector.ts +4 -0
- package/lib/hider.js +1 -1
- package/lib/hider.ts +1 -1
- package/lib/messages.d.ts +3 -0
- package/lib/node.js +8 -3
- package/lib/node.ts +10 -5
- package/lib/puppet/tab.js +10 -3
- package/lib/puppet/tab.ts +13 -3
- package/lib/tabwrapper.js +6 -0
- package/lib/tabwrapper.ts +6 -0
- package/lib/types.d.ts +2 -2
- package/lib/web/content-utils.js +29 -0
- package/lib/web/content-utils.ts +31 -0
- package/lib/web/content.js +20 -22
- package/lib/web/content.ts +19 -22
- package/lib/web/tab.js +12 -6
- package/lib/web/tab.ts +13 -6
- package/lib/web.js +5 -0
- package/lib/web.ts +5 -0
- package/package.json +1 -1
- package/readme.md +1 -1
- 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/bing.json +14 -0
- package/rules/autoconsent/bundesregierung-de.json +1 -1
- package/rules/autoconsent/dunelm.json +18 -0
- package/rules/autoconsent/etsy.json +13 -0
- package/rules/autoconsent/gov-uk.json +10 -0
- package/rules/autoconsent/marksandspencer.json +7 -0
- package/rules/autoconsent/{paypal-de.json → paypal.json} +6 -2
- 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 +308 -50
- package/tests/192.spec.ts +7 -0
- package/tests/ausopen.spec.ts +7 -0
- package/tests/cookiebot.spec.ts +1 -0
- package/tests/dunelm.spec.ts +7 -0
- package/tests/etsy.spec.ts +7 -0
- package/tests/gov-uk.spec.ts +9 -0
- package/tests/marksandspencer.spec.ts +7 -0
- package/tests/onetrust.spec.ts +6 -0
- package/tests/paypal.spec.ts +7 -5
- package/tests/runner.ts +1 -1
- package/tests/trustarc.spec.ts +1 -0
- package/tests/uswitch.spec.ts +7 -0
- package/tests/waitrose.spec.ts +7 -0
- package/tests/wetransfer.spec.ts +7 -0
- package/rules/autoconsent/onetrust.json +0 -24
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
const enableLogs = false; // change this to enable debug logs
|
|
6
|
+
|
|
5
7
|
/* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
|
|
6
8
|
async function waitFor(predicate, maxTimes, interval) {
|
|
7
9
|
let result = await predicate();
|
|
@@ -17,7 +19,7 @@ async function waitFor(predicate, maxTimes, interval) {
|
|
|
17
19
|
async function success(action) {
|
|
18
20
|
const result = await action;
|
|
19
21
|
if (!result) {
|
|
20
|
-
throw new Error(`Action failed: ${action}`);
|
|
22
|
+
throw new Error(`Action failed: ${action} ${result}`);
|
|
21
23
|
}
|
|
22
24
|
return result;
|
|
23
25
|
}
|
|
@@ -361,6 +363,36 @@ function matches(config) {
|
|
|
361
363
|
}
|
|
362
364
|
}
|
|
363
365
|
|
|
366
|
+
// get or create a style container for CSS overrides
|
|
367
|
+
function getStyleElementUtil() {
|
|
368
|
+
const styleOverrideElementId = "autoconsent-css-rules";
|
|
369
|
+
const styleSelector = `style#${styleOverrideElementId}`;
|
|
370
|
+
const existingElement = document.querySelector(styleSelector);
|
|
371
|
+
if (existingElement && existingElement instanceof HTMLStyleElement) {
|
|
372
|
+
return existingElement;
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
const parent = document.head ||
|
|
376
|
+
document.getElementsByTagName("head")[0] ||
|
|
377
|
+
document.documentElement;
|
|
378
|
+
const css = document.createElement("style");
|
|
379
|
+
css.id = styleOverrideElementId;
|
|
380
|
+
parent.appendChild(css);
|
|
381
|
+
return css;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// hide elements with a CSS rule
|
|
385
|
+
function hideElementsUtil(selectors, method) {
|
|
386
|
+
const hidingSnippet = method === 'display' ? `display: none` : `opacity: 0`;
|
|
387
|
+
const rule = `${selectors.join(",")} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
|
|
388
|
+
const styleEl = getStyleElementUtil();
|
|
389
|
+
if (styleEl instanceof HTMLStyleElement) {
|
|
390
|
+
styleEl.innerText += rule;
|
|
391
|
+
return selectors.length > 0;
|
|
392
|
+
}
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
|
|
364
396
|
const DEBUG = false;
|
|
365
397
|
class Tab {
|
|
366
398
|
constructor(page, url, frames) {
|
|
@@ -369,6 +401,10 @@ class Tab {
|
|
|
369
401
|
this.page = page;
|
|
370
402
|
this.url = url;
|
|
371
403
|
this.frames = frames;
|
|
404
|
+
this._utilsSnippet = `
|
|
405
|
+
${getStyleElementUtil.toString()}
|
|
406
|
+
${hideElementsUtil.toString()}
|
|
407
|
+
`;
|
|
372
408
|
}
|
|
373
409
|
async elementExists(selector, frameId = 0) {
|
|
374
410
|
const elements = await this.frames[frameId].$$(selector);
|
|
@@ -440,9 +476,11 @@ class Tab {
|
|
|
440
476
|
}
|
|
441
477
|
return false;
|
|
442
478
|
}
|
|
443
|
-
async hideElements(selectors, frameId = 0) {
|
|
444
|
-
|
|
445
|
-
|
|
479
|
+
async hideElements(selectors, frameId = 0, method = 'display') {
|
|
480
|
+
return await this.frames[frameId].evaluate(`(() => {
|
|
481
|
+
${this._utilsSnippet}
|
|
482
|
+
return hideElementsUtil(${JSON.stringify(selectors)}, '${method}');
|
|
483
|
+
})()`);
|
|
446
484
|
}
|
|
447
485
|
undoHideElements(frameId) {
|
|
448
486
|
return Promise.resolve(true);
|
|
@@ -477,6 +515,7 @@ async function detectDialog(tab, retries, rules) {
|
|
|
477
515
|
try {
|
|
478
516
|
if (await r.detectCmp(tab)) {
|
|
479
517
|
earlyReturn = true;
|
|
518
|
+
enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
|
|
480
519
|
resolve(index);
|
|
481
520
|
}
|
|
482
521
|
}
|
|
@@ -521,10 +560,12 @@ class TabConsent {
|
|
|
521
560
|
}
|
|
522
561
|
async doOptOut() {
|
|
523
562
|
try {
|
|
563
|
+
enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
|
|
524
564
|
this.optOutStatus = await this.rule.optOut(this.tab);
|
|
525
565
|
return this.optOutStatus;
|
|
526
566
|
}
|
|
527
567
|
catch (e) {
|
|
568
|
+
console.error('error during opt out', e);
|
|
528
569
|
this.optOutStatus = e;
|
|
529
570
|
throw e;
|
|
530
571
|
}
|
|
@@ -561,6 +602,20 @@ class TabConsent {
|
|
|
561
602
|
}
|
|
562
603
|
}
|
|
563
604
|
|
|
605
|
+
// hide rules not specific to a single CMP rule
|
|
606
|
+
const globalHidden = [
|
|
607
|
+
"#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium",
|
|
608
|
+
];
|
|
609
|
+
async function prehideElements(tab, rules) {
|
|
610
|
+
const selectors = rules.reduce((selectorList, rule) => {
|
|
611
|
+
if (rule.prehideSelectors) {
|
|
612
|
+
return [...selectorList, ...rule.prehideSelectors];
|
|
613
|
+
}
|
|
614
|
+
return selectorList;
|
|
615
|
+
}, globalHidden);
|
|
616
|
+
await tab.hideElements(selectors, undefined, 'opacity');
|
|
617
|
+
}
|
|
618
|
+
|
|
564
619
|
class TrustArc extends AutoConsentBase {
|
|
565
620
|
constructor() {
|
|
566
621
|
super("TrustArc");
|
|
@@ -577,10 +632,10 @@ class TrustArc extends AutoConsentBase {
|
|
|
577
632
|
tab.frame.url.startsWith("https://consent-pref.trustarc.com/?")) {
|
|
578
633
|
return true;
|
|
579
634
|
}
|
|
580
|
-
return tab.elementExists("#truste-show-consent");
|
|
635
|
+
return tab.elementExists("#truste-show-consent,#truste-consent-track");
|
|
581
636
|
}
|
|
582
637
|
async detectPopup(tab) {
|
|
583
|
-
return ((await tab.elementsAreVisible("#truste-consent-content,#trustarc-banner-overlay")) ||
|
|
638
|
+
return ((await tab.elementsAreVisible("#truste-consent-content,.truste-consent-content,#trustarc-banner-overlay")) ||
|
|
584
639
|
(tab.frame &&
|
|
585
640
|
(await tab.waitForElement("#defaultpreferencemanager", 5000, tab.frame.id))));
|
|
586
641
|
}
|
|
@@ -670,7 +725,7 @@ class TrustArc extends AutoConsentBase {
|
|
|
670
725
|
class Cookiebot extends AutoConsentBase {
|
|
671
726
|
constructor() {
|
|
672
727
|
super('Cybotcookiebot');
|
|
673
|
-
this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner"];
|
|
728
|
+
this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"];
|
|
674
729
|
}
|
|
675
730
|
async detectCmp(tab) {
|
|
676
731
|
try {
|
|
@@ -681,7 +736,7 @@ class Cookiebot extends AutoConsentBase {
|
|
|
681
736
|
}
|
|
682
737
|
}
|
|
683
738
|
detectPopup(tab) {
|
|
684
|
-
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner');
|
|
739
|
+
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
|
|
685
740
|
}
|
|
686
741
|
async optOut(tab) {
|
|
687
742
|
if (await tab.elementExists('.cookie-alert-extended-detail-link')) {
|
|
@@ -720,6 +775,10 @@ class Cookiebot extends AutoConsentBase {
|
|
|
720
775
|
await tab.eval('Cookiebot.dialog.submitConsent() || true');
|
|
721
776
|
await tab.wait(500);
|
|
722
777
|
}
|
|
778
|
+
// site with 3rd confirm settings modal
|
|
779
|
+
if (await tab.elementExists('#cb-confirmedSettings')) {
|
|
780
|
+
await tab.eval('endCookieProcess()');
|
|
781
|
+
}
|
|
723
782
|
return true;
|
|
724
783
|
}
|
|
725
784
|
async optIn(tab) {
|
|
@@ -879,12 +938,47 @@ class Evidon extends AutoConsentBase {
|
|
|
879
938
|
}
|
|
880
939
|
}
|
|
881
940
|
|
|
941
|
+
class Onetrust extends AutoConsentBase {
|
|
942
|
+
constructor() {
|
|
943
|
+
super("Onetrust");
|
|
944
|
+
this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
|
|
945
|
+
}
|
|
946
|
+
detectCmp(tab) {
|
|
947
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
948
|
+
}
|
|
949
|
+
detectPopup(tab) {
|
|
950
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
951
|
+
}
|
|
952
|
+
async optOut(tab) {
|
|
953
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
954
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
955
|
+
}
|
|
956
|
+
else { // otherwise look for a generic "show settings" button
|
|
957
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
958
|
+
}
|
|
959
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
960
|
+
await success(tab.wait(1000));
|
|
961
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
962
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
963
|
+
// popup doesn't disappear immediately
|
|
964
|
+
await waitFor(async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")), 10, 500);
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
967
|
+
async optIn(tab) {
|
|
968
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
969
|
+
}
|
|
970
|
+
async test(tab) {
|
|
971
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
882
975
|
const rules = [
|
|
883
976
|
new TrustArc(),
|
|
884
977
|
new Cookiebot(),
|
|
885
978
|
new SourcePoint(),
|
|
886
979
|
new ConsentManager(),
|
|
887
980
|
new Evidon(),
|
|
981
|
+
new Onetrust(),
|
|
888
982
|
];
|
|
889
983
|
function createAutoCMP(config) {
|
|
890
984
|
return new AutoConsent(config);
|
|
@@ -945,10 +1039,11 @@ class ConsentOMaticCMP {
|
|
|
945
1039
|
}
|
|
946
1040
|
}
|
|
947
1041
|
|
|
948
|
-
function attachToPage(page, url, rules, retries = 1) {
|
|
949
|
-
const frames = {
|
|
1042
|
+
function attachToPage(page, url, rules, retries = 1, prehide = true) {
|
|
1043
|
+
const frames = {
|
|
1044
|
+
0: page.mainFrame(),
|
|
1045
|
+
};
|
|
950
1046
|
const tab = new Tab(page, url, frames);
|
|
951
|
-
frames[0] = page.mainFrame();
|
|
952
1047
|
async function onFrame(frame) {
|
|
953
1048
|
const allFrames = await page.frames();
|
|
954
1049
|
allFrames.forEach((frame, frameId) => {
|
|
@@ -967,6 +1062,9 @@ function attachToPage(page, url, rules, retries = 1) {
|
|
|
967
1062
|
}
|
|
968
1063
|
page.on('framenavigated', onFrame);
|
|
969
1064
|
page.frames().forEach(onFrame);
|
|
1065
|
+
if (prehide) {
|
|
1066
|
+
prehideElements(tab, rules);
|
|
1067
|
+
}
|
|
970
1068
|
return new TabConsent(tab, detectDialog(tab, retries, rules));
|
|
971
1069
|
}
|
|
972
1070
|
|
package/lib/cmps/all.js
CHANGED
|
@@ -4,12 +4,14 @@ import CookieBot from './cookiebot';
|
|
|
4
4
|
import SourcePoint from './sourcepoint';
|
|
5
5
|
import ContentManager from './consentmanager';
|
|
6
6
|
import Evidon from './evidon';
|
|
7
|
+
import Onetrust from './onetrust';
|
|
7
8
|
const rules = [
|
|
8
9
|
new TrustArc(),
|
|
9
10
|
new CookieBot(),
|
|
10
11
|
new SourcePoint(),
|
|
11
12
|
new ContentManager(),
|
|
12
13
|
new Evidon(),
|
|
14
|
+
new Onetrust(),
|
|
13
15
|
];
|
|
14
16
|
export function createAutoCMP(config) {
|
|
15
17
|
return new AutoConsent(config);
|
package/lib/cmps/all.ts
CHANGED
|
@@ -5,6 +5,7 @@ import SourcePoint from './sourcepoint';
|
|
|
5
5
|
import ContentManager from './consentmanager';
|
|
6
6
|
import Evidon from './evidon';
|
|
7
7
|
import { AutoConsentCMPRule } from '../rules';
|
|
8
|
+
import Onetrust from './onetrust';
|
|
8
9
|
|
|
9
10
|
const rules = [
|
|
10
11
|
new TrustArc(),
|
|
@@ -12,6 +13,7 @@ const rules = [
|
|
|
12
13
|
new SourcePoint(),
|
|
13
14
|
new ContentManager(),
|
|
14
15
|
new Evidon(),
|
|
16
|
+
new Onetrust(),
|
|
15
17
|
];
|
|
16
18
|
|
|
17
19
|
export function createAutoCMP(config: AutoConsentCMPRule): AutoConsent {
|
package/lib/cmps/base.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
|
|
2
|
+
import { enableLogs } from "../config";
|
|
2
3
|
export async function waitFor(predicate, maxTimes, interval) {
|
|
3
4
|
let result = await predicate();
|
|
4
5
|
if (!result && maxTimes > 0) {
|
|
@@ -13,7 +14,7 @@ export async function waitFor(predicate, maxTimes, interval) {
|
|
|
13
14
|
export async function success(action) {
|
|
14
15
|
const result = await action;
|
|
15
16
|
if (!result) {
|
|
16
|
-
throw new Error(`Action failed: ${action}`);
|
|
17
|
+
throw new Error(`Action failed: ${action} ${result}`);
|
|
17
18
|
}
|
|
18
19
|
return result;
|
|
19
20
|
}
|
|
@@ -118,7 +119,9 @@ export class AutoConsent extends AutoConsentBase {
|
|
|
118
119
|
}
|
|
119
120
|
async _runRulesSequentially(tab, rules) {
|
|
120
121
|
for (const rule of rules) {
|
|
122
|
+
enableLogs && console.log('Running rule...', rule, tab.id);
|
|
121
123
|
const result = await evaluateRule(rule, tab);
|
|
124
|
+
enableLogs && console.log('...rule result', result);
|
|
122
125
|
if (!result && !rule.optional) {
|
|
123
126
|
return false;
|
|
124
127
|
}
|
|
@@ -145,6 +148,7 @@ export class AutoConsent extends AutoConsentBase {
|
|
|
145
148
|
}
|
|
146
149
|
async optOut(tab) {
|
|
147
150
|
if (this.config.optOut) {
|
|
151
|
+
enableLogs && console.log('Initiated optOut()', this.config.optOut);
|
|
148
152
|
return this._runRulesSequentially(tab, this.config.optOut);
|
|
149
153
|
}
|
|
150
154
|
return false;
|
package/lib/cmps/base.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { AutoCMP, TabActor } from "../types";
|
|
4
4
|
import { AutoConsentCMPRule, AutoConsentRuleStep } from "../rules";
|
|
5
|
+
import { enableLogs } from "../config";
|
|
5
6
|
|
|
6
7
|
export async function waitFor(predicate: () => Promise<boolean> | boolean, maxTimes: number, interval: number): Promise<boolean> {
|
|
7
8
|
let result = await predicate();
|
|
@@ -19,7 +20,7 @@ export async function waitFor(predicate: () => Promise<boolean> | boolean, maxTi
|
|
|
19
20
|
export async function success(action: Promise<boolean>): Promise<boolean> {
|
|
20
21
|
const result = await action;
|
|
21
22
|
if (!result) {
|
|
22
|
-
throw new Error(`Action failed: ${action}`)
|
|
23
|
+
throw new Error(`Action failed: ${action} ${result}`)
|
|
23
24
|
}
|
|
24
25
|
return result
|
|
25
26
|
}
|
|
@@ -140,7 +141,9 @@ export class AutoConsent extends AutoConsentBase {
|
|
|
140
141
|
|
|
141
142
|
async _runRulesSequentially(tab: TabActor, rules: AutoConsentRuleStep[]): Promise<boolean> {
|
|
142
143
|
for (const rule of rules) {
|
|
144
|
+
enableLogs && console.log('Running rule...', rule, tab.id);
|
|
143
145
|
const result = await evaluateRule(rule, tab);
|
|
146
|
+
enableLogs && console.log('...rule result', result);
|
|
144
147
|
if (!result && !rule.optional) {
|
|
145
148
|
return false;
|
|
146
149
|
}
|
|
@@ -171,6 +174,7 @@ export class AutoConsent extends AutoConsentBase {
|
|
|
171
174
|
|
|
172
175
|
async optOut(tab: TabActor) {
|
|
173
176
|
if (this.config.optOut) {
|
|
177
|
+
enableLogs && console.log('Initiated optOut()', this.config.optOut);
|
|
174
178
|
return this._runRulesSequentially(tab, this.config.optOut);
|
|
175
179
|
}
|
|
176
180
|
return false;
|
package/lib/cmps/cookiebot.js
CHANGED
|
@@ -2,7 +2,7 @@ import AutoConsentBase from './base';
|
|
|
2
2
|
export default class Cookiebot extends AutoConsentBase {
|
|
3
3
|
constructor() {
|
|
4
4
|
super('Cybotcookiebot');
|
|
5
|
-
this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner"];
|
|
5
|
+
this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"];
|
|
6
6
|
}
|
|
7
7
|
async detectCmp(tab) {
|
|
8
8
|
try {
|
|
@@ -13,7 +13,7 @@ export default class Cookiebot extends AutoConsentBase {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
detectPopup(tab) {
|
|
16
|
-
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner');
|
|
16
|
+
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
|
|
17
17
|
}
|
|
18
18
|
async optOut(tab) {
|
|
19
19
|
if (await tab.elementExists('.cookie-alert-extended-detail-link')) {
|
|
@@ -52,6 +52,10 @@ export default class Cookiebot extends AutoConsentBase {
|
|
|
52
52
|
await tab.eval('Cookiebot.dialog.submitConsent() || true');
|
|
53
53
|
await tab.wait(500);
|
|
54
54
|
}
|
|
55
|
+
// site with 3rd confirm settings modal
|
|
56
|
+
if (await tab.elementExists('#cb-confirmedSettings')) {
|
|
57
|
+
await tab.eval('endCookieProcess()');
|
|
58
|
+
}
|
|
55
59
|
return true;
|
|
56
60
|
}
|
|
57
61
|
async optIn(tab) {
|
package/lib/cmps/cookiebot.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { TabActor } from '../types';
|
|
|
3
3
|
|
|
4
4
|
export default class Cookiebot extends AutoConsentBase {
|
|
5
5
|
|
|
6
|
-
prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner"]
|
|
6
|
+
prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"]
|
|
7
7
|
|
|
8
8
|
constructor() {
|
|
9
9
|
super('Cybotcookiebot');
|
|
@@ -18,7 +18,7 @@ export default class Cookiebot extends AutoConsentBase {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
detectPopup(tab: TabActor) {
|
|
21
|
-
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner');
|
|
21
|
+
return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
async optOut(tab: TabActor) {
|
|
@@ -57,6 +57,12 @@ export default class Cookiebot extends AutoConsentBase {
|
|
|
57
57
|
await tab.eval('Cookiebot.dialog.submitConsent() || true');
|
|
58
58
|
await tab.wait(500);
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
// site with 3rd confirm settings modal
|
|
62
|
+
if (await tab.elementExists('#cb-confirmedSettings')) {
|
|
63
|
+
await tab.eval('endCookieProcess()')
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
return true;
|
|
61
67
|
}
|
|
62
68
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import AutoConsentBase, { success, waitFor } from "./base";
|
|
2
|
+
export default class Onetrust extends AutoConsentBase {
|
|
3
|
+
constructor() {
|
|
4
|
+
super("Onetrust");
|
|
5
|
+
this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
|
|
6
|
+
}
|
|
7
|
+
detectCmp(tab) {
|
|
8
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
9
|
+
}
|
|
10
|
+
detectPopup(tab) {
|
|
11
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
12
|
+
}
|
|
13
|
+
async optOut(tab) {
|
|
14
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
15
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
16
|
+
}
|
|
17
|
+
else { // otherwise look for a generic "show settings" button
|
|
18
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
19
|
+
}
|
|
20
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
21
|
+
await success(tab.wait(1000));
|
|
22
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
23
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
24
|
+
// popup doesn't disappear immediately
|
|
25
|
+
await waitFor(async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")), 10, 500);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
async optIn(tab) {
|
|
29
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
30
|
+
}
|
|
31
|
+
async test(tab) {
|
|
32
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import AutoConsentBase, { success, waitFor } from "./base";
|
|
2
|
+
import { TabActor } from "../types";
|
|
3
|
+
|
|
4
|
+
export default class Onetrust extends AutoConsentBase {
|
|
5
|
+
|
|
6
|
+
prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"]
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super("Onetrust");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
detectCmp(tab: TabActor) {
|
|
13
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
detectPopup(tab: TabActor) {
|
|
17
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async optOut(tab: TabActor) {
|
|
21
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
22
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
23
|
+
} else { // otherwise look for a generic "show settings" button
|
|
24
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
28
|
+
await success(tab.wait(1000));
|
|
29
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
30
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
31
|
+
// popup doesn't disappear immediately
|
|
32
|
+
await waitFor(
|
|
33
|
+
async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")),
|
|
34
|
+
10,
|
|
35
|
+
500
|
|
36
|
+
);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async optIn(tab: TabActor) {
|
|
41
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async test(tab: TabActor){
|
|
45
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
46
|
+
}
|
|
47
|
+
}
|
package/lib/cmps/trustarc.js
CHANGED
|
@@ -15,10 +15,10 @@ export default class TrustArc extends AutoConsentBase {
|
|
|
15
15
|
tab.frame.url.startsWith("https://consent-pref.trustarc.com/?")) {
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
|
-
return tab.elementExists("#truste-show-consent");
|
|
18
|
+
return tab.elementExists("#truste-show-consent,#truste-consent-track");
|
|
19
19
|
}
|
|
20
20
|
async detectPopup(tab) {
|
|
21
|
-
return ((await tab.elementsAreVisible("#truste-consent-content,#trustarc-banner-overlay")) ||
|
|
21
|
+
return ((await tab.elementsAreVisible("#truste-consent-content,.truste-consent-content,#trustarc-banner-overlay")) ||
|
|
22
22
|
(tab.frame &&
|
|
23
23
|
(await tab.waitForElement("#defaultpreferencemanager", 5000, tab.frame.id))));
|
|
24
24
|
}
|
package/lib/cmps/trustarc.ts
CHANGED
|
@@ -23,12 +23,12 @@ export default class TrustArc extends AutoConsentBase {
|
|
|
23
23
|
) {
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
26
|
-
return tab.elementExists("#truste-show-consent");
|
|
26
|
+
return tab.elementExists("#truste-show-consent,#truste-consent-track");
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
async detectPopup(tab: TabActor) {
|
|
30
30
|
return (
|
|
31
|
-
(await tab.elementsAreVisible("#truste-consent-content,#trustarc-banner-overlay")) ||
|
|
31
|
+
(await tab.elementsAreVisible("#truste-consent-content,.truste-consent-content,#trustarc-banner-overlay")) ||
|
|
32
32
|
(tab.frame &&
|
|
33
33
|
(await tab.waitForElement(
|
|
34
34
|
"#defaultpreferencemanager",
|
package/lib/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const enableLogs = false; // change this to enable debug logs
|
package/lib/config.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const enableLogs = false; // change this to enable debug logs
|
package/lib/detector.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { enableLogs } from './config';
|
|
1
2
|
export default async function detectDialog(tab, retries, rules) {
|
|
2
3
|
let breakEarly = false;
|
|
3
4
|
const found = await new Promise(async (resolve) => {
|
|
4
5
|
let earlyReturn = false;
|
|
6
|
+
enableLogs && console.log(`${new Date()} [${tab.id}] Detecting CMPs (${rules.length} rules)`);
|
|
5
7
|
await Promise.all(rules.map(async (r, index) => {
|
|
6
8
|
try {
|
|
7
9
|
if (await r.detectCmp(tab)) {
|
|
8
10
|
earlyReturn = true;
|
|
11
|
+
enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
|
|
9
12
|
resolve(index);
|
|
10
13
|
}
|
|
11
14
|
}
|
|
@@ -17,6 +20,7 @@ export default async function detectDialog(tab, retries, rules) {
|
|
|
17
20
|
resolve(-1);
|
|
18
21
|
}
|
|
19
22
|
});
|
|
23
|
+
enableLogs && console.log(`${new Date()} CMP detection finished in [${tab.id}], found rule #${found}`);
|
|
20
24
|
if (found === -1 && retries > 0 && !breakEarly) {
|
|
21
25
|
return new Promise((resolve) => {
|
|
22
26
|
setTimeout(async () => {
|
package/lib/detector.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { enableLogs } from './config';
|
|
1
2
|
import { AutoCMP, TabActor } from './types';
|
|
2
3
|
|
|
3
4
|
export default async function detectDialog(tab: TabActor, retries: number, rules: AutoCMP[]): Promise<AutoCMP> {
|
|
4
5
|
let breakEarly = false;
|
|
5
6
|
const found: number = await new Promise(async (resolve) => {
|
|
6
7
|
let earlyReturn = false;
|
|
8
|
+
enableLogs && console.log(`${new Date()} [${tab.id}] Detecting CMPs (${rules.length} rules)`);
|
|
7
9
|
await Promise.all(rules.map(async (r, index) => {
|
|
8
10
|
try {
|
|
9
11
|
if (await r.detectCmp(tab)) {
|
|
10
12
|
earlyReturn = true;
|
|
13
|
+
enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
|
|
11
14
|
resolve(index)
|
|
12
15
|
}
|
|
13
16
|
} catch (e) {
|
|
@@ -18,6 +21,7 @@ export default async function detectDialog(tab: TabActor, retries: number, rules
|
|
|
18
21
|
resolve(-1)
|
|
19
22
|
}
|
|
20
23
|
})
|
|
24
|
+
enableLogs && console.log(`${new Date()} CMP detection finished in [${tab.id}], found rule #${found}`);
|
|
21
25
|
if (found === -1 && retries > 0 && !breakEarly) {
|
|
22
26
|
return new Promise((resolve) => {
|
|
23
27
|
setTimeout(async () => {
|
package/lib/hider.js
CHANGED
package/lib/hider.ts
CHANGED
package/lib/messages.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type ContentScriptMessage =
|
|
|
9
9
|
| MatchesMessage
|
|
10
10
|
| ActionMessage;
|
|
11
11
|
|
|
12
|
+
export type HideMethod = 'display' | 'opacity';
|
|
13
|
+
|
|
12
14
|
type ClickMessage = {
|
|
13
15
|
type: "click";
|
|
14
16
|
selector: string;
|
|
@@ -40,6 +42,7 @@ type EvalMessage = {
|
|
|
40
42
|
type HideMessage = {
|
|
41
43
|
type: "hide";
|
|
42
44
|
selectors: string[];
|
|
45
|
+
method: HideMethod;
|
|
43
46
|
};
|
|
44
47
|
|
|
45
48
|
type UndoHideMessage = {
|
package/lib/node.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import Tab from './puppet/tab';
|
|
2
2
|
import detectDialog from './detector';
|
|
3
3
|
import TabConsent from './tabwrapper';
|
|
4
|
+
import prehideElements from './hider';
|
|
4
5
|
export * from './index';
|
|
5
6
|
export { ConsentOMaticCMP } from './consentomatic/index';
|
|
6
7
|
export { Tab, detectDialog, TabConsent, };
|
|
7
|
-
export function attachToPage(page, url, rules, retries = 1) {
|
|
8
|
-
const frames = {
|
|
8
|
+
export function attachToPage(page, url, rules, retries = 1, prehide = true) {
|
|
9
|
+
const frames = {
|
|
10
|
+
0: page.mainFrame(),
|
|
11
|
+
};
|
|
9
12
|
const tab = new Tab(page, url, frames);
|
|
10
|
-
frames[0] = page.mainFrame();
|
|
11
13
|
async function onFrame(frame) {
|
|
12
14
|
const allFrames = await page.frames();
|
|
13
15
|
allFrames.forEach((frame, frameId) => {
|
|
@@ -26,5 +28,8 @@ export function attachToPage(page, url, rules, retries = 1) {
|
|
|
26
28
|
}
|
|
27
29
|
page.on('framenavigated', onFrame);
|
|
28
30
|
page.frames().forEach(onFrame);
|
|
31
|
+
if (prehide) {
|
|
32
|
+
prehideElements(tab, rules);
|
|
33
|
+
}
|
|
29
34
|
return new TabConsent(tab, detectDialog(tab, retries, rules));
|
|
30
35
|
}
|
package/lib/node.ts
CHANGED
|
@@ -2,6 +2,7 @@ import Tab from './puppet/tab';
|
|
|
2
2
|
import detectDialog from './detector';
|
|
3
3
|
import TabConsent from './tabwrapper';
|
|
4
4
|
import { AutoCMP } from './types';
|
|
5
|
+
import prehideElements from './hider';
|
|
5
6
|
|
|
6
7
|
export * from './index';
|
|
7
8
|
export { ConsentOMaticCMP } from './consentomatic/index';
|
|
@@ -11,11 +12,12 @@ export {
|
|
|
11
12
|
TabConsent,
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export function attachToPage(page: any, url: string, rules: AutoCMP[], retries = 1) {
|
|
15
|
-
const frames: { [id: number]: any } = {
|
|
15
|
+
export function attachToPage(page: any, url: string, rules: AutoCMP[], retries = 1, prehide = true) {
|
|
16
|
+
const frames: { [id: number]: any } = {
|
|
17
|
+
0: page.mainFrame(),
|
|
18
|
+
};
|
|
16
19
|
const tab = new Tab(page, url, frames);
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
|
|
19
21
|
async function onFrame(frame: any) {
|
|
20
22
|
const allFrames: any[] = await page.frames();
|
|
21
23
|
allFrames.forEach((frame, frameId) => {
|
|
@@ -34,5 +36,8 @@ export function attachToPage(page: any, url: string, rules: AutoCMP[], retries =
|
|
|
34
36
|
}
|
|
35
37
|
page.on('framenavigated', onFrame);
|
|
36
38
|
page.frames().forEach(onFrame);
|
|
37
|
-
|
|
39
|
+
if (prehide) {
|
|
40
|
+
prehideElements(tab, rules);
|
|
41
|
+
}
|
|
42
|
+
return new TabConsent(tab, detectDialog(tab, retries, rules));
|
|
38
43
|
}
|