Detecting protocol handler with Javascript

439 views Asked by At

Foreword: I am not a Windows/software developer. I am just a Web Dev with Javascript skills, so I know that I may not understand the ins and outs of protocol handlers.

I am part of a team that has created a piece of software that installs a protocol handler. Once a user has installed the software, they could launch it via visiting a link like <a href="myAwesomeApp://params">Start!</a>.

My issue (and I understand it is a very old issue) is I need a way to see if this protocol handler is installed.

  • If it is, run the protocol handler
  • If not, redirect to software installer location

I have found a semi-promising solution that works for FF and Chrome here (old blog post about script here). I'm not sure why this doesn't work for IE, even while the author explicitly created functionality for IE. Here is the code I am currently using (HTML/JS):

<html>
<head>
    <title>Detect Custome Protocol</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.1.min.js"></script>
</head>
<body>
<input id="protocol" value="" placeholder="custom protocol"/>
<button id="launch">Launch</button>
<!-- Mozilla Only -->
<iframe id="hiddenIframe" src="about:blank" style="display:none"></iframe>
<!-- IE Case 1 -->
<a id="hiddenLink" style="display:none;" href="#">custom protocol</a>
<script>

    //Default State
    var isSupported = false;

    //Helper Methods
    function getProtocol(){
        return $('#protocol').val();
    }

    function getUrl(){
        return getProtocol()+"://"+"rajeshsegu.com";
    }

    function result(){
        alert(getProtocol() + " supported => " + isSupported);
    }

    //Handle Click on Launch button
    $('#launch').click(function(){
        if($.browser.mozilla){
            launchMozilla();
        }else if($.browser.chrome){
            launchChrome();
        }else if($.browser.msie){
            launchIE();
        }
    });

    //Handle IE
    function launchIE(){

        var url = getUrl(),
            aLink = $('#hiddenLink')[0];

        isSupported = false;
        aLink.href = url;

        //IE10+
        if(navigator.msLaunchUri){
            navigator.msLaunchUri(url, 
                   function(){ isSupported = true; result(); }, //success
                   function(){ isSupported=false; result();  }  //failure 
            );
            return;
        } else if (navigator.appName=="Microsoft Internet Explorer" && aLink.protocolLong=="Unknown Protocol"){
            //Case 1: protcolLong
            console.log("Case 1");
            isSupported = false;
            result();
            return;
        }

        //Case2: Open New Window, set iframe src, and access the location.href
        console.log("Case 2");
        var myWindow = window.open('','','width=0,height=0');
        myWindow.document.write("<iframe src='"+ url + "'></iframe>");
        setTimeout(function(){
            try{
                myWindow.location.href;
                isSupported = true;
            }catch(e){ 
                //Handle Exception
            }

            if(isSupported){
                myWindow.setTimeout('window.close()', 100);
            }else{
                myWindow.close();
            }
            result();
        }, 100)

    };

    //Handle Firefox
    function launchMozilla(){

        var url = getUrl(),
            iFrame = $('#hiddenIframe')[0];

        isSupported = false;

        //Set iframe.src and handle exception
        try{
            iFrame.contentWindow.location.href = url;
            isSupported = true;
            result();
        }catch(e){
            //FireFox
            if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL"){
                isSupported = false;
                result();
            }
        }
    }

    //Handle Chrome
    function launchChrome(){

        var url = getUrl(),
            protcolEl = $('#protocol')[0];

        isSupported = false;


        protcolEl.focus();
        protcolEl.onblur = function(){
            isSupported = true;
            console.log("Text Field onblur called");
        };

        //will trigger onblur
        location.href = url;
        
        //Note: timeout could vary as per the browser version, have a higher value
        setTimeout(function(){
            protcolEl.onblur = null;
            result()
        }, 500);   

    }
</script>
</body>
</html>

I have created a sample page for troubleshooting purposes. There was a single ' quote missing on line 72, so I have added that. Nothing else has changed.*

My question is two-fold:

  1. Is there a better way to implement this type of protocol handler detection? Is there a way to fix the launchIE() function so it works?
  2. Is there a way to know what handlers I should have access to while using this check? For instance, with my current code, "acrobat" comes up as True in Chrome. In IE10, it comes up as false. I have a general idea of what should be true/false, but I don't know definitively.

I am trying to do this in Javascript, as the requirements of this project are to start the program from the browser (and later return results). If this is not possible in Javascript, I am open to hearing any other solutions.

0

There are 0 answers