web-dev-qa-db-ja.com

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

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

http://

mailto://

custom://

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

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

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

共有できるアイデアをお寄せいただきありがとうございます。

76
Chris Craft

これは、veryveryhackyこれを行う方法...しかし、これは動作しますか?

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

防弾とはほど遠い...しかしそれは役立つかもしれない?

32
scunliffe

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

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

17
EricLaw

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

16
Hugh Guiney

組み込みiframeを使用して、カスタムプロトコルと既知のプロトコル(Webまたはアプリストア)を自動的に切り替えることができます。 https://Gist.github.com/2662899 を参照してください。

13
David W. Keith

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

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

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

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

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

13
jtomson

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

例ごとに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/'
10
Natim

カスタムプロトコルハンドラーがブラウザーからフォーカスを奪うために新しいウィンドウをトリガーするという仮定に基づいて、この問題の汎用ライブラリーを作成しました。

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

6
habsq

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

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

  2. プログラムを開き、意図データを渡します。

  3. プログラムがサーバーにリクエストを行って、データベースエントリを削除します(インテントデータを使用して正しい行を見つけます)。

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

私はこの方法を試したことがありませんでした。

5
quano

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

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

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を返した場合、アプリケーション(つまり、カスタムプロトコル)がインストールされていないことをユーザーに通知することがわかります。

4
whiskeyspider

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

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

3
Brian

次のようなものを試すことができます:

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
        }
    }
}
3
Ariel Guitian

これは、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エラーをトラップするトリックは機能せず、andい「ウェブページを表示できません」というエラーになります。この場合の用途は、カスタムプロトコルリンクをクリックするとアプリケーションが開くことをブラウザ固有の画像でユーザーに通知することであり、開いているアプリが見つからない場合は、「インストール」ページをクリックすることができます。 IEのActiveXアプローチよりも優れています。FFとChromeの場合は、検出せずにカスタムプロトコルを起動してください。ユーザーに表示を教えてください。

1
Megha

同様のことをしようとしていますが、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
user200565

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

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

0
ken

これは、起動時に「ホームに電話をかける」ためにアプリケーションを変更(できれば軽く)する必要がある、もう1つのハッキーな答えです。

  1. ユーザーがリンクをクリックすると、アプリケーションが起動されます。一意の識別子がリンクに配置されるため、起動時にアプリケーションに渡されます。 Webアプリには、スピナーまたはその性質のものが表示されます。
  2. Webページは、この同じ一意のIDを持つアプリからの「アプリケーションフォンホーム」イベントのチェックを開始します。
  3. 起動すると、アプリケーションは、存在を示すために、一意の識別子を使用してWebアプリにHTTPポストを実行します。
  4. Webページは、アプリケーションが最終的に起動したことを確認するか、「ダウンロードしてください」ページに進みます。
0
sethcall