Jak wykryć programy obsługi protokołów przeglądarki?


82

Stworzyłem niestandardowy program obsługi protokołu URL.

http://

mailto://

custom://

Zarejestrowałem aplikację WinForms, aby odpowiednio odpowiedzieć. To wszystko działa świetnie.

Ale chciałbym móc z wdziękiem obsłużyć przypadek, w którym użytkownik nie ma jeszcze zainstalowanej niestandardowej obsługi protokołu URL.

Aby móc to zrobić, muszę być w stanie wykryć zarejestrowane programy obsługi protokołów przeglądarki, założyłbym z JavaScript. Ale nie udało mi się znaleźć sposobu, aby uzyskać informacje. Mam nadzieję, że znajdę rozwiązanie tego problemu.

Dziękujemy za wszelkie pomysły, którymi mógłbyś się podzielić.


5
Myślę, że byłoby to możliwe tylko w kodzie chrome (tj. XPCOM, ActiveX itp.). W przeciwnym razie byłby to problem dotyczący prywatności („Wykryliśmy, że korzystasz z Eudory. Przełącz się na FooMail już dziś!”). Ale proszę wyjaśnić, jakie przeglądarki / systemy operacyjne Cię interesują.
Matthew Flaschen,

1
Dobra uwaga, ale byłbym szczęśliwy, wiedząc, że coś jest zarejestrowane do obsługi mojego zastrzeżonego protokołu acsfs: // Windows IE, FireFox i idealnie Safari
Chris Craft

Czy rozwiązałeś już ten problem?
jstuardo

Odpowiedzi:


35

Byłby to bardzo , bardzo hakerski sposób na zrobienie tego ... ale czy to zadziała?

  • Umieść link jak zwykle ...
  • Ale dołącz do niego moduł obsługi onclick, który ustawia licznik czasu i dodaje moduł obsługi onblur dla okna
  • (teoretycznie) jeśli przeglądarka obsługuje link (aplikacja X) załaduje kradzież fokusa z okna ...
  • Jeśli zdarzenie onblur zadziała, wyczyść licznik czasu ...
  • W przeciwnym razie w ciągu 3-5 sekund wyzwolisz swój limit czasu ... i powiadom użytkownika „Hmm, wygląda na to, że nie masz zainstalowanej aplikacji Mega Uber Cool… czy chcesz ją teraz zainstalować? (OK) (Anuluj)”

Daleko od kuloodporności ... ale to może pomóc?


1
: D To sprytny pomysł. Wydaje się, że byłby sposób, ponieważ wydaje się, że jest to powszechna potrzeba.
Chris Craft

2
W przeglądarce Firefox na Macu (może w większej liczbie przeglądarek) okno traci ostrość i onblur jest uruchamiany, mimo że aplikacja z niestandardowym protokołem nie uruchamia się.
quano

To przyzwoite rozwiązanie dla Chrome, ponieważ nie ma żadnego rodzaju obsługi błędów dla protokołów. Zostało to użyte w połączeniu z wykrywaniem innych przeglądarek tutaj: rajeshsegu.com/2012/09/browser-detect-custom-protocols/ ...
Fillip Peyton

wykrywanie protokołów było ostatnio dużym bólem głowy. ;) Powyższa metoda wydaje się trochę działać ... używając rzeczywistego przykładu rajesha znajdującego się pod adresem rajeshsegu.com/fun/code/browser/detect.html Otrzymuję „prawda” w Chrome. Ale jeśli dokonam refaktoryzacji tak, aby nie było funkcji results () (która z kolei używa pola ostrzegawczego - wywołanie blokujące) i pozwolę jej po prostu zwrócić wartość logiczną, otrzymuję fałsz. W jakiś sposób wyczuwam, że ostrzeżenie o blokowaniu to także hacky sposób na wymuszenie wyczucia czasu ... jakiś wgląd, @scunliffe?
Greg Pettit

Ta metoda działa w Chrome, z wyjątkiem przypadku, gdy użytkownik wybrał zapamiętanie swojej odpowiedzi, używając Win8 i nie ma aplikacji. W tym przypadku zdarzenie rozmycia ma miejsce, mimo że aplikacja nie może się uruchomić
Paul Haggo

18

Nie ma na to świetnego sposobu na różne przeglądarki. W IE10 + w Win8 + nowy msLaunchUriinterfejs API umożliwia uruchomienie protokołu, na przykład:

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

Jeśli protokół nie jest zainstalowany, wywołanie zwrotne niepowodzenia zostanie uruchomione. W przeciwnym razie protokół zostanie uruchomiony i wywołanie zwrotne o powodzeniu zostanie uruchomione.

Omawiam ten temat nieco dalej tutaj: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my .aspx


NIE DZIAŁA - testowane w przeglądarkach Windows 7, IE

6
msLaunchUri działa tylko w systemie Windows 8+.
EricLaw

Link nie działał.
Qiulang

16

HTML5 definiuje niestandardowy schemat i procedury obsługi treści (o ile wiem, że Firefox jest dotychczas jedynym implementatorem ), ale niestety obecnie nie ma możliwości sprawdzenia, czy moduł już istnieje - został zaproponowany , ale nie było żadnych dalszych działań. Wydaje się, że jest to krytyczna funkcja do efektywnego korzystania z niestandardowych programów obsługi i jako programiści powinniśmy zwrócić uwagę na ten problem, aby go zaimplementować.


13

Wydaje się, że nie ma prostego sposobu za pomocą javascript na wykrycie obecności zainstalowanej aplikacji, która zarejestrowała program obsługi protokołu.

W modelu iTunes Apple dostarcza adresy URL do swoich serwerów, które następnie udostępniają strony, na których jest uruchamiany skrypt javascript:

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

Tak więc instalator iTunes najwyraźniej wdraża wtyczki dla głównych przeglądarek, których obecność można następnie wykryć.

Jeśli Twoja wtyczka jest zainstalowana, możesz być dość pewny, że przekierowanie na adres URL Twojej aplikacji powiedzie się.


2
To powinno być najbardziej niezawodnym rozwiązaniem. Ale mam na myśli, że musisz zainstalować, a także utworzyć wtyczkę dla większości przeglądarek, a to jest trochę trudne. Mógłbym być bardziej przyjazny dla użytkownika, aby zamiast tego przekierować użytkownika na stronę pobierania.
Natim

Dlaczego nie używać FireBreath, jak wspomniano tutaj? stackoverflow.com/a/14758085/427793
swdev

11

Wydaje się, że najłatwiejszym rozwiązaniem jest pytanie użytkownika za pierwszym razem.

Korzystanie z okna dialogowego potwierdzenia Javascript na przykładzie:

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/'

Pliki cookie można usuwać codziennie. Czy nie ma lepszego sposobu na utworzenie pliku cookie opartego na technologii Flash?

Cóż, jeśli plik cookie zostanie usunięty, użytkownik zostanie ponownie zapytany.
Natim

Myślę, że vscode używa tej metody, sprawdź ich witrynę marketplace.visualstudio.com
Qiulang

5

Jeśli masz kontrolę nad programem, który próbujesz uruchomić (kod), jednym ze sposobów sprawdzenia, czy użytkownikowi udało się uruchomić aplikację, jest:

  1. Przed próbą otwarcia niestandardowego protokołu wyślij żądanie AJAX do skryptu serwera, który zapisuje intencje użytkownika w bazie danych (na przykład zapisz identyfikator użytkownika i to, co chciał zrobić).

  2. Spróbuj otworzyć program i przekaż dane intencji.

  3. Poproś program, aby wysłał żądanie do serwera, aby usunąć wpis z bazy danych (używając danych intencji, aby znaleźć właściwy wiersz).

  4. Niech javascript sonduje serwer przez chwilę, aby sprawdzić, czy wpis w bazie danych zniknął. Jeśli wpis zniknie, będziesz wiedział, że użytkownikowi udało się otworzyć aplikację, w przeciwnym razie wpis pozostanie (możesz go później usunąć za pomocą cronjob).

Nie próbowałem tej metody, po prostu o tym pomyślałem.


4

W końcu udało mi się uzyskać rozwiązanie dla różnych przeglądarek (Chrome 32, Firefox 27, IE 11, Safari 6) działające w połączeniu z tym i super prostym rozszerzeniem do Safari. Wiele z tego rozwiązania zostało w ten czy inny sposób wspomnianych w tym i innym pytaniu .

Oto skrypt:

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

Rozszerzenie Safari było łatwe do wdrożenia. Składał się z jednej linii skryptu wtrysku:

myinject.js:

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

Następnie na stronie JavaScript musisz najpierw zarejestrować zdarzenie wiadomości i ustawić flagę, jeśli wiadomość zostanie odebrana:

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

Zakłada się, że aplikacja powiązana z protokołem niestandardowym będzie zarządzać instalacją rozszerzenia Safari.

We wszystkich przypadkach, jeśli wywołanie zwrotne zwróci fałsz, wiesz, aby poinformować użytkownika, że ​​aplikacja (tj. Jej niestandardowy protokół) nie jest zainstalowana.


To nie działa dla IE. Jak to ma działać? jakie jest połączenie między myWindow.location.href;i iframe srczdefiniowane w tym oknie? Czy ma zgłosić wyjątek? Nie ma znaczenia, czy protokół niestandardowy jest obsługiwany, czy nie.
Burjua

3

Mówisz, że musisz wykryć programy obsługi protokołów przeglądarki - czy naprawdę?

Co by było, gdybyś zrobił coś podobnego do tego, co się dzieje, gdy pobierzesz plik z sourceforge? Powiedzmy, że chcesz otworzyć myapp: // coś. Zamiast po prostu tworzyć łącze do niego, utwórz łącze do innej strony HTML dostępnej przez HTTP. Następnie na tej stronie powiedz, że próbujesz otworzyć dla nich aplikację. Jeśli to nie zadziała, muszą zainstalować Twoją aplikację, co może zrobić, klikając link, który podasz. Jeśli to zadziała, wszystko gotowe.


4
Sugerowanie, że nie byłoby to przydatne, nie jest pomocne. Wydaje mi się oczywiste, że możliwość warunkowego wyświetlenia linku do uruchomienia lub pobrania - a nawet warunkowego uruchomienia lub pobrania po kliknięciu linku byłaby lepszym UX niż poinformowanie użytkownika, że ​​musi najpierw zainstalować.
StuartQ

3

Możesz spróbować czegoś takiego:

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

Nie, nie działa w przeglądarce Firefox 27. (Nie testowano w innych przeglądarkach)
Blaise,

1
NIE DZIAŁA - testowano w Windows 7, IE, Firefox, Opera, Chrome

1

Próbuję zrobić coś podobnego i właśnie odkryłem sztuczkę, która działa z Firefoksem. Jeśli połączysz to ze sztuczką dla IE, możesz mieć taką, która działa na obu głównych przeglądarkach (nie jestem pewien, czy działa w Safari i wiem, że nie działa w 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");
        }
    }
}

Aby to zadziałało, musisz również mieć ukryty link gdzieś na stronie, taki jak ten:

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

To trochę hacky, ale działa. Wersja przeglądarki Firefox niestety nadal wyświetla domyślny alert, który pojawia się, gdy próbujesz odwiedzić łącze z nieznanym protokołem, ale uruchomi twój kod po odrzuceniu alertu.


1
Okazało się, że nadal wyświetla się komunikat „Firefox nie wie, jak otworzyć ten adres, ponieważ protokół (tel) nie jest powiązany z żadnym programem”. wiadomość przed blokiem catch
Deebster

6
protocolLong zwraca wyniki tylko dla „znanych” protokołów (plik:, mailto:, gopher:, ftp:, http:, https:, news :), a nie dla innych protokołów aplikacji.
EricLaw

1

Było to zalecane podejście dla IE przez pomoc techniczną Microsoft

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

„Jeśli masz kontrolę nad plikami binarnymi instalowanymi na komputerze użytkownika, sprawdzenie UA w skrypcie wydaje się odpowiednim podejściem: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Internet Settings \ 5.0 \ User Agent \ Post Platform” - Przez wsparcie M $

Każda strona internetowa ma dostęp do ciągu userAgent i jeśli upuścisz niestandardową wartość platformy postów, wykrycie tego w javascript za pomocą navigator.userAgent jest dość proste.

Na szczęście inne główne przeglądarki, takie jak Firefox i Chrome (za wyjątkiem Safari :(), nie wyświetlają błędu „nie znaleziono strony”, gdy kliknięto łącze z niestandardowym protokołem, a protokół nie został zainstalowany na komputerze użytkownika. IE jest tutaj bardzo bezlitosny , jakakolwiek sztuczka polegająca na kliknięciu w niewidoczną ramkę lub pułapkę błędy javascript nie działa i kończy się brzydkim błędem „nie można wyświetlić strony internetowej”. Sztuczka, której używamy w naszym przypadku, polega na poinformowaniu użytkowników za pomocą obrazów specyficznych dla przeglądarki, które klikają niestandardowy protokół link otworzy aplikację. A jeśli nie znajdą otwieranej aplikacji, mogą kliknąć stronę „zainstaluj”. Pod względem XD wygląda to znacznie lepiej niż podejście ActiveX dla IE. W przypadku FF i Chrome, po prostu śmiało i uruchom niestandardowy protokół bez żadnego wykrywania. Pozwól użytkownikowi powiedzieć, co widzi. W przeglądarce Safari:(nie ma jeszcze odpowiedzi


Rozszerzenie User-Agent to powszechne, ale problematyczne podejście. blogs.msdn.com/b/ieinternals/archive/2009/10/08/…
EricLaw

0

Nie jest to proste zadanie; jedną z opcji może być użycie podpisanego kodu, którego można użyć do uzyskania dostępu do rejestru i / lub systemu plików (należy pamiętać, że jest to bardzo kosztowne opcja). Nie ma również ujednoliconego interfejsu API ani specyfikacji do podpisywania kodu, więc będziesz musiał wygenerować określony kod dla każdej przeglądarki docelowej. Koszmar wsparcia.

Wiem też, że Steam , system dostarczania treści do gier, również nie rozwiązał tego problemu.


2
Podpisany kod powinien być podpisany certyfikatem, który jest instalowany wraz z aplikacją obsługującą custom: //, aby nie było potrzeby stosowania naprawdę drogiego certyfikatu aplikacji podpisanego przez kogoś takiego jak verisign.
WhyNotHugo

0

Oto kolejna hackerska odpowiedź, która wymagałaby (miejmy nadzieję, lekkiej) modyfikacji aplikacji, aby po uruchomieniu była „telefon do domu”.

  1. Użytkownik klika link, który próbuje uruchomić aplikację. W odsyłaczu umieszczany jest unikalny identyfikator, który jest przekazywany do aplikacji podczas jej uruchamiania. Aplikacja internetowa pokazuje spinner lub coś w tym rodzaju.
  2. Następnie strona internetowa rozpoczyna sprawdzanie, czy nie występuje zdarzenie „domowa telefonu aplikacji” z aplikacji o tym samym unikalnym identyfikatorze.
  3. Po uruchomieniu aplikacja wysyła wiadomość HTTP do Twojej aplikacji internetowej z unikalnym identyfikatorem, aby wskazać obecność.
  4. Albo strona internetowa zobaczy, że aplikacja została w końcu uruchomiona, albo przejdzie do strony „pobierz”.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.