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

拡張機能は、他のメッセージ受け渡し 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 が stdinstdout を使用してホストと通信する必要があることを示します。
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 ウィンドウを作成できます。呼び出しコンテキストが Service Worker の場合、この値は 0 になります。

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

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

ネイティブ アプリとのメッセージの送受信は、拡張機能のメッセージとよく似ています。主な違いは、runtime.connect() の代わりに runtime.connectNative() が使用され、runtime.sendMessage() の代わりに runtime.sendNativeMessage() が使用されることです。

これらのメソッドを使用するには、拡張機能のマニフェスト ファイルで「nativeMessaging」権限を宣言する必要があります。

これらのメソッドは、コンテンツ スクリプト内では使用できず、拡張機能のページ内と Service Worker 内でのみ使用できます。コンテンツ スクリプトからネイティブ アプリケーションと通信する必要がある場合は、メッセージを Service Worker に送信してネイティブ アプリに渡します。

次の例では、ネイティブ メッセージング ホスト 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 ビットのメッセージ長がプラットフォームのネイティブ整数形式(リトル エンディアン / ビッグ エンディアン)であることを確認します。
  • メッセージの長さは 1024*1024 以下にする必要があります。
  • メッセージ サイズは、メッセージのバイト数と同じである必要があります。文字は複数のバイトで表される場合があるため、文字列の「length」とは異なる場合があります。
  • Windows のみ: プログラムの I/O モードが O_BINARY に設定されていることを確認します。デフォルトでは、I/O モードは O_TEXT で、改行(\n = 0A)が Windows スタイルの改行(\r\n = 0D 0A)に置き換えられるため、メッセージ形式が破損します。I/O モードは __setmode を使用して設定できます。