8

外部コンテンツを含むiframeを含むページがあります。外部コンテンツの無限ループによってページ全体がクラッシュすることは望ましくありません。これを回避する方法はありますか?

親が子iframeに頻繁にpostMessagesするように設定しようとしましたが、子Iframeが長時間応答しない場合、親はiframe srcを変更しますが、これは機能しないようです。iframeがループを開始すると、親のsetTimeout関数は実行されなくなります。ここで私のコードを参照してください(実行するとタブがクラッシュすることに注意してください。実行する前にコンソールを開いてログを表示してください):

<html>
<head>
</head>
<body>
<script type="text/javascript">
var scr = 'script';
var html = '<html><head><script>\n' +
'  window.addEventListener("message", answer, false);' +
'  function answer() { console.log("answered"); parent.postMessage(\'hi\', \'*\');}' +
'  setTimeout("while(1){console.log(\'in loop\')};", 3000)' +
"</" + scr + "></head><body>IFRAME</body</html>";

var lastAnswer = (new Date()).getTime();
var iframe = document.createElement('iframe');
queryChild();

window.addEventListener("message", receive, false);
function receive() {
  lastAnswer = (new Date()).getTime();
  console.log('got answer');
}

function queryChild() {
  console.log('querying');
  if((new Date()).getTime() - lastAnswer > 5000) {
    console.log('killing');
    iframe.src = '';
  } else if(iframe.contentWindow){
    iframe.contentWindow.postMessage('hi', '*');
  }
  setTimeout(queryChild, 2000);
};

document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();


</script>
</body>
</html>

この問題を解決する方法について何か提案はありますか?

4

4 に答える 4

5

iframeこの種の問題に関する私の経験では、外部コードを(URLとしてまたはsrcdoc属性を介して)フィードする前にアクセスできない限り、ループによってJavaScriptの実行が完全に中断されます。

実装するタイムアウト機能の種類が何であれ、ブラウザがクラッシュを報告するまでiframeコードの実行が100%のリソースを消費するため、呼び出されません。

オプションは次のとおりです。

  • に追加する前にコードを自動的にサニタイズしますiframe。これは、無限にループする方法が無限にあり、すべてをキャッチすることはできないため、実用的ではありません。コードのスキャン中にクラッシュすることなく、無限ループを検出できるスキャナースクリプトを作成する必要があります。
  • Google Cajaなどのサンドボックスソリューションを使用して、コードをサニタイズします。ただし、これにより、大きく構成されていない場合、コードが構造的に変更されます。
  • 仮想環境を作成して監視する機能を備えたアプリケーションの場合、iframeコードを実行し(たとえば、ある種の仮想マシンで)、プロセスがロックアップするかどうかを確認し、その結果を使用して安全に設定できるかどうかを判断できます。コードのURLへのiframe.srcプロパティ。これは、このコードがすぐにロックされないことを保証できる唯一のソリューションである可能性があります(ただし、実行後のある時点で競合状態を発生させる方法は多数あるため、確実に言う方法はありません。ブラウザをロックすることはありません)。

要約:に表示する前にコードを広範囲にテストする方法を見つけられない限りiframe、iframeコードがブラウザータブをロックしないことを保証することはできません。

于 2012-10-08T22:55:59.313 に答える
0

これはブラウザに大きく依存します。一部のブラウザはページ(またはiframe)ごとに1つのスレッドを使用します。この場合、iframeの実行が終了するまでスクリプトを実行できません(無限ループ)。他のいくつかはページ(またはiframe)ごとに1つのスレッドを持っており、おそらくあなたはそれを行うことができます。

私が確信しているのは、エンタープライズブラウザ(IE8など)をサポートすることを期待している場合よりも、サポートできないということです。

于 2012-10-08T21:37:25.177 に答える
0

これ

console.log('killing');
    iframe.src = '';

を殺しませんiframe同一生成元ポリシーに従って、ドメインから外部ドメインを操作することはできません。のを変更するだけsrcではiframe、のナビゲーションはトリガーされませんiframesrc変更されますが、iframeナビゲートされません。

内部からメッセージを受け取ったiframe場合は、ドキュメントツリーからを削除しiframe、ドキュメントツリーに新しいメッセージを挿入して、を使用してiframeを強制終了する必要があります。removeChild

document.body.removeChild(iframe);
document.body.appendChild(newiframe);

私がここで作成したこの簡単なデモンストレーションを見てください:http://jsbin.com/avodeb/1/

于 2012-10-08T21:37:51.587 に答える
0

これを試して:

<script>
 document.getElementById('iframeID').onload= function() { //When the iframe loads quickly
     clearTimeout(killerTimer); // Stop the Killer Timer
 };
 var killerTimer = setTimeout( function() {
     document.getElementById("iframeID").setAttribute("src",""); //Otherwise, kill the iframe
 }, 3000 ); 
</script>
于 2012-10-08T22:33:38.327 に答える