@duckduckgo/autoconsent 3.0.4 → 4.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 (183) hide show
  1. package/.eslintrc +21 -0
  2. package/.github/ISSUE_TEMPLATE/broken-site-issue.md +29 -0
  3. package/.github/dependabot.yml +6 -0
  4. package/.github/workflows/checks.yml +19 -0
  5. package/.prettierrc +4 -0
  6. package/CHANGELOG.md +65 -0
  7. package/Jenkinsfile +4 -4
  8. package/api.md +10 -1
  9. package/dist/addon-firefox/background.bundle.js +312 -1
  10. package/dist/addon-firefox/content.bundle.js +1912 -1
  11. package/dist/addon-firefox/manifest.json +2 -2
  12. package/dist/addon-firefox/rules.json +183 -42
  13. package/dist/addon-mv3/background.bundle.js +312 -1
  14. package/dist/addon-mv3/content.bundle.js +1912 -1
  15. package/dist/addon-mv3/devtools/background.html +10 -0
  16. package/dist/addon-mv3/devtools/bulma.min.css +1 -0
  17. package/dist/addon-mv3/devtools/loader.js +2 -0
  18. package/dist/addon-mv3/devtools/panel.html +88 -0
  19. package/dist/addon-mv3/devtools/panel.js +148 -0
  20. package/dist/addon-mv3/devtools/panel.ts +145 -0
  21. package/dist/addon-mv3/manifest.json +5 -3
  22. package/dist/addon-mv3/popup.bundle.js +173 -1
  23. package/dist/addon-mv3/popup.html +14 -0
  24. package/dist/addon-mv3/rules.json +183 -42
  25. package/dist/autoconsent.cjs.js +1 -1
  26. package/dist/autoconsent.esm.js +1 -1
  27. package/dist/autoconsent.playwright.js +1 -1
  28. package/lib/cmps/airbnb.ts +4 -0
  29. package/lib/cmps/base.ts +8 -0
  30. package/lib/cmps/consentmanager.ts +4 -0
  31. package/lib/cmps/consentomatic.ts +1 -0
  32. package/lib/cmps/conversant.ts +4 -0
  33. package/lib/cmps/cookiebot.ts +4 -0
  34. package/lib/cmps/evidon.ts +4 -0
  35. package/lib/cmps/klaro.ts +4 -0
  36. package/lib/cmps/onetrust.ts +4 -0
  37. package/lib/cmps/sourcepoint-frame.ts +35 -7
  38. package/lib/cmps/tiktok.ts +4 -0
  39. package/lib/cmps/trustarc-frame.ts +4 -0
  40. package/lib/cmps/trustarc-top.ts +4 -0
  41. package/lib/cmps/uniconsent.ts +4 -0
  42. package/lib/consentomatic/index.ts +12 -12
  43. package/lib/consentomatic/tools.ts +13 -13
  44. package/lib/eval-handler.ts +2 -6
  45. package/lib/messages.ts +44 -13
  46. package/lib/random.ts +6 -0
  47. package/lib/rule-executors.ts +8 -3
  48. package/lib/rules.ts +2 -1
  49. package/lib/types.ts +27 -0
  50. package/lib/web.ts +127 -82
  51. package/package.json +11 -8
  52. package/playwright/runner.ts +1 -0
  53. package/rollup.config.js +18 -5
  54. package/rules/autoconsent/affinity-serif-com.json +1 -4
  55. package/rules/autoconsent/ausopen.json +2 -2
  56. package/rules/autoconsent/baden-wuerttemberg-de.json +1 -0
  57. package/rules/autoconsent/cc-banner.json +1 -0
  58. package/rules/autoconsent/complianz-notice.json +1 -0
  59. package/rules/autoconsent/cookie-notice.json +2 -1
  60. package/rules/autoconsent/cookiealert.json +48 -0
  61. package/rules/autoconsent/dsgvo.json +1 -0
  62. package/rules/autoconsent/eu-cookie-compliance.json +1 -1
  63. package/rules/autoconsent/eu-cookie-law.json +1 -0
  64. package/rules/autoconsent/ezoic.json +1 -0
  65. package/rules/autoconsent/generic-cosmetic.json +9 -0
  66. package/rules/autoconsent/indeed-com.json +9 -0
  67. package/rules/autoconsent/jquery-cookiebar.json +1 -0
  68. package/rules/autoconsent/marksandspencer.json +2 -2
  69. package/rules/autoconsent/notice-cookie.json +1 -0
  70. package/rules/autoconsent/osano.json +1 -0
  71. package/rules/autoconsent/pornhub.json +12 -0
  72. package/rules/autoconsent/uk-cookie-consent.json +1 -0
  73. package/rules/autoconsent/xnxx-com.json +9 -0
  74. package/rules/rules.json +183 -42
  75. package/tests/192.spec.ts +3 -3
  76. package/tests/adroll.spec.ts +7 -7
  77. package/tests/affinity-serif-com.spec.ts +1 -1
  78. package/tests/airbnb.spec.ts +3 -3
  79. package/tests/amazon.spec.ts +8 -8
  80. package/tests/arzt-auskunft.spec.ts +3 -3
  81. package/tests/ausopen.spec.ts +2 -2
  82. package/tests/aws.amazon.spec.ts +3 -3
  83. package/tests/axeptio.spec.ts +3 -3
  84. package/tests/baden-wuerttemberg.spec.ts +3 -3
  85. package/tests/borlabs.spec.ts +4 -4
  86. package/tests/bundesregierung.spec.ts +6 -6
  87. package/tests/ccbanner.spec.ts +4 -4
  88. package/tests/clickio.spec.ts +5 -5
  89. package/tests/complianz-banner.spec.ts +2 -2
  90. package/tests/complianz-categories.spec.ts +5 -5
  91. package/tests/complianz-notice.spec.ts +3 -3
  92. package/tests/complianz-optin.spec.ts +4 -4
  93. package/tests/consentmanager.spec.ts +8 -8
  94. package/tests/conversant.spec.ts +5 -5
  95. package/tests/cookie-notice.spec.ts +5 -3
  96. package/tests/cookiealert.spec.ts +9 -0
  97. package/tests/cookiebot.spec.ts +7 -11
  98. package/tests/cookieinformation.spec.ts +4 -5
  99. package/tests/cookielawinfo.spec.ts +3 -3
  100. package/tests/corona-in-zahlen.spec.ts +3 -3
  101. package/tests/dailymotion.spec.ts +5 -5
  102. package/tests/deepl.spec.ts +3 -3
  103. package/tests/didomi.spec.ts +8 -8
  104. package/tests/dmgmedia.spec.ts +7 -7
  105. package/tests/drupal.spec.ts +3 -3
  106. package/tests/dsgvo.spec.ts +4 -1
  107. package/tests/dunelm.spec.ts +3 -3
  108. package/tests/etsy.spec.ts +2 -2
  109. package/tests/eu-cookie-compliance-banner.spec.ts +2 -2
  110. package/tests/eu-cookie-law.spec.ts +2 -2
  111. package/tests/evidon.spec.ts +4 -6
  112. package/tests/ezoic.spec.ts +2 -3
  113. package/tests/facebook.spec.ts +5 -5
  114. package/tests/fundingchoices.spec.ts +5 -6
  115. package/tests/generic-cosmetic.spec.ts +11 -0
  116. package/tests/google.spec.ts +2 -2
  117. package/tests/gov-uk.spec.ts +4 -4
  118. package/tests/hl-co-uk.spec.ts +3 -3
  119. package/tests/hubspot.spec.ts +2 -2
  120. package/tests/indeed.spec.ts +7 -0
  121. package/tests/ionos.spec.ts +3 -3
  122. package/tests/iubenda.spec.ts +3 -3
  123. package/tests/johnlewis.spec.ts +3 -3
  124. package/tests/jquery-cookiebar.spec.ts +2 -2
  125. package/tests/klaro.spec.ts +5 -5
  126. package/tests/linkedin.spec.ts +2 -2
  127. package/tests/marksandspencer.spec.ts +2 -2
  128. package/tests/mediamarkt.spec.ts +3 -3
  129. package/tests/mediavine.spec.ts +3 -3
  130. package/tests/metoffice-gov-uk.spec.ts +3 -3
  131. package/tests/microsoft.spec.ts +4 -4
  132. package/tests/moneysavingexpert.spec.ts +3 -3
  133. package/tests/monzo-com.spec.ts +1 -1
  134. package/tests/moove.spec.ts +4 -10
  135. package/tests/national-lottery.spec.ts +3 -3
  136. package/tests/netflix.spec.ts +3 -3
  137. package/tests/nhs.spec.ts +3 -3
  138. package/tests/notice-cookie.spec.ts +2 -2
  139. package/tests/obi.spec.ts +3 -3
  140. package/tests/oil.spec.ts +6 -6
  141. package/tests/onetrust.spec.ts +24 -24
  142. package/tests/osano.spec.ts +1 -1
  143. package/tests/otto.spec.ts +3 -3
  144. package/tests/paypal.spec.ts +4 -4
  145. package/tests/pornhub.spec.ts +7 -0
  146. package/tests/primebox.spec.ts +2 -2
  147. package/tests/privacymanager.spec.ts +3 -3
  148. package/tests/pubtech.spec.ts +8 -9
  149. package/tests/quantcast.spec.ts +10 -10
  150. package/tests/reddit.spec.ts +3 -3
  151. package/tests/sibbo.spec.ts +9 -10
  152. package/tests/sirdata.spec.ts +2 -3
  153. package/tests/snigel.spec.ts +3 -3
  154. package/tests/sourcepoint.spec.ts +17 -17
  155. package/tests/springer.spec.ts +6 -6
  156. package/tests/steampowered.spec.ts +3 -3
  157. package/tests/tarteaucitron.spec.ts +4 -4
  158. package/tests/tealium.spec.ts +2 -2
  159. package/tests/termly.spec.ts +4 -4
  160. package/tests/testcmp.spec.ts +1 -1
  161. package/tests/thalia.spec.ts +3 -3
  162. package/tests/thefreedictionary.spec.ts +3 -3
  163. package/tests/tiktok.spec.ts +5 -5
  164. package/tests/trustarc.spec.ts +13 -15
  165. package/tests/twitter.spec.ts +7 -7
  166. package/tests/uk-cookie-consent.spec.ts +3 -3
  167. package/tests/uniconsent.spec.ts +4 -4
  168. package/tests/usercentrics-api.spec.ts +6 -5
  169. package/tests/usercentrics-button.spec.ts +2 -3
  170. package/tests/uswitch.spec.ts +3 -3
  171. package/tests/vodafone.spec.ts +3 -3
  172. package/tests/waitrose.spec.ts +3 -3
  173. package/tests/wetransfer.spec.ts +3 -3
  174. package/tests/wordpressgdpr.spec.ts +3 -3
  175. package/tests/wp-cookie-notice.spec.ts +3 -3
  176. package/tests/xing.spec.ts +4 -4
  177. package/tests/xnxx.spec.ts +8 -0
  178. package/tests/youtube-desktop.spec.ts +2 -4
  179. package/tests/youtube-mobile.spec.ts +3 -3
  180. package/tsconfig.json +2 -1
  181. package/.eslintrc.cjs +0 -14
  182. package/rules/autoconsent/motor-talk-de.json +0 -24
  183. package/tests/motor-talk.spec.ts +0 -7
@@ -1 +1,1912 @@
1
- !function(){"use strict";class e{constructor(e,t=1e3){this.id=e,this.promise=new Promise(((e,t)=>{this.resolve=e,this.reject=t})),this.timer=window.setTimeout((()=>{this.reject(new Error("timeout"))}),t)}}const t={pending:new Map,sendContentMessage:null};function n(e="autoconsent-css-rules"){const t=`style#${e}`,n=document.querySelector(t);if(n&&n instanceof HTMLStyleElement)return n;{const t=document.head||document.getElementsByTagName("head")[0]||document.documentElement,n=document.createElement("style");return n.id=e,t.appendChild(n),n}}function o(e,t,n="display"){const o="opacity"===n?"opacity: 0":"display: none",i=`${t.join(",")} { ${o} !important; z-index: -1 !important; pointer-events: none !important; } `;return e instanceof HTMLStyleElement&&(e.innerText+=i,t.length>0)}async function i(e,t,n){const o=await e();return!o&&t>0?new Promise((o=>{setTimeout((async()=>{o(i(e,t-1,n))}),n)})):Promise.resolve(o)}function s(e){if(!e)return!1;if(null!==e.offsetParent)return!0;{const t=window.getComputedStyle(e);if("fixed"===t.position&&"none"!==t.display)return!0}return!1}function r(n){return function(n){let o;o=crypto&&void 0!==crypto.randomUUID?crypto.randomUUID():Math.random().toString(),t.sendContentMessage({type:"eval",id:o,code:n});const i=new e(o);return t.pending.set(i.id,i),i.promise}(n).catch((e=>!1))}function a(e,t=!1){const n=document.querySelectorAll(e);return n.length>0&&(t?n.forEach((e=>e.click())):n[0].click()),n.length>0}function c(e){return null!==document.querySelector(e)}function u(e,t){const n=document.querySelectorAll(e),o=new Array(n.length);return n.forEach(((e,t)=>{o[t]=s(e)})),"none"===t?o.every((e=>!e)):0!==o.length&&("any"===t?o.some((e=>e)):o.every((e=>e)))}function l(e,t=1e4){return i((()=>null!==document.querySelector(e)),Math.ceil(t/200),200)}async function d(e,t=1e4,n=!1){return await l(e,t),a(e,n)}function p(e){return new Promise((t=>{setTimeout((()=>{t(!0)}),e)}))}function h(){const e=n("autoconsent-prehide");return e&&e.remove(),!!e}const m={main:!0,frame:!1,urlPattern:""};class f{constructor(e){this.runContext=m,this.name=e}get hasSelfTest(){throw new Error("Not Implemented")}get isIntermediate(){throw new Error("Not Implemented")}checkRunContext(){const e={...m,...this.runContext},t=window.top===window;return!(t&&!e.main)&&(!(!t&&!e.frame)&&!(e.urlPattern&&!window.location.href.match(e.urlPattern)))}detectCmp(){throw new Error("Not Implemented")}async detectPopup(){return!1}optOut(){throw new Error("Not Implemented")}optIn(){throw new Error("Not Implemented")}openCmp(){throw new Error("Not Implemented")}async test(){return Promise.resolve(!0)}}async function y(e){const t=[];if(e.exists&&t.push(c(e.exists)),e.visible&&t.push(u(e.visible,e.check)),e.eval){const n=r(e.eval);t.push(n)}var s,h;if(e.waitFor&&t.push(l(e.waitFor,e.timeout)),e.waitForVisible&&t.push(function(e,t=1e4,n="any"){return i((()=>u(e,n)),Math.ceil(t/200),200)}(e.waitForVisible,e.timeout,e.check)),e.click&&t.push(a(e.click,e.all)),e.waitForThenClick&&t.push(d(e.waitForThenClick,e.timeout,e.all)),e.wait&&t.push(p(e.wait)),e.hide&&t.push((s=e.hide,h=e.method,o(n(),s,h))),e.if){if(!e.if.exists&&!e.if.visible)return console.error("invalid conditional rule",e.if),!1;await y(e.if)?t.push(w(e.then)):e.else&&t.push(w(e.else))}if(0===t.length)return!1;return(await Promise.all(t)).reduce(((e,t)=>e&&t),!0)}async function w(e){for(const t of e){if(!await y(t)&&!t.optional)return!1}return!0}class g extends f{constructor(e){super(e.name),this.config=e,this.runContext=e.runContext||m}get hasSelfTest(){return!!this.config.test}get isIntermediate(){return!!this.config.intermediate}get prehideSelectors(){return this.config.prehideSelectors}async detectCmp(){return!!this.config.detectCmp&&async function(e){const t=e.map((e=>y(e)));return(await Promise.all(t)).every((e=>!!e))}(this.config.detectCmp)}async detectPopup(){return!!this.config.detectPopup&&w(this.config.detectPopup)}async optOut(){return!!this.config.optOut&&w(this.config.optOut)}async optIn(){return!!this.config.optIn&&w(this.config.optIn)}async openCmp(){return!!this.config.openCmp&&w(this.config.openCmp)}async test(){return this.hasSelfTest?w(this.config.test):super.test()}}const b="#truste-show-consent",C="#truste-consent-track";const k=[new class extends f{constructor(){super("TrustArc-top"),this.prehideSelectors=[".trustarc-banner-container",`.truste_popframe,.truste_overlay,.truste_box_overlay,${C}`],this.runContext={main:!0,frame:!1},this._shortcutButton=null,this._optInDone=!1}get hasSelfTest(){return!1}get isIntermediate(){return!this._optInDone&&!this._shortcutButton}async detectCmp(){const e=c(`#truste-show-consent,${C}`);return e&&(this._shortcutButton=document.querySelector("#truste-consent-required")),e}async detectPopup(){return u(`#truste-consent-content,#trustarc-banner-overlay,${C}`,"all")}openFrame(){a(b)}async optOut(){return this._shortcutButton?(this._shortcutButton.click(),!0):(o(n(),[".truste_popframe",".truste_overlay",".truste_box_overlay",C]),a(b),setTimeout((()=>{n().remove()}),1e4),!0)}async optIn(){return this._optInDone=!0,a("#truste-consent-button")}async openCmp(){return!0}async test(){return!0}},new class extends f{constructor(){super("TrustArc-frame"),this.runContext={main:!1,frame:!0,urlPattern:"^https://consent-pref\\.trustarc\\.com/\\?"}}get hasSelfTest(){return!1}get isIntermediate(){return!1}async detectCmp(){return!0}async detectPopup(){return u("#defaultpreferencemanager","any")&&u(".mainContent","any")}async navigateToSettings(){return await i((async()=>c(".shp")||u(".advance","any")||c(".switch span:first-child")),10,500),c(".shp")&&a(".shp"),await l(".prefPanel",5e3),u(".advance","any")&&a(".advance"),await i((()=>u(".switch span:first-child","any")),5,1e3)}async optOut(){return await i((()=>"complete"===document.readyState),20,100),await l(".mainContent[aria-hidden=false]",5e3),!!a(".rejectAll")||(c(".prefPanel")&&await l('.prefPanel[style="visibility: visible;"]',3e3),a("#catDetails0")?(a(".submit"),!0):(a(".required")||(await this.navigateToSettings(),a(".switch span:nth-child(1):not(.active)",!0),a(".submit"),l("#gwt-debug-close_id",3e5).then((()=>{a("#gwt-debug-close_id")}))),!0))}async optIn(){return a(".call")||(await this.navigateToSettings(),a(".switch span:nth-child(2)",!0),a(".submit"),l("#gwt-debug-close_id",3e5).then((()=>{a("#gwt-debug-close_id")}))),!0}},new class extends f{constructor(){super("Cybotcookiebot"),this.prehideSelectors=["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c("#CybotCookiebotDialogBodyLevelButtonPreferences")}async detectPopup(){return c("#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner")}async optOut(){return a(".cookie-alert-extended-detail-link")?(await l(".cookie-alert-configuration",2e3),a(".cookie-alert-configuration-input:checked",!0),a(".cookie-alert-extended-button-secondary"),!0):c("#dtcookie-container")?a(".h-dtcookie-decline"):(a(".cookiebot__button--settings")||a("#CybotCookiebotDialogBodyButtonDecline")||(a(".cookiebanner__link--details"),a('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled',!0),a("#CybotCookiebotDialogBodyButtonDecline"),a("input[id^=CybotCookiebotDialogBodyLevelButton]:checked",!0),c("#CybotCookiebotDialogBodyButtonAcceptSelected")?a("#CybotCookiebotDialogBodyButtonAcceptSelected"):a("#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection",!0),await r("window.CookieConsent.hasResponse !== true")&&(await r("window.Cookiebot.dialog.submitConsent()"),await p(500)),c("#cb-confirmedSettings")&&await r("endCookieProcess()")),!0)}async optIn(){return c("#dtcookie-container")?a(".h-dtcookie-accept"):(a(".CybotCookiebotDialogBodyLevelButton:not(:checked):enabled",!0),a("#CybotCookiebotDialogBodyLevelButtonAccept"),a("#CybotCookiebotDialogBodyButtonAccept"),!0)}async test(){return r("window.CookieConsent.declined === true")}},new class extends f{constructor(){super("Sourcepoint-frame"),this.prehideSelectors=["div[id^='sp_message_container_'],.message-overlay"],this.ccpaMode=!1,this.runContext={main:!1,frame:!0}}get hasSelfTest(){return!1}get isIntermediate(){return!1}async detectCmp(){const e=new URL(location.href);return e.searchParams.has("message_id")&&"ccpa-notice.sp-prod.net"===e.hostname?(this.ccpaMode=!0,!0):("/index.html"===e.pathname||"/privacy-manager/index.html"===e.pathname)&&(e.searchParams.has("message_id")||e.searchParams.has("requestUUID")||e.searchParams.has("consentUUID"))}async detectPopup(){return await l(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL",2e3),!c(".sp_choice_type_9")}async optIn(){return await l(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL",2e3),!!a(".sp_choice_type_11")||!!a(".sp_choice_type_ACCEPT_ALL")}isManagerOpen(){return"/privacy-manager/index.html"===new URL(location.href).pathname}async optOut(){if(!this.isManagerOpen()){if(!await l(".sp_choice_type_12,.sp_choice_type_13"))return!1;if(!c(".sp_choice_type_12"))return a(".sp_choice_type_13");a(".sp_choice_type_12"),await i((()=>"/privacy-manager/index.html"===location.pathname),200,100)}await l(".type-modal",2e4);try{const e=".sp_choice_type_REJECT_ALL",t=".reject-toggle",n=await Promise.race([l(e,2e3).then((e=>e?0:-1)),l(t,2e3).then((e=>e?1:-1)),l(".pm-features",2e3).then((e=>e?2:-1))]);if(0===n)return await p(1e3),a(e);1===n?a(t):2===n&&(await l(".pm-features",1e4),a(".checked > span",!0),a(".chevron"))}catch(e){}return a(".sp_choice_type_SAVE_AND_EXIT"),!0}},new class extends f{constructor(){super("consentmanager.net"),this.prehideSelectors=["#cmpbox,#cmpbox2"],this.apiAvailable=!1}get hasSelfTest(){return this.apiAvailable}get isIntermediate(){return!1}async detectCmp(){return this.apiAvailable=await r('window.__cmp && typeof __cmp("getCMPData") === "object"'),!!this.apiAvailable||c("#cmpbox")}async detectPopup(){return this.apiAvailable?(await p(500),await r("!__cmp('consentStatus').userChoiceExists")):u("#cmpbox .cmpmore","any")}async optOut(){return await p(500),this.apiAvailable?await r("__cmp('setConsent', 0)"):!!a(".cmpboxbtnno")||(c(".cmpwelcomeprpsbtn")?(a(".cmpwelcomeprpsbtn > a[aria-checked=true]",!0),a(".cmpboxbtnsave"),!0):(a(".cmpboxbtncustom"),await l(".cmptblbox",2e3),a(".cmptdchoice > a[aria-checked=true]",!0),a(".cmpboxbtnyescustomchoices"),!0))}async optIn(){return this.apiAvailable?await r("__cmp('setConsent', 1)"):a(".cmpboxbtnyes")}async test(){if(this.apiAvailable)return await r("__cmp('consentStatus').userChoiceExists")}},new class extends f{constructor(){super("Evidon")}get hasSelfTest(){return!1}get isIntermediate(){return!1}async detectCmp(){return c("#_evidon_banner")}async detectPopup(){return u("#_evidon_banner","any")}async optOut(){return a("#_evidon-decline-button")||(o(n(),["#evidon-prefdiag-overlay","#evidon-prefdiag-background"]),a("#_evidon-option-button"),await l("#evidon-prefdiag-overlay",5e3),a("#evidon-prefdiag-decline")),!0}async optIn(){return a("#_evidon-accept-button")}},new class extends f{constructor(){super("Onetrust"),this.prehideSelectors=["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c("#onetrust-banner-sdk")}async detectPopup(){return u("#onetrust-banner-sdk","all")}async optOut(){return c("#onetrust-pc-btn-handler")?a("#onetrust-pc-btn-handler"):a(".ot-sdk-show-settings,button.js-cookie-settings"),await l("#onetrust-consent-sdk",2e3),await p(1e3),a("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked",!0),await p(1e3),await l(".save-preference-btn-handler,.js-consent-save",2e3),a(".save-preference-btn-handler,.js-consent-save"),await i((()=>u("#onetrust-banner-sdk","none")),10,500),!0}async optIn(){return a("#onetrust-accept-btn-handler,.js-accept-cookies")}async test(){return await r("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1")}},new class extends f{constructor(){super("Klaro"),this.prehideSelectors=[".klaro"],this.settingsOpen=!1}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c(".klaro > .cookie-modal")?(this.settingsOpen=!0,!0):c(".klaro > .cookie-notice")}async detectPopup(){return u(".klaro > .cookie-notice,.klaro > .cookie-modal","any")}async optOut(){return!!a(".klaro .cn-decline")||(this.settingsOpen||(a(".klaro .cn-learn-more"),await l(".klaro > .cookie-modal",2e3),this.settingsOpen=!0),!!a(".klaro .cn-decline")||(a(".cm-purpose:not(.cm-toggle-all) > input:not(.half-checked)",!0),a(".cm-btn-accept")))}async optIn(){return!!a(".klaro .cm-btn-accept-all")||(this.settingsOpen?(a(".cm-purpose:not(.cm-toggle-all) > input.half-checked",!0),a(".cm-btn-accept")):a(".klaro .cookie-notice .cm-btn-success"))}async test(){return await r("klaro.getManager().config.services.every(c => c.required || !klaro.getManager().consents[c.name])")}},new class extends f{constructor(){super("Uniconsent")}get prehideSelectors(){return[".unic",".modal:has(.unic)"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c(".unic .unic-box,.unic .unic-bar")}async detectPopup(){return u(".unic .unic-box,.unic .unic-bar","any")}async optOut(){if(await l(".unic button",1e3),document.querySelectorAll(".unic button").forEach((e=>{const t=e.textContent;(t.includes("Manage Options")||t.includes("Optionen verwalten"))&&e.click()})),await l(".unic input[type=checkbox]",1e3)){await l(".unic button",1e3),document.querySelectorAll(".unic input[type=checkbox]").forEach((e=>{e.checked&&e.click()}));for(const e of document.querySelectorAll(".unic button")){const t=e.textContent;for(const n of["Confirm Choices","Save Choices","Auswahl speichern"])if(t.includes(n))return e.click(),await p(500),!0}}return!1}async optIn(){return d(".unic #unic-agree")}async test(){await p(1e3);return!c(".unic .unic-box,.unic .unic-bar")}},new class extends f{constructor(){super("Conversant"),this.prehideSelectors=[".cmp-root"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c(".cmp-root .cmp-receptacle")}async detectPopup(){return u(".cmp-root .cmp-receptacle","any")}async optOut(){if(!await d(".cmp-main-button:not(.cmp-main-button--primary)"))return!1;if(!await l(".cmp-view-tab-tabs"))return!1;await d(".cmp-view-tab-tabs > :first-child"),await d(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");for(const e of Array.from(document.querySelectorAll(".cmp-accordion-item"))){e.querySelector(".cmp-accordion-item-title").click(),await i((()=>!!e.querySelector(".cmp-accordion-item-content.cmp-active")),10,50);const t=e.querySelector(".cmp-accordion-item-content.cmp-active");t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e=>e.click())),t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e=>e.click()))}return await a(".cmp-main-button:not(.cmp-main-button--primary)"),!0}async optIn(){return d(".cmp-main-button.cmp-main-button--primary")}async test(){return document.cookie.includes("cmp-data=0")}},new class extends f{constructor(){super("tiktok.com"),this.runContext={urlPattern:"tiktok"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}getShadowRoot(){const e=document.querySelector("tiktok-cookie-banner");return e?e.shadowRoot:null}async detectCmp(){return c("tiktok-cookie-banner")}async detectPopup(){return s(this.getShadowRoot().querySelector(".tiktok-cookie-banner"))}async optOut(){const e=this.getShadowRoot().querySelector(".button-wrapper button:first-child");return!!e&&(e.click(),!0)}async optIn(){const e=this.getShadowRoot().querySelector(".button-wrapper button:last-child");return!!e&&(e.click(),!0)}async test(){const e=document.cookie.match(/cookie-consent=([^;]+)/);if(!e)return!1;const t=JSON.parse(decodeURIComponent(e[1]));return Object.values(t).every((e=>"boolean"!=typeof e||!1===e))}},new class extends f{constructor(){super("airbnb"),this.runContext={urlPattern:"^https://(www\\.)?airbnb\\.[^/]+/"},this.prehideSelectors=["div[data-testid=main-cookies-banner-container]",'div:has(> div:first-child):has(> div:last-child):has(> section [data-testid="strictly-necessary-cookies"])']}get hasSelfTest(){return!0}get isIntermediate(){return!1}async detectCmp(){return c("div[data-testid=main-cookies-banner-container]")}async detectPopup(){return u("div[data-testid=main-cookies-banner-container","any")}async optOut(){let e;for(await d("div[data-testid=main-cookies-banner-container] button._snbhip0");e=document.querySelector("[data-testid=modal-container] button[aria-checked=true]:not([disabled])");)e.click();return d("button[data-testid=save-btn]")}async optIn(){return d("div[data-testid=main-cookies-banner-container] button._148dgdpk")}async test(){return await i((()=>!!document.cookie.match("OptanonAlertBoxClosed")),20,200)}}];class v{static setBase(e){v.base=e}static findElement(e,t=null,n=!1){let o=null;return o=null!=t?Array.from(t.querySelectorAll(e.selector)):null!=v.base?Array.from(v.base.querySelectorAll(e.selector)):Array.from(document.querySelectorAll(e.selector)),null!=e.textFilter&&(o=o.filter((t=>{let n=t.textContent.toLowerCase();if(Array.isArray(e.textFilter)){let t=!1;for(let o of e.textFilter)if(-1!==n.indexOf(o.toLowerCase())){t=!0;break}return t}if(null!=e.textFilter)return-1!==n.indexOf(e.textFilter.toLowerCase())}))),null!=e.styleFilters&&(o=o.filter((t=>{let n=window.getComputedStyle(t),o=!0;for(let t of e.styleFilters){let e=n[t.option];o=t.negated?o&&e!==t.value:o&&e===t.value}return o}))),null!=e.displayFilter&&(o=o.filter((t=>e.displayFilter?0!==t.offsetHeight:0===t.offsetHeight))),null!=e.iframeFilter&&(o=o.filter((t=>e.iframeFilter?window.location!==window.parent.location:window.location===window.parent.location))),null!=e.childFilter&&(o=o.filter((t=>{let n=v.base;v.setBase(t);let o=v.find(e.childFilter);return v.setBase(n),null!=o.target}))),n?o:(o.length>1&&console.warn("Multiple possible targets: ",o,e,t),o[0])}static find(e,t=!1){let n=[];if(null!=e.parent){let o=v.findElement(e.parent,null,t);if(null!=o){if(o instanceof Array)return o.forEach((o=>{let i=v.findElement(e.target,o,t);i instanceof Array?i.forEach((e=>{n.push({parent:o,target:e})})):n.push({parent:o,target:i})})),n;{let i=v.findElement(e.target,o,t);i instanceof Array?i.forEach((e=>{n.push({parent:o,target:e})})):n.push({parent:o,target:i})}}}else{let o=v.findElement(e.target,null,t);o instanceof Array?o.forEach((e=>{n.push({parent:null,target:e})})):n.push({parent:null,target:o})}return 0===n.length&&n.push({parent:null,target:null}),t?n:(1!==n.length&&console.warn("Multiple results found, even though multiple false",n),n[0])}}function _(e){const t=v.find(e);return"css"===e.type?!!t.target:"checkbox"===e.type?!!t.target&&t.target.checked:void 0}async function S(e,t){switch(e.type){case"click":return async function(e){const t=v.find(e);null!=t.target&&t.target.click();return x(0)}(e);case"list":return async function(e,t){for(let n of e.actions)await S(n,t)}(e,t);case"consent":return async function(e,t){for(const n of e.consents){const e=-1!==t.indexOf(n.type);if(n.matcher&&n.toggleAction){_(n.matcher)!==e&&await S(n.toggleAction)}else e?await S(n.trueAction):await S(n.falseAction)}}(e,t);case"ifcss":return async function(e,t){v.find(e).target?e.falseAction&&await S(e.falseAction,t):e.trueAction&&await S(e.trueAction,t)}(e,t);case"waitcss":return async function(e){await new Promise((t=>{let n=e.retries||10;const o=e.waitTime||250,i=()=>{const s=v.find(e);(e.negated&&s.target||!e.negated&&!s.target)&&n>0?(n-=1,setTimeout(i,o)):t()};i()}))}(e);case"foreach":return async function(e,t){const n=v.find(e,!0),o=v.base;for(const o of n)o.target&&(v.setBase(o.target),await S(e.action,t));v.setBase(o)}(e,t);case"hide":return async function(e){const t=v.find(e);t.target&&t.target.classList.add("Autoconsent-Hidden")}(e);case"slide":return async function(e){const t=v.find(e),n=v.find(e.dragTarget);if(t.target){let e=t.target.getBoundingClientRect(),o=n.target.getBoundingClientRect(),i=o.top-e.top,s=o.left-e.left;"y"===this.config.axis.toLowerCase()&&(s=0),"x"===this.config.axis.toLowerCase()&&(i=0);let r=window.screenX+e.left+e.width/2,a=window.screenY+e.top+e.height/2,c=e.left+e.width/2,u=e.top+e.height/2,l=document.createEvent("MouseEvents");l.initMouseEvent("mousedown",!0,!0,window,0,r,a,c,u,!1,!1,!1,!1,0,t.target);let d=document.createEvent("MouseEvents");d.initMouseEvent("mousemove",!0,!0,window,0,r+s,a+i,c+s,u+i,!1,!1,!1,!1,0,t.target);let p=document.createEvent("MouseEvents");p.initMouseEvent("mouseup",!0,!0,window,0,r+s,a+i,c+s,u+i,!1,!1,!1,!1,0,t.target),t.target.dispatchEvent(l),await this.waitTimeout(10),t.target.dispatchEvent(d),await this.waitTimeout(10),t.target.dispatchEvent(p)}}(e);case"close":return async function(e){window.close()}();case"wait":return async function(e){await x(e.waitTime)}(e);case"eval":return async function(e){return console.log("eval!",e.code),new Promise((t=>{try{e.async?(window.eval(e.code),setTimeout((()=>{t(window.eval("window.__consentCheckResult"))}),e.timeout||250)):t(window.eval(e.code))}catch(n){console.warn("eval error",n,e.code),t(!1)}}))}(e);default:throw"Unknown action type: "+e.type}}v.base=null;function x(e){return new Promise((t=>{setTimeout((()=>{t()}),e)}))}class A{constructor(e,t){this.name=e,this.config=t,this.methods=new Map,this.runContext=m,t.methods.forEach((e=>{e.action&&this.methods.set(e.name,e.action)})),this.hasSelfTest=!1}get isIntermediate(){return!1}checkRunContext(){return!0}async detectCmp(){return this.config.detectors.map((e=>_(e.presentMatcher))).some((e=>!!e))}async detectPopup(){return this.config.detectors.map((e=>_(e.showingMatcher))).some((e=>!!e))}async executeAction(e,t){return!this.methods.has(e)||S(this.methods.get(e),t)}async optOut(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",[]),await this.executeAction("SAVE_CONSENT"),!0}async optIn(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",["D","A","B","E","F","X"]),await this.executeAction("SAVE_CONSENT"),!0}async openCmp(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),!0}async test(){return!0}}const P=new class{constructor(e,n=null,o=null){if(this.rules=[],this.foundCmp=null,t.sendContentMessage=e,this.sendContentMessage=e,this.rules=[...k],n)this.initialize(n,o);else{o&&this.parseRules(o);e({type:"init",url:window.location.href})}}initialize(e,t){if(this.config=e,e.enabled){if(t&&this.parseRules(t),e.disabledCmps?.length>0&&this.disableCMPs(e.disabledCmps),e.enablePrehide)if(document.documentElement)this.prehideElements();else{const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.prehideElements()};window.addEventListener("DOMContentLoaded",e)}if("loading"===document.readyState){const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.start()};window.addEventListener("DOMContentLoaded",e)}else this.start()}}parseRules(e){Object.keys(e.consentomatic).forEach((t=>{this.addConsentomaticCMP(t,e.consentomatic[t])})),e.autoconsent.forEach((e=>{this.addCMP(e)}))}addCMP(e){this.rules.push(function(e){return new g(e)}(e))}disableCMPs(e){this.rules=this.rules.filter((t=>!e.includes(t.name)))}addConsentomaticCMP(e,t){this.rules.push(new A(`com_${e}`,t))}start(){window.requestIdleCallback?window.requestIdleCallback((()=>this._start()),{timeout:500}):this._start()}async _start(){const e=await this.findCmp(this.config.detectRetries);if(e.length>0){const t=[];for(const n of e)this.sendContentMessage({type:"cmpDetected",url:location.href,cmp:n.name}),t.push(this.waitForPopup(n).then((e=>e?(this.foundCmp||(this.foundCmp=n),this.sendContentMessage({type:"popupFound",cmp:n.name,url:location.href}),!0):Promise.reject(`${n.name} popup not found`))));let n=!1;for(const e of t)try{await e,n=!0;break}catch(e){continue}return n?"optOut"===this.config.autoAction?await this.doOptOut():"optIn"!==this.config.autoAction||await this.doOptIn():(this.config.enablePrehide&&h(),!1)}return this.config.enablePrehide&&h(),!1}async findCmp(e){const t=[];for(const e of this.rules)try{if(!e.checkRunContext())continue;await e.detectCmp()&&t.push(e)}catch(e){}if(t.length>1){const e={msg:"Found multiple CMPs, check the detection rules.",cmps:t.map((e=>e.name))};this.sendContentMessage({type:"autoconsentError",details:e})}return 0===t.length&&e>0?new Promise((t=>{setTimeout((async()=>{const n=this.findCmp(e-1);t(n)}),500)})):t}async doOptOut(){let e;return e=!!this.foundCmp&&await this.foundCmp.optOut(),this.config.enablePrehide&&h(),this.sendContentMessage({type:"optOutResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:e,scheduleSelfTest:this.foundCmp&&this.foundCmp.hasSelfTest,url:location.href}),e&&!this.foundCmp.isIntermediate&&this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,url:location.href}),e}async doOptIn(){let e;return e=!!this.foundCmp&&await this.foundCmp.optIn(),this.config.enablePrehide&&h(),this.sendContentMessage({type:"optInResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:e,scheduleSelfTest:!1,url:location.href}),e&&!this.foundCmp.isIntermediate&&this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,url:location.href}),e}async doSelfTest(){let e;return e=!!this.foundCmp&&await this.foundCmp.test(),this.sendContentMessage({type:"selfTestResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:e,url:location.href}),e}async waitForPopup(e,t=5,n=500){const o=await e.detectPopup();return!o&&t>0?new Promise((o=>setTimeout((()=>o(this.waitForPopup(e,t-1,n))),n))):o}prehideElements(){return function(e){return o(n("autoconsent-prehide"),e,"opacity")}(this.rules.reduce(((e,t)=>t.prehideSelectors?[...e,...t.prehideSelectors]:e),["#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium"]))}async receiveMessageCallback(e){switch(e.type){case"initResp":this.initialize(e.config,e.rules);break;case"optIn":await this.doOptIn();break;case"optOut":await this.doOptOut();break;case"selfTest":await this.doSelfTest();break;case"evalResp":!function(e,n){const o=t.pending.get(e);o?(t.pending.delete(e),o.timer&&window.clearTimeout(o.timer),o.resolve(n)):console.warn("no eval #",e)}(e.id,e.result)}}}(chrome.runtime.sendMessage);chrome.runtime.onMessage.addListener((e=>Promise.resolve(P.receiveMessageCallback(e))))}();
1
+ (function () {
2
+ 'use strict';
3
+
4
+ const enableLogs = false; // change this to enable debug logs
5
+
6
+ function getRandomID() {
7
+ if (crypto && typeof crypto.randomUUID !== "undefined") {
8
+ return crypto.randomUUID();
9
+ }
10
+ return Math.random().toString();
11
+ }
12
+
13
+ class Deferred {
14
+ constructor(id, timeout = 1000) {
15
+ this.id = id;
16
+ this.promise = new Promise((resolve, reject) => {
17
+ this.resolve = resolve;
18
+ this.reject = reject;
19
+ });
20
+ this.timer = window.setTimeout(() => {
21
+ this.reject(new Error("timeout"));
22
+ }, timeout);
23
+ }
24
+ }
25
+ const evalState = {
26
+ pending: new Map(),
27
+ sendContentMessage: null,
28
+ };
29
+ function requestEval(code) {
30
+ const id = getRandomID();
31
+ evalState.sendContentMessage({
32
+ type: 'eval',
33
+ id,
34
+ code,
35
+ });
36
+ const deferred = new Deferred(id);
37
+ evalState.pending.set(deferred.id, deferred);
38
+ return deferred.promise;
39
+ }
40
+ function resolveEval(id, value) {
41
+ const deferred = evalState.pending.get(id);
42
+ if (deferred) {
43
+ evalState.pending.delete(id);
44
+ deferred.timer && window.clearTimeout(deferred.timer);
45
+ deferred.resolve(value);
46
+ }
47
+ else {
48
+ console.warn('no eval #', id);
49
+ }
50
+ }
51
+
52
+ // get or create a style container for CSS overrides
53
+ function getStyleElement(styleOverrideElementId = "autoconsent-css-rules") {
54
+ const styleSelector = `style#${styleOverrideElementId}`;
55
+ const existingElement = document.querySelector(styleSelector);
56
+ if (existingElement && existingElement instanceof HTMLStyleElement) {
57
+ return existingElement;
58
+ }
59
+ else {
60
+ const parent = document.head ||
61
+ document.getElementsByTagName("head")[0] ||
62
+ document.documentElement;
63
+ const css = document.createElement("style");
64
+ css.id = styleOverrideElementId;
65
+ parent.appendChild(css);
66
+ return css;
67
+ }
68
+ }
69
+ // hide elements with a CSS rule
70
+ function hideElements(styleEl, selectors, method = 'display') {
71
+ const hidingSnippet = method === "opacity" ? `opacity: 0` : `display: none`; // use display by default
72
+ const rule = `${selectors.join(",")} { ${hidingSnippet} !important; z-index: -1 !important; pointer-events: none !important; } `;
73
+ if (styleEl instanceof HTMLStyleElement) {
74
+ styleEl.innerText += rule;
75
+ return selectors.length > 0;
76
+ }
77
+ return false;
78
+ }
79
+ async function waitFor(predicate, maxTimes, interval) {
80
+ const result = await predicate();
81
+ if (!result && maxTimes > 0) {
82
+ return new Promise((resolve) => {
83
+ setTimeout(async () => {
84
+ resolve(waitFor(predicate, maxTimes - 1, interval));
85
+ }, interval);
86
+ });
87
+ }
88
+ return Promise.resolve(result);
89
+ }
90
+ function isElementVisible(elem) {
91
+ if (!elem) {
92
+ return false;
93
+ }
94
+ if (elem.offsetParent !== null) {
95
+ return true;
96
+ }
97
+ else {
98
+ const css = window.getComputedStyle(elem);
99
+ if (css.position === 'fixed' && css.display !== "none") { // fixed elements may be visible even if the parent is not
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
105
+
106
+ function doEval(expr) {
107
+ return requestEval(expr).catch((e) => {
108
+ return false;
109
+ });
110
+ }
111
+ function click(selectorOrElements, all = false) {
112
+ let elem = [];
113
+ if (typeof selectorOrElements === 'string') {
114
+ elem = Array.from(document.querySelectorAll(selectorOrElements));
115
+ }
116
+ else {
117
+ elem = selectorOrElements;
118
+ }
119
+ if (elem.length > 0) {
120
+ if (all) {
121
+ elem.forEach((e) => e.click());
122
+ }
123
+ else {
124
+ elem[0].click();
125
+ }
126
+ }
127
+ return elem.length > 0;
128
+ }
129
+ function elementExists(selector) {
130
+ const exists = document.querySelector(selector) !== null;
131
+ // enableLogs && console.log("[exists?]", selector, exists);
132
+ return exists;
133
+ }
134
+ function elementVisible(selector, check) {
135
+ const elem = document.querySelectorAll(selector);
136
+ const results = new Array(elem.length);
137
+ elem.forEach((e, i) => {
138
+ // check for display: none
139
+ results[i] = isElementVisible(e);
140
+ });
141
+ // enableLogs && console.log("[visible?]", selector, check, elem, results);
142
+ if (check === "none") {
143
+ return results.every(r => !r);
144
+ }
145
+ else if (results.length === 0) {
146
+ return false;
147
+ }
148
+ else if (check === "any") {
149
+ return results.some(r => r);
150
+ }
151
+ // all
152
+ return results.every(r => r);
153
+ }
154
+ function waitForElement(selector, timeout = 10000) {
155
+ const interval = 200;
156
+ const times = Math.ceil((timeout) / interval);
157
+ // enableLogs && console.log("[waitFor]", ruleStep.waitFor);
158
+ return waitFor(() => document.querySelector(selector) !== null, times, interval);
159
+ }
160
+ function waitForVisible(selector, timeout = 10000, check = 'any') {
161
+ const interval = 200;
162
+ const times = Math.ceil((timeout) / interval);
163
+ // enableLogs && console.log("[waitForVisible]", ruleStep.waitFor);
164
+ return waitFor(() => elementVisible(selector, check), times, interval);
165
+ }
166
+ async function waitForThenClick(selector, timeout = 10000, all = false) {
167
+ // enableLogs && console.log("[waitForThenClick]", ruleStep.waitForThenClick);
168
+ await waitForElement(selector, timeout);
169
+ return click(selector, all);
170
+ }
171
+ function wait(ms) {
172
+ // enableLogs && console.log(`waiting for ${ruleStep.wait}ms`);
173
+ return new Promise(resolve => {
174
+ setTimeout(() => {
175
+ // enableLogs && console.log(`done waiting`);
176
+ resolve(true);
177
+ }, ms);
178
+ });
179
+ }
180
+ function hide(selectors, method) {
181
+ // enableLogs && console.log("[hide]", ruleStep.hide, ruleStep.method);
182
+ const styleEl = getStyleElement();
183
+ return hideElements(styleEl, selectors, method);
184
+ }
185
+ function prehide(selectors) {
186
+ const styleEl = getStyleElement('autoconsent-prehide');
187
+ return hideElements(styleEl, selectors, "opacity");
188
+ }
189
+ function undoPrehide() {
190
+ const existingElement = getStyleElement('autoconsent-prehide');
191
+ if (existingElement) {
192
+ existingElement.remove();
193
+ }
194
+ return !!existingElement;
195
+ }
196
+
197
+ /* eslint-disable no-restricted-syntax,no-await-in-loop,no-underscore-dangle */
198
+ const defaultRunContext = {
199
+ main: true,
200
+ frame: false,
201
+ urlPattern: "",
202
+ };
203
+ class AutoConsentCMPBase {
204
+ constructor(name) {
205
+ this.runContext = defaultRunContext;
206
+ this.name = name;
207
+ }
208
+ get hasSelfTest() {
209
+ throw new Error('Not Implemented');
210
+ }
211
+ get isIntermediate() {
212
+ throw new Error('Not Implemented');
213
+ }
214
+ get isCosmetic() {
215
+ throw new Error('Not Implemented');
216
+ }
217
+ checkRunContext() {
218
+ const runCtx = {
219
+ ...defaultRunContext,
220
+ ...this.runContext,
221
+ };
222
+ const isTop = window.top === window;
223
+ if (isTop && !runCtx.main) {
224
+ return false;
225
+ }
226
+ if (!isTop && !runCtx.frame) {
227
+ return false;
228
+ }
229
+ if (runCtx.urlPattern && !window.location.href.match(runCtx.urlPattern)) {
230
+ return false;
231
+ }
232
+ return true;
233
+ }
234
+ detectCmp() {
235
+ throw new Error('Not Implemented');
236
+ }
237
+ async detectPopup() {
238
+ return false;
239
+ }
240
+ optOut() {
241
+ throw new Error('Not Implemented');
242
+ }
243
+ optIn() {
244
+ throw new Error('Not Implemented');
245
+ }
246
+ openCmp() {
247
+ throw new Error('Not Implemented');
248
+ }
249
+ async test() {
250
+ // try IAB by default
251
+ return Promise.resolve(true);
252
+ }
253
+ }
254
+ async function evaluateRuleStep(rule) {
255
+ const results = [];
256
+ if (rule.exists) {
257
+ results.push(elementExists(rule.exists));
258
+ }
259
+ if (rule.visible) {
260
+ results.push(elementVisible(rule.visible, rule.check));
261
+ }
262
+ if (rule.eval) {
263
+ const res = doEval(rule.eval);
264
+ results.push(res);
265
+ }
266
+ if (rule.waitFor) {
267
+ results.push(waitForElement(rule.waitFor, rule.timeout));
268
+ }
269
+ if (rule.waitForVisible) {
270
+ results.push(waitForVisible(rule.waitForVisible, rule.timeout, rule.check));
271
+ }
272
+ if (rule.click) {
273
+ results.push(click(rule.click, rule.all));
274
+ }
275
+ if (rule.waitForThenClick) {
276
+ results.push(waitForThenClick(rule.waitForThenClick, rule.timeout, rule.all));
277
+ }
278
+ if (rule.wait) {
279
+ results.push(wait(rule.wait));
280
+ }
281
+ if (rule.hide) {
282
+ results.push(hide(rule.hide, rule.method));
283
+ }
284
+ if (rule.if) {
285
+ if (!rule.if.exists && !rule.if.visible) {
286
+ console.error('invalid conditional rule', rule.if);
287
+ return false;
288
+ }
289
+ const condition = await evaluateRuleStep(rule.if);
290
+ if (condition) {
291
+ results.push(_runRulesSequentially(rule.then));
292
+ }
293
+ else if (rule.else) {
294
+ results.push(_runRulesSequentially(rule.else));
295
+ }
296
+ }
297
+ if (results.length === 0) {
298
+ return false;
299
+ }
300
+ // boolean and of results
301
+ const all = await Promise.all(results);
302
+ return all.reduce((a, b) => a && b, true);
303
+ }
304
+ async function _runRulesParallel(rules) {
305
+ const results = rules.map(rule => evaluateRuleStep(rule));
306
+ const detections = await Promise.all(results);
307
+ return detections.every(r => !!r);
308
+ }
309
+ async function _runRulesSequentially(rules) {
310
+ for (const rule of rules) {
311
+ const result = await evaluateRuleStep(rule);
312
+ if (!result && !rule.optional) {
313
+ return false;
314
+ }
315
+ }
316
+ return true;
317
+ }
318
+ class AutoConsentCMP extends AutoConsentCMPBase {
319
+ constructor(config) {
320
+ super(config.name);
321
+ this.config = config;
322
+ this.runContext = config.runContext || defaultRunContext;
323
+ }
324
+ get hasSelfTest() {
325
+ return !!this.config.test;
326
+ }
327
+ get isIntermediate() {
328
+ return !!this.config.intermediate;
329
+ }
330
+ get isCosmetic() {
331
+ return !!this.config.cosmetic;
332
+ }
333
+ get prehideSelectors() {
334
+ return this.config.prehideSelectors;
335
+ }
336
+ async detectCmp() {
337
+ if (this.config.detectCmp) {
338
+ return _runRulesParallel(this.config.detectCmp);
339
+ }
340
+ return false;
341
+ }
342
+ async detectPopup() {
343
+ if (this.config.detectPopup) {
344
+ return _runRulesSequentially(this.config.detectPopup);
345
+ }
346
+ return false;
347
+ }
348
+ async optOut() {
349
+ if (this.config.optOut) {
350
+ return _runRulesSequentially(this.config.optOut);
351
+ }
352
+ return false;
353
+ }
354
+ async optIn() {
355
+ if (this.config.optIn) {
356
+ return _runRulesSequentially(this.config.optIn);
357
+ }
358
+ return false;
359
+ }
360
+ async openCmp() {
361
+ if (this.config.openCmp) {
362
+ return _runRulesSequentially(this.config.openCmp);
363
+ }
364
+ return false;
365
+ }
366
+ async test() {
367
+ if (this.hasSelfTest) {
368
+ return _runRulesSequentially(this.config.test);
369
+ }
370
+ return super.test();
371
+ }
372
+ }
373
+
374
+ const cookieSettingsButton = "#truste-show-consent";
375
+ const shortcutOptOut = '#truste-consent-required';
376
+ const shortcutOptIn = '#truste-consent-button';
377
+ const popupContent = '#truste-consent-content';
378
+ const bannerOverlay = '#trustarc-banner-overlay';
379
+ const bannerContainer = '#truste-consent-track';
380
+ class TrustArcTop extends AutoConsentCMPBase {
381
+ constructor() {
382
+ super("TrustArc-top");
383
+ this.prehideSelectors = [
384
+ ".trustarc-banner-container",
385
+ `.truste_popframe,.truste_overlay,.truste_box_overlay,${bannerContainer}`,
386
+ ];
387
+ this.runContext = {
388
+ main: true,
389
+ frame: false,
390
+ };
391
+ this._shortcutButton = null; // indicates if the "reject all" button is detected
392
+ this._optInDone = false;
393
+ }
394
+ get hasSelfTest() {
395
+ return false;
396
+ }
397
+ get isIntermediate() {
398
+ if (this._optInDone) {
399
+ return false;
400
+ }
401
+ return !this._shortcutButton;
402
+ }
403
+ get isCosmetic() {
404
+ return false;
405
+ }
406
+ async detectCmp() {
407
+ const result = elementExists(`${cookieSettingsButton},${bannerContainer}`);
408
+ if (result) {
409
+ // additionally detect the opt-out button
410
+ this._shortcutButton = document.querySelector(shortcutOptOut);
411
+ }
412
+ return result;
413
+ }
414
+ async detectPopup() {
415
+ // not every element should exist, but if it does, it's a popup
416
+ return elementVisible(`${popupContent},${bannerOverlay},${bannerContainer}`, 'all');
417
+ }
418
+ openFrame() {
419
+ click(cookieSettingsButton);
420
+ }
421
+ async optOut() {
422
+ if (this._shortcutButton) {
423
+ this._shortcutButton.click();
424
+ return true;
425
+ }
426
+ // hide elements permanently, so user doesn't see the popup
427
+ hideElements(getStyleElement(), [".truste_popframe", ".truste_overlay", ".truste_box_overlay", bannerContainer]);
428
+ click(cookieSettingsButton);
429
+ // schedule cleanup
430
+ setTimeout(() => {
431
+ getStyleElement().remove();
432
+ }, 10000);
433
+ return true;
434
+ }
435
+ async optIn() {
436
+ this._optInDone = true; // just a hack to force autoconsentDone
437
+ return click(shortcutOptIn);
438
+ }
439
+ async openCmp() {
440
+ // await tab.eval("truste.eu.clickListener()");
441
+ return true;
442
+ }
443
+ async test() {
444
+ // TODO: find out how to test TrustArc
445
+ return true;
446
+ }
447
+ }
448
+
449
+ class TrustArcFrame extends AutoConsentCMPBase {
450
+ constructor() {
451
+ super("TrustArc-frame");
452
+ this.runContext = {
453
+ main: false,
454
+ frame: true,
455
+ urlPattern: "^https://consent-pref\\.trustarc\\.com/\\?",
456
+ };
457
+ }
458
+ get hasSelfTest() {
459
+ return false;
460
+ }
461
+ get isIntermediate() {
462
+ return false;
463
+ }
464
+ get isCosmetic() {
465
+ return false;
466
+ }
467
+ async detectCmp() {
468
+ return true;
469
+ }
470
+ async detectPopup() {
471
+ // we're already inside the popup
472
+ return elementVisible("#defaultpreferencemanager", 'any') && elementVisible(".mainContent", 'any');
473
+ }
474
+ async navigateToSettings() {
475
+ // wait for it to load
476
+ await waitFor(async () => {
477
+ return (elementExists(".shp") ||
478
+ elementVisible(".advance", 'any') ||
479
+ elementExists(".switch span:first-child"));
480
+ }, 10, 500);
481
+ // splash screen -> hit more information
482
+ if (elementExists(".shp")) {
483
+ click(".shp");
484
+ }
485
+ await waitForElement(".prefPanel", 5000);
486
+ // go to advanced settings if not yet shown
487
+ if (elementVisible(".advance", 'any')) {
488
+ click(".advance");
489
+ }
490
+ // takes a while to load the opt-in/opt-out buttons
491
+ return await waitFor(() => elementVisible(".switch span:first-child", 'any'), 5, 1000);
492
+ }
493
+ async optOut() {
494
+ await waitFor(() => document.readyState === 'complete', 20, 100);
495
+ await waitForElement(".mainContent[aria-hidden=false]", 5000);
496
+ if (click(".rejectAll")) {
497
+ return true;
498
+ }
499
+ if (elementExists('.prefPanel')) {
500
+ await waitForElement('.prefPanel[style="visibility: visible;"]', 3000);
501
+ }
502
+ if (click("#catDetails0")) {
503
+ click(".submit");
504
+ return true;
505
+ }
506
+ if (click(".required")) {
507
+ return true;
508
+ }
509
+ await this.navigateToSettings();
510
+ click(".switch span:nth-child(1):not(.active)", true);
511
+ click(".submit");
512
+ // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
513
+ waitForElement("#gwt-debug-close_id", 300000).then(() => {
514
+ click("#gwt-debug-close_id");
515
+ });
516
+ return true;
517
+ }
518
+ async optIn() {
519
+ if (click('.call')) {
520
+ return true;
521
+ }
522
+ await this.navigateToSettings();
523
+ click(".switch span:nth-child(2)", true);
524
+ click(".submit");
525
+ // at this point, iframe usually closes. Sometimes we need to close manually, but we don't wait for it to report success
526
+ waitForElement("#gwt-debug-close_id", 300000).then(() => {
527
+ click("#gwt-debug-close_id");
528
+ });
529
+ return true;
530
+ }
531
+ }
532
+
533
+ class Cookiebot extends AutoConsentCMPBase {
534
+ constructor() {
535
+ super('Cybotcookiebot');
536
+ this.prehideSelectors = ["#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookieoverlay"];
537
+ }
538
+ get hasSelfTest() {
539
+ return true;
540
+ }
541
+ get isIntermediate() {
542
+ return false;
543
+ }
544
+ get isCosmetic() {
545
+ return false;
546
+ }
547
+ async detectCmp() {
548
+ return elementExists('#CybotCookiebotDialogBodyLevelButtonPreferences');
549
+ }
550
+ async detectPopup() {
551
+ return elementExists('#CybotCookiebotDialog,#dtcookie-container,#cookiebanner,#cb-cookiebanner');
552
+ }
553
+ async optOut() {
554
+ if (click('.cookie-alert-extended-detail-link')) {
555
+ await waitForElement('.cookie-alert-configuration', 2000);
556
+ click('.cookie-alert-configuration-input:checked', true);
557
+ click('.cookie-alert-extended-button-secondary');
558
+ return true;
559
+ }
560
+ if (elementExists('#dtcookie-container')) {
561
+ return click('.h-dtcookie-decline');
562
+ }
563
+ if (click('.cookiebot__button--settings')) {
564
+ return true;
565
+ }
566
+ if (click('#CybotCookiebotDialogBodyButtonDecline')) {
567
+ return true;
568
+ }
569
+ click('.cookiebanner__link--details');
570
+ click('.CybotCookiebotDialogBodyLevelButton:checked:enabled,input[id*="CybotCookiebotDialogBodyLevelButton"]:checked:enabled', true);
571
+ click('#CybotCookiebotDialogBodyButtonDecline');
572
+ click('input[id^=CybotCookiebotDialogBodyLevelButton]:checked', true);
573
+ if (elementExists('#CybotCookiebotDialogBodyButtonAcceptSelected')) {
574
+ click('#CybotCookiebotDialogBodyButtonAcceptSelected');
575
+ }
576
+ else {
577
+ click('#CybotCookiebotDialogBodyLevelButtonAccept,#CybotCookiebotDialogBodyButtonAccept,#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowallSelection', true);
578
+ }
579
+ // some sites have custom submit buttons with no obvious selectors. In this case we just call the submitConsent API.
580
+ if (await doEval('window.CookieConsent.hasResponse !== true')) {
581
+ await doEval('window.Cookiebot.dialog.submitConsent()');
582
+ await wait(500);
583
+ }
584
+ // site with 3rd confirm settings modal
585
+ if (elementExists('#cb-confirmedSettings')) {
586
+ await doEval('endCookieProcess()');
587
+ }
588
+ return true;
589
+ }
590
+ async optIn() {
591
+ if (elementExists('#dtcookie-container')) {
592
+ return click('.h-dtcookie-accept');
593
+ }
594
+ click('.CybotCookiebotDialogBodyLevelButton:not(:checked):enabled', true);
595
+ click('#CybotCookiebotDialogBodyLevelButtonAccept');
596
+ click('#CybotCookiebotDialogBodyButtonAccept');
597
+ return true;
598
+ }
599
+ async test() {
600
+ return doEval('window.CookieConsent.declined === true');
601
+ }
602
+ }
603
+
604
+ class SourcePoint extends AutoConsentCMPBase {
605
+ constructor() {
606
+ super("Sourcepoint-frame");
607
+ this.prehideSelectors = ["div[id^='sp_message_container_'],.message-overlay", '#sp_privacy_manager_container'];
608
+ this.ccpaNotice = false;
609
+ this.ccpaPopup = false;
610
+ this.runContext = {
611
+ main: false,
612
+ frame: true,
613
+ };
614
+ }
615
+ get hasSelfTest() {
616
+ return false; // self-test is done by parent frame
617
+ }
618
+ get isIntermediate() {
619
+ return false;
620
+ }
621
+ get isCosmetic() {
622
+ return false;
623
+ }
624
+ async detectCmp() {
625
+ const url = new URL(location.href);
626
+ if (url.searchParams.has('message_id') && url.hostname === 'ccpa-notice.sp-prod.net') {
627
+ this.ccpaNotice = true;
628
+ return true;
629
+ }
630
+ if (url.hostname === 'ccpa-pm.sp-prod.net') {
631
+ this.ccpaPopup = true;
632
+ return true;
633
+ }
634
+ return (url.pathname === '/index.html' || url.pathname === '/privacy-manager/index.html')
635
+ && (url.searchParams.has('message_id') || url.searchParams.has('requestUUID') || url.searchParams.has('consentUUID'));
636
+ }
637
+ async detectPopup() {
638
+ if (this.ccpaNotice) {
639
+ return true;
640
+ }
641
+ if (this.ccpaPopup) {
642
+ return await waitForElement('.priv-save-btn', 2000);
643
+ }
644
+ // check for the paywall button, and bail if it exists to prevent broken opt out
645
+ await waitForElement(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL", 2000);
646
+ return !elementExists('.sp_choice_type_9');
647
+ }
648
+ async optIn() {
649
+ await waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL", 2000);
650
+ if (click(".sp_choice_type_11")) {
651
+ return true;
652
+ }
653
+ if (click('.sp_choice_type_ACCEPT_ALL')) {
654
+ return true;
655
+ }
656
+ return false;
657
+ }
658
+ isManagerOpen() {
659
+ return location.pathname === "/privacy-manager/index.html";
660
+ }
661
+ async optOut() {
662
+ if (this.ccpaPopup) {
663
+ // toggles with 2 buttons
664
+ const toggles = document.querySelectorAll('.priv-purpose-container .sp-switch-arrow-block a.neutral.on .right');
665
+ for (const t of toggles) {
666
+ click([t]);
667
+ }
668
+ // switch toggles
669
+ const switches = document.querySelectorAll('.priv-purpose-container .sp-switch-arrow-block a.switch-bg.on');
670
+ for (const t of switches) {
671
+ click([t]);
672
+ }
673
+ return click('.priv-save-btn');
674
+ }
675
+ if (!this.isManagerOpen()) {
676
+ const actionable = await waitForElement('.sp_choice_type_12,.sp_choice_type_13');
677
+ if (!actionable) {
678
+ return false;
679
+ }
680
+ if (!elementExists(".sp_choice_type_12")) {
681
+ // do not sell button
682
+ return click(".sp_choice_type_13");
683
+ }
684
+ click(".sp_choice_type_12");
685
+ // the page may navigate at this point but that's okay
686
+ await waitFor(() => this.isManagerOpen(), 200, 100);
687
+ }
688
+ await waitForElement('.type-modal', 20000);
689
+ // reject all button is offered by some sites
690
+ try {
691
+ const rejectSelector1 = '.sp_choice_type_REJECT_ALL';
692
+ const rejectSelector2 = '.reject-toggle';
693
+ const path = await Promise.race([
694
+ waitForElement(rejectSelector1, 2000).then(success => success ? 0 : -1),
695
+ waitForElement(rejectSelector2, 2000).then(success => success ? 1 : -1),
696
+ waitForElement('.pm-features', 2000).then(success => success ? 2 : -1),
697
+ ]);
698
+ if (path === 0) {
699
+ await wait(1000);
700
+ return click(rejectSelector1);
701
+ }
702
+ else if (path === 1) {
703
+ click(rejectSelector2);
704
+ }
705
+ else if (path === 2) {
706
+ await waitForElement('.pm-features', 10000);
707
+ click('.checked > span', true);
708
+ click('.chevron');
709
+ }
710
+ }
711
+ catch (e) {
712
+ }
713
+ // TODO: race condition: the popup disappears very quickly, so the background script may not receive a success report.
714
+ return click('.sp_choice_type_SAVE_AND_EXIT');
715
+ }
716
+ }
717
+
718
+ // Note: JS API is also available:
719
+ // https://help.consentmanager.net/books/cmp/page/javascript-api
720
+ class ConsentManager extends AutoConsentCMPBase {
721
+ constructor() {
722
+ super("consentmanager.net");
723
+ this.prehideSelectors = ["#cmpbox,#cmpbox2"];
724
+ this.apiAvailable = false;
725
+ }
726
+ get hasSelfTest() {
727
+ return this.apiAvailable;
728
+ }
729
+ get isIntermediate() {
730
+ return false;
731
+ }
732
+ get isCosmetic() {
733
+ return false;
734
+ }
735
+ async detectCmp() {
736
+ this.apiAvailable = await doEval('window.__cmp && typeof __cmp("getCMPData") === "object"');
737
+ if (!this.apiAvailable) {
738
+ return elementExists("#cmpbox");
739
+ }
740
+ else {
741
+ return true;
742
+ }
743
+ }
744
+ async detectPopup() {
745
+ if (this.apiAvailable) {
746
+ // wait before making this check because early in the page lifecycle this may incorrectly return
747
+ // true, causing an opt-out when it is not needed.
748
+ await wait(500);
749
+ return await doEval("!__cmp('consentStatus').userChoiceExists");
750
+ }
751
+ return elementVisible("#cmpbox .cmpmore", 'any');
752
+ }
753
+ async optOut() {
754
+ await wait(500);
755
+ if (this.apiAvailable) {
756
+ return await doEval("__cmp('setConsent', 0)");
757
+ }
758
+ if (click(".cmpboxbtnno")) {
759
+ return true;
760
+ }
761
+ if (elementExists(".cmpwelcomeprpsbtn")) {
762
+ click(".cmpwelcomeprpsbtn > a[aria-checked=true]", true);
763
+ click(".cmpboxbtnsave");
764
+ return true;
765
+ }
766
+ click(".cmpboxbtncustom");
767
+ await waitForElement(".cmptblbox", 2000);
768
+ click(".cmptdchoice > a[aria-checked=true]", true);
769
+ click(".cmpboxbtnyescustomchoices");
770
+ return true;
771
+ }
772
+ async optIn() {
773
+ if (this.apiAvailable) {
774
+ return await doEval("__cmp('setConsent', 1)");
775
+ }
776
+ return click(".cmpboxbtnyes");
777
+ }
778
+ async test() {
779
+ if (this.apiAvailable) {
780
+ return await doEval("__cmp('consentStatus').userChoiceExists");
781
+ }
782
+ }
783
+ }
784
+
785
+ class Evidon extends AutoConsentCMPBase {
786
+ constructor() {
787
+ super("Evidon");
788
+ }
789
+ get hasSelfTest() {
790
+ return false;
791
+ }
792
+ get isIntermediate() {
793
+ return false;
794
+ }
795
+ get isCosmetic() {
796
+ return false;
797
+ }
798
+ async detectCmp() {
799
+ return elementExists("#_evidon_banner");
800
+ }
801
+ async detectPopup() {
802
+ return elementVisible("#_evidon_banner", 'any');
803
+ }
804
+ async optOut() {
805
+ if (click("#_evidon-decline-button")) {
806
+ return true;
807
+ }
808
+ hideElements(getStyleElement(), ["#evidon-prefdiag-overlay", "#evidon-prefdiag-background"]);
809
+ click("#_evidon-option-button");
810
+ await waitForElement("#evidon-prefdiag-overlay", 5000);
811
+ click("#evidon-prefdiag-decline");
812
+ return true;
813
+ }
814
+ async optIn() {
815
+ return click("#_evidon-accept-button");
816
+ }
817
+ }
818
+
819
+ class Onetrust extends AutoConsentCMPBase {
820
+ constructor() {
821
+ super("Onetrust");
822
+ this.prehideSelectors = ["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"];
823
+ }
824
+ get hasSelfTest() {
825
+ return true;
826
+ }
827
+ get isIntermediate() {
828
+ return false;
829
+ }
830
+ get isCosmetic() {
831
+ return false;
832
+ }
833
+ async detectCmp() {
834
+ return elementExists("#onetrust-banner-sdk");
835
+ }
836
+ async detectPopup() {
837
+ return elementVisible("#onetrust-banner-sdk", 'all');
838
+ }
839
+ async optOut() {
840
+ if (elementExists("#onetrust-pc-btn-handler")) { // "show purposes" button inside a popup
841
+ click("#onetrust-pc-btn-handler");
842
+ }
843
+ else { // otherwise look for a generic "show settings" button
844
+ click(".ot-sdk-show-settings,button.js-cookie-settings");
845
+ }
846
+ await waitForElement('#onetrust-consent-sdk', 2000);
847
+ await wait(1000);
848
+ click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked", true); // optional step
849
+ await wait(1000);
850
+ await waitForElement(".save-preference-btn-handler,.js-consent-save", 2000);
851
+ click(".save-preference-btn-handler,.js-consent-save");
852
+ // popup doesn't disappear immediately
853
+ await waitFor(() => elementVisible("#onetrust-banner-sdk", 'none'), 10, 500);
854
+ return true;
855
+ }
856
+ async optIn() {
857
+ return click("#onetrust-accept-btn-handler,.js-accept-cookies");
858
+ }
859
+ async test() {
860
+ return await doEval("window.OnetrustActiveGroups.split(',').filter(s => s.length > 0).length <= 1");
861
+ }
862
+ }
863
+
864
+ class Klaro extends AutoConsentCMPBase {
865
+ constructor() {
866
+ super("Klaro");
867
+ this.prehideSelectors = [".klaro"];
868
+ this.settingsOpen = false;
869
+ }
870
+ get hasSelfTest() {
871
+ return true;
872
+ }
873
+ get isIntermediate() {
874
+ return false;
875
+ }
876
+ get isCosmetic() {
877
+ return false;
878
+ }
879
+ async detectCmp() {
880
+ if (elementExists('.klaro > .cookie-modal')) {
881
+ this.settingsOpen = true;
882
+ return true;
883
+ }
884
+ return elementExists(".klaro > .cookie-notice");
885
+ }
886
+ async detectPopup() {
887
+ return elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal", 'any');
888
+ }
889
+ async optOut() {
890
+ if (click('.klaro .cn-decline')) {
891
+ return true;
892
+ }
893
+ if (!this.settingsOpen) {
894
+ click('.klaro .cn-learn-more');
895
+ await waitForElement('.klaro > .cookie-modal', 2000);
896
+ this.settingsOpen = true;
897
+ }
898
+ if (click('.klaro .cn-decline')) {
899
+ return true;
900
+ }
901
+ click('.cm-purpose:not(.cm-toggle-all) > input:not(.half-checked)', true);
902
+ return click('.cm-btn-accept');
903
+ }
904
+ async optIn() {
905
+ if (click('.klaro .cm-btn-accept-all')) {
906
+ return true;
907
+ }
908
+ if (this.settingsOpen) {
909
+ click('.cm-purpose:not(.cm-toggle-all) > input.half-checked', true);
910
+ return click('.cm-btn-accept');
911
+ }
912
+ return click('.klaro .cookie-notice .cm-btn-success');
913
+ }
914
+ async test() {
915
+ return await doEval('klaro.getManager().config.services.every(c => c.required || !klaro.getManager().consents[c.name])');
916
+ }
917
+ }
918
+
919
+ class Uniconsent extends AutoConsentCMPBase {
920
+ constructor() {
921
+ super("Uniconsent");
922
+ }
923
+ get prehideSelectors() {
924
+ return ['.unic', '.modal:has(.unic)'];
925
+ }
926
+ get hasSelfTest() {
927
+ return true;
928
+ }
929
+ get isIntermediate() {
930
+ return false;
931
+ }
932
+ get isCosmetic() {
933
+ return false;
934
+ }
935
+ async detectCmp() {
936
+ return elementExists(".unic .unic-box,.unic .unic-bar");
937
+ }
938
+ async detectPopup() {
939
+ return elementVisible(".unic .unic-box,.unic .unic-bar", 'any');
940
+ }
941
+ async optOut() {
942
+ await waitForElement(".unic button", 1000);
943
+ document.querySelectorAll(".unic button").forEach((button) => {
944
+ const text = button.textContent;
945
+ if (text.includes('Manage Options') || text.includes('Optionen verwalten')) {
946
+ button.click();
947
+ }
948
+ });
949
+ if (await waitForElement('.unic input[type=checkbox]', 1000)) {
950
+ await waitForElement('.unic button', 1000);
951
+ document.querySelectorAll('.unic input[type=checkbox]').forEach((c) => {
952
+ if (c.checked) {
953
+ c.click();
954
+ }
955
+ });
956
+ for (const b of document.querySelectorAll('.unic button')) {
957
+ const text = b.textContent;
958
+ for (const pattern of ['Confirm Choices', 'Save Choices', 'Auswahl speichern']) {
959
+ if (text.includes(pattern)) {
960
+ b.click();
961
+ await wait(500); // give it some time to close the popup
962
+ return true;
963
+ }
964
+ }
965
+ }
966
+ }
967
+ return false;
968
+ }
969
+ async optIn() {
970
+ return waitForThenClick(".unic #unic-agree");
971
+ }
972
+ async test() {
973
+ await wait(1000);
974
+ const res = elementExists(".unic .unic-box,.unic .unic-bar");
975
+ return !res;
976
+ }
977
+ }
978
+
979
+ class Conversant extends AutoConsentCMPBase {
980
+ constructor() {
981
+ super("Conversant");
982
+ this.prehideSelectors = [".cmp-root"];
983
+ }
984
+ get hasSelfTest() {
985
+ return true;
986
+ }
987
+ get isIntermediate() {
988
+ return false;
989
+ }
990
+ get isCosmetic() {
991
+ return false;
992
+ }
993
+ async detectCmp() {
994
+ return elementExists(".cmp-root .cmp-receptacle");
995
+ }
996
+ async detectPopup() {
997
+ return elementVisible(".cmp-root .cmp-receptacle", 'any');
998
+ }
999
+ async optOut() {
1000
+ if (!(await waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)"))) {
1001
+ return false;
1002
+ }
1003
+ if (!(await waitForElement(".cmp-view-tab-tabs"))) {
1004
+ return false;
1005
+ }
1006
+ await waitForThenClick(".cmp-view-tab-tabs > :first-child");
1007
+ await waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");
1008
+ for (const item of Array.from(document.querySelectorAll('.cmp-accordion-item'))) {
1009
+ item.querySelector('.cmp-accordion-item-title').click();
1010
+ await waitFor(() => !!item.querySelector('.cmp-accordion-item-content.cmp-active'), 10, 50);
1011
+ const content = item.querySelector('.cmp-accordion-item-content.cmp-active');
1012
+ content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)').forEach((e) => e.click());
1013
+ content.querySelectorAll('.cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)').forEach((e) => e.click());
1014
+ // await waitFor(() => !item.querySelector('.cmp-toggle-deny--active,.cmp-toggle-checkbox--active'), 5, 50); // this may take a long time
1015
+ }
1016
+ await click(".cmp-main-button:not(.cmp-main-button--primary)");
1017
+ return true;
1018
+ }
1019
+ async optIn() {
1020
+ return waitForThenClick(".cmp-main-button.cmp-main-button--primary");
1021
+ }
1022
+ async test() {
1023
+ return document.cookie.includes('cmp-data=0');
1024
+ }
1025
+ }
1026
+
1027
+ class Tiktok extends AutoConsentCMPBase {
1028
+ constructor() {
1029
+ super("tiktok.com");
1030
+ this.runContext = {
1031
+ urlPattern: 'tiktok'
1032
+ };
1033
+ }
1034
+ get hasSelfTest() {
1035
+ return true;
1036
+ }
1037
+ get isIntermediate() {
1038
+ return false;
1039
+ }
1040
+ get isCosmetic() {
1041
+ return false;
1042
+ }
1043
+ getShadowRoot() {
1044
+ const container = document.querySelector('tiktok-cookie-banner');
1045
+ if (!container) {
1046
+ return null;
1047
+ }
1048
+ return container.shadowRoot;
1049
+ }
1050
+ async detectCmp() {
1051
+ return elementExists("tiktok-cookie-banner");
1052
+ }
1053
+ async detectPopup() {
1054
+ const banner = this.getShadowRoot().querySelector('.tiktok-cookie-banner');
1055
+ return isElementVisible(banner);
1056
+ }
1057
+ async optOut() {
1058
+ const declineButton = this.getShadowRoot().querySelector('.button-wrapper button:first-child');
1059
+ if (declineButton) {
1060
+ declineButton.click();
1061
+ return true;
1062
+ }
1063
+ else {
1064
+ return false;
1065
+ }
1066
+ }
1067
+ async optIn() {
1068
+ const acceptButton = this.getShadowRoot().querySelector('.button-wrapper button:last-child');
1069
+ if (acceptButton) {
1070
+ acceptButton.click();
1071
+ return true;
1072
+ }
1073
+ else {
1074
+ return false;
1075
+ }
1076
+ }
1077
+ async test() {
1078
+ const match = document.cookie.match(/cookie-consent=([^;]+)/);
1079
+ if (!match) {
1080
+ return false;
1081
+ }
1082
+ const value = JSON.parse(decodeURIComponent(match[1]));
1083
+ return Object.values(value).every(x => typeof x !== 'boolean' || x === false);
1084
+ }
1085
+ }
1086
+
1087
+ class Airbnb extends AutoConsentCMPBase {
1088
+ constructor() {
1089
+ super("airbnb");
1090
+ this.runContext = {
1091
+ urlPattern: '^https://(www\\.)?airbnb\\.[^/]+/'
1092
+ };
1093
+ this.prehideSelectors = [
1094
+ "div[data-testid=main-cookies-banner-container]",
1095
+ "div:has(> div:first-child):has(> div:last-child):has(> section [data-testid=\"strictly-necessary-cookies\"])"
1096
+ ];
1097
+ }
1098
+ get hasSelfTest() {
1099
+ return true;
1100
+ }
1101
+ get isIntermediate() {
1102
+ return false;
1103
+ }
1104
+ get isCosmetic() {
1105
+ return false;
1106
+ }
1107
+ async detectCmp() {
1108
+ return elementExists('div[data-testid=main-cookies-banner-container]');
1109
+ }
1110
+ async detectPopup() {
1111
+ return elementVisible('div[data-testid=main-cookies-banner-container', 'any');
1112
+ }
1113
+ async optOut() {
1114
+ await waitForThenClick('div[data-testid=main-cookies-banner-container] button._snbhip0');
1115
+ let check;
1116
+ // eslint-disable-next-line no-cond-assign
1117
+ while (check = document.querySelector('[data-testid=modal-container] button[aria-checked=true]:not([disabled])')) { // each click may toggle multiple checkboxes
1118
+ check.click();
1119
+ }
1120
+ return waitForThenClick('button[data-testid=save-btn]');
1121
+ }
1122
+ async optIn() {
1123
+ return waitForThenClick('div[data-testid=main-cookies-banner-container] button._148dgdpk');
1124
+ }
1125
+ async test() {
1126
+ return await waitFor(() => !!document.cookie.match('OptanonAlertBoxClosed'), 20, 200);
1127
+ }
1128
+ }
1129
+
1130
+ const rules$1 = [
1131
+ new TrustArcTop(),
1132
+ new TrustArcFrame(),
1133
+ new Cookiebot(),
1134
+ new SourcePoint(),
1135
+ new ConsentManager(),
1136
+ new Evidon(),
1137
+ new Onetrust(),
1138
+ new Klaro(),
1139
+ new Uniconsent(),
1140
+ new Conversant(),
1141
+ new Tiktok(),
1142
+ new Airbnb(),
1143
+ ];
1144
+ function createAutoCMP(config) {
1145
+ return new AutoConsentCMP(config);
1146
+ }
1147
+
1148
+ const rules = rules$1;
1149
+
1150
+ /**
1151
+ * This code is in most parts copied from https://github.com/cavi-au/Consent-O-Matic/blob/master/Extension/Tools.js
1152
+ * which is licened under the MIT.
1153
+ */
1154
+ class Tools {
1155
+ static setBase(base) {
1156
+ Tools.base = base;
1157
+ }
1158
+ static findElement(options, parent = null, multiple = false) {
1159
+ let possibleTargets = null;
1160
+ if (parent != null) {
1161
+ possibleTargets = Array.from(parent.querySelectorAll(options.selector));
1162
+ }
1163
+ else {
1164
+ if (Tools.base != null) {
1165
+ possibleTargets = Array.from(Tools.base.querySelectorAll(options.selector));
1166
+ }
1167
+ else {
1168
+ possibleTargets = Array.from(document.querySelectorAll(options.selector));
1169
+ }
1170
+ }
1171
+ if (options.textFilter != null) {
1172
+ possibleTargets = possibleTargets.filter(possibleTarget => {
1173
+ const textContent = possibleTarget.textContent.toLowerCase();
1174
+ if (Array.isArray(options.textFilter)) {
1175
+ let foundText = false;
1176
+ for (const text of options.textFilter) {
1177
+ if (textContent.indexOf(text.toLowerCase()) !== -1) {
1178
+ foundText = true;
1179
+ break;
1180
+ }
1181
+ }
1182
+ return foundText;
1183
+ }
1184
+ else if (options.textFilter != null) {
1185
+ return textContent.indexOf(options.textFilter.toLowerCase()) !== -1;
1186
+ }
1187
+ });
1188
+ }
1189
+ if (options.styleFilters != null) {
1190
+ possibleTargets = possibleTargets.filter(possibleTarget => {
1191
+ const styles = window.getComputedStyle(possibleTarget);
1192
+ let keep = true;
1193
+ for (const styleFilter of options.styleFilters) {
1194
+ const option = styles[styleFilter.option];
1195
+ if (styleFilter.negated) {
1196
+ keep = keep && option !== styleFilter.value;
1197
+ }
1198
+ else {
1199
+ keep = keep && option === styleFilter.value;
1200
+ }
1201
+ }
1202
+ return keep;
1203
+ });
1204
+ }
1205
+ if (options.displayFilter != null) {
1206
+ possibleTargets = possibleTargets.filter(possibleTarget => {
1207
+ if (options.displayFilter) {
1208
+ //We should be displayed
1209
+ return possibleTarget.offsetHeight !== 0;
1210
+ }
1211
+ else {
1212
+ //We should not be displayed
1213
+ return possibleTarget.offsetHeight === 0;
1214
+ }
1215
+ });
1216
+ }
1217
+ if (options.iframeFilter != null) {
1218
+ possibleTargets = possibleTargets.filter(( /* possibleTarget */) => {
1219
+ if (options.iframeFilter) {
1220
+ //We should be inside an iframe
1221
+ return window.location !== window.parent.location;
1222
+ }
1223
+ else {
1224
+ //We should not be inside an iframe
1225
+ return window.location === window.parent.location;
1226
+ }
1227
+ });
1228
+ }
1229
+ if (options.childFilter != null) {
1230
+ possibleTargets = possibleTargets.filter(possibleTarget => {
1231
+ const oldBase = Tools.base;
1232
+ Tools.setBase(possibleTarget);
1233
+ const childResults = Tools.find(options.childFilter);
1234
+ Tools.setBase(oldBase);
1235
+ return childResults.target != null;
1236
+ });
1237
+ }
1238
+ if (multiple) {
1239
+ return possibleTargets;
1240
+ }
1241
+ else {
1242
+ if (possibleTargets.length > 1) {
1243
+ console.warn("Multiple possible targets: ", possibleTargets, options, parent);
1244
+ }
1245
+ return possibleTargets[0];
1246
+ }
1247
+ }
1248
+ static find(options, multiple = false) {
1249
+ const results = [];
1250
+ if (options.parent != null) {
1251
+ const parent = Tools.findElement(options.parent, null, multiple);
1252
+ if (parent != null) {
1253
+ if (parent instanceof Array) {
1254
+ parent.forEach(p => {
1255
+ const targets = Tools.findElement(options.target, p, multiple);
1256
+ if (targets instanceof Array) {
1257
+ targets.forEach(target => {
1258
+ results.push({
1259
+ parent: p,
1260
+ target: target
1261
+ });
1262
+ });
1263
+ }
1264
+ else {
1265
+ results.push({
1266
+ parent: p,
1267
+ target: targets
1268
+ });
1269
+ }
1270
+ });
1271
+ return results;
1272
+ }
1273
+ else {
1274
+ const targets = Tools.findElement(options.target, parent, multiple);
1275
+ if (targets instanceof Array) {
1276
+ targets.forEach(target => {
1277
+ results.push({
1278
+ parent: parent,
1279
+ target: target
1280
+ });
1281
+ });
1282
+ }
1283
+ else {
1284
+ results.push({
1285
+ parent: parent,
1286
+ target: targets
1287
+ });
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ else {
1293
+ const targets = Tools.findElement(options.target, null, multiple);
1294
+ if (targets instanceof Array) {
1295
+ targets.forEach(target => {
1296
+ results.push({
1297
+ parent: null,
1298
+ target: target
1299
+ });
1300
+ });
1301
+ }
1302
+ else {
1303
+ results.push({
1304
+ parent: null,
1305
+ target: targets
1306
+ });
1307
+ }
1308
+ }
1309
+ if (results.length === 0) {
1310
+ results.push({
1311
+ parent: null,
1312
+ target: null
1313
+ });
1314
+ }
1315
+ if (multiple) {
1316
+ return results;
1317
+ }
1318
+ else {
1319
+ if (results.length !== 1) {
1320
+ console.warn("Multiple results found, even though multiple false", results);
1321
+ }
1322
+ return results[0];
1323
+ }
1324
+ }
1325
+ }
1326
+ Tools.base = null;
1327
+
1328
+ function matches(config) {
1329
+ const result = Tools.find(config);
1330
+ if (config.type === "css") {
1331
+ return !!result.target;
1332
+ }
1333
+ else if (config.type === "checkbox") {
1334
+ return !!result.target && result.target.checked;
1335
+ }
1336
+ }
1337
+ async function executeAction(config, param) {
1338
+ switch (config.type) {
1339
+ case "click":
1340
+ return clickAction(config);
1341
+ case "list":
1342
+ return listAction(config, param);
1343
+ case "consent":
1344
+ return consentAction(config, param);
1345
+ case "ifcss":
1346
+ return ifCssAction(config, param);
1347
+ case "waitcss":
1348
+ return waitCssAction(config);
1349
+ case "foreach":
1350
+ return forEachAction(config, param);
1351
+ case "hide":
1352
+ return hideAction(config);
1353
+ case "slide":
1354
+ return slideAction(config);
1355
+ case "close":
1356
+ return closeAction();
1357
+ case "wait":
1358
+ return waitAction(config);
1359
+ case "eval":
1360
+ return evalAction(config);
1361
+ default:
1362
+ throw "Unknown action type: " + config.type;
1363
+ }
1364
+ }
1365
+ const STEP_TIMEOUT = 0;
1366
+ function waitTimeout(timeout) {
1367
+ return new Promise(resolve => {
1368
+ setTimeout(() => {
1369
+ resolve();
1370
+ }, timeout);
1371
+ });
1372
+ }
1373
+ async function clickAction(config) {
1374
+ const result = Tools.find(config);
1375
+ if (result.target != null) {
1376
+ result.target.click();
1377
+ }
1378
+ return waitTimeout(STEP_TIMEOUT);
1379
+ }
1380
+ async function listAction(config, param) {
1381
+ for (const action of config.actions) {
1382
+ await executeAction(action, param);
1383
+ }
1384
+ }
1385
+ async function consentAction(config, consentTypes) {
1386
+ for (const consentConfig of config.consents) {
1387
+ const shouldEnable = consentTypes.indexOf(consentConfig.type) !== -1;
1388
+ if (consentConfig.matcher && consentConfig.toggleAction) {
1389
+ const isEnabled = matches(consentConfig.matcher);
1390
+ if (isEnabled !== shouldEnable) {
1391
+ await executeAction(consentConfig.toggleAction);
1392
+ }
1393
+ }
1394
+ else {
1395
+ if (shouldEnable) {
1396
+ await executeAction(consentConfig.trueAction);
1397
+ }
1398
+ else {
1399
+ await executeAction(consentConfig.falseAction);
1400
+ }
1401
+ }
1402
+ }
1403
+ }
1404
+ async function ifCssAction(config, param) {
1405
+ const result = Tools.find(config);
1406
+ if (!result.target) {
1407
+ if (config.trueAction) {
1408
+ await executeAction(config.trueAction, param);
1409
+ }
1410
+ }
1411
+ else {
1412
+ if (config.falseAction) {
1413
+ await executeAction(config.falseAction, param);
1414
+ }
1415
+ }
1416
+ }
1417
+ async function waitCssAction(config) {
1418
+ await new Promise(resolve => {
1419
+ let numRetries = config.retries || 10;
1420
+ const waitTime = config.waitTime || 250;
1421
+ const checkCss = () => {
1422
+ const result = Tools.find(config);
1423
+ if ((config.negated && result.target) ||
1424
+ (!config.negated && !result.target)) {
1425
+ if (numRetries > 0) {
1426
+ numRetries -= 1;
1427
+ setTimeout(checkCss, waitTime);
1428
+ }
1429
+ else {
1430
+ resolve();
1431
+ }
1432
+ }
1433
+ else {
1434
+ resolve();
1435
+ }
1436
+ };
1437
+ checkCss();
1438
+ });
1439
+ }
1440
+ async function forEachAction(config, param) {
1441
+ const results = Tools.find(config, true);
1442
+ const oldBase = Tools.base;
1443
+ for (const result of results) {
1444
+ if (result.target) {
1445
+ Tools.setBase(result.target);
1446
+ await executeAction(config.action, param);
1447
+ }
1448
+ }
1449
+ Tools.setBase(oldBase);
1450
+ }
1451
+ async function hideAction(config) {
1452
+ const result = Tools.find(config);
1453
+ if (result.target) {
1454
+ result.target.classList.add("Autoconsent-Hidden");
1455
+ // result.target.setAttribute("style", "display: none;");
1456
+ }
1457
+ }
1458
+ async function slideAction(config) {
1459
+ const result = Tools.find(config);
1460
+ const dragResult = Tools.find(config.dragTarget);
1461
+ if (result.target) {
1462
+ const targetBounds = result.target.getBoundingClientRect();
1463
+ const dragTargetBounds = dragResult.target.getBoundingClientRect();
1464
+ let yDiff = dragTargetBounds.top - targetBounds.top;
1465
+ let xDiff = dragTargetBounds.left - targetBounds.left;
1466
+ if (this.config.axis.toLowerCase() === "y") {
1467
+ xDiff = 0;
1468
+ }
1469
+ if (this.config.axis.toLowerCase() === "x") {
1470
+ yDiff = 0;
1471
+ }
1472
+ const screenX = window.screenX + targetBounds.left + targetBounds.width / 2.0;
1473
+ const screenY = window.screenY + targetBounds.top + targetBounds.height / 2.0;
1474
+ const clientX = targetBounds.left + targetBounds.width / 2.0;
1475
+ const clientY = targetBounds.top + targetBounds.height / 2.0;
1476
+ const mouseDown = document.createEvent("MouseEvents");
1477
+ mouseDown.initMouseEvent("mousedown", true, true, window, 0, screenX, screenY, clientX, clientY, false, false, false, false, 0, result.target);
1478
+ const mouseMove = document.createEvent("MouseEvents");
1479
+ mouseMove.initMouseEvent("mousemove", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
1480
+ const mouseUp = document.createEvent("MouseEvents");
1481
+ mouseUp.initMouseEvent("mouseup", true, true, window, 0, screenX + xDiff, screenY + yDiff, clientX + xDiff, clientY + yDiff, false, false, false, false, 0, result.target);
1482
+ result.target.dispatchEvent(mouseDown);
1483
+ await this.waitTimeout(10);
1484
+ result.target.dispatchEvent(mouseMove);
1485
+ await this.waitTimeout(10);
1486
+ result.target.dispatchEvent(mouseUp);
1487
+ }
1488
+ }
1489
+ async function waitAction(config) {
1490
+ await waitTimeout(config.waitTime);
1491
+ }
1492
+ async function closeAction() {
1493
+ window.close();
1494
+ }
1495
+ async function evalAction(config) {
1496
+ console.log("eval!", config.code);
1497
+ return new Promise(resolve => {
1498
+ try {
1499
+ if (config.async) {
1500
+ window.eval(config.code);
1501
+ setTimeout(() => {
1502
+ resolve(window.eval("window.__consentCheckResult"));
1503
+ }, config.timeout || 250);
1504
+ }
1505
+ else {
1506
+ resolve(window.eval(config.code));
1507
+ }
1508
+ }
1509
+ catch (e) {
1510
+ console.warn("eval error", e, config.code);
1511
+ resolve(false);
1512
+ }
1513
+ });
1514
+ }
1515
+
1516
+ class ConsentOMaticCMP {
1517
+ constructor(name, config) {
1518
+ this.name = name;
1519
+ this.config = config;
1520
+ this.methods = new Map();
1521
+ this.runContext = defaultRunContext;
1522
+ this.isCosmetic = false;
1523
+ config.methods.forEach(methodConfig => {
1524
+ if (methodConfig.action) {
1525
+ this.methods.set(methodConfig.name, methodConfig.action);
1526
+ }
1527
+ });
1528
+ this.hasSelfTest = false;
1529
+ }
1530
+ get isIntermediate() {
1531
+ return false; // TODO: support UTILITY rules
1532
+ }
1533
+ checkRunContext() {
1534
+ return true;
1535
+ }
1536
+ async detectCmp() {
1537
+ const matchResults = this.config.detectors.map(detectorConfig => matches(detectorConfig.presentMatcher));
1538
+ return matchResults.some(r => !!r);
1539
+ }
1540
+ async detectPopup() {
1541
+ const matchResults = this.config.detectors.map(detectorConfig => matches(detectorConfig.showingMatcher));
1542
+ return matchResults.some(r => !!r);
1543
+ }
1544
+ async executeAction(method, param) {
1545
+ if (this.methods.has(method)) {
1546
+ return executeAction(this.methods.get(method), param);
1547
+ }
1548
+ return true;
1549
+ }
1550
+ async optOut() {
1551
+ await this.executeAction("HIDE_CMP");
1552
+ await this.executeAction("OPEN_OPTIONS");
1553
+ await this.executeAction("HIDE_CMP");
1554
+ await this.executeAction("DO_CONSENT", []);
1555
+ await this.executeAction("SAVE_CONSENT");
1556
+ return true;
1557
+ }
1558
+ async optIn() {
1559
+ await this.executeAction("HIDE_CMP");
1560
+ await this.executeAction("OPEN_OPTIONS");
1561
+ await this.executeAction("HIDE_CMP");
1562
+ await this.executeAction("DO_CONSENT", ['D', 'A', 'B', 'E', 'F', 'X']);
1563
+ await this.executeAction("SAVE_CONSENT");
1564
+ return true;
1565
+ }
1566
+ async openCmp() {
1567
+ await this.executeAction("HIDE_CMP");
1568
+ await this.executeAction("OPEN_OPTIONS");
1569
+ return true;
1570
+ }
1571
+ async test() {
1572
+ return true;
1573
+ }
1574
+ }
1575
+
1576
+ function filterCMPs(rules, config) {
1577
+ return rules.filter((cmp) => {
1578
+ return ((!config.disabledCmps || !config.disabledCmps.includes(cmp.name)) // CMP is not disabled
1579
+ &&
1580
+ (config.enableCosmeticRules || !cmp.isCosmetic) // CMP is not cosmetic or cosmetic rules are enabled
1581
+ );
1582
+ });
1583
+ }
1584
+ class AutoConsent {
1585
+ constructor(sendContentMessage, config = null, declarativeRules = null) {
1586
+ this.id = getRandomID();
1587
+ this.rules = [];
1588
+ this.foundCmp = null;
1589
+ this.state = {
1590
+ lifecycle: 'loading',
1591
+ prehideOn: false,
1592
+ findCmpAttempts: 0,
1593
+ detectedCmps: [],
1594
+ detectedPopups: [],
1595
+ selfTest: null,
1596
+ };
1597
+ evalState.sendContentMessage = sendContentMessage;
1598
+ this.sendContentMessage = sendContentMessage;
1599
+ this.rules = [...rules];
1600
+ this.updateState({ lifecycle: 'loading' });
1601
+ if (config) {
1602
+ this.initialize(config, declarativeRules);
1603
+ }
1604
+ else {
1605
+ if (declarativeRules) {
1606
+ this.parseRules(declarativeRules);
1607
+ }
1608
+ const initMsg = {
1609
+ type: "init",
1610
+ url: window.location.href,
1611
+ };
1612
+ sendContentMessage(initMsg);
1613
+ this.updateState({ lifecycle: 'waitingForInitResponse' });
1614
+ }
1615
+ }
1616
+ initialize(config, declarativeRules) {
1617
+ this.config = config;
1618
+ if (!config.enabled) {
1619
+ return;
1620
+ }
1621
+ if (declarativeRules) {
1622
+ this.parseRules(declarativeRules);
1623
+ }
1624
+ this.rules = filterCMPs(this.rules, config);
1625
+ if (config.enablePrehide) {
1626
+ if (document.documentElement) {
1627
+ this.prehideElements(); // prehide as early as possible to prevent flickering
1628
+ }
1629
+ else {
1630
+ // we're injected really early
1631
+ const delayedPrehide = () => {
1632
+ window.removeEventListener('DOMContentLoaded', delayedPrehide);
1633
+ this.prehideElements();
1634
+ };
1635
+ window.addEventListener('DOMContentLoaded', delayedPrehide);
1636
+ }
1637
+ }
1638
+ // start detection
1639
+ if (document.readyState === 'loading') {
1640
+ const onReady = () => {
1641
+ window.removeEventListener('DOMContentLoaded', onReady);
1642
+ this.start();
1643
+ };
1644
+ window.addEventListener('DOMContentLoaded', onReady);
1645
+ }
1646
+ else {
1647
+ this.start();
1648
+ }
1649
+ this.updateState({ lifecycle: 'initialized' });
1650
+ }
1651
+ parseRules(declarativeRules) {
1652
+ Object.keys(declarativeRules.consentomatic).forEach((name) => {
1653
+ this.addConsentomaticCMP(name, declarativeRules.consentomatic[name]);
1654
+ });
1655
+ declarativeRules.autoconsent.forEach((rule) => {
1656
+ this.addCMP(rule);
1657
+ });
1658
+ }
1659
+ addCMP(config) {
1660
+ this.rules.push(createAutoCMP(config));
1661
+ }
1662
+ addConsentomaticCMP(name, config) {
1663
+ this.rules.push(new ConsentOMaticCMP(`com_${name}`, config));
1664
+ }
1665
+ // start the detection process, possibly with a delay
1666
+ start() {
1667
+ if (window.requestIdleCallback) {
1668
+ window.requestIdleCallback(() => this._start(), { timeout: 500 });
1669
+ }
1670
+ else {
1671
+ this._start();
1672
+ }
1673
+ }
1674
+ async _start() {
1675
+ this.updateState({ lifecycle: 'started' });
1676
+ const foundCmps = await this.findCmp(this.config.detectRetries);
1677
+ this.updateState({ detectedCmps: foundCmps.map(c => c.name) });
1678
+ if (foundCmps.length === 0) {
1679
+ if (this.config.enablePrehide) {
1680
+ this.undoPrehide();
1681
+ }
1682
+ this.updateState({ lifecycle: 'nothingDetected' });
1683
+ return false;
1684
+ }
1685
+ this.updateState({ lifecycle: 'cmpDetected' });
1686
+ // we resort to cosmetic rules only if no non-cosmetic rules are found
1687
+ let foundPopups = await this.detectPopups(foundCmps.filter(r => !r.isCosmetic));
1688
+ if (foundPopups.length === 0) {
1689
+ foundPopups = await this.detectPopups(foundCmps.filter(r => r.isCosmetic));
1690
+ }
1691
+ if (foundPopups.length === 0) {
1692
+ if (this.config.enablePrehide) {
1693
+ this.undoPrehide();
1694
+ }
1695
+ return false;
1696
+ }
1697
+ this.updateState({ lifecycle: 'openPopupDetected' });
1698
+ if (foundPopups.length > 1) {
1699
+ const errorDetails = {
1700
+ msg: `Found multiple CMPs, check the detection rules.`,
1701
+ cmps: foundPopups.map((cmp) => cmp.name),
1702
+ };
1703
+ this.sendContentMessage({
1704
+ type: 'autoconsentError',
1705
+ details: errorDetails,
1706
+ });
1707
+ }
1708
+ this.foundCmp = foundPopups[0];
1709
+ if (this.config.autoAction === 'optOut') {
1710
+ return await this.doOptOut();
1711
+ }
1712
+ else if (this.config.autoAction === 'optIn') {
1713
+ return await this.doOptIn();
1714
+ }
1715
+ else {
1716
+ return true;
1717
+ }
1718
+ }
1719
+ async findCmp(retries) {
1720
+ this.updateState({ findCmpAttempts: this.state.findCmpAttempts + 1 });
1721
+ const foundCMPs = [];
1722
+ for (const cmp of this.rules) {
1723
+ try {
1724
+ if (!cmp.checkRunContext()) {
1725
+ continue;
1726
+ }
1727
+ const result = await cmp.detectCmp();
1728
+ if (result) {
1729
+ enableLogs && console.log(`Found CMP: ${cmp.name} ${window.location.href}`);
1730
+ this.sendContentMessage({
1731
+ type: 'cmpDetected',
1732
+ url: location.href,
1733
+ cmp: cmp.name,
1734
+ }); // notify the browser
1735
+ foundCMPs.push(cmp);
1736
+ }
1737
+ }
1738
+ catch (e) {
1739
+ }
1740
+ }
1741
+ if (foundCMPs.length === 0 && retries > 0) {
1742
+ return new Promise((resolve) => {
1743
+ setTimeout(async () => {
1744
+ const result = this.findCmp(retries - 1);
1745
+ resolve(result);
1746
+ }, 500);
1747
+ });
1748
+ }
1749
+ return foundCMPs;
1750
+ }
1751
+ async detectPopups(cmps) {
1752
+ const result = [];
1753
+ const popupLookups = cmps.map((cmp) => this.waitForPopup(cmp).then((isOpen) => {
1754
+ if (isOpen) {
1755
+ this.updateState({ detectedPopups: this.state.detectedPopups.concat([cmp.name]) });
1756
+ this.sendContentMessage({
1757
+ type: 'popupFound',
1758
+ cmp: cmp.name,
1759
+ url: location.href,
1760
+ }); // notify the browser
1761
+ result.push(cmp);
1762
+ }
1763
+ }).catch(() => null));
1764
+ await Promise.all(popupLookups);
1765
+ return result;
1766
+ }
1767
+ async doOptOut() {
1768
+ this.updateState({ lifecycle: 'runningOptOut' });
1769
+ let optOutResult;
1770
+ if (!this.foundCmp) {
1771
+ optOutResult = false;
1772
+ }
1773
+ else {
1774
+ optOutResult = await this.foundCmp.optOut();
1775
+ }
1776
+ if (this.config.enablePrehide) {
1777
+ this.undoPrehide();
1778
+ }
1779
+ this.sendContentMessage({
1780
+ type: 'optOutResult',
1781
+ cmp: this.foundCmp ? this.foundCmp.name : 'none',
1782
+ result: optOutResult,
1783
+ scheduleSelfTest: this.foundCmp && this.foundCmp.hasSelfTest,
1784
+ url: location.href,
1785
+ });
1786
+ if (optOutResult && !this.foundCmp.isIntermediate) {
1787
+ this.sendContentMessage({
1788
+ type: 'autoconsentDone',
1789
+ cmp: this.foundCmp.name,
1790
+ isCosmetic: this.foundCmp.isCosmetic,
1791
+ url: location.href,
1792
+ });
1793
+ this.updateState({ lifecycle: 'done' });
1794
+ }
1795
+ else {
1796
+ this.updateState({ lifecycle: optOutResult ? 'optOutSucceeded' : 'optOutFailed' });
1797
+ }
1798
+ return optOutResult;
1799
+ }
1800
+ async doOptIn() {
1801
+ this.updateState({ lifecycle: 'runningOptIn' });
1802
+ let optInResult;
1803
+ if (!this.foundCmp) {
1804
+ optInResult = false;
1805
+ }
1806
+ else {
1807
+ optInResult = await this.foundCmp.optIn();
1808
+ }
1809
+ if (this.config.enablePrehide) {
1810
+ this.undoPrehide();
1811
+ }
1812
+ this.sendContentMessage({
1813
+ type: 'optInResult',
1814
+ cmp: this.foundCmp ? this.foundCmp.name : 'none',
1815
+ result: optInResult,
1816
+ scheduleSelfTest: false,
1817
+ url: location.href,
1818
+ });
1819
+ if (optInResult && !this.foundCmp.isIntermediate) {
1820
+ this.sendContentMessage({
1821
+ type: 'autoconsentDone',
1822
+ cmp: this.foundCmp.name,
1823
+ isCosmetic: this.foundCmp.isCosmetic,
1824
+ url: location.href,
1825
+ });
1826
+ this.updateState({ lifecycle: 'done' });
1827
+ }
1828
+ else {
1829
+ this.updateState({ lifecycle: optInResult ? 'optInSucceeded' : 'optInFailed' });
1830
+ }
1831
+ return optInResult;
1832
+ }
1833
+ async doSelfTest() {
1834
+ let selfTestResult;
1835
+ if (!this.foundCmp) {
1836
+ selfTestResult = false;
1837
+ }
1838
+ else {
1839
+ selfTestResult = await this.foundCmp.test();
1840
+ }
1841
+ this.sendContentMessage({
1842
+ type: 'selfTestResult',
1843
+ cmp: this.foundCmp ? this.foundCmp.name : 'none',
1844
+ result: selfTestResult,
1845
+ url: location.href,
1846
+ });
1847
+ this.updateState({ selfTest: selfTestResult });
1848
+ return selfTestResult;
1849
+ }
1850
+ async waitForPopup(cmp, retries = 5, interval = 500) {
1851
+ const isOpen = await cmp.detectPopup();
1852
+ if (!isOpen && retries > 0) {
1853
+ return new Promise((resolve) => setTimeout(() => resolve(this.waitForPopup(cmp, retries - 1, interval)), interval));
1854
+ }
1855
+ return isOpen;
1856
+ }
1857
+ prehideElements() {
1858
+ // hide rules not specific to a single CMP rule
1859
+ const globalHidden = [
1860
+ "#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium",
1861
+ ];
1862
+ const selectors = this.rules.reduce((selectorList, rule) => {
1863
+ if (rule.prehideSelectors) {
1864
+ return [...selectorList, ...rule.prehideSelectors];
1865
+ }
1866
+ return selectorList;
1867
+ }, globalHidden);
1868
+ this.updateState({ prehideOn: true });
1869
+ return prehide(selectors);
1870
+ }
1871
+ undoPrehide() {
1872
+ this.updateState({ prehideOn: false });
1873
+ return undoPrehide();
1874
+ }
1875
+ updateState(change) {
1876
+ Object.assign(this.state, change);
1877
+ this.sendContentMessage({
1878
+ type: 'report',
1879
+ instanceId: this.id,
1880
+ url: window.location.href,
1881
+ mainFrame: window.top === window.self,
1882
+ state: this.state,
1883
+ });
1884
+ }
1885
+ async receiveMessageCallback(message) {
1886
+ switch (message.type) {
1887
+ case 'initResp':
1888
+ this.initialize(message.config, message.rules);
1889
+ break;
1890
+ case 'optIn':
1891
+ await this.doOptIn();
1892
+ break;
1893
+ case 'optOut':
1894
+ await this.doOptOut();
1895
+ break;
1896
+ case 'selfTest':
1897
+ await this.doSelfTest();
1898
+ break;
1899
+ case 'evalResp':
1900
+ resolveEval(message.id, message.result);
1901
+ break;
1902
+ }
1903
+ }
1904
+ }
1905
+
1906
+ const consent = new AutoConsent(chrome.runtime.sendMessage);
1907
+ chrome.runtime.onMessage.addListener((message) => {
1908
+ return Promise.resolve(consent.receiveMessageCallback(message));
1909
+ });
1910
+ chrome.runtime.connect({ name: `instance-${consent.id}` });
1911
+
1912
+ })();