原生訊息傳遞

擴充功能和應用程式可透過與其他訊息傳遞 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.connectNativeruntime.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 MB,主要是為了避免 Chrome 運作錯誤的原生應用程式。傳送至原生訊息傳遞主機的訊息大小上限為 4 GB。

原生訊息傳遞主機的第一個引數是呼叫端的來源,通常是 chrome-extension://[ID of allowed extension]。當您在原生訊息傳遞主機資訊清單中以 allowed_origins 金鑰指定多個擴充功能時,這可讓原生訊息傳遞主機識別訊息的來源。警告:在 Windows 中,在 Chrome 54 以下版本中,系統會將來源當做第二個參數傳遞,而非第一個參數。

使用 runtime.connectNative 建立訊息通訊埠時,Chrome 會啟動原生訊息傳遞主機程序,並保持執行狀態,直到刪除通訊埠為止。另一方面,如果使用 runtime.sendNativeMessage 傳送訊息,但未建立訊息通訊埠,Chrome 會為每個訊息啟動新的原生訊息傳遞主機程序。在這種情況下,主機程序產生的第一則訊息會視為對原始要求的回應。例如,Chrome 會將該訊息傳送至呼叫 runtime.sendNativeMessage 時指定的回應回呼。在這種情況下,系統會忽略原生訊息傳遞主機產生的所有其他訊息。

在 Windows 上,系統也會將指令列引數與呼叫 Chrome 原生視窗 --parent-window=<decimal handle value> 的處理常式傳遞給這個指令列引數。如此一來,原生訊息主機就能建立已正確父項的原生 UI 視窗。請注意,如果呼叫結構定義是背景指令碼頁面,這個值會是 0。

連線至原生應用程式

與原生應用程式互傳訊息與接收訊息的功能與跨擴充功能訊息類似。主要差別在於使用的是 runtime.connectNative (而非 runtime.connect),並使用 runtime.sendNativeMessage,而非 runtime.sendMessage。只有在應用程式的資訊清單檔案中宣告「nativeMessaging」權限時,才能使用這些方法。

下列範例會建立並連線至原生訊息傳遞主機 com.my_company.my_applicationruntime.Port 物件,開始監聽來自該通訊埠的訊息,並傳送一則傳出訊息:

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。
    • 訊息大小必須等於訊息的位元組數。這可能與字串的「長度」不同,因為字元可能以多個位元組表示。
    • 僅限 Windows:確認程式的 I/O 模式已設為 O_BINARY。根據預設,I/O 模式為 O_TEXT,這會以分行符號 (\n = 0A) 取代訊息格式,並以 Windows 樣式的行結尾 (\r\n = 0D 0A) 取代。I/O 模式可使用 __setmode 設定。