为什么这段代码不起作用?我正在创建 Firefox 扩展,但代码未运行。但是如果我将代码粘贴到控制台中它就可以工作

Car*_*nez 4 javascript firefox xmlhttprequest firefox-addon firefox-addon-webextensions

我制作了一个 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";
Run Code Online (Sandbox Code Playgroud)

清单.json

{
    "manifest_version": 2,
    "name": "XHR request urls",
    "version": "1.0",
    "description": "get all the request url's",

    "content_scripts": [
      {
        "matches": ["*://*/*"],
        "js": ["xhrScript.js"]
      }
    ]  
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在最后一行中document.body.style.border = "7px solid blue";,每次都运行良好。但 XMLHttpRequestopensend方法不起作用。仅当我将代码粘贴到控制台中时才有效。

如果您想查看示例,您可以尝试在 devTools 控制台中复制并粘贴https://reactjs.orgxhrScript.js中的代码(这是一个 SPA,因此很容易检查我想要的内容),然后查看所有请求。

我不知道为什么此代码仅在粘贴到控制台时运行

wOx*_*xOm 5

内容脚本在隔离的 JavaScript 环境中运行,这意味着window其内容与页面隔离,因此当您修改它时,您仅修改内容脚本的版本。

有两种解决方案:

  1. 特定于 Firefox。

    使用wrappedJSObjectexportFunction访问页面上下文(更多信息):

    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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 兼容 Chrome。

    使用 DOM 脚本在页面上下文中运行代码:指令

    它不适用于受严格的内容安全策略(CSP)保护的页面,该策略会阻止脚本执行,因此在为 Firefox 编写扩展时,我们应该使用wrappedJSObject方法。