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

Manifest V3扩展:右键点击仅注入一次Content Script求助

解决方案

方法一:通过DOM标记检测注入状态

这种方法直接在页面DOM中添加标识,background通过执行检测脚本读取该标记判断是否已注入,不受页面刷新外的其他因素影响,可靠性更高。

步骤1:修改payload.js,注入后添加DOM标记

在Content Script执行时,给document添加自定义属性作为已注入的标记,同时修正原代码的消息发送逻辑:

function extract() {
    // 原提取逻辑保留,修正变量声明避免全局污染
    const htmlInnerText = document.documentElement.innerText;
    const url_exp = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
    const list_url = htmlInnerText.match(url_exp);

    const ip_exp = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
    const list_ip = htmlInnerText.match(ip_exp);

    const hash_exp = /\b[A-Fa-f0-9]{32}\b|\b[A-Fa-f0-9]{40}\b|\b[A-Fa-f0-9]{64}\b/g;
    const list_hash = htmlInnerText.match(hash_exp);

    chrome.storage.local.set({ list_url, list_ip, list_hash });
    // 提取完成后发送消息通知background
    chrome.runtime.sendMessage({ type: 'extractionComplete' });
}

// 添加DOM标记,标记当前页面已注入脚本
document.documentElement.setAttribute('data-payload-injected', 'true');
// 执行提取逻辑
extract();

// 监听background的重新提取指令
chrome.runtime.onMessage.addListener((message) => {
    if (message.type === 'reExtract') {
        extract();
    }
});

步骤2:修改background.js,先检测再注入

在右键点击事件中,先执行检测脚本判断是否已注入,未注入时才加载payload.js,同时修正消息监听的重复绑定问题:

// 全局绑定消息监听,避免每次点击重复添加
chrome.runtime.onMessage.addListener(async (message) => {
    if (message.type !== 'extractionComplete') return;
    
    // 用Promise封装storage操作,避免回调嵌套
    const [urlData, ipData, hashData] = await Promise.all([
        chrome.storage.local.get('list_url'),
        chrome.storage.local.get('list_ip'),
        chrome.storage.local.get('list_hash')
    ]);
    const urls = urlData.list_url || [];
    const ips = ipData.list_ip || [];
    const hashes = hashData.list_hash || [];

    if (hashes.length > 0 || urls.length > 0 || ips.length > 0) {
        chrome.windows.create({ url: "output.html", type: "popup", height: 1000, width: 1000 });
    }
});

const genericOnClick = async () => {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    if (!tab) return;

    // 执行检测脚本,读取DOM标记判断是否已注入
    const [{result: isInjected}] = await chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: () => document.documentElement.hasAttribute('data-payload-injected')
    });

    if (!isInjected) {
        // 未注入时加载payload.js
        await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            files: ["payload.js"]
        });
    } else {
        // 已注入时,发送指令让脚本重新执行提取逻辑
        chrome.tabs.sendMessage(tab.id, { type: 'reExtract' });
    }
};

方法二:在Background中维护注入状态集合

通过在background中记录已注入的tabId,配合tab关闭/刷新事件清理记录,适合不需要频繁刷新的场景:

步骤1:background.js中维护注入状态

const injectedTabs = new Set();

// 监听tab关闭,移除对应记录
chrome.tabs.onRemoved.addListener((tabId) => injectedTabs.delete(tabId));
// 监听tab刷新,刷新后清空记录(页面刷新后脚本会被清除)
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
    if (changeInfo.status === 'loading') injectedTabs.delete(tabId);
});

const genericOnClick = async () => {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    if (!tab) return;

    if (!injectedTabs.has(tab.id)) {
        await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            files: ["payload.js"]
        });
        injectedTabs.add(tab.id);
    } else {
        chrome.tabs.sendMessage(tab.id, { type: 'reExtract' });
    }
};

// 消息监听同方法一
chrome.runtime.onMessage.addListener(async (message) => {
    // ... 同方法一逻辑
});

步骤2:payload.js添加重新提取监听

同方法一中的payload.js消息监听部分即可。

关键修正说明

  • 原代码中chrome.runtime.sendMessage(extract())会立即执行extract并发送其返回值(undefined),改为在extract内部发送消息,确保逻辑顺序正确。
  • 原代码每次右键点击都会新增消息监听,导致多次触发弹窗,改为全局绑定一次监听。

内容的提问来源于stack exchange,提问作者tonia j sebastian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:20:34