From bb34b6768022d53ef94bc65c1dd738becb43813f Mon Sep 17 00:00:00 2001 From: johnysigma Date: Mon, 30 Mar 2026 15:13:46 +0300 Subject: [PATCH] fix: improve proxy fallback and kill switch logic --- js/background.js | 41 +++++++++++++++++++++++++---------------- js/proxy-manager.js | 13 ++++++++++--- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/js/background.js b/js/background.js index 871902d..c303592 100644 --- a/js/background.js +++ b/js/background.js @@ -307,6 +307,7 @@ async function handleNextProxy() { status: 'connected', proxy: result.proxy }); + } else { } return result; @@ -441,7 +442,7 @@ async function handleSaveSettings(settings) { Utils.log('warn', 'Custom proxy settings invalid, disconnecting...'); await ProxyManager.disconnect(); await Storage.setProxyEnabled(false); - broadcastMessage({ + broadcastMessage({ action: 'statusUpdate', status: 'error', error: 'Custom proxy not configured' @@ -456,7 +457,7 @@ async function handleSaveSettings(settings) { ); if (result) { - broadcastMessage({ + broadcastMessage({ action: 'statusUpdate', status: 'connected', proxy: { host: customProxy.ip, port: customProxy.port }, @@ -466,7 +467,7 @@ async function handleSaveSettings(settings) { // Failed to apply - disconnect await ProxyManager.disconnect(); await Storage.setProxyEnabled(false); - broadcastMessage({ + broadcastMessage({ action: 'statusUpdate', status: 'error', error: 'Failed to apply proxy settings' @@ -556,6 +557,7 @@ function broadcastMessage(message) { }); } + /** * Handle proxy errors */ @@ -573,14 +575,27 @@ chrome.proxy.onProxyError.addListener(async (details) => { Utils.log('error', 'Proxy error', details); + // Check if proxy is enabled - don't reconnect if user disconnected + const proxyEnabled = await Storage.isProxyEnabled(); + if (!proxyEnabled) { + Utils.log('debug', 'Proxy disabled, ignoring error'); + return; + } + // Check current mode - only attempt fallback for public proxies const mode = await Storage.getMode(); const killSwitch = await Storage.getValue(CONFIG.STORAGE_KEYS.KILL_SWITCH, false); - // For non-fatal errors in public mode, attempt fallback - if (!details.fatal && mode === CONFIG.MODES.PUBLIC) { + // For public mode, always attempt fallback (regardless of fatal flag) + if (mode === CONFIG.MODES.PUBLIC) { const result = await ProxyManager.fallbackToNext(); if (result.success) { + // Deactivate kill switch if it was active + const killSwitchActive = await Storage.getValue('killSwitchActive', false); + if (killSwitchActive) { + await applyKillSwitch(false); + Utils.log('info', 'Kill switch deactivated after successful fallback'); + } broadcastMessage({ action: 'statusUpdate', status: 'connected', @@ -653,23 +668,17 @@ async function applyKillSwitch(activate) { }; await chrome.proxy.settings.set({ value: config, scope: 'regular' }); await Storage.setValue('killSwitchActive', true); + // Show red badge with exclamation mark + await chrome.action.setBadgeText({ text: '!' }); + await chrome.action.setBadgeBackgroundColor({ color: '#E74C3C' }); Utils.log('info', 'Kill switch ACTIVATED - all traffic blocked'); - - // Update icon to show blocked state - try { - await chrome.action.setBadgeText({ text: '!' }); - await chrome.action.setBadgeBackgroundColor({ color: '#e74c3c' }); - } catch (e) {} } else { // Deactivate kill switch - clear proxy settings await chrome.proxy.settings.clear({ scope: 'regular' }); await Storage.setValue('killSwitchActive', false); + // Remove badge + await chrome.action.setBadgeText({ text: '' }); Utils.log('info', 'Kill switch DEACTIVATED - traffic restored'); - - // Clear badge - try { - await chrome.action.setBadgeText({ text: '' }); - } catch (e) {} } return true; } catch (error) { diff --git a/js/proxy-manager.js b/js/proxy-manager.js index 3f55ebe..9eecfdd 100644 --- a/js/proxy-manager.js +++ b/js/proxy-manager.js @@ -375,9 +375,10 @@ const ProxyManager = { /** * Fallback to next proxy + * @param {number} attemptCount - Number of attempts made * @returns {Promise<{success: boolean, proxy: object|null, error: string|null}>} */ - async fallbackToNext() { + async fallbackToNext(attemptCount = 0) { if (this._proxyList.length === 0) { return { success: false, proxy: null, error: 'No proxies available. Please refresh the proxy list.' }; } @@ -386,17 +387,23 @@ const ProxyManager = { return { success: false, proxy: null, error: 'Only one proxy available' }; } + // Prevent infinite loop - stop after trying all proxies + if (attemptCount >= this._proxyList.length) { + Utils.log('error', 'All proxies failed, no working proxy found'); + return { success: false, proxy: null, error: 'All proxies are unavailable' }; + } + this._currentIndex = (this._currentIndex + 1) % this._proxyList.length; const proxy = this._proxyList[this._currentIndex]; - Utils.log('info', `Switching to proxy ${this._currentIndex + 1}/${this._proxyList.length}: ${proxy.host}:${proxy.port}`); + Utils.log('info', `Switching to proxy ${this._currentIndex + 1}/${this._proxyList.length}: ${proxy.host}:${proxy.port} (attempt ${attemptCount + 1}/${this._proxyList.length})`); // Test the proxy first to get latency const testResult = await this.testProxy(proxy); if (!testResult.working) { // Try next proxy if this one doesn't work Utils.log('warn', `Proxy ${proxy.host}:${proxy.port} not working, trying next...`); - return this.fallbackToNext(); + return this.fallbackToNext(attemptCount + 1); } // Merge test results (latency) with proxy info