ネイティブ メッセージング

拡張機能とアプリは、他のメッセージ受け渡し API と同様の API を使用して、ネイティブ アプリとメッセージを交換できます。この機能をサポートするネイティブ アプリは、拡張機能との通信方法を認識しているネイティブ メッセージング ホストを登録する必要があります。Chrome はホストを別のプロセスで起動し、標準の入力ストリームと標準出力ストリームを使用してホストと通信します。

ネイティブ メッセージング ホスト

ネイティブ メッセージング ホストを登録するには、アプリケーションで、ネイティブ メッセージング ホストの構成を定義するマニフェスト ファイルをインストールする必要があります。マニフェスト ファイルの例を次に示します。

{
  "name": "com.my_company.my_application",
  "description": "My Application",
  "path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

ネイティブ メッセージング ホストのマニフェスト ファイルは有効な JSON で、次のフィールドが含まれている必要があります。

名前説明
nameネイティブ メッセージング ホストの名前。クライアントは、この文字列を runtime.connectNative または runtime.sendNativeMessage に渡します。名前に使用できるのは、英小文字、数字、アンダースコア、ドットのみです。名前の先頭や末尾をドットにすることはできません。また、ドットの後に別のドットを付けることはできません。
descriptionアプリケーションの短い説明。
pathネイティブ メッセージング ホストバイナリへのパス。Linux と OSX では、パスは絶対パスである必要があります。Windows では、マニフェスト ファイルが配置されているディレクトリからの相対パスで、ホストプロセスは、ホストバイナリを含むディレクトリに設定された現在のディレクトリで開始されます。たとえば、このパラメータが C:\Application\nm_host.exe に設定されている場合、現在のディレクトリ C:\Application\ で開始されます。
typeネイティブ メッセージング ホストとの通信に使用されるインターフェースのタイプ。現在、このパラメータに使用できる値は stdio のみです。これは、Chrome が stdinstdout を使用してホストと通信する必要があることを示します。
allowed_originsネイティブ メッセージング ホストへのアクセスを許可する必要がある拡張機能のリスト。chrome-extension://*/* などのワイルドカードは使用できません

ネイティブ メッセージング ホストの場所

マニフェスト ファイルの場所はプラットフォームによって異なります。

Windows の場合、マニフェスト ファイルはファイル システム内の任意の場所に配置できます。アプリケーション インストーラはレジストリ キー HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\_com.my_company.my_application_ または HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\_com.my_company.my_application_ を作成し、そのキーのデフォルト値をマニフェスト ファイルへのフルパスに設定する必要があります。たとえば、次のコマンドを使用します。

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f

または、次の .reg ファイルを使用します。

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application]
@="C:\\path\\to\\nmh-manifest.json"

Chrome がネイティブ メッセージング ホストを探す際、まず 32 ビット レジストリがクエリされ、次に 64 ビット レジストリがクエリされます。

OS XLinux では、ネイティブ メッセージング ホストのマニフェスト ファイルの場所はブラウザ(Google Chrome または Chromium)によって異なります。システムレベルのネイティブ メッセージング ホストは固定の場所で検索され、ユーザーレベルのネイティブ メッセージング ホストは NativeMessagingHosts というユーザー プロファイル ディレクトリ内のサブディレクトリで検索されます。

  • OS X(システム全体)
    • Google Chrome: /Library/Google/Chrome/NativeMessagingHosts/_com.my_company.my_application_.json
    • Chromium: /Library/Application Support/Chromium/NativeMessagingHosts/_com.my_company.my_application_.json
  • OS X(ユーザー固有のデフォルトパス)
    • Google Chrome: ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/_com.my_company.my_application_.json
    • Chromium: ~/Library/Application Support/Chromium/NativeMessagingHosts/_com.my_company.my_application_.json
  • Linux(システム全体)
    • Google Chrome: /etc/opt/chrome/native-messaging-hosts/_com.my_company.my_application_.json
    • Chromium: /etc/chromium/native-messaging-hosts/_com.my_company.my_application_.json
  • Linux(ユーザー固有のデフォルトパス)
    • Google Chrome: ~/.config/google-chrome/NativeMessagingHosts/_com.my_company.my_application_.json
    • Chromium: ~/.config/chromium/NativeMessagingHosts/_com.my_company.my_application_.json

ネイティブ メッセージング プロトコル

Chrome は各ネイティブ メッセージング ホストを個別のプロセスで起動し、標準入力(stdin)と標準出力(stdout)を使用してホストと通信します。同じ形式で双方向のメッセージを送信します。各メッセージは JSON の UTF-8 エンコードを使用してシリアル化され、ネイティブ バイト順の 32 ビットのメッセージ長が先頭に付加されます。ネイティブ メッセージング ホストから送信される 1 つのメッセージの最大サイズは 1 MB です。これは、ネイティブ アプリの誤動作から Chrome を保護するための主な目的です。ネイティブ メッセージング ホストに送信されるメッセージの最大サイズは 4 GB です。

ネイティブ メッセージング ホストの最初の引数は、呼び出し元のオリジン(通常は chrome-extension://[ID of allowed extension])です。これにより、ネイティブ メッセージング ホスト マニフェストallowed_origins キーに複数の拡張機能が指定されている場合、ネイティブ メッセージング ホストはメッセージのソースを識別できます。警告: Windows の Chrome 54 以前では、起点が最初のパラメータではなく 2 番目のパラメータとして渡されていました。

runtime.connectNative を使用してメッセージング ポートを作成すると、Chrome はネイティブ メッセージング ホストプロセスを起動し、ポートが破棄されるまで実行を継続します。一方、メッセージ ポートを作成せずに runtime.sendNativeMessage を使用してメッセージが送信されると、Chrome はメッセージごとに新しいネイティブ メッセージング ホストプロセスを開始します。その場合、ホストプロセスによって生成された最初のメッセージは、元のリクエストに対するレスポンスとして処理されます。つまり、Chrome は、runtime.sendNativeMessage が呼び出されたときに指定されたレスポンス コールバックにそのメッセージを渡します。この場合、ネイティブ メッセージング ホストによって生成された他のすべてのメッセージは無視されます。

Windows の場合、ネイティブ メッセージング ホストには、呼び出し元の Chrome ネイティブ ウィンドウへのハンドル(--parent-window=<decimal handle value>)を含むコマンドライン引数も渡されます。これにより、ネイティブ メッセージング ホストは、適切な親を持つネイティブ UI ウィンドウを作成できます。呼び出し元のコンテキストがバックグラウンドのスクリプト ページの場合、この値は 0 になります。

ネイティブ アプリへの接続

ネイティブ アプリとのメッセージの送受信は、拡張機能のメッセージとよく似ています。主な違いは、runtime.connect の代わりに runtime.connectNative を使用し、runtime.sendMessage の代わりに runtime.sendNativeMessage を使用することです。 これらのメソッドは、アプリのマニフェスト ファイルで「nativeMessaging」権限が宣言されている場合にのみ使用できます。

次の例では、ネイティブ メッセージング ホスト com.my_company.my_application に接続された runtime.Port オブジェクトを作成し、そのポートからのメッセージをリッスンし、1 つの送信メッセージを送信します。

var port = chrome.runtime.connectNative('com.my_company.my_application');
port.onMessage.addListener(function(msg) {
  console.log("Received" + msg);
});
port.onDisconnect.addListener(function() {
  console.log("Disconnected");
});
port.postMessage({ text: "Hello, my_application" });

runtime.sendNativeMessage を使用すると、ポートを作成せずにネイティブ アプリケーションにメッセージを送信できます。次に例を示します。

chrome.runtime.sendNativeMessage('com.my_company.my_application',
  { text: "Hello" },
  function(response) {
    console.log("Received " + response);
  });

ネイティブ メッセージのデバッグ

ネイティブ メッセージング ホストの起動に失敗した場合、stderr に書き込む場合、または通信プロトコルに違反する場合は、出力が Chrome のエラーログに書き込まれます。Linux と OS X では、コマンドラインから Chrome を起動し、ターミナルで出力を監視することで、このログに簡単にアクセスできます。Windows では、ロギングを有効にする方法の説明に沿って --enable-logging を使用します。

エラーと、この問題を解決するためのヒントをいくつか紹介します。

  • ネイティブ メッセージング ホストを起動できませんでした。
    • ファイルを実行するのに十分な権限があるかどうかを確認します。
  • 指定されたネイティブ メッセージングのホスト名が無効です。
    • 名前に無効な文字が含まれていないか確認します。使用できるのは、英小文字、数字、アンダースコア、ドットのみです。名前の先頭または末尾をドットにすることはできません。また、ドットの後に別のドットを付けることはできません。
  • ネイティブ ホストを終了しました。
    • Chrome でメッセージが読み取られる前に、ネイティブ メッセージング ホストへのパイプが切断されました。通常は、ネイティブ メッセージング ホストから送信されます。
  • 指定されたネイティブ メッセージング ホストが見つかりません。
    • 拡張機能とマニフェスト ファイルで、名前のスペルが正しいかをご確認ください。
    • マニフェストは正しいディレクトリに配置されており、正しい名前が付けられていますか?想定される形式については、ネイティブ メッセージング ホストの場所をご覧ください。
    • マニフェスト ファイルは正しい形式ですか?特に、JSON 構文は正しく、値がネイティブ メッセージング ホスト マニフェストの定義と一致しているか。
    • path で指定されたファイルは存在するか。Windows では相対パスを指定できますが、OS X と Linux では絶対パスにする必要があります。
  • ネイティブ メッセージング ホストのホスト名が登録されていません。(Windows のみ)
    • Windows レジストリでネイティブ メッセージング ホストが見つかりませんでした。regedit を使用して、キーが実際に作成されたかどうか、およびネイティブ メッセージ ホストの場所に記載されている必要な形式と一致していることを再確認します。
  • 指定されたネイティブ メッセージング ホストへのアクセスは禁止されています。
    • 拡張機能のオリジンが allowed_origins にリストされていますか?
  • ネイティブ メッセージング ホストとの通信中にエラーが発生しました。
    • これは非常に一般的なエラーで、ネイティブ メッセージング ホストでの通信プロトコルの実装が正しくないことを示します。
    • stdout のすべての出力がネイティブ メッセージング プロトコルに準拠していることを確認します。デバッグ目的でデータを出力する場合は、stderr に書き込みます。
    • 32 ビットのメッセージ長がプラットフォームのネイティブ整数形式(リトル エンディアン / ビッグ エンディアン)であることを確認します。
    • メッセージの長さは 1024*1024 以下にする必要があります。
    • メッセージ サイズは、メッセージのバイト数と同じである必要があります。文字は複数のバイトで表される場合があるため、文字列の「length」とは異なる場合があります。
    • Windows のみ: プログラムの I/O モードが O_BINARY に設定されていることを確認します。デフォルトでは、I/O モードは O_TEXT で、改行(\n = 0A)が Windows スタイルの改行(\r\n = 0D 0A)に置き換えられるため、メッセージ形式が破損します。I/O モードは __setmode を使用して設定できます。