Skip to content

Commit

Permalink
fix(linux): don't share UserContentManager between webviews (v0.24) (#…
Browse files Browse the repository at this point in the history
…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)
  • Loading branch information
ollpu authored Aug 22, 2024
1 parent 3c7b54b commit 3937421
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changes/linux-shared-webcontext-ipc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": patch
---

Fix Linux IPC handler and initialization scripts when sharing a WebContext between multiple WebViews.
20 changes: 11 additions & 9 deletions src/webview/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand All @@ -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 = {
Expand All @@ -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();
Expand Down Expand Up @@ -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(_) => (),
}
Expand Down
13 changes: 2 additions & 11 deletions src/webview/webkitgtk/web_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<WebviewUriLoader>,
registered_protocols: HashSet<String>,
automation: bool,
Expand Down Expand Up @@ -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),
Expand All @@ -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
Expand Down Expand Up @@ -150,10 +145,6 @@ impl WebContextExt for super::WebContext {
&self.os.context
}

fn manager(&self) -> &UserContentManager {
&self.os.manager
}

fn register_uri_scheme<F>(&mut self, name: &str, handler: F) -> crate::Result<()>
where
F: Fn(&Request<Vec<u8>>) -> crate::Result<Response<Cow<'static, [u8]>>> + 'static,
Expand Down

0 comments on commit 3937421

Please sign in to comment.