feat: Add configurable CEF command line flags (#16)
## Summary
- Add CommandLineConfig struct for CEF command line switches
- Use direct struct initialization with optional helper methods
- Change default to secure: only use-mock-keychain enabled on macOS debug builds
- Add comprehensive documentation with usage examples
## Usage
```rust
use bevy_cef::prelude::*;
// Default (secure, includes use-mock-keychain on macOS debug)
app.add_plugins((DefaultPlugins, CefPlugin::default()));
// Add switches while preserving defaults (recommended)
app.add_plugins((
DefaultPlugins,
CefPlugin {
command_line_config: CommandLineConfig::default()
.with_switch("disable-gpu")
.with_switch_value("remote-debugging-port", "9222"),
},
));
// Full customization with direct initialization
app.add_plugins((
DefaultPlugins,
CefPlugin {
command_line_config: CommandLineConfig {
switches: vec!["disable-gpu"],
switch_values: vec![("remote-debugging-port", "9222")],
},
},
));
```
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@ target/
|
|||||||
.idea/
|
.idea/
|
||||||
book/
|
book/
|
||||||
.DS_Store**/.DS_Store
|
.DS_Store**/.DS_Store
|
||||||
|
.claude/memo.md
|
||||||
|
docs/plans/
|
||||||
@@ -2,6 +2,7 @@ mod app;
|
|||||||
mod browser_process_handler;
|
mod browser_process_handler;
|
||||||
mod browsers;
|
mod browsers;
|
||||||
mod client_handler;
|
mod client_handler;
|
||||||
|
mod command_line_config;
|
||||||
mod context_menu_handler;
|
mod context_menu_handler;
|
||||||
mod display_handler;
|
mod display_handler;
|
||||||
mod localhost;
|
mod localhost;
|
||||||
@@ -13,6 +14,7 @@ pub use app::*;
|
|||||||
pub use browser_process_handler::*;
|
pub use browser_process_handler::*;
|
||||||
pub use browsers::*;
|
pub use browsers::*;
|
||||||
pub use client_handler::*;
|
pub use client_handler::*;
|
||||||
|
pub use command_line_config::*;
|
||||||
pub use context_menu_handler::*;
|
pub use context_menu_handler::*;
|
||||||
pub use localhost::*;
|
pub use localhost::*;
|
||||||
pub use message_pump::*;
|
pub use message_pump::*;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::browser_process::CommandLineConfig;
|
||||||
use crate::browser_process::MessageLoopTimer;
|
use crate::browser_process::MessageLoopTimer;
|
||||||
use crate::browser_process::browser_process_handler::BrowserProcessHandlerBuilder;
|
use crate::browser_process::browser_process_handler::BrowserProcessHandlerBuilder;
|
||||||
use crate::util::{SCHEME_CEF, cef_scheme_flags};
|
use crate::util::{SCHEME_CEF, cef_scheme_flags};
|
||||||
@@ -15,13 +16,18 @@ use std::sync::mpsc::Sender;
|
|||||||
pub struct BrowserProcessAppBuilder {
|
pub struct BrowserProcessAppBuilder {
|
||||||
object: *mut RcImpl<_cef_app_t, Self>,
|
object: *mut RcImpl<_cef_app_t, Self>,
|
||||||
message_loop_working_requester: Sender<MessageLoopTimer>,
|
message_loop_working_requester: Sender<MessageLoopTimer>,
|
||||||
|
config: CommandLineConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BrowserProcessAppBuilder {
|
impl BrowserProcessAppBuilder {
|
||||||
pub fn build(message_loop_working_requester: Sender<MessageLoopTimer>) -> cef::App {
|
pub fn build(
|
||||||
|
message_loop_working_requester: Sender<MessageLoopTimer>,
|
||||||
|
config: CommandLineConfig,
|
||||||
|
) -> cef::App {
|
||||||
cef::App::new(Self {
|
cef::App::new(Self {
|
||||||
object: core::ptr::null_mut(),
|
object: core::ptr::null_mut(),
|
||||||
message_loop_working_requester,
|
message_loop_working_requester,
|
||||||
|
config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,6 +42,7 @@ impl Clone for BrowserProcessAppBuilder {
|
|||||||
Self {
|
Self {
|
||||||
object,
|
object,
|
||||||
message_loop_working_requester: self.message_loop_working_requester.clone(),
|
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 {
|
let Some(command_line) = command_line else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
command_line.append_switch(Some(&"use-mock-keychain".into()));
|
|
||||||
// command_line.append_switch(Some(&"disable-gpu".into()));
|
for switch in &self.config.switches {
|
||||||
// command_line.append_switch(Some(&"disable-gpu-compositing".into()));
|
command_line.append_switch(Some(&(*switch).into()));
|
||||||
// command_line.append_switch(Some(&" disable-gpu-shader-disk-cache".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>) {
|
fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ fn main() {
|
|||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins,
|
DefaultPlugins,
|
||||||
RemotePlugin::default().with_method("greet", greet),
|
RemotePlugin::default().with_method("greet", greet),
|
||||||
CefPlugin,
|
CefPlugin::default(),
|
||||||
))
|
))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ fn main() {
|
|||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins,
|
DefaultPlugins,
|
||||||
CefPlugin,
|
CefPlugin::default(),
|
||||||
WebviewExtendMaterialPlugin::<CustomExtension>::default(),
|
WebviewExtendMaterialPlugin::<CustomExtension>::default(),
|
||||||
))
|
))
|
||||||
.add_systems(Startup, (spawn_camera, spawn_webview))
|
.add_systems(Startup, (spawn_camera, spawn_webview))
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ fn main() {
|
|||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins,
|
DefaultPlugins,
|
||||||
CefPlugin,
|
CefPlugin::default(),
|
||||||
JsEmitEventPlugin::<Message>::default(),
|
JsEmitEventPlugin::<Message>::default(),
|
||||||
))
|
))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(Startup, (spawn_camera_2d, spawn_sprite_webview))
|
.add_systems(Startup, (spawn_camera_2d, spawn_sprite_webview))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use bevy_cef::prelude::*;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((DefaultPlugins, CefPlugin))
|
.add_plugins((DefaultPlugins, CefPlugin::default()))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Startup,
|
Startup,
|
||||||
(spawn_camera, spawn_directional_light, spawn_webview),
|
(spawn_camera, spawn_directional_light, spawn_webview),
|
||||||
|
|||||||
@@ -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.
|
/// - 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.
|
/// - 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 {
|
impl Plugin for MessageLoopPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@@ -19,7 +21,7 @@ impl Plugin for MessageLoopPlugin {
|
|||||||
let args = Args::new();
|
let args = Args::new();
|
||||||
let (tx, rx) = std::sync::mpsc::channel();
|
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(
|
let ret = execute_process(
|
||||||
Some(args.as_main_args()),
|
Some(args.as_main_args()),
|
||||||
Some(&mut cef_app),
|
Some(&mut cef_app),
|
||||||
|
|||||||
11
src/lib.rs
11
src/lib.rs
@@ -16,21 +16,28 @@ use crate::mute::AudioMutePlugin;
|
|||||||
use crate::prelude::{IpcPlugin, NavigationPlugin, WebviewPlugin};
|
use crate::prelude::{IpcPlugin, NavigationPlugin, WebviewPlugin};
|
||||||
use crate::zoom::ZoomPlugin;
|
use crate::zoom::ZoomPlugin;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy_cef_core::prelude::CommandLineConfig;
|
||||||
use bevy_remote::RemotePlugin;
|
use bevy_remote::RemotePlugin;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{CefPlugin, RunOnMainThread, common::*, navigation::*, webview::prelude::*};
|
pub use crate::{CefPlugin, RunOnMainThread, common::*, navigation::*, webview::prelude::*};
|
||||||
|
pub use bevy_cef_core::prelude::CommandLineConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunOnMainThread;
|
pub struct RunOnMainThread;
|
||||||
|
|
||||||
pub struct CefPlugin;
|
#[derive(Debug, Default)]
|
||||||
|
pub struct CefPlugin {
|
||||||
|
pub command_line_config: CommandLineConfig,
|
||||||
|
}
|
||||||
|
|
||||||
impl Plugin for CefPlugin {
|
impl Plugin for CefPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
LocalHostPlugin,
|
LocalHostPlugin,
|
||||||
MessageLoopPlugin,
|
MessageLoopPlugin {
|
||||||
|
config: self.command_line_config.clone(),
|
||||||
|
},
|
||||||
WebviewCoreComponentsPlugin,
|
WebviewCoreComponentsPlugin,
|
||||||
WebviewPlugin,
|
WebviewPlugin,
|
||||||
IpcPlugin,
|
IpcPlugin,
|
||||||
|
|||||||
Reference in New Issue
Block a user