From 78477e49843f807cb294731f8f0a006e89416638 Mon Sep 17 00:00:00 2001 From: rui hildt Date: Thu, 25 Jul 2024 16:11:20 +0200 Subject: [PATCH] Fix update of the proxy badge --- src/background/main.ts | 8 +-- src/components/Location.vue | 4 +- src/components/Proxy/HomeProxyStatus.vue | 45 ++++++++++++++ src/composables/useActiveTab.ts | 14 ++--- src/composables/useProxyPermissions.ts | 5 +- src/composables/useSocksProxy.ts | 8 ++- .../{browserAction.ts => proxyBadge.ts} | 38 +++--------- src/helpers/proxyListeners.ts | 62 +++++++++++++++++++ src/helpers/socksProxy.ts | 50 +++++---------- src/popup/views/Home.vue | 35 ++--------- src/popup/views/Proxy.vue | 4 +- 11 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 src/components/Proxy/HomeProxyStatus.vue rename src/helpers/{browserAction.ts => proxyBadge.ts} (62%) create mode 100644 src/helpers/proxyListeners.ts diff --git a/src/background/main.ts b/src/background/main.ts index 5b9d03f6..1a38d5ff 100644 --- a/src/background/main.ts +++ b/src/background/main.ts @@ -1,5 +1,5 @@ import { addExtensionsListeners } from '@/helpers/extensions'; -import { cleanProxyListeners, initProxyListeners } from '@/helpers/socksProxy'; +import { initProxyListeners } from '@/helpers/proxyListeners'; // only on dev mode if (import.meta.hot) { @@ -10,9 +10,5 @@ if (import.meta.hot) { // Add listeners on extension actions addExtensionsListeners(); -// Init proxy listeners +// Add listeners for proxy actions initProxyListeners(); - -// Listeners for permissions changes -browser.permissions.onAdded.addListener(initProxyListeners); -browser.permissions.onRemoved.addListener(cleanProxyListeners); diff --git a/src/components/Location.vue b/src/components/Location.vue index dd2c8d9a..395005bf 100644 --- a/src/components/Location.vue +++ b/src/components/Location.vue @@ -4,8 +4,8 @@ import { NButton, NCollapse, NCollapseItem, NSpace } from 'naive-ui'; import LocationTabs from '@/components/LocationTabs.vue'; -import { updateTabsProxyBadges } from '@/helpers/browserAction'; import getRandomSocksProxy from '@/helpers/getRandomSocksProxy'; +import { updateCurrentTabProxyBadge } from '@/helpers/proxyBadge'; import useListProxies from '@/composables/useListProxies'; import useSocksProxy from '@/composables/useSocksProxy'; @@ -43,7 +43,7 @@ const setProxy = ( } else { setGlobalProxy({ country, countryCode, city, hostname, ipv4_address, port }); } - updateTabsProxyBadges(); + updateCurrentTabProxyBadge(); }; const clickServer = ( diff --git a/src/components/Proxy/HomeProxyStatus.vue b/src/components/Proxy/HomeProxyStatus.vue new file mode 100644 index 00000000..90544ad5 --- /dev/null +++ b/src/components/Proxy/HomeProxyStatus.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/composables/useActiveTab.ts b/src/composables/useActiveTab.ts index d32a6699..e3b15610 100644 --- a/src/composables/useActiveTab.ts +++ b/src/composables/useActiveTab.ts @@ -1,23 +1,19 @@ +import { getActiveTabDetails } from '@/helpers/socksProxy'; import { ref } from 'vue'; -import useProxyPermissions from '@/composables/useProxyPermissions'; -const { proxyPermissionsGranted } = useProxyPermissions(); const activeTabHost = ref(''); const isAboutPage = ref(false); const getActiveTab = async () => { - if (proxyPermissionsGranted.value) { - const activeWindow = await browser.windows.getCurrent({ populate: true }); - const activeTab = activeWindow.tabs!.find((tab) => tab.active); + const activeTabDetails = await getActiveTabDetails(); - const activeTabURL = new URL(activeTab!.url!); - activeTabHost.value = activeTabURL.hostname; - isAboutPage.value = activeTabURL.protocol === 'about:'; - } + activeTabHost.value = activeTabDetails.host; + isAboutPage.value = activeTabDetails.protocol === 'about:'; }; const useActiveTab = () => { getActiveTab(); + return { activeTabHost, isAboutPage }; }; diff --git a/src/composables/useProxyPermissions.ts b/src/composables/useProxyPermissions.ts index f9f74b45..4309fb7e 100644 --- a/src/composables/useProxyPermissions.ts +++ b/src/composables/useProxyPermissions.ts @@ -8,13 +8,14 @@ const useProxyPermissions = () => { proxyPermissionsGranted.value = await getProxyPermissions(); }; - const triggerProxyPermissions = async () => { + const triggerRequestProxyPermissions = async () => { proxyPermissionsGranted.value = await requestProxyPermissions(); + return proxyPermissionsGranted.value; }; checkProxyPermissions(); - return { proxyPermissionsGranted, triggerProxyPermissions }; + return { proxyPermissionsGranted, triggerRequestProxyPermissions }; }; export default useProxyPermissions; diff --git a/src/composables/useSocksProxy.ts b/src/composables/useSocksProxy.ts index de9550c8..37d3f192 100644 --- a/src/composables/useSocksProxy.ts +++ b/src/composables/useSocksProxy.ts @@ -6,7 +6,7 @@ import { ProxyInfoType, ProxyOperationArgs, } from '@/helpers/socksProxy.types'; -import { updateTabsProxyBadges } from '@/helpers/browserAction'; +import { updateCurrentTabProxyBadge } from '@/helpers/proxyBadge'; import useActiveTab from '@/composables/useActiveTab'; import useConnection from '@/composables/useConnection'; @@ -37,22 +37,24 @@ const currentHostProxyDNSEnabled = computed(() => currentHostProxyDetails.value? const toggleGlobalProxy = () => { globalProxyDetails.value.socksEnabled = !globalProxyDetails.value.socksEnabled; - updateTabsProxyBadges(); + updateCurrentTabProxyBadge(); }; const toggleCurrentHostProxy = () => { hostProxiesDetails.value[activeTabHost.value].socksEnabled = !currentHostProxyEnabled.value; - updateTabsProxyBadges(); + updateCurrentTabProxyBadge(); }; const toggleGlobalProxyDNS = () => { const updatedGlobalProxyDNS = !globalProxyDetails.value.proxyDNS; globalProxyDetails.value.proxyDNS = updatedGlobalProxyDNS; globalProxy.value.proxyDNS = updatedGlobalProxyDNS; + updateCurrentTabProxyBadge(); }; const toggleCurrentHostProxyDNS = () => { const updatedCurrentHostProxyDNS = !currentHostProxyDetails.value.proxyDNS; hostProxiesDetails.value[activeTabHost.value].proxyDNS = updatedCurrentHostProxyDNS; hostProxies.value[activeTabHost.value].proxyDNS = updatedCurrentHostProxyDNS; + updateCurrentTabProxyBadge(); }; const setGlobalProxy = ({ diff --git a/src/helpers/browserAction.ts b/src/helpers/proxyBadge.ts similarity index 62% rename from src/helpers/browserAction.ts rename to src/helpers/proxyBadge.ts index 17313d7f..08542ad3 100644 --- a/src/helpers/browserAction.ts +++ b/src/helpers/proxyBadge.ts @@ -1,15 +1,18 @@ -import { ProxyDetails } from './socksProxy.types'; import { getActiveProxyDetails } from '@/helpers/socksProxy'; +import { ProxyDetails } from '@/helpers/socksProxy.types'; -export const initBrowserAction = () => { - // Each time a tab is updated, reset the browserAction for that tab - browser.tabs.onUpdated.addListener(updatedTabListener); +export const updateCurrentTabProxyBadge = async () => { + const activeTab = await browser.tabs.query({ active: true, currentWindow: true }); - updateTabsProxyBadges(); + if (activeTab[0]) { + await updateTabProxyBadge(activeTab[0], await getActiveProxyDetails()); + } }; -// Update a tab browserAction badge & title -const updateTabProxyBadge = async (tab: browser.tabs.Tab, activeProxyDetails: ProxyDetails) => { +export const updateTabProxyBadge = async ( + tab: browser.tabs.Tab, + activeProxyDetails: ProxyDetails, +) => { const { id: tabId, url } = tab; const { excludedHosts } = await browser.storage.local.get('excludedHosts'); const tabHost = new URL(url!).hostname; @@ -32,27 +35,6 @@ const updateTabProxyBadge = async (tab: browser.tabs.Tab, activeProxyDetails: Pr } }; -// Update state of the proxy badge & title, for all tabs -export const updateTabsProxyBadges = async () => { - const tabs = await browser.tabs.query({}); - const activeProxyDetails = await getActiveProxyDetails(); - - for (const tab of tabs) { - if (tab.id !== undefined) { - updateTabProxyBadge(tab, activeProxyDetails); - } - } -}; - -export const updatedTabListener = async ( - _tabId: number, - _changeInfo: browser.tabs._OnUpdatedChangeInfo, - tab: browser.tabs.Tab, -) => { - const activeProxyDetails = await getActiveProxyDetails(); - updateTabProxyBadge(tab, activeProxyDetails); -}; - const setTabExtBadge = async ( tab: browser.tabs.Tab, proxy = true, diff --git a/src/helpers/proxyListeners.ts b/src/helpers/proxyListeners.ts new file mode 100644 index 00000000..b8d760f6 --- /dev/null +++ b/src/helpers/proxyListeners.ts @@ -0,0 +1,62 @@ +import { getProxyPermissions } from '@/helpers/permissions'; +import { updateCurrentTabProxyBadge, updateTabProxyBadge } from '@/helpers/proxyBadge'; +import { getActiveProxyDetails, handleProxyRequest } from '@/helpers/socksProxy'; + +export const initProxyListeners = () => { + // Will init listeners on extension start if permissions are granted + initListeners(); + + // Will monitor permissions changes and update proxy accordingly + browser.permissions.onAdded.addListener(initListeners); + browser.permissions.onRemoved.addListener(cleanListeners); +}; + +const initListeners = async () => { + const proxyPermissionsGranted = await getProxyPermissions(); + + if (proxyPermissionsGranted) { + updateCurrentTabProxyBadge(); + + // Initialize tab listeners + browser.tabs.onActivated.addListener(handleActivedTab); + browser.tabs.onUpdated.addListener(handleUpdatedTab); + + // Initialize proxy request listener + browser.proxy.onRequest.addListener(handleProxyRequest, { urls: [''] }); + } +}; + +const cleanListeners = async () => { + const proxyPermissionsGranted = await getProxyPermissions(); + + if (!proxyPermissionsGranted) { + // Clear the badge for all tabs + // TODO Add a notification to warn the user the proxy has been deactivated + const tabs = await browser.tabs.query({}); + for (const tab of tabs) { + if (tab.id !== undefined) { + browser.browserAction.setBadgeText({ text: '', tabId: tab.id }); + } + } + + // Remove tab listeners + browser.tabs.onActivated.removeListener(handleActivedTab); + browser.tabs.onUpdated.removeListener(handleUpdatedTab); + + // Remove proxy request listener + browser.proxy.onRequest.removeListener(handleProxyRequest); + } +}; + +const handleActivedTab = async (activeInfo: browser.tabs._OnActivatedActiveInfo) => { + const tab = await browser.tabs.get(activeInfo.tabId); + updateTabProxyBadge(tab, await getActiveProxyDetails()); +}; + +const handleUpdatedTab = async ( + _tabId: number, + _changeInfo: browser.tabs._OnUpdatedChangeInfo, + tab: browser.tabs.Tab, +) => { + updateTabProxyBadge(tab, await getActiveProxyDetails()); +}; diff --git a/src/helpers/socksProxy.ts b/src/helpers/socksProxy.ts index 8c68ff7a..0625f43d 100644 --- a/src/helpers/socksProxy.ts +++ b/src/helpers/socksProxy.ts @@ -1,8 +1,6 @@ import ipaddr from 'ipaddr.js'; -import { RequestDetails, ProxyDetails } from './socksProxy.types'; -import { getProxyPermissions } from './permissions'; -import { initBrowserAction, updatedTabListener } from './browserAction'; +import { RequestDetails, ProxyDetails } from '@/helpers/socksProxy.types'; const getGlobalProxyDetails = async (): Promise => { const response = await browser.storage.local.get('globalProxyDetails'); @@ -19,9 +17,8 @@ const getHostProxyDetails = async (): Promise => { if (hostProxiesDetails) { const hostProxiesDetailsParsed = JSON.parse(hostProxiesDetails); const proxiedHosts = Object.keys(hostProxiesDetailsParsed); + const activeTabHost = (await getActiveTabDetails()).host; - const activeTab = await browser.tabs.query({ active: true }); - const activeTabHost = new URL(activeTab[0].url!).hostname; if ( proxiedHosts.includes(activeTabHost) && hostProxiesDetailsParsed[activeTabHost].socksEnabled @@ -32,46 +29,27 @@ const getHostProxyDetails = async (): Promise => { return { socksEnabled: false }; }; +export const getActiveTabDetails = async () => { + const activeTab = await browser.tabs.query({ active: true }); + + return activeTab[0].url + ? { + host: new URL(activeTab[0].url).hostname, + protocol: new URL(activeTab[0].url).protocol, + } + : { host: '', protocol: '' }; +}; + export const getActiveProxyDetails = async () => { const globalProxyDetails = await getGlobalProxyDetails(); const hostProxyDetails = await getHostProxyDetails(); return hostProxyDetails.socksEnabled ? hostProxyDetails : globalProxyDetails; }; -export const initProxyRequests = () => { - browser.proxy.onRequest.addListener(handleProxyRequest, { urls: [''] }); -}; - -export const initProxyListeners = async () => { - const proxyPermissionsGranted = await getProxyPermissions(); - if (proxyPermissionsGranted) { - await removeProxyListeners(); - await addProxyListeners(); - } -}; - -export const cleanProxyListeners = async () => { - const proxyPermissionsGranted = await getProxyPermissions(); - - if (!proxyPermissionsGranted) { - await removeProxyListeners(); - } -}; - -const addProxyListeners = async () => { - initBrowserAction(); - initProxyRequests(); -}; - -const removeProxyListeners = async () => { - browser.tabs.onUpdated.removeListener(updatedTabListener); - browser.proxy.onRequest.removeListener(handleProxyRequest); -}; - // TODO decide what how to handle fallback proxy (if proxy is invalid, it will fallback to Firefox proxy if configured) // https://bugzilla.mozilla.org/show_bug.cgi?id=1750561 -const handleProxyRequest = async (details: browser.proxy._OnRequestDetails) => { +export const handleProxyRequest = async (details: browser.proxy._OnRequestDetails) => { const { globalProxy } = await browser.storage.local.get('globalProxy'); const { globalProxyDetails } = await browser.storage.local.get('globalProxyDetails'); const { excludedHosts } = await browser.storage.local.get('excludedHosts'); diff --git a/src/popup/views/Home.vue b/src/popup/views/Home.vue index ca65225b..4cb70bd0 100644 --- a/src/popup/views/Home.vue +++ b/src/popup/views/Home.vue @@ -1,47 +1,20 @@ diff --git a/src/popup/views/Proxy.vue b/src/popup/views/Proxy.vue index b1a0ba59..7b142bc5 100644 --- a/src/popup/views/Proxy.vue +++ b/src/popup/views/Proxy.vue @@ -16,7 +16,7 @@ import useProxyPermissions from '@/composables/useProxyPermissions'; const { isAboutPage } = useActiveTab(); const { getSocksProxies } = useListProxies(); -const { proxyPermissionsGranted, triggerProxyPermissions } = useProxyPermissions(); +const { proxyPermissionsGranted, triggerRequestProxyPermissions } = useProxyPermissions(); const { connection } = inject(ConnectionKey, defaultConnection); @@ -60,7 +60,7 @@ onMounted(loadProxies); - +