原生訊息傳遞

擴充功能可透過與其他訊息傳遞 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_applicationHKEY_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 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.connectNative() 而非 runtime.connect(),並使用 runtime.sendNativeMessage() 而非 runtime.sendMessage()

如要使用這些方法,您必須在擴充功能的資訊清單檔案中宣告「nativeMessaging」權限。

這些方法無法在內容指令碼內使用,只能於擴充功能的網頁和 Service Worker 內使用。如果您想從內容指令碼與原生應用程式通訊,請傳送訊息至服務工作站,將訊息傳送至原生應用程式。

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

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