Skip to content

Commit

Permalink
fix: fix incorrect label passed to ipc protocol
Browse files Browse the repository at this point in the history
closes #11171
  • Loading branch information
amrbashir committed Oct 8, 2024
1 parent 04fd3a7 commit d1b985b
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 117 deletions.
7 changes: 7 additions & 0 deletions .changes/incorrect-label-linux-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri": "minor:bug"
"tauri-runtime": "minor:bug"
"tauri-runtime-wry": "minor:bug"
---

On Linux, fix commands, that use `Webview` or `WebviewWindow` as an argument, receiving an inccorect webview when using multi webviews.
7 changes: 7 additions & 0 deletions .changes/incorrect-label-linux-event.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri": "minor:bug"
"tauri-runtime": "minor:bug"
"tauri-runtime-wry": "minor:bug"
---

On Linux, fix events only emitted to first webview only when using multi webviews.
7 changes: 7 additions & 0 deletions .changes/incorrect-label-linux-protocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri": "minor:bug"
"tauri-runtime": "minor:bug"
"tauri-runtime-wry": "minor:bug"
---

On Linux, fix custom protocols receiving an inccorect webview label when using multi webviews
5 changes: 2 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
wry = { version = "0.44.0", default-features = false, features = [
wry = { git = "https://github.com/tauri-apps/wry", branch = "refactor/protocol-webview-id", default-features = false, features = [
"drag-drop",
"protocol",
"os-webview",
Expand Down
167 changes: 81 additions & 86 deletions crates/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3963,52 +3963,45 @@ fn create_webview<T: UserEvent>(
..
} = pending;

let builder = match kind {
#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
)))]
WebviewKind::WindowChild => {
// only way to account for menu bar height, and also works for multiwebviews :)
let vbox = window.default_vbox().unwrap();
WebViewBuilder::new_gtk(vbox)
let mut web_context = context
.main_thread
.web_context
.lock()
.expect("poisoned WebContext store");
let is_first_context = web_context.is_empty();
// the context must be stored on the HashMap because it must outlive the WebView on macOS
let automation_enabled = std::env::var("TAURI_WEBVIEW_AUTOMATION").as_deref() == Ok("true");
let web_context_key = webview_attributes.data_directory;
let entry = web_context.entry(web_context_key.clone());
let web_context = match entry {
Occupied(occupied) => {
let occupied = occupied.into_mut();
occupied.referenced_by_webviews.insert(label.clone());
occupied
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
))]
WebviewKind::WindowChild => WebViewBuilder::new_as_child(&window),
WebviewKind::WindowContent => {
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
))]
let builder = WebViewBuilder::new(&window);
#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
)))]
let builder = {
let vbox = window.default_vbox().unwrap();
WebViewBuilder::new_gtk(vbox)
};
builder
Vacant(vacant) => {
let mut web_context = WryWebContext::new(web_context_key.clone());
web_context.set_allows_automation(if automation_enabled {
is_first_context
} else {
false
});
vacant.insert(WebContext {
inner: web_context,
referenced_by_webviews: [label.clone()].into(),
registered_custom_protocols: HashSet::new(),
})
}
};

let mut webview_builder = builder
let mut webview_builder = WebViewBuilder::with_web_context(&mut web_context.inner)
.with_id(&label)
.with_focused(window.is_focused())
.with_url(&url)
.with_transparent(webview_attributes.transparent)
.with_accept_first_mouse(webview_attributes.accept_first_mouse)
.with_incognito(webview_attributes.incognito)
.with_clipboard(webview_attributes.clipboard)
.with_hotkeys_zoom(webview_attributes.zoom_hotkeys_enabled);

if webview_attributes.drag_drop_handler_enabled {
Expand Down Expand Up @@ -4177,47 +4170,17 @@ fn create_webview<T: UserEvent>(
webview_builder = webview_builder.with_initialization_script(&script);
}

let mut web_context = context
.main_thread
.web_context
.lock()
.expect("poisoned WebContext store");
let is_first_context = web_context.is_empty();
// the context must be stored on the HashMap because it must outlive the WebView on macOS
let automation_enabled = std::env::var("TAURI_WEBVIEW_AUTOMATION").as_deref() == Ok("true");
let web_context_key = webview_attributes.data_directory;
let entry = web_context.entry(web_context_key.clone());
let web_context = match entry {
Occupied(occupied) => {
let occupied = occupied.into_mut();
occupied.referenced_by_webviews.insert(label.clone());
occupied
}
Vacant(vacant) => {
let mut web_context = WryWebContext::new(web_context_key.clone());
web_context.set_allows_automation(if automation_enabled {
is_first_context
} else {
false
});
vacant.insert(WebContext {
inner: web_context,
referenced_by_webviews: [label.clone()].into(),
registered_custom_protocols: HashSet::new(),
})
}
};

for (scheme, protocol) in uri_scheme_protocols {
// on Linux the custom protocols are associated with the web context
// and you cannot register a scheme more than once
if cfg!(any(
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)) {
))]
{
if web_context.registered_custom_protocols.contains(&scheme) {
continue;
}
Expand All @@ -4227,21 +4190,16 @@ fn create_webview<T: UserEvent>(
.insert(scheme.clone());
}

webview_builder =
webview_builder.with_asynchronous_custom_protocol(scheme, move |request, responder| {
webview_builder = webview_builder.with_asynchronous_custom_protocol(
scheme,
move |webview_id, request, responder| {
protocol(
webview_id.as_deref(),
request,
Box::new(move |response| responder.respond(response)),
)
});
}

if webview_attributes.clipboard {
webview_builder.attrs.clipboard = true;
}

if webview_attributes.incognito {
webview_builder.attrs.incognito = true;
},
);
}

#[cfg(any(debug_assertions, feature = "devtools"))]
Expand All @@ -4262,10 +4220,47 @@ fn create_webview<T: UserEvent>(
}
}

let webview = webview_builder
.with_web_context(&mut web_context.inner)
.build()
.map_err(|e| Error::CreateWebview(Box::new(e)))?;
let webview = match kind {
#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
)))]
WebviewKind::WindowChild => {
// only way to account for menu bar height, and also works for multiwebviews :)
let vbox = window.default_vbox().unwrap();
webview_builder.build_gtk(vbox)
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
))]
WebviewKind::WindowChild => webview_builder.build(&window),
WebviewKind::WindowContent => {
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
))]
let builder = webview_builder.build(&window);
#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "ios",
target_os = "android"
)))]
let builder = {
let vbox = window.default_vbox().unwrap();
webview_builder.build_gtk(vbox)
};
builder
}
}
.map_err(|e| Error::CreateWebview(Box::new(dbg!(e))))?;

if kind == WebviewKind::WindowContent {
#[cfg(any(
Expand Down
14 changes: 10 additions & 4 deletions crates/tauri-runtime/src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ use std::{
sync::Arc,
};

type UriSchemeProtocol = dyn Fn(http::Request<Vec<u8>>, Box<dyn FnOnce(http::Response<Cow<'static, [u8]>>) + Send>)
+ Send
type UriSchemeProtocol = dyn Fn(
Option<&str>,
http::Request<Vec<u8>>,
Box<dyn FnOnce(http::Response<Cow<'static, [u8]>>) + Send>,
) + Send
+ Sync
+ 'static;

Expand Down Expand Up @@ -129,8 +132,11 @@ impl<T: UserEvent, R: Runtime<T>> PendingWebview<T, R> {

pub fn register_uri_scheme_protocol<
N: Into<String>,
H: Fn(http::Request<Vec<u8>>, Box<dyn FnOnce(http::Response<Cow<'static, [u8]>>) + Send>)
+ Send
H: Fn(
Option<&str>,
http::Request<Vec<u8>>,
Box<dyn FnOnce(http::Response<Cow<'static, [u8]>>) + Send>,
) + Send
+ Sync
+ 'static,
>(
Expand Down
5 changes: 2 additions & 3 deletions crates/tauri/src/ipc/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ pub fn message_handler<R: Runtime>(
Box::new(move |webview, request| handle_ipc_message(request, &manager, &webview.label))
}

pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeProtocolHandler {
Box::new(move |request, responder| {
pub fn get<R: Runtime>(manager: Arc<AppManager<R>>) -> UriSchemeProtocolHandler {
Box::new(move |label, request, responder| {
#[cfg(feature = "tracing")]
let span = tracing::trace_span!(
"ipc::request",
Expand All @@ -46,7 +46,6 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
.entered();

let manager = manager.clone();
let label = label.clone();

let respond = move |mut response: http::Response<Cow<'static, [u8]>>| {
response
Expand Down
52 changes: 36 additions & 16 deletions crates/tauri/src/manager/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,16 @@ impl<R: Runtime> WebviewManager<R> {
let app_handle = manager.app_handle().clone();
let webview_label = label.to_string();

pending.register_uri_scheme_protocol(uri_scheme.clone(), move |request, responder| {
let context = UriSchemeContext {
app_handle: &app_handle,
webview_label: webview_label.as_str(),
};
(protocol.protocol)(context, request, UriSchemeResponder(responder))
});
pending.register_uri_scheme_protocol(
uri_scheme.clone(),
move |webview_id, request, responder| {
let context = UriSchemeContext {
app_handle: &app_handle,
webview_label: webview_id.unwrap_or(&webview_label),
};
(protocol.protocol)(context, request, UriSchemeResponder(responder))
},
);
}

let window_url = Url::parse(&pending.url).unwrap();
Expand Down Expand Up @@ -252,16 +255,25 @@ impl<R: Runtime> WebviewManager<R> {
&window_origin,
web_resource_request_handler,
);
pending.register_uri_scheme_protocol("tauri", move |request, responder| {
protocol(request, UriSchemeResponder(responder))
pending.register_uri_scheme_protocol("tauri", move |webview_id, request, responder| {
protocol(
webview_id.unwrap_or_default(),
request,
UriSchemeResponder(responder),
)
});
registered_scheme_protocols.push("tauri".into());
}

if !registered_scheme_protocols.contains(&"ipc".into()) {
let protocol = crate::ipc::protocol::get(manager.manager_owned(), pending.label.clone());
pending.register_uri_scheme_protocol("ipc", move |request, responder| {
protocol(request, UriSchemeResponder(responder))
let protocol = crate::ipc::protocol::get(manager.manager_owned());
let webview_label = pending.label.clone();
pending.register_uri_scheme_protocol("ipc", move |webview_id, request, responder| {
protocol(
webview_id.unwrap_or(&webview_label),
request,
UriSchemeResponder(responder),
)
});
registered_scheme_protocols.push("ipc".into());
}
Expand Down Expand Up @@ -299,8 +311,12 @@ impl<R: Runtime> WebviewManager<R> {
.asset_protocol
.clone();
let protocol = crate::protocol::asset::get(asset_scope.clone(), window_origin.clone());
pending.register_uri_scheme_protocol("asset", move |request, responder| {
protocol(request, UriSchemeResponder(responder))
pending.register_uri_scheme_protocol("asset", move |webview_id, request, responder| {
protocol(
webview_id.unwrap_or_default(),
request,
UriSchemeResponder(responder),
)
});
}

Expand All @@ -319,8 +335,12 @@ impl<R: Runtime> WebviewManager<R> {
*crypto_keys.aes_gcm().raw(),
window_origin,
);
pending.register_uri_scheme_protocol(schema, move |request, responder| {
protocol(request, UriSchemeResponder(responder))
pending.register_uri_scheme_protocol(schema, move |webview_id, request, responder| {
protocol(
webview_id.unwrap_or_default(),
request,
UriSchemeResponder(responder),
)
});
}

Expand Down
Loading

0 comments on commit d1b985b

Please sign in to comment.