From c14266ee4d3bb777bb4b9f3d23f96f98ae378930 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Sat, 11 Apr 2026 02:52:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E7=9A=84=E5=8A=A0=E8=BD=BD=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=B6=85=E6=97=B6=E4=B8=8E=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BC=98=E5=8C=96=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E7=9B=91=E5=90=AC=E5=99=A8=E7=9A=84=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background.js | 132 ++++++++++++++++++++++++++++++++--------------- content/utils.js | 30 ++++++----- 2 files changed, 107 insertions(+), 55 deletions(-) diff --git a/background.js b/background.js index ad9526a..125b3a7 100644 --- a/background.js +++ b/background.js @@ -344,39 +344,90 @@ async function pingContentScriptOnTab(tabId) { } } +async function waitForTabUrlFamily(source, tabId, referenceUrl, options = {}) { + const { timeoutMs = 15000, retryDelayMs = 400 } = options; + const start = Date.now(); + + while (Date.now() - start < timeoutMs) { + try { + const tab = await chrome.tabs.get(tabId); + if (matchesSourceUrlFamily(source, tab.url, referenceUrl)) { + return tab; + } + } catch { + return null; + } + + await new Promise((resolve) => setTimeout(resolve, retryDelayMs)); + } + + return null; +} + async function ensureContentScriptReadyOnTab(source, tabId, options = {}) { - const { inject = null, injectSource = null } = options; - const pong = await pingContentScriptOnTab(tabId); + const { + inject = null, + injectSource = null, + timeoutMs = 30000, + retryDelayMs = 700, + logMessage = '', + } = options; - if (pong?.ok && (!pong.source || pong.source === source)) { - await registerTab(source, tabId); - return; + const start = Date.now(); + let lastError = null; + let logged = false; + + while (Date.now() - start < timeoutMs) { + const pong = await pingContentScriptOnTab(tabId); + if (pong?.ok && (!pong.source || pong.source === source)) { + await registerTab(source, tabId); + return; + } + + if (!inject || !inject.length) { + throw new Error(`${getSourceLabel(source)} 内容脚本未就绪,且未提供可用的注入文件。`); + } + + const registry = await getTabRegistry(); + if (registry[source]) { + registry[source].ready = false; + await setState({ tabRegistry: registry }); + } + + try { + if (injectSource) { + await chrome.scripting.executeScript({ + target: { tabId }, + func: (injectedSource) => { + window.__MULTIPAGE_SOURCE = injectedSource; + }, + args: [injectSource], + }); + } + + await chrome.scripting.executeScript({ + target: { tabId }, + files: inject, + }); + } catch (err) { + lastError = err; + } + + const pongAfterInject = await pingContentScriptOnTab(tabId); + if (pongAfterInject?.ok && (!pongAfterInject.source || pongAfterInject.source === source)) { + await registerTab(source, tabId); + return; + } + + if (logMessage && !logged) { + await addLog(logMessage, 'warn'); + logged = true; + } + + await new Promise((resolve) => setTimeout(resolve, retryDelayMs)); } - if (!inject || !inject.length) { - throw new Error(`${getSourceLabel(source)} 内容脚本未就绪,且未提供可用的注入文件。`); - } - - const registry = await getTabRegistry(); - if (registry[source]) { - registry[source].ready = false; - await setState({ tabRegistry: registry }); - } - - if (injectSource) { - await chrome.scripting.executeScript({ - target: { tabId }, - func: (injectedSource) => { - window.__MULTIPAGE_SOURCE = injectedSource; - }, - args: [injectSource], - }); - } - - await chrome.scripting.executeScript({ - target: { tabId }, - files: inject, - }); + throw lastError || new Error(`${getSourceLabel(source)} 内容脚本长时间未就绪。`); } // ============================================================ @@ -1799,23 +1850,20 @@ async function executeStep1(state) { const tabId = tab.id; await rememberSourceLastUrl('vps-panel', state.vpsUrl); - await new Promise((resolve) => { - const timer = setTimeout(() => { - chrome.tabs.onUpdated.removeListener(listener); - resolve(); - }, 30000); - const listener = (updatedTabId, info) => { - if (updatedTabId === tabId && info.status === 'complete') { - chrome.tabs.onUpdated.removeListener(listener); - clearTimeout(timer); - resolve(); - } - }; - chrome.tabs.onUpdated.addListener(listener); + await addLog('步骤 1:CPA 面板已打开,正在等待页面进入目标地址...'); + const matchedTab = await waitForTabUrlFamily('vps-panel', tabId, state.vpsUrl, { + timeoutMs: 15000, + retryDelayMs: 400, }); + if (!matchedTab) { + await addLog('步骤 1:CPA 页面尚未完全进入目标地址,继续尝试连接内容脚本...', 'warn'); + } await ensureContentScriptReadyOnTab('vps-panel', tabId, { inject: injectFiles, + timeoutMs: 45000, + retryDelayMs: 900, + logMessage: '步骤 1:CPA 面板仍在加载,正在重试连接内容脚本...', }); const result = await sendToContentScriptResilient('vps-panel', { diff --git a/content/utils.js b/content/utils.js index a4aa52d..2d95fb3 100644 --- a/content/utils.js +++ b/content/utils.js @@ -17,20 +17,24 @@ const LOG_PREFIX = `[MultiPage:${SCRIPT_SOURCE}]`; const STOP_ERROR_MESSAGE = '流程已被用户停止。'; let flowStopped = false; -chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - if (message.type === 'STOP_FLOW') { - flowStopped = true; - console.warn(LOG_PREFIX, STOP_ERROR_MESSAGE); - return; - } +if (!window.__MULTIPAGE_UTILS_LISTENER_READY__) { + window.__MULTIPAGE_UTILS_LISTENER_READY__ = true; - if (message.type === 'PING') { - sendResponse({ - ok: true, - source: SCRIPT_SOURCE, - }); - } -}); + chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'STOP_FLOW') { + flowStopped = true; + console.warn(LOG_PREFIX, STOP_ERROR_MESSAGE); + return; + } + + if (message.type === 'PING') { + sendResponse({ + ok: true, + source: SCRIPT_SOURCE, + }); + } + }); +} function resetStopState() { flowStopped = false;