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

如何为Manifest V3版Chrome扩展实现网站拦截开关?

解决Chrome Manifest V3网站拦截扩展的开关功能与规则问题

问题概述

我开发了一款基于Manifest V3的Chrome网站拦截扩展(Chrome版本111.0.5563.146),已完成弹窗菜单的HTML结构,但缺少关闭拦截、移除网站拦截的逻辑代码。目前所有拦截规则均未生效,此前仅stackoverflow.com拦截有效,google.com/search*始终无效,怀疑是规则定义问题,需实现开关功能并修复拦截规则。

当前代码

manifest.json

{    
    "manifest_version": 3,    
    "name": "On-Off Switch",    
    "version": "1.0.0",    
    "action": {
        "default_popup": "popup.html"
    },    
    "background": {
        "service_worker": "background.js"
    },    
    "declarative_net_request": {
        "rule_resources": [
            {
                "id": "ruleset_1",
                "enabled": false,
                "path": "ruleset_1.json"
            }
        ]
    },    
    "permissions": [
        "declarativeNetRequest",
        "storage"
    ]
}
<!DOCTYPE html>
<html>    
    <head>
        <title>popup</title>
    </head>    
    <body>
        <p>popup</p>
        <button id="on">On</button>
        <button id="off">Off</button>
        <script src="popup.js"></script>
    </body>
</html>
document.getElementById("on").onclick = () => {  
    chrome.storage.local.set({active: true});
}

document.getElementById("off").onclick = () => {  
    chrome.storage.local.set({active: false});
}

ruleset_1.json

[    
    {
        "id": 1,
        "action": { "type": "block" },
        "condition": { "urlFilter": "stackoverflow.com", "resourceTypes": ["main_frame"] }
    },    
    {
        "id": 2,
        "action": { "type": "block" },
        "condition": { "urlFilter": "google.com/search*", "resourceTypes": ["main_frame"] }
    }
]

background.js

async function runtime_on_installed(details) {    
    if (details.reason == "install") {
        let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
        if (ruleset_ids.length == 0) {
            await chrome.storage.local.set({active: false});
        }
        else if (ruleset_ids.length == 1) {
            await chrome.storage.local.set({active: true});
        }
    }    
    else if (details.reason == "update") {
        let { active } = chrome.storage.local.get("active");
        let ruleset_ids = await chrome.declarativeNetRequest.getEnabledRulesets();
        if (active && ruleset_ids.length == 0) {
            chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
        }
        else if (!active && ruleset_ids.length == 1) {
            chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
        }
    }
}

function storage_on_changed(changes, area_name) {    
    if (area_name == "local") {
        if (changes.active.oldValue == false && changes.active.newValue == true) {
            chrome.declarativeNetRequest.updateEnabledRulesets({enableRulesetIds: ["ruleset_1"]});
        }
        else if (changes.active.oldValue == true && changes.active.newValue == false) {
            chrome.declarativeNetRequest.updateEnabledRulesets({disableRulesetIds: ["ruleset_1"]});
        }
    }
}

chrome.runtime.onInstalled.addListener(runtime_on_installed);
chrome.storage.onChanged.addListener(storage_on_changed);

问题分析与修复方案

一、开关功能失效修复

  1. 异步操作缺失await
    background.js的update分支中,chrome.storage.local.get("active")是异步操作,未加await会导致active值为undefined,无法正确恢复状态,修正后代码:

    let { active } = await chrome.storage.local.get("active");
    
  2. 弹窗UI状态同步
    原弹窗无法直观显示当前开关状态,修改popup.js添加状态同步逻辑:

    document.addEventListener('DOMContentLoaded', async () => {
        let { active } = await chrome.storage.local.get("active");
        updateButtonState(active);
    });
    
    document.getElementById("on").onclick = async () => {  
        await chrome.storage.local.set({active: true});
        updateButtonState(true);
    }
    
    document.getElementById("off").onclick = async () => {  
        await chrome.storage.local.set({active: false});
        updateButtonState(false);
    }
    
    function updateButtonState(isActive) {
        document.getElementById("on").disabled = isActive;
        document.getElementById("off").disabled = !isActive;
        document.getElementById("on").style.backgroundColor = isActive ? '#4CAF50' : '#ddd';
        document.getElementById("off").style.backgroundColor = !isActive ? '#f44336' : '#ddd';
    }
    

二、拦截规则失效修复

google.com/search*规则无效的核心原因是未匹配HTTP/HTTPS协议和子域名,且通配符使用不符合DNR语法。修改ruleset_1.json:

[    
    {
        "id": 1,
        "action": { "type": "block" },
        "condition": { 
            "urlFilter": "*://*.stackoverflow.com/*", 
            "resourceTypes": ["main_frame"] 
        }
    },    
    {
        "id": 2,
        "action": { "type": "block" },
        "condition": { 
            "urlFilter": "*://*.google.com/search*", 
            "resourceTypes": ["main_frame"] 
        }
    }
]
  • *://匹配HTTP和HTTPS协议
  • *.匹配任意子域名(如www.google.com)
  • /*确保匹配域名下所有路径(针对stackoverflow)
  • search*匹配包含search开头的路径(如search?q=xxx)

三、测试验证

  1. 在Chrome扩展管理页面重新加载扩展
  2. 点击弹窗"On"按钮,测试访问stackoverflow.com和google.com/search?q=test,确认拦截生效
  3. 点击"Off"按钮,确认网站可正常访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:43:11