mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
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
This commit is contained in:
5
.changes/validate-environment-options.md
Normal file
5
.changes/validate-environment-options.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-runtime-wry": patch:enhance
|
||||
---
|
||||
|
||||
Validate environment options match previously defined environment for the given data directory on Windows.
|
||||
@@ -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<String>,
|
||||
#[cfg(windows)]
|
||||
environment: Option<ICoreWebView2Environment>,
|
||||
#[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<String>,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct WebView2EnvironmentOptions {
|
||||
proxy_url: Option<Url>,
|
||||
additional_browser_args: Option<String>,
|
||||
browser_extensions_enabled: bool,
|
||||
// TODO: scroll_bar_style
|
||||
}
|
||||
|
||||
pub type WebContextStore = Arc<Mutex<HashMap<Option<PathBuf>, WebContext>>>;
|
||||
// window
|
||||
pub type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user