Javascript 如何检查是否支持自定义协议
我们使用的是注册自己协议的软件。我们可以通过以下链接从浏览器运行应用程序:Javascript 如何检查是否支持自定义协议,javascript,Javascript,我们使用的是注册自己协议的软件。我们可以通过以下链接从浏览器运行应用程序: customprotocol://do_this. 但有没有办法检查用户系统是否支持这种定制协议?如果不是,我们想让用户先安装软件 例如: 编辑 我知道protocolLong属性,但它只在IE中起作用。不幸的是,实现这一点并不容易。当然没有预先确定是否安装了协议处理程序的方法 Internet Explorer,如您所述,具有protocolLong属性,但我很难让它为所有自定义协议处理程序返回除“未知协议”以外的任
customprotocol://do_this.
但有没有办法检查用户系统是否支持这种定制协议?如果不是,我们想让用户先安装软件
例如:
编辑
我知道protocolLong属性,但它只在IE中起作用。不幸的是,实现这一点并不容易。当然没有预先确定是否安装了协议处理程序的方法 Internet Explorer,如您所述,具有
protocolLong
属性,但我很难让它为所有自定义协议处理程序返回除“未知协议”以外的任何内容--如果有人知道如何让IE返回正确值,请告诉我,以便我可以更新此部分。我发现IE最好的解决方案是在你的应用程序中安装一个浏览器扩展,它公开了一个Javascript可访问的属性
Firefox是目前为止最简单的主流浏览器,因为它允许您尝试并捕获失败的导航尝试。返回的错误对象包含一个name
属性,其值为NS\u error\u UNKNOWN\u PROTOCOL
:
try {
iframe.contentWindow.location.href = "randomprotocolstring://test/";
} catch(e) {
if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL")
window.location = "/download/";
}
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);
这里的setTimeout
是为了确保我们在导航后检查位置。需要注意的是,如果您尝试访问该页面,Opera会抛出ReferenceException(跨域安全错误)。这无关紧要,因为我们需要知道的是位置已从about:blank
更改,因此try…catch
可以正常工作
Chrome在这方面正式表现不佳。如果一个自定义协议处理程序失败,它绝对不会执行。如果处理器工作。。。你猜对了。。。它绝对是拉链。恐怕无法区分这两者
我还没有测试过Safari,但我担心它会和Chrome一样
欢迎您在调查这件事的同时尝试一下(我自己也有既得利益)。它与Opera和Firefox交叉兼容,但目前在IE和Chrome中没有任何功能。对于Internet Explorer,我找到的最佳解决方案是使用条件注释和版本向量(应用程序在安装协议时必须向注册表写入内容,请参阅)。protocolLong不适用于自定义协议。在移动设备上,您可以使用嵌入式iframe在自定义协议和已知协议(web或app store)之间自动切换,请参见为了配合我们自己的体验,我们使用FireSpreat创建了一个简单的跨平台插件。一旦安装了这个插件,就会注册一个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
}
}
Windows 8上的Internet Explorer 10介绍了一种非常有用的方法,用于启动自定义协议URL并检测成功或失败。例如:
if (typeof (navigator.msLaunchUri) == typeof (Function)) {
navigator.msLaunchUri(witchUrl,
function () { /* Success */ },
function () { /* Failure */ showError(); });
return;
}
Windows 7/IE 9及以下版本支持@mark kahn建议的条件注释。这里有一个现成的答案:在注册自定义协议时安装一种不寻常的字体。然后使用javascript检查该字体是否存在,并使用一些东西
当然,这是一个黑客攻击,但与其他答案不同,它可以跨浏览器和操作系统工作。我只想解释更多Mark之前的答案(有些人不理解,例如用户7892745) 1) 当您启动网页或web应用程序时,它会检查是否有不寻常的字体(如中文Konfuciuz字体) 下面是带有检查字体功能的示例网页的代码(称为isFontAvailable): 4) 之后,当用户再次运行web应用程序时,他会收到“自定义协议可用!”消息,因为这次安装了字体
在Google Chrome、Internet Explorer和Firefox上进行了测试-效果非常好 对于Firefox,我在谷歌上搜索的大部分文章,包括Andy E在这里的答案,以及本文的要点或用法 但是自从Firefox64之后,它就停止了工作,例如这里也证实了这一点 所以FF 64+我发现我可以使用Chrome的方法,
blurHandler
或者使用那里的帖子
对于Chrome 86+它也无法工作,请查看我的答案以了解详细信息
顺便说一句,我发现大多数答案/文章在某些情况下已经过时。您可能想了解Thx,已经尝试了其中描述的大多数方法。在所有流行浏览器中,如果没有警报或其他问题,似乎没有很好的方法来实现这一点。对于Chrome,可能可以在安装过程中注册MIME时间,并使用
window.navigator.mimeTypes[i]
进行检查。我找不到一个简单的方法来做它。+1,这是IE 9和更低版本的一个很好的解决方法,马克。不幸的是,IE 10不再支持条件注释,但可能它们修复了protocolLong
问题。+1―虽然不是一种“隐藏”的检测方法(IE将要求用户允许运行ActiveXObject),但这仍然是一种聪明的方法。特别是对于没有其他解决办法的Chrome,浏览器插件可能是一些人的唯一选择。FireBreath是解决这一问题的一个非常好的方法,而且是一种真正的解决方法
if (typeof (navigator.msLaunchUri) == typeof (Function)) {
navigator.msLaunchUri(witchUrl,
function () { /* Success */ },
function () { /* Failure */ showError(); });
return;
}
<!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>
// Adding the font ..
AddFontResource(PChar('XXXFont.TTF'));
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
iframe.contentWindow.location.href = uri
try {
iframe.contentWindow.location.href = uri;
setTimeout(function () {
try {
if (iframe.contentWindow.location.protocol === "about:") {
successCb();
} else {
failCb();
}
} catch (e) {
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL" ||
e.name === "NS_ERROR_FAILURE" || e.name === "SecurityError") {
failCb();
}
}
}, 500);
} catch (e) {
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL" || e.name === "NS_ERROR_FAILURE"
|| e.name === "SecurityError") {
failCb();
}
}