From 39374211f95e84a68620e9527c6d1f797829b471 Mon Sep 17 00:00:00 2001 From: Roope Salmi Date: Thu, 22 Aug 2024 03:00:21 +0300 Subject: [PATCH] fix(linux): don't share UserContentManager between webviews (v0.24) (#1325) Fixes #1308 Init scripts are registered to the `UserContentManager`, so if it is shared between `WebView`s, the init scripts conflict. Use a unique `UserContentManager` for each `WebView` instead of sharing it across the `WebContext`. The IPC message handler is also registered to `UserContentManager`. Also changed from `register_uri_scheme` to `try_register_uri_scheme`, which doesn't attempt to register a URI scheme if we already know that one with the same name was registered to the `WebContext` before. Without this change, I get this error from WebKitGTK: ``` ** (tauri-app:[...]): CRITICAL **: 14:03:50.040: Cannot register URI scheme tauri more than once ``` It doesn't seem to affect functionality, but better to issue a more appropriate warning on our side. (On dev, this is propagated as an error) --- .changes/linux-shared-webcontext-ipc.md | 5 +++++ src/webview/webkitgtk/mod.rs | 20 +++++++++++--------- src/webview/webkitgtk/web_context.rs | 13 ++----------- 3 files changed, 18 insertions(+), 20 deletions(-) create mode 100644 .changes/linux-shared-webcontext-ipc.md diff --git a/.changes/linux-shared-webcontext-ipc.md b/.changes/linux-shared-webcontext-ipc.md new file mode 100644 index 000000000..bcb966ffd --- /dev/null +++ b/.changes/linux-shared-webcontext-ipc.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +Fix Linux IPC handler and initialization scripts when sharing a WebContext between multiple WebViews. diff --git a/src/webview/webkitgtk/mod.rs b/src/webview/webkitgtk/mod.rs index e8d6a6a7a..6fc0212fd 100644 --- a/src/webview/webkitgtk/mod.rs +++ b/src/webview/webkitgtk/mod.rs @@ -17,7 +17,8 @@ use std::{ use url::Url; use webkit2gtk::{ traits::*, LoadEvent, NavigationPolicyDecision, PolicyDecisionType, URIRequest, - UserContentInjectedFrames, UserScript, UserScriptInjectionTime, WebView, WebViewBuilder, + UserContentInjectedFrames, UserContentManager, UserScript, UserScriptInjectionTime, WebView, + WebViewBuilder, }; use webkit2gtk_sys::{ webkit_get_major_version, webkit_get_micro_version, webkit_get_minor_version, @@ -63,9 +64,11 @@ impl InnerWebView { } }; + let manager = UserContentManager::new(); + let webview = { let mut webview = WebViewBuilder::new(); - webview = webview.user_content_manager(web_context.manager()); + webview = webview.user_content_manager(&manager); webview = webview.web_context(web_context.context()); webview = webview.is_controlled_by_automation(web_context.allows_automation()); webview.build() @@ -77,8 +80,6 @@ impl InnerWebView { let webview = Rc::new(webview); let w = window_rc.clone(); let ipc_handler = attributes.ipc_handler.take(); - let manager = web_context.manager(); - // Use the window hash as the script handler name to prevent from conflict when sharing same // web context. let window_hash = { @@ -99,8 +100,8 @@ impl InnerWebView { } }); - // Register the handler we just connected - manager.register_script_message_handler(&window_hash); + // Register handler on JS side + manager.register_script_message_handler("ipc"); // Allow the webview to close it's own window let close_window = window_rc.clone(); @@ -355,10 +356,11 @@ impl InnerWebView { } for (name, handler) in attributes.custom_protocols { - match web_context.register_uri_scheme(&name, handler) { + match web_context.try_register_uri_scheme(&name, handler) { // Swallow duplicate scheme errors to preserve current behavior. - // FIXME: we should log this error in the future - Err(Error::DuplicateCustomProtocol(_)) => (), + Err(Error::DuplicateCustomProtocol(_)) => { + log::warn!("Ignoring already registered custom protocol {name}"); + } Err(e) => return Err(e), Ok(_) => (), } diff --git a/src/webview/webkitgtk/web_context.rs b/src/webview/webkitgtk/web_context.rs index 1b4063993..c80a9f13d 100644 --- a/src/webview/webkitgtk/web_context.rs +++ b/src/webview/webkitgtk/web_context.rs @@ -21,14 +21,13 @@ use std::{ }; use url::Url; use webkit2gtk::{ - traits::*, ApplicationInfo, CookiePersistentStorage, LoadEvent, URIRequest, UserContentManager, - WebContext, WebContextBuilder, WebView, WebsiteDataManagerBuilder, + traits::*, ApplicationInfo, CookiePersistentStorage, LoadEvent, URIRequest, WebContext, + WebContextBuilder, WebView, WebsiteDataManagerBuilder, }; #[derive(Debug)] pub struct WebContextImpl { context: WebContext, - manager: UserContentManager, webview_uri_loader: Rc, registered_protocols: HashSet, automation: bool, @@ -82,7 +81,6 @@ impl WebContextImpl { Self { context, automation, - manager: UserContentManager::new(), registered_protocols: Default::default(), webview_uri_loader: Rc::default(), app_info: Some(app_info), @@ -101,9 +99,6 @@ pub trait WebContextExt { /// The GTK [`WebContext`] of all webviews in the context. fn context(&self) -> &WebContext; - /// The GTK [`UserContentManager`] of all webviews in the context. - fn manager(&self) -> &UserContentManager; - /// Register a custom protocol to the web context. /// /// When duplicate schemes are registered, the duplicate handler will still be submitted and the @@ -150,10 +145,6 @@ impl WebContextExt for super::WebContext { &self.os.context } - fn manager(&self) -> &UserContentManager { - &self.os.manager - } - fn register_uri_scheme(&mut self, name: &str, handler: F) -> crate::Result<()> where F: Fn(&Request>) -> crate::Result>> + 'static,