2

I've successfully created and registered a custom protocol handler in my web application and it's working fine in all browsers. There's the initial warning dialog about launching an external application which is fine.

However when the app is deployed and the site is running under SSL, the custom protocol links no longer work in Chrome. I see the following message appears in the Developer Tools console:

[blocked] The page at https://my.site.com/path/to/page ran insecure content from iwd:-action=myaction

The same links work fine in Internet Explorer and Firefox.

Any ideas as to how to make this work? My external application by the way is a console application that's installed on the client.

edit: One extra important piece of information is that the link specifies a target which is a hidden iframe on the same page.

4 Answers 4

2

The solution was to not specify a target frame for Chrome users. It would appear that Chrome is looking at the url being passed from the main page to the embedded iframe and sees that the embedded iframe url is not secure and therefore rejecting it.

I don't think Chrome always behaved this way but with v30+ the solution appears to be to specify and empty target in the link.

Edit - expanded solution

Here's the JavaScript I use to clean the target attributes of the links (for Chrome users only) - Otherwise, the simple solution is to not specify a target attribute in the HTML in the first place.

// Get a list of all the links with external commands
var commandButtons = $("a[target='my_command']");
updateCommandButtonTargetsForChrome();

// Remove target attribute for Chrome only users
function updateCommandButtonTargetsForChrome() {
    var browserInfo = getBrowserInfo();
    if (browserInfo[0] == "Chrome")
        commandButtons.attr("target", "");
}

function getBrowserInfo() {
    var n = navigator.appName, ua = navigator.userAgent, tem;
    var m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
    if (m && (tem = ua.match(/version\/([\.\d]+)/i)) != null) m[2] = tem[1];
    m = m ? [m[1], m[2]] : [n, navigator.appVersion, '-?'];
    return m;
}
6
  • 1
    Glad to see I'm not the only one to run into this very same issue. Doesn't it seem like a bug in Chrome v30 though? Unless there is some way for a custom protocol handler to be designed as "secure" then this breaks anything that uses a custom protocol handler in an iframe of a secure page. Oct 9, 2013 at 14:24
  • Can you elaborate as to how you did this? I am having the same problem. Oct 17, 2013 at 8:08
  • @BrianMcGinity I've edited the answer to provide the javascript code
    – Catch22
    Oct 17, 2013 at 11:34
  • Thank you, looks great. Do you have problems when the SRC of iframe is more than 2000 or so characters? I would like to pass 10k or more to a vbscript. When I pass lots of data, it just dies. Oct 18, 2013 at 1:15
  • I figured out 2083 is the documented max. Wonder if it possible for the executable to call a js function in the html page? Oct 18, 2013 at 2:19
1

Since it looks like all of the answers in this thread are already doing things specific to Chrome, there is a much simpler way to open an application via protocol handler that only will only work for Chrome.

Simply call window.location.assign("customprotocol://");. As far as the user is concerned, this will work exactly the same as the IFRAME approach used to. If the user does not have the protocol handler installed, nothing happens. If the protocol handler is installed, it will open the application.

This will only work in Chrome, as Firefox and IE will redirect the user to a "Could not load" page if they do not have the protocol handler installed on their machine.

3
  • 1
    This is great!!!!! It works well. It fails in an iframe, so this fixes it: var w = (window.parent)?window.parent:window w.location.assign(service + '://' + data) Oct 19, 2013 at 3:00
  • formating is off in my comment above: var w = (window.parent)?window.parent:window; w.location.assign(service + '://' + data) Oct 19, 2013 at 3:09
  • I have referenced this thread at: stackoverflow.com/questions/2330545/… Oct 19, 2013 at 3:11
1

It looks like the problem the whole time is how the url is written.

create the url without the "//":

customproto:xyzabcdef

Instead of:

customproto://xyzabcdef
0

Thank you for finding this, using the same principle, I turned it into a dynamic function call, here's the code:

    <input type='button' value='Test Custom Url' onclick='exec()'>

    <script>
    function submitRequest(buttonId) {
        if (document.getElementById(buttonId) == null || document.getElementById(buttonId) == undefined) return;
        if (document.getElementById(buttonId).dispatchEvent) {
                var e = document.createEvent("MouseEvents");
                e.initEvent("click", true, true);
                document.getElementById(buttonId).dispatchEvent(e);
        } 
        else {
                document.getElementById(buttonId).click();
        }
    }

    function exec(){
        var f = document.getElementById('customUrlLink')
        if (f ) {f.parentNode.removeChild(f);}
        var a = document.createElement('a');
        a.href =  'mycustomproto://arg1';    
        a.innerHTML = "Link"                                    
        a.setAttribute('id',        'customUrlLink');
        a.setAttribute("style", "display:none; "); 
        document.body.appendChild(a); 
        submitRequest("customUrlLink");
    }
    </script>

One thing, this code will not run in an iframe. So the iframe can call this in the parent or it is possible to create the link object in the parent.

Also IE only allows <1000 (i don't know the exact number) characters using this approach.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .