我有一个产品在 Flash 中播放视频(如果可用),如果 Flash 不可用则回退到 HTML5。
我无法找到一种方法来确定 JavaScript 是否在具有“沙盒”属性的 iframe 中执行,这对我的解决方案来说是必需的,因为沙盒 iframe 会禁用所有插件。沙盒 iframe 可以像这样简单:
<iframe src="http://www.cross-domain.com/" sandbox="allow-scripts">
为了确定是否启用了 Flash,我使用了 swfobject 的检查 navigator.plugins["Shockwave Flash"].description 的方法,即使在沙盒 iframe 中也会设置该方法。我可以加载 swf 对象,但它不播放。
要重现此问题,请访问 http://jsfiddle.net/max_winderbaum/9cqkjo45/ ,打开你的 chrome inspector 并点击“运行”。跨域站点上的脚本将在沙盒 iframe 的上下文中暂停。
根据 W3 规范 http://dev.w3.org/html5/spec-preview/browsers.html#sandboxing-flag-set ,在 JavaScript 可以访问的文档上应该有一个“事件沙盒标志集”(至少我是这样阅读规范的)。 iframe 的文档上似乎没有设置任何标志。
对于如何检测 JavaScript 是否在沙盒 iframe 中执行,有没有人有任何想法/解决方案?
最佳答案
我会考虑不同类型的 iframe(选择第一种适用的情况):
带有 sandboxed scripts browsing context flag 的 iframe
也就是说,带有
sandbox
的 iframe不包含allow-scripts
的属性关键字。这面旗帜 blocks script execution .特别是,您不能使用脚本来检查 iframe 是否已沙盒化。
没有 sandboxed origin browsing context flag 的同源 iframe
也就是说,没有
sandbox
的同源 iframe属性,或带有sandbox
的同源 iframe包含allow-same-origin
的属性和allow-scripts
关键字。在这种情况下,您可以使用
frameElement
用于访问框架元素的全局属性(如果未在 iframe 中使用,则返回null
)。一旦您有了对 iframe 的引用,您就可以使用
hasAttribute
或getAttribute
检查它的sandboxed
属性。还有sandboxed
属性,它应该返回一个DOMSettableTokenList
(旧浏览器可能会根据旧规范返回一个字符串)。没有 sandboxed origin browsing context flag 的跨源 iframe
即没有
sandbox
的跨源iframe属性,或带有sandbox
的跨源 iframe包含allow-same-origin
的属性和allow-scripts
关键字。在这种情况下,使用
frameElement
被阻止:- According to W3C , 它应该抛出
SecurityError
异常(exception)。这是由 Chrome 实现的。 - According to WHATWG ,它应该返回
null
。这是由 Firefox 实现的。
allow-same-origin
没有多大用处,请考虑假设 iframe 未被沙盒化。- According to W3C , 它应该抛出
带有 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';
}
关于javascript - 检测 JavaScript 是否在沙盒 Iframe 中执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29435076/