为什么这段代码不起作用?我正在创建一个 Firefox 扩展,但代码没有运行.但是,如果我将代码粘贴到控制台中,它就可以工作
我做了一个 Firefox 扩展来获取所有请求的 url 并显示它们.但代码只有在我将其粘贴到控制台时才有效.
I make a firefox extension that get all the request url's and displays them. But the code only works if I paste it in the console.
当扩展程序加载时它没有显示任何错误,它似乎只是不会运行
when the extension loads it doesn't show any error, it seems like it just won't run
这是完整的代码
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
方法不起作用.仅当我将代码粘贴到控制台时才有效.
As you can see, in the last line is document.body.style.border = "7px solid blue";
, this works fine every time. But the XMLHttpRequest open
and send
methods don't work. only works if I paste the code in the console.
如果您想查看示例,可以尝试将 xhrScript.js
代码复制并粘贴到 https://reactjs.org(这是一个 SPA,所以很容易检查我想要什么)在 devTools 控制台中,并查看所有请求.
if you want see an example, you can try copy and paste the xhrScript.js
code in https://reactjs.org (it's a SPA, so it's easy to check what I want) in the devTools console, and see all the request.
我不知道为什么这段代码只有在控制台粘贴时才会运行
I don't know why this code only runs when it is pasted in console
推荐答案
内容脚本在隔离的 JavaScript 环境中运行,这意味着 window
及其内容与页面隔离,因此当您修改它时,您只修改内容脚本的版本.
Content scripts run in an isolated JavaScript environment meaning that window
and its contents are isolated from the page so when you modify it, you only modify the content script's version.
有两种解决方案:
Firefox 专用.
Firefox-specific.
使用 wrappedJSObject
和 exportFunction
访问页面上下文(更多信息):
Use wrappedJSObject
and exportFunction
to access the page context (more info):
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 兼容.
Chrome-compatible.
使用 DOM 脚本在页面上下文中运行代码:说明.
它不适用于受严格的 Content-Security-Policy (CSP) 保护的页面,该 CSP 会阻止脚本执行,因此在为 Firefox 编写扩展时,我们应该改用 wrappedJSObject
方法.
It won't work on pages protected by a strict Content-Security-Policy (CSP) that prevents script execution so when writing an extension for Firefox we should use wrappedJSObject
method instead.
相关文章