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

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

customprotocol://do_this. 

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

例如:

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

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

不幸的是,实现这一点并不容易。 当然没有预先确定协议处理程序是否安装的方法。

如上所述, Internet Explorer具有protocolLong属性,但是我无法让所有自定义协议处理程序返回“Unknown Protocol”以外的任何内容 – 如果有人知道如何让IE返回正确的值,请让我知道所以我可以更新这一节。 我在IE中find的最好的解决scheme是附加到用户代理string,或者安装一个浏览器扩展和你的应用程序一起暴露一个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/"; } 

Firefox将popup自己的警报框:

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

一旦你closures这个盒子, 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正式吸引了这方面的。 如果自定义协议处理程序失败,它绝对压缩。 如果处理程序工作…你猜对了…它绝对压缩。 没有办法区分两者,恐怕。

我没有testingSafari,但我担心它会和Chrome一样。

欢迎您尝试我编写的testing代码,同时对此进行调查(我自己也有一个既得利益)。 这是Opera和Firefox交叉兼容,但目前在IE和Chrome中什么都不做。

为了和我们自己的经验吻合,我们使用FireBreath创build了一个简单的跨平台插件。 一旦安装这个插件注册一个MIMEtypes,可以在页面刷新后从浏览器javascript中检测到。 MIMEtypes的检测表明协议处理程序已安装。

 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 } } 

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

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

Windows 7 / IE 9及以下版本支持@ mark-kahnbuild议的条件注释。

对于Internet Explorer,我发现的最佳解决scheme是使用Conditionl注释和版本向量(应用程序必须在安装协议时写入registry,请参阅http://msdn.microsoft.com/zh-cn/library/ms537512.aspx #Version_Vectors )。 protocolLong不适用于自定义协议。

在移动设备上,您可以使用embedded式iframe在自定义协议和已知设备(networking或app store)之间自动切换,请参阅https://gist.github.com/2662899

这是一个非常好的答案:在注册自定义协议时安装一个不寻常的字体。 然后使用JavaScript来检查是否存在该字体,使用这样的东西。

当然这是一个黑客攻击,但不同于其他答案,它可以跨浏览器和操作系统。

我只想解释更多以前的Mark的答案(有些人不明白例如user7892745)。

1)当你启动你的网页或网页应用程序,它会检查一个不寻常的字体(如中文Konfuciuz字体http://www.fontspace.com/apostrophic-lab/konfuciuz )。

下面是带有函数的示例网页代码,它检查字体(称为isFontAvailable):

 <!DOCTYPE html> <html> <head> </head> <body> <script> /** * Checks if a font is available to be used on a web page. * * @param {String} fontName The name of the font to check * @return {Boolean} * @license MIT * @copyright Sam Clarke 2013 * @author Sam Clarke <sam@samclarke.com> */ (function (document) { var width; var body = document.body; var container = document.createElement('span'); container.innerHTML = Array(100).join('wi'); container.style.cssText = [ 'position:absolute', 'width:auto', 'font-size:128px', 'left:-99999px' ].join(' !important;'); var getWidth = function (fontFamily) { container.style.fontFamily = fontFamily; body.appendChild(container); width = container.clientWidth; body.removeChild(container); return width; }; // Pre compute the widths of monospace, serif & sans-serif // to improve performance. var monoWidth = getWidth('monospace'); var serifWidth = getWidth('serif'); var sansWidth = getWidth('sans-serif'); window.isFontAvailable = function (font) { return monoWidth !== getWidth(font + ',monospace') || sansWidth !== getWidth(font + ',sans-serif') || serifWidth !== getWidth(font + ',serif'); }; })(document); function isProtocolAvailable() { if (isFontAvailable('Konfuciuz')) { return true; } else { return false; } } function checkProtocolAvail() { if (isProtocolAvailable()) { alert('Custom protocol is available!'); } else { alert('Please run executable to install protocol!'); } } </script> <h3>Check if custom protocol was installed or not</h3> <pre> <input type="button" value="Check if custom protocol was installed!" onclick="checkProtocolAvail()"> </body> </html> 

2)第一次用户打开这个页面时,字体不会被安装,所以他会得到一个消息,说:“请运行可执行文件来安装自定义协议…”。

3)他将运行将安装字体的可执行文件。 您的exe文件可以复制到C:\ Windows目录或使用这样的代码(在Delphi中的例子):复制字体文件(在我的情况下它是KONFUC __。ttf):

 // Adding the font .. AddFontResource(PChar('XXXFont.TTF')); SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0); 

4)之后,当用户再次运行Web应用程序时,他会得到“自定义协议可用! 消息,因为这次是安装字体。

在Google Chrome,Internet Explorer和Firefox上testing – 效果很好!