From 7a9a92918dede2eec94eca925391f0c923608bc1 Mon Sep 17 00:00:00 2001 From: penge Date: Mon, 19 Jun 2023 11:59:35 +0200 Subject: [PATCH] Allow to block URLs navigated by browser history - add "tabs" permission Note: "history" permission isn't suitable as it is global (per any tab), doesn't have knowledge of tabId - optimize execution time by having prepared __enabled and __blocked (thus not loading every time from storage) --- manifest.json | 7 ++- src/background.ts | 46 ++++++++++++++++++-- src/helpers/block-site.ts | 69 +++++++++++++++--------------- src/helpers/create-context-menu.ts | 8 ++-- 4 files changed, 85 insertions(+), 45 deletions(-) diff --git a/manifest.json b/manifest.json index 18fd47c..bf974a2 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,12 @@ } }, "options_page": "options.html", - "permissions": ["storage", "webNavigation", "contextMenus"], + "permissions": [ + "storage", + "tabs", + "webNavigation", + "contextMenus" + ], "background": { "service_worker": "background.mjs", "type": "module" diff --git a/src/background.ts b/src/background.ts index fc1f353..119cf42 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1,18 +1,56 @@ import initStorage from "./storage/init"; -import blockSite from "./helpers/block-site"; +import storage from "./storage"; import createContextMenu from "./helpers/create-context-menu"; +import blockSite from "./helpers/block-site"; + +let __enabled: boolean; +let __blocked: string[]; + +initStorage(() => { + createContextMenu(); + + storage.get(["enabled", "blocked"], ({ enabled, blocked }) => { + __enabled = enabled; + __blocked = blocked; + }); -initStorage(createContextMenu); + chrome.storage.local.onChanged.addListener((changes) => { + if (changes["enabled"]) { + __enabled = changes["enabled"].newValue as boolean; + } + + if (changes["blocked"]) { + __blocked = changes["blocked"].newValue as string[]; + } + }); +}); chrome.action.onClicked.addListener(() => { chrome.runtime.openOptionsPage(); }); chrome.webNavigation.onBeforeNavigate.addListener((details) => { - const { tabId, url, timeStamp, frameId } = details; + if (!__enabled || !__blocked.length) { + return; + } + + const { tabId, url, frameId } = details; if (!url || !url.startsWith("http") || frameId !== 0) { return; } - blockSite({ tabId, url, timeStamp }); + blockSite({ blocked: __blocked, tabId, url }); +}); + +chrome.tabs.onUpdated.addListener((tabId, changeInfo) => { + if (!tabId || !__enabled || !__blocked.length) { + return; + } + + const { status, url } = changeInfo; + if (status !== "loading" || !url || !url.startsWith("http")) { + return; + } + + blockSite({ blocked: __blocked, tabId, url }); }); diff --git a/src/helpers/block-site.ts b/src/helpers/block-site.ts index a53ecf8..4719a18 100644 --- a/src/helpers/block-site.ts +++ b/src/helpers/block-site.ts @@ -4,50 +4,49 @@ import * as counterHelper from "./counter"; import getBlockedUrl from "./get-blocked-url"; interface BlockSiteOptions { + blocked: string[] tabId: number url: string - timeStamp: number } export default (options: BlockSiteOptions) => { - const { tabId, url, timeStamp } = options; + const { blocked, tabId, url } = options; + if (!blocked.length || !tabId || !url.startsWith("http")) { + return; + } - storage.get(["enabled", "blocked"], ({ enabled, blocked }) => { - if (!enabled || blocked.length === 0) { - return; - } - - const foundRule = findRule(url, blocked); - if (!foundRule || foundRule.type === "allow") { - storage.get(["counter"], ({ counter }) => { - counterHelper.flushObsoleteEntries({ blocked, counter }); - storage.set({ counter }); - }); - return; - } - - storage.get(["counter", "counterShow", "counterPeriod", "resolution"], ({ counter, counterShow, counterPeriod, resolution }) => { + const foundRule = findRule(url, blocked); + if (!foundRule || foundRule.type === "allow") { + storage.get(["counter"], ({ counter }) => { counterHelper.flushObsoleteEntries({ blocked, counter }); - const count = counterHelper.add(foundRule.path, timeStamp, { - counter, - countFromTimeStamp: counterHelper.counterPeriodToTimeStamp(counterPeriod, new Date().getTime()), - }); storage.set({ counter }); + }); + return; + } - switch (resolution) { - case "CLOSE_TAB": - chrome.tabs.remove(tabId); - break; - case "SHOW_BLOCKED_INFO_PAGE": { - chrome.tabs.update(tabId, { - url: getBlockedUrl({ - url, - rule: foundRule.path, - countParams: counterShow ? { count, period: counterPeriod } : undefined }, - )}, - ); - break; - }} + storage.get(["counter", "counterShow", "counterPeriod", "resolution"], ({ counter, counterShow, counterPeriod, resolution }) => { + counterHelper.flushObsoleteEntries({ blocked, counter }); + + const timeStamp = Date.now(); + const count = counterHelper.add(foundRule.path, timeStamp, { + counter, + countFromTimeStamp: counterHelper.counterPeriodToTimeStamp(counterPeriod, new Date().getTime()), }); + storage.set({ counter }); + + switch (resolution) { + case "CLOSE_TAB": + chrome.tabs.remove(tabId); + break; + case "SHOW_BLOCKED_INFO_PAGE": { + chrome.tabs.update(tabId, { + url: getBlockedUrl({ + url, + rule: foundRule.path, + countParams: counterShow ? { count, period: counterPeriod } : undefined }, + )}, + ); + break; + }} }); }; diff --git a/src/helpers/create-context-menu.ts b/src/helpers/create-context-menu.ts index 9c5a211..2d57a93 100644 --- a/src/helpers/create-context-menu.ts +++ b/src/helpers/create-context-menu.ts @@ -27,10 +27,8 @@ const createContextMenu = () => { const normalizedUrl = normalizeUrl(url); const updatedBlocked = [...blocked, normalizedUrl]; - storage.set({ blocked: updatedBlocked }, () => { - const timeStamp = Date.now(); - blockSite({ tabId, url, timeStamp }); - }); + storage.set({ blocked: updatedBlocked }); + blockSite({ blocked: updatedBlocked, tabId, url }); }); }); }; @@ -46,7 +44,7 @@ export default () => { chrome.storage.local.onChanged.addListener((changes) => { if (changes["enabled"]) { chrome.contextMenus.removeAll(() => { - if (changes["enabled"].newValue) { + if (changes["enabled"].newValue as boolean) { createContextMenu(); } });