扩展如何监听WebSocket?(如果WebSocket在iframe中呢?)



我正在编写一个Firefox扩展,它需要监听浏览器和服务器之间的通信。对于HTTP通信,我在后台脚本中使用webRequest库。但是根据Mozilla的错误报告,我不能使用webRequest来拦截WebSocket消息。我的扩展如何监听WebSocket通信?

更新:

我已经注入了我的WebSocket包装器,但它从未被调用!我试图监听的WebSocket位于iframe内部。这有关系吗?

监听WebSocket通信的唯一方法是将WebSocket包装器注入到站点的代码中,并让它将消息中继给您。你的代码应该看起来像这样:

manifest.json

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

content/syringe.js

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

lib/ssocket-sniffer.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);

上面代码的所有功劳显然都归功于上面链接的海报。为了方便起见,我把它抄在这里了。

更新:

是的,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的文档。

我不知道你是否还需要这个,但我通过编辑trexinf14的答案来实现它。

1,将syring.js添加到您的manifest.json中,"run_at":"document_end";如果您希望在网页完全加载后运行此扩展,请更改";web_accessible_resources";转换为新的清单格式。

"content_scripts": [{
"css": ["styles.css"],
"run_at": "document_end",
"all_frames": true,  
"js": ["lib/jquery-3.6.0.min.js","content/jquerycontent.js","content/syringe.js"],  
"matches": ["https://example.com/*"]
}],

"web_accessible_resources": [{ 
"resources": ["lib/socket-sniffer.js"],
"matches": ["<all_urls>"]
}]

2、注入";s";变量,结果是:

var s = document.createElement('script');
s.src = chrome.runtime.getURL('lib/socket-sniffer.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
  1. 从socket-sniffer.js中删除appendChilds,结果是:

(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);
};
})();
console.log("nothing to show");

最新更新