Почему этот код не работает? Я создаю расширение Firefox, но код не работает. Но если я вставляю код в консоль, он работает

Я делаю расширение 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 не работают. работает только если я вставлю код в консоль.

если вы хотите увидеть пример, попробуйте скопировать и вставить код xhrScript.js в https://reactjs.org (это SPA, так что легко проверить, что я хочу) в консоли devTools, и увидеть весь запрос.

Я не знаю, почему этот код запускается только тогда, когда он вставлен в консоль.


person Carlos Martínez    schedule 13.11.2020    source источник


Ответы (1)


Скрипты контента выполняются в изолированной среде 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.

person wOxxOm    schedule 13.11.2020
comment
Ничего себе, это работает, я действительно новичок в создании расширений для браузера. Это мне очень помогает, спасибо, что поделились документами - person Carlos Martínez; 13.11.2020