参考文档
前情提要:“WebUI” is a term used to loosely describe parts of Chrome's UI implemented with web technologies (i.e. HTML, CSS, JavaScript).
💡 方法1. Mojo - 推荐
JS发送消息给C++
- <C++> 定义Mojo接口:在
.mojom
文件中定义一个通用的通信接口。
// example.mojom module example.mojom; interface Service { // 从JS到C++的消息。 DoSomething(string data); }
- <C++> 生成绑定代码:使用Mojo构建工具自动生成C++和TypeScript的绑定代码。
- <C++> 实现接口:在C++端实现Mojo接口定义的方法。
// example_service_impl.h class ExampleServiceImpl : public example::mojom::Service { void DoSomething(const std::string& data) override { // 处理从JS发送的数据。 std::cout << "Received data from JS: " << data << std::endl; } };
- <JS> 使用Mojo接口:在JS端,通过生成的TypeScript绑定代码使用Mojo接口。
// example.ts // 创建Mojo接口的远程对象。 const serviceRemote = new example.mojom.ServiceRemote(); const serviceReceiver = new example.mojom.ServiceReceiver( serviceRemote.$.bindNewPipeAndPassReceiver() ); // 使用Mojo接口发送消息。 serviceRemote.doSomething("Hello from JS!");
JS接收C++发来的消息
- <C++> 触发接口调用:在C++端,当需要向JS发送消息时,调用Mojo接口的相应方法。
// example_service_impl.cc void NotifyJS(const std::string& message) { // 通过Mojo接口发送消息给JS。 service_->DoSomething(message); }
- <JS> 监听接口事件:JS端通过Mojo接口的异步事件监听器接收消息。
// example.ts // 设置异步回调。 serviceRemote.doSomethingCallback = (response) => { // 响应从C++接收到的数据。 console.log(`Response from C++: ${response}`); };
- <JS> 使用TypeScript Promises:对于需要响应的操作,使用Promise来简化异步通信。
// example.ts function sendRequest(data: string): Promise<string> { return new Promise((resolve, reject) => { // 设置一次性的回调。 const onceCallback = (response) => { serviceRemote.doSomethingCallback = null; resolve(response); }; // 发送请求并设置回调。 serviceRemote.doSomething(data, onceCallback); }); } sendRequest("Request from JS").then((response) => { alert(response); });
- <C++> 响应Promise:C++端在完成异步操作后,使用Mojo的回调机制来响应JS的Promise。
// example_service_impl.cc void DoSomething(const std::string& data, const DoSomethingCallback& callback) override { // 模拟异步操作。 std::thread([=]() { // 假设这里是一些异步操作。 std::this_thread::sleep_for(std::chrono::seconds(1)); // 响应JS的请求。 callback("Response from C++"); }).detach(); }
💡 方法2. WebUIMessageHandler + chrome.send()
JS发送消息给C++
- <JS> 使用
chrome.send()
函数: 在JS代码中,当需要向C++发送消息时,可以使用chrome.send()
函数。这个函数接受两个参数:消息的名称和一个参数列表。
// 在JS中,调用chrome.send()发送消息到C++。 chrome.send('messageName', [arg1, arg2, ...]);
- <C++> 创建
WebUIMessageHandler
类: 在C++端,WebUIMessageHandler
类用于处理从JS发送过来的消息。我们需要创建一个WebUIMessageHandler
的子类,并重写RegisterMessages()
方法来注册可以处理的消息和对应的回调函数。
class MyWebUIMessageHandler : public WebUIMessageHandler { public: void RegisterMessages() override { web_ui()->RegisterMessageCallback("messageName", base::BindRepeating(&MyWebUIMessageHandler::HandleMessageName, base::Unretained(this))); } private: void HandleMessageName(const base::Value::List& args) { // 处理接收到的参数。 } };
- <C++> 在
WebUIController
中注册消息处理器: 创建WebUIMessageHandler
的实例,并在WebUIController
的实现中注册该处理器。
class MyWebUIController : public WebUIController { public: explicit MyWebUIController(content::WebUI* web_ui) : WebUIController(web_ui), message_handler_(new MyWebUIMessageHandler()) { message_handler_->RegisterMessages(); } private: std::unique_ptr<MyWebUIMessageHandler> message_handler_; };
JS接收C++发来的消息
- 方法1
- <C++> 调用
CallJavascriptFunction()
: 当C++需要在JS中执行一个函数时,可以使用CallJavascriptFunction()
。这个方法允许C++端调用JS中定义的全局函数。 - <JS> 定义相应的函数: 在JS代码中,需要定义C++可能会调用的函数。
// 在C++中,通过CallJavascriptFunction()调用JS中的函数。 CallJavascriptFunction("functionNameInJS", base::Value("argument"));
// 在JS中定义一个函数,C++可能会调用这个函数。 function functionNameInJS(argument) { // 根据参数执行相应的操作。 }
- 方法2
- <C++> 使用
FireWebUIListener()
: C++端还可以使用FireWebUIListener()
来触发在JS端注册的事件监听器。 - <JS> 监听事件: JS可以使用
addWebUiListener()
来监听由C++触发的事件。
// 在C++中触发一个事件监听器。 void MyWebUIMessageHandler::TriggerEvent() { FireWebUIListener("eventName", base::Value("eventData")); }
// 在JS中监听一个事件。 addWebUiListener('eventName', function(eventData) { // 响应事件和数据。 });
Comments