改变Window.prototype.open的方式是不可检测的/不可逆转的
Changing Window.prototype.open in a way that isn't detectable/reversible
我正在寻找从扩展扩展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+中工作的,你不是那个害怕困难的人;)
- 如何检测是否有溢出
- 如何检测用于WebGL的专用或集成显卡
- 防止Alt+Shift默认操作或检测多种操作系统语言的Javascript
- 如何在使用selectBoxIt JQuery插件时检测选项更改
- 如何使用密码检测网络中的状态连接
- 使用JavaScript检测Flash
- 在不阻止默认行为的情况下检测IE10中的缩放
- 检测个位数整数时正在转换毫秒
- 检测电话窃听,即:<a href="电话:xxx">在UIWebview上
- 动态插入的表:JQuery未检测到最后一行
- 检测页面上某个元素中选择(突出显示)或单击的内容
- jQuery检测浏览器是否支持Zoom
- 检测iframe是否跨域的愚蠢方法
- 检测图像分辨率
- 如何检测第三方广告服务器请求
- 我是否可以检测到javascript正在被卸载(作为调试模式)
- 当没有文本输入聚焦时检测空格键按下
- 正在检测导航到<a name=“;最新主题”></a>
- 如何检测重叠元素下的单击
- 改变Window.prototype.open的方式是不可检测的/不可逆转的