@duckduckgo/autoconsent 1.0.5 → 1.0.6
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 +85 -30
- package/dist/autoconsent.esm.js +85 -30
- package/dist/autoconsent.puppet.js +99 -7
- 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/onetrust.js +32 -0
- package/lib/cmps/onetrust.ts +41 -0
- 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 +10 -22
- package/lib/web/content.ts +10 -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/etsy.json +13 -0
- package/rules/rules.json +38 -48
- package/tests/etsy.spec.ts +7 -0
- package/tests/onetrust.spec.ts +6 -0
- package/tests/runner.ts +1 -1
- package/rules/autoconsent/onetrust.json +0 -24
package/dist/autoconsent.cjs.js
CHANGED
|
@@ -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
|
}
|
|
@@ -181,7 +183,6 @@ class TabActions {
|
|
|
181
183
|
this.id = tabId;
|
|
182
184
|
}
|
|
183
185
|
async elementExists(selector, frameId = 0) {
|
|
184
|
-
console.log(`check for ${selector} in tab ${this.id}, frame ${frameId}`);
|
|
185
186
|
return this.sendContentMessage(this.id, {
|
|
186
187
|
type: "elemExists",
|
|
187
188
|
selector
|
|
@@ -190,7 +191,6 @@ class TabActions {
|
|
|
190
191
|
});
|
|
191
192
|
}
|
|
192
193
|
async clickElement(selector, frameId = 0) {
|
|
193
|
-
console.log(`click element ${selector} in tab ${this.id}`);
|
|
194
194
|
return this.sendContentMessage(this.id, {
|
|
195
195
|
type: "click",
|
|
196
196
|
selector
|
|
@@ -199,7 +199,6 @@ class TabActions {
|
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
async clickElements(selector, frameId = 0) {
|
|
202
|
-
console.log(`click elements ${selector} in tab ${this.id}`);
|
|
203
202
|
return this.sendContentMessage(this.id, {
|
|
204
203
|
type: "click",
|
|
205
204
|
all: true,
|
|
@@ -242,10 +241,11 @@ class TabActions {
|
|
|
242
241
|
}
|
|
243
242
|
return false;
|
|
244
243
|
}
|
|
245
|
-
async hideElements(selectors, frameId = 0) {
|
|
244
|
+
async hideElements(selectors, frameId = 0, method = 'display') {
|
|
246
245
|
return this.sendContentMessage(this.id, {
|
|
247
246
|
type: "hide",
|
|
248
|
-
selectors
|
|
247
|
+
selectors,
|
|
248
|
+
method,
|
|
249
249
|
}, { frameId });
|
|
250
250
|
}
|
|
251
251
|
async undoHideElements(frameId = 0) {
|
|
@@ -261,7 +261,9 @@ class TabActions {
|
|
|
261
261
|
}
|
|
262
262
|
wait(ms) {
|
|
263
263
|
return new Promise(resolve => {
|
|
264
|
-
setTimeout(() =>
|
|
264
|
+
setTimeout(() => {
|
|
265
|
+
resolve(true);
|
|
266
|
+
}, ms);
|
|
265
267
|
});
|
|
266
268
|
}
|
|
267
269
|
matches(matcherConfig) {
|
|
@@ -645,9 +647,37 @@ async function evalAction(config) {
|
|
|
645
647
|
});
|
|
646
648
|
}
|
|
647
649
|
|
|
650
|
+
// get or create a style container for CSS overrides
|
|
651
|
+
function getStyleElementUtil() {
|
|
652
|
+
const styleOverrideElementId = "autoconsent-css-rules";
|
|
653
|
+
const styleSelector = `style#${styleOverrideElementId}`;
|
|
654
|
+
const existingElement = document.querySelector(styleSelector);
|
|
655
|
+
if (existingElement && existingElement instanceof HTMLStyleElement) {
|
|
656
|
+
return existingElement;
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
const parent = document.head ||
|
|
660
|
+
document.getElementsByTagName("head")[0] ||
|
|
661
|
+
document.documentElement;
|
|
662
|
+
const css = document.createElement("style");
|
|
663
|
+
css.id = styleOverrideElementId;
|
|
664
|
+
parent.appendChild(css);
|
|
665
|
+
return css;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
// hide elements with a CSS rule
|
|
669
|
+
function hideElementsUtil(selectors, method) {
|
|
670
|
+
const hidingSnippet = method === 'display' ? `display: none` : `opacity: 0`;
|
|
671
|
+
const rule = `${selectors.join(",")} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
|
|
672
|
+
const styleEl = getStyleElementUtil();
|
|
673
|
+
if (styleEl instanceof HTMLStyleElement) {
|
|
674
|
+
styleEl.innerText += rule;
|
|
675
|
+
return selectors.length > 0;
|
|
676
|
+
}
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
|
|
648
680
|
let actionQueue = Promise.resolve(null);
|
|
649
|
-
const styleOverrideElementId = "autoconsent-css-rules";
|
|
650
|
-
const styleSelector = `style#${styleOverrideElementId}`;
|
|
651
681
|
function handleMessage(message, debug = false) {
|
|
652
682
|
if (message.type === "click") {
|
|
653
683
|
const elem = document.querySelectorAll(message.selector);
|
|
@@ -671,8 +701,9 @@ function handleMessage(message, debug = false) {
|
|
|
671
701
|
const elem = document.querySelectorAll(message.selector);
|
|
672
702
|
const results = new Array(elem.length);
|
|
673
703
|
elem.forEach((e, i) => {
|
|
674
|
-
results[i] = e.offsetParent !== null || window.getComputedStyle(e).display !== "none"
|
|
704
|
+
results[i] = e.offsetParent !== null || window.getComputedStyle(e).display !== "none"; // TODO: handle visibility and z-index?
|
|
675
705
|
});
|
|
706
|
+
debug && console.log("[visible?]", message.selector, elem, results);
|
|
676
707
|
if (results.length === 0) {
|
|
677
708
|
return false;
|
|
678
709
|
}
|
|
@@ -687,6 +718,7 @@ function handleMessage(message, debug = false) {
|
|
|
687
718
|
}
|
|
688
719
|
else if (message.type === "getAttribute") {
|
|
689
720
|
const elem = document.querySelector(message.selector);
|
|
721
|
+
debug && console.log("[getAttribute]", message.selector, elem);
|
|
690
722
|
if (!elem) {
|
|
691
723
|
return false;
|
|
692
724
|
}
|
|
@@ -694,31 +726,16 @@ function handleMessage(message, debug = false) {
|
|
|
694
726
|
}
|
|
695
727
|
else if (message.type === "eval") {
|
|
696
728
|
// TODO: chrome support
|
|
729
|
+
debug && console.log("about to [eval]", message.script); // this will not show in Webkit console
|
|
697
730
|
const result = window.eval(message.script); // eslint-disable-line no-eval
|
|
698
|
-
debug && console.log("[eval]", message.script, result);
|
|
699
731
|
return result;
|
|
700
732
|
}
|
|
701
733
|
else if (message.type === "hide") {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
document.documentElement;
|
|
705
|
-
const rule = `${message.selectors.join(",")} { display: none !important; z-index: -1 !important; } `;
|
|
706
|
-
const existingElement = document.querySelector(styleSelector);
|
|
707
|
-
debug && console.log("[hide]", message.selectors, !!existingElement);
|
|
708
|
-
if (existingElement && existingElement instanceof HTMLStyleElement) {
|
|
709
|
-
existingElement.innerText += rule;
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
const css = document.createElement("style");
|
|
713
|
-
css.type = "text/css";
|
|
714
|
-
css.id = styleOverrideElementId;
|
|
715
|
-
css.appendChild(document.createTextNode(rule));
|
|
716
|
-
parent.appendChild(css);
|
|
717
|
-
}
|
|
718
|
-
return message.selectors.length > 0;
|
|
734
|
+
debug && console.log("[hide]", message.selectors);
|
|
735
|
+
return hideElementsUtil(message.selectors, message.method);
|
|
719
736
|
}
|
|
720
737
|
else if (message.type === "undohide") {
|
|
721
|
-
const existingElement =
|
|
738
|
+
const existingElement = getStyleElementUtil();
|
|
722
739
|
debug && console.log("[unhide]", !!existingElement);
|
|
723
740
|
if (existingElement) {
|
|
724
741
|
existingElement.remove();
|
|
@@ -727,9 +744,11 @@ function handleMessage(message, debug = false) {
|
|
|
727
744
|
}
|
|
728
745
|
else if (message.type === "matches") {
|
|
729
746
|
const matched = matches(message.config);
|
|
747
|
+
debug && console.log("[matches?]", message.config.type, JSON.stringify(message.config), matched);
|
|
730
748
|
return matched;
|
|
731
749
|
}
|
|
732
750
|
else if (message.type === "executeAction") {
|
|
751
|
+
debug && console.log("[executeAction]", message);
|
|
733
752
|
actionQueue = actionQueue.then(() => executeAction(message.config, message.param));
|
|
734
753
|
return true;
|
|
735
754
|
}
|
|
@@ -758,10 +777,12 @@ class TabConsent {
|
|
|
758
777
|
}
|
|
759
778
|
async doOptOut() {
|
|
760
779
|
try {
|
|
780
|
+
enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
|
|
761
781
|
this.optOutStatus = await this.rule.optOut(this.tab);
|
|
762
782
|
return this.optOutStatus;
|
|
763
783
|
}
|
|
764
784
|
catch (e) {
|
|
785
|
+
console.error('error during opt out', e);
|
|
765
786
|
this.optOutStatus = e;
|
|
766
787
|
throw e;
|
|
767
788
|
}
|
|
@@ -806,6 +827,7 @@ async function detectDialog(tab, retries, rules) {
|
|
|
806
827
|
try {
|
|
807
828
|
if (await r.detectCmp(tab)) {
|
|
808
829
|
earlyReturn = true;
|
|
830
|
+
enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
|
|
809
831
|
resolve(index);
|
|
810
832
|
}
|
|
811
833
|
}
|
|
@@ -1146,12 +1168,45 @@ class Evidon extends AutoConsentBase {
|
|
|
1146
1168
|
}
|
|
1147
1169
|
}
|
|
1148
1170
|
|
|
1171
|
+
class Onetrust extends AutoConsentBase {
|
|
1172
|
+
constructor() {
|
|
1173
|
+
super("Onetrust");
|
|
1174
|
+
this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
|
|
1175
|
+
}
|
|
1176
|
+
detectCmp(tab) {
|
|
1177
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
1178
|
+
}
|
|
1179
|
+
detectPopup(tab) {
|
|
1180
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
1181
|
+
}
|
|
1182
|
+
async optOut(tab) {
|
|
1183
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
1184
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
1185
|
+
}
|
|
1186
|
+
else { // otherwise look for a generic "show settings" button
|
|
1187
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
1188
|
+
}
|
|
1189
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
1190
|
+
await success(tab.wait(1000));
|
|
1191
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
1192
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
async optIn(tab) {
|
|
1196
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
1197
|
+
}
|
|
1198
|
+
async test(tab) {
|
|
1199
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1149
1203
|
const rules = [
|
|
1150
1204
|
new TrustArc(),
|
|
1151
1205
|
new Cookiebot(),
|
|
1152
1206
|
new SourcePoint(),
|
|
1153
1207
|
new ConsentManager(),
|
|
1154
1208
|
new Evidon(),
|
|
1209
|
+
new Onetrust(),
|
|
1155
1210
|
];
|
|
1156
1211
|
function createAutoCMP(config) {
|
|
1157
1212
|
return new AutoConsent(config);
|
|
@@ -1223,7 +1278,7 @@ async function prehideElements(tab, rules) {
|
|
|
1223
1278
|
}
|
|
1224
1279
|
return selectorList;
|
|
1225
1280
|
}, globalHidden);
|
|
1226
|
-
await tab.hideElements(selectors);
|
|
1281
|
+
await tab.hideElements(selectors, undefined, 'opacity');
|
|
1227
1282
|
}
|
|
1228
1283
|
|
|
1229
1284
|
class AutoConsent$1 {
|
package/dist/autoconsent.esm.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const enableLogs = false; // change this to enable debug logs
|
|
2
|
+
|
|
1
3
|
/* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
|
|
2
4
|
async function waitFor(predicate, maxTimes, interval) {
|
|
3
5
|
let result = await predicate();
|
|
@@ -13,7 +15,7 @@ async function waitFor(predicate, maxTimes, interval) {
|
|
|
13
15
|
async function success(action) {
|
|
14
16
|
const result = await action;
|
|
15
17
|
if (!result) {
|
|
16
|
-
throw new Error(`Action failed: ${action}`);
|
|
18
|
+
throw new Error(`Action failed: ${action} ${result}`);
|
|
17
19
|
}
|
|
18
20
|
return result;
|
|
19
21
|
}
|
|
@@ -177,7 +179,6 @@ class TabActions {
|
|
|
177
179
|
this.id = tabId;
|
|
178
180
|
}
|
|
179
181
|
async elementExists(selector, frameId = 0) {
|
|
180
|
-
console.log(`check for ${selector} in tab ${this.id}, frame ${frameId}`);
|
|
181
182
|
return this.sendContentMessage(this.id, {
|
|
182
183
|
type: "elemExists",
|
|
183
184
|
selector
|
|
@@ -186,7 +187,6 @@ class TabActions {
|
|
|
186
187
|
});
|
|
187
188
|
}
|
|
188
189
|
async clickElement(selector, frameId = 0) {
|
|
189
|
-
console.log(`click element ${selector} in tab ${this.id}`);
|
|
190
190
|
return this.sendContentMessage(this.id, {
|
|
191
191
|
type: "click",
|
|
192
192
|
selector
|
|
@@ -195,7 +195,6 @@ class TabActions {
|
|
|
195
195
|
});
|
|
196
196
|
}
|
|
197
197
|
async clickElements(selector, frameId = 0) {
|
|
198
|
-
console.log(`click elements ${selector} in tab ${this.id}`);
|
|
199
198
|
return this.sendContentMessage(this.id, {
|
|
200
199
|
type: "click",
|
|
201
200
|
all: true,
|
|
@@ -238,10 +237,11 @@ class TabActions {
|
|
|
238
237
|
}
|
|
239
238
|
return false;
|
|
240
239
|
}
|
|
241
|
-
async hideElements(selectors, frameId = 0) {
|
|
240
|
+
async hideElements(selectors, frameId = 0, method = 'display') {
|
|
242
241
|
return this.sendContentMessage(this.id, {
|
|
243
242
|
type: "hide",
|
|
244
|
-
selectors
|
|
243
|
+
selectors,
|
|
244
|
+
method,
|
|
245
245
|
}, { frameId });
|
|
246
246
|
}
|
|
247
247
|
async undoHideElements(frameId = 0) {
|
|
@@ -257,7 +257,9 @@ class TabActions {
|
|
|
257
257
|
}
|
|
258
258
|
wait(ms) {
|
|
259
259
|
return new Promise(resolve => {
|
|
260
|
-
setTimeout(() =>
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
resolve(true);
|
|
262
|
+
}, ms);
|
|
261
263
|
});
|
|
262
264
|
}
|
|
263
265
|
matches(matcherConfig) {
|
|
@@ -641,9 +643,37 @@ async function evalAction(config) {
|
|
|
641
643
|
});
|
|
642
644
|
}
|
|
643
645
|
|
|
646
|
+
// get or create a style container for CSS overrides
|
|
647
|
+
function getStyleElementUtil() {
|
|
648
|
+
const styleOverrideElementId = "autoconsent-css-rules";
|
|
649
|
+
const styleSelector = `style#${styleOverrideElementId}`;
|
|
650
|
+
const existingElement = document.querySelector(styleSelector);
|
|
651
|
+
if (existingElement && existingElement instanceof HTMLStyleElement) {
|
|
652
|
+
return existingElement;
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
const parent = document.head ||
|
|
656
|
+
document.getElementsByTagName("head")[0] ||
|
|
657
|
+
document.documentElement;
|
|
658
|
+
const css = document.createElement("style");
|
|
659
|
+
css.id = styleOverrideElementId;
|
|
660
|
+
parent.appendChild(css);
|
|
661
|
+
return css;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
// hide elements with a CSS rule
|
|
665
|
+
function hideElementsUtil(selectors, method) {
|
|
666
|
+
const hidingSnippet = method === 'display' ? `display: none` : `opacity: 0`;
|
|
667
|
+
const rule = `${selectors.join(",")} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
|
|
668
|
+
const styleEl = getStyleElementUtil();
|
|
669
|
+
if (styleEl instanceof HTMLStyleElement) {
|
|
670
|
+
styleEl.innerText += rule;
|
|
671
|
+
return selectors.length > 0;
|
|
672
|
+
}
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
|
|
644
676
|
let actionQueue = Promise.resolve(null);
|
|
645
|
-
const styleOverrideElementId = "autoconsent-css-rules";
|
|
646
|
-
const styleSelector = `style#${styleOverrideElementId}`;
|
|
647
677
|
function handleMessage(message, debug = false) {
|
|
648
678
|
if (message.type === "click") {
|
|
649
679
|
const elem = document.querySelectorAll(message.selector);
|
|
@@ -667,8 +697,9 @@ function handleMessage(message, debug = false) {
|
|
|
667
697
|
const elem = document.querySelectorAll(message.selector);
|
|
668
698
|
const results = new Array(elem.length);
|
|
669
699
|
elem.forEach((e, i) => {
|
|
670
|
-
results[i] = e.offsetParent !== null || window.getComputedStyle(e).display !== "none"
|
|
700
|
+
results[i] = e.offsetParent !== null || window.getComputedStyle(e).display !== "none"; // TODO: handle visibility and z-index?
|
|
671
701
|
});
|
|
702
|
+
debug && console.log("[visible?]", message.selector, elem, results);
|
|
672
703
|
if (results.length === 0) {
|
|
673
704
|
return false;
|
|
674
705
|
}
|
|
@@ -683,6 +714,7 @@ function handleMessage(message, debug = false) {
|
|
|
683
714
|
}
|
|
684
715
|
else if (message.type === "getAttribute") {
|
|
685
716
|
const elem = document.querySelector(message.selector);
|
|
717
|
+
debug && console.log("[getAttribute]", message.selector, elem);
|
|
686
718
|
if (!elem) {
|
|
687
719
|
return false;
|
|
688
720
|
}
|
|
@@ -690,31 +722,16 @@ function handleMessage(message, debug = false) {
|
|
|
690
722
|
}
|
|
691
723
|
else if (message.type === "eval") {
|
|
692
724
|
// TODO: chrome support
|
|
725
|
+
debug && console.log("about to [eval]", message.script); // this will not show in Webkit console
|
|
693
726
|
const result = window.eval(message.script); // eslint-disable-line no-eval
|
|
694
|
-
debug && console.log("[eval]", message.script, result);
|
|
695
727
|
return result;
|
|
696
728
|
}
|
|
697
729
|
else if (message.type === "hide") {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
document.documentElement;
|
|
701
|
-
const rule = `${message.selectors.join(",")} { display: none !important; z-index: -1 !important; } `;
|
|
702
|
-
const existingElement = document.querySelector(styleSelector);
|
|
703
|
-
debug && console.log("[hide]", message.selectors, !!existingElement);
|
|
704
|
-
if (existingElement && existingElement instanceof HTMLStyleElement) {
|
|
705
|
-
existingElement.innerText += rule;
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
const css = document.createElement("style");
|
|
709
|
-
css.type = "text/css";
|
|
710
|
-
css.id = styleOverrideElementId;
|
|
711
|
-
css.appendChild(document.createTextNode(rule));
|
|
712
|
-
parent.appendChild(css);
|
|
713
|
-
}
|
|
714
|
-
return message.selectors.length > 0;
|
|
730
|
+
debug && console.log("[hide]", message.selectors);
|
|
731
|
+
return hideElementsUtil(message.selectors, message.method);
|
|
715
732
|
}
|
|
716
733
|
else if (message.type === "undohide") {
|
|
717
|
-
const existingElement =
|
|
734
|
+
const existingElement = getStyleElementUtil();
|
|
718
735
|
debug && console.log("[unhide]", !!existingElement);
|
|
719
736
|
if (existingElement) {
|
|
720
737
|
existingElement.remove();
|
|
@@ -723,9 +740,11 @@ function handleMessage(message, debug = false) {
|
|
|
723
740
|
}
|
|
724
741
|
else if (message.type === "matches") {
|
|
725
742
|
const matched = matches(message.config);
|
|
743
|
+
debug && console.log("[matches?]", message.config.type, JSON.stringify(message.config), matched);
|
|
726
744
|
return matched;
|
|
727
745
|
}
|
|
728
746
|
else if (message.type === "executeAction") {
|
|
747
|
+
debug && console.log("[executeAction]", message);
|
|
729
748
|
actionQueue = actionQueue.then(() => executeAction(message.config, message.param));
|
|
730
749
|
return true;
|
|
731
750
|
}
|
|
@@ -754,10 +773,12 @@ class TabConsent {
|
|
|
754
773
|
}
|
|
755
774
|
async doOptOut() {
|
|
756
775
|
try {
|
|
776
|
+
enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
|
|
757
777
|
this.optOutStatus = await this.rule.optOut(this.tab);
|
|
758
778
|
return this.optOutStatus;
|
|
759
779
|
}
|
|
760
780
|
catch (e) {
|
|
781
|
+
console.error('error during opt out', e);
|
|
761
782
|
this.optOutStatus = e;
|
|
762
783
|
throw e;
|
|
763
784
|
}
|
|
@@ -802,6 +823,7 @@ async function detectDialog(tab, retries, rules) {
|
|
|
802
823
|
try {
|
|
803
824
|
if (await r.detectCmp(tab)) {
|
|
804
825
|
earlyReturn = true;
|
|
826
|
+
enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
|
|
805
827
|
resolve(index);
|
|
806
828
|
}
|
|
807
829
|
}
|
|
@@ -1142,12 +1164,45 @@ class Evidon extends AutoConsentBase {
|
|
|
1142
1164
|
}
|
|
1143
1165
|
}
|
|
1144
1166
|
|
|
1167
|
+
class Onetrust extends AutoConsentBase {
|
|
1168
|
+
constructor() {
|
|
1169
|
+
super("Onetrust");
|
|
1170
|
+
this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
|
|
1171
|
+
}
|
|
1172
|
+
detectCmp(tab) {
|
|
1173
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
1174
|
+
}
|
|
1175
|
+
detectPopup(tab) {
|
|
1176
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
1177
|
+
}
|
|
1178
|
+
async optOut(tab) {
|
|
1179
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
1180
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
1181
|
+
}
|
|
1182
|
+
else { // otherwise look for a generic "show settings" button
|
|
1183
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
1184
|
+
}
|
|
1185
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
1186
|
+
await success(tab.wait(1000));
|
|
1187
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
1188
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
1189
|
+
return true;
|
|
1190
|
+
}
|
|
1191
|
+
async optIn(tab) {
|
|
1192
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
1193
|
+
}
|
|
1194
|
+
async test(tab) {
|
|
1195
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1145
1199
|
const rules = [
|
|
1146
1200
|
new TrustArc(),
|
|
1147
1201
|
new Cookiebot(),
|
|
1148
1202
|
new SourcePoint(),
|
|
1149
1203
|
new ConsentManager(),
|
|
1150
1204
|
new Evidon(),
|
|
1205
|
+
new Onetrust(),
|
|
1151
1206
|
];
|
|
1152
1207
|
function createAutoCMP(config) {
|
|
1153
1208
|
return new AutoConsent(config);
|
|
@@ -1219,7 +1274,7 @@ async function prehideElements(tab, rules) {
|
|
|
1219
1274
|
}
|
|
1220
1275
|
return selectorList;
|
|
1221
1276
|
}, globalHidden);
|
|
1222
|
-
await tab.hideElements(selectors);
|
|
1277
|
+
await tab.hideElements(selectors, undefined, 'opacity');
|
|
1223
1278
|
}
|
|
1224
1279
|
|
|
1225
1280
|
class AutoConsent$1 {
|
|
@@ -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");
|
|
@@ -879,12 +934,45 @@ class Evidon extends AutoConsentBase {
|
|
|
879
934
|
}
|
|
880
935
|
}
|
|
881
936
|
|
|
937
|
+
class Onetrust extends AutoConsentBase {
|
|
938
|
+
constructor() {
|
|
939
|
+
super("Onetrust");
|
|
940
|
+
this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
|
|
941
|
+
}
|
|
942
|
+
detectCmp(tab) {
|
|
943
|
+
return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
944
|
+
}
|
|
945
|
+
detectPopup(tab) {
|
|
946
|
+
return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
|
|
947
|
+
}
|
|
948
|
+
async optOut(tab) {
|
|
949
|
+
if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
|
|
950
|
+
await success(tab.clickElement("#onetrust-pc-btn-handler"));
|
|
951
|
+
}
|
|
952
|
+
else { // otherwise look for a generic "show settings" button
|
|
953
|
+
await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
|
|
954
|
+
}
|
|
955
|
+
await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
|
|
956
|
+
await success(tab.wait(1000));
|
|
957
|
+
await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
|
|
958
|
+
await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
|
|
959
|
+
return true;
|
|
960
|
+
}
|
|
961
|
+
async optIn(tab) {
|
|
962
|
+
return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
|
|
963
|
+
}
|
|
964
|
+
async test(tab) {
|
|
965
|
+
return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
882
969
|
const rules = [
|
|
883
970
|
new TrustArc(),
|
|
884
971
|
new Cookiebot(),
|
|
885
972
|
new SourcePoint(),
|
|
886
973
|
new ConsentManager(),
|
|
887
974
|
new Evidon(),
|
|
975
|
+
new Onetrust(),
|
|
888
976
|
];
|
|
889
977
|
function createAutoCMP(config) {
|
|
890
978
|
return new AutoConsent(config);
|
|
@@ -945,10 +1033,11 @@ class ConsentOMaticCMP {
|
|
|
945
1033
|
}
|
|
946
1034
|
}
|
|
947
1035
|
|
|
948
|
-
function attachToPage(page, url, rules, retries = 1) {
|
|
949
|
-
const frames = {
|
|
1036
|
+
function attachToPage(page, url, rules, retries = 1, prehide = true) {
|
|
1037
|
+
const frames = {
|
|
1038
|
+
0: page.mainFrame(),
|
|
1039
|
+
};
|
|
950
1040
|
const tab = new Tab(page, url, frames);
|
|
951
|
-
frames[0] = page.mainFrame();
|
|
952
1041
|
async function onFrame(frame) {
|
|
953
1042
|
const allFrames = await page.frames();
|
|
954
1043
|
allFrames.forEach((frame, frameId) => {
|
|
@@ -967,6 +1056,9 @@ function attachToPage(page, url, rules, retries = 1) {
|
|
|
967
1056
|
}
|
|
968
1057
|
page.on('framenavigated', onFrame);
|
|
969
1058
|
page.frames().forEach(onFrame);
|
|
1059
|
+
if (prehide) {
|
|
1060
|
+
prehideElements(tab, rules);
|
|
1061
|
+
}
|
|
970
1062
|
return new TabConsent(tab, detectDialog(tab, retries, rules));
|
|
971
1063
|
}
|
|
972
1064
|
|
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);
|