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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2872090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:17:10  来源:igfitidea点击:

How to check if a custom protocol supported

javascript

提问by Piotr Pankowski

We are using software that registers its own protocol. We can run application from browser then by link like:

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

customprotocol://do_this.

but is there a way to check is such custom protocol supported by user`s system? If not we would like to ask user to install software first.

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

E.g:

例如:

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

EditI know about protocolLong property but it works only in IE.

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

采纳答案by Andy E

Unfortunately, there's no easy way of achieving this. There's certainly no method of pre-determining whether or not the protocol handler is installed.

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

Internet Explorer, as you mentioned, has the protocolLongproperty but I'm having trouble getting it to return anything other than "Unknown Protocol" for all custom protocol handlers -- if anyone knows how to get IE to return the correct value please let me know so I can update this section. The best solution I've found with IE is to append to the user agent stringor install a browser extension along with your app that exposes a Javascript accessible property.

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

Firefoxis by far the easiest of the major browsers, as it will allow you to try and catch a navigation attempt that fails. The error object returned contains a nameproperty whose value is NS_ERROR_UNKNOWN_PROTOCOL:

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 will pop up with its own alert box:

Firefox 会弹出自己的警告框:

Firefox doesn't know how to open this address, because the protocol (randomprotocolstring) isn't associated with any program.

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

Once you close this box, the catchblock will execute and you have a working fallback.

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

Second is Opera, which allows you to employ the laws of predictability to detect success of a custom protocol link clicked. If a custom protocol click works, the page will remain the same location. If there is no handler installed, Opera will navigate to an error page. This makes it rather easy to detect with an iframe:

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

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

The setTimeouthere is to make sure we check the location afternavigation. It's important to note that if you try and access the page, Opera throws a ReferenceException (cross-domain security error). That doesn't matter, because all we need to know is that the location changed from about:blank, so a try...catchworks just fine.

setTimeout是为了确保我们导航检查位置。需要注意的是,如果您尝试访问该页面,Opera 会抛出一个 ReferenceException(跨域安全错误)。这没关系,因为我们只需要知道位置从 改变了about:blank,所以 atry...catch工作得很好。

Chromeofficially sucks with this regard. If a custom protocol handler fails, it does absolutely zip. If the handler works... you guessed it... it does absolutely zip. No way of differentiating between the two, I'm afraid.

Chrome官方在这方面很糟糕。如果自定义协议处理程序失败,它绝对会压缩。如果处理程序有效......你猜对了......它绝对可以压缩。恐怕没有办法区分这两者。

I haven't tested Safaribut I fear it would be the same as Chrome.

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

You're welcome to try the test code I wrotewhilst investigating this (I had a vested interest in it myself). It's Opera and Firefox cross compatible but currently does nothing in IE and Chrome.

欢迎您尝试在调查时编写测试代码(我自己对它有既得利益)。它与 Opera 和 Firefox 交叉兼容,但目前在 IE 和 Chrome 中没有任何作用。

回答by Gearoid Murphy

Just to chime in with our own experience, we used FireBreath to create a simple cross-platform plugin. Once installed this plugin registers a mime type which can be detected from the browser javascript after a page refresh. Detection of the mime type indicates that the protocol handler is installed.

为了配合我们自己的经验,我们使用 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
    }
}

回答by antmeehan

Internet Explorer 10 on Windows 8 introduced the very useful navigator.msLaunchUrimethod for launching a custom protocol URL and detecting the success or failure. For example:

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 and below support conditional comments as suggested by @mark-kahn.

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

回答by Mark

Here's an off-the-wall answer: Install an unusual font at the time you register your custom protocol. Then use javascript to check whether that font exists, using something like this.

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

Sure it's a hack, but unlike the other answers it would work across browsers and operating systems.

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

回答by Mark Kahn

For Internet Explorer, the best solution I've found is to use Conditionl comments & Version Vector (application must write something to registry while installing protocol, see http://msdn.microsoft.com/en-us/library/ms537512.aspx#Version_Vectors). protocolLong doesn't work for custom protocol.

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

回答by David W. Keith

On mobile you can use an embedded iframe to auto switch between the custom protocol and a known one (web or app store), see https://gist.github.com/2662899

在移动设备上,您可以使用嵌入式 iframe 在自定义协议和已知协议(网络或应用程序商店)之间自动切换,请参阅https://gist.github.com/2662899

回答by Vasiliy Tsiganov

I just want to explain more previous Mark's answer (some people did not understand for example user7892745).

我只是想解释更多以前马克的回答(有些人不明白,例如user7892745)。

1) When you launch you web-page or web-application it checks for an unusual font (something like Chinese Konfuciuz font http://www.fontspace.com/apostrophic-lab/konfuciuz).

1) 当您启动网页或网络应用程序时,它会检查异常字体(类似于中文 Konfuciuz 字体http://www.fontspace.com/apostrophic-lab/konfuciuz)。

Below is the code of sample web-page with function which checks the font (called isFontAvailable):

以下是带有检查字体的函数(称为 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 <[email protected]>
*/
(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) First time when user opens this page, font will not be installed so he will get a message saying "Please run executable to install custom protocol...".

2) 用户第一次打开此页面时,不会安装字体,因此他会收到一条消息“请运行可执行文件以安装自定义协议...”。

3) He will run executable which will install the font. Your exe can just copy the font file (in my case it is KONFUC__.ttf) into C:\Windows directory or using a code like this (example on Delphi):

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

// Adding the font ..

AddFontResource(PChar('XXXFont.TTF'));
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);

4) After that, when user runs web app again, he gets "Custom protocol is available!" message because font was installed this time.

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

Tested on Google Chrome, Internet Explorer and Firefox - working great!

在 Google Chrome、Internet Explorer 和 Firefox 上进行了测试 - 效果很好!