@duckduckgo/autoconsent 1.0.7 → 2.1.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.
Files changed (187) hide show
  1. package/.eslintrc.cjs +14 -0
  2. package/.vscode/.idea/.vscode.iml +9 -0
  3. package/.vscode/.idea/modules.xml +8 -0
  4. package/.vscode/.idea/workspace.xml +28 -0
  5. package/.vscode/settings.json +7 -0
  6. package/Jenkinsfile +68 -39
  7. package/api.md +104 -0
  8. package/dist/addon-firefox/background.bundle.js +1 -0
  9. package/dist/addon-firefox/content.bundle.js +1 -0
  10. package/dist/addon-firefox/icons/cog.png +0 -0
  11. package/dist/addon-firefox/icons/cookie-idle.png +0 -0
  12. package/dist/addon-firefox/icons/cookie.png +0 -0
  13. package/dist/addon-firefox/icons/party.png +0 -0
  14. package/dist/addon-firefox/icons/tick.png +0 -0
  15. package/dist/addon-firefox/icons/verified.png +0 -0
  16. package/dist/addon-firefox/rules.json +4167 -0
  17. package/dist/addon-mv3/background.bundle.js +1 -0
  18. package/dist/addon-mv3/content.bundle.js +1 -0
  19. package/dist/addon-mv3/icons/cog.png +0 -0
  20. package/dist/addon-mv3/icons/cookie-idle.png +0 -0
  21. package/dist/addon-mv3/icons/cookie.png +0 -0
  22. package/dist/addon-mv3/icons/party.png +0 -0
  23. package/dist/addon-mv3/icons/tick.png +0 -0
  24. package/dist/addon-mv3/icons/verified.png +0 -0
  25. package/dist/addon-mv3/rules.json +4167 -0
  26. package/dist/autoconsent.cjs.js +1 -1383
  27. package/dist/autoconsent.esm.js +1 -1375
  28. package/dist/autoconsent.playwright.js +1 -0
  29. package/lib/cmps/all.ts +15 -10
  30. package/lib/cmps/base.ts +95 -90
  31. package/lib/cmps/consentmanager.ts +31 -19
  32. package/lib/cmps/consentomatic.ts +89 -0
  33. package/lib/cmps/cookiebot.ts +62 -53
  34. package/lib/cmps/evidon.ts +29 -18
  35. package/lib/cmps/onetrust.ts +32 -20
  36. package/lib/cmps/sourcepoint-frame.ts +104 -0
  37. package/lib/cmps/sourcepoint-top.ts +47 -0
  38. package/lib/cmps/trustarc-frame.ts +115 -0
  39. package/lib/cmps/trustarc-top.ts +97 -0
  40. package/lib/consentomatic/index.ts +233 -70
  41. package/lib/{web/consentomatic → consentomatic}/tools.ts +0 -0
  42. package/lib/eval-handler.ts +58 -0
  43. package/lib/index.ts +0 -2
  44. package/lib/messages.ts +100 -0
  45. package/lib/rule-executors.ts +108 -0
  46. package/lib/rules.ts +82 -0
  47. package/lib/types.ts +35 -0
  48. package/lib/utils.ts +64 -0
  49. package/lib/web.ts +288 -74
  50. package/package.json +20 -16
  51. package/playwright/content.ts +21 -0
  52. package/playwright/runner.ts +162 -0
  53. package/playwright.config.ts +7 -0
  54. package/readme.md +61 -47
  55. package/rollup.config.js +30 -16
  56. package/rules/autoconsent/192.json +17 -0
  57. package/rules/autoconsent/ausopen.json +8 -0
  58. package/rules/autoconsent/baden-wuerttemberg-de.json +7 -3
  59. package/rules/autoconsent/bing.json +14 -0
  60. package/rules/autoconsent/bundesregierung-de.json +5 -1
  61. package/rules/autoconsent/cc-banner.json +0 -1
  62. package/rules/autoconsent/cookie-law-info.json +1 -1
  63. package/rules/autoconsent/cookie-notice.json +1 -2
  64. package/rules/autoconsent/cookieconsent.json +5 -6
  65. package/rules/autoconsent/destatis-de.json +2 -2
  66. package/rules/autoconsent/dunelm.json +18 -0
  67. package/rules/autoconsent/etsy.json +4 -3
  68. package/rules/autoconsent/eu-cookie-compliance.json +0 -1
  69. package/rules/autoconsent/gov-uk.json +10 -0
  70. package/rules/autoconsent/hl-co-uk.json +8 -9
  71. package/rules/autoconsent/johnlewis.json +5 -2
  72. package/rules/autoconsent/marksandspencer.json +8 -0
  73. package/rules/autoconsent/mediamarkt-de.json +1 -1
  74. package/rules/autoconsent/microsoft.json +1 -1
  75. package/rules/autoconsent/notice-cookie.json +0 -1
  76. package/rules/autoconsent/osano.json +4 -2
  77. package/rules/autoconsent/{paypal-de.json → paypal.json} +6 -2
  78. package/rules/autoconsent/snigel.json +2 -1
  79. package/rules/autoconsent/tealium.json +4 -5
  80. package/rules/autoconsent/thefreedictionary.json +1 -1
  81. package/rules/autoconsent/uswitch.json +8 -0
  82. package/rules/autoconsent/waitrose.json +28 -0
  83. package/rules/autoconsent/wetransfer.json +7 -0
  84. package/rules/rules.json +345 -45
  85. package/tests/192.spec.ts +7 -0
  86. package/tests/arzt-auskunft.spec.ts +1 -1
  87. package/tests/asus.spec.ts +1 -1
  88. package/tests/ausopen.spec.ts +7 -0
  89. package/tests/aws.amazon.spec.ts +1 -1
  90. package/tests/baden-wuerttemberg.spec.ts +1 -1
  91. package/tests/borlabs.spec.ts +1 -1
  92. package/tests/bundesregierung.spec.ts +5 -2
  93. package/tests/ccbanner.spec.ts +1 -1
  94. package/tests/consentmanager.spec.ts +3 -3
  95. package/tests/cookiebot.spec.ts +8 -1
  96. package/tests/cookieconsent.spec.ts +1 -1
  97. package/tests/cookielawinfo.spec.ts +1 -1
  98. package/tests/cookienotice.spec.ts +1 -1
  99. package/tests/corona-in-zahlen.spec.ts +1 -1
  100. package/tests/deepl.spec.ts +1 -1
  101. package/tests/destatis.spec.ts +1 -1
  102. package/tests/didomi.spec.ts +7 -3
  103. package/tests/drupal.spec.ts +8 -0
  104. package/tests/dunelm.spec.ts +7 -0
  105. package/tests/etsy.spec.ts +1 -1
  106. package/tests/eu-cookie-compliance-banner.spec.ts +1 -1
  107. package/tests/evidon.spec.ts +7 -2
  108. package/tests/fundingchoices.spec.ts +2 -1
  109. package/tests/gov-uk.spec.ts +9 -0
  110. package/tests/hl-co-uk.spec.ts +1 -1
  111. package/tests/hubspot.spec.ts +1 -1
  112. package/tests/ionos.spec.ts +1 -1
  113. package/tests/johnlewis.spec.ts +2 -2
  114. package/tests/klaro.spec.ts +1 -1
  115. package/tests/marksandspencer.spec.ts +7 -0
  116. package/tests/mediamarkt.spec.ts +1 -1
  117. package/tests/metoffice-gov-uk.spec.ts +1 -1
  118. package/tests/microsoft.spec.ts +1 -1
  119. package/tests/moneysavingexpert.spec.ts +1 -1
  120. package/tests/motor-talk.spec.ts +1 -1
  121. package/tests/national-lottery.spec.ts +1 -1
  122. package/tests/netflix.spec.ts +1 -1
  123. package/tests/nhs.spec.ts +1 -1
  124. package/tests/notice-cookie.spec.ts +1 -1
  125. package/tests/obi.spec.ts +1 -1
  126. package/tests/oil.spec.ts +2 -2
  127. package/tests/onetrust.spec.ts +27 -2
  128. package/tests/osano.spec.ts +1 -1
  129. package/tests/otto.spec.ts +1 -1
  130. package/tests/paypal.spec.ts +8 -6
  131. package/tests/quantcast.spec.ts +5 -2
  132. package/tests/snigel.spec.ts +1 -1
  133. package/tests/sourcepoint.spec.ts +8 -8
  134. package/tests/springer.spec.ts +2 -2
  135. package/tests/steampowered.spec.ts +1 -1
  136. package/tests/tealium.spec.ts +1 -1
  137. package/tests/testcmp.spec.ts +1 -1
  138. package/tests/thalia.spec.ts +1 -1
  139. package/tests/thefreedictionary.spec.ts +1 -1
  140. package/tests/trustarc.spec.ts +26 -3
  141. package/tests/usercentrics-1.spec.ts +1 -1
  142. package/tests/uswitch.spec.ts +7 -0
  143. package/tests/vodafone.spec.ts +1 -1
  144. package/tests/waitrose.spec.ts +7 -0
  145. package/tests/wetransfer.spec.ts +7 -0
  146. package/tests/wordpressgdpr.spec.ts +2 -2
  147. package/tests/xing.spec.ts +1 -1
  148. package/tsconfig.json +2 -2
  149. package/update_version.js +10 -6
  150. package/.eslintrc +0 -12
  151. package/cosmetics/rules.json +0 -110
  152. package/dist/autoconsent.puppet.js +0 -1074
  153. package/lib/cmps/all.js +0 -19
  154. package/lib/cmps/base.js +0 -174
  155. package/lib/cmps/consentmanager.js +0 -31
  156. package/lib/cmps/cookiebot.js +0 -73
  157. package/lib/cmps/evidon.js +0 -26
  158. package/lib/cmps/onetrust.js +0 -34
  159. package/lib/cmps/sourcepoint.js +0 -82
  160. package/lib/cmps/sourcepoint.ts +0 -95
  161. package/lib/cmps/trustarc.js +0 -106
  162. package/lib/cmps/trustarc.ts +0 -147
  163. package/lib/config.js +0 -1
  164. package/lib/consentomatic/index.js +0 -52
  165. package/lib/detector.js +0 -33
  166. package/lib/detector.ts +0 -34
  167. package/lib/hider.js +0 -13
  168. package/lib/hider.ts +0 -16
  169. package/lib/index.js +0 -4
  170. package/lib/messages.d.ts +0 -61
  171. package/lib/node.js +0 -35
  172. package/lib/node.ts +0 -43
  173. package/lib/puppet/tab.js +0 -121
  174. package/lib/puppet/tab.ts +0 -146
  175. package/lib/rules.d.ts +0 -80
  176. package/lib/tabwrapper.js +0 -67
  177. package/lib/tabwrapper.ts +0 -74
  178. package/lib/types.d.ts +0 -61
  179. package/lib/web/consentomatic/index.ts +0 -249
  180. package/lib/web/content-utils.js +0 -29
  181. package/lib/web/content-utils.ts +0 -31
  182. package/lib/web/content.js +0 -89
  183. package/lib/web/content.ts +0 -80
  184. package/lib/web/tab.js +0 -112
  185. package/lib/web/tab.ts +0 -178
  186. package/lib/web.js +0 -95
  187. package/tests/runner.ts +0 -61
@@ -0,0 +1,89 @@
1
+ import { AutoCMP } from "../types";
2
+ import { executeAction, matches } from "../consentomatic";
3
+ import { RunContext } from "../rules";
4
+ import { defaultRunContext } from "./base";
5
+
6
+ export type DetectorConfig = {
7
+ presentMatcher: any;
8
+ showingMatcher: any;
9
+ };
10
+ export type MethodConfig = {
11
+ action?: any;
12
+ name: string;
13
+ };
14
+
15
+ export type ConsentOMaticConfig = {
16
+ detectors: DetectorConfig[];
17
+ methods: MethodConfig[];
18
+ };
19
+
20
+ export class ConsentOMaticCMP implements AutoCMP {
21
+ methods = new Map<string, any>();
22
+ hasSelfTest: boolean;
23
+ runContext: RunContext = defaultRunContext;
24
+
25
+ constructor(public name: string, public config: ConsentOMaticConfig) {
26
+ config.methods.forEach(methodConfig => {
27
+ if (methodConfig.action) {
28
+ this.methods.set(methodConfig.name, methodConfig.action);
29
+ }
30
+ });
31
+ this.hasSelfTest = false;
32
+ }
33
+
34
+ get isIntermediate(): boolean {
35
+ return false; // TODO: support UTILITY rules
36
+ }
37
+
38
+ checkRunContext(): boolean {
39
+ return true;
40
+ }
41
+
42
+ async detectCmp(): Promise<boolean> {
43
+ const matchResults = this.config.detectors.map(detectorConfig =>
44
+ matches(detectorConfig.presentMatcher)
45
+ )
46
+ return matchResults.some(r => !!r);
47
+ }
48
+
49
+ async detectPopup(): Promise<boolean> {
50
+ const matchResults = this.config.detectors.map(detectorConfig =>
51
+ matches(detectorConfig.showingMatcher)
52
+ )
53
+ return matchResults.some(r => !!r);
54
+ }
55
+
56
+ async executeAction(method: string, param?: any) {
57
+ if (this.methods.has(method)) {
58
+ return executeAction(this.methods.get(method), param);
59
+ }
60
+ return true;
61
+ }
62
+
63
+ async optOut(): Promise<boolean> {
64
+ await this.executeAction("HIDE_CMP");
65
+ await this.executeAction("OPEN_OPTIONS");
66
+ await this.executeAction("HIDE_CMP");
67
+ await this.executeAction("DO_CONSENT", []);
68
+ await this.executeAction("SAVE_CONSENT");
69
+ return true;
70
+ }
71
+
72
+ async optIn(): Promise<boolean> {
73
+ await this.executeAction("HIDE_CMP");
74
+ await this.executeAction("OPEN_OPTIONS");
75
+ await this.executeAction("HIDE_CMP");
76
+ await this.executeAction("DO_CONSENT", ['D', 'A', 'B', 'E', 'F', 'X']);
77
+ await this.executeAction("SAVE_CONSENT");
78
+ return true;
79
+ }
80
+ async openCmp(): Promise<boolean> {
81
+ await this.executeAction("HIDE_CMP");
82
+ await this.executeAction("OPEN_OPTIONS");
83
+ return true;
84
+ }
85
+
86
+ async test(): Promise<boolean> {
87
+ return true;
88
+ }
89
+ }
@@ -1,81 +1,90 @@
1
- import AutoConsentBase from './base';
2
- import { TabActor } from '../types';
1
+ import { click, doEval, elementExists, wait, waitForElement } from '../rule-executors';
2
+ import AutoConsentCMPBase from './base';
3
3
 
4
- export default class Cookiebot extends AutoConsentBase {
4
+ export default class Cookiebot extends AutoConsentCMPBase {
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');
10
10
  }
11
11
 
12
- async detectCmp(tab: TabActor) {
13
- try {
14
- return await tab.eval('typeof window.CookieConsent === "object" && typeof window.CookieConsent.name === "string"');
15
- } catch (e) {
16
- return false;
17
- }
12
+ get hasSelfTest(): boolean {
13
+ return true;
18
14
  }
19
15
 
20
- detectPopup(tab: TabActor) {
21
- return tab.elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner');
16
+ get isIntermediate(): boolean {
17
+ return false;
22
18
  }
23
19
 
24
- async optOut(tab: TabActor) {
25
- if (await tab.elementExists('.cookie-alert-extended-detail-link')) {
26
- await tab.clickElement('.cookie-alert-extended-detail-link');
27
- await tab.waitForElement('.cookie-alert-configuration', 1000);
28
- await tab.clickElements('.cookie-alert-configuration-input:checked');
29
- return tab.clickElement('.cookie-alert-extended-button-secondary');
30
- }
31
- if (await tab.elementExists('#dtcookie-container')) {
32
- return tab.clickElement('.h-dtcookie-decline');
33
- }
34
- if (await tab.elementExists('.cookiebot__button--settings')) {
35
- await tab.clickElement('.cookiebot__button--settings');
36
- }
37
- if (await tab.elementsAreVisible('#CybotCookiebotDialogBodyButtonDecline', 'all')) {
38
- return await tab.clickElement('#CybotCookiebotDialogBodyButtonDecline');
20
+ async detectCmp() {
21
+ return elementExists('#CybotCookiebotDialogBodyLevelButtonPreferences');
22
+ }
23
+
24
+ async detectPopup() {
25
+ return elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
26
+ }
27
+
28
+ async optOut() {
29
+ if (click('.cookie-alert-extended-detail-link')) {
30
+ await waitForElement('.cookie-alert-configuration', 2000);
31
+ click('.cookie-alert-configuration-input:checked', true);
32
+ click('.cookie-alert-extended-button-secondary');
33
+ return true;
39
34
  }
40
- if (await tab.elementExists('.cookiebanner__link--details')) {
41
- await tab.clickElement('.cookiebanner__link--details')
35
+
36
+ if (elementExists('#dtcookie-container')) {
37
+ return click('.h-dtcookie-decline');
42
38
  }
43
- await tab.clickElements('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled');
44
- if (await tab.elementExists('#CybotCookiebotDialogBodyButtonDecline')) {
45
- await tab.clickElement('#CybotCookiebotDialogBodyButtonDecline');
39
+
40
+ if (click('.cookiebot__button--settings')) {
41
+ return true;
46
42
  }
47
- if (await tab.elementExists('input[id^=CybotCookiebotDialogBodyLevelButton]:checked')) {
48
- await tab.clickElements('input[id^=CybotCookiebotDialogBodyLevelButton]:checked')
43
+
44
+ if (click('#CybotCookiebotDialogBodyButtonDecline')) {
45
+ return true;
49
46
  }
50
- if (await tab.elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
51
- await tab.clickElement('#CybotCookiebotDialogBodyButtonAcceptSelected');
47
+
48
+ click('.cookiebanner__link--details');
49
+
50
+ click('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled', true);
51
+
52
+ click('#CybotCookiebotDialogBodyButtonDecline');
53
+
54
+ click('input[id^=CybotCookiebotDialogBodyLevelButton]:checked', true);
55
+
56
+ if (elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
57
+ click('#CybotCookiebotDialogBodyButtonAcceptSelected');
52
58
  } else {
53
- await tab.clickElements('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection');
59
+ click('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection', true);
54
60
  }
61
+
55
62
  // some sites have custom submit buttons with no obvious selectors. In this case we just call the submitConsent API.
56
- if (await tab.eval('CookieConsent.hasResponse !== true')) {
57
- await tab.eval('Cookiebot.dialog.submitConsent() || true');
58
- await tab.wait(500);
63
+ if (await doEval('window.CookieConsent.hasResponse !== true')) {
64
+ await doEval('window.Cookiebot.dialog.submitConsent()');
65
+ await wait(500);
59
66
  }
60
- return true;
61
- }
62
67
 
63
- async optIn(tab: TabActor) {
64
- if (await tab.elementExists('#dtcookie-container')) {
65
- return tab.clickElement('.h-dtcookie-accept');
68
+ // site with 3rd confirm settings modal
69
+ if (elementExists('#cb-confirmedSettings')) {
70
+ await doEval('endCookieProcess()');
66
71
  }
67
- await tab.clickElements('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled');
68
- await tab.clickElement('#CybotCookiebotDialogBodyLevelButtonAccept');
69
- await tab.clickElement('#CybotCookiebotDialogBodyButtonAccept');
72
+
70
73
  return true;
71
74
  }
72
75
 
73
- async openCmp(tab: TabActor) {
74
- await tab.eval('CookieConsent.renew() || true');
75
- return tab.waitForElement('#CybotCookiebotDialog', 10000);
76
+ async optIn() {
77
+ if (elementExists('#dtcookie-container')) {
78
+ return click('.h-dtcookie-accept');
79
+ }
80
+
81
+ click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
82
+ click('#CybotCookiebotDialogBodyLevelButtonAccept');
83
+ click('#CybotCookiebotDialogBodyButtonAccept');
84
+ return true;
76
85
  }
77
86
 
78
- async test(tab: TabActor) {
79
- return tab.eval('CookieConsent.declined === true');
87
+ async test() {
88
+ return doEval('window.CookieConsent.declined === true');
80
89
  }
81
90
  }
@@ -1,32 +1,43 @@
1
- import AutoConsentBase from "./base";
2
- import { TabActor } from "../types";
1
+ import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
2
+ import { getStyleElement, hideElements } from "../utils";
3
+ import AutoConsentCMPBase from "./base";
3
4
 
4
- // Note: JS API is also available:
5
- // https://help.consentmanager.net/books/cmp/page/javascript-api
6
- export default class Evidon extends AutoConsentBase {
5
+ export default class Evidon extends AutoConsentCMPBase {
7
6
  constructor() {
8
7
  super("Evidon");
9
8
  }
10
9
 
11
- detectCmp(tab: TabActor) {
12
- return tab.elementExists("#_evidon_banner");
10
+ get hasSelfTest(): boolean {
11
+ return false;
13
12
  }
14
13
 
15
- detectPopup(tab: TabActor) {
16
- return tab.elementsAreVisible("#_evidon_banner");
14
+ get isIntermediate(): boolean {
15
+ return false;
17
16
  }
18
17
 
19
- async optOut(tab: TabActor) {
20
- if (await tab.elementExists("#_evidon-decline-button")) {
21
- return tab.clickElement("#_evidon-decline-button");
18
+ async detectCmp() {
19
+ return elementExists("#_evidon_banner");
20
+ }
21
+
22
+ async detectPopup() {
23
+ return elementVisible("#_evidon_banner", 'any');
24
+ }
25
+
26
+ async optOut() {
27
+ if (click("#_evidon-decline-button")) {
28
+ return true;
22
29
  }
23
- tab.hideElements(["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"])
24
- await tab.clickElement("#_evidon-option-button");
25
- await tab.waitForElement("#evidon-prefdiag-overlay", 5000);
26
- return tab.clickElement("#evidon-prefdiag-decline");
30
+
31
+ hideElements(getStyleElement(), ["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"]);
32
+ click("#_evidon-option-button");
33
+
34
+ await waitForElement("#evidon-prefdiag-overlay", 5000);
35
+
36
+ click("#evidon-prefdiag-decline");
37
+ return true;
27
38
  }
28
39
 
29
- async optIn(tab: TabActor) {
30
- return tab.clickElement("#_evidon-accept-button");
40
+ async optIn() {
41
+ return click("#_evidon-accept-button");
31
42
  }
32
43
  }
@@ -1,7 +1,8 @@
1
- import AutoConsentBase, { success, waitFor } from "./base";
2
- import { TabActor } from "../types";
1
+ import { click, doEval, elementExists, elementVisible, wait, waitForElement } from "../rule-executors";
2
+ import { waitFor } from "../utils";
3
+ import AutoConsentCMPBase from "./base";
3
4
 
4
- export default class Onetrust extends AutoConsentBase {
5
+ export default class Onetrust extends AutoConsentCMPBase {
5
6
 
6
7
  prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.optanon-alert-box-wrapper,.onetrust-pc-dark-filter,.js-consent-banner"]
7
8
 
@@ -9,39 +10,50 @@ export default class Onetrust extends AutoConsentBase {
9
10
  super("Onetrust");
10
11
  }
11
12
 
12
- detectCmp(tab: TabActor) {
13
- return tab.elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
13
+ get hasSelfTest(): boolean {
14
+ return true;
15
+ }
16
+
17
+ get isIntermediate(): boolean {
18
+ return false;
14
19
  }
15
20
 
16
- detectPopup(tab: TabActor) {
17
- return tab.elementsAreVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
21
+ async detectCmp() {
22
+ return elementExists("#onetrust-banner-sdk,.optanon-alert-box-wrapper");
18
23
  }
19
24
 
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"));
25
+ async detectPopup() {
26
+ return elementVisible("#onetrust-banner-sdk,.optanon-alert-box-wrapper", 'all');
27
+ }
28
+
29
+ async optOut() {
30
+ if (elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
31
+ click("#onetrust-pc-btn-handler");
23
32
  } else { // otherwise look for a generic "show settings" button
24
- await success(tab.clickElement(".ot-sdk-show-settings,button.js-cookie-settings"));
33
+ click(".ot-sdk-show-settings,button.js-cookie-settings");
25
34
  }
26
35
 
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));
36
+ await waitForElement('#onetrust-consent-sdk', 2000);
37
+ await wait(1000);
38
+ click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked", true); // optional step
39
+
40
+ await waitForElement(".save-preference-btn-handler,.js-consent-save", 2000);
41
+ click(".save-preference-btn-handler,.js-consent-save");
42
+
31
43
  // popup doesn't disappear immediately
32
44
  await waitFor(
33
- async () => !(await tab.elementsAreVisible("#onetrust-banner-sdk")),
45
+ () => elementVisible("#onetrust-banner-sdk", 'none'),
34
46
  10,
35
47
  500
36
48
  );
37
49
  return true;
38
50
  }
39
51
 
40
- async optIn(tab: TabActor) {
41
- return tab.clickElement("onetrust-accept-btn-handler,js-accept-cookies");
52
+ async optIn() {
53
+ return click("#onetrust-accept-btn-handler,.js-accept-cookies");
42
54
  }
43
55
 
44
- async test(tab: TabActor){
45
- return tab.eval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
56
+ async test() {
57
+ return await doEval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
46
58
  }
47
59
  }
@@ -0,0 +1,104 @@
1
+ import { enableLogs } from "../config";
2
+ import { click, elementExists, wait, waitForElement } from "../rule-executors";
3
+ import { RunContext } from "../rules";
4
+ import { waitFor } from "../utils";
5
+ import AutoConsentCMPBase from "./base";
6
+
7
+ export default class SourcePoint extends AutoConsentCMPBase {
8
+
9
+ ccpaMode = false;
10
+
11
+ runContext: RunContext = {
12
+ main: false,
13
+ frame: true,
14
+ }
15
+
16
+ constructor() {
17
+ super("Sourcepoint-frame");
18
+ }
19
+
20
+ get hasSelfTest(): boolean {
21
+ return false; // self-test is done by parent frame
22
+ }
23
+
24
+ get isIntermediate(): boolean {
25
+ return false;
26
+ }
27
+
28
+ async detectCmp() {
29
+ const url = new URL(location.href);
30
+ if (url.searchParams.has('message_id') && url.hostname === 'ccpa-notice.sp-prod.net') {
31
+ this.ccpaMode = true;
32
+ return true;
33
+ }
34
+ return (url.pathname === '/index.html' || url.pathname === '/privacy-manager/index.html')
35
+ && url.searchParams.has('message_id') && url.searchParams.has('requestUUID');
36
+ }
37
+
38
+ async detectPopup() {
39
+ return true;
40
+ }
41
+
42
+ async optIn() {
43
+ await waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL", 2000);
44
+ if (click(".sp_choice_type_11")) {
45
+ return true;
46
+ }
47
+
48
+ if (click('.sp_choice_type_ACCEPT_ALL')) {
49
+ return true;
50
+ }
51
+ return false;
52
+ }
53
+
54
+ isManagerOpen() {
55
+ return (new URL(location.href)).pathname === "/privacy-manager/index.html";
56
+ }
57
+
58
+ async optOut() {
59
+ if (!this.isManagerOpen()) {
60
+ const actionable = await waitForElement('button.sp_choice_type_12,button.sp_choice_type_13');
61
+ if (!actionable) {
62
+ return false;
63
+ }
64
+ if (!elementExists("button.sp_choice_type_12")) {
65
+ // do not sell button
66
+ return click("button.sp_choice_type_13");
67
+ }
68
+
69
+ click("button.sp_choice_type_12");
70
+ await waitFor(
71
+ () => location.pathname === "/privacy-manager/index.html",
72
+ 200,
73
+ 100
74
+ );
75
+ }
76
+
77
+ await waitForElement('.type-modal', 20000);
78
+ // reject all button is offered by some sites
79
+ try {
80
+ const rejectSelector1 = '.sp_choice_type_REJECT_ALL';
81
+ const rejectSelector2 = '.reject-toggle';
82
+ const path = await Promise.race([
83
+ waitForElement(rejectSelector1, 2000).then(success => success ? 0: -1),
84
+ waitForElement(rejectSelector2, 2000).then(success => success ? 1: -1),
85
+ waitForElement('.pm-features', 2000).then(success => success ? 2: -1),
86
+ ]);
87
+ if (path === 0) {
88
+ await wait(1000);
89
+ return click(rejectSelector1);
90
+ } else if (path === 1) {
91
+ return click(rejectSelector2);
92
+ } else if (path === 2) {
93
+ // TODO: check if this is still working
94
+ await waitForElement('.pm-features', 10000);
95
+ click('.checked > span', true);
96
+
97
+ click('.chevron');
98
+ }
99
+ } catch (e) {
100
+ enableLogs && console.warn(e);
101
+ }
102
+ return click('.sp_choice_type_SAVE_AND_EXIT');
103
+ }
104
+ }
@@ -0,0 +1,47 @@
1
+ import { doEval, elementExists, elementVisible } from "../rule-executors";
2
+ import { RunContext } from "../rules";
3
+ import AutoConsentCMPBase from "./base";
4
+
5
+ export default class SourcePoint extends AutoConsentCMPBase {
6
+ prehideSelectors = ["div[id^='sp_message_container_'],.message-overlay"]
7
+
8
+ constructor() {
9
+ super("Sourcepoint-top");
10
+ }
11
+
12
+ runContext: RunContext = {
13
+ main: true,
14
+ frame: false,
15
+ }
16
+
17
+ get hasSelfTest(): boolean {
18
+ return true;
19
+ }
20
+
21
+ get isIntermediate(): boolean {
22
+ return true;
23
+ }
24
+
25
+ async detectCmp() {
26
+ return elementExists("div[id^='sp_message_container_']");
27
+ }
28
+
29
+ async detectPopup() {
30
+ return elementVisible("div[id^='sp_message_container_']", 'all');
31
+ }
32
+
33
+ async optIn() {
34
+ return true;
35
+ }
36
+
37
+ async optOut() {
38
+ return true;
39
+ }
40
+
41
+ async test() {
42
+ await doEval("__tcfapi('getTCData', 2, r => window.__rcsResult = r)");
43
+ return await doEval(
44
+ "Object.values(window.__rcsResult.purpose.consents).every(c => !c)"
45
+ );
46
+ }
47
+ }
@@ -0,0 +1,115 @@
1
+ import { click, elementExists, elementVisible, waitForElement } from "../rule-executors";
2
+ import { RunContext } from "../rules";
3
+ import { waitFor } from "../utils";
4
+ import AutoConsentCMPBase from "./base";
5
+
6
+ export default class TrustArcFrame extends AutoConsentCMPBase {
7
+ constructor() {
8
+ super("TrustArc-frame");
9
+ }
10
+
11
+ runContext: RunContext = {
12
+ main: false,
13
+ frame: true,
14
+ url: "https://consent-pref.trustarc.com/?",
15
+ }
16
+
17
+ get hasSelfTest(): boolean {
18
+ return false;
19
+ }
20
+
21
+ get isIntermediate(): boolean {
22
+ return false;
23
+ }
24
+
25
+ async detectCmp() {
26
+ return true;
27
+ }
28
+
29
+ async detectPopup() {
30
+ // we're already inside the popup
31
+ return elementVisible("#defaultpreferencemanager", 'any') && elementVisible(".mainContent", 'any');
32
+ }
33
+
34
+ async navigateToSettings() {
35
+ // wait for it to load
36
+ await waitFor(
37
+ async () => {
38
+ return (
39
+ elementExists(".shp") ||
40
+ elementVisible(".advance", 'any') ||
41
+ elementExists(".switch span:first-child")
42
+ );
43
+ },
44
+ 10,
45
+ 500
46
+ );
47
+ // splash screen -> hit more information
48
+ if (elementExists(".shp")) {
49
+ click(".shp");
50
+ }
51
+
52
+ await waitForElement(".prefPanel", 5000);
53
+
54
+ // go to advanced settings if not yet shown
55
+ if (elementVisible(".advance", 'any')) {
56
+ click(".advance");
57
+ }
58
+
59
+ // takes a while to load the opt-in/opt-out buttons
60
+ return await waitFor(
61
+ () => elementVisible(".switch span:first-child", 'any'),
62
+ 5,
63
+ 1000
64
+ );
65
+ }
66
+
67
+ async optOut() {
68
+ await waitFor(() => document.readyState === 'complete', 20, 100);
69
+ await waitForElement(".mainContent[aria-hidden=false]", 5000);
70
+
71
+ if (click(".rejectAll")) {
72
+ return true;
73
+ }
74
+
75
+ if (elementExists('.prefPanel')) {
76
+ await waitForElement('.prefPanel[style="visibility: visible;"]', 3000);
77
+ }
78
+
79
+ if (click("#catDetails0")) {
80
+ click(".submit");
81
+ return true;
82
+ }
83
+
84
+ if (click(".required")) {
85
+ return true;
86
+ }
87
+
88
+ await this.navigateToSettings();
89
+
90
+ click(".switch span:nth-child(1):not(.active)", true);
91
+
92
+ click(".submit");
93
+
94
+ // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
95
+ waitForElement("#gwt-debug-close_id", 300000).then(() => {
96
+ click("#gwt-debug-close_id");
97
+ });
98
+
99
+ return true;
100
+ }
101
+
102
+ async optIn() {
103
+ await this.navigateToSettings();
104
+ click(".switch span:nth-child(2)", true);
105
+
106
+ click(".submit");
107
+
108
+ // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
109
+ waitForElement("#gwt-debug-close_id", 300000).then(() => {
110
+ click("#gwt-debug-close_id");
111
+ });
112
+
113
+ return true;
114
+ }
115
+ }