在射茶包的過程中,發現了一個有趣的瀏覽器行為。

程式碼如下,按下Button會在IFrame元素中開啟目前所在網頁。會寫成這種架構是打算讓一個網頁同時扮種兩種角色,不必為了一個小測試搞出兩個HTML檔案來。實際的測試中,我用if (parent != window)判別網頁是否在IFrame中被開啟,執行不同的功能。這裡只為了突顯瀏覽器的行為特性,我把程式碼簡化到最少。

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<iframe id="f" src=""></iframe><br />
<input type="button" value="showFrame" 
onclick="document.getElementById('f').src=location.href;" />
</body>
</html>

我本來預期按下Button後,IFrame中會出現同一個網頁,結果不然!

使用IE8進行測試,按下Button後,啥事也沒發生,IFrame中空白一片,由網頁屬性發現它仍維持about:blank,也就是src並未被改變。如果把src設定改為http://www.google.com http://www.bing.com(身為MVP,偶爾也要從事一下政令宣導莒光教學咩)則行為正常。看來,問題出在location.href。接著我把location.href改成httq://localhost/lab/recursive.htm,依然無效,但再改成recursive.htm?x=1,則可以順利開啟。

經過推敲,我覺得這是一種安全機制,防止網頁內嵌自己,內嵌那一分又再內嵌了自己,形成無窮迴圈會吃光資源。打個比喻,如果將DV的即時影像輸出到電視上,再用DV去拍電視,畫面就會變成一層包一層,層層相包無窮無盡的電視框。還想像不出來的人,我們請基努李維親自示範一下類似的效果。

就像程式的遞迴呼叫Recursive有相對的防呆,瀏覽器也要設法防止這種內嵌無窮迴圈發生! 好奇心起,用各家瀏覽器做了一下測試,發現有三種結果:

IE、Opera: 完全不允許內嵌自己,iframe.src = location.href 無反應。

Chrome、Safari: 只能呼叫一層,內嵌的那一層便不再允許內嵌自己。

Firefox: 會出現錯誤訊息--uncaught exception: [Exception... "Component returned failure code: 0x8000ffff (NS_ERROR_UNEXPECTED) [nsIDOMHTMLIFrameElement.src]" nsresult: "0x8000ffff (NS_ERROR_UNEXPECTED)" location: "JS frame :: httq://localhost/Lab/Recursive.htm :: onclick :: line 1" data: no]

以上是我的心得報告。


Comments

# by Kuo

哈,好有趣的問題 不過如果是a內嵌b,b內嵌c,c內嵌a 那好像就仍會有此bug

# by Kuo

更正 我剛剛試驗 如果照a>b,b>c,c>a的話,內嵌框只會出現四次 不會一直循環下去

# by steve

呃...突然讓我想到以前做請假系統的循環代理.......

# by roviury

用javascript騙掉笨笨的browser吧 (for ALL browser) <html> <body> <iframe></iframe><br /> <script> function a(){ document.getElementsByTagName('iframe')[0].src='javascript:location.href="'+location.href+'"'; } </script> <button onclick='a()'>showFrame</button> </body> </html>

# by roviury

ps.測試下,safari和chrome都不行 問題是出在它們不接受iframe的location.href更改 上面出現BLOCKED SCRIPT的地方是javascript:

# by roviury

原來chrome和safari都是可以的 不過opera不支持iframe使用javascript url (好像是故意的) <iframe></iframe><br /> <button onclick='a()'>showFrame</button> <script> function a(){ document.getElementsByTagName('iframe')[0].src= 'j'+'avascript:location.href="'+location.href+'";void(0);'; } </script>

Post a comment