JavaScript
New Year, New Slash-to-Search
0大家新年好,赶在2012来临之前,对之前写的一个Chrome小插件Slash-to-Search做了一些小的改进,新年新气象,如果你还在用这个插件,那么来看看吧:

What’s New?
- 选项页面有了新UI,如上图。
- 规则的添加和显示集成到了一起。
- 去除了规则到处功能,让插件更小巧。
Chrome下的iframe的诡异问题
3问题
本周五的时候为了方便工作上的操作,想开发一个浏览器插件,可以获取页面里面出现的第一个iframe加载的URL地址,目标是支持Firefox和Chrome,本来是一个非常简单的需求,无非只需下面一行代码就可以搞定:
alert(document.getElementsByTagName('iframe')[0].contentWindow.document.URL);
但是这行代码在Chrome下却栽了一个大跟头。原因是在插件代码中,从iframe中拿出contentWindow是undefined,我很是不解。
原因分析
我的第一个反映是会不会是Chrome的Webkit内核不支持contentWindow,但是当我打开页面源代码的时候却看到:
源代码里面清清楚楚地写着iframe的contentWindow属性是一个DOMWindow,这和代码中的情况不符合,我去网上Google了一把,有人说是这个是Chrome的BUG,还有人联想到了跨域的问题,总之,这个是Chrome本身的问题,当然,我更相信这个是Chrome的BUG,因为contentWindow在firefox是完全可行的,Chrome支持contentWindow,但是在插件代码中获取出来又是undefined,这种不一致显然是一个BUG。
解决方案
不过,BUG归BUG,问题还是要解决,可悲的是你不能指望Chrome啥时候能够把这个BUG给修复掉,然后你可以很爽快的获取到iframe的contentWindow,现阶段只能通过猥琐手段绕过这个BUG了。
解决这个问题的难处在于对于页面里面的诸多URL加载出来的Document,如何确定出你想要的哪一个。好在Chrome插件的Content Scripts可以设置一个属性all_frames,让Content Scripts可以在页面的所有frame上都执行一遍。这样就可以通过一个放在background.html中的全局计数器,让所有frame的Content Script都去请求这个全局计数器,全局计数器每被请求一次就加一,这样就达到了给所有的frame编号,而frame的Content Script的执行顺序又是按DOM树的顺序来的,所以通过frame的编号很容易区分出你想要的frame,下面是我写的简单的代码,可供参考:
<html>
<head>
<script type="text/javascript">
var counter = 0;
var tabId;
chrome.extension.onRequest.addListener(function(request, sender, return_storage){
if (request.type == 'counter') {
counter++;
}
return_storage(counter);
});
chrome.browserAction.onClicked.addListener(function(tab) {
counter = 0
chrome.tabs.executeScript(null, {"code":"tryAlert();", "allFrames":true});
});
</script>
</head>
<body></body>
</html>
function tryAlert() {
chrome.extension.sendRequest({
"type":"counter"
}, function(response){
if(response == 2) {
alert(document.URL);
}
}
);
}
