From 96e27a9845b979cd1029e4fd4c24651985eb3144 Mon Sep 17 00:00:00 2001 From: wanhose Date: Sat, 30 Oct 2021 14:25:58 +0200 Subject: [PATCH 1/3] feat(scripts): improve background script documentation and remove matches from cache --- scripts/background.js | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/scripts/background.js b/scripts/background.js index a29e4ca..cd35624 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -1,11 +1,10 @@ /** * @description Cache initial state - * @type {{ enabled: boolean, matches: string[] }} + * @type {{ enabled: boolean }} */ const initial = { enabled: true, - matches: [], }; /** @@ -13,10 +12,7 @@ const initial = { * @param {object} [cache] */ -const check = (cache) => - typeof cache.enabled === "boolean" && - Array.isArray(cache.matches) && - cache.matches.every((match) => typeof match === "string"); +const check = (cache) => typeof cache.enabled === "boolean"; /** * @description Disables icon @@ -70,7 +66,7 @@ const enablePopup = (tabId) => { * @description Retrieves cache state * @param {string} [hostname] * @param {void} [callback] - * @returns {Promise<{ enabled: boolean, matches: string[] }>} Cache state + * @returns {Promise<{ enabled: boolean }>} */ const getCache = (hostname, callback) => { @@ -92,7 +88,7 @@ const getCache = (hostname, callback) => { * @async * @description Retrieves a selectors list * @param {void} [callback] - * @returns {Promise<{ matches: string[] }>} A selectors list + * @returns {Promise<{ classes: string[] }>} */ const getClasses = async (callback) => { @@ -114,7 +110,7 @@ const getClasses = async (callback) => { * @async * @description Retrieves a selectors list * @param {void} [callback] - * @returns {Promise<{ matches: string[] }>} A selectors list + * @returns {Promise<{ selectors: string }>} */ const getSelectors = async (callback) => { @@ -126,7 +122,7 @@ const getSelectors = async (callback) => { if (response.status !== 200) throw new Error(); - callback({ selectors: data.split("\n") }); + callback({ selectors: data.split("\n").join(",") }); } catch { callback({ selectors: [] }); } @@ -135,7 +131,7 @@ const getSelectors = async (callback) => { /** * @description Retrieves current tab information * @param {void} [callback] - * @returns {Promise<{ id: string, location: string }>} Current tab information + * @returns {Promise<{ id: string, location: string }>} */ const getTab = (callback) => { @@ -163,10 +159,6 @@ const updateCache = (hostname, state) => { typeof state.enabled === "undefined" ? current.enabled : state.enabled, - matches: - typeof state.matches === "undefined" - ? current.matches - : [...new Set([...current.matches, ...state.matches])], }, }); }); From 365a23c7e8819759538abe6b9557a0365b246eac Mon Sep 17 00:00:00 2001 From: wanhose Date: Sat, 30 Oct 2021 14:26:22 +0200 Subject: [PATCH 2/3] feat(scripts): improve content scripts with mutation observer instead of recursive functions --- scripts/content.js | 136 +++++++++++---------------------------------- 1 file changed, 32 insertions(+), 104 deletions(-) diff --git a/scripts/content.js b/scripts/content.js index 69fd171..ef5514b 100644 --- a/scripts/content.js +++ b/scripts/content.js @@ -1,16 +1,9 @@ -/** - * @description Number of attempts - * @type {number} - */ - -let attempts = 1; - /** * @description Array of selectors * @type {string[]} */ -let classesFromNetwork = []; +let classes = []; /** * @description Shortcut to send messages to background script @@ -20,32 +13,23 @@ let classesFromNetwork = []; const dispatch = chrome.runtime.sendMessage; /** - * @description Array of selectors - * @type {string[]} + * @description Options provided to observer */ -let selectorsFromCache = []; +const options = { childList: true, subtree: true }; /** - * @description Array of selectors - * @type {Promise[]} + * @description Selectors list + * @type {string} */ -let selectorsFromNetwork = []; +let selectors = ""; /** - * @description Split large arrays into promises - * @param {string[]} array + * @description Target provided to observer */ -const chunkerize = (array) => - [...Array(Math.ceil(array.length / 300))].map( - (_, index) => () => - new Promise((resolve) => { - removeElements(array.slice(index * 300, (index + 1) * 300), true); - resolve(true); - }) - ); +const target = document.body || document.documentElement; /** * @description Fixes scroll issues @@ -53,7 +37,6 @@ const chunkerize = (array) => const fix = () => { const body = document.body; - const classes = classesFromNetwork; const facebook = document.getElementsByClassName("_31e")[0]; const html = document.documentElement; @@ -63,116 +46,61 @@ const fix = () => { if (html) html.style.setProperty("overflow-y", "unset", "important"); }; -/** - * @description Removes matched elements from a selectors array - * @param {string[]} selectors - * @param {boolean} updateCache - */ +const observer = new MutationObserver((mutations, instance) => { + instance.disconnect(); + fix(); -const removeElements = (selectors, updateCache) => { - for (let i = selectors.length; i--; ) { - const selector = selectors[i]; - const element = search(selector); + for (let i = mutations.length; i--; ) { + const mutation = mutations[i]; - if (element) { - const tagName = element.tagName.toUpperCase(); + for (let j = mutation.addedNodes.length; j--; ) { + const node = mutation.addedNodes[j]; - if (!["BODY", "HTML"].includes(tagName)) { - element.outerHTML = ""; + if (!(node instanceof HTMLElement)) continue; - if (updateCache) { - selectorsFromCache = [...selectorsFromCache, selector]; - dispatch({ - hostname: document.location.hostname, - state: { matches: [selector] }, - type: "UPDATE_CACHE", - }); - } - } + if (node.matches(selectors)) node.outerHTML = ""; } } -}; -/** - * @async - * @description Runs tasks - */ - -const run = async () => { - if (attempts <= 20) { - fix(); - removeElements(selectorsFromCache); - - if (selectorsFromNetwork.length > 0) { - const selectors = selectorsFromNetwork; - - if (attempts <= 5) await Promise.all(selectors.map((fn) => fn())); - if (document.readyState === "complete") attempts += 1; - } - - requestAnimationFrame(run); - } -}; - -/** - * @description Retrieves HTML element if selector exists - * @param {string} selector - * @returns {HTMLElement | null} An HTML element or null - */ - -const search = (selector) => { - if (!selector.includes("[") && !selector.includes(">")) { - if (selector.startsWith(".")) { - return document.getElementsByClassName(selector.slice(1))[0]; - } - - if (selector.startsWith("#")) { - return document.getElementById(selector.slice(1)); - } - } else { - return document.querySelector(selector); - } - - return null; -}; + instance.observe(target, options); +}); /** * @description Setups classes selectors - * @returns {Promise} + * @returns {Promise<{ classes: string[] }>} */ const setupClasses = () => new Promise((resolve) => { - dispatch({ type: "GET_CLASSES" }, null, ({ classes }) => { - classesFromNetwork = classes; - resolve(true); - }); + dispatch({ type: "GET_CLASSES" }, null, resolve); }); /** * @description Setups elements selectors - * @returns {Promise} + * @returns {Promise<{ selectors: string }>} */ const setupSelectors = () => new Promise((resolve) => { - dispatch({ type: "GET_SELECTORS" }, null, ({ selectors }) => { - selectorsFromNetwork = chunkerize(selectors); - resolve(true); - }); + dispatch({ type: "GET_SELECTORS" }, null, resolve); }); +/** + * @description Setups everything and starts to observe if enabled + */ + dispatch( { hostname: document.location.hostname, type: "GET_CACHE" }, null, - async ({ enabled, matches }) => { + async ({ enabled }) => { dispatch({ type: "ENABLE_POPUP" }); if (enabled) { - selectorsFromCache = matches; dispatch({ type: "ENABLE_ICON" }); - await Promise.all([setupClasses(), setupSelectors()]); - await run(); + const results = await Promise.all([setupClasses(), setupSelectors()]); + classes = results[0].classes; + selectors = results[1].selectors; + observer.observe(target, options); } } ); From 8d5071dcd2d2779ee72825791a25300a2078feb0 Mon Sep 17 00:00:00 2001 From: wanhose Date: Sat, 30 Oct 2021 14:26:36 +0200 Subject: [PATCH 3/3] chore(manifest): upgrade version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index c9946fd..962196b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Cookie Dialog Monster", - "version": "5.1.0", + "version": "5.2.0", "default_locale": "en", "description": "__MSG_appDesc__", "icons": {