Skip to content

Commit 83d39fb

Browse files
timon-schellingadamgerhantTrueDoctor
authored
Desktop: Cleaner CEF bidirectional message implementation (#2950)
* Rename CEF implementations to match the process they are called in * Rename CEF implementations to match the process they are called in * Implement ipc abstraction * Call js function `receiveNativeMessage` for all SendToJS ipc messages * Allow js to call `sendNativeMessage` for sending messages to the browser process Co-authored-by: Adam <[email protected]> Co-authored-by: Dennis Kobert <[email protected]> * Fix missing safety consideration --------- Co-authored-by: Adam <[email protected]> Co-authored-by: Dennis Kobert <[email protected]>
1 parent 7bdf167 commit 83d39fb

12 files changed

+469
-80
lines changed

desktop/src/cef.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ mod context;
88
mod dirs;
99
mod input;
1010
mod internal;
11+
mod ipc;
1112
mod scheme_handler;
13+
mod utility;
1214

1315
pub(crate) use context::{Context, InitError, Initialized, Setup, SetupError};
1416
use winit::event_loop::EventLoopProxy;
@@ -19,6 +21,7 @@ pub(crate) trait CefEventHandler: Clone {
1921
/// Scheudule the main event loop to run the cef event loop after the timeout
2022
/// [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
2123
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
24+
fn receive_web_message(&self, message: &[u8]);
2225
}
2326

2427
#[derive(Clone, Copy)]
@@ -116,4 +119,6 @@ impl CefEventHandler for CefHandler {
116119
fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) {
117120
let _ = self.event_loop_proxy.send_event(CustomEvent::ScheduleBrowserWork(scheduled_time));
118121
}
122+
123+
fn receive_web_message(&self, message: &[u8]) {}
119124
}

desktop/src/cef/context.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use winit::event::WindowEvent;
77
use crate::cef::dirs::{cef_cache_dir, cef_data_dir};
88

99
use super::input::InputState;
10+
use super::ipc::{MessageType, SendMessage};
1011
use super::scheme_handler::{FRONTEND_DOMAIN, GRAPHITE_SCHEME};
1112
use super::{CefEventHandler, input};
1213

13-
use super::internal::{AppImpl, ClientImpl, NonBrowserAppImpl, RenderHandlerImpl};
14+
use super::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderHandlerImpl, RenderProcessAppImpl};
1415

1516
pub(crate) struct Setup {}
1617
pub(crate) struct Initialized {}
@@ -42,7 +43,7 @@ impl Context<Setup> {
4243

4344
if !is_browser_process {
4445
let process_type = CefString::from(&cmd.switch_value(Some(&switch)));
45-
let mut app = NonBrowserAppImpl::app();
46+
let mut app = RenderProcessAppImpl::app();
4647
let ret = execute_process(Some(args.as_main_args()), Some(&mut app), std::ptr::null_mut());
4748
if ret >= 0 {
4849
return Err(SetupError::SubprocessFailed(process_type.to_string()));
@@ -70,7 +71,7 @@ impl Context<Setup> {
7071
};
7172

7273
// Attention! Wrapping this in an extra App is necessary, otherwise the program still compiles but segfaults
73-
let mut cef_app = App::new(AppImpl::new(event_handler.clone()));
74+
let mut cef_app = App::new(BrowserProcessAppImpl::new(event_handler.clone()));
7475

7576
let result = initialize(Some(self.args.as_main_args()), Some(&settings), Some(&mut cef_app), std::ptr::null_mut());
7677
if result != 1 {
@@ -81,8 +82,8 @@ impl Context<Setup> {
8182
return Err(InitError::InitializationFailed(cef_exit_code));
8283
}
8384

84-
let render_handler = RenderHandlerImpl::new(event_handler.clone());
85-
let mut client = Client::new(ClientImpl::new(RenderHandler::new(render_handler)));
85+
let render_handler = RenderHandler::new(RenderHandlerImpl::new(event_handler.clone()));
86+
let mut client = Client::new(BrowserProcessClientImpl::new(render_handler, event_handler.clone()));
8687

8788
let url = CefString::from(format!("{GRAPHITE_SCHEME}://{FRONTEND_DOMAIN}/").as_str());
8889

@@ -129,6 +130,10 @@ impl Context<Initialized> {
129130
browser.host().unwrap().was_resized();
130131
}
131132
}
133+
134+
pub(crate) fn send_web_message(&self, message: &[u8]) {
135+
self.send_message(MessageType::SendToJS, message);
136+
}
132137
}
133138

134139
impl<S: ContextState> Drop for Context<S> {

desktop/src/cef/internal.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
mod app;
1+
mod browser_process_app;
2+
mod browser_process_client;
23
mod browser_process_handler;
3-
mod client;
4-
mod non_browser_app;
54
mod render_handler;
5+
mod render_process_app;
6+
mod render_process_handler;
7+
mod render_process_v8_handler;
68

7-
pub(crate) use app::AppImpl;
8-
pub(crate) use client::ClientImpl;
9-
pub(crate) use non_browser_app::NonBrowserAppImpl;
9+
pub(crate) use browser_process_app::BrowserProcessAppImpl;
10+
pub(crate) use browser_process_client::BrowserProcessClientImpl;
1011
pub(crate) use render_handler::RenderHandlerImpl;
12+
pub(crate) use render_process_app::RenderProcessAppImpl;

desktop/src/cef/internal/app.rs renamed to desktop/src/cef/internal/browser_process_app.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ use cef::sys::{_cef_app_t, cef_base_ref_counted_t};
55
use cef::{BrowserProcessHandler, CefString, ImplApp, ImplCommandLine, SchemeRegistrar, WrapApp};
66

77
use crate::cef::CefEventHandler;
8+
89
use crate::cef::scheme_handler::GraphiteSchemeHandlerFactory;
910

1011
use super::browser_process_handler::BrowserProcessHandlerImpl;
1112

12-
pub(crate) struct AppImpl<H: CefEventHandler> {
13+
pub(crate) struct BrowserProcessAppImpl<H: CefEventHandler> {
1314
object: *mut RcImpl<_cef_app_t, Self>,
1415
event_handler: H,
1516
}
16-
impl<H: CefEventHandler + Clone> AppImpl<H> {
17+
impl<H: CefEventHandler + Clone> BrowserProcessAppImpl<H> {
1718
pub(crate) fn new(event_handler: H) -> Self {
1819
Self {
1920
object: std::ptr::null_mut(),
@@ -22,7 +23,7 @@ impl<H: CefEventHandler + Clone> AppImpl<H> {
2223
}
2324
}
2425

25-
impl<H: CefEventHandler + Clone> ImplApp for AppImpl<H> {
26+
impl<H: CefEventHandler + Clone> ImplApp for BrowserProcessAppImpl<H> {
2627
fn browser_process_handler(&self) -> Option<BrowserProcessHandler> {
2728
Some(BrowserProcessHandler::new(BrowserProcessHandlerImpl::new(self.event_handler.clone())))
2829
}
@@ -58,7 +59,7 @@ impl<H: CefEventHandler + Clone> ImplApp for AppImpl<H> {
5859
}
5960
}
6061

61-
impl<H: CefEventHandler + Clone> Clone for AppImpl<H> {
62+
impl<H: CefEventHandler + Clone> Clone for BrowserProcessAppImpl<H> {
6263
fn clone(&self) -> Self {
6364
unsafe {
6465
let rc_impl = &mut *self.object;
@@ -70,15 +71,15 @@ impl<H: CefEventHandler + Clone> Clone for AppImpl<H> {
7071
}
7172
}
7273
}
73-
impl<H: CefEventHandler> Rc for AppImpl<H> {
74+
impl<H: CefEventHandler> Rc for BrowserProcessAppImpl<H> {
7475
fn as_base(&self) -> &cef_base_ref_counted_t {
7576
unsafe {
7677
let base = &*self.object;
7778
std::mem::transmute(&base.cef_object)
7879
}
7980
}
8081
}
81-
impl<H: CefEventHandler + Clone> WrapApp for AppImpl<H> {
82+
impl<H: CefEventHandler + Clone> WrapApp for BrowserProcessAppImpl<H> {
8283
fn wrap_rc(&mut self, object: *mut RcImpl<_cef_app_t, Self>) {
8384
self.object = object;
8485
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use cef::rc::{Rc, RcImpl};
2+
use cef::sys::{_cef_client_t, cef_base_ref_counted_t};
3+
use cef::{ImplClient, RenderHandler, WrapClient};
4+
5+
use crate::cef::CefEventHandler;
6+
use crate::cef::ipc::{MessageType, UnpackMessage, UnpackedMessage};
7+
8+
pub(crate) struct BrowserProcessClientImpl<H: CefEventHandler> {
9+
object: *mut RcImpl<_cef_client_t, Self>,
10+
render_handler: RenderHandler,
11+
event_handler: H,
12+
}
13+
impl<H: CefEventHandler> BrowserProcessClientImpl<H> {
14+
pub(crate) fn new(render_handler: RenderHandler, event_handler: H) -> Self {
15+
Self {
16+
object: std::ptr::null_mut(),
17+
render_handler,
18+
event_handler,
19+
}
20+
}
21+
}
22+
23+
impl<H: CefEventHandler> ImplClient for BrowserProcessClientImpl<H> {
24+
fn on_process_message_received(
25+
&self,
26+
_browser: Option<&mut cef::Browser>,
27+
_frame: Option<&mut cef::Frame>,
28+
_source_process: cef::ProcessId,
29+
message: Option<&mut cef::ProcessMessage>,
30+
) -> ::std::os::raw::c_int {
31+
let unpacked_message = unsafe { message.and_then(|m| m.unpack()) };
32+
match unpacked_message {
33+
Some(UnpackedMessage {
34+
message_type: MessageType::SendToNative,
35+
data,
36+
}) => self.event_handler.receive_web_message(data),
37+
38+
_ => {
39+
tracing::error!("Unexpected message type received in browser process");
40+
return 0;
41+
}
42+
}
43+
1
44+
}
45+
46+
fn render_handler(&self) -> Option<RenderHandler> {
47+
Some(self.render_handler.clone())
48+
}
49+
50+
fn get_raw(&self) -> *mut _cef_client_t {
51+
self.object.cast()
52+
}
53+
}
54+
55+
impl<H: CefEventHandler> Clone for BrowserProcessClientImpl<H> {
56+
fn clone(&self) -> Self {
57+
unsafe {
58+
let rc_impl = &mut *self.object;
59+
rc_impl.interface.add_ref();
60+
}
61+
Self {
62+
object: self.object,
63+
render_handler: self.render_handler.clone(),
64+
event_handler: self.event_handler.clone(),
65+
}
66+
}
67+
}
68+
impl<H: CefEventHandler> Rc for BrowserProcessClientImpl<H> {
69+
fn as_base(&self) -> &cef_base_ref_counted_t {
70+
unsafe {
71+
let base = &*self.object;
72+
std::mem::transmute(&base.cef_object)
73+
}
74+
}
75+
}
76+
impl<H: CefEventHandler> WrapClient for BrowserProcessClientImpl<H> {
77+
fn wrap_rc(&mut self, object: *mut RcImpl<_cef_client_t, Self>) {
78+
self.object = object;
79+
}
80+
}

desktop/src/cef/internal/client.rs

Lines changed: 0 additions & 52 deletions
This file was deleted.

desktop/src/cef/internal/non_browser_app.rs renamed to desktop/src/cef/internal/render_process_app.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,58 @@
11
use cef::rc::{Rc, RcImpl};
22
use cef::sys::{_cef_app_t, cef_base_ref_counted_t};
3-
use cef::{App, ImplApp, SchemeRegistrar, WrapApp};
3+
use cef::{App, ImplApp, RenderProcessHandler, SchemeRegistrar, WrapApp};
44

5+
use super::render_process_handler::RenderProcessHandlerImpl;
56
use crate::cef::scheme_handler::GraphiteSchemeHandlerFactory;
67

7-
pub(crate) struct NonBrowserAppImpl {
8+
pub(crate) struct RenderProcessAppImpl {
89
object: *mut RcImpl<_cef_app_t, Self>,
10+
render_process_handler: RenderProcessHandler,
911
}
10-
impl NonBrowserAppImpl {
12+
impl RenderProcessAppImpl {
1113
pub(crate) fn app() -> App {
12-
App::new(Self { object: std::ptr::null_mut() })
14+
App::new(Self {
15+
object: std::ptr::null_mut(),
16+
render_process_handler: RenderProcessHandler::new(RenderProcessHandlerImpl::new()),
17+
})
1318
}
1419
}
1520

16-
impl ImplApp for NonBrowserAppImpl {
21+
impl ImplApp for RenderProcessAppImpl {
1722
fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) {
1823
GraphiteSchemeHandlerFactory::register_schemes(registrar);
1924
}
2025

26+
fn render_process_handler(&self) -> Option<RenderProcessHandler> {
27+
Some(self.render_process_handler.clone())
28+
}
29+
2130
fn get_raw(&self) -> *mut _cef_app_t {
2231
self.object.cast()
2332
}
2433
}
2534

26-
impl Clone for NonBrowserAppImpl {
35+
impl Clone for RenderProcessAppImpl {
2736
fn clone(&self) -> Self {
2837
unsafe {
2938
let rc_impl = &mut *self.object;
3039
rc_impl.interface.add_ref();
3140
}
32-
Self { object: self.object }
41+
Self {
42+
object: self.object,
43+
render_process_handler: self.render_process_handler.clone(),
44+
}
3345
}
3446
}
35-
impl Rc for NonBrowserAppImpl {
47+
impl Rc for RenderProcessAppImpl {
3648
fn as_base(&self) -> &cef_base_ref_counted_t {
3749
unsafe {
3850
let base = &*self.object;
3951
std::mem::transmute(&base.cef_object)
4052
}
4153
}
4254
}
43-
impl WrapApp for NonBrowserAppImpl {
55+
impl WrapApp for RenderProcessAppImpl {
4456
fn wrap_rc(&mut self, object: *mut RcImpl<_cef_app_t, Self>) {
4557
self.object = object;
4658
}

0 commit comments

Comments
 (0)