Wie erkenne ich die Protokollhandler des Browsers?

81

Ich habe einen benutzerdefinierten URL-Protokollhandler erstellt.

http://

mailto://

custom://

Ich habe eine WinForms-Anwendung registriert, um entsprechend zu antworten. Das alles funktioniert super.

Ich möchte jedoch in der Lage sein, den Fall, in dem der Benutzer den benutzerdefinierten URL-Protokollhandler noch nicht installiert hat, ordnungsgemäß zu behandeln.

Um dies tun zu können, muss ich in der Lage sein, die registrierten Protokollhandler des Browsers zu erkennen, würde ich von JavaScript annehmen. Aber ich konnte keinen Weg finden, um nach Informationen zu suchen. Ich hoffe, eine Lösung für dieses Problem zu finden.

Vielen Dank für alle Ideen, die Sie teilen können.

Chris Craft
quelle
5
Ich denke, dass dies nur in Chrome-Code (dh XPCOM, ActiveX usw.) möglich wäre. Andernfalls handelt es sich um ein Datenschutzproblem ("Wir haben festgestellt, dass Sie Eudora verwenden. Wechseln Sie heute zu FooMail!"). Aber bitte klären Sie, an welchen Browsern / Betriebssystemen Sie interessiert sind.
Matthew Flaschen
1
Guter Punkt, aber ich würde mich freuen zu wissen, dass etwas registriert ist, um mein proprietäres Protokoll acsfs zu verarbeiten: // Windows IE, FireFox und idealerweise Safari
Chris Craft

Antworten:

34

Dies wäre ein sehr , sehr hackiger Weg, dies zu tun ... aber würde das funktionieren?

  • Setzen Sie den Link wie gewohnt ein ...
  • Fügen Sie jedoch einen Onclick-Handler hinzu, der einen Timer einstellt und einen Onblur-Handler für das Fenster hinzufügt
  • (theoretisch) Wenn der Browser den Link verarbeitet (Anwendung X), wird der Fokus aus dem Fenster gestohlen ...
  • Wenn das Onblur-Ereignis ausgelöst wird, löschen Sie den Timer ...
  • Andernfalls können Sie in 3-5 Sekunden Ihre Zeitüberschreitung auslösen ... und den Benutzer benachrichtigen. "Hmm, es sieht so aus, als hätten Sie die Mega Uber Cool-Anwendung nicht installiert. Möchten Sie sie jetzt installieren? (Ok) (Abbrechen)"

Weit davon entfernt, kugelsicher zu sein ... aber es könnte helfen?

scunliffe
quelle
1
: D Es ist eine kluge Idee. Es scheint, als gäbe es einen Weg, weil es ein gemeinsames Bedürfnis zu sein scheint.
Chris Craft
2
In Firefox auf Mac (möglicherweise mehr Browser) verliert das Fenster den Fokus und Unschärfe wird ausgelöst, obwohl die Anwendung mit dem benutzerdefinierten Protokoll nicht gestartet werden kann.
Quano
Dies ist eine anständige Lösung für Chrome, da es keine Fehlerbehandlung für Protokolle gibt. Dies wurde in Verbindung mit der Erkennung anderer Browser hier verwendet: rajeshsegu.com/2012/09/browser-detect-custom-protocols/…
Fillip Peyton
Die Protokollerkennung war in letzter Zeit ein großes Problem. ;) Die obige Methode scheint etwas zu funktionieren ... anhand des Live-Beispiels von Rajesh unter rajeshsegu.com/fun/code/browser/detect.html bekomme ich "true" in Chrome. Aber wenn ich so umgestalte, dass es keine results () -Funktion gibt (die wiederum eine Warnbox verwendet - einen blockierenden Aufruf) und sie nur einen Booleschen Wert zurückgeben lasse, werde ich falsch. Ich spüre irgendwie, dass der Blockierungsalarm auch eine hackige Möglichkeit ist, das Timing irgendwie zu erzwingen ... irgendeinen Einblick, @scunliffe?
Greg Pettit
Diese Methode funktioniert in Chrome, außer in dem Fall, dass der Benutzer ausgewählt hat, sich seine Antwort zu merken, Win8 verwendet und die Anwendung nicht hat. In diesem Fall tritt das Unschärfeereignis auf, obwohl die Anwendung nicht gestartet werden kann
Paul Haggo
18

Es gibt keine großartige browserübergreifende Möglichkeit, dies zu tun. In IE10 + unter Win8 + msLaunchUrikönnen Sie mit einer neuen API ein Protokoll wie folgt starten:

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

Wenn das Protokoll nicht installiert ist, wird der Fehlerrückruf ausgelöst. Andernfalls wird das Protokoll gestartet und der erfolgreiche Rückruf wird ausgelöst.

Ich diskutiere dieses Thema hier etwas weiter: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my .aspx

EricLaw
quelle
ES FUNKTIONIERT NICHT - getestet in Windows 7, IE-Browsern
6
msLaunchUri ist nur Windows 8+.
EricLaw
Die Verbindung war tot.
Qiulang
16

HTML5 definiert benutzerdefinierte Schema- und Inhaltshandler (meines Wissens ist Firefox der einzige Implementierer bis jetzt), aber leider gibt es derzeit keine Möglichkeit zu überprüfen, ob bereits ein Handler vorhanden ist - es wurde vorgeschlagen , aber es gab keine Folgemaßnahmen. Dies scheint eine wichtige Funktion zu sein, um benutzerdefinierte Handler effektiv zu verwenden, und wir als Entwickler sollten auf dieses Problem aufmerksam machen, um es zu implementieren.

Hugh Guiney
quelle
13

Es scheint keine einfache Möglichkeit zu geben, über Javascript das Vorhandensein einer installierten App zu erkennen, die einen Protokollhandler registriert hat.

Im iTunes-Modell stellt Apple seinen Servern URLs zur Verfügung, die dann Seiten bereitstellen, auf denen Javascript ausgeführt wird:

http://ax.itunes.apple.com/detection/itmsCheck.js

Das iTunes-Installationsprogramm stellt also anscheinend Plugins für die wichtigsten Browser bereit, deren Vorhandensein dann erkannt werden kann.

Wenn Ihr Plugin installiert ist, können Sie ziemlich sicher sein, dass die Umleitung zu Ihrer app-spezifischen URL erfolgreich ist.

jtomson
quelle
2
Dies sollte die zuverlässigste Lösung sein. Aber ich meine, dass Sie für den größten Teil des Browsers ein Plugin installieren und erstellen müssen, und das ist etwas schwierig. Ich könnte benutzerfreundlicher sein, um den Benutzer stattdessen auf die Download-Seite umleiten zu können.
Natim
Warum nicht FireBreath wie hier erwähnt verwenden? stackoverflow.com/a/14758085/427793
swdev
10

Die einfachste Lösung besteht darin, den Benutzer zum ersten Mal zu fragen.

Verwenden eines Javascript-Bestätigungsdialogs pro Beispiel:

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/'
Natim
quelle
Cookies können täglich sauber entfernt werden. Gibt es keinen besseren Weg, um ein Flash-basiertes Cookie zu erstellen?
Nun, wenn Cookies entfernt werden, wird der Benutzer einfach erneut aufgefordert.
Natim
5

Wenn Sie die Kontrolle über das Programm haben, das Sie ausführen möchten (den Code), können Sie feststellen, ob der Benutzer die Anwendung erfolgreich ausgeführt hat:

  1. Bevor Sie versuchen, das benutzerdefinierte Protokoll zu öffnen, stellen Sie eine AJAX-Anforderung an ein Serverskript, das die Absicht des Benutzers in einer Datenbank speichert (speichern Sie beispielsweise die Benutzer-ID und die gewünschten Aktionen).

  2. Versuchen Sie, das Programm zu öffnen und die Absichtsdaten weiterzugeben.

  3. Lassen Sie das Programm den Server auffordern, den Datenbankeintrag zu entfernen (verwenden Sie die Absichtsdaten, um die richtige Zeile zu finden).

  4. Lassen Sie das Javascript eine Weile auf dem Server abfragen, um festzustellen, ob der Datenbankeintrag nicht mehr vorhanden ist. Wenn der Eintrag nicht mehr vorhanden ist, wissen Sie, dass der Benutzer die Anwendung erfolgreich geöffnet hat. Andernfalls bleibt der Eintrag erhalten (Sie können ihn später mit cronjob entfernen).

Ich habe diese Methode nicht ausprobiert, sondern nur gedacht.

Quano
quelle
4

Mit einer Kombination aus dieser und einer supereinfachen Safari-Erweiterung konnte ich endlich eine browserübergreifende Lösung (Chrome 32, Firefox 27, IE 11, Safari 6) erhalten . Ein Großteil dieser Lösung wurde auf die eine oder andere Weise in dieser und dieser anderen Frage erwähnt .

Hier ist das Skript:

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

Die Safari-Erweiterung war einfach zu implementieren. Es bestand aus einer einzelnen Zeile des Injektionsskripts:

myinject.js:

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

Dann müssen Sie auf der Webseite JavaScript zuerst das Nachrichtenereignis registrieren und ein Flag setzen, wenn die Nachricht empfangen wird:

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

Dies setzt voraus, dass die Anwendung, die dem benutzerdefinierten Protokoll zugeordnet ist, die Installation der Safari-Erweiterung verwaltet.

Wenn der Rückruf false zurückgibt, müssen Sie den Benutzer in allen Fällen darüber informieren, dass die Anwendung (dh das benutzerdefinierte Protokoll) nicht installiert ist.

Whiskyspider
quelle
Es funktioniert nicht für IE. Wie soll es funktionieren? Was ist die Verbindung zwischen myWindow.location.href;und iframe srcin diesem Fenster definiert? Soll es eine Ausnahme auslösen? Dies gilt unabhängig davon, ob das benutzerdefinierte Protokoll unterstützt wird oder nicht.
Burjua
3

Sie sagen, Sie müssen die Protokollhandler des Browsers erkennen - wirklich?

Was ist, wenn Sie so etwas wie das getan haben, was passiert, wenn Sie eine Datei von sourceforge herunterladen? Angenommen, Sie möchten myapp: // etwas öffnen. Anstatt einfach einen Link zu erstellen, erstellen Sie einen Link zu einer anderen HTML-Seite, auf die über HTTP zugegriffen wird. Sagen Sie dann auf dieser Seite, dass Sie versuchen, die Anwendung für sie zu öffnen. Wenn es nicht funktioniert, müssen sie Ihre Anwendung installieren. Klicken Sie dazu auf den von Ihnen angegebenen Link. Wenn es funktioniert, sind Sie fertig.

Brian
quelle
4
Es ist nicht hilfreich zu behaupten, dass dies nicht nützlich wäre. Es scheint mir offensichtlich, dass die Möglichkeit, einen Start- oder Download-Link bedingt anzuzeigen - oder sogar bedingt zu starten oder herunterzuladen, wenn Sie auf einen Link klicken, eine bessere UX wäre, als dem Benutzer mitzuteilen, dass er zuerst installiert werden muss.
StuartQ
3

Sie können so etwas ausprobieren:

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
        }
    }
}
Ariel Guitian
quelle
Nein, funktioniert nicht in Firefox 27. (Nicht in anderen Browsern getestet)
Blaise
1
FUNKTIONIERT NICHT - getestet in Windows 7, IE, Firefox, Opera, Chrome
1

Ich versuche etwas Ähnliches zu tun und habe gerade einen Trick entdeckt, der mit Firefox funktioniert. Wenn Sie es mit dem Trick für IE kombinieren, können Sie einen haben, der auf beiden Hauptbrowsern funktioniert (ich bin nicht sicher, ob es in Safari funktioniert und ich weiß, dass es in Chrome nicht funktioniert).

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");
        }
    }
}

Damit dies funktioniert, müssen Sie außerdem irgendwo auf der Seite einen versteckten Link haben, wie folgt:

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

Es ist ein bisschen hacky, aber es funktioniert. In der Firefox-Version wird leider immer noch die Standardwarnung angezeigt, die angezeigt wird, wenn Sie versuchen, einen Link mit einem unbekannten Protokoll zu besuchen. Ihr Code wird jedoch ausgeführt, nachdem die Warnung verworfen wurde.

user200565
quelle
1
Ich habe festgestellt, dass ich immer noch die Meldung "Firefox weiß nicht, wie diese Adresse geöffnet werden soll, da das Protokoll (tel) keinem Programm zugeordnet ist." Nachricht vor dem
Fangblock
6
protocolLong gibt nur Ergebnisse für "bekannte" Protokolle zurück (file :, mailto :, gopher :, ftp :, http :, https :, news :) und nicht für andere Anwendungsprotokolle.
EricLaw
1

Dies war ein vom Microsoft-Support empfohlener Ansatz für IE

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

"Wenn Sie die Kontrolle über die auf dem Computer eines Benutzers installierten Binärdateien haben, scheint das Überprüfen der UA im Skript ein relevanter Ansatz zu sein: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ Aktuelle Version \ Interneteinstellungen \ 5.0 \ User Agent \ Post Platform" - Durch M $ Unterstützung

Jede Webseite hat Zugriff auf die Zeichenfolge userAgent. Wenn Sie einen benutzerdefinierten Wert für die Post-Plattform löschen, ist es recht einfach, diesen Wert mithilfe von navigator.userAgent in Javascript zu erkennen.

Glücklicherweise werfen andere gängige Browser wie Firefox und Chrome (mit Ausnahme von Safari :() keine Fehler "Seite nicht gefunden" aus, wenn auf einen Link mit einem benutzerdefinierten Protokoll geklickt wird und das Protokoll nicht auf dem Computer des Benutzers installiert ist. Der IE ist hier sehr unversöhnlich Jeder Trick, in einen unsichtbaren Frame zu klicken oder Javascript-Fehler abzufangen, funktioniert nicht und führt zu einem hässlichen Fehler "Webseite kann nicht angezeigt werden". Der Trick, den wir in unserem Fall verwenden, besteht darin, Benutzer mit browserspezifischen Bildern darüber zu informieren, dass sie auf das benutzerdefinierte Protokoll klicken Der Link öffnet eine Anwendung. Wenn die App nicht geöffnet wird, können sie auf eine "Installations" -Seite klicken. In Bezug auf XD ist dies weitaus besser als der ActiveX-Ansatz für IE. Für FF und Chrome fahren Sie einfach fort und starten Sie das benutzerdefinierte Protokoll ohne Erkennung. Lassen Sie sich vom Benutzer mitteilen, was er sieht. Für Safari:(noch keine Antworten

Megha
quelle
Die User-Agent-Erweiterung ist ein gängiger, aber problematischer Ansatz. blogs.msdn.com/b/ieinternals/archive/2009/10/08/…
EricLaw
0

Dies ist keine triviale Aufgabe; Eine Option könnte darin bestehen, signierten Code zu verwenden, mit dem Sie auf die Registrierung und / oder das Dateisystem zugreifen können (bitte beachten Sie, dass dies eine sehr teure Option ist). Es gibt auch keine einheitliche API oder Spezifikation für die Codesignatur, sodass Sie für jeden Zielbrowser spezifischen Code generieren müssen. Ein unterstützender Albtraum.

Ich weiß auch, dass Steam , das System zur Bereitstellung von Spielinhalten, dieses Problem anscheinend auch nicht gelöst hat.

Ken
quelle
2
Der signierte Code sollte von einem Zertifikat signiert werden, das zusammen mit der Anwendung installiert wird, die das benutzerdefinierte // verarbeitet. Es ist also kein wirklich teures Anwendungszertifikat erforderlich, das von jemandem wie verisign signiert wurde.
WhyNotHugo
0

Hier ist eine weitere hackige Antwort, die eine (hoffentlich leichte) Änderung Ihrer Anwendung erfordern würde, um beim Start nach Hause zu telefonieren.

  1. Der Benutzer klickt auf den Link, der versucht, die Anwendung zu starten. Der Link enthält eine eindeutige Kennung, die beim Start an die Anwendung übergeben wird. Die Web-App zeigt einen Spinner oder etwas Ähnliches.
  2. Die Webseite sucht dann in einer App mit derselben eindeutigen ID nach einem Ereignis "Anwendungstelefon zu Hause".
  3. Beim Start sendet Ihre Anwendung einen HTTP-Beitrag mit der eindeutigen Kennung an Ihre Webanwendung, um die Anwesenheit anzuzeigen.
  4. Entweder sieht die Webseite, dass die Anwendung irgendwann gestartet wurde, oder sie fährt mit einer Seite zum Herunterladen fort.
Sethcall
quelle