#[cfg(target_os = "linux")] use std::env; use cef::rc::{Rc, RcImpl}; use cef::sys::{_cef_app_t, cef_base_ref_counted_t}; use cef::{BrowserProcessHandler, CefString, ImplApp, ImplCommandLine, SchemeRegistrar, WrapApp}; use super::browser_process_handler::BrowserProcessHandlerImpl; use super::scheme_handler_factory::SchemeHandlerFactoryImpl; use crate::cef::CefEventHandler; pub(crate) struct BrowserProcessAppImpl { object: *mut RcImpl<_cef_app_t, Self>, event_handler: H, } impl BrowserProcessAppImpl { pub(crate) fn new(event_handler: H) -> Self { Self { object: std::ptr::null_mut(), event_handler, } } } impl ImplApp for BrowserProcessAppImpl { fn browser_process_handler(&self) -> Option { Some(BrowserProcessHandler::new(BrowserProcessHandlerImpl::new(self.event_handler.duplicate()))) } fn on_register_custom_schemes(&self, registrar: Option<&mut SchemeRegistrar>) { SchemeHandlerFactoryImpl::::register_schemes(registrar); } fn on_before_command_line_processing(&self, _process_type: Option<&cef::CefString>, command_line: Option<&mut cef::CommandLine>) { if let Some(cmd) = command_line { cmd.append_switch_with_value(Some(&CefString::from("renderer-process-limit")), Some(&CefString::from("1"))); cmd.append_switch_with_value(Some(&CefString::from("password-store")), Some(&CefString::from("basic"))); cmd.append_switch_with_value(Some(&CefString::from("disk-cache-size")), Some(&CefString::from("0"))); cmd.append_switch(Some(&CefString::from("incognito"))); cmd.append_switch(Some(&CefString::from("no-first-run"))); cmd.append_switch(Some(&CefString::from("no-default-browser-check"))); cmd.append_switch(Some(&CefString::from("disable-component-update"))); cmd.append_switch(Some(&CefString::from("disable-geolocation"))); cmd.append_switch(Some(&CefString::from("disable-notifications"))); cmd.append_switch(Some(&CefString::from("disable-audio-input"))); cmd.append_switch(Some(&CefString::from("disable-audio-output"))); cmd.append_switch(Some(&CefString::from("disable-sync"))); cmd.append_switch(Some(&CefString::from("disable-file-system"))); cmd.append_switch(Some(&CefString::from("disable-local-storage"))); cmd.append_switch(Some(&CefString::from("disable-background-networking"))); cmd.append_switch(Some(&CefString::from("disable-default-apps"))); cmd.append_switch(Some(&CefString::from("disable-breakpad"))); cmd.append_switch_with_value(Some(&CefString::from("disable-blink-features")), Some(&CefString::from("WebBluetooth,WebUSB,Serial"))); let extra_disabled_features = ["OptimizationHints", "OnDeviceModelService", "TranslateUI"]; let disabled_features_switch = Some(&CefString::from("disable-features")); let disabled_features: String = CefString::from(&cmd.switch_value(disabled_features_switch)) .to_string() .split(',') .chain(extra_disabled_features) .collect::>() .join(","); cmd.append_switch_with_value(disabled_features_switch, Some(&CefString::from(disabled_features.as_str()))); #[cfg(not(feature = "accelerated_paint"))] { // Disable GPU acceleration when accelerated_paint feature is not enabled cmd.append_switch(Some(&CefString::from("disable-gpu"))); cmd.append_switch(Some(&CefString::from("disable-gpu-compositing"))); } #[cfg(feature = "accelerated_paint")] { // Enable GPU acceleration switches for better performance cmd.append_switch(Some(&CefString::from("enable-gpu-rasterization"))); cmd.append_switch(Some(&CefString::from("enable-accelerated-2d-canvas"))); } #[cfg(all(feature = "accelerated_paint", target_os = "linux"))] { // Use Vulkan for accelerated painting cmd.append_switch_with_value(Some(&CefString::from("use-angle")), Some(&CefString::from("vulkan"))); } // Tell CEF to use Wayland if available #[cfg(target_os = "linux")] { let use_wayland = env::var("WAYLAND_DISPLAY") .ok() .filter(|var| !var.is_empty()) .or_else(|| env::var("WAYLAND_SOCKET").ok()) .filter(|var| !var.is_empty()) .is_some(); if use_wayland { cmd.append_switch_with_value(Some(&CefString::from("ozone-platform")), Some(&CefString::from("wayland"))); } } #[cfg(target_os = "macos")] { // Hide user prompt asking for keychain access cmd.append_switch(Some(&CefString::from("use-mock-keychain"))); } // Enable browser debugging via environment variable if let Some(env) = std::env::var("GRAPHITE_BROWSER_DEBUG_PORT").ok() && let Some(port) = env.parse::().ok() { cmd.append_switch_with_value(Some(&CefString::from("remote-debugging-port")), Some(&CefString::from(port.to_string().as_str()))); cmd.append_switch_with_value(Some(&CefString::from("remote-allow-origins")), Some(&CefString::from("*"))); } } } fn get_raw(&self) -> *mut _cef_app_t { self.object.cast() } } impl Clone for BrowserProcessAppImpl { fn clone(&self) -> Self { unsafe { let rc_impl = &mut *self.object; rc_impl.interface.add_ref(); } Self { object: self.object, event_handler: self.event_handler.duplicate(), } } } impl Rc for BrowserProcessAppImpl { fn as_base(&self) -> &cef_base_ref_counted_t { unsafe { let base = &*self.object; std::mem::transmute(&base.cef_object) } } } impl WrapApp for BrowserProcessAppImpl { fn wrap_rc(&mut self, object: *mut RcImpl<_cef_app_t, Self>) { self.object = object; } }