diff --git a/data/elements.txt b/data/elements.txt index 54c10a6..1c782c0 100644 --- a/data/elements.txt +++ b/data/elements.txt @@ -12579,4 +12579,5 @@ aside[class*="CookieModalstyles"] #cookie_consent_layer body#Index.Matriculas > div#overlay #cookie-popup-with-overlay -.wt-cli-cookie-bar-container \ No newline at end of file +.wt-cli-cookie-bar-container +html[id="facebook"] > body > div.__fb-light-mode \ No newline at end of file diff --git a/manifest.json b/manifest.json index a5f1668..2342898 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Do Not Consent", - "version": "3.4.2", + "version": "4.0.0", "default_locale": "en", "description": "__MSG_appDesc__", "icons": { @@ -20,7 +20,8 @@ }, "content_scripts": [ { - "exclude_matches": ["https://accounts.google.com/*"], + "all_frames": true, + "css": ["styles/content.css"], "js": ["scripts/content.js"], "matches": ["http://*/*", "https://*/*"], "run_at": "document_start" diff --git a/scripts/background.js b/scripts/background.js index 09f6a1f..5f0d3d5 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -1,3 +1,14 @@ +/** + * @var cacheInitialState + * @description Cache initial state + * @type {{ enabled: boolean, matches: string[] }} + */ + +const cacheInitialState = { + enabled: true, + matches: [], +}; + /** * @function disableIcon * @description Disables icon @@ -8,7 +19,7 @@ const disableIcon = (tabId) => { chrome.browserAction.setIcon({ path: "assets/icons/disabled.png", - tabId: tabId, + tabId, }); }; @@ -22,7 +33,7 @@ const disableIcon = (tabId) => { const disablePopup = (tabId) => { chrome.browserAction.setPopup({ popup: "", - tabId: tabId, + tabId, }); }; @@ -36,7 +47,7 @@ const disablePopup = (tabId) => { const enableIcon = (tabId) => { chrome.browserAction.setIcon({ path: "assets/icons/enabled.png", - tabId: tabId, + tabId, }); }; @@ -50,15 +61,78 @@ const enableIcon = (tabId) => { const enablePopup = (tabId) => { chrome.browserAction.setPopup({ popup: "popup.html", - tabId: tabId, + tabId, }); }; +/** + * @async + * @function getCache + * @description Retrieves cache state + * + * @returns {Promise<{ enabled: boolean, matches: string[] }>} Cache state + */ + +const getCache = async (hostname, responseCallback) => { + chrome.storage.local.get(null, (store) => { + const cache = store[hostname]; + + if (cache) { + responseCallback(cache); + } else { + chrome.storage.local.set({ [hostname]: cacheInitialState }); + responseCallback(cacheInitialState); + } + }); +}; + +/** + * @async + * @function updateCache + * @description Update cache state + */ + +const updateCache = async (hostname, selector) => { + chrome.storage.local.get(null, (cache) => { + const current = cache[hostname]; + + chrome.storage.local.set({ + [hostname]: { + ...current, + matches: [...new Set([...current.matches, selector])], + }, + }); + }); +}; + +/** + * @async + * @function getList + * @description Retrieves selectors list + * + * @returns {Promise<{ matches: string[] }>} A selectors list + */ + +const getList = async (responseCallback) => { + try { + const url = + "https://raw.githubusercontent.com/wanhose/do-not-consent/master/data/elements.txt"; + const response = await fetch(url); + const data = await response.text(); + + if (response.status !== 200) throw new Error(); + + responseCallback({ matches: data.split("\n") }); + } catch { + responseCallback({ matches: [] }); + } +}; + /** * @description Listens to content messages */ -chrome.runtime.onMessage.addListener((request) => { +chrome.runtime.onMessage.addListener((request, sender, responseCallback) => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { const tab = tabs[0]; const tabId = tab.id; @@ -76,8 +150,19 @@ chrome.runtime.onMessage.addListener((request) => { case "ENABLE_POPUP": enablePopup(tabId); break; + case "GET_CACHE": + getCache(request.hostname, responseCallback); + break; + case "GET_LIST": + getList(responseCallback); + break; + case "UPDATE_CACHE": + updateCache(request.hostname, request.selector); + break; default: break; } }); + + return true; }); diff --git a/scripts/content.js b/scripts/content.js index 8b4168f..17f64c5 100644 --- a/scripts/content.js +++ b/scripts/content.js @@ -7,48 +7,36 @@ let attempts = 1; /** - * @var enabled - * @description Is extension enabled? + * @var intervalId + * @description Task interval identifier + * @type {number} + */ + +let intervalId = 0; + +/** + * @var ready + * @description Is extension ready? * @type {boolean} */ -let enabled = true; +let ready = false; /** - * @var selectors + * @var selectorsFromCache * @description Array of selectors * @type {string[]} */ -let selectors = []; +let selectorsFromCache = []; /** - * @constant url - * @description Database link - * @type {string} + * @var selectorsFromNetwork + * @description Array of selectors + * @type {string[]} */ -const url = - "https://raw.githubusercontent.com/wanhose/do-not-consent/master/data/elements.txt"; - -/** - * @function commit - * @description Commits selector to cache - * @param {string} selector - */ - -const commit = (selector) => { - chrome.storage.local.get(null, (cache) => { - const current = cache[document.location.hostname]; - - chrome.storage.local.set({ - [document.location.hostname]: { - ...current, - matches: [...new Set([...cache.matches, selector])], - }, - }); - }); -}; +let selectorsFromNetwork = []; /** * @function fix @@ -58,11 +46,12 @@ const commit = (selector) => { const fix = () => { const html = document.documentElement; const body = document.body; - const facebook = document.querySelector("._31e"); + const facebook = document.getElementsByClassName("._31e")[0]; - html.style.setProperty("overflow-y", "unset", "important"); - body.style.setProperty("overflow-y", "unset", "important"); - if (facebook) root.style.setProperty("position", "unset", "important"); + if (body) body.style.setProperty("overflow-y", "unset", "important"); + if (facebook) facebook.style.setProperty("position", "unset", "important"); + if (html) html.style.setProperty("overflow-y", "unset", "important"); + if (ready) html.style.setProperty("opacity", "1", "important"); }; /** @@ -89,59 +78,25 @@ const search = (selector) => { return null; }; -/** - * @async - * @function check - * @description Checks if extension is enabled - * @returns {Promise} - */ - -const check = () => - new Promise((resolve) => { - chrome.storage.local.get(null, (store) => { - try { - const cache = store[document.location.hostname]; - - resolve(cache.enabled); - } catch { - chrome.storage.local.set( - { - [document.location.hostname]: { - enabled: true, - matches: [], - }, - }, - () => resolve(true) - ); - } - }); - }); - /** * @function removeFromCache * @description Removes matched elements from cache results */ const removeFromCache = () => { - chrome.storage.local.get(null, (store) => { - const cache = store[document.location.hostname]; - const matches = cache.matches; + for (let i = selectorsFromCache.length; i--; ) { + const selector = selectorsFromCache[i]; + const element = search(selector); - if (!!matches.length) { - for (let i = matches.length; i--; ) { - const selector = selectors[i]; - const element = search(selector); + if (element) { + const tagName = element.tagName.toUpperCase(); - if (element) { - const tagName = element.tagName.toUpperCase(); - - if (!["BODY", "HTML"].includes(tagName)) { - element.remove(); - } - } + if (!["BODY", "HTML"].includes(tagName)) { + element.remove(); + ready = true; } } - }); + } }; /** @@ -150,8 +105,8 @@ const removeFromCache = () => { */ const removeFromNetwork = () => { - for (let i = selectors.length; i--; ) { - const selector = selectors[i]; + for (let i = selectorsFromNetwork.length; i--; ) { + const selector = selectorsFromNetwork[i]; const element = search(selector); if (element) { @@ -159,88 +114,61 @@ const removeFromNetwork = () => { if (!["BODY", "HTML"].includes(tagName)) { element.remove(); - commit(selector); + ready = true; + chrome.runtime.sendMessage({ + hostname: document.location.hostname, + selector, + type: "UPDATE_CACHE", + }); } } } }; /** - * @async - * @function query - * @description Retrieves selectors list - * - * @returns {Promise} A selectors list + * @function runTasks + * @description Starts running tasks */ -const query = async () => { - try { - const response = await fetch(url, { cache: "no-cache" }); - const data = await response.text(); +const runTasks = () => { + if (attempts >= 5 || selectorsFromCache.length === 0) ready = true; - if (response.status !== 200) throw new Error(); + if (attempts <= 20) { + fix(); + removeFromCache(); + if (attempts <= 5) removeFromNetwork(); + attempts += 1; + } - return data.split("\n"); - } catch { - return []; + if (attempts > 20) { + clearInterval(intervalId); } }; /** - * @constant observer - * @description Observer instance - * @type {MutationObserver} + * @description Setup extension context */ -const observer = new MutationObserver((_, instance) => { - instance.disconnect(); - fix(); - removeFromCache(); - if (attempts <= 5) removeFromNetwork(); - attempts += 1; - observe(); -}); +chrome.runtime.sendMessage( + { hostname: document.location.hostname, type: "GET_CACHE" }, + null, + async (cacheResponse) => { + console.log(cacheResponse); + chrome.runtime.sendMessage({ type: "ENABLE_POPUP" }); -/** - * @function observe - * @description Starts observing document.body element - */ - -const observe = () => { - observer.observe(document.body, { - attributes: true, - childList: true, - }); -}; - -/** - * @async - * @function handleContentLoaded - * @description Cleans, fixes scroll issues and observes document.body element - */ - -const handleContentLoaded = async () => { - chrome.runtime.sendMessage({ type: "ENABLE_POPUP" }); - enabled = await check(); - - if (enabled) { - chrome.runtime.sendMessage({ type: "ENABLE_ICON" }); - selectors = await query(); - - if (selectors.length > 0) { - fix(); - removeFromCache(); - removeFromNetwork(); - observe(); + if (cacheResponse.enabled) { + selectorsFromCache = cacheResponse.matches; + chrome.runtime.sendMessage({ type: "ENABLE_ICON" }); + chrome.runtime.sendMessage( + { type: "GET_LIST" }, + null, + async (networkResponse) => { + selectorsFromNetwork = networkResponse.matches; + intervalId = setInterval(runTasks, 500); + } + ); + } else { + document.documentElement.style.setProperty("opacity", "1", "important"); } } -}; - -/** - * @description Listen to document ready - * - * @type {Document} - * @listens document#ready - */ - -document.addEventListener("DOMContentLoaded", handleContentLoaded); +); diff --git a/styles/content.css b/styles/content.css new file mode 100644 index 0000000..41fc891 --- /dev/null +++ b/styles/content.css @@ -0,0 +1,3 @@ +html { + opacity: 0 !important; +}