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

拡張機能は、他のメッセージ パス 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 と macOS では、パスは絶対パスにする必要があります。Windows では、マニフェスト ファイルを含むディレクトリを基準に相対パスを指定できます。ホストプロセスは、現在のディレクトリがホスト バイナリを含むディレクトリに設定された状態で開始されます。たとえば、このパラメータを C:\Application\nm_host.exe に設定すると、現在のディレクトリ「C:\Application」で開始されます。
type
ネイティブ メッセージ ホストとの通信に使用されるインターフェースのタイプ。このパラメータには、stdio という値を指定できます。これは、Chrome が stdin および stdout を使用してホストと通信する必要があることを示します。
allowed_origins
ネイティブ メッセージング ホストにアクセスできる拡張機能のリスト。allowed-origins 値にワイルドカードを含めることはできません。

ネイティブ メッセージングのホストのロケーション

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

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 ビット レジストリがクエリされます。

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

macOS(システム全体)
Google Chrome: /Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: /Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json
macOS(ユーザー固有のデフォルト パス)
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 ネイティブ ウィンドウへのハンドルを含むコマンドライン引数 --parent-window=<decimal handle value> も渡されます。これにより、ネイティブ メッセージング ホストは、親が正しく設定されたネイティブ UI ウィンドウを作成できます。呼び出しコンテキストがサービス ワーカーの場合、この値は 0 になります。

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

ネイティブ アプリケーションへの接続

ネイティブ アプリとのメッセージの送受信は、拡張機能間メッセージングと非常によく似ています。主な違いは、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);
  }
);

ネイティブ メッセージングをデバッグする

ネイティブ メッセージングで特定のエラーが発生すると、出力は Chrome のエラーログに書き込まれます。これには、ネイティブ メッセージング ホストの起動に失敗した場合、stderr に書き込んだ場合、通信プロトコルに違反した場合などが含まれます。Linux と macOS では、コマンドラインから Chrome を起動してターミナルで出力を監視すると、このログにアクセスできます。Windows では、ロギングを有効にする方法で説明されているように --enable-logging を使用します。

以下に、一般的なエラーとその解決方法をご紹介します。

ネイティブ メッセージング ホストを起動できませんでした。

ネイティブ メッセージ ホスト ファイルを実行するための十分な権限があるかどうかを確認します。

無効なネイティブ メッセージ ホスト名が指定されています。

名前に無効な文字が含まれているかどうかを確認します。英小文字、数字、アンダースコア、ドットのみ使用できます。名前の先頭または末尾にドットを付けたり、ドットの後に別のドットを使用したりすることはできません。

ネイティブ ホストが終了しました。

Chrome がメッセージを読み取る前に、ネイティブ メッセージング ホストへのパイプが切断されました。これは、ネイティブ メッセージング ホストから開始される可能性が高いです。

指定されたネイティブ メッセージング ホストが見つかりません。

以下を確認します。

  • 拡張機能とマニフェスト ファイルで名前のスペルが正しく入力されていますか?
  • マニフェストは正しいディレクトリにあり、正しい名前で作成されているか。想定される形式については、ネイティブ メッセージングのホストの場所をご覧ください。
  • マニフェスト ファイルの形式は正しいですか?特に、JSON は有効で適切な形式であり、値はネイティブ メッセージング ホスト マニフェストの定義と一致していますか?
  • path で指定されたファイルは存在しますか?Windows ではパスを相対パスにできますが、macOS と Linux ではパスを絶対パスにする必要があります。

ネイティブ メッセージング ホストのホスト名が登録されていません。(Windows のみ)

ネイティブ メッセージング ホストが Windows レジストリで見つかりませんでした。regedit を使用して、鍵が実際に作成され、ネイティブ メッセージング ホストのロケーションに記載されている必要な形式と一致しているかどうかを再確認します。

指定したネイティブ メッセージング ホストへのアクセスは禁止されています。

拡張機能のオリジンが allowed_origins に登録されていますか?

ネイティブ メッセージ ホストとの通信中にエラーが発生しました。

これは、ネイティブ メッセージング ホストの通信プロトコルの実装が正しくないことを示します。

  • stdout のすべての出力がネイティブ メッセージング プロトコルに準拠していることを確認します。デバッグ目的でデータを出力する場合は、stderr に書き込みます。
  • 32 ビットのメッセージ長がプラットフォームのネイティブ整数形式(リトルエンディアン / ビッグエンディアン)であることを確認します。
  • メッセージの長さは 1,024*1,024 を超えないようにしてください。
  • メッセージ サイズは、メッセージのバイト数と同じにする必要があります。1 つの文字が複数のバイトで表される場合があるため、これは文字列の「長さ」とは異なる場合があります。
  • Windows のみ: プログラムの I/O モードが O_BINARY に設定されていることを確認します。デフォルトでは、I/O モードは O_TEXT です。この場合、改行(\n = 0A)が Windows 形式の改行(\r\n = 0D 0A)に置き換えられるため、メッセージ形式が破損します。I/O モードは __setmode を使用して設定できます。