一尘不染

如何检查是否支持自定义协议

javascript

我们正在使用注册自己的协议的软件。我们可以从浏览器运行应用程序,然后通过如下链接:

customprotocol://do_this.

但是有没有办法检查用户系统是否支持这种自定义协议?如果不是,我们想请用户先安装软件。

例如:

if (canHandle ('customprotocol')) {
     // run software
}
else {
    // ask to install
}

编辑 我知道关于protocolLong属性,但是它仅在IE中有效。


阅读 507

收藏
2020-05-01

共1个答案

一尘不染

不幸的是,没有简单的方法来实现这一目标。当然,没有预先确定是否安装协议处理程序的方法。

*正如您所提到的, *Internet Explorer
具有该protocolLong属性,但是我很难让它为所有自定义协议处理程序返回除“未知协议”之外的任何内容-
如果有人知道如何让IE返回正确的值,请告诉我因此我可以更新此部分。我用IE找到的最好的解决方案是将附加到用户代理字符串或安装浏览器扩展以及与您的应用一起公开Java可访问属性的应用程序。

*到目前为止, *Firefox
是主要浏览器中最简单的浏览器,因为它使您可以尝试捕获失败的导航尝试。返回的错误对象包含一个name属性,其值为NS_ERROR_UNKNOWN_PROTOCOL

try {
    iframe.contentWindow.location.href = "randomprotocolstring://test/";
} catch(e) {
    if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL")
        window.location = "/download/";
}

Firefox将弹出并带有其自己的警报框:

Firefox不知道如何打开该地址,因为该协议(随机协议字符串)未与任何程序关联。

关闭此框后,该catch块将执行,并且您将拥有一个有效的备用。

其次是 Opera
,它使您可以利用可预测性定律来检测单击的自定义协议链接是否成功。如果单击自定义协议,则该页面将保持不变。如果没有安装处理程序,Opera将导航到错误页面。这使得使用iframe进行检测非常容易:

   iframe.contentWindow.location = "randomprotocolstring://test/";
   window.setTimeout(function () {
       try {
           alert(ifr.contentWindow.location); 
       } catch (e) { window.location = "/download/"; }
   }, 0);

setTimeout是为了确保我们在导航后检查位置。重要的是要注意,如果您尝试访问该页面,Opera会引发ReferenceException(跨域安全性错误)。没关系,因为我们所需要知道的是位置从更改为about:blank,因此try...catch工作正常。

Chrome 在这方面很烂。如果自定义协议处理程序失败,则绝对压缩。如果处理程序有效…您猜对了…它确实可以压缩。恐怕无法区分两者。

我尚未测试过 Safari, 但我担心它会与Chrome相同。

2020-05-01