From 4050e3473f4f07eb89200cd21f42d42baeb58b2b Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Sat, 11 Apr 2026 20:29:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=B8=8E=E5=86=85=E5=AE=B9=E8=84=9A=E6=9C=AC=E7=9A=84=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/background.js b/background.js index 61101c9..c0e8458 100644 --- a/background.js +++ b/background.js @@ -436,6 +436,52 @@ async function ensureContentScriptReadyOnTab(source, tabId, options = {}) { const pendingCommands = new Map(); // source -> { message, resolve, reject, timer } +function getContentScriptResponseTimeoutMs(message) { + if (!message || typeof message !== 'object') { + return 30000; + } + + if (message.type === 'POLL_EMAIL') { + const maxAttempts = Math.max(1, Number(message.payload?.maxAttempts) || 1); + const intervalMs = Math.max(0, Number(message.payload?.intervalMs) || 0); + return Math.max(45000, maxAttempts * intervalMs + 25000); + } + + if (message.type === 'FILL_CODE') { + return Number(message.step) === 7 ? 45000 : 30000; + } + + if (message.type === 'PREPARE_SIGNUP_VERIFICATION') { + return 45000; + } + + return 30000; +} + +function sendTabMessageWithTimeout(tabId, source, message, responseTimeoutMs = getContentScriptResponseTimeoutMs(message)) { + return new Promise((resolve, reject) => { + let settled = false; + + const finalize = (callback) => (value) => { + if (settled) return; + settled = true; + clearTimeout(timer); + callback(value); + }; + + const timer = setTimeout(() => { + if (settled) return; + settled = true; + const seconds = Math.ceil(responseTimeoutMs / 1000); + reject(new Error(`Content script on ${source} did not respond in ${seconds}s. Try refreshing the tab and retry.`)); + }, responseTimeoutMs); + + chrome.tabs.sendMessage(tabId, message) + .then(finalize(resolve)) + .catch(finalize(reject)); + }); +} + function queueCommand(source, message, timeout = 15000) { return new Promise((resolve, reject) => { const timer = setTimeout(() => { @@ -454,7 +500,7 @@ function flushCommand(source, tabId) { if (pending) { clearTimeout(pending.timer); pendingCommands.delete(source); - chrome.tabs.sendMessage(tabId, pending.message).then(pending.resolve).catch(pending.reject); + sendTabMessageWithTimeout(tabId, source, pending.message).then(pending.resolve).catch(pending.reject); console.log(LOG_PREFIX, `Flushed queued command to ${source} (tab ${tabId})`); } } @@ -614,7 +660,8 @@ async function reuseOrCreateTab(source, url, options = {}) { // Send command to content script (with readiness check) // ============================================================ -async function sendToContentScript(source, message) { +async function sendToContentScript(source, message, options = {}) { + const { responseTimeoutMs = getContentScriptResponseTimeoutMs(message) } = options; const registry = await getTabRegistry(); const entry = registry[source]; @@ -632,7 +679,7 @@ async function sendToContentScript(source, message) { } console.log(LOG_PREFIX, `Sending to ${source} (tab ${entry.tabId}):`, message.type); - return chrome.tabs.sendMessage(entry.tabId, message); + return sendTabMessageWithTimeout(entry.tabId, source, message, responseTimeoutMs); } async function sendToContentScriptResilient(source, message, options = {}) { @@ -756,7 +803,7 @@ function isStopError(error) { function isRetryableContentScriptTransportError(error) { const message = String(typeof error === 'string' ? error : error?.message || ''); - return /back\/forward cache|message channel is closed|Receiving end does not exist|port closed before a response was received|A listener indicated an asynchronous response/i.test(message); + return /back\/forward cache|message channel is closed|Receiving end does not exist|port closed before a response was received|A listener indicated an asynchronous response|did not respond in \d+s/i.test(message); } function getErrorMessage(error) {