diff --git a/.changes/remove-invoke-system-responder.md b/.changes/remove-invoke-system-responder.md new file mode 100644 index 000000000..78f90a232 --- /dev/null +++ b/.changes/remove-invoke-system-responder.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:breaking +--- + +Remove the `responder` part of a custom invoke system now that the responder can be set directly in the `tauri::WebviewWindow::on_message` function. diff --git a/crates/tauri/src/app.rs b/crates/tauri/src/app.rs index 272c63b30..c5e8ae856 100644 --- a/crates/tauri/src/app.rs +++ b/crates/tauri/src/app.rs @@ -5,8 +5,7 @@ use crate::{ image::Image, ipc::{ - channel::ChannelDataIpcQueue, CallbackFn, CommandArg, CommandItem, Invoke, InvokeError, - InvokeHandler, InvokeResponder, InvokeResponse, + channel::ChannelDataIpcQueue, CommandArg, CommandItem, Invoke, InvokeError, InvokeHandler, }, manager::{webview::UriSchemeProtocol, AppManager, Asset}, plugin::{Plugin, PluginStore}, @@ -1169,9 +1168,6 @@ pub struct Builder { /// The JS message handler. invoke_handler: Box>, - /// The JS message responder. - invoke_responder: Option>>, - /// The script that initializes the `window.__TAURI_INTERNALS__.postMessage` function. pub(crate) invoke_initialization_script: String, @@ -1248,7 +1244,6 @@ impl Builder { runtime_any_thread: false, setup: Box::new(|_| Ok(())), invoke_handler: Box::new(|_| false), - invoke_responder: None, invoke_initialization_script: InvokeInitializationScript { process_ipc_message_fn: crate::manager::webview::PROCESS_IPC_MESSAGE_FN, os_name: std::env::consts::OS, @@ -1312,8 +1307,6 @@ impl Builder { /// Defines a custom JS message system. /// - /// The `responder` is a function that will be called when a command has been executed and must send a response to the JS layer. - /// /// The `initialization_script` is a script that initializes `window.__TAURI_INTERNALS__.postMessage`. /// That function must take the `(message: object, options: object)` arguments and send it to the backend. /// @@ -1331,13 +1324,9 @@ impl Builder { /// /// Note that the implementation details is up to your implementation. #[must_use] - pub fn invoke_system(mut self, initialization_script: String, responder: F) -> Self - where - F: Fn(&Webview, &str, &InvokeResponse, CallbackFn, CallbackFn) + Send + Sync + 'static, - { + pub fn invoke_system(mut self, initialization_script: String) -> Self { self.invoke_initialization_script = initialization_script.replace("__INVOKE_KEY__", &format!("\"{}\"", self.invoke_key)); - self.invoke_responder.replace(Arc::new(responder)); self } @@ -1797,7 +1786,7 @@ tauri::Builder::default() self.webview_event_listeners, #[cfg(desktop)] HashMap::new(), - (self.invoke_responder, self.invoke_initialization_script), + self.invoke_initialization_script, self.invoke_key, )); diff --git a/crates/tauri/src/ipc/protocol.rs b/crates/tauri/src/ipc/protocol.rs index 23563251b..8252a9257 100644 --- a/crates/tauri/src/ipc/protocol.rs +++ b/crates/tauri/src/ipc/protocol.rs @@ -325,7 +325,6 @@ fn handle_ipc_message(request: Request, manager: &AppManager request, Box::new(move |webview, cmd, response, callback, error| { use crate::ipc::Channel; - use crate::sealed::ManagerBase; #[cfg(feature = "tracing")] let _respond_span = tracing::trace_span!( @@ -334,104 +333,101 @@ fn handle_ipc_message(request: Request, 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() { - fn responder_eval( - webview: &crate::Webview, - js: crate::Result, - error: CallbackFn, - ) { - let eval_js = match js { - Ok(js) => js, - Err(e) => crate::ipc::format_callback::format(error, &e.to_string()) - .expect("unable to serialize response error string to json"), - }; - - 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 mime_type = match &response { - InvokeResponse::Ok(InvokeResponseBody::Json(_)) => mime::APPLICATION_JSON, - InvokeResponse::Ok(InvokeResponseBody::Raw(_)) => mime::APPLICATION_OCTET_STREAM, - InvokeResponse::Err(_) => mime::APPLICATION_JSON, + fn responder_eval( + webview: &crate::Webview, + js: crate::Result, + error: CallbackFn, + ) { + let eval_js = match js { + Ok(js) => js, + Err(e) => crate::ipc::format_callback::format(error, &e.to_string()) + .expect("unable to serialize response error string to json"), }; - #[cfg(feature = "tracing")] - let _response_span = match &response { - InvokeResponse::Ok(InvokeResponseBody::Json(v)) => tracing::trace_span!( - "ipc::request::response", - response = v, - mime_type = mime_type.essence_str() - ) - .entered(), - InvokeResponse::Ok(InvokeResponseBody::Raw(v)) => tracing::trace_span!( - "ipc::request::response", - response = format!("{v:?}"), - mime_type = mime_type.essence_str() - ) - .entered(), - InvokeResponse::Err(e) => tracing::trace_span!( - "ipc::request::response", - response = format!("{e:?}"), - mime_type = mime_type.essence_str() - ) - .entered(), - }; + let _ = webview.eval(&eval_js); + } - match response { - InvokeResponse::Ok(InvokeResponseBody::Json(v)) => { - if !(cfg!(target_os = "macos") || cfg!(target_os = "ios")) - && (v.starts_with('{') || v.starts_with('[')) - && can_use_channel_for_response - { - let _ = Channel::from_callback_fn(webview, callback) - .send(InvokeResponseBody::Json(v)); - } else { - responder_eval( - &webview, - crate::ipc::format_callback::format_result_raw( - Result::<_, String>::Ok(v), - callback, - error, - ), + let can_use_channel_for_response = cmd + != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND + && !options.custom_protocol_ipc_blocked; + + #[cfg(feature = "tracing")] + let mime_type = match &response { + InvokeResponse::Ok(InvokeResponseBody::Json(_)) => mime::APPLICATION_JSON, + InvokeResponse::Ok(InvokeResponseBody::Raw(_)) => mime::APPLICATION_OCTET_STREAM, + InvokeResponse::Err(_) => mime::APPLICATION_JSON, + }; + + #[cfg(feature = "tracing")] + let _response_span = match &response { + InvokeResponse::Ok(InvokeResponseBody::Json(v)) => tracing::trace_span!( + "ipc::request::response", + response = v, + mime_type = mime_type.essence_str() + ) + .entered(), + InvokeResponse::Ok(InvokeResponseBody::Raw(v)) => tracing::trace_span!( + "ipc::request::response", + response = format!("{v:?}"), + mime_type = mime_type.essence_str() + ) + .entered(), + InvokeResponse::Err(e) => tracing::trace_span!( + "ipc::request::response", + response = format!("{e:?}"), + mime_type = mime_type.essence_str() + ) + .entered(), + }; + + match response { + InvokeResponse::Ok(InvokeResponseBody::Json(v)) => { + if !(cfg!(target_os = "macos") || cfg!(target_os = "ios")) + && (v.starts_with('{') || v.starts_with('[')) + && can_use_channel_for_response + { + let _ = + Channel::from_callback_fn(webview, callback).send(InvokeResponseBody::Json(v)); + } else { + responder_eval( + &webview, + crate::ipc::format_callback::format_result_raw( + Result::<_, String>::Ok(v), + callback, error, - ) - } - } - InvokeResponse::Ok(InvokeResponseBody::Raw(v)) => { - if cfg!(target_os = "macos") - || cfg!(target_os = "ios") - || !can_use_channel_for_response - { - responder_eval( - &webview, - crate::ipc::format_callback::format_result( - Result::<_, ()>::Ok(v), - callback, - error, - ), - error, - ); - } else { - let _ = Channel::from_callback_fn(webview, callback) - .send(InvokeResponseBody::Raw(v.clone())); - } - } - InvokeResponse::Err(e) => responder_eval( - &webview, - crate::ipc::format_callback::format_result( - Result::<(), _>::Err(&e.0), - callback, + ), error, - ), + ) + } + } + InvokeResponse::Ok(InvokeResponseBody::Raw(v)) => { + if cfg!(target_os = "macos") + || cfg!(target_os = "ios") + || !can_use_channel_for_response + { + responder_eval( + &webview, + crate::ipc::format_callback::format_result( + Result::<_, ()>::Ok(v), + callback, + error, + ), + error, + ); + } else { + let _ = Channel::from_callback_fn(webview, callback) + .send(InvokeResponseBody::Raw(v.clone())); + } + } + InvokeResponse::Err(e) => responder_eval( + &webview, + crate::ipc::format_callback::format_result( + Result::<(), _>::Err(&e.0), + callback, error, ), - } + error, + ), } }), ); @@ -593,7 +589,7 @@ mod tests { Default::default(), Default::default(), Default::default(), - (None, "".into()), + "".into(), crate::generate_invoke_key().unwrap(), ); @@ -706,7 +702,7 @@ mod tests { Default::default(), Default::default(), Default::default(), - (None, "".into()), + "".into(), crate::generate_invoke_key().unwrap(), ); diff --git a/crates/tauri/src/manager/mod.rs b/crates/tauri/src/manager/mod.rs index b09508623..00b13fef1 100644 --- a/crates/tauri/src/manager/mod.rs +++ b/crates/tauri/src/manager/mod.rs @@ -22,7 +22,7 @@ use tauri_utils::{ use crate::{ app::{AppHandle, GlobalWebviewEventListener, GlobalWindowEventListener, OnPageLoad}, event::{assert_event_name_is_valid, Event, EventId, EventTarget, Listeners}, - ipc::{Invoke, InvokeHandler, InvokeResponder, RuntimeAuthority}, + ipc::{Invoke, InvokeHandler, RuntimeAuthority}, plugin::PluginStore, utils::{config::Config, PackageInfo}, Assets, Context, Pattern, Runtime, StateManager, Window, @@ -254,7 +254,7 @@ impl AppManager { String, crate::app::GlobalMenuEventListener>, >, - (invoke_responder, invoke_initialization_script): (Option>>, String), + invoke_initialization_script: String, invoke_key: String, ) -> Self { // generate a random isolation key at runtime @@ -276,7 +276,6 @@ impl AppManager { on_page_load, uri_scheme_protocols: Mutex::new(uri_scheme_protocols), event_listeners: Arc::new(webiew_event_listeners), - invoke_responder, invoke_initialization_script, invoke_key: invoke_key.clone(), }, @@ -731,7 +730,7 @@ mod test { Default::default(), Default::default(), Default::default(), - (None, "".into()), + "".into(), crate::generate_invoke_key().unwrap(), ); diff --git a/crates/tauri/src/manager/webview.rs b/crates/tauri/src/manager/webview.rs index ebb0f3f96..0ea38e93d 100644 --- a/crates/tauri/src/manager/webview.rs +++ b/crates/tauri/src/manager/webview.rs @@ -21,7 +21,7 @@ use url::Url; use crate::{ app::{GlobalWebviewEventListener, OnPageLoad, UriSchemeResponder, WebviewEvent}, - ipc::{InvokeHandler, InvokeResponder}, + ipc::InvokeHandler, pattern::PatternJavascript, sealed::ManagerBase, webview::PageLoadPayload, @@ -75,8 +75,6 @@ pub struct WebviewManager { /// Webview event listeners to all webviews. pub event_listeners: Arc>>, - /// Responder for invoke calls. - pub invoke_responder: Option>>, /// The script that initializes the invoke system. pub invoke_initialization_script: String, diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index 6ec49a8db..b26dec6bf 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -1136,17 +1136,11 @@ fn main() { return; } - let custom_responder = self.manager().webview.invoke_responder.clone(); - let resolver = InvokeResolver::new( self.clone(), Arc::new(Mutex::new(Some(Box::new( #[allow(unused_variables)] move |webview: Webview, cmd, response, callback, error| { - if let Some(responder) = &custom_responder { - (responder)(&webview, &cmd, &response, callback, error); - } - responder(webview, cmd, response, callback, error); }, )))),