Why is this code not working? I am creating a Firefox extension but the code is not running. But if I paste the code into the console it works

妖精的绣舞 提交于 2021-02-04 19:55:33

问题


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:

  1. Firefox-specific.

    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;
    }
    
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!