Safari 12.1中更改了跨域iframe麦克风权限?

时间:2019-04-04 14:52:40

标签: javascript html safari getusermedia

Safari 12.1似乎已停止记住跨域iframe的getUserMedia(在这种情况下为麦克风)权限。

给出两个站点的简化示例:

域A:

<!DOCTYPE html>
<html>
    <head></head>
    <body>

        <button onclick="triggerUserMedia()">Get User Media</button>

        <script>
            function triggerUserMedia(){
                const constraints = { audio: true, video: false };
                navigator.mediaDevices.getUserMedia(constraints)
                .then(function(stream) {
                    console.log('got stream');
                })
                .catch(function(err) {
                    console.log('couldn\'t get the stream');
                });
            }
        </script>
    </body>
</html>

域B:

<!DOCTYPE html>
<html style="height:100%">
    <head></head>
    <body>
        <iframe src="https://domain-a/index.html" allow="microphone"></iframe>
    </body>
</html>

在Safari 1.2.1之前的版本以及当前的Chrome等版本中,如果将其嵌入到域B中,则多次按下按钮会导致一个“允许“域A”使用您的麦克风?”,仅在第一个按下。

但是,现在每次按下按钮都会弹出权限弹出窗口。

有人知道在Safari 12.1中有哪些特别更改是什么导致此行为更改的吗? (这是新的Webkit安全限制吗?)

如何做才能确保仅像以前那样只请求一次许可?

(我们在旨在嵌入不同站点的项目中多次调用getUserMedia,因此对用户体验产生了重大影响)

2 个答案:

答案 0 :(得分:1)

即使对于相同的域iframe,我也遇到相同的问题-仅在iframe内部请求getUserMedia总是会请求权限。

即使在跨域环境中,我也发现了一个丑陋的解决方法:如果您至少一次在“主机”页面上请求权限,它将开始在iframe中运行。它要求您有一些“主机页面”脚本,可以与iframe通信(通过窗口消息,以避免跨域问题),但是它可以工作。

即使使用我的解决方法,另一个奇怪的行为是,enumerateDevices如果先在主机页上然后在iframe内请求权限,则不会返回有效的设备名称。因此,完整的解决方法(如果需要枚举)将具有2个权限提示:

  1. 首先在iframe中问(这将确保枚举有效)
  2. 然后在主页上(这将确保Safari记住权限,并且不会在下一次getUserMedia调用时显示提示)

答案 1 :(得分:0)

我无法回答浏览器供应商在每次请求媒体流时都会使iframe getUserMedia请求再次提示获得许可的情况,但是我们发现解决方案是使用父mediaDevices单例请求流。

function getRootWindow(window) {
    if (window.parent === window) {
        return window;
    }

    return getRootWindow(window.parent);
}

getRootWindow(window).navigator.mediaDevices.getUserMedia().then(...);

我们已经在iOS,FF,Chrome,Safari和Safari上对此进行了测试,并且在授予权限之后,对媒体设备的后续请求也可以正常运行。从iFrames DOM调用此操作会导致它在每次请求时发出提示。

相关问题