JavaScript

New Year, New Slash-to-Search

0

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

image

What’s New?

  • 选项页面有了新UI,如上图。
  • 规则的添加和显示集成到了一起。
  • 去除了规则到处功能,让插件更小巧。

下载:Slash-to-Search

Chrome下的iframe的诡异问题

3

问题

本周五的时候为了方便工作上的操作,想开发一个浏览器插件,可以获取页面里面出现的第一个iframe加载的URL地址,目标是支持Firefox和Chrome,本来是一个非常简单的需求,无非只需下面一行代码就可以搞定:

alert(document.getElementsByTagName('iframe')[0].contentWindow.document.URL);

但是这行代码在Chrome下却栽了一个大跟头。原因是在插件代码中,从iframe中拿出contentWindow是undefined,我很是不解。

原因分析

我的第一个反映是会不会是Chrome的Webkit内核不支持contentWindow,但是当我打开页面源代码的时候却看到:

Screen Shot 2011-08-21 at 上午12.42.19

源代码里面清清楚楚地写着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);
			}
		}
	);
}
Go to Top