拦截Omegle的COMETBackend.fireEvent后功能异常的原因排查
问题描述
我正在为视频聊天平台Omegle开发浏览器扩展,需要获取其内部事件。该平台使用Mootools触发事件,创建了继承Mootools Events类的全局对象COMETBackend。我通过注入以下代码拦截COMETBackend对象的fireEvent函数调用:
let proxy = COMETBackend.prototype.fireEvent; COMETBackend.prototype.fireEvent = function (...args) { console.log(...args) return proxy(...args); }
Mootools.js中的Events类代码如下:
var Events = new Class({ $events: {}, addEvent: function(c, b, a) { c = Events.removeOn(c); if (b != $empty) { this.$events[c] = this.$events[c] || []; this.$events[c].include(b); if (a) { b.internal = true; } } return this; }, addEvents: function(a) { for (var b in a) { this.addEvent(b, a[b]); } return this; }, fireEvent: function(c, b, a) { c = Events.removeOn(c); if (!this.$events || !this.$events[c]) { return this; } this.$events[c].each(function(d) { d.create({ bind: this, delay: a, "arguments": b })(); }, this); return this; }, removeEvent: function(b, a) { b = Events.removeOn(b); if (!this.$events[b]) { return this; } if (!a.internal) { this.$events[b].erase(a); } return this; }, removeEvents: function(c) { var d; if ($type(c) == "object") { for (d in c) { this.removeEvent(d, c[d]); } return this; } if (c) { c = Events.removeOn(c); } for (d in this.$events) { if (c && c != d) { continue; } var b = this.$events[d]; for (var a = b.length; a--; a) { this.removeEvent(d, b[a]); } } return this; } });
Omegle.js中的COMETBackend对象代码如下:
var COMETBackend = new Class({ Implements: [Options, Events], initialize: function(a) { this.setOptions(a), this.clientID = null, this.stopped = !1 }....
目前控制台已成功输出事件日志,但Omegle却不再响应这些事件,扩展的拦截操作似乎破坏了平台功能。请问这是什么原因?我的拦截方式是否存在问题?
原因分析与修复方案
你的拦截代码核心问题是:调用原fireEvent函数时没有绑定正确的this上下文。
在Mootools的fireEvent方法里,this指向的是COMETBackend的实例对象,它必须通过this访问实例上的$events属性才能触发对应的事件回调。但你直接调用proxy(...args)时,proxy函数的this会默认指向全局对象(浏览器中为window),而非COMETBackend实例,导致原方法找不到实例的$events集合,自然无法触发事件回调。
修复只需在调用原函数时用apply或call绑定当前实例的this:
let proxy = COMETBackend.prototype.fireEvent; COMETBackend.prototype.fireEvent = function (...args) { console.log(...args); // 用apply绑定this,确保原方法能访问实例属性 return proxy.apply(this, args); // 也可以用call:return proxy.call(this, ...args); };
修改后,原fireEvent方法就能正确获取实例的$events,正常触发事件回调,同时你依然能拦截到事件日志。
内容的提问来源于stack exchange,提问作者GuntherKushner
相关产品推荐
相关产品推荐

