From 8018cd2ecf2072f52887f6b1d933c0fdbf7f10ee Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 12 Mar 2025 07:22:34 -0300 Subject: [PATCH] wip custom protocol --- crates/tauri-runtime-cef/Cargo.toml | 2 +- crates/tauri-runtime-cef/src/cef_impl.rs | 325 ++++++++++++++++------- crates/tauri-runtime-cef/src/lib.rs | 3 +- crates/tauri/Cargo.toml | 1 + 4 files changed, 229 insertions(+), 102 deletions(-) diff --git a/crates/tauri-runtime-cef/Cargo.toml b/crates/tauri-runtime-cef/Cargo.toml index e115407b8..f7fbb8a7c 100644 --- a/crates/tauri-runtime-cef/Cargo.toml +++ b/crates/tauri-runtime-cef/Cargo.toml @@ -22,4 +22,4 @@ gtk = { version = "0.18", features = ["v3_24"] } [features] devtools = [] -macos-private-api = [] +macos-private-api = ["tauri-runtime/macos-private-api"] diff --git a/crates/tauri-runtime-cef/src/cef_impl.rs b/crates/tauri-runtime-cef/src/cef_impl.rs index 3a9378715..f901d2288 100644 --- a/crates/tauri-runtime-cef/src/cef_impl.rs +++ b/crates/tauri-runtime-cef/src/cef_impl.rs @@ -14,6 +14,81 @@ use tauri_runtime::{ use crate::{AppWindow, CefRuntime, Message}; +macro_rules! cef_object { + ($struct: ident, $inner: ty, $cef_obj: ident, $wrap_trait: ty) => { + pub struct $struct { + object: *mut RcImpl, + inner: $inner, + } + + impl Rc for $struct { + fn as_base(&self) -> &cef_dll_sys::cef_base_ref_counted_t { + unsafe { + let base = &*self.object; + std::mem::transmute(&base.cef_object) + } + } + } + + impl $wrap_trait for $struct { + fn wrap_rc(&mut self, object: *mut RcImpl) { + self.object = object; + } + } + + impl Clone for $struct { + fn clone(&self) -> Self { + let object = unsafe { + let rc_impl = &mut *self.object; + rc_impl.interface.add_ref(); + self.object + }; + + Self { + object, + inner: self.inner.clone(), + } + } + } + }; + ($struct: ident, $inner: ty, $cef_obj: ident, $wrap_trait: ty) => { + pub struct $struct { + object: *mut RcImpl, + inner: $inner, + } + + impl Rc for $struct { + fn as_base(&self) -> &cef_dll_sys::cef_base_ref_counted_t { + unsafe { + let base = &*self.object; + std::mem::transmute(&base.cef_object) + } + } + } + + impl $wrap_trait for $struct { + fn wrap_rc(&mut self, object: *mut RcImpl) { + self.object = object; + } + } + + impl Clone for $struct { + fn clone(&self) -> Self { + let object = unsafe { + let rc_impl = &mut *self.object; + rc_impl.interface.add_ref(); + self.object + }; + + Self { + object, + inner: self.inner.clone(), + } + } + } + }; +} + #[derive(Clone)] pub struct Context { pub windows: Arc>>, @@ -42,101 +117,38 @@ impl Context { } } -pub struct TauriApp { - object: *mut RcImpl, - context: Context, -} +cef_object!(TauriApp, Context, _cef_app_t, WrapApp); impl TauriApp { pub fn new(context: Context) -> App { App::new(Self { object: std::ptr::null_mut(), - context, + inner: context, }) } } -impl WrapApp for TauriApp { - fn wrap_rc(&mut self, object: *mut RcImpl) { - self.object = object; - } -} - -impl Clone for TauriApp { - fn clone(&self) -> Self { - let object = unsafe { - let rc_impl = &mut *self.object; - rc_impl.interface.add_ref(); - self.object - }; - let context = self.context.clone(); - - Self { object, context } - } -} - -impl Rc for TauriApp { - fn as_base(&self) -> &cef_dll_sys::cef_base_ref_counted_t { - unsafe { - let base = &*self.object; - std::mem::transmute(&base.cef_object) - } - } -} - impl ImplApp for TauriApp { fn get_raw(&self) -> *mut cef_dll_sys::_cef_app_t { - self.object as *mut cef_dll_sys::_cef_app_t + self.object.cast() } fn get_browser_process_handler(&self) -> Option { - Some(AppBrowserProcessHandler::new(self.context.clone())) + Some(AppBrowserProcessHandler::new(self.inner.clone())) } } -struct AppBrowserProcessHandler { - object: *mut RcImpl, - context: Context, -} +cef_object!(AppBrowserProcessHandler, Context, cef_browser_process_handler_t, WrapBrowserProcessHandler); impl AppBrowserProcessHandler { pub fn new(context: Context) -> BrowserProcessHandler { BrowserProcessHandler::new(Self { object: std::ptr::null_mut(), - context, + inner: context, }) } } -impl Rc for AppBrowserProcessHandler { - fn as_base(&self) -> &cef_dll_sys::cef_base_ref_counted_t { - unsafe { - let base = &*self.object; - std::mem::transmute(&base.cef_object) - } - } -} - -impl WrapBrowserProcessHandler for AppBrowserProcessHandler { - fn wrap_rc(&mut self, object: *mut RcImpl) { - self.object = object; - } -} - -impl Clone for AppBrowserProcessHandler { - fn clone(&self) -> Self { - let object = unsafe { - let rc_impl = &mut *self.object; - rc_impl.interface.add_ref(); - rc_impl - }; - - let context = self.context.clone(); - - Self { object, context } - } -} - impl ImplBrowserProcessHandler for AppBrowserProcessHandler { fn get_raw(&self) -> *mut cef_dll_sys::_cef_browser_process_handler_t { self.object.cast() @@ -145,47 +157,160 @@ impl ImplBrowserProcessHandler for AppBrowserProcessHandler { // The real lifespan of cef starts from `on_context_initialized`, so all the cef objects should be manipulated after that. fn on_context_initialized(&self) { println!("cef context initialized"); - (self.context.callback.borrow_mut())(RunEvent::Ready); + (self.inner.callback.borrow_mut())(RunEvent::Ready); + } + + fn get_default_request_context_handler(&self) -> Option { + Some(WebRequestContextHandler::new()) + } + + fn get_default_client(&self) -> Option { + None + //Some(BrowserClient::new()) } } -struct BrowserClient(*mut RcImpl); +cef_object!( + WebRequestContextHandler, + (), + _cef_request_context_handler_t, + WrapRequestContextHandler +); + +impl WebRequestContextHandler { + fn new() -> RequestContextHandler { + RequestContextHandler::new(Self { + object: std::ptr::null_mut(), + inner: (), + }) + } +} + +impl ImplRequestContextHandler for WebRequestContextHandler { + fn get_raw(&self) -> *mut cef_dll_sys::_cef_request_context_handler_t { + self.object.cast() + } + + fn get_resource_request_handler( + &self, + browser: Option<&mut impl ImplBrowser>, + frame: Option<&mut impl ImplFrame>, + request: Option<&mut impl ImplRequest>, + is_navigation: ::std::os::raw::c_int, + is_download: ::std::os::raw::c_int, + request_initiator: Option<&CefStringUtf16>, + disable_default_handling: Option<&mut ::std::os::raw::c_int>, + ) -> Option { + Some(WebResourceRequestHandler::new()) + } +} + +cef_object!( + WebResourceRequestHandler, + (), + _cef_resource_request_handler_t, + WrapResourceRequestHandler +); + +impl WebResourceRequestHandler { + fn new() -> ResourceRequestHandler { + ResourceRequestHandler::new(Self { + object: std::ptr::null_mut(), + inner: (), + }) + } +} + +impl ImplResourceRequestHandler for WebResourceRequestHandler { + fn get_resource_handler( + &self, + browser: Option<&mut impl ImplBrowser>, + frame: Option<&mut impl ImplFrame>, + request: Option<&mut impl ImplRequest>, + ) -> Option { + println!( + "get_resource_handler {:?}", + request + .as_ref() + .map(|r| r.get_url().map(|s| CefStringUtf8::from(&s).to_string())) + ); + None + } + + fn on_before_resource_load( + &self, + browser: Option<&mut impl ImplBrowser>, + frame: Option<&mut impl ImplFrame>, + request: Option<&mut impl ImplRequest>, + callback: Option<&mut impl ImplCallback>, + ) -> ReturnValue { + println!( + "on_before_resource_load {:?}", + request + .as_ref() + .map(|r| r.get_url().map(|s| CefStringUtf8::from(&s).to_string())) + ); + Default::default() + } + + fn get_raw(&self) -> *mut cef_dll_sys::_cef_resource_request_handler_t { + self.object.cast() + } +} + +cef_object!(BrowserClient, (), _cef_client_t, WrapClient); impl BrowserClient { pub fn new() -> Client { - Client::new(Self(std::ptr::null_mut())) - } -} - -impl WrapClient for BrowserClient { - fn wrap_rc(&mut self, object: *mut RcImpl) { - self.0 = object; - } -} - -impl Clone for BrowserClient { - fn clone(&self) -> Self { - unsafe { - let rc_impl = &mut *self.0; - rc_impl.interface.add_ref(); - } - - Self(self.0) - } -} - -impl Rc for BrowserClient { - fn as_base(&self) -> &cef_dll_sys::cef_base_ref_counted_t { - unsafe { - let base = &*self.0; - std::mem::transmute(&base.cef_object) - } + Client::new(Self { + object: std::ptr::null_mut(), + inner: (), + }) } } impl ImplClient for BrowserClient { fn get_raw(&self) -> *mut cef_dll_sys::_cef_client_t { - self.0 as *mut cef_dll_sys::_cef_client_t + self.object.cast() + } + + fn get_request_handler(&self) -> Option { + Some(WebRequestHandler::new()) + } +} + +cef_object!( + WebRequestHandler, + (), + _cef_request_handler_t, + WrapRequestHandler +); + +impl WebRequestHandler { + fn new() -> RequestHandler { + RequestHandler::new(Self { + object: std::ptr::null_mut(), + inner: (), + }) + } +} + +impl ImplRequestHandler for WebRequestHandler { + fn get_raw(&self) -> *mut cef_dll_sys::_cef_request_handler_t { + self.object.cast() + } + + fn get_resource_request_handler( + &self, + browser: Option<&mut impl ImplBrowser>, + frame: Option<&mut impl ImplFrame>, + request: Option<&mut impl ImplRequest>, + is_navigation: ::std::os::raw::c_int, + is_download: ::std::os::raw::c_int, + request_initiator: Option<&CefStringUtf16>, + disable_default_handling: Option<&mut ::std::os::raw::c_int>, + ) -> Option { + Some(WebResourceRequestHandler::new()) } } @@ -243,7 +368,7 @@ impl ImplViewDelegate for AppWindowDelegate { } fn get_raw(&self) -> *mut cef_dll_sys::_cef_view_delegate_t { - self.base as *mut cef_dll_sys::_cef_view_delegate_t + self.base.cast() } } diff --git a/crates/tauri-runtime-cef/src/lib.rs b/crates/tauri-runtime-cef/src/lib.rs index dc6890ec8..db74f3f20 100644 --- a/crates/tauri-runtime-cef/src/lib.rs +++ b/crates/tauri-runtime-cef/src/lib.rs @@ -986,7 +986,8 @@ impl CefRuntime { #[cfg(target_os = "macos")] let _loader = { - let loader = library_loader::LibraryLoader::new(&std::env::current_exe().unwrap(), false); + let loader = + cef::library_loader::LibraryLoader::new(&std::env::current_exe().unwrap(), false); assert!(loader.load()); loader }; diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml index d234f5cb9..4806709f2 100644 --- a/crates/tauri/Cargo.toml +++ b/crates/tauri/Cargo.toml @@ -213,6 +213,7 @@ process-relaunch-dangerous-allow-symlink-macos = [ macos-private-api = [ "tauri-runtime/macos-private-api", "tauri-runtime-wry?/macos-private-api", + "tauri-runtime-cef?/macos-private-api", ] webview-data-url = ["data-url", "tauri-utils/html-manipulation"] protocol-asset = ["http-range"]