Tarayıcının protokol işleyicileri nasıl tespit edilir?


82

Özel bir URL protokol işleyicisi oluşturdum.

http://

mailto://

custom://

Buna göre yanıt vermek için bir WinForms uygulamasını kaydettim. Bunların hepsi harika çalışıyor.

Ancak, kullanıcının henüz özel URL protokol işleyicisini yüklemediği durumu incelikle ele alabilmek istiyorum.

Bunu yapabilmek için tarayıcının kayıtlı protokol işleyicilerini tespit edebilmem gerekiyor, JavaScript'ten varsayıyorum. Ama bilgiyi sorgulamanın bir yolunu bulamadım. Bu soruna bir çözüm bulmayı umuyorum.

Paylaşabileceğiniz tüm fikirler için teşekkürler.


5
Bunun sadece krom (yani XPCOM, ActiveX vb.) Kodunda mümkün olacağını düşünüyorum. Aksi takdirde, bu bir gizlilik sorunu olur ("Eudora kullandığınızı tespit ettik. Bugün FooMail'e geçin!"). Ama lütfen ilgilendiğiniz tarayıcıları / işletim sistemlerini açıklığa kavuşturun.
Matthew Flaschen

1
İyi bir nokta, ancak tescilli protokolümü işlemek için bir şeyin kaydedildiğini bilmekten mutluluk duyarım acsfs: // Windows IE, FireFox ve ideal olarak Safari
Chris Craft,

Bu sorunu çözdünüz mü zaten?
jstuardo

Yanıtlar:


35

Bu olacağını çok , çok hacky Bunu yapmanın yolu ... ama bu iş olur?

  • Bağlantıyı normal bir şekilde yerleştirin ...
  • Ancak buna bir zamanlayıcı ayarlayan ve pencere için bir bulanıklaştırma işleyicisi ekleyen bir onclick işleyici ekleyin
  • (teorik olarak) tarayıcı bağlantıyı işliyorsa (uygulama X) odağı pencereden çalarak yükleyecektir ...
  • Onblur olayı tetiklenirse, zamanlayıcıyı temizleyin ...
  • Aksi takdirde 3-5 saniye içinde zaman aşımınızın patlamasına izin verin ... ve kullanıcıyı "Hmm, Mega Uber Cool Uygulaması yüklenmemiş gibi görünüyor ... şimdi yüklemek ister misiniz? (Tamam) (İptal)"

Kurşun geçirmez olmaktan uzak ... ama yardımcı olabilir mi?


1
: D Bu akıllıca bir fikir. Ortak bir ihtiyaç gibi göründüğü için bir yolu var gibi görünüyor.
Chris Craft

2
Mac'teki Firefox'ta (belki daha fazla tarayıcı), özel protokole sahip uygulama başlatılamasa bile pencere odağı kaybediyor ve yangınlarda bulanıklık oluşuyor.
quano

Protokoller için herhangi bir hata işleme özelliği olmadığı için bu Chrome için iyi bir çözümdür. Bu, burada diğer tarayıcıların tespit edilmesiyle bağlantılı olarak kullanılmıştır: rajeshsegu.com/2012/09/browser-detect-custom-protocols/…
Fillip Peyton

protokol algılama, son zamanlarda büyük bir baş ağrısı oldu. ;) Yukarıdaki yöntem bir şekilde işe yarıyor gibi görünüyor ... rajeshsegu.com/fun/code/browser/detect.html adresinde bulunan rajesh'in canlı örneğini kullanarak Chrome'da "true" oluyorum. Ancak sonuç () işlevi olmayacak şekilde yeniden düzenleme yaparsam (bu da bir uyarı kutusu kullanır - engelleme çağrısı kullanır) ve yalnızca bir boole döndürmesine izin verirsem, yanlış alıyorum. Bir şekilde engelleme uyarısının da bir şekilde zamanlamayı zorlamanın hilekar bir yolu olduğunu hissediyorum ... herhangi bir fikir, @scunliffe?
Greg Pettit

Bu yöntem, kullanıcının yanıtını hatırlamak için seçtiği, Win8 kullanarak ve uygulamaya sahip olmadığı durumlar dışında Chrome'da çalışır. Bu durumda, uygulama başlatılamasa bile bulanıklık olayı gerçekleşir
Paul Haggo

18

Bunu yapmanın çapraz tarayıcıda harika bir yolu yok. Win8 + üzerindeki IE10 + 'da, yeni bir msLaunchUriAPI, aşağıdaki gibi bir protokol başlatmanıza olanak tanır:

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

Protokol kurulmamışsa, arıza geri araması tetiklenir. Aksi takdirde, protokol başlayacak ve başarılı geri arama etkinleşecektir.

Bu konuyu burada biraz daha tartışıyorum: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my .aspx


ÇALIŞMIYOR - Windows 7, IE tarayıcılarında test edildi

6
msLaunchUri yalnızca Windows 8+ içindir.
EricLaw

Bağlantı kesildi.
Qiulang

16

HTML5, Özel şema ve içerik işleyicileri tanımlar (bildiğim kadarıyla Firefox şimdiye kadarki tek uygulayıcıdır ), ancak maalesef şu anda bir işleyicinin var olup olmadığını kontrol etmenin bir yolu yok - bu önerildi , ancak takip edilmedi. Bu, özel işleyicileri etkili bir şekilde kullanmak için kritik bir özellik gibi görünüyor ve biz geliştiriciler olarak, uygulanması için bu konuya dikkat etmeliyiz.


13

Bir protokol işleyicisini kaydeden yüklü bir uygulamanın varlığını tespit etmenin javascript aracılığıyla basit bir yolu yok gibi görünüyor.

İTunes modelinde, Apple sunucularına url'ler sağlar ve bunlar daha sonra bazı javascript çalıştıran sayfalar sağlar:

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

Dolayısıyla, iTunes yükleyicisi görünüşe göre büyük tarayıcılar için eklentiler kullanıyor ve bu tarayıcıların varlığı daha sonra tespit edilebiliyor.

Eklentiniz kuruluysa, uygulamaya özel url'nize yönlendirmenin başarılı olacağından makul ölçüde emin olabilirsiniz.


2
Bu en güvenilir çözüm olmalı. Ancak, tarayıcının çoğu için bir eklenti kurmanız ve oluşturmanız gerektiği anlamına gelir ve bu biraz zordur. Bunun yerine kullanıcıyı indirme sayfasına yönlendirmek için daha kullanıcı dostu olabilirim.
Natim

Neden FireBreath'u burada belirtildiği gibi kullanmıyorsunuz? stackoverflow.com/a/14758085/427793
swdev

11

En kolay çözüm, kullanıcıya ilk kez sormaktır.

Her örnek için bir Javascript onaylama iletişim kutusu kullanarak:

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

Çerezler her gün temizlenebilir. Flash tabanlı bir çerez yapmanın daha iyi bir yolu yok mu?

Çerez kaldırılırsa, kullanıcıya tekrar sorulacaktır.
Natim

Bence vscode bu yöntemi kullanıyor, sitelerini kontrol edin marketplace.visualstudio.com
Qiulang

5

Çalıştırmaya çalıştığınız programın (kod) kontrolüne sahipseniz, kullanıcının uygulamayı çalıştırmada başarılı olup olmadığını görmenin bir yolu şudur:

  1. Özel protokolü açmaya çalışmadan önce, kullanıcının amacını bir veritabanına kaydeden bir sunucu komut dosyasına bir AJAX isteği yapın (örneğin, kullanıcı kimliğini ve yapmak istediği şeyi kaydedin).

  2. Programı açmayı ve amaç verilerini iletmeyi deneyin.

  3. Programın, veritabanı girişini kaldırması için sunucuya bir istekte bulunmasını sağlayın (doğru satırı bulmak için amaç verilerini kullanarak).

  4. Veritabanı girişinin gidip gitmediğini görmek için javascript'in sunucuda bir süre anket yapmasını sağlayın. Giriş kaybolursa, kullanıcının uygulamayı açmada başarılı olduğunu anlarsınız, aksi takdirde giriş kalır (daha sonra cronjob ile kaldırabilirsiniz).

Bu yöntemi denemedim, sadece düşündüm.


4

Sonunda bunun ve süper basit bir Safari uzantısının birleşimiyle çalışan bir çapraz tarayıcı (Chrome 32, Firefox 27, IE 11, Safari 6) çözümü elde etmeyi başardım . Bu çözümün çoğundan, bu ve bu diğer soruda şu ya da bu şekilde bahsedilmiştir .

İşte senaryo:

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

Safari uzantısının uygulanması kolaydı. Tek satırlık bir enjeksiyon betiğinden oluşuyordu:

myinject.js:

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

Ardından JavaScript web sayfasında, önce mesaj olayını kaydetmeniz ve mesaj alınırsa bir bayrak ayarlamanız gerekir:

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

Bu, özel protokolle ilişkilendirilen uygulamanın Safari uzantısının kurulumunu yöneteceğini varsayar.

Her durumda, geri arama yanlış döndürürse, kullanıcıya uygulamanın (yani, özel protokolünün) yüklenmediğini bildirmeyi bilirsiniz.


IE için çalışmıyor. Nasıl çalışması gerekiyor? bu pencerede tanımlanan myWindow.location.href;iframe ile arasındaki bağlantı srcnedir? Bir istisna yapması mı gerekiyor? Özel protokolün desteklenip desteklenmediğine bakılmaksızın.
Burjua

3

Tarayıcının protokol işleyicilerini algılamanız gerektiğini söylüyorsunuz - gerçekten öyle mi?

Sourceforge'dan bir dosya indirdiğinizde ne olacağı gibi bir şey yaptıysanız ne olur? Diyelim ki uygulamam: // bir şey açmak istiyorsunuz. Sadece ona bir bağlantı oluşturmak yerine, HTTP üzerinden erişilen başka bir HTML sayfasına bir bağlantı oluşturun. Ardından, bu sayfada, onlar için uygulamayı açmaya çalıştığınızı söyleyin. Çalışmazsa, uygulamanızı yüklemeleri gerekir, bunu sağlayacağınız bağlantıya tıklayarak yapabilirler. İşe yararsa, hazırsınız demektir.


4
Bunun yararlı olmayacağını söylemek faydasızdır. Bir başlatma veya indirme bağlantısını koşullu olarak gösterebilmenin - hatta bir bağlantıya tıklandığında koşullu olarak başlatmanın veya indirmenin, kullanıcıya önce yüklemesi gerektiğini söylemekten daha üstün bir UX olacağı bana açık görünüyor.
StuartQ

3

Bunun gibi bir şey deneyebilirsiniz:

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

Hayır, Firefox 27'de çalışmıyor. (Diğer tarayıcılarda test edilmedi)
Blaise

1
ÇALIŞMIYOR - Windows 7, IE, Firefox, Opera, Chrome'da test edildi

1

Benzer bir şey yapmaya çalışıyorum ve Firefox ile çalışan bir numara keşfettim. Bunu IE hilesi ile birleştirirseniz, her iki ana tarayıcıda da çalışan bir tarayıcıya sahip olabilirsiniz (Safari'de çalışıp çalışmadığından emin değilim ve Chrome'da çalışmadığını biliyorum)

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

Bunun çalışması için sayfanın herhangi bir yerinde aşağıdaki gibi gizli bir bağlantıya sahip olmanız gerekir:

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

Biraz karmaşık ama işe yarıyor. Firefox sürümü, ne yazık ki, bilinmeyen bir protokole sahip bir bağlantıyı ziyaret etmeye çalıştığınızda gelen varsayılan uyarıyı hala açmaktadır, ancak uyarı kapatıldıktan sonra kodunuzu çalıştıracaktır.


1
Hala "Firefox bu adresi nasıl açacağını bilmiyor, çünkü protokol (tel) herhangi bir programla ilişkili değil." catch bloğundan önce mesaj
Deebster

6
protocolLong yalnızca "bilinen" protokoller için sonuçları döndürür (dosya:, mailto:, gopher:, ftp:, http:, https:, haberler :) ve diğer Uygulama Protokolleri için değil.
EricLaw

1

Bu, Microsoft desteği tarafından IE için önerilen bir yaklaşımdı

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

"Bir kullanıcının makinesine yüklenen ikili dosyalar üzerinde biraz kontrolünüz varsa, UA'nın komut dosyasında kontrol edilmesi uygun bir yaklaşım gibi görünüyor: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ İnternet Ayarları \ 5.0 \ Kullanıcı Aracısı \ Post Platform" - M $ desteği ile

Her web sayfasının userAgent dizesine erişimi vardır ve özel bir gönderi platformu değeri bırakırsanız, navigator.userAgent kullanarak bunu javascript'te tespit etmek oldukça basittir.

Neyse ki, Firefox ve Chrome gibi diğer büyük tarayıcılar (Safari :( hariç), özel bir protokole sahip bir bağlantı tıklandığında ve bu protokol kullanıcıların makinesine yüklenmediğinde "sayfa bulunamadı" hataları atmayın. IE burada çok affetmez. , görünmez bir çerçeveye tıklamak veya javascript hatalarını tuzağa düşürmek için yapılan herhangi bir numara çalışmaz ve çirkin "web sayfası görüntülenemez" hatasıyla sonuçlanır. Bizim durumumuzda kullandığımız hile, tarayıcıya özel görüntülerle kullanıcıları özel protokolü tıkladıklarını bildirmektir. bağlantı bir uygulamayı açacaktır. Ve uygulamayı açarken bulamazlarsa, bir "yükle" sayfasına tıklayabilirler. XD açısından bu, IE için ActiveX yaklaşımından çok daha iyidir. FF ve Chrome için, devam edin ve herhangi bir algılama olmaksızın özel protokolü başlatın. Kullanıcının gördüklerini size söylemesine izin verin. Safari için:(henüz cevap yok


Kullanıcı-Aracı uzantısı, yaygın ancak sorunlu bir yaklaşımdır. blogs.msdn.com/b/ieinternals/archive/2009/10/08/…
EricLaw

0

Bu önemsiz bir görev değildir; bir seçenek, kayıt defterine ve / veya dosya sistemine erişmek için kullanabileceğiniz imzalı kodu kullanmak olabilir (lütfen bunun çok pahalı bir seçenek olduğunu unutmayın ). Kod imzalama için birleşik bir API veya belirtim de yoktur, bu nedenle her hedef tarayıcı için belirli bir kod oluşturmanız istenir. Bir destek kabusu.

Ayrıca, oyun içeriği dağıtım sistemi Steam'in de bu sorunu çözmemiş gibi göründüğünü biliyorum.


2
İmzalanmış kod, custom: // işlevini işleyen uygulamayla birlikte yüklenen bir sertifika ile imzalanmalıdır, böylece verisign gibi biri tarafından imzalanmış gerçekten pahalı bir uygulama sertifikasına gerek kalmaz.
WhyNotHugo

0

İşte, uygulamanızda başlatma sırasında 'eve telefon et' için (umarım hafif) değişiklik yapılmasını gerektiren başka bir hacky cevap.

  1. Kullanıcı, uygulamayı başlatmaya çalışan bağlantıyı tıklar. Bağlantıya, başlatıldığında uygulamaya aktarılması için benzersiz bir tanımlayıcı eklenir. Web uygulaması bir eğirici veya bu türden bir şey gösterir.
  2. Web sayfası daha sonra aynı benzersiz kimliğe sahip bir uygulamadan bir 'uygulama telefonu ana sayfası' olayını kontrol etmeye başlar.
  3. Uygulamanız başlatıldığında, varlığını belirtmek için web uygulamanıza benzersiz tanımlayıcıyla bir HTTP gönderisi yapar.
  4. Ya web sayfası, uygulamanın sonunda başlatıldığını görür veya bir 'lütfen indirin' sayfasıyla ilerler.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.