检测JavaScript是否在Sandboxed iframe中执行?

时间:2015-04-03 15:26:42

标签: javascript html5 iframe

我的产品在Flash中播放视频(如果可用),如果Flash不可用,则会回退到HTML5。

我无法找到一种方法来确定JavaScript是否在具有“sandbox”属性的iframe中执行,这对我的解决方案是必需的,因为沙盒iframe会禁用所有插件。沙盒iframe可以像这样简单:

<iframe src="http://www.cross-domain.com/" sandbox="allow-scripts">

要确定Flash是否已启用,我正在使用swfobject的方法检查navigator.plugins [“Shockwave Flash”]。描述,即使在沙盒iframe中也会设置。我可以加载swf对象,但它不会播放。

要重现此问题,请访问http://jsfiddle.net/max_winderbaum/9cqkjo45/,打开Chrome检查器,然后点击“运行”。跨域网站上的脚本将在沙盒iframe的上下文中暂停。

根据http://dev.w3.org/html5/spec-preview/browsers.html#sandboxing-flag-set的W3规范,在JavaScript可以访问的文档上应该有一个“活动沙盒标志集”(至少我正在阅读规范)。 iframe的文档似乎没有设置任何标记。

有没有人对如何检测JavaScript是否在沙盒iframe中执行有任何想法/解决方案?

2 个答案:

答案 0 :(得分:5)

我会考虑不同种类的iframe(选择适用的第一种情况):

注意:Firefox将数据URI视为同源,因此可以。但是,Chrome将它们视为交叉来源。然后frameElement无法正常工作,document.domain是空字符串,无论iframe是否为沙盒。您可以检查location.protocol是否为'data:'字符串以检测数据URI。

一般,您可以尝试类似

的内容
function isSandboxedIframe() {
  if (window.parent === window) return 'no-iframe';
  try { var f = window.frameElement; } catch(err) { f = null; }
  if(f === null) {
    if(document.domain !== '') return 'unkown'; // Probably 'non-sandboxed'
    if(location.protocol !== 'data:') return 'sandboxed';
    return 'unkown'; // Can be 'sandboxed' on Firefox
  }
  return f.hasAttribute('sandbox') ? 'sandboxed' : 'non-sandboxed';
}

答案 1 :(得分:4)

项目sandblaster可以帮助您检测是否正在运行沙盒。

沙箱检查自身是否先构成框架然后扫描框架元素的属性以检测有关其自身的若干信息。其中包括framedcrossOriginsandboxedsandboxAllowancesunsandboxableresandboxablesandboxable

为了检测本身是否为沙箱,它会检查框架元素是否具有属性sandbox

// On below `frameEl` is the detected frame element
try {
  result.sandboxed = frameEl.hasAttribute("sandbox");
}
catch (sandboxErr) {
  result.sandboxed = null;
  if (typeof errback === "function") {
    errback(sandboxErr);
  }
}

我尝试复制您的问题,并测试此解决方案是否有效,由于安全问题,我不得不将脚本粘贴到窗口中。

<html>
    <head>
    </head>
    <body>

    <script>
        //Paste the contents of the script(https://raw.githubusercontent.com/JamesMGreene/sandblaster/master/dist/sandblaster.js) here

        var result = sandblaster.detect();
        if(result.sandboxed === true) {
            //sandboxed
        }
        debugger;
    </script>
    </body>
</html>

这是一个演示:http://jsfiddle.net/Starx/tzmn4088/,显示了这一点。