我有一个 chrome 扩展,旨在拦截响应正文数据,将其处理成有用的统计数据,然后在页面上呈现这些统计数据。
问题是请求拦截器在最重要的请求已经发送/接收之后加载,因此无法抓取它们(请参阅我从 chrome 网络选项卡中附加的图像,希望这会让事情变得更清楚)。
目前,我的拦截器在与我感兴趣的网址匹配的 content.js 脚本中运行。
拦截器.JS
listenerFn = (event) => {
console.log("Url:, ", event.target.responseURL);
// DO OTHER STUFF
}
(
() => {
var XHR = XMLHttpRequest.prototype;
var send = XHR.send;
XHR.send = function() {
this.addEventListener('load', listenerFn)
return send.apply(this, arguments);
};
}
)();
我的清单(V3)脚本看起来像这样......
清单.JSON
{
"manifest_version": 3,
.....
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["URL_OF_INTEREST.com/*"],
"js": ["interceptor.js"],
"run_at": "document_start"
}
],
"web_accessible_resources": [
{
"matches": ["<all_urls>"],
"resources": ["interceptor.js"]
}
],
"permissions": [
"scripting",
"activeTab",
"declarativeContent",
"storage",
"tabs"
],
"host_permissions": [
"*://*/*"
]
}
我觉得我的选择是:
我不知道这些是否可行。 1 - 我不认为在当前设置中可以更快地注入拦截器(因为我认为我已经通过设置 run_at 完成了所有操作)。 2 - 我什至不知道这是否可以做到。 3 - 我相信 WebRequest 不允许访问请求主体。
有人向我提到,由于代码与页面内容无关,因此可以在background.js脚本中运行此代码。所以也许这是一个很好的探索途径。
我在下面附上了两张图片,显示了 chrome 开发工具中的网络选项卡。
在第一张图片中(仅显示 XHR),绿色箭头是我需要抓取的请求,紫色括号涵盖尚未被拦截的请求,黄色箭头是已拦截的请求。第二张图片中的颜色相似(显示 XHR 和 JS 文件),但这包括一个蓝色箭头,显示何时运行 Interceptor.js 文件。
任何建议或指导将不胜感激。如果有人想要/需要任何其他信息,请告诉我,
谢谢!
问题是您的注入器脚本是通过 DOM
script
元素的 src
加载的,因此它是异步加载的,并在页面加载的其他脚本之后运行。
解决方案是直接在页面上下文(又名
document_start
世界)中注册MAIN
处的注入脚本,有两种方法可以实现,如下所示。
您不需要创建
script
元素的内容脚本。
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["interceptor.js"],
"run_at": "document_start",
"world": "MAIN"
}]
删除
web_accessible_resources
以及内容脚本中加载interceptor.js的代码
在manifest.json中添加permissions和host_permissions:
"permissions": ["scripting"],
"host_permissions": ["*://*.example.com/*"],
"background": { "service_worker": "background.js" },
将以下代码添加到您的background.js中:
chrome.runtime.onInstalled.addListener(async () => {
const scripts = [{
id: 'interceptor',
js: ['interceptor.js'],
matches: ['*://*.example.com/*'],
runAt: 'document_start',
world: 'MAIN',
}];
const ids = scripts.map(s => s.id);
await chrome.scripting.unregisterContentScripts({ids}).catch(() => {});
await chrome.scripting.registerContentScripts(scripts).catch(() => {});
});
附注
另一个问题是您在
content_scripts
和web_accessible_resources
中加载相同的文件。您应该使用两个不同的脚本,因为它们在两个不同的上下文(“世界”)中运行。要在它们之间进行通信,您可以使用 CustomEvent 消息传递(示例)。
最后,该网站可能使用 iframe 发出请求,在这种情况下,您需要将
"all_frames": true
添加到 manifest.json 中内容脚本的声明中,如果 iframe 是 "match_origin_as_fallback": true
或不存在,则可能需要添加 about:blank
没有任何src
。