转 浏览器自定义协议检测

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
</head>
<body>
    <iframe id="trigger_protocol_ifrm" style="display:none"></iframe>
    <input id="protocolTxt" type="text" value="" />
    <input id="checkBtn" type="button" value="检测是否支持该协议" />
    <script>
    document.getElementById('checkBtn').onclick = function(){
        var url = document.getElementById('protocolTxt').value;
        launchApplication(url, function(){
            alert('success');
        }, function(){
            alert('fail');
        });
    };
    
    var isDone = true;
    var timeout;
    var assistEl = document.getElementById('checkBtn');
    var triggerEl = document.getElementById('trigger_protocol_ifrm');
    
    function done(){
        isDone = true;
        assistEl.onblur = null;
        triggerEl.onerror = null;
        clearTimeout(timeout);
    }
    
    function launchApplication(url, success, fail){
        if(!isDone)return;
        isDone = false;
        
        assistEl.focus();
        assistEl.onblur = function(){
            if(document.activeElement && document.activeElement !== assistEl){
                assistEl.focus();
            } else {
                done();
                success();          
            }
        };
        
        triggerEl.onerror = function(){
            done();
            fail();
        };


        try{
            triggerEl.src = url;
        }catch(e){
            done();
            fail();
            return;
        }


        timeout = setTimeout(function(){
            done();
            fail();
        }, 1800);
    }
    </script>
</body>
</html>

  

function launchApplication(url, success, fail) {
	if('msLaunchUri' in navigator){//如果是windows8,IE10+,可以支持这种方式调起客户端。
		navigator.msLaunchUri(url, success, fail);
		return;
	}
	if (!isDone) return;//如果上次调起客户端没有完成,则直接返回,防止重复调用。
		isDone = false;

		assistEl.focus();
		assistEl.onblur = function () {
		if (document.activeElement && document.activeElement !== assistEl) {
			assistEl.focus(); //防止用户因为随机操作,而误认为是调起了客户端。
		} else {
			done();
			success();//如果焦点元素,快速失去了焦点,说明客户端已经被调起。
		}
	};
	timeout = setTimeout(function () {
		done();
		fail();//如果超过一定时间仍然没有变化,说明没有注册协议
	},1200);
	triggerEl.onerror = function () {
		done();
		fail();//进入错误事件回调函数说明没有注册协议
	};
	try {
		triggerEl.src = url;
	} catch(e) {
		done();
		fail(); //捕获到异常说明没有注册协议
	}
}

  上方法主要假定如果客户端调起,则页面会失去焦点。用这样的方式来“推测”客户端是否被调起。但这种做法并不准确。

有赖于客户端调起的速度,还可能会被一些特殊的操作干扰而导致判断错误。

对于Chrome浏览器,若不能启动指定的应用,请查看如下几点

6.1 自定义协议后的参数不能太短,最好超过三个字符,并且最好不要用一些常用的关键字.

6.2 配置Chrome的阻止的协议列表, 配置文件路径如下,不用的安装路径,还不用的用户,路径稍有不同:

      C:UsersliuAppDataLocalGoogleChromeUser DataLocal State

      打开此文件后,找到如下内容:

"protocol_handler":
{
	"excluded_schemes":
	{
		"afp":true,
		"data":true,
		"disk":true,
		"disks":true,
		"file":true,
		"hcp":true,
		"iview":false,
		"javascript":true,
		"mailto":false,
		"ms-help":true,
		"ms-windows-store":false,
		"myapp":false,
		"news":false,
		"nntp":true,
		"shell":true,
		"snews":false,
		"tencent":false,
		"vbscript":true,
		"view-source":true,

  确保我们自己定义的协议 myapp 后面的值为"false", 即不在被排除的列表中.

原文地址:https://www.cnblogs.com/xiangxiong/p/7640210.html