Browse Source

refactor(core): remove responder from custom invoke systems (#11027)

* refactor(core): remove responder from custom invoke systems

the responder can be set directly in the WebviewWindow::on_message call

* fix tests
Lucas Fernandes Nogueira 10 months ago
parent
commit
551e0624a9

+ 5 - 0
.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.

+ 3 - 14
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<R: Runtime> {
   /// The JS message handler.
   invoke_handler: Box<InvokeHandler<R>>,
 
-  /// The JS message responder.
-  invoke_responder: Option<Arc<InvokeResponder<R>>>,
-
   /// The script that initializes the `window.__TAURI_INTERNALS__.postMessage` function.
   pub(crate) invoke_initialization_script: String,
 
@@ -1248,7 +1244,6 @@ impl<R: Runtime> Builder<R> {
       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<R: Runtime> Builder<R> {
 
   /// 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<R: Runtime> Builder<R> {
   ///
   /// Note that the implementation details is up to your implementation.
   #[must_use]
-  pub fn invoke_system<F>(mut self, initialization_script: String, responder: F) -> Self
-  where
-    F: Fn(&Webview<R>, &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,
     ));
 

+ 87 - 91
crates/tauri/src/ipc/protocol.rs

@@ -325,7 +325,6 @@ fn handle_ipc_message<R: Runtime>(request: Request<String>, 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<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() {
-              fn responder_eval<R: Runtime>(
-                webview: &crate::Webview<R>,
-                js: crate::Result<String>,
-                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);
-              }
+            fn responder_eval<R: Runtime>(
+              webview: &crate::Webview<R>,
+              js: crate::Result<String>,
+              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 can_use_channel_for_response = cmd
-                != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND
-                && !options.custom_protocol_ipc_blocked;
+              let _ = webview.eval(&eval_js);
+            }
 
-              #[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,
-              };
+            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 = 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(),
-              };
+            #[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,
+            };
 
-              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,
-                      ),
+            #[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,
-                    )
-                  }
+                    ),
+                    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,
-                      ),
+              }
+              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,
-                    );
-                  } 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,
-                  ),
+                  );
+                } 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(),
     );
 

+ 3 - 4
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<R: Runtime> AppManager<R> {
       String,
       crate::app::GlobalMenuEventListener<Window<R>>,
     >,
-    (invoke_responder, invoke_initialization_script): (Option<Arc<InvokeResponder<R>>>, String),
+    invoke_initialization_script: String,
     invoke_key: String,
   ) -> Self {
     // generate a random isolation key at runtime
@@ -276,7 +276,6 @@ impl<R: Runtime> AppManager<R> {
         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(),
     );
 

+ 1 - 3
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<R: Runtime> {
   /// Webview event listeners to all webviews.
   pub event_listeners: Arc<Vec<GlobalWebviewEventListener<R>>>,
 
-  /// Responder for invoke calls.
-  pub invoke_responder: Option<Arc<InvokeResponder<R>>>,
   /// The script that initializes the invoke system.
   pub invoke_initialization_script: String,
 

+ 0 - 6
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<R>, cmd, response, callback, error| {
-          if let Some(responder) = &custom_responder {
-            (responder)(&webview, &cmd, &response, callback, error);
-          }
-
           responder(webview, cmd, response, callback, error);
         },
       )))),