【问题标题】:Test if navigator.getUserMedia requires https without browser user agent sniffing测试 navigator.getUserMedia 是否需要 https 而无需浏览器用户代理嗅探
【发布时间】:2016-10-17 18:13:00
【问题描述】:

如果我不想将用户重定向到 https,我想使用 Javascript 来确定浏览器是否支持通过 http 访问网络摄像头 (navigator.getUserMedia)。但是,如果浏览器支持网络摄像头访问而不需要 https(例如,firefox),我根本不想将用户重定向到 https。我想使用专门的 http 为站点提供服务。我目前的解决方案是改变浏览器的用户代理:

var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;

我目前的解决方案在理论上会失败,因为 Firefox 可能会在未来几年的某个时间修补对网络摄像头访问的 http 支持。

目前我不愿在所有浏览器上推送 https 是有原因的,但我意识到浏览器世界正在朝着有一天需要无处不在的 https 的方向发展。

!!navigator.getUserMedia

无论我是在 http 还是 https 中运行 chrome,这都会返回 true,我想在当前版本的 chrome 而不是 firefox 上运行 http 时产生一个错误的值,我想这样做而不是用户代理的原因嗅探是因为浏览器修补了对 http 上的网络摄像头访问的支持,我希望我的代码能够适应而不需要修补。

简而言之,如何在不查找特定浏览器用户代理的情况下检测支持 http 中视频功能的浏览器?

【问题讨论】:

    标签: javascript google-chrome firefox https getusermedia


    【解决方案1】:

    以下将检测 Chrome 今天的 https 行为,无需提示:

    (在 Chrome 中使用 fiddle,因为 SO sn-ps 中的 getUserMedia 由于某种原因在 Chrome 中不起作用)

    if ('https:' == document.location.protocol) {
      console.log("Page is https.");
    } else {
      navigator.mediaDevices.getUserMedia({video: {width: {min: 2, max: 1}}})
      .then(stream => {
        log("Detection failed!");
        stream.getTracks().forEach(t => t.stop());
      })
      .catch(e => {
        switch (e.name) {
          case "NotSupportedError":
          case "NotAllowedError":
          case "SecurityError":
            console.log("getUserMedia in http is disallowed");
            break;
          case "OverconstrainedError":
          default:
            console.log("getUserMedia in http is allowed");
            break;
        }
      });
    }

    这是可行的,因为 Chrome 今天在 https 中以 "NotSupportedError" 失败 之前 它考虑了约束。我们传递了不可能的约束,因此在允许 http 的情况下,我们会以 "OverconstrainedError" 失败,因此无论哪种方式都不会向用户显示提示。

    你会注意到我有点对冲,因为根据spec,“NotSupportedError”实际上不是一个有效的错误。我认为一旦 Chrome 更新以遵循规范,它应该会以 "SecurityError" 而不是 "NotSupportedError" 失败,但我不确定。有可能它会首先考虑约束,在这种情况下,此测试可能会停止工作。

    【讨论】:

    • 如果这是在 ES5 中就太好了
    • @denodster 用function(foo) { return bar; } 替换foo => bar 应该可以。
    【解决方案2】:

    我想我找到了解决方案,我已经在 safari、firefox 和 chrome 上对此进行了测试:

    if(navigator.mediaDevices){
      navigator.mediaDevices.getUserMedia({video:true}).then(function(){
        //firefox, chrome in https
        alert('success!'); 
      }, function(){
        //chrome in http
        alert('failure!'); 
      });
    } else {
      //safari, ie
      alert('not supported');
    }
    

    但是,这确实会在运行时弹出一个权限气泡,这是不可取的,我想找到一个不会在检测过程中打扰用户的解决方案。

    【讨论】:

      最近更新 更多