擴充功能可以使用類似其他訊息傳遞 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 位元登錄檔。
在 macOS 和 Linux 上,原生訊息主機資訊清單檔案的位置會因瀏覽器 (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 免於行為異常的原生應用程式影響。傳送至原生訊息主機的訊息大小上限為 64 MiB。
原生訊息主機的第一個引數是呼叫端的來源,通常是 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.connectNative() 取代 runtime.connect(),並使用 runtime.sendNativeMessage() 取代 runtime.sendMessage()。
如要使用這些方法,必須在擴充功能的資訊清單檔案中宣告「nativeMessaging」權限。
這些方法無法在內容指令碼中使用,只能在擴充功能的頁面和服務工作人員中使用。如要從內容指令碼與原生應用程式通訊,請將訊息傳送至服務工作人員,再由服務工作人員將訊息傳遞至原生應用程式。
下列範例會建立連結至原生訊息主機 com.my_company.my_application 的 runtime.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);
}
);
偵錯原生訊息傳遞
發生特定原生訊息傳遞失敗時,系統會將輸出內容寫入 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),導致訊息格式損毀。您可以使用__setmode設定 I/O 模式。