diff --git a/entrypoints/background.ts b/entrypoints/background.ts index 8d1ec61..cac4d62 100644 --- a/entrypoints/background.ts +++ b/entrypoints/background.ts @@ -74,15 +74,30 @@ async function initTab(tabId: number, url: string, resolveDns = false) { applyIconForState(tabId, newState); - if (!isSystem && !hasExistingData && resolveDns) { - const ip = await DnsService.resolve(domain); - if (ip) { - await processIp(tabId, url, ip); + if (!isSystem && !hasExistingData) { + const performDnsFallback = async () => { + const state = tabStates.get(tabId); + if (state?.status !== 'loading' || state.url !== url) return; + + const ip = await DnsService.resolve(domain); + + const stateAfterDns = tabStates.get(tabId); + if (stateAfterDns?.status !== 'loading' || stateAfterDns.url !== url) return; + + if (ip) { + await processIp(tabId, url, ip); + } else { + await updateState(tabId, { + status: 'error', + errorMessage: 'Could not resolve host' + }, url); + } + }; + + if (resolveDns) { + await performDnsFallback(); } else { - await updateState(tabId, { - status: 'error', - errorMessage: 'Could not resolve host' - }); + setTimeout(performDnsFallback, 1500); } } } @@ -132,13 +147,14 @@ async function processIp(tabId: number, url: string, ip: string) { applyIconForState(tabId, newState); } -async function updateState(tabId: number, updates: Partial) { +async function updateState(tabId: number, updates: Partial, expectedUrl?: string) { let current = tabStates.get(tabId); if (!current) { current = await StorageService.getTabState(tabId) || undefined; } if (current) { + if (expectedUrl && current.url !== expectedUrl) return; const newState = { ...current, ...updates }; tabStates.set(tabId, newState); await StorageService.setTabState(tabId, newState); @@ -194,13 +210,16 @@ export default defineBackground({ } const ip = await DnsService.resolve(hostname); + const currentState = tabStates.get(details.tabId); + if (currentState?.status !== 'loading' || currentState.url !== details.url) return; + if (ip) { await processIp(details.tabId, details.url, ip); } else { await updateState(details.tabId, { status: 'error', errorMessage: 'Could not resolve host' - }); + }, details.url); } } }); @@ -208,12 +227,23 @@ export default defineBackground({ browser.webRequest.onErrorOccurred.addListener( async (details) => { if (details.type !== 'main_frame') return; - if (details.error === 'net::ERR_ABORTED') return; + if (details.error === 'net::ERR_ABORTED') { + try { + const tab = await browser.tabs.get(details.tabId); + if (tab.url) { + const currentState = tabStates.get(details.tabId); + if (currentState && currentState.url !== tab.url) { + initTab(tab.id!, tab.url, true); + } + } + } catch { } + return; + } await updateState(details.tabId, { status: 'error', errorMessage: details.error - }); + }, details.url); }, { urls: [''] } ); diff --git a/services/dns.ts b/services/dns.ts index 85015e9..3cdc143 100644 --- a/services/dns.ts +++ b/services/dns.ts @@ -1,13 +1,17 @@ export const DnsService = { async resolve(hostname: string): Promise { try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 5000); const response = await fetch( `https://cloudflare-dns.com/dns-query?name=${hostname}&type=A`, { headers: { accept: 'application/dns-json' }, - credentials: 'omit' + credentials: 'omit', + signal: controller.signal, } ); + clearTimeout(timeout); if (!response.ok) return null; diff --git a/services/geo.ts b/services/geo.ts index 18e6568..6616cf7 100644 --- a/services/geo.ts +++ b/services/geo.ts @@ -13,11 +13,15 @@ export const GeoService = { if (cached) return cached; try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 5000); const res = await fetch(`https://ip.albert.lol/${ip}`, { method: 'GET', cache: 'force-cache', - credentials: 'omit' + credentials: 'omit', + signal: controller.signal, }); + clearTimeout(timeout); if (!res.ok) throw new Error(`API Error ${res.status}`);