IFRAME 间操作外部对象导致 Opera 崩溃

以下崩溃现象在 Opera 9.6 和 Opera 10.0 beta 版本中均有出现,而在 IE6/7、Firefox2/3、Chrome 中均测试正常。

下面来看这个案例:

在一个页面中嵌入了两个 IFRAME,一个 IFRAME 中显示 FLASH,另一个 IFRAME 中放置监控 FLASH 的代码:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> Demo </title>
<script type=”text/javascript” src=”swfobject.js”></script>
</head>

<body>
<iframe id=”flashw” name=”flashw” src=”flash.html” style=”width:200px;height:200px;”></iframe>
<iframe src=”monitor.html” style=”width:200px;height:200px;”></iframe>
</body>
</html>

flash.html:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> Demo </title>
<script type=”text/javascript” src=”swfobject.js”></script>
</head>
<body>
<div id=”flashzone”></div>
<script type=”text/javascript”>
window.onload=function(){
    var so = new SWFObject(‘flash.swf’, “flash”, “100”, “100”, “9”, “#FF6600”);
    so.addParam(“allowscriptaccess”, “always”);
    so.write(‘flashzone’);
};
</script>
</body>
</html>

monitor.html:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> Demo </title>
</head>
<body>
Status:<input id=”status” type=”text” value=”” />

<script type=”text/javascript”>
var f, t;

window.onload=function(){
        t=setInterval(function(){
            try{
                f=parent.flashw.document.getElementById(‘flash’);
                if(!f)return;
                if(!f.getStatus)return;
                clearInterval(t);
                setInterval(function(){
                    try{
                        document.getElementById(‘status’).value=f.getStatus();
                    }catch(e){}
                }, 10);
            }catch(e){}
        }, 100);

};
</script>
</body>
</html>

在监控器 IFRAME 中,不断检测并显示 Flash 的状态,其中 f.getStatus() 是调用 flash 对象的一个方法。

接着在 Opera 中不断刷新页面,就会发生类似“应用程序故障”的问题,Opera 崩溃退出。

通过和网友的讨论,发现问题可能是由于 Opera 对资源释放判断不够完善,导致在页面 unload 时 setInterval 线程还在引用已释放的对象,也就是引用了一个空指针造成的。

解决这个问题,只需要把 setInterval 交给资源所在的窗体来管理即可。将以上 monitor.html 改成以下代码就可以了:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> Demo </title>
</head>
<body>
Status:<input id=”status” type=”text” value=”” />

<script type=”text/javascript”>
var f, t;

window.onload=function(){
        t=parent.flashw.setInterval(function(){
            try{
                f=parent.flashw.document.getElementById(‘flash’);
                if(!f)return;
                if(!f.getStatus)return;
                clearInterval(t);
                parent.flashw.setInterval(function(){
                    try{
                        document.getElementById(‘status’).value=f.getStatus();
                    }catch(e){}
                }, 10);
            }catch(e){}
        }, 100);

};
</script>
</body>
</html>

注意,这里指的资源是指类似 Flash 之类的外联的资源,对其它 IFRAME 的 DOM 的操作不会发生崩溃。

— EOF —

43 thoughts on “IFRAME 间操作外部对象导致 Opera 崩溃”

  1. Hey,

    朋友,您好,我是 Opera 中国的一名 QA,很高兴能认识您。

    我们通过 Google 注意到了您的这篇文章,并且试图重现您所说的问题。但是,却没在您这篇文章中找到相应的 flash.swf 下载链接,您可否提供一个相应的下载方式,或者直接发到我的邮箱里。

    我们会尽可能地使 Opera 产品更好地服务于中国用户,谢谢您一如即往的支持!

  2. 通过您的协助,Opera 已经修复了这个问题,相信在将来的版本中,这个问题可以保证了

发表评论

电子邮件地址不会被公开。 必填项已用*标注