From 3f3449d056fa078e81a8b2c2f277a6874a3efd58 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 28 Aug 2025 13:17:11 -0300 Subject: [PATCH 1/3] feat(tauri-runtime-wry): ensure webview2 environment options matches on Windows the Webview2 environment options must match when created webviews sharing the same data directory (unless specified, all webviews share the same data directory). This PR validates the options, warning if they do not match, and forces the webview to be created with the same previous environment to prevent a crash. discovered as part of #14089 --- .changes/validate-environment-options.md | 5 +++ crates/tauri-runtime-wry/src/lib.rs | 50 +++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 .changes/validate-environment-options.md diff --git a/.changes/validate-environment-options.md b/.changes/validate-environment-options.md new file mode 100644 index 000000000000..f0f31563c302 --- /dev/null +++ b/.changes/validate-environment-options.md @@ -0,0 +1,5 @@ +--- +"tauri-runtime-wry": patch:enhance +--- + +Validate environment options match previously defined environment for the given data directory on Windows. diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index a5b6a11886fa..b2a66248b96a 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -40,7 +40,10 @@ use tao::platform::unix::{WindowBuilderExtUnix, WindowExtUnix}; #[cfg(windows)] use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows}; #[cfg(windows)] -use webview2_com::{ContainsFullScreenElementChangedEventHandler, FocusChangedEventHandler}; +use webview2_com::{ + ContainsFullScreenElementChangedEventHandler, FocusChangedEventHandler, + Microsoft::Web::WebView2::Win32::ICoreWebView2Environment, +}; #[cfg(windows)] use windows::Win32::Foundation::HWND; #[cfg(target_os = "ios")] @@ -157,11 +160,24 @@ use window::WindowExt as _; pub struct WebContext { pub inner: WryWebContext, pub referenced_by_webviews: HashSet, + #[cfg(windows)] + environment: Option, + #[cfg(windows)] + environment_options: WebView2EnvironmentOptions, // on Linux the custom protocols are associated with the context // and you cannot register a URI scheme more than once pub registered_custom_protocols: HashSet, } +#[cfg(windows)] +#[derive(Debug, PartialEq, Eq)] +struct WebView2EnvironmentOptions { + proxy_url: Option, + additional_browser_args: Option, + browser_extensions_enabled: bool, + // TODO: scroll_bar_style +} + pub type WebContextStore = Arc, WebContext>>>; // window pub type WindowEventHandler = Box; @@ -4544,6 +4560,13 @@ You may have it installed on another user account, but it is not available for t .. } = pending; + #[cfg(windows)] + let environment_options = WebView2EnvironmentOptions { + proxy_url: webview_attributes.proxy_url.clone(), + additional_browser_args: webview_attributes.additional_browser_args.clone(), + browser_extensions_enabled: webview_attributes.browser_extensions_enabled, + }; + let mut web_context = context .main_thread .web_context @@ -4558,6 +4581,17 @@ You may have it installed on another user account, but it is not available for t Occupied(occupied) => { let occupied = occupied.into_mut(); occupied.referenced_by_webviews.insert(label.clone()); + + #[cfg(windows)] + if cfg!(debug_assertions) && occupied.environment_options != environment_options { + let message = + format!("environment options {environment_options:?} for {web_context_key:?} do not match previously defined options for the same data directory on webviews {:?}, expected {:?}. Since this results in a crash, we are going to force the previously defined environment options", occupied.referenced_by_webviews, occupied.environment_options); + #[cfg(feature = "tracing")] + tracing::warn!("{message}"); + #[cfg(not(feature = "tracing"))] + eprintln!("{message}"); + } + occupied } Vacant(vacant) => { @@ -4571,6 +4605,10 @@ You may have it installed on another user account, but it is not available for t inner: web_context, referenced_by_webviews: [label.clone()].into(), registered_custom_protocols: HashSet::new(), + #[cfg(windows)] + environment: None, + #[cfg(windows)] + environment_options, }) } }; @@ -4584,6 +4622,11 @@ You may have it installed on another user account, but it is not available for t .with_clipboard(webview_attributes.clipboard) .with_hotkeys_zoom(webview_attributes.zoom_hotkeys_enabled); + #[cfg(windows)] + if let Some(environment) = &web_context.environment { + webview_builder = webview_builder.with_environment(environment.clone()); + } + if url != "about:blank" { webview_builder = webview_builder.with_url(&url); } @@ -5016,6 +5059,11 @@ You may have it installed on another user account, but it is not available for t #[cfg(windows)] { + // set the environment on the web context + // important so the next webview with the same context can reuse the environment instance + // to ensure its options matches + web_context.environment.replace(webview.environment()); + let controller = webview.controller(); let proxy_clone = context.proxy.clone(); let window_id_ = window_id.clone(); From 781e8fce9717194418bce0a5ecdfec29546c331a Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 28 Aug 2025 13:30:02 -0300 Subject: [PATCH 2/3] message before modifying ctx --- crates/tauri-runtime-wry/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index b2a66248b96a..a69a389a5201 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -4580,7 +4580,6 @@ You may have it installed on another user account, but it is not available for t let web_context = match entry { Occupied(occupied) => { let occupied = occupied.into_mut(); - occupied.referenced_by_webviews.insert(label.clone()); #[cfg(windows)] if cfg!(debug_assertions) && occupied.environment_options != environment_options { @@ -4592,6 +4591,8 @@ You may have it installed on another user account, but it is not available for t eprintln!("{message}"); } + occupied.referenced_by_webviews.insert(label.clone()); + occupied } Vacant(vacant) => { From 059bafaab4ce590dfb82ed7255fe8e2705f1c976 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 28 Aug 2025 13:32:50 -0300 Subject: [PATCH 3/3] update message format --- crates/tauri-runtime-wry/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index a69a389a5201..85d5c2dc3482 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -4583,8 +4583,11 @@ You may have it installed on another user account, but it is not available for t #[cfg(windows)] if cfg!(debug_assertions) && occupied.environment_options != environment_options { - let message = - format!("environment options {environment_options:?} for {web_context_key:?} do not match previously defined options for the same data directory on webviews {:?}, expected {:?}. Since this results in a crash, we are going to force the previously defined environment options", occupied.referenced_by_webviews, occupied.environment_options); + let message = format!( + "environment options {environment_options:?} for {} do not match previously defined options for the same data directory on webviews {:?}, expected {:?}. Since this results in a crash, we are going to force the previously defined environment options", + web_context_key.as_ref().map(|p| p.to_string_lossy()).unwrap_or_else(|| "".into()), + occupied.referenced_by_webviews, occupied.environment_options + ); #[cfg(feature = "tracing")] tracing::warn!("{message}"); #[cfg(not(feature = "tracing"))]