ブラウザのプロトコルハンドラを検出する方法は?


82

カスタムURLプロトコルハンドラーを作成しました。

http://

mailto://

custom://

それに応じて応答するWinFormsアプリケーションを登録しました。これはすべてうまく機能します。

ただし、ユーザーがカスタムURLプロトコルハンドラーをまだインストールしていない場合は、適切に処理できるようにしたいと思います。

これを実行できるようにするには、ブラウザーに登録されているプロトコルハンドラーを検出できる必要があります。これは、JavaScriptから推測します。しかし、私は情報をポーリングする方法を見つけることができませんでした。私はこの問題の解決策を見つけたいと思っています。

あなたが共有することができるかもしれないどんな考えにも感謝します。


5
これはクロム(つまり、XPCOM、ActiveXなど)コードでのみ可能だと思います。そうしないと、プライバシーの問題になります(「Eudoraを使用していることが検出されました。今日はFooMailに切り替えてください!」)。しかし、明確にしてください何ブラウザ(S)/ OS(ES)あなたにしている興味インチ
マシューFlaschen

1
良い点ですが、独自のプロトコルacsfs:// Windows IE、FireFox、理想的にはSafariを処理するために何かが登録されていることを知ってうれしいです
Chris Craft

あなたはすでにこの問題を解決しましたか?
jstuardo

回答:


35

これは、これを行うための非常に非常に ハッキーな方法になります...しかし、これは機能しますか?

  • 通常どおりリンクを挿入します...
  • ただし、それにonclickハンドラーをアタッチすると、タイマーが設定され、ウィンドウにonblurハンドラーが追加されます。
  • (理論的には)ブラウザがリンクを処理する場合(アプリケーションX)は、ウィンドウからフォーカスを盗んでロードします。
  • onblurイベントが発生した場合は、タイマーをクリアしてください...
  • それ以外の場合は、3〜5秒でタイムアウトが発生します...そしてユーザーに「うーん、Mega Uber Coolアプリケーションがインストールされていないようです...今すぐインストールしますか?(OK)(キャンセル)」

防弾にはほど遠い...しかし、それは役立つかもしれませんか?


1
:Dそれは賢い考えです。それは一般的なニーズのように思われるので、方法があるようです。
クリスクラフト

2
Mac上のFirefox(おそらくより多くのブラウザ)では、カスタムプロトコルを使用するアプリケーションの起動に失敗しても、ウィンドウのフォーカスが失われ、onblurが起動します。
quano 2012

プロトコルのエラー処理がないため、これはChromeにとって適切なソリューションです。これは、他のブラウザの検出と組み合わせて使用​​されています:rajeshsegu.com/2012/09/browser-detect-custom-protocols/…– Fillip
Peyton

最近、プロトコルの検出が大きな頭痛の種になっています。;)上記の方法は、ラジェッシュのライブの例を使用して...多少動作しているようで発見rajeshsegu.com/fun/code/browser/detect.html私はクロームに「真」になっています。しかし、results()関数がないようにリファクタリングして(アラートボックス(ブロッキング呼び出し)を使用する)、ブール値を返すようにすると、falseになります。どういうわけか、ブロッキングアラートはタイミングを強制するためのハッキーな方法でもあると感じています...何か洞察、@ scunliffe?
グレッグペティット2014

この方法は、ユーザーがWin8を使用して回答を記憶することを選択し、アプリケーションを持っていない場合を除いて、Chromeで機能します。この場合、アプリケーションを起動できなくてもブラーイベントが発生します
Paul Haggo 2015

18

これを行うための優れたクロスブラウザの方法はありません。Win8 +のIE10 +では、新しいmsLaunchUriAPIを使用すると、次のようなプロトコルを起動できます。

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

プロトコルがインストールされていない場合、失敗コールバックが発生します。それ以外の場合は、プロトコルが起動し、成功コールバックが起動します。

このトピックについては、ここでもう少し詳しく説明します:http//blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my .aspx


動作しません

6
msLaunchUriはWindows8以降のみです。
EricLaw 2014

リンクが切れていました。
qiulang

16

HTML5はカスタムスキームとコンテンツハンドラーを定義します(私の知る限り、Firefoxはこれまでのところ唯一の実装者です)が、残念ながら現在、ハンドラーがすでに存在するかどうかを確認する方法はありません。提案ています、フォローアップはありませんでした。これは、カスタムハンドラーを効果的に使用するための重要な機能のようです。開発者は、この問題を実装するために注意を払う必要があります。


13

プロトコルハンドラーを登録したインストール済みアプリの存在を検出するためのJavaScriptを介した簡単な方法はないようです。

iTunesモデルでは、AppleはサーバーにURLを提供し、サーバーはJavaScriptを実行するページを提供します。

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

そのため、iTunesインストーラーは、主要なブラウザー用のプラグインをデプロイしているようです。プラグインの存在を検出できます。

プラグインがインストールされている場合は、アプリ固有のURLへのリダイレクトが成功することを合理的に確信できます。


2
これが最も信頼できるソリューションになるはずです。しかし、私はあなたがほとんどのブラウザのためにプラグインをインストールして作成する必要があることを意味します、そしてそれはちょっとトリッキーです。代わりに、ユーザーをダウンロードページにリダイレクトできるようにすると、よりユーザーフレンドリーになる可能性があります。
ナティム2010年

ここで述べたようにFireBreathを使用しないのはなぜですか?stackoverflow.com/a/14758085/427793
swdev 2014

10

最も簡単な解決策は、ユーザーに最初に尋ねることです。

例ごとにJavascript確認ダイアログを使用する:

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

クッキーは毎日きれいに取り除くことができます。FlashベースのCookieを作成するためのより良い方法はありませんか?

クッキーが削除された場合、ユーザーは再びプロンプトが表示されます。
ナティム2014

5

実行しようとしているプログラム(コード)を制御できる場合、ユーザーがアプリケーションの実行に成功したかどうかを確認する1つの方法は、次のとおりです。

  1. カスタムプロトコルを開こうとする前に、ユーザーの意図をデータベースに保存するサーバースクリプトにAJAXリクエストを送信します(たとえば、ユーザーIDとユーザーがやりたいことを保存します)。

  2. プログラムを開いて、インテントデータを渡してみてください。

  3. プログラムにサーバーにデータベースエントリを削除するように要求させます(インテントデータを使用して正しい行を見つけます)。

  4. javascriptでサーバーをしばらくポーリングして、データベースエントリがなくなったかどうかを確認します。エントリがなくなった場合、ユーザーがアプリケーションを開くことに成功したことがわかります。そうでない場合、エントリは残ります(後でcronjobを使用して削除できます)。

私はこの方法を試したことがなく、考えただけです。


4

私はついにクロスブラウザー(Chrome 32、Firefox 27、IE 11、Safari 6)ソリューションを、これと非常にシンプルなSafari拡張機能の組み合わせで動作させることができました。この解決策の多くは、この質問とこの他の質問で何らかの形で言及されています。

スクリプトは次のとおりです。

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拡張機能は簡単に実装できました。これは、1行のインジェクションスクリプトで構成されていました。

myinject.js:

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

次に、WebページのJavaScriptで、最初にメッセージイベントを登録し、メッセージが受信された場合にフラグを設定する必要があります。

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

これは、カスタムプロトコルに関連付けられているアプリケーションがSafari拡張機能のインストールを管理することを前提としています。

いずれの場合も、コールバックがfalseを返した場合は、アプリケーション(つまり、カスタムプロトコル)がインストールされていないことをユーザーに通知する必要があります。


IEでは機能しません。それはどのように機能するはずですか?そのウィンドウ内で定義されたmyWindow.location.href;とiframeの間の接続は何srcですか?例外をスローすることになっていますか?カスタムプロトコルがサポートされているかどうかに関係なく、それは関係ありません。
ブルジョア2015年

3

あなたはブラウザのプロトコルハンドラを検出する必要があると言います-あなたは本当にですか?

sourceforgeからファイルをダウンロードしたときに何が起こるかのようなことをした場合はどうなりますか?myapp:// somethingを開きたいとしましょう。単にリンクを作成するのではなく、HTTP経由でアクセスする別のHTMLページへのリンクを作成します。次に、そのページで、それらのアプリケーションを開こうとしていると言います。それが機能しない場合、彼らはあなたのアプリケーションをインストールする必要があります、それはあなたが提供するリンクをクリックすることによって彼らがすることができます。それが機能する場合は、すべて設定されています。


4
これが役に立たないと示唆するのは役に立たない。起動リンクまたはダウンロードリンクを条件付きで表示できること、またはリンクをクリックしたときに条件付きで起動またはダウンロードできることは、最初にインストールする必要があることをユーザーに伝えるよりも優れたUXであることは明らかです。
StuartQ 2015年

3

あなたはこのようなことを試すことができます:

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

いいえ、Firefox 27では機能しません。(他のブラウザではテストしませんでした)
2014年

1
動作しません-Windows7、IE、Firefox、Opera、Chromeでテスト済み

1

私は似たようなことをしようとしていますが、Firefoxで機能するトリックを発見しました。IEのトリックと組み合わせると、両方のメインブラウザで動作するものを使用できます(Safariで動作するかどうかはわかりませんが、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");
        }
    }
}

これが機能するためには、次のように、ページのどこかに非表示のリンクが必要です。

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

少しハッキーですが、機能します。残念ながら、Firefoxバージョンでは、不明なプロトコルのリンクにアクセスしようとすると表示されるデフォルトのアラートがポップアップ表示されますが、アラートが解除された後、コードが実行されます。


1
「プロトコル(tel)がどのプログラムにも関連付けられていないため、Firefoxはこのアドレスを開く方法を知りません」というメッセージが表示されます。キャッチブロックの前のメッセージ
Deebster 2010

6
protocolLongは、「既知の」プロトコル(file:、mailto:、gopher:、ftp:、http:、https:、news :)の結果のみを返し、他のアプリケーションプロトコルの結果は返しません。
EricLaw 2011

1

これは、MicrosoftサポートによるIEの推奨アプローチでした

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

「ユーザーのマシンにインストールされているバイナリをある程度制御できる場合は、スクリプトでUAを確認することが適切なアプローチのようです:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Internet Settings \ 5.0 \ User Agent \ Post Platform "- M $サポートによる

すべてのWebページはuserAgent文字列にアクセスでき、カスタムの投稿プラットフォーム値を削除すると、navigator.userAgentを使用してjavascriptでこれを検出するのは非常に簡単です。

幸い、FirefoxやChromeなどの他の主要なブラウザ(Safariを除く:()は、カスタムプロトコルのリンクがクリックされ、プロトコルがユーザーのマシンにインストールされていない場合、「ページが見つかりません」エラーをスローしません。IEはここでは非常に寛容ではありません。 、非表示のフレームをクリックしたり、javascriptエラーをトラップしたりするトリックは機能せず、醜い「ウェブページを表示できません」エラーになります。この場合に使用するトリックは、カスタムプロトコルをクリックすることをブラウザ固有の画像でユーザーに通知することです。リンクをクリックするとアプリケーションが開きます。アプリが開いていない場合は、「インストール」ページをクリックできます。XDに関しては、このwprksはIEのActiveXアプローチよりもはるかに優れています。FFおよびChromeの場合は、先に進んでください。検出せずにカスタムプロトコルを起動します。ユーザーに表示内容を知らせます。Safariの場合、:(まだ答えはありません


User-Agent拡張は一般的ですが、問題のあるアプローチです。blogs.msdn.com/b/ieinternals/archive/2009/10/08/...
EricLaw

0

これは簡単な作業ではありません。1つのオプションは、署名されたコードを使用することです。これを利用して、レジストリやファイルシステムにアクセスできます(これは非常に高価なオプションであること注意してください)。また、コード署名用の統一されたAPIまたは仕様がないため、ターゲットブラウザごとに特定のコードを生成する必要があります。サポートの悪夢。

また、ゲームコンテンツ配信システムであるSteamでも、この問題は解決されていないようです。


2
署名されたコードは、custom://を処理するアプリケーションと一緒にインストールされる証明書によって署名される必要があるため、verisignのような誰かによって署名された非常に高価なアプリケーション証明書は必要ありません。
WhyNotHugo 2010

0

これは、起動時にアプリケーションを「phonehome」に変更する必要がある(できれば軽い)別のハッキーな答えです。

  1. ユーザーがリンクをクリックすると、アプリケーションが起動しようとします。一意の識別子がリンクに配置されるため、アプリケーションの起動時にアプリケーションに渡されます。Webアプリは、スピナーまたはその性質の何かを示しています。
  2. 次に、Webページは、これと同じ一意のIDを持つアプリからの「applicationphonehome」イベントのチェックを開始します。
  3. 起動すると、アプリケーションは、存在を示すために一意の識別子を使用してWebアプリにHTTPPOSTを実行します。
  4. Webページは、アプリケーションが最終的に起動したことを確認するか、「ダウンロードしてください」ページに進みます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.