Finalmente pude obtener una solución de navegador cruzado (Chrome 32, Firefox 27, IE 11, Safari 6) que funciona con una combinación de esto y una extensión de Safari súper simple. Gran parte de esta solución se ha mencionado de una forma u otra en esta y otra pregunta .
Aquí está el guión:
function launchCustomProtocol(elem, url, callback) {
var iframe, myWindow, success = false;
if (Browser.name === "Internet Explorer") {
myWindow = window.open('', '', 'width=0,height=0');
myWindow.document.write("<iframe src='" + url + "'></iframe>");
setTimeout(function () {
try {
myWindow.location.href;
success = true;
} catch (ex) {
console.log(ex);
}
if (success) {
myWindow.setTimeout('window.close()', 100);
} else {
myWindow.close();
}
callback(success);
}, 100);
} else if (Browser.name === "Firefox") {
try {
iframe = $("<iframe />");
iframe.css({"display": "none"});
iframe.appendTo("body");
iframe[0].contentWindow.location.href = url;
success = true;
} catch (ex) {
success = false;
}
iframe.remove();
callback(success);
} else if (Browser.name === "Chrome") {
elem.css({"outline": 0});
elem.attr("tabindex", "1");
elem.focus();
elem.blur(function () {
success = true;
callback(true);
});
location.href = url;
setTimeout(function () {
elem.off('blur');
elem.removeAttr("tabindex");
if (!success) {
callback(false);
}
}, 1000);
} else if (Browser.name === "Safari") {
if (myappinstalledflag) {
location.href = url;
success = true;
} else {
success = false;
}
callback(success);
}
}
La extensión de Safari fue fácil de implementar. Consistía en una sola línea de script de inyección:
myinject.js:
window.postMessage("myappinstalled", window.location.origin);
Luego, en la página web JavaScript, primero debe registrar el evento del mensaje y establecer una bandera si se recibe el mensaje:
window.addEventListener('message', function (msg) {
if (msg.data === "myappinstalled") {
myappinstalledflag = true;
}
}, false);
Esto supone que la aplicación que está asociada con el protocolo personalizado administrará la instalación de la extensión de Safari.
En todos los casos, si la devolución de llamada devuelve falso, sabrá informar al usuario que la aplicación (es decir, su protocolo personalizado) no está instalada.