Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C++ 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改造浏览器底层的开发者。
🔧 典型交互场景分类
场景 | 描述 | 技术路径 |
---|---|---|
1️⃣ WebUI 页面与 C++ 后端交互 | 如设置页、扩展页等 | WebUI <-> WebUIMessageHandler |
2️⃣ 页面 JS 与 Extension 后端 | 如插件调用 chrome.runtime.sendMessage | JS <-> Mojo / native extension API |
3️⃣ 页面 JS 与 Native 功能交互 | 如调用浏览器硬件能力 | JS <-> Mojo / C++ Impl |
📍 框架组件总览图
1️⃣ WebUI 页面交互机制详解
▶ 构成组件
-
前端:
WebUI HTML + JS
页面,嵌入在chrome://
或browser://
-
后端:继承自
content::WebUIController
+WebUIMessageHandler
▶ 流程详解
-
前端 JS 发起调用:
chrome.send("MyFunctionName", [arg1, arg2]);
-
后端 C++ 注册 handler:
void MyHandler::RegisterMessages() override {web_ui()->RegisterMessageCallback("MyFunctionName",base::BindRepeating(&MyHandler::OnMyFunction, base::Unretained(this))); }void MyHandler::OnMyFunction(const base::Value::List& args) {// 处理参数,回调 JSFireWebUIListener("on-data-ready", data); }
-
后端回调前端:
cr.addWebUIListener("on-data-ready", (data) => { ... });
▶ 应用场景
-
设置页 (
chrome://settings
) -
下载页、扩展页、历史页等
2️⃣ Extension 与 Native 通信机制
▶ 构成组件
-
JS:使用
chrome.runtime.sendMessage
或chrome.extension.getBackgroundPage()
-
后端:继承
ExtensionFunction
并注册到ExtensionFunctionRegistry
▶ 流程示意
chrome.runtime.sendMessage({cmd: "doSomething"}, function(response) {console.log("Response:", response);
});// C++ Extension Function 实现
class DoSomethingFunction : public ExtensionFunction {public:ResponseAction Run() override {// 处理逻辑...return RespondNow(OneArgument(base::Value("OK")));}
};// 注册宏
EXTENSION_FUNCTION_NAME("extensionInternal.doSomething")
✅ Chrome 扩展调用的是基于 IPC 和 Mojo 的通道,最终由浏览器进程分发请求到对应 ExtensionFunction。
3️⃣ Mojo 通信机制(JS <-> Mojo <-> C++)
适用于较底层的交互,如性能数据、打印、系统 API 等。
▶ 构成组件
-
前端:JS Binding(
*.mojom-webui.js
) -
后端:C++ Mojo Impl(绑定接口实现)
-
通道:
RenderFrameHost->GetRemoteInterfaces()
or WebUIDataSourceWithMojo
▶ 示例流程
// JS 侧
mojo.bindInterface('my_namespace.MyInterface');
myInterface.doSomething().then((result) => { ... });// mojom 定义
interface MyInterface {DoSomething() => (string result);
}// C++ 实现并绑定
class MyInterfaceImpl : public mojom::MyInterface {public:void DoSomething(DoSomethingCallback callback) override {std::move(callback).Run("Done!");}
};web_ui()->BindInterface(std::make_unique<MyInterfaceImpl>());
🔄 JS 与 C++ 通信方式对比总结
通信方式 | 特点 | 适用场景 |
---|---|---|
chrome.send() | 简单、基于 WebUI Message | 内部页面(如 chrome://* ) |
chrome.runtime.sendMessage() | 基于扩展 IPC,功能强大 | 插件调用浏览器能力 |
Mojo | 模块化、高性能、支持多进程 | 深层系统通信(如 Debug、音频) |