在Windows 8+操作系统中使用Chrome浏览器检测自定义协议处理程序

25

我正在尝试使用不同的浏览器检测是否安装并使用了处理自定义协议的应用程序。我查看了本站上的其他问题,例如:如何检测浏览器的协议处理程序?,并查看了像这样的资源,以便在大多数平台上在大多数浏览器中运行。

在您标记此问题为重复之前,请听我说...

我已经使我的函数在除Windows 8+上的Chrome之外的所有浏览器上正常工作。我无法像在Windows 7上那样在Chrome上使用窗口焦点方法,因为它会弹出消息要求我在商店中找到应用程序。

除了扩展之外,是否有任何方法可以在Chrome的Windows 8+上检测自定义协议处理程序?

更新:

仅使用onBlur进行检测仅适用于Windows 7,因为在8+上,如果它找不到要打开您的协议的内容,它会打开“从应用商店查找内容”的对话框,这会使浏览器失去焦点。


Windows 上的 Chrome 很重要,你需要检测哪个协议? - dandavis
1
@dandavis 我同意。这是一种自定义协议...例如 "foo://" - PixelAcorn
@dandavis 它没有 MIME 类型。至于名称,它可以是我想要的任何东西。 - PixelAcorn
你期望它做什么?忽略你的协议吗?请澄清问题和预期的解决方案。 - ProllyGeek
嗨,PixelAcorn,我在Chrome上遇到了同样的问题。你解决了吗?如果是的话,能告诉我你是怎么解决的吗? - yo2011
显示剩余2条评论
2个回答

2

嘿,我认为你的方向是正确的。这绝对不是那么容易的,但是到目前为止Chrome并不是我的问题,更像是Edge和IE。但我的解决方案是假设它们不支持协议,如果任何事情失败或者它们没有正确地响应,就会出现这种情况。

模糊/聚焦是需要检查的内容,但您需要与可见性更改一起检查。HTML5可见性API和这篇文章(关于此)帮助我找到了一个相当可靠的解决方案,除了上述浏览器之外,因为它们在navigator.msLaunchUri函数上有一些问题,并且已经实现了自己的方法,不依赖于模糊/聚焦。但是该函数存在缺陷,并且并非总是正确响应。

您可以在这里找到我的codepen (链接)。希望这可以帮助您,尽管答案有点晚了。这也适用于移动浏览器,但我尚未进行多次测试,只在我的Android 6.0.2上进行了测试。长期来看可能需要一些调整,但我认为它相当可靠。

(function() {
  var noProtocolHash = '#protocolXYnotsupported',
      checkDelay = 800, // apps might start slowly
      isBlurred = false,
      inCheck = false,
      inLauncherCheck = false,

  tabVisible = (function(){ 
      var stateKey, 
          eventKey, 
          keys = {
                  hidden: "visibilitychange",
                  webkitHidden: "webkitvisibilitychange",
                  mozHidden: "mozvisibilitychange",
                  msHidden: "msvisibilitychange"
      };
      for (stateKey in keys) {
          if (stateKey in document) {
              eventKey = keys[stateKey];
              break;
          }
      }
      return function(c) {
          if (c) document.addEventListener(eventKey, c);
          return !document[stateKey];
      }
  })(),

  isMSIE = function(){
    var rv = -1;

    if(navigator.appName == 'Microsoft Internet Explorer'){
      var ua = navigator.userAgent;
      var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
      if(re.exec(ua) != null){
        rv = parseFloat(RegExp.$1);
      }
    }
    else if(navigator.appName == 'Netscape'){
      var ua = navigator.userAgent;
      var re  = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
      if(re.exec(ua) != null){
        rv = parseFloat(RegExp.$1);
      }
    }
    return (rv !== -1)? true: false;
  },

  isEdge = function(){
    return window.navigator.userAgent.indexOf("Edge") > -1;
  },

  checkIfFocusLost = function($el){
    try {
      document.location.href = $el.attr("href");
    } catch (ex) {
        document.location.href = document.location.href + '/' + noProtocolHash;
    }

    setTimeout(checkVisibility, checkDelay);
  },

  checkVisibility = function(){
    if(tabVisible() && !isBlurred){
      handleNoProtocol();
    }
    else {
      handleProtocol();
    }
  },

  handleNoProtocol = function(){
    $('.result').text('has no protocol');

    inLauncherCheck = false;
  },

  handleProtocol = function(){
    $('.result').text('has the protocol');

    inLauncherCheck = false;
  },

  checkHash = function(){
    if(document.location.hash === noProtocolHash){
      handleNoProtocol();
    }
  },

  checkLauncherProtocol = function($el){
    inLauncherCheck = true;

    navigator.msLaunchUri($el.attr("href"), function(){
      handleProtocol();
    }, 
    function(){
      handleNoProtocol();
    });

    setTimeout(function(){
      // fallback when edge is not responding correctly
      if(inLauncherCheck === true){
        handleNoProtocol();
      }
    }, 500);
  },

  checkIfHasProtocol = function($el){
    inCheck = true;

    if(isEdge() || isMSIE()){
      checkLauncherProtocol($el);
    }
    else {
      checkIfFocusLost($el)
    }
  };

  checkHash();
  tabVisible(function(){
    if(tabVisible() && inCheck){
      handleProtocol();
      inCheck = false;
    }    
  });

  window.addEventListener("blur", function(){
    isBlurred = true;   
  });

  window.addEventListener("focus", function(){
    isBlurred = false; 
    inCheck = false;
  });

  window.checkIfHasProtocol = checkIfHasProtocol;
})();

$('.protocol').click(function(e) {
  checkIfHasProtocol($(this));
  e.preventDefault();
});

我的代码已在Win10上测试过:Chrome,Firefox,IE11,Edge + Android:Chrome(6.0.1)。

还有这个GitHub项目https://github.com/ismailhabib/custom-protocol-detection,它采用了类似的方法,可能更加维护,但由于某些原因我无法让他们的解决方案工作,但也许这正是你需要的。


-1

我认为这个链接可能会帮助你解决不同浏览器的问题,但请更好地定义你的问题或者至少添加一些例子来使其更加清晰明了。


3
我看过那样的解决方案。问题在于那个Chrome解决方案只适用于Windows 7。我不太明白我的问题为什么不清楚... - PixelAcorn
嗨,PixelAcorn,我在Chrome上遇到了同样的问题,正在等待您的反馈。 - yo2011

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接