扩展程序和应用可以使用类似于 消息传递 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 和 OSX 上,路径必须为绝对路径。在 Windows 中,此文件可以相对于清单文件所在的目录。启动主机进程时,将当前目录设置为包含主机二进制文件的目录。例如,如果此参数设置为 C:\Application\nm_host.exe ,则将使用当前目录 C:\Application\ 启动。 |
type | 用于与原生消息传递主机通信的接口类型。目前,此参数只有一个可能的值:stdio 。它表示 Chrome 应使用 stdin 和 stdout 与主机通信。 |
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 X 和 Linux 上,原生消息传递主机清单文件的位置因
浏览器(Google Chrome 或 Chromium)。系统会查找系统级原生消息传递主机,
而用户级本地消息传递主机在
用户个人资料目录(名为 NativeMessagingHosts
)。
- OS X(系统级)
<ph type="x-smartling-placeholder">
- </ph>
- Google Chrome:
/Library/Google/Chrome/NativeMessagingHosts/_com.my_company.my_application_.json
- Chromium:
/Library/Application Support/Chromium/NativeMessagingHosts/_com.my_company.my_application_.json
- Google Chrome:
- OS X(特定于用户的默认路径)
<ph type="x-smartling-placeholder">
- </ph>
- 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
- Google Chrome:
- Linux(系统级)
<ph type="x-smartling-placeholder">
- </ph>
- 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
- Google Chrome:
- Linux(特定于用户的默认路径)
<ph type="x-smartling-placeholder">
- </ph>
- Google Chrome:
~/.config/google-chrome/NativeMessagingHosts/_com.my_company.my_application_.json
- Chromium:
~/.config/chromium/NativeMessagingHosts/_com.my_company.my_application_.json
- Google Chrome:
原生消息传递协议
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>
。这样,原生
消息主机创建正确父级的原生界面窗口。请注意,该值将
如果调用上下文是后台脚本页面,则为 0。
连接到原生应用
向原生应用发送和接收来自原生应用的消息与跨扩展非常相似 消息。主要区别在于使用的是 runtime.connectNative 使用 runtime.connect 和 runtime.sendNativeMessage,而不是 runtime.sendMessage. 这些方法只能在“nativeMessaging”权限时(在应用的声明中) 清单文件
以下示例创建了一个连接到原生消息传递主机的 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);
});
调试原生消息传递
当原生消息传递主机无法启动时,向 stderr
写入数据或当它违反
通信协议,会将输出写入 Chrome 的错误日志。在 Linux 和 OS X 上,此日志
通过从命令行启动 Chrome 并在
终端。在 Windows 上,请按照如何启用日志记录中的说明使用 --enable-logging
。
以下是一些错误和问题解决方法:
- 未能启动原生消息传递主机。
- 检查您是否有足够的权限来执行文件。
- 指定的本地消息传递主机名称无效。
- 检查名称是否包含任何无效字符。只能包含小写字母数字字符、 允许使用下划线和英文句点。名称不能以句点开头或结尾,也不能以句点结尾 后面跟一个点
- 原生主机已退出。
- 在 Chrome 读取消息之前,通向本地消息传递主机的管道已损坏。这是 可能是由原生消息传递主机发起的。
- 找不到指定的原生消息传递主机。
- 名称在扩展程序和清单文件中是否拼写正确?
- 清单是否位于正确的目录中并且使用了正确的名称?请参阅原生消息传递主机 location。
- 清单文件的格式是否正确?具体而言,JSON 语法是否正确? 值是否与原生消息传递主机清单的定义相符?
path
中指定的文件是否存在?在 Windows 上,路径可能是相对路径;但在 OS X 和 Linux 上 路径必须是绝对路径
- 原生消息传递主机主机名未注册。(仅限 Windows)
<ph type="x-smartling-placeholder">
- </ph>
- 在 Windows 注册表中找不到原生消息传递主机。使用
regedit
进行核查 键是否确实已创建,以及键是否与 native 消息主机位置。
- 在 Windows 注册表中找不到原生消息传递主机。使用
- 禁止访问指定的本地消息传递主机。
allowed_origins
中是否列出了扩展程序的来源?
- 与本地消息传递主机通信时出错。
- 这是一个很常见的错误,表示通信协议的实现不正确 本地消息传递主机中。
- 确保
stdout
中的所有输出均符合原生消息传递协议。如果您想 如需输出一些数据以进行调试,请将其写入stderr
。 - 确保 32 位消息长度采用平台的原生整数格式(小端字节序) / big-endian)。
- 消息长度不得超过 1024*1024。
- 消息大小必须等于消息中的字节数。这可能不同于 “长度”因为字符可以用多个字节表示。
- 仅适用于 Windows:确保程序的 I/O 模式设置为
O_BINARY
。默认情况下,I/O 模式为O_TEXT
,这会破坏邮件格式,因为换行符 (\n
=0A
) 替换为 Windows 样式的行结尾 (\r\n
=0D 0A
)。您可以使用__setmode
设置 I/O 模式。