改变Window.prototype.open的方式是不可检测的/不可逆转的

Changing Window.prototype.open in a way that isn't detectable/reversible

本文关键字:检测 不可逆转 方式 Window prototype open 改变      更新时间:2023-09-26

我正在寻找从扩展扩展Firefox弹出窗口阻止的方法。一种选择是用包装器函数替换网页中的window.open()(或者更确切地说是Window.prototype.open())。一个重要的要求是,该操作不能被网页检测到或还原。例如,如果我只是这样做:

Window.prototype.open = wrapper;

网页可以很容易地恢复更改:

delete Window.prototype.open;

我可以使用Object.defineProperty()来设置高级属性标志:

Object.defineProperty(Window.prototype, "open", {value: wrapper, configurable: false});

网页无法恢复这个变化,但仍然可以检测到:delete Window.prototype.open通常会改变Window.prototype.open的值(似乎是同一函数的不同实例),这里delete根本不会有任何影响。此外,Window.prototype.open = "test";delete Window.prototype.open;将产生不一致的结果(不同的结果取决于是否为属性指定了writable: false标志)。

我还能做些什么来模拟原始属性的行为吗(除了使用二进制XPCOM组件,它自己有太多的问题)?

您可以尝试使用nsIWindowWatcher接口来注册您自己的窗口创建器(nsIWindowCreator)。这样,你就可以控制是否打开一个新窗口,而不影响窗口对象本身(从而保持对网站不可见)。

我不确定是否无法改变window.open()的实现而不被检测到是一个bug。也许它只是不被认为是Object.defineProperty等方法的重要要求。但也许值得提交一个bug,看看其他人对将来将其作为一个选项的看法。毕竟,广告拦截是一个主要用例。

最后我不得不放弃使用JavaScript代理完成这项工作。尽管经过一些努力,我可以为window.open()创建一个行为与原始完全相同的包装器(需要考虑bug 650299),但似乎没有合适的方法来替换原始的window.open()函数。更改后的属性的行为总是与原来的属性不同,太糟糕了。

所以我决定用一种不同的方法来阻止弹出窗口:监听content-document-global-created通知,看看主题(新窗口)以及它的打开器。具有非空打开器的窗口是某种弹出窗口。可以查看url并决定是否应该阻止弹出窗口。要阻塞,可以调用window.stop()(在发送任何网络请求之前停止所有网络活动)和window.close()。后者必须异步地调用(有延迟),因为当窗口的初始化继续进行时,它将导致崩溃。关于这种方法的一些注意事项:

  • 对于在新窗口中打开的弹出窗口,窗口仍然会显示,但会立即消失。这似乎不可避免。
  • 对于网页,它看起来像它的弹出窗口打开,但立即关闭-这不是内置的弹出窗口拦截器如何工作,更像是一个外部的弹出窗口拦截应用程序。
  • 新窗口总是在更改到实际目的地之前先加载about:blank。对于同源弹出窗口,后者不会发送新的content-document-global-created通知,这是不幸的。

总而言之:不完美但可用。它非常简单,远不及JavaScript代理所需的代码量。

Web浏览器故意阻止这种行为,这是为了维护Web的安全性,例如当你使用iFrame时,你不希望iFrame搞砸或入侵你的页面。

但是,而不是操纵窗口对象的属性,为什么不为窗口对象创建一个包装器和覆盖窗口的包装器在本地?

的例子:

// Copy window object to wraper
var wrapper = {};
for(prop in window) {
  wrapper[prop] = window[prop];
}
wrapper.open = function yourNewOpenFunction() {
  /// do your custom code here
}
(function fakeScope(window){
    window.open(); // this is wrapper.open
}(wrapper));

顺便说一下,这只影响fakeScope()函数的主体,不能全局应用。

今天早上我突然想到:你可以使用Object.freeze(Window.prototype); !测试表明,被该大炮保护的方法可以被删除,但它们可以很容易地被检测到


老答:

ES:Harmony proxy怎么样?http://brendaneich.com/2010/11/proxy-inception/

当然,他们是不稳定的,但他们是在Firefox 4+中工作的,你不是那个害怕困难的人;)