@duckduckgo/autoconsent 1.0.4 → 1.0.7

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.
Files changed (93) hide show
  1. package/dist/autoconsent.cjs.js +97 -30
  2. package/dist/autoconsent.esm.js +97 -30
  3. package/dist/autoconsent.puppet.js +101 -7
  4. package/lib/cmps/all.js +2 -0
  5. package/lib/cmps/all.ts +2 -0
  6. package/lib/cmps/base.js +5 -1
  7. package/lib/cmps/base.ts +5 -1
  8. package/lib/cmps/onetrust.js +34 -0
  9. package/lib/cmps/onetrust.ts +47 -0
  10. package/lib/config.js +1 -0
  11. package/lib/config.ts +1 -0
  12. package/lib/detector.js +4 -0
  13. package/lib/detector.ts +4 -0
  14. package/lib/hider.js +1 -1
  15. package/lib/hider.ts +1 -1
  16. package/lib/messages.d.ts +3 -0
  17. package/lib/node.js +8 -3
  18. package/lib/node.ts +10 -5
  19. package/lib/puppet/tab.js +10 -3
  20. package/lib/puppet/tab.ts +13 -3
  21. package/lib/tabwrapper.js +6 -0
  22. package/lib/tabwrapper.ts +6 -0
  23. package/lib/types.d.ts +2 -2
  24. package/lib/web/content-utils.js +29 -0
  25. package/lib/web/content-utils.ts +31 -0
  26. package/lib/web/content.js +20 -22
  27. package/lib/web/content.ts +19 -22
  28. package/lib/web/tab.js +12 -6
  29. package/lib/web/tab.ts +13 -6
  30. package/lib/web.js +5 -0
  31. package/lib/web.ts +5 -0
  32. package/package.json +1 -1
  33. package/readme.md +1 -1
  34. package/rules/autoconsent/arzt-auskunft-de.json +1 -1
  35. package/rules/autoconsent/aws-amazon.json +1 -1
  36. package/rules/autoconsent/bundesregierung-de.json +1 -1
  37. package/rules/autoconsent/corona-in-zahlen-de.json +1 -1
  38. package/rules/autoconsent/deepl.json +1 -1
  39. package/rules/autoconsent/etsy.json +13 -0
  40. package/rules/autoconsent/hl-co-uk.json +1 -1
  41. package/rules/autoconsent/johnlewis.json +1 -1
  42. package/rules/autoconsent/metoffice-gov-uk.json +1 -1
  43. package/rules/autoconsent/microsoft.json +1 -1
  44. package/rules/autoconsent/moneysavingexpert.json +1 -1
  45. package/rules/autoconsent/national-lottery-co-uk.json +2 -3
  46. package/rules/autoconsent/netflix-de.json +1 -1
  47. package/rules/autoconsent/nhs.json +1 -1
  48. package/rules/autoconsent/steampowered.json +14 -7
  49. package/rules/autoconsent/thefreedictionary.json +1 -1
  50. package/rules/autoconsent/usercentrics-1.json +16 -5
  51. package/rules/autoconsent/vodafone-de.json +12 -9
  52. package/rules/autoconsent/xing.json +2 -2
  53. package/rules/rules.json +73 -73
  54. package/tests/arzt-auskunft.spec.ts +7 -0
  55. package/tests/aws.amazon.spec.ts +7 -0
  56. package/tests/baden-wuerttemberg.spec.ts +7 -0
  57. package/tests/borlabs.spec.ts +7 -0
  58. package/tests/bundesregierung.spec.ts +7 -0
  59. package/tests/consentmanager.spec.ts +2 -1
  60. package/tests/cookiebot.spec.ts +3 -3
  61. package/tests/cookieconsent.spec.ts +2 -1
  62. package/tests/cookielawinfo.spec.ts +0 -1
  63. package/tests/corona-in-zahlen.spec.ts +7 -0
  64. package/tests/deepl.spec.ts +7 -0
  65. package/tests/destatis.spec.ts +7 -0
  66. package/tests/etsy.spec.ts +7 -0
  67. package/tests/eu-cookie-compliance-banner.spec.ts +0 -1
  68. package/tests/hl-co-uk.spec.ts +7 -0
  69. package/tests/ionos.spec.ts +7 -0
  70. package/tests/johnlewis.spec.ts +7 -0
  71. package/tests/mediamarkt.spec.ts +7 -0
  72. package/tests/metoffice-gov-uk.spec.ts +7 -0
  73. package/tests/microsoft.spec.ts +9 -0
  74. package/tests/moneysavingexpert.spec.ts +7 -0
  75. package/tests/motor-talk.spec.ts +7 -0
  76. package/tests/national-lottery.spec.ts +7 -0
  77. package/tests/netflix.spec.ts +7 -0
  78. package/tests/nhs.spec.ts +7 -0
  79. package/tests/obi.spec.ts +7 -0
  80. package/tests/onetrust.spec.ts +6 -1
  81. package/tests/otto.spec.ts +7 -0
  82. package/tests/paypal.spec.ts +7 -0
  83. package/tests/runner.ts +2 -2
  84. package/tests/snigel.spec.ts +7 -0
  85. package/tests/steampowered.spec.ts +7 -0
  86. package/tests/thalia.spec.ts +7 -0
  87. package/tests/thefreedictionary.spec.ts +7 -0
  88. package/tests/usercentrics-1.spec.ts +9 -0
  89. package/tests/vodafone.spec.ts +7 -0
  90. package/tests/wordpressgdpr.spec.ts +0 -1
  91. package/tests/xing.spec.ts +8 -0
  92. package/rules/autoconsent/onetrust.json +0 -24
  93. package/tests/optanon.spec.ts +0 -10
@@ -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(() => resolve(true), ms);
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,19 @@ 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" || e.style?.display !== "none";
704
+ // check for display: none
705
+ results[i] = false;
706
+ if (e.offsetParent !== null) {
707
+ results[i] = true;
708
+ }
709
+ else {
710
+ const css = window.getComputedStyle(e);
711
+ if (css.position === 'fixed' && css.display !== "none") { // fixed elements may be visible even if the parent is not
712
+ results[i] = true;
713
+ }
714
+ }
675
715
  });
716
+ debug && console.log("[visible?]", message.selector, elem, results);
676
717
  if (results.length === 0) {
677
718
  return false;
678
719
  }
@@ -687,6 +728,7 @@ function handleMessage(message, debug = false) {
687
728
  }
688
729
  else if (message.type === "getAttribute") {
689
730
  const elem = document.querySelector(message.selector);
731
+ debug && console.log("[getAttribute]", message.selector, elem);
690
732
  if (!elem) {
691
733
  return false;
692
734
  }
@@ -694,31 +736,16 @@ function handleMessage(message, debug = false) {
694
736
  }
695
737
  else if (message.type === "eval") {
696
738
  // TODO: chrome support
739
+ debug && console.log("about to [eval]", message.script); // this will not show in Webkit console
697
740
  const result = window.eval(message.script); // eslint-disable-line no-eval
698
- debug && console.log("[eval]", message.script, result);
699
741
  return result;
700
742
  }
701
743
  else if (message.type === "hide") {
702
- const parent = document.head ||
703
- document.getElementsByTagName("head")[0] ||
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;
744
+ debug && console.log("[hide]", message.selectors);
745
+ return hideElementsUtil(message.selectors, message.method);
719
746
  }
720
747
  else if (message.type === "undohide") {
721
- const existingElement = document.querySelector(styleSelector);
748
+ const existingElement = getStyleElementUtil();
722
749
  debug && console.log("[unhide]", !!existingElement);
723
750
  if (existingElement) {
724
751
  existingElement.remove();
@@ -727,9 +754,11 @@ function handleMessage(message, debug = false) {
727
754
  }
728
755
  else if (message.type === "matches") {
729
756
  const matched = matches(message.config);
757
+ debug && console.log("[matches?]", message.config.type, JSON.stringify(message.config), matched);
730
758
  return matched;
731
759
  }
732
760
  else if (message.type === "executeAction") {
761
+ debug && console.log("[executeAction]", message);
733
762
  actionQueue = actionQueue.then(() => executeAction(message.config, message.param));
734
763
  return true;
735
764
  }
@@ -758,10 +787,12 @@ class TabConsent {
758
787
  }
759
788
  async doOptOut() {
760
789
  try {
790
+ enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
761
791
  this.optOutStatus = await this.rule.optOut(this.tab);
762
792
  return this.optOutStatus;
763
793
  }
764
794
  catch (e) {
795
+ console.error('error during opt out', e);
765
796
  this.optOutStatus = e;
766
797
  throw e;
767
798
  }
@@ -806,6 +837,7 @@ async function detectDialog(tab, retries, rules) {
806
837
  try {
807
838
  if (await r.detectCmp(tab)) {
808
839
  earlyReturn = true;
840
+ enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
809
841
  resolve(index);
810
842
  }
811
843
  }
@@ -1146,12 +1178,47 @@ class Evidon extends AutoConsentBase {
1146
1178
  }
1147
1179
  }
1148
1180
 
1181
+ class Onetrust extends AutoConsentBase {
1182
+ constructor() {
1183
+ super("Onetrust");
1184
+ this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
1185
+ }
1186
+ detectCmp(tab) {
1187
+ return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
1188
+ }
1189
+ detectPopup(tab) {
1190
+ return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
1191
+ }
1192
+ async optOut(tab) {
1193
+ if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
1194
+ await success(tab.clickElement("#onetrust-pc-btn-handler"));
1195
+ }
1196
+ else { // otherwise look for a generic "show settings" button
1197
+ await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
1198
+ }
1199
+ await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
1200
+ await success(tab.wait(1000));
1201
+ await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
1202
+ await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
1203
+ // popup doesn't disappear immediately
1204
+ await waitFor(async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")), 10, 500);
1205
+ return true;
1206
+ }
1207
+ async optIn(tab) {
1208
+ return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
1209
+ }
1210
+ async test(tab) {
1211
+ return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
1212
+ }
1213
+ }
1214
+
1149
1215
  const rules = [
1150
1216
  new TrustArc(),
1151
1217
  new Cookiebot(),
1152
1218
  new SourcePoint(),
1153
1219
  new ConsentManager(),
1154
1220
  new Evidon(),
1221
+ new Onetrust(),
1155
1222
  ];
1156
1223
  function createAutoCMP(config) {
1157
1224
  return new AutoConsent(config);
@@ -1223,7 +1290,7 @@ async function prehideElements(tab, rules) {
1223
1290
  }
1224
1291
  return selectorList;
1225
1292
  }, globalHidden);
1226
- await tab.hideElements(selectors);
1293
+ await tab.hideElements(selectors, undefined, 'opacity');
1227
1294
  }
1228
1295
 
1229
1296
  class AutoConsent$1 {
@@ -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(() => resolve(true), ms);
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,19 @@ 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" || e.style?.display !== "none";
700
+ // check for display: none
701
+ results[i] = false;
702
+ if (e.offsetParent !== null) {
703
+ results[i] = true;
704
+ }
705
+ else {
706
+ const css = window.getComputedStyle(e);
707
+ if (css.position === 'fixed' && css.display !== "none") { // fixed elements may be visible even if the parent is not
708
+ results[i] = true;
709
+ }
710
+ }
671
711
  });
712
+ debug && console.log("[visible?]", message.selector, elem, results);
672
713
  if (results.length === 0) {
673
714
  return false;
674
715
  }
@@ -683,6 +724,7 @@ function handleMessage(message, debug = false) {
683
724
  }
684
725
  else if (message.type === "getAttribute") {
685
726
  const elem = document.querySelector(message.selector);
727
+ debug && console.log("[getAttribute]", message.selector, elem);
686
728
  if (!elem) {
687
729
  return false;
688
730
  }
@@ -690,31 +732,16 @@ function handleMessage(message, debug = false) {
690
732
  }
691
733
  else if (message.type === "eval") {
692
734
  // TODO: chrome support
735
+ debug && console.log("about to [eval]", message.script); // this will not show in Webkit console
693
736
  const result = window.eval(message.script); // eslint-disable-line no-eval
694
- debug && console.log("[eval]", message.script, result);
695
737
  return result;
696
738
  }
697
739
  else if (message.type === "hide") {
698
- const parent = document.head ||
699
- document.getElementsByTagName("head")[0] ||
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;
740
+ debug && console.log("[hide]", message.selectors);
741
+ return hideElementsUtil(message.selectors, message.method);
715
742
  }
716
743
  else if (message.type === "undohide") {
717
- const existingElement = document.querySelector(styleSelector);
744
+ const existingElement = getStyleElementUtil();
718
745
  debug && console.log("[unhide]", !!existingElement);
719
746
  if (existingElement) {
720
747
  existingElement.remove();
@@ -723,9 +750,11 @@ function handleMessage(message, debug = false) {
723
750
  }
724
751
  else if (message.type === "matches") {
725
752
  const matched = matches(message.config);
753
+ debug && console.log("[matches?]", message.config.type, JSON.stringify(message.config), matched);
726
754
  return matched;
727
755
  }
728
756
  else if (message.type === "executeAction") {
757
+ debug && console.log("[executeAction]", message);
729
758
  actionQueue = actionQueue.then(() => executeAction(message.config, message.param));
730
759
  return true;
731
760
  }
@@ -754,10 +783,12 @@ class TabConsent {
754
783
  }
755
784
  async doOptOut() {
756
785
  try {
786
+ enableLogs && console.log(`doing opt out ${this.getCMPName()} in tab ${this.tab.id}`);
757
787
  this.optOutStatus = await this.rule.optOut(this.tab);
758
788
  return this.optOutStatus;
759
789
  }
760
790
  catch (e) {
791
+ console.error('error during opt out', e);
761
792
  this.optOutStatus = e;
762
793
  throw e;
763
794
  }
@@ -802,6 +833,7 @@ async function detectDialog(tab, retries, rules) {
802
833
  try {
803
834
  if (await r.detectCmp(tab)) {
804
835
  earlyReturn = true;
836
+ enableLogs && console.log(`Found CMP in [${tab.id}]: ${r.name}`);
805
837
  resolve(index);
806
838
  }
807
839
  }
@@ -1142,12 +1174,47 @@ class Evidon extends AutoConsentBase {
1142
1174
  }
1143
1175
  }
1144
1176
 
1177
+ class Onetrust extends AutoConsentBase {
1178
+ constructor() {
1179
+ super("Onetrust");
1180
+ this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"];
1181
+ }
1182
+ detectCmp(tab) {
1183
+ return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
1184
+ }
1185
+ detectPopup(tab) {
1186
+ return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
1187
+ }
1188
+ async optOut(tab) {
1189
+ if (await tab.elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
1190
+ await success(tab.clickElement("#onetrust-pc-btn-handler"));
1191
+ }
1192
+ else { // otherwise look for a generic "show settings" button
1193
+ await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
1194
+ }
1195
+ await success(tab.waitForElement("#onetrust-consent-sdk", 2000));
1196
+ await success(tab.wait(1000));
1197
+ await tab.clickElements("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked"); // optional step
1198
+ await success(tab.waitForThenClick(".save-preference-btn-handler,.js-consent-save", 1000));
1199
+ // popup doesn't disappear immediately
1200
+ await waitFor(async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")), 10, 500);
1201
+ return true;
1202
+ }
1203
+ async optIn(tab) {
1204
+ return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
1205
+ }
1206
+ async test(tab) {
1207
+ return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
1208
+ }
1209
+ }
1210
+
1145
1211
  const rules = [
1146
1212
  new TrustArc(),
1147
1213
  new Cookiebot(),
1148
1214
  new SourcePoint(),
1149
1215
  new ConsentManager(),
1150
1216
  new Evidon(),
1217
+ new Onetrust(),
1151
1218
  ];
1152
1219
  function createAutoCMP(config) {
1153
1220
  return new AutoConsent(config);
@@ -1219,7 +1286,7 @@ async function prehideElements(tab, rules) {
1219
1286
  }
1220
1287
  return selectorList;
1221
1288
  }, globalHidden);
1222
- await tab.hideElements(selectors);
1289
+ await tab.hideElements(selectors, undefined, 'opacity');
1223
1290
  }
1224
1291
 
1225
1292
  class AutoConsent$1 {