【问题标题】:JavaScript - addEventListener is not definedJavaScript - 未定义 addEventListener
【发布时间】:2017-04-20 16:22:29
【问题描述】:

我正在创建一个用于屏蔽广告的 chrome 扩展程序。到目前为止,一切都很好。我的目标是:

  1. 禁用WebSocket
  2. 禁用console.log
  3. 禁用alert
  4. 禁用弹出窗口 (window.open)
  5. 禁用onbeforeunload

当然,它应该只在指定的网站上阻止这些功能。我搜索了如何阻止功能。我发现使用扩展禁用功能的唯一方法是

  1. manifest.json 添加一个内容脚本init.js,它将在document_start 运行(这将防止任何其他代码在我的扩展程序代码之前执行,因此在我禁用它们之前没有人可以窃取和保存对这些函数的引用)
  2. 来自init.js在网页中注入代码,让我的扩展可以访问非沙盒环境
  3. 覆盖列入黑名单的函数

我什么都做了,但问题是如何覆盖函数。我在 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 对象。

【问题讨论】:

  • 为什么要禁用sockets和console.log?
  • @DanielHerr。许多网站以image:dataWebSockets 传输广告。标准adBlock 将永远无法阻止它们。所以,我决定创建自己的扩展。

标签: javascript google-chrome google-chrome-extension ecmascript-6 ecmascript-2016


【解决方案1】:

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

【讨论】:

  • 我不知道你这样做是否会遇到问题,或者你的整体方法是否会奏效(祝你好运!),但这就是你收到关于 addEventListener.. 的错误的原因。 . :-)
  • 再问一个问题。你如何解释修改addEventListener 会抛出ReferenceError,而我可以访问它,但不能修改它?
  • @jumpjet__ 我不知道你为什么会这样。当我在普通的 Chrome 窗口中尝试时,我不会。顺便说一句,我之前没想过,addEventListener 全局的,因为window 继承自EventTarget.prototype。 :-) 但是分配给window 的版本并不能处理到处更新它。
猜你喜欢
  • 2018-12-27
  • 1970-01-01
  • 2017-03-05
  • 2019-11-08
  • 2021-06-22
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
相关资源
最近更新 更多