web-dev-qa-db-fra.com

Comment détecter les gestionnaires de protocole du navigateur?

J'ai créé un gestionnaire de protocole d'URL personnalisé.

http://

mailto://

custom://

J'ai enregistré une application WinForms pour répondre en conséquence. Tout cela fonctionne très bien.

Mais j'aimerais pouvoir gérer avec élégance le cas où l'utilisateur ne dispose pas encore du gestionnaire de protocole d'URL personnalisé.

Pour pouvoir faire cela, je suppose que je dois pouvoir détecter les gestionnaires de protocole enregistrés du navigateur, à partir de JavaScript. Mais j'ai été incapable de trouver un moyen de rechercher l'information. J'espère trouver une solution à ce problème.

Merci pour toutes les idées que vous pourriez être en mesure de partager.

74
Chris Craft

Ce serait un très , très hacky moyen de le faire ... mais cela fonctionnerait-il?

  • Placez le lien comme d'habitude ...
  • Mais y attacher un gestionnaire onclick, qui définit une minuterie et ajoute un gestionnaire onblur pour la fenêtre
  • (en théorie) si le navigateur gère le lien (application X) chargera voler le focus de la fenêtre ...
  • Si l'événement onblur se déclenche, effacez le chronomètre ...
  • Sinon, laissez votre délai expirer dans 3-5 secondes et prévenez l'utilisateur "Hmm, il semblerait que l'application Mega Uber Cool ne soit pas installée ... voudriez-vous l'installer maintenant? (Ok) (Annuler)"

Loin d'être à l'épreuve des balles ... mais cela pourrait aider?

32
scunliffe

Il n'y a pas de très bon moyen de le faire sur plusieurs navigateurs. Dans IE10 + sur Win8 +, une nouvelle API msLaunchUri vous permet de lancer un protocole, comme suit:

navigator.msLaunchUri('skype:123456', 
  function() 
  { 
    alert('success');
  }, 
  function()
  {
    alert('failed');
  } 
); 

Si le protocole n'est pas installé, le rappel d'échec se déclenchera. Sinon, le protocole sera lancé et le rappel de succès sera déclenché.

J'aborde ce sujet un peu plus loin ici: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable- protocoles-oh-my.aspx

17
EricLaw

HTML5 définit Schéma personnalisé et gestionnaires de contenu (à ma connaissance, Firefox est le seul réalisateur jusqu'à présent), mais malheureusement, il n'existe actuellement aucun moyen de vérifier si un gestionnaire existe déjà - il a été proposé , mais il n'y a pas eu de suivi. Cela semble être une fonctionnalité essentielle pour utiliser efficacement les gestionnaires personnalisés et nous, en tant que développeurs, devrions attirer l'attention sur ce problème afin de le mettre en œuvre.

16
Hugh Guiney

Vous pouvez utiliser une iframe intégrée pour basculer automatiquement entre le protocole personnalisé et un protocole connu (Web ou magasin d'applications), voir https://Gist.github.com/2662899

13
David W. Keith

Il ne semble pas exister de moyen simple, via javascript, de détecter la présence d'une application installée ayant enregistré un gestionnaire de protocole.

Dans le modèle iTunes, Apple fournit des URL à leurs serveurs, qui fournissent ensuite des pages exécutant du javascript:

http://ax.iTunes.Apple.com/detection/itmsCheck.js

Donc, le programme d'installation iTunes déploie apparemment des plug-ins pour les principaux navigateurs, dont la présence peut ensuite être détectée.

Si votre plugin est installé, vous pouvez être raisonnablement sûr que la redirection vers l'URL spécifique à votre application aboutira.

13
jtomson

La solution la plus simple est de demander à l'utilisateur la première fois. 

Utiliser un dialogue de confirmation Javascript par exemple:

You need this software to be able to read this link. Did you install it ?

if yes: create a cookie to not ask next time; return false and the link applies
if false: window.location.href = '/downloadpage/'
9
Natim

J'ai créé une bibliothèque générique pour ce problème en partant du principe que le gestionnaire de protocole personnalisé déclenchera une nouvelle fenêtre pour retirer le focus du navigateur.

https://github.com/ismailhabib/custom-protocol-detection

5
habsq

Si vous avez le contrôle du programme que vous essayez d'exécuter (le code), un moyen de voir si l'utilisateur a réussi à exécuter l'application est le suivant:

  1. Avant d'essayer d'ouvrir le protocole personnalisé, envoyez une requête AJAX à un script de serveur qui enregistre l'intention de l'utilisateur dans une base de données (par exemple, enregistrez l'ID utilisateur et ce qu'il souhaite faire).

  2. Essayez d'ouvrir le programme et de transmettre les données d'intention.

  3. Demandez au programme de demander au serveur de supprimer l'entrée de la base de données (en utilisant les données d'intention pour trouver la ligne correcte).

  4. Faites que le javascript interroge le serveur pendant un moment pour voir si l'entrée de la base de données a disparu. Si l'entrée est supprimée, vous saurez que l'utilisateur a réussi à ouvrir l'application, sinon l'entrée restera (vous pourrez la supprimer ultérieurement avec cronjob).

Je n'ai pas essayé cette méthode, juste pensé.

5
quano

J'ai finalement pu obtenir une solution multi-navigateurs (Chrome 32, Firefox 27, IE 11, Safari 6) fonctionnant avec une combinaison de this et d'une extension Safari extrêmement simple. Une grande partie de cette solution a été mentionnée d'une manière ou d'une autre dans cette question et cette autre .

Voici le script:

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);  // true
        });

        location.href = url;

        setTimeout(function () {
            elem.off('blur');
            elem.removeAttr("tabindex");

            if (!success) {
                callback(false);  // false
            }
        }, 1000);
    } else if (Browser.name === "Safari") {
        if (myappinstalledflag) {
            location.href = url;
            success = true;
        } else {
            success = false;
        }

        callback(success);
    }
}

L'extension Safari était facile à mettre en œuvre. Il consistait en une seule ligne de script d'injection:

myinject.js:

window.postMessage("myappinstalled", window.location.Origin);

Ensuite, dans la page Web JavaScript, vous devez d’abord enregistrer l’événement de message et définir un indicateur si le message est reçu:

window.addEventListener('message', function (msg) {
    if (msg.data === "myappinstalled") {
        myappinstalledflag = true;
    }
}, false);

Cela suppose que l'application associée au protocole personnalisé gérera l'installation de l'extension Safari.

Dans tous les cas, si le rappel retourne false, vous devez informer l'utilisateur que l'application (c'est-à-dire son protocole personnalisé) n'est pas installée.

4
whiskeyspider

Vous pouvez essayer quelque chose comme ça:

function OpenCustomLink(link) {

    var w = window.open(link, 'xyz', 'status=0,toolbar=0,menubar=0,height=0,width=0,top=-10,left=-10');
    if(w == null) {            
        //Work Fine
    }
    else {
        w.close();
        if (confirm('You Need a Custom Program. Do you want to install?')) {
            window.location = 'SetupCustomProtocol.exe'; //URL for installer
        }
    }
}
4
Ariel Guitian

Vous dites que vous devez détecter les gestionnaires de protocole du navigateur. Vraiment?

Et si vous faisiez quelque chose comme ce qui se passe lorsque vous téléchargez un fichier à partir de sourceforge? Disons que vous voulez ouvrir myapp: // quelque chose. Au lieu de simplement créer un lien vers celui-ci, créez un lien vers une autre page HTML accessible via HTTP. Ensuite, sur cette page, dites que vous essayez d'ouvrir l'application pour eux. Si cela ne fonctionne pas, ils doivent installer votre application, ce qu'ils peuvent faire en cliquant sur le lien que vous allez fournir. Si cela fonctionne, alors vous êtes tous ensemble.

3
Brian

Il s'agissait d'une approche recommandée pour IE par le support technique de Microsoft.

http://msdn.Microsoft.com/en-us/library/ms537503%28VS.85%29.aspx#related_topics

"Si vous avez un certain contrôle sur les fichiers binaires en cours d'installation sur la machine d'un utilisateur, la vérification de l'agent utilisateur dans le script semble être une approche pertinente: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Paramètres Internet\5.0\Agent utilisateur\Plate-forme de publication " - Par M $ support

Chaque page Web a accès à la chaîne userAgent et si vous supprimez une valeur de publication personnalisée, sa détection en javascript à l'aide de navigator.userAgent est très simple.

Heureusement, d'autres navigateurs majeurs tels que Firefox et Chrome (sauf Safari :(), ne génèrent pas d'erreurs "page introuvable" lorsqu'un lien avec un protocole personnalisé est cliqué et que le protocole n'est pas installé sur la machine de l'utilisateur. IE est très impitoyable ici, toute astuce pour cliquer dans un cadre invisible ou emprisonner les erreurs javascript ne fonctionne pas et se termine avec une erreur "la page Web ne peut pas être affichée" erreur. L'astuce que nous utilisons dans notre cas est d'informer les utilisateurs avec des images spécifiques à leur navigateur que cliquer sur le lien de protocole personnalisé ouvrira une application. Et s’ils ne trouvent pas l’application qui s’ouvre, ils peuvent cliquer sur une page "installer". En termes de XD, cette méthode est bien meilleure que l’approche ActiveX pour IE. Pour. FF et Chrome, lancez le protocole personnalisé sans aucune détection et laissez l'utilisateur vous dire ce qu'il voit . Pour Safari, :( pas encore de réponse.

1
Megha

J'essaie de faire quelque chose de similaire et je viens de découvrir un truc qui fonctionne avec Firefox. Si vous le combinez avec l'astuce de IE, vous pouvez en avoir un qui fonctionne sur les deux principaux navigateurs (je ne suis pas sûr que cela fonctionne dans Safari et je sais que cela ne fonctionne pas dans Chrome).

if (navigator.appName=="Microsoft Internet Explorer" && document.getElementById("testprotocollink").protocolLong=="Unknown Protocol") {
    alert("No handler registered");
} else {
    try {
        window.location = "custom://stuff";
    } catch(err) {
        if (err.toString().search("NS_ERROR_UNKNOWN_PROTOCOL") != -1) {
            alert("No handler registered");
        }
    }
}

Pour que cela fonctionne, vous devez également avoir un lien caché quelque part sur la page, comme ceci:

<a id="testprotocollink" href="custom://testprotocol" style="display: none;">testprotocollink</a>

C'est un peu hacky mais ça marche. Malheureusement, la version de Firefox affiche toujours l'alerte par défaut qui apparaît lorsque vous essayez de visiter un lien avec un protocole inconnu, mais votre code sera exécuté une fois l'alerte supprimée.

1
user200565

Ce n'est pas une tâche banale; Une option pourrait consister à utiliser un code signé, que vous pourriez utiliser pour accéder au registre et/ou au système de fichiers (veuillez noter qu'il s'agit d'une option très coûteuse ). Il n'existe pas non plus d'API ou de spécification unifiée pour la signature de code. Vous devez donc générer un code spécifique pour chaque navigateur cible. Un cauchemar de soutien.

De plus, je sais que Steam , le système de distribution de contenu de jeu, ne semble pas avoir résolu ce problème non plus.

0
ken

Voici une autre réponse hacky qui nécessiterait une modification (espérons-le légère) de votre application pour qu'elle soit "phone home" au lancement.

  1. L'utilisateur clique sur le lien qui tente de lancer l'application. Un identifiant unique Est placé dans le lien, de sorte qu'il soit transmis à l'application Lors de son lancement. L'application Web montre un spinner ou quelque chose de ce genre.
  2. La page Web commence alors à rechercher un événement 'Application phone home' à partir d'une application avec ce même identifiant unique.
  3. Une fois lancée, votre application publie une publication HTTP sur votre application Web Avec l'identificateur unique, pour indiquer sa présence. 
  4. Soit la page Web voit que l'application a finalement été lancée, soit une page "s'il vous plaît télécharger".
0
sethcall