如何为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" ] }
popup.html
<!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>
popup.js
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);
问题分析与修复方案
一、开关功能失效修复
异步操作缺失await
background.js的update分支中,chrome.storage.local.get("active")是异步操作,未加await会导致active值为undefined,无法正确恢复状态,修正后代码:let { active } = await chrome.storage.local.get("active");弹窗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)
三、测试验证
- 在Chrome扩展管理页面重新加载扩展
- 点击弹窗"On"按钮,测试访问stackoverflow.com和google.com/search?q=test,确认拦截生效
- 点击"Off"按钮,确认网站可正常访问
内容的提问来源于stack exchange,提问作者Nicholas Picklas
相关产品推荐
相关产品推荐

