JavaScript - addEventListener 未定义

JavaScript - addEventListener is not defined

我正在创建 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 对象。

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.