我的产品在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中执行有任何想法/解决方案?
答案 0 :(得分:5)
我会考虑不同种类的iframe(选择适用的第一种情况):
具有sandboxed scripts browsing context flag
的iframe也就是说,sandbox
属性的iframe不包含allow-scripts
关键字。
此标志blocks script execution。特别是,您无法使用脚本来检查iframe是否为沙盒。
没有sandboxed origin browsing context flag的同源iframe
即,不具有sandbox
属性的同源iframe,或包含sandbox
和allow-same-origin
关键字的allow-scripts
属性的同源iframe。
在这种情况下,您可以使用frameElement
全局属性来访问frame元素(在iframe中未使用时返回null
)。
在您引用iframe后,您可以使用hasAttribute
或getAttribute
来检查其sandboxed
属性。还有sandboxed
属性,该属性应返回DOMSettableTokenList
(旧浏览器可能会根据旧规范返回字符串)。
没有sandboxed origin browsing context flag 的跨源iframe
即,没有sandbox
属性的跨源iframe,或包含sandbox
和allow-same-origin
关键字的allow-scripts
属性的跨源iframe。
在这种情况下,frameElement
的使用被阻止:
SecurityError
例外。这是由Chrome实现的。null
。这是由Firefox实现的。
然后,在这种情况下,我认为您无法区分iframe是否为沙盒。但是,由于在跨源iframe中使用
allow-same-origin
并不是很有用,因此请考虑假设iframe不是沙箱。
具有sandboxed origin browsing context flag
的iframe也就是说,sandbox
属性的iframe不包含allow-same-origin
关键字但包含allow-scripts
关键字。
与前一种情况一样,frameElement
的使用被阻止。
但是,您可以检测到这种情况,因为document.domain
将是空字符串。
注意: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可以帮助您检测是否正在运行沙盒。
沙箱检查自身是否先构成框架然后扫描框架元素的属性以检测有关其自身的若干信息。其中包括framed
,crossOrigin
,sandboxed
,sandboxAllowances
,unsandboxable
,resandboxable
,sandboxable
。
为了检测本身是否为沙箱,它会检查框架元素是否具有属性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/,显示了这一点。