覆盖 Firefox 扩展内容脚本中页面的功能

问题描述 投票:0回答:1

我制作了一个 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";

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
方法不起作用。仅当我将代码粘贴到控制台中时才有效。

如果你想看一个例子,你可以尝试在 devTools 控制台中复制并粘贴

https://reactjs.org
中的 xhrScript.js 代码(这是一个 SPA,所以很容易检查我想要的内容),然后查看所有的要求。

我不知道为什么这段代码只有在粘贴到控制台时才运行

javascript firefox xmlhttprequest firefox-addon firefox-addon-webextensions
1个回答
5
投票

内容脚本在隔离的 JavaScript 环境中运行,这意味着

window
及其内容与页面隔离,因此当您修改它时,您仅修改内容脚本的版本。

有两种解决方案:

  1. 特定于 Firefox。

    使用

    wrappedJSObject
    exportFunction
    访问页面上下文(更多信息):

    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。

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

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

    wrappedJSObject
    方法。

© www.soinside.com 2019 - 2024. All rights reserved.