我制作了一个 Firefox 扩展来获取所有请求 url 并显示它们。但只有当我将代码粘贴到控制台中时,该代码才有效。
当扩展加载时,它没有显示任何错误,看起来它只是无法运行
这是完整代码
xhrScript.js
(function(){
const proxiedOpen = XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function ( _, url) {
this.__URL = url;
return proxiedOpen.apply(this, arguments);
};
const proxiedSend = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function () {
const { protocol, host } = window.location;
// showing only when it paste in console
console.log("full request url ", `${protocol}//${host}${this.__URL}`);
return proxiedSend.apply(this, [].slice.call(arguments));
};
})();
// this works all times
document.body.style.border = "7px solid blue";
manifest.json
{
"manifest_version": 2,
"name": "XHR request urls",
"version": "1.0",
"description": "get all the request url's",
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["xhrScript.js"]
}
]
}
如您所见,最后一行是
document.body.style.border = "7px solid blue";
,每次都可以正常工作。但是 XMLHttpRequest open
和 send
方法不起作用。仅当我将代码粘贴到控制台中时才有效。
如果你想看一个例子,你可以尝试在 devTools 控制台中复制并粘贴
https://reactjs.org中的
xhrScript.js
代码(这是一个 SPA,所以很容易检查我想要的内容),然后查看所有的要求。
我不知道为什么这段代码只有在粘贴到控制台时才运行
内容脚本在隔离的 JavaScript 环境中运行,这意味着
window
及其内容与页面隔离,因此当您修改它时,您仅修改内容脚本的版本。
有两种解决方案:
特定于 Firefox。
使用
wrappedJSObject
和 exportFunction
访问页面上下文(更多信息):
const urls = new WeakMap();
const origXhr = hookPagePrototype('XMLHttpRequest', {
open(method, url) {
urls.set(this, url);
return origXhr.open.apply(this, arguments);
},
send() {
console.log('Sending', new URL(urls.get(this), location).href);
return origXhr.send.apply(this, arguments);
},
});
function hookPagePrototype(protoName, funcs) {
const proto = wrappedJSObject[protoName].prototype;
const oldFuncs = {};
for (const [name, fn] of Object.entries(funcs)) {
oldFuncs[name] = exportFunction(proto[name], wrappedJSObject);
proto[name] = exportFunction(fn, wrappedJSObject);
}
return oldFuncs;
}
兼容 Chrome。
使用 DOM 脚本在页面上下文中运行代码:指令。
它不适用于受严格的内容安全策略(CSP)保护的页面,该策略会阻止脚本执行,因此在为 Firefox 编写扩展时,我们应该使用
wrappedJSObject
方法。