最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript: possible for parent to kill child iframe if it is stuck in an infinite loop? - Stack Overflow

programmeradmin2浏览0评论

I have a page that has an iframe with external content. I don't want infinite loops in the external content to crash my whole page. Is there any way to get around this.

I tried to set something up where the parent postMessages the child iframe every so often and if the child Iframe doesn't respond for too long a time the parent changes the iframes src, but this doesn't seem to work. The parent's setTimeout functions no longer execute once the iframe starts looping. See my code here (note that it will crash your tab if you execute it, open the console before execution to view the logging):

<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>

Any suggestions on how to solve this problem?

I have a page that has an iframe with external content. I don't want infinite loops in the external content to crash my whole page. Is there any way to get around this.

I tried to set something up where the parent postMessages the child iframe every so often and if the child Iframe doesn't respond for too long a time the parent changes the iframes src, but this doesn't seem to work. The parent's setTimeout functions no longer execute once the iframe starts looping. See my code here (note that it will crash your tab if you execute it, open the console before execution to view the logging):

<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>

Any suggestions on how to solve this problem?

Share Improve this question asked Oct 8, 2012 at 21:32 asutherlandasutherland 2,9694 gold badges38 silver badges51 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

My experience with this kind of problem is that unless you can access the external code before feeding it to the iframe (either as an URL or via the srcdoc attribute), the loop will pletely interrupt any JavaScript execution.

Whatever kind of timeout functionality you implement, it will not be called due to the iframe code execution consuming 100% resources until the browser reports a crash.

Your options are:

  • Sanitize the code automatically before adding it to the iframe, which proves impractical since there are infinite ways to loop infinitely, and you will not be able to catch them all. You would have to write a scanner script that could detect infinite loops while not crashing in the course of scanning the code.
  • Use a sandboxing solution like Google Caja to sanitize the code. However, this will change the code structurally if not configured heavily.
  • In case of an application that has capabilites of creating virtual environments and monitoring them, you could execute the iframe code (let's say on a virtual machine of sorts), check if the process locks up and use that oute to determine if you can safely set the iframe.src property to your code's URL. This might be the only solution that can guarantee some sort of guarantee that this code will not lock up immediately (however, there are many ways to have race conditions at some later point of execution, so there will not be a sure way to say it will never lock up the browser).

Summary: Unless you can find a way to test the code extensively before showing it in the iframe, you can not guarantee that the iframe code will not lock up the browser tab.

It depends highly on the browser, some browser uses one thread for each page (or iframe), in this case your script cannot be executed until the iframe execution is over (the infinite loop). Some others have one thread per page (or iframe) and maybe you are able to do it.

What I'm sure is than if you expect to support enterprise browsers (like IE8) you can't.

This

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

Will not kill the iframe. according to same origin policy you can not manipulate external domains from your domain. Just changing the src of an iframe doesn't trigger a navigation in the iframe. src will change, but iframe will not get navigated.

If your get the message from inner iframe you should remove the iframe from your document tree and insert a new one in document tree in order to kill the iframe using removeChild

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

Look at this simple demonstration I've created here: http://jsbin./avodeb/1/

Try this:

<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>
发布评论

评论列表(0)

  1. 暂无评论