问题
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
here is the full code
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"]
}
]
}
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.
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
回答1:
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.
There are two solutions:
Firefox-specific.
Use
wrappedJSObject
andexportFunction
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-compatible.
Use a DOM script to run the code in page context: instruction.
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.
来源:https://stackoverflow.com/questions/64816454/why-is-this-code-not-working-i-am-creating-a-firefox-extension-but-the-code-is