JavaScript - addEventListener 未定义
JavaScript - addEventListener is not defined
我正在创建 chrome 用于拦截广告的扩展程序。到目前为止一切都很好。我的目标是:
- 禁用
WebSocket
- 禁用
console.log
- 禁用
alert
- 禁用弹出窗口(
window.open
)
- 禁用
onbeforeunload
当然,应该只在指定的网站上屏蔽这些功能。我搜索了如何阻止功能。我发现使用扩展禁用功能的唯一方法是
- 在
manifest.json
中添加一个内容脚本 init.js
,它将 运行 在 document_start
(这将阻止任何其他代码在我的扩展代码之前执行,所以没有人可以在我禁用它们之前窃取并保存对这些函数的引用)
- 从
init.js
在网页中注入代码,使我的扩展程序可以访问非沙盒环境
- 覆盖列入黑名单的函数
我什么都做了,但问题是如何覆盖函数。我在 EcmaScript7 规范中发现 无法检测函数是否是代理实例 。因此,我代理了这些功能中的每一个,并且它按预期工作。网站不会注意到我已经覆盖了所有这些功能。
但是,它适用于 addEventListener
以外的所有功能。为了阻止 onbeforeunload
,我应该向它添加一个代理处理程序并跟踪调用以检查侦听器名称是否为 onbeforeunload
。我写了以下脚本:
addEventListener = new Proxy(addEventListener, {
apply: (f, t, args) => {
if(args[0] !== 'onbeforeunload'){
f.apply(t, args);
}
}
});
这应该过滤调用并只允许未设置 onbeforeunload
事件的调用。但是,它会抛出 ReferenceError: addEventListener is not defined。这让我很惊讶。我想这可能是因为 addEventListener
尚未在 document_start
处初始化,但是 console.log(typeof addEventListener) 将 function
记录到安慰。这怎么可能?
我无法解释。但是,我试图将它放在一个函数中,然后 requestAnimationFrame
到那个函数,直到 addEventListener
变得可访问(我也将上面的代码封装在 try...catch
中)。但是,事实证明修改 addEventListener
总是抛出 ReferenceError,而只是访问它 从不抛出错误 .
我也尝试从开发者控制台和 javascript:...
方法访问它,但它表现正常,我可以修改它而不会出现任何错误。
编辑
当然,问题不像 this one,因为我正确地将脚本注入了非沙盒(真实的)页面环境,我可以访问真实的 window
对象。
addEventListener
不是全局的 实际上,它是间接的。它是 EventTarget.prototype
的 属性(至少在 Chrome 中)。 window
在它的原型链中有 EventTarget.prototype
,这使得 addEventListener
是一个全局的。
所以你需要代理它,大致(不检查你的事件名称,只是为了演示):
const save = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = new Proxy(save, {
apply: function(target, thisArg, args) {
console.log("Foo!");
return save.apply(thisArg, args);
}
});
document.body.addEventListener("click", function() {
console.log("Clicked");
});
<p>....</p>
其他说明:
- 活动名称是
beforeunload
,不是onbeforeunload
。
- 您需要重新定义
window.onbeforeunload
属性 以防止对其赋值,可能是通过 Object.defineProperty
.
我正在创建 chrome 用于拦截广告的扩展程序。到目前为止一切都很好。我的目标是:
- 禁用
WebSocket
- 禁用
console.log
- 禁用
alert
- 禁用弹出窗口(
window.open
) - 禁用
onbeforeunload
当然,应该只在指定的网站上屏蔽这些功能。我搜索了如何阻止功能。我发现使用扩展禁用功能的唯一方法是
- 在
manifest.json
中添加一个内容脚本init.js
,它将 运行 在document_start
(这将阻止任何其他代码在我的扩展代码之前执行,所以没有人可以在我禁用它们之前窃取并保存对这些函数的引用) - 从
init.js
在网页中注入代码,使我的扩展程序可以访问非沙盒环境 - 覆盖列入黑名单的函数
我什么都做了,但问题是如何覆盖函数。我在 EcmaScript7 规范中发现 无法检测函数是否是代理实例 。因此,我代理了这些功能中的每一个,并且它按预期工作。网站不会注意到我已经覆盖了所有这些功能。
但是,它适用于 addEventListener
以外的所有功能。为了阻止 onbeforeunload
,我应该向它添加一个代理处理程序并跟踪调用以检查侦听器名称是否为 onbeforeunload
。我写了以下脚本:
addEventListener = new Proxy(addEventListener, {
apply: (f, t, args) => {
if(args[0] !== 'onbeforeunload'){
f.apply(t, args);
}
}
});
这应该过滤调用并只允许未设置 onbeforeunload
事件的调用。但是,它会抛出 ReferenceError: addEventListener is not defined。这让我很惊讶。我想这可能是因为 addEventListener
尚未在 document_start
处初始化,但是 console.log(typeof addEventListener) 将 function
记录到安慰。这怎么可能?
我无法解释。但是,我试图将它放在一个函数中,然后 requestAnimationFrame
到那个函数,直到 addEventListener
变得可访问(我也将上面的代码封装在 try...catch
中)。但是,事实证明修改 addEventListener
总是抛出 ReferenceError,而只是访问它 从不抛出错误 .
我也尝试从开发者控制台和 javascript:...
方法访问它,但它表现正常,我可以修改它而不会出现任何错误。
编辑
当然,问题不像 this one,因为我正确地将脚本注入了非沙盒(真实的)页面环境,我可以访问真实的 window
对象。
实际上,它是间接的。它是 addEventListener
不是全局的EventTarget.prototype
的 属性(至少在 Chrome 中)。 window
在它的原型链中有 EventTarget.prototype
,这使得 addEventListener
是一个全局的。
所以你需要代理它,大致(不检查你的事件名称,只是为了演示):
const save = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = new Proxy(save, {
apply: function(target, thisArg, args) {
console.log("Foo!");
return save.apply(thisArg, args);
}
});
document.body.addEventListener("click", function() {
console.log("Clicked");
});
<p>....</p>
其他说明:
- 活动名称是
beforeunload
,不是onbeforeunload
。 - 您需要重新定义
window.onbeforeunload
属性 以防止对其赋值,可能是通过Object.defineProperty
.