Как расширение может прослушивать WebSocket? (а что, если WebSocket находится внутри iframe?)

Я пишу расширение Firefox, которому нужно прослушивать связь между браузером и сервером. Для связи по протоколу HTTP я использую библиотеку webRequest в фоновом сценарии. Но, согласно этому отчету об ошибке Mozilla, я не могу использовать webRequest для перехвата сообщений WebSocket. . Как мое расширение может прослушивать связь через WebSocket?

Обновление:

Я ввел моя оболочка WebSocket, но она никогда не вызывается! WebSocket, который я пытаюсь прослушать, находится внутри iframe. Это имеет значение?




Ответы (1)


Единственный способ прослушать связь WebSocket — это внедрить оболочку WebSocket в код сайта и передать вам сообщения. Ваш код должен выглядеть примерно так:

manifest.json

{
  ...
  "content_scripts": [
    {
      "matches": [
        "<website-url>",    
      ],
      "js": ["content/syringe.js"]
    }
  ],
  "web_accessible_resources": ["lib/socket-sniffer.js"]
}

содержимое /syringe.js

var s = document.createElement('script');
s.src = browser.runtime.getURL('lib/socket-sniffer.js');
s.onload = function() {
    this.remove();
};

lib/сокет-сниффер.js

(function() {
  var OrigWebSocket = window.WebSocket;
  var callWebSocket = OrigWebSocket.apply.bind(OrigWebSocket);
  var wsAddListener = OrigWebSocket.prototype.addEventListener;
  wsAddListener = wsAddListener.call.bind(wsAddListener);
  window.WebSocket = function WebSocket(url, protocols) {
    var ws;
    if (!(this instanceof WebSocket)) {
      // Called without 'new' (browsers will throw an error).
      ws = callWebSocket(this, arguments);
    } else if (arguments.length === 1) {
      ws = new OrigWebSocket(url);
    } else if (arguments.length >= 2) {
      ws = new OrigWebSocket(url, protocols);
    } else { // No arguments (browsers will throw an error)
      ws = new OrigWebSocket();
    }

    wsAddListener(ws, 'message', function(event) {
      console.log("Received:", event);
    });
    return ws;
  }.bind();
  window.WebSocket.prototype = OrigWebSocket.prototype;
  window.WebSocket.prototype.constructor = window.WebSocket;

  var wsSend = OrigWebSocket.prototype.send;
  wsSend = wsSend.apply.bind(wsSend);
  OrigWebSocket.prototype.send = function(data) {
    console.log("Sent:", data);
    return wsSend(this, arguments);
  };
})();

(document.head || document.documentElement).appendChild(s);

Вся заслуга в приведенном выше коде, очевидно, принадлежит постерам, указанным выше. Я скопировал tt здесь только для удобства.

Обновление:

Да, имеет значение, что WebSocket находится внутри iframe! По умолчанию расширения загружаются только в самый верхний фрейм. Чтобы он загружался в iframe, вы должны добавить "all_frames": true к вашему manifest.json:

manifest.json

{
  ...
  "content_scripts": [
    {
      "matches": [
        "<website-url>",    
      ],
      "all_frames": true,      
      "js": ["content/syringe.js"]
    }
  ],
  "web_accessible_resources": ["lib/socket-sniffer.js"]
}

Если вы хотите узнать больше, вот документация для all_frames.

person trexinf14s    schedule 10.07.2020