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

Pio*_*ski 56 javascript

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

customprotocol://do_this.
Run Code Online (Sandbox Code Playgroud)

但有没有办法检查用户系统支持的自定义协议?如果不是,我们首先要求用户安装软件.

例如:

if (canHandle ('customprotocol')) {
     // run software
}
else {
    // ask to install
}
Run Code Online (Sandbox Code Playgroud)

编辑 我知道protocolLong属性,但它只适用于IE.

And*_*y E 46

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

正如您所提到的,Internet Explorer具有该protocolLong属性,但是我无法为所有自定义协议处理程序返回除"未知协议"之外的任何内容 - 如果有人知道如何让IE返回正确的值,请告诉我所以我可以更新这一节.我在IE中找到的最佳解决方案是附加到用户代理字符串或安装浏览器扩展以及暴露Javascript可访问属性的应用程序.

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/";
}
Run Code Online (Sandbox Code Playgroud)

Firefox将弹出自己的警告框:

Firefox不知道如何打开此地址,因为协议(randomprotocolstring)与任何程序都没有关联.

关闭此框后,该catch块将执行,并且您有一个工作后备.

其次是Opera,它允许您使用可预测性定律来检测单击的自定义协议链接的成功.如果自定义协议单击有效,则页面将保持相同的位置.如果没有安装处理程序,Opera将导航到错误页面.这样可以很容易地使用iframe进行检测:

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

setTimeout是为了确保我们导航检查位置.重要的是要注意,如果您尝试访问该页面,Opera会抛出ReferenceException(跨域安全性错误).这没关系,因为我们需要知道的是位置改变了about:blank,所以一切try...catch正常.

Chrome在这方面正式糟透了.如果自定义协议处理程序失败,它绝对会拉链.如果处理程序有效...你猜对了......它绝对是拉链的.我害怕,无法区分这两者.

我还没有测试Safari,但我担心它会和Chrome一样.

欢迎您在调查时尝试我编写测试代码(我自己对此感兴趣).它与Opera和Firefox交叉兼容,但目前在IE和Chrome中无效.

  • 由于这个答案写于2010年,我应该向Google员工提及,在更新版本的Firefox中,try/catch方法似乎不再有任何影响.(iframe仍然避免错误页面) (2认同)

Gea*_*phy 11

为了充分利用我们自己的经验,我们使用FireBreath创建一个简单的跨平台插件.安装完成后,此插件会注册一个mime类型,可以在页面刷新后从浏览器javascript中检测到该类型.检测mime类型表示已安装协议处理程序.

if(IE) { //This bastard always needs special treatment
    try {
        var flash = new ActiveXObject("Plugin.Name");
    } catch (e) {
        //not installed
    }
else { //firefox,chrome,opera
    navigator.plugins.refresh(true);
    var mimeTypes = navigator.mimeTypes;
    var mime = navigator.mimeTypes['application/x-plugin-name'];
    if(mime) {
        //installed
    } else {
        //not installed
    }
}
Run Code Online (Sandbox Code Playgroud)


ant*_*han 9

Windows 8上的Internet Explorer 10引入了非常有用的navigator.msLaunchUri方法,用于启动自定义协议URL并检测成功或失败.例如:

        if (typeof (navigator.msLaunchUri) == typeof (Function)) {
            navigator.msLaunchUri(witchUrl,
                function () { /* Success */ },
                function () { /* Failure */ showError(); });

            return;
        }
Run Code Online (Sandbox Code Playgroud)

Windows 7/IE 9及更低版本支持@ mark-kahn建议的条件注释.

  • 我在Windows 7上检查了IE 10和IE11。在这两种情况下,`typeof navigator.msLaunchUri`均返回“未定义”。此外,Microsoft确认尚未将此API添加到Windows 7中:[Windows 7中不存在[记录的API函数'navigator.msLaunchUri']](https://connect.microsoft.com/IE/feedback/details/864863 / documented-api-function-navigator-mslaunchuri-not-present-in-windows-7)(请参阅2014年5月5日下午12:27的评论) (2认同)

Mar*_*ark 6

这是一个现成的答案:在注册自定义协议时安装不寻常的字体。然后使用javascript来检查字体是否存在,例如

当然,这是黑客,但是与其他答案不同,它可以在浏览器和操作系统上运行。