diff --git a/.gitignore b/.gitignore index 8a26db3..b5e851c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ target/ .idea/ book/ .DS_Store**/.DS_Store +.claude/memo.md +docs/plans/ \ No newline at end of file diff --git a/crates/bevy_cef_core/src/browser_process.rs b/crates/bevy_cef_core/src/browser_process.rs index 4c4ed69..b7ff9c6 100644 --- a/crates/bevy_cef_core/src/browser_process.rs +++ b/crates/bevy_cef_core/src/browser_process.rs @@ -2,6 +2,7 @@ mod app; mod browser_process_handler; mod browsers; mod client_handler; +mod command_line_config; mod context_menu_handler; mod display_handler; mod localhost; @@ -13,6 +14,7 @@ pub use app::*; pub use browser_process_handler::*; pub use browsers::*; pub use client_handler::*; +pub use command_line_config::*; pub use context_menu_handler::*; pub use localhost::*; pub use message_pump::*; diff --git a/crates/bevy_cef_core/src/browser_process/app.rs b/crates/bevy_cef_core/src/browser_process/app.rs index 18a4bba..3171f36 100644 --- a/crates/bevy_cef_core/src/browser_process/app.rs +++ b/crates/bevy_cef_core/src/browser_process/app.rs @@ -1,3 +1,4 @@ +use crate::browser_process::CommandLineConfig; use crate::browser_process::MessageLoopTimer; use crate::browser_process::browser_process_handler::BrowserProcessHandlerBuilder; use crate::util::{SCHEME_CEF, cef_scheme_flags}; @@ -15,13 +16,18 @@ use std::sync::mpsc::Sender; pub struct BrowserProcessAppBuilder { object: *mut RcImpl<_cef_app_t, Self>, message_loop_working_requester: Sender, + config: CommandLineConfig, } impl BrowserProcessAppBuilder { - pub fn build(message_loop_working_requester: Sender) -> cef::App { + pub fn build( + message_loop_working_requester: Sender, + config: CommandLineConfig, + ) -> cef::App { cef::App::new(Self { object: core::ptr::null_mut(), message_loop_working_requester, + config, }) } } @@ -36,6 +42,7 @@ impl Clone for BrowserProcessAppBuilder { Self { object, message_loop_working_requester: self.message_loop_working_requester.clone(), + config: self.config.clone(), } } } @@ -58,10 +65,14 @@ impl ImplApp for BrowserProcessAppBuilder { let Some(command_line) = command_line else { return; }; - command_line.append_switch(Some(&"use-mock-keychain".into())); - // command_line.append_switch(Some(&"disable-gpu".into())); - // command_line.append_switch(Some(&"disable-gpu-compositing".into())); - // command_line.append_switch(Some(&" disable-gpu-shader-disk-cache".into())); + + for switch in &self.config.switches { + command_line.append_switch(Some(&(*switch).into())); + } + + for (name, value) in &self.config.switch_values { + command_line.append_switch_with_value(Some(&(*name).into()), Some(&(*value).into())); + } } fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) { diff --git a/crates/bevy_cef_core/src/browser_process/command_line_config.rs b/crates/bevy_cef_core/src/browser_process/command_line_config.rs new file mode 100644 index 0000000..0a956d4 --- /dev/null +++ b/crates/bevy_cef_core/src/browser_process/command_line_config.rs @@ -0,0 +1,56 @@ +/// Configuration for CEF command line switches. +/// +/// Used to customize CEF behavior at startup. +/// +/// # Default Switches +/// +/// On macOS debug builds, the following switches are enabled by default: +/// - `use-mock-keychain`: Uses a mock keychain for testing +/// +/// # Example +/// +/// ```no_run +/// use bevy_cef::prelude::*; +/// +/// // Add switches while preserving defaults (recommended) +/// let config = CommandLineConfig::default() +/// .with_switch("disable-gpu") +/// .with_switch_value("remote-debugging-port", "9222"); +/// +/// // Or use direct initialization (replaces defaults) +/// let config = CommandLineConfig { +/// switches: vec!["disable-gpu"], +/// switch_values: vec![("remote-debugging-port", "9222")], +/// }; +/// ``` +#[derive(Clone, Debug)] +pub struct CommandLineConfig { + pub switches: Vec<&'static str>, + pub switch_values: Vec<(&'static str, &'static str)>, +} + +impl Default for CommandLineConfig { + fn default() -> Self { + Self { + switches: vec![ + #[cfg(all(target_os = "macos", debug_assertions))] + "use-mock-keychain", + ], + switch_values: Vec::new(), + } + } +} + +impl CommandLineConfig { + /// Add a command line switch (e.g., "disable-gpu", "disable-web-security"). + pub fn with_switch(mut self, name: &'static str) -> Self { + self.switches.push(name); + self + } + + /// Add a command line switch with a value (e.g., "remote-debugging-port", "9222"). + pub fn with_switch_value(mut self, name: &'static str, value: &'static str) -> Self { + self.switch_values.push((name, value)); + self + } +} diff --git a/examples/brp.rs b/examples/brp.rs index 9735083..ef264c9 100644 --- a/examples/brp.rs +++ b/examples/brp.rs @@ -13,7 +13,7 @@ fn main() { .add_plugins(( DefaultPlugins, RemotePlugin::default().with_method("greet", greet), - CefPlugin, + CefPlugin::default(), )) .add_systems( Startup, diff --git a/examples/custom_material.rs b/examples/custom_material.rs index b309581..9cfb503 100644 --- a/examples/custom_material.rs +++ b/examples/custom_material.rs @@ -12,7 +12,7 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - CefPlugin, + CefPlugin::default(), WebviewExtendMaterialPlugin::::default(), )) .add_systems(Startup, (spawn_camera, spawn_webview)) diff --git a/examples/devtool.rs b/examples/devtool.rs index 540b771..de5ea5b 100644 --- a/examples/devtool.rs +++ b/examples/devtool.rs @@ -10,7 +10,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/host_emit.rs b/examples/host_emit.rs index f0e19aa..de2c407 100644 --- a/examples/host_emit.rs +++ b/examples/host_emit.rs @@ -7,7 +7,7 @@ use std::time::Duration; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/js_emit.rs b/examples/js_emit.rs index e3094bd..6df888a 100644 --- a/examples/js_emit.rs +++ b/examples/js_emit.rs @@ -8,7 +8,7 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - CefPlugin, + CefPlugin::default(), JsEmitEventPlugin::::default(), )) .add_systems( diff --git a/examples/navigation.rs b/examples/navigation.rs index 6117e96..fc20289 100644 --- a/examples/navigation.rs +++ b/examples/navigation.rs @@ -11,7 +11,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/preload_scripts.rs b/examples/preload_scripts.rs index 15d2cf8..84f87c7 100644 --- a/examples/preload_scripts.rs +++ b/examples/preload_scripts.rs @@ -7,7 +7,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/simple.rs b/examples/simple.rs index 646f364..3cfd51d 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -5,7 +5,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/sprite.rs b/examples/sprite.rs index 9f5ca82..bd72f14 100644 --- a/examples/sprite.rs +++ b/examples/sprite.rs @@ -5,7 +5,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems(Startup, (spawn_camera_2d, spawn_sprite_webview)) .run(); } diff --git a/examples/zoom_level.rs b/examples/zoom_level.rs index 3de14c6..f0ba217 100644 --- a/examples/zoom_level.rs +++ b/examples/zoom_level.rs @@ -6,7 +6,7 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin)) + .add_plugins((DefaultPlugins, CefPlugin::default())) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/src/common/message_loop.rs b/src/common/message_loop.rs index 5301a36..ee3e257 100644 --- a/src/common/message_loop.rs +++ b/src/common/message_loop.rs @@ -8,7 +8,9 @@ use cef::{Settings, api_hash, execute_process, initialize, shutdown, sys}; /// /// - Windows and Linux: Support [`multi_threaded_message_loop`](https://cef-builds.spotifycdn.com/docs/106.1/structcef__settings__t.html#a518ac90db93ca5133a888faa876c08e0), so it is used. /// - macOS: Calls [`CefDoMessageLoopWork`](https://cef-builds.spotifycdn.com/docs/106.1/cef__app_8h.html#a830ae43dcdffcf4e719540204cefdb61) every frame. -pub struct MessageLoopPlugin; +pub struct MessageLoopPlugin { + pub config: CommandLineConfig, +} impl Plugin for MessageLoopPlugin { fn build(&self, app: &mut App) { @@ -19,7 +21,7 @@ impl Plugin for MessageLoopPlugin { let args = Args::new(); let (tx, rx) = std::sync::mpsc::channel(); - let mut cef_app = BrowserProcessAppBuilder::build(tx); + let mut cef_app = BrowserProcessAppBuilder::build(tx, self.config.clone()); let ret = execute_process( Some(args.as_main_args()), Some(&mut cef_app), diff --git a/src/lib.rs b/src/lib.rs index 7d8cf10..4a7b39f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,21 +16,28 @@ use crate::mute::AudioMutePlugin; use crate::prelude::{IpcPlugin, NavigationPlugin, WebviewPlugin}; use crate::zoom::ZoomPlugin; use bevy::prelude::*; +use bevy_cef_core::prelude::CommandLineConfig; use bevy_remote::RemotePlugin; pub mod prelude { pub use crate::{CefPlugin, RunOnMainThread, common::*, navigation::*, webview::prelude::*}; + pub use bevy_cef_core::prelude::CommandLineConfig; } pub struct RunOnMainThread; -pub struct CefPlugin; +#[derive(Debug, Default)] +pub struct CefPlugin { + pub command_line_config: CommandLineConfig, +} impl Plugin for CefPlugin { fn build(&self, app: &mut App) { app.add_plugins(( LocalHostPlugin, - MessageLoopPlugin, + MessageLoopPlugin { + config: self.command_line_config.clone(), + }, WebviewCoreComponentsPlugin, WebviewPlugin, IpcPlugin,