From 19b7ab141a8418f35ea500d87f46ca4e84795b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Sun, 15 Feb 2026 01:35:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(extension):=20=E6=B7=BB=E5=8A=A0=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E5=99=A8=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 集成 Chrome 调试器 API 支持 attach/detach 功能 - 新增 tabUtils 工具模块用于获取活动标签页 ID - 在背景脚本中添加标签页激活和更新事件监听 - 使用 Material-UI 容器和堆叠组件重构页面布局 - 移除 Chromium 启动参数中的自动打开开发者工具选项 - 更新权限配置添加调试器相关权限 - 在测试页面添加多个调试功能按钮和状态管理 --- components/TimestampExecution.tsx | 4 +- entrypoints/background.ts | 40 +++-------- entrypoints/popup/pages/RecordeReplayPage.tsx | 10 +-- entrypoints/popup/pages/TestPage.tsx | 68 +++++++++++++++++++ entrypoints/popup/pages/TimestampPage.tsx | 13 ++-- utils/tabUtils.ts | 35 ++++++++++ web-ext.config.ts | 2 +- wxt.config.ts | 1 + 8 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 utils/tabUtils.ts diff --git a/components/TimestampExecution.tsx b/components/TimestampExecution.tsx index a912131..7ca6b07 100644 --- a/components/TimestampExecution.tsx +++ b/components/TimestampExecution.tsx @@ -40,7 +40,7 @@ export function TimestampExecution(): JSX.Element { const toggleButtonText = isRunningTimestamp ? '停止' : '开始'; return ( - + { ); }); + chrome.tabs.onActivated.addListener((activeInfo) => { + console.log('当前活跃的 Tab ID:', activeInfo.tabId); + }); + + chrome.tabs.onUpdated.addListener((tabId) => { + console.log('加载完成的 Tab ID:', tabId); + }); + onMessage('popup:check-status', async (message) => { console.log(`[background] popup:check-status: ${message}`); const obj = { @@ -109,35 +118,4 @@ export default defineBackground(() => { events.push(eventsList); return true; }); - - async function getActiveTabId() { - const activeTabs = await chrome.tabs.query({ - active: true, - currentWindow: true, - }); - const activeTab = activeTabs[0]; - - if (!activeTab) { - throw new Error('No active tab found.'); - } - - // 检查URL是否受限 - if (activeTab?.url) { - const restrictedProtocols = [ - 'chrome:', - 'chrome-extension:', - 'about:', - 'edge:', - 'view-source:', - 'data:', - 'file:', - ]; - if (restrictedProtocols.some((protocol) => activeTab.url!.startsWith(protocol))) { - throw new Error(`Cannot send message to a restricted URL: ${activeTab.url}`); - } - } - - const sendTo = activeTab.id; - return sendTo!; - } }); diff --git a/entrypoints/popup/pages/RecordeReplayPage.tsx b/entrypoints/popup/pages/RecordeReplayPage.tsx index 7de7e06..1f9dd19 100644 --- a/entrypoints/popup/pages/RecordeReplayPage.tsx +++ b/entrypoints/popup/pages/RecordeReplayPage.tsx @@ -1,7 +1,7 @@ import { useEffect, useState, useMemo } from 'react'; import { AppState } from '../types'; import { sendMessage, onMessage } from '@/utils/messages'; -import { Button } from '@mui/material'; +import { Button, Container, Stack } from '@mui/material'; const RecordeReplayPage = () => { const [status, setStatus] = useState(AppState.READ); @@ -54,8 +54,8 @@ const RecordeReplayPage = () => { }; return ( -
-
+ + -
-
+ + ); }; diff --git a/entrypoints/popup/pages/TestPage.tsx b/entrypoints/popup/pages/TestPage.tsx index 6e915fe..318d9e8 100644 --- a/entrypoints/popup/pages/TestPage.tsx +++ b/entrypoints/popup/pages/TestPage.tsx @@ -1,16 +1,84 @@ import { sendMessage } from '@/utils/messages'; import { Button } from '@mui/material'; +import { useState, useEffect } from 'react'; const TestPage = () => { + const [tabId, setTabId] = useState(-1); + + useEffect(() => { + (async () => { + const activeTabs = await chrome.tabs.query({ + active: true, + currentWindow: true, + }); + console.log(`activeTabs:`, activeTabs[0].id); + if (activeTabs[0].id && activeTabs[0].id > 0) setTabId(activeTabs[0].id); + else throw new Error('no active tab'); + })(); + }); + const handleSeedMessage = async () => { const status = await sendMessage('popup:check-status'); console.log(`[popup]status: ${status}`); }; + + const handleAttach = () => { + try { + chrome.debugger.attach({ tabId: tabId }, '1.2', () => { + console.log('[debugger] attached'); + }); + } catch (err) { + console.error(err); + } + }; + + const handleDetach = async () => { + try { + chrome.debugger.detach({ tabId: tabId }, () => { + console.log('[debugger] detached'); + }); + } catch (err) { + console.error(err); + } + }; + + const handleGetTarget = () => { + chrome.debugger.getTargets((targets) => { + console.log('[debugger] targets:', targets); + }); + }; + + const enableRuntime = () => { + chrome.debugger.sendCommand({ tabId: tabId }, 'Runtime.enable', {}, (res) => { + console.log('[debugger] Runtime.enable:', res); + }); + }; + + const disableRuntime = () => { + chrome.debugger.sendCommand({ tabId: tabId }, 'Runtime.disable', {}, (res) => { + console.log('[debugger] Runtime.disable:', res); + }); + }; return (
+ + + + +
); }; diff --git a/entrypoints/popup/pages/TimestampPage.tsx b/entrypoints/popup/pages/TimestampPage.tsx index d02c555..172ab41 100644 --- a/entrypoints/popup/pages/TimestampPage.tsx +++ b/entrypoints/popup/pages/TimestampPage.tsx @@ -1,14 +1,17 @@ import { TimestampToDatetime } from '@/components/TimestampToDatetime'; import { DatetimeToTimestamp } from '@/components/DatetimeToTimestamp'; import { TimestampExecution } from '@/components/TimestampExecution'; +import { Container, Box } from '@mui/material'; const TimestampPage = () => { return ( -
- - - -
+ + + + + + + ); }; diff --git a/utils/tabUtils.ts b/utils/tabUtils.ts new file mode 100644 index 0000000..95d1dc8 --- /dev/null +++ b/utils/tabUtils.ts @@ -0,0 +1,35 @@ +import { browser } from 'wxt/browser'; + +/** + * 获取当前活动标签页的 ID + * @returns Promise 返回活动标签页的 ID,如果未找到则返回 undefined + */ +export async function getActiveTabId(): Promise { + const activeTabs = await browser.tabs.query({ + active: true, + currentWindow: true, + }); + const activeTab = activeTabs[0]; + + if (!activeTab) { + throw new Error('No active tab found.'); + } + + // 检查URL是否受限 + if (activeTab?.url) { + const restrictedProtocols = [ + 'chrome:', + 'chrome-extension:', + 'about:', + 'edge:', + 'view-source:', + 'data:', + 'file:', + ]; + if (restrictedProtocols.some((protocol) => activeTab.url!.startsWith(protocol))) { + throw new Error(`Cannot send message to a restricted URL: ${activeTab.url}`); + } + } + + return activeTab.id; +} \ No newline at end of file diff --git a/web-ext.config.ts b/web-ext.config.ts index 2e2de5d..63bf5c3 100644 --- a/web-ext.config.ts +++ b/web-ext.config.ts @@ -2,5 +2,5 @@ import { defineWebExtConfig } from 'wxt'; export default defineWebExtConfig({ startUrls: ['https://www.baidu.com', 'chrome://extensions/'], - chromiumArgs: ['chrome://extensions/', '--auto-open-devtools-for-tabs'], + chromiumArgs: ['chrome://extensions/'], }); diff --git a/wxt.config.ts b/wxt.config.ts index 4a50750..d79a761 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -16,6 +16,7 @@ export default defineConfig({ 'tabs', 'offscreen', 'downloads', + 'debugger', ], host_permissions: [''], action: {