You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展注入脚本未接收StartTimer消息及注入相关问题

Chrome 扩展消息通信与注入问题解决方案

核心问题:点击 popup 按钮后内容脚本未收到消息

问题原因

chrome.runtime.sendMessage 是向扩展的**后台脚本(background.js)**发送消息,内容脚本(injected.js)无法直接接收该消息。要给内容脚本发消息,需要使用 chrome.tabs.sendMessage 并指定目标标签页 ID。

修复代码

修改 popup.js,获取当前活跃标签页并发送消息:

const startTimerBtn = document.getElementById("start-timer-btn")
startTimerBtn.addEventListener("click", async () => {
    // 获取当前窗口的活跃标签页
    const [tab] = await chrome.tabs.query({active: true, currentWindow: true})
    if (tab) {
        // 向目标标签页的内容脚本发送消息
        chrome.tabs.sendMessage(tab.id, { type: "StartTimer"})
    }
})

修改后点击按钮,injected.js 就能收到消息并打印 injected.js: start timer 日志。


额外问题解答

1. 避免向同一标签页重复注入脚本

通过在标签页的全局对象中设置标记,注入前先检查标记是否存在,存在则跳过注入。

修改 background.js 的 injectJS 函数

async function injectJS() {
    let blockUrlList = []
    const res = await chrome.storage.local.get(["block_urls"])
    blockUrlList = res.block_urls || []
    if (!blockUrlList.length) return

    try {
        const qryOptions = { "url": blockUrlList.map(p => `*://*.${p}/*`)}
        const tabs = await chrome.tabs.query(qryOptions) 
        for (const tab of tabs) {
            console.log('checking injection status for tab', tab.id, tab.url)
            try {
                // 检查标签页是否已注入脚本
                const checkResult = await chrome.scripting.executeScript({
                    target: {tabId: tab.id},
                    func: () => window._hasInjectedTimerScript
                })
                if (checkResult[0].result) {
                    console.log('script already injected into tab', tab.id)
                    continue
                }
                // 注入脚本
                await chrome.scripting.executeScript({
                    target: {tabId: tab.id},
                    files: ['content/injected.js']
                })
                // 设置已注入标记
                await chrome.scripting.executeScript({
                    target: {tabId: tab.id},
                    func: () => window._hasInjectedTimerScript = true
                })
                console.log('successfully injected into tab', tab.id)
            } catch(err) {
                console.log('failed to handle tab', tab.id, err)
            }
        }
    } catch(err) {
        console.log('No matching tab', err)
    }
}

修改 injected.js 添加标记初始化

// 初始化已注入标记
window._hasInjectedTimerScript = true;

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "StartTimer") {
        console.log('injected.js: start timer')
    } else if(message.type === "StopTimer"){
        console.log('injected.js: stop timer')
    }
});

console.log("you have been injected") 

2. 新标签打开/刷新时自动注入脚本

在 background.js 中监听标签页的更新和创建事件,当标签加载完成且 URL 匹配规则时自动执行注入逻辑:

// background.js 添加以下代码
// 监听标签页加载完成事件
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
    if (changeInfo.status !== 'complete') return
    await injectScriptIfMatched(tabId, tab.url)
})

// 监听新标签页创建事件
chrome.tabs.onCreated.addListener(async (tab) => {
    // 等待新标签页加载完成
    const waitForLoad = () => new Promise(resolve => {
        const listener = (id, info) => {
            if (id === tab.id && info.status === 'complete') {
                chrome.tabs.onUpdated.removeListener(listener)
                resolve()
            }
        }
        chrome.tabs.onUpdated.addListener(listener)
    })
    await waitForLoad()
    await injectScriptIfMatched(tab.id, tab.url)
})

// 封装匹配检查与注入逻辑
async function injectScriptIfMatched(tabId, tabUrl) {
    const res = await chrome.storage.local.get(["block_urls"])
    const blockUrlList = res.block_urls || []
    if (!blockUrlList.length) return

    // 检查当前URL是否在拦截列表中
    const isMatched = blockUrlList.some(domain => {
        const pattern = new RegExp(`^https?://.*\\.${domain}/.*`, 'i')
        return pattern.test(tabUrl)
    })

    if (isMatched) {
        try {
            const checkResult = await chrome.scripting.executeScript({
                target: {tabId: tabId},
                func: () => window._hasInjectedTimerScript
            })
            if (!checkResult[0].result) {
                await chrome.scripting.executeScript({
                    target: {tabId: tabId},
                    files: ['content/injected.js']
                })
                await chrome.scripting.executeScript({
                    target: {tabId: tabId},
                    func: () => window._hasInjectedTimerScript = true
                })
                console.log('auto injected into tab', tabId)
            }
        } catch(err) {
            console.log('failed auto inject for tab', tabId, err)
        }
    }
}

内容的提问来源于stack exchange,提问作者Ani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:48:14