自定义Chrome扩展未按预期执行重定向功能,请求排查问题
自定义Chrome扩展未按预期执行重定向功能,请求排查问题
我帮你梳理下代码里的几个核心问题,这些问题导致你的扩展没按预期工作:
1. 监听时机与逻辑顺序错误
你用了chrome.webRequest.onCompleted来监听CSS资源加载完成,但这个事件是单个资源加载完就触发,而不是等页面所有CSS都加载完毕。这会导致:
- 你可能误把先加载的小CSS当成最大的,后续更大的CSS加载时又会覆盖,但之前已经做了无用的计数判断
- 页面已经在加载甚至开始渲染了,这时候再重定向,完全不符合你“页面显示前处理”的需求
另外,你在webRequest.onCompleted里用chrome.tabs.query({active: true})获取标签ID非常不可靠——如果用户同时打开多个标签,当前激活的标签可能根本不是触发请求的那个标签,应该直接用details.tabId(webRequest的回调参数里自带当前请求对应的标签ID)。
2. 最大CSS文件的判断逻辑有漏洞
当前代码每加载一个CSS就更新一次“最大尺寸”并立即做计数判断,但后续可能还有更大的CSS加载,这会导致你判断的对象根本不是真正最大的那个CSS文件,自然不会触发预期的重定向。
3. 架构设计冗余
你把核心的计数、对比逻辑放在content.js里,还要通过消息来回传递,不仅增加了复杂度,还容易因为时机问题导致逻辑失效。这类资源分析、页面控制的逻辑更适合放在background脚本里处理。
修正后的完整代码方案
我调整了整个逻辑,确保在页面DOM加载完成但还未完全渲染前,收集所有CSS资源、找到最大的那个,再完成计数对比和重定向:
1. manifest.json(仅调整部分权限,核心不变)
{ "manifest_version": 2, "name": "Page Blocker", "version": "1.0", "permissions": ["webRequest", "webRequestBlocking", "storage", "<all_urls>", "webNavigation"], "background": { "scripts": ["background.js"], "persistent": true }, "browser_action": { "default_icon": "icon.png" }, "icons": { "48": "icon.png" } }
新增了
webNavigation权限,用来监听页面加载的关键节点
2. background.js(核心逻辑重构)
// 存储每个标签页的CSS资源信息:key是tabId,value是CSS数组 const tabCssResources = {}; // 监听所有CSS资源加载完成,收集资源信息 chrome.webRequest.onCompleted.addListener( (details) => { if (details.type === "stylesheet" && details.tabId !== -1) { // 初始化当前标签的CSS数组 if (!tabCssResources[details.tabId]) { tabCssResources[details.tabId] = []; } // 记录CSS的URL和大小(优先用encodedDataLength,更准确) const cssSize = details.encodedDataLength || details.transferSize; tabCssResources[details.tabId].push({ url: details.url, size: cssSize }); } }, { urls: ["<all_urls>"], types: ["stylesheet"] } ); // 监听页面DOM加载完成(此时所有CSS已加载,页面还未完全渲染) chrome.webNavigation.onDOMContentLoaded.addListener( (details) => { const tabId = details.tabId; const cssList = tabCssResources[tabId]; if (!cssList || cssList.length === 0) { // 当前页面没有CSS,直接清理缓存并返回 delete tabCssResources[tabId]; return; } // 找到最大的CSS文件 const largestCss = cssList.reduce((prev, curr) => { return prev.size > curr.size ? prev : curr; }); // 读取本地db.txt的阈值 fetch(chrome.extension.getURL("db.txt")) .then(res => res.text()) .then(thresholdText => { const thresholdCount = parseInt(thresholdText.trim(), 10); if (isNaN(thresholdCount)) { console.error("db.txt中的阈值不是有效数字"); return; } // 获取最大CSS的内容并计数 fetch(largestCss.url) .then(res => res.text()) .then(cssContent => { const targetCount = (cssContent.match(/maimuna/g) || []).length; // 对比计数,触发重定向 if (targetCount === thresholdCount) { chrome.tabs.update(tabId, { url: "http://1.1.1.1/error.html" }); } }) .catch(err => console.error("获取CSS内容失败:", err)); }) .catch(err => console.error("读取db.txt失败:", err)) .finally(() => { // 清理当前标签的CSS缓存,避免内存泄漏 delete tabCssResources[tabId]; }); }, { urls: ["<all_urls>"] } ); // 扩展安装时初始化存储 chrome.runtime.onInstalled.addListener(() => { chrome.storage.local.set({ thresholdCount: 0 }, () => { console.log("本地存储初始化完成"); }); });
3. 删除content.js
现在核心逻辑都在background里,不需要content.js了,直接删掉即可。
额外注意事项
- 确保
db.txt文件和你的扩展文件放在同一目录下,并且内容是纯数字(比如5) - 测试时要开启Chrome的开发者模式,加载已解压的扩展包,同时打开开发者工具的background页面查看日志,方便排查问题
- 如果你需要兼容Chrome Manifest V3,后续可以再调整架构,但当前V2的方案已经能满足你的需求
备注:内容来源于stack exchange,提问作者ionicle
相关产品推荐
相关产品推荐

