Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

javascript - 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

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...