/** * @description Array of selectors * @type {string[]} */ let classes = []; /** * @description Shortcut to send messages to background script * @type {void} */ const dispatch = chrome.runtime.sendMessage; /** * @description Hostname */ const hostname = document.location.hostname; /** * @description Is consent preview page? */ const isConsentPreview = hostname.startsWith("consent."); /** * @description Options provided to observer */ const options = { childList: true, subtree: true }; /** * @description Selectors list * @type {string} */ let selectors = ""; /** * @description Target provided to observer */ const target = document.body || document.documentElement; /** * @description Checks if node element is removable * @param {Element} node */ const check = (node) => node instanceof HTMLElement && node.parentElement && !["APP", "ROOT"].includes(node.id.toUpperCase()) && !["BODY", "HTML"].includes(node.tagName); /** * @description Cleans DOM */ const clean = () => { if (selectors.length) { const nodes = document.querySelectorAll(selectors); for (let i = nodes.length; i--; ) { const node = nodes[i]; const valid = check(node); if (valid) node.outerHTML = ""; } } }; /** * @description Fixes scroll issues */ const fix = () => { const automobiel = /automobielmanagement.nl/g.test(hostname); const body = document.body; const facebook = document.getElementsByClassName("_31e")[0]; const frame = document.location.ancestorOrigins.length; const google = document.querySelector('form[action*="consent.google"]'); const html = document.documentElement; const play = hostname.startsWith("play.google."); const yahoo = document.querySelector("#consent-page"); if (automobiel && body) { for (let i = body.childNodes.length; i--; ) { const node = body.childNodes[i]; if (node instanceof HTMLElement) { node.style.setProperty("filter", "initial", "important"); } } } if (body) { body.classList.remove(...classes); if (!frame) { body.style.setProperty("overflow-y", "initial", "important"); body.style.setProperty("position", "initial", "important"); } } if (facebook) { facebook.style.setProperty("position", "initial", "important"); } if (google) { const submit = google.querySelector("button"); if (submit && submit instanceof HTMLElement) { submit.click(); } } if (html) { html.classList.remove(...classes); if (!frame) { html.style.setProperty("position", "initial", "important"); html.style.setProperty("overflow-y", "initial", "important"); } } if (play) { const node = document.querySelector("body > div"); if (node && node instanceof HTMLElement) { node.style.setProperty("z-index", "initial", "important"); } } if (yahoo) { const submit = yahoo.querySelector('button[type="submit"]'); if (submit && submit instanceof HTMLElement) { submit.click(); } } }; const observer = new MutationObserver((mutations, instance) => { instance.disconnect(); fix(); if (!isConsentPreview) { for (let i = mutations.length; i--; ) { const mutation = mutations[i]; for (let j = mutation.addedNodes.length; j--; ) { const node = mutation.addedNodes[j]; const valid = check(node); if (valid && node.matches(selectors)) node.outerHTML = ""; } } } instance.observe(target, options); }); /** * @description Setups classes selectors * @returns {Promise<{ classes: string[] }>} */ const setupClasses = () => new Promise((resolve) => { dispatch({ type: "GET_CLASSES" }, null, resolve); }); /** * @description Setups elements selectors * @returns {Promise<{ selectors: string }>} */ const setupSelectors = () => new Promise((resolve) => { dispatch({ type: "GET_SELECTORS" }, null, resolve); }); /** * @description Listens DOM complete state * @listens document#readystatechange */ document.addEventListener("readystatechange", () => { dispatch({ hostname, type: "GET_CACHE" }, null, async ({ enabled }) => { if (document.readyState === "complete" && enabled && !isConsentPreview) { fix(); clean(); setTimeout(clean, 2000); } }); }); /** * @description Setups everything and starts to observe if enabled */ dispatch({ hostname, type: "GET_CACHE" }, null, async ({ enabled }) => { dispatch({ type: "ENABLE_POPUP" }); if (enabled) { dispatch({ type: "ENABLE_ICON" }); const results = await Promise.all([setupClasses(), setupSelectors()]); classes = results[0].classes; selectors = results[1].selectors; observer.observe(target, options); } });