mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
The IPC fallback system kicks in when the custom protocol implementation cannot be used (e.g. CORS issues). The fallback uses the postMessage mechanism, which by default uses channels to send large responses. If the custom protocol implementation cannot be used, we should not use channels, but eval the response directly.
This commit is contained in:
committed by
GitHub
parent
794cf8234f
commit
b1d9ffa1ab
5
.changes/fix-ipc-fallback.md
Normal file
5
.changes/fix-ipc-fallback.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:bug
|
||||
---
|
||||
|
||||
Fix IPC fallback (postMessage implementation when custom protocol fails) hanging when sending responses.
|
||||
@@ -62,7 +62,11 @@
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((e) => {
|
||||
console.warn(
|
||||
'IPC custom protocol failed, Tauri will now use the postMessage interface instead',
|
||||
e
|
||||
)
|
||||
// failed to use the custom protocol IPC (either the webview blocked a custom protocol or it was a CSP error)
|
||||
// so we need to fallback to the postMessage interface
|
||||
customProtocolIpcFailed = true
|
||||
@@ -74,7 +78,10 @@
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
options,
|
||||
options: {
|
||||
...options,
|
||||
customProtocolIpcBlocked: customProtocolIpcFailed
|
||||
},
|
||||
payload,
|
||||
__TAURI_INVOKE_KEY__
|
||||
})
|
||||
|
||||
@@ -174,6 +174,7 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct HeaderMap(http::HeaderMap);
|
||||
|
||||
impl<'de> Deserialize<'de> for HeaderMap {
|
||||
@@ -199,9 +200,13 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct RequestOptions {
|
||||
#[serde(default)]
|
||||
headers: HeaderMap,
|
||||
#[serde(default)]
|
||||
custom_protocol_ipc_blocked: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -260,13 +265,15 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
|
||||
match message {
|
||||
Ok(message) => {
|
||||
let options = message.options.unwrap_or_default();
|
||||
|
||||
let request = InvokeRequest {
|
||||
cmd: message.cmd,
|
||||
callback: message.callback,
|
||||
error: message.error,
|
||||
url: Url::parse(&request.uri().to_string()).expect("invalid IPC request URL"),
|
||||
body: message.payload.into(),
|
||||
headers: message.options.map(|o| o.headers.0).unwrap_or_default(),
|
||||
headers: options.headers.0,
|
||||
invoke_key: message.invoke_key,
|
||||
};
|
||||
|
||||
@@ -293,9 +300,7 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
.entered();
|
||||
|
||||
// the channel data command is the only command that uses a custom protocol on Linux
|
||||
if webview.manager().webview.invoke_responder.is_none()
|
||||
&& cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND
|
||||
{
|
||||
if webview.manager().webview.invoke_responder.is_none() {
|
||||
fn responder_eval<R: Runtime>(
|
||||
webview: &crate::Webview<R>,
|
||||
js: crate::Result<String>,
|
||||
@@ -310,6 +315,10 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
let _ = webview.eval(&eval_js);
|
||||
}
|
||||
|
||||
let can_use_channel_for_response = cmd
|
||||
!= crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND
|
||||
&& !options.custom_protocol_ipc_blocked;
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _response_span = tracing::trace_span!(
|
||||
"ipc::request::response",
|
||||
@@ -327,6 +336,7 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
InvokeResponse::Ok(InvokeBody::Json(v)) => {
|
||||
if !(cfg!(target_os = "macos") || cfg!(target_os = "ios"))
|
||||
&& matches!(v, JsonValue::Object(_) | JsonValue::Array(_))
|
||||
&& can_use_channel_for_response
|
||||
{
|
||||
let _ = Channel::from_callback_fn(webview, callback).send(v);
|
||||
} else {
|
||||
@@ -338,7 +348,10 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, manager: &AppManager
|
||||
}
|
||||
}
|
||||
InvokeResponse::Ok(InvokeBody::Raw(v)) => {
|
||||
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
|
||||
if cfg!(target_os = "macos")
|
||||
|| cfg!(target_os = "ios")
|
||||
|| !can_use_channel_for_response
|
||||
{
|
||||
responder_eval(
|
||||
&webview,
|
||||
format_callback_result(Result::<_, ()>::Ok(v), callback, error),
|
||||
|
||||
Reference in New Issue
Block a user