如何阻止已添加的事件监听器被调用?(浏览器扩展场景)
问题背景
我正在开发浏览器扩展的content script,想要修改页面部分功能,需要阻止特定事件触发。常规方法是注册事件监听器并调用stopImmediatePropagation(),但这要求监听器是第一个注册的,而作为content script,我的监听器没法满足这个条件。
在推进自己那套接近可行的复杂方案前,想先问下有没有更简单的解决办法,有的话下面的内容可以忽略。
尝试的双脚本方案
我想到用两个脚本实现需求:
- 第一个脚本在页面加载前执行,替换
prototype.addEventListener,让它首次被调用时创建firstListener函数并作为目标事件类型的首个监听器添加,之后调用原addEventListener,再恢复该方法为原始版本。代码如下:
const injection = document.createElement("script"); injection.textContent = `HTMLSelectElement.prototype.originalAddEventListener = HTMLSelectElement.prototype.addEventListener; HTMLSelectElement.prototype.addEventListener = function(a, b, c) { this.firstListener = event => { }; this.originalAddEventListener("change", event => this.firstListener(event)); this.originalAddEventListener(a, b, c); this.addEventListener = this.originalAddEventListener; };`; (document.head || document.documentElement).appendChild(injection); injection.remove();
- 第二个是包含核心功能的脚本,在页面加载后正常加载,用来找到目标元素并替换
firstListener方法,示例代码:
document.body.querySelectorAll("select").forEach(element => { element.firstListener = event => event.stopImmediatePropagation(); // 这里也可以写更复杂的处理逻辑 });
遇到的问题
第二个脚本无法覆盖firstListener方法,但在控制台执行完全相同的脚本却能生效,这是为什么?该怎么解决?
问题原因与解决思路
了解到content script和网页存在隔离,content script会获取页面内容的“干净视图”,这就导致脚本在控制台有效但在content script里无效。至少Firefox提供了一些绕过方法:
- 用
element.wrappedJSObject.firstListener可以重新定义函数,但网页没有调用这个新函数的权限,因为它属于content script。 - 使用
exportFunction(firstListenerFunc, element, { defineAs: "firstListener" })就能解决权限问题。
重写后的第一个脚本
基于exportFunction重写了第一个脚本,这样firstListener仅存在于content script中,网页视角下的对象几乎和原始状态一致:
const origAddEventListener = HTMLSelectElement.prototype.addEventListener; exportFunction(tempAddEventListener, HTMLSelectElement.prototype, { defineAs: "addEventListener" }); function tempAddEventListener(type, ev, options) { this.firstListener = event => { }; origAddEventListener.call(this, "change", event => this.firstListener(event)); exportFunction(origAddEventListener, this, { defineAs: "addEventListener" }); this.addEventListener(type, ev, options); }
内容的提问来源于stack exchange,提问作者Torn
相关产品推荐
相关产品推荐

