소스 검색

fix(core): use postMessage IPC for remote URLs on macOS closes #7662 (#7751)

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
Lucas Fernandes Nogueira 1 년 전
부모
커밋
29818de682

+ 5 - 0
.changes/fix-ipc-remote-url-macos.md

@@ -0,0 +1,5 @@
+---
+"tauri": patch:bug
+---
+
+Fixes IPC failing to communicate for remote URLs on macOS.

+ 10 - 9
core/tauri-runtime-wry/src/lib.rs

@@ -94,6 +94,7 @@ use std::{
   fmt,
   ops::Deref,
   path::PathBuf,
+  rc::Rc,
   sync::{
     mpsc::{channel, Sender},
     Arc, Mutex, Weak,
@@ -227,7 +228,7 @@ impl<T: UserEvent> Context<T> {
 pub struct DispatcherMainThreadContext<T: UserEvent> {
   pub window_target: EventLoopWindowTarget<Message<T>>,
   pub web_context: WebContextStore,
-  pub windows: Arc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
+  pub windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
 }
 
 impl<T: UserEvent> std::fmt::Debug for DispatcherMainThreadContext<T> {
@@ -1544,7 +1545,7 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
 #[derive(Clone)]
 enum WindowHandle {
   Webview {
-    inner: Arc<WebView>,
+    inner: Rc<WebView>,
     context_store: WebContextStore,
     // the key of the WebContext if it's not shared
     context_key: Option<PathBuf>,
@@ -1560,7 +1561,7 @@ impl Drop for WindowHandle {
       context_key,
     } = self
     {
-      if Arc::get_mut(inner).is_some() {
+      if Rc::get_mut(inner).is_some() {
         context_store.lock().unwrap().remove(context_key);
       }
     }
@@ -1816,7 +1817,7 @@ impl<T: UserEvent> Wry<T> {
     let main_thread_id = current_thread().id();
     let web_context = WebContextStore::default();
 
-    let windows = Arc::new(RefCell::new(HashMap::default()));
+    let windows = Rc::new(RefCell::new(HashMap::default()));
     let webview_id_map = WebviewIdStore::default();
 
     let context = Context {
@@ -2056,11 +2057,11 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
 pub struct EventLoopIterationContext<'a, T: UserEvent> {
   pub callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
   pub webview_id_map: WebviewIdStore,
-  pub windows: Arc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
+  pub windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
 }
 
 struct UserMessageContext {
-  windows: Arc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
+  windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
   webview_id_map: WebviewIdStore,
 }
 
@@ -2529,7 +2530,7 @@ fn handle_event_loop<T: UserEvent>(
 fn on_close_requested<'a, T: UserEvent>(
   callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
   window_id: WebviewId,
-  windows: Arc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
+  windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
 ) {
   let (tx, rx) = channel();
   let windows_ref = windows.borrow();
@@ -2557,7 +2558,7 @@ fn on_close_requested<'a, T: UserEvent>(
   }
 }
 
-fn on_window_close(window_id: WebviewId, windows: Arc<RefCell<HashMap<WebviewId, WindowWrapper>>>) {
+fn on_window_close(window_id: WebviewId, windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>) {
   if let Some(window_wrapper) = windows.borrow_mut().get_mut(&window_id) {
     window_wrapper.inner = None;
   }
@@ -2803,7 +2804,7 @@ fn create_webview<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
   Ok(WindowWrapper {
     label,
     inner: Some(WindowHandle::Webview {
-      inner: Arc::new(webview),
+      inner: Rc::new(webview),
       context_store: web_context_store.clone(),
       context_key: if automation_enabled {
         None

+ 35 - 5
core/tauri/scripts/ipc-protocol.js

@@ -10,11 +10,33 @@
 
   Object.defineProperty(window, '__TAURI_POST_MESSAGE__', {
     value: (message) => {
-      const { cmd, callback, error, payload, options } = message
+      const {
+        cmd,
+        callback,
+        error,
+        payload,
+        options
+      } = message
 
-      // use custom protocol for IPC if the flag is set to true, the command is the fetch data command or when not on Linux/Android
-      if (useCustomProtocol || cmd === fetchChannelDataCommand || (osName !== 'linux' && osName !== 'android')) {
-        const { contentType, data } = processIpcMessage(payload)
+      // use custom protocol for IPC if:
+      // - the flag is set to true or
+      // - the command is the fetch data command or
+      // - when not on Linux/Android
+      // AND
+      // - when not on macOS with an https URL
+      if (
+        (
+          useCustomProtocol ||
+          cmd === fetchChannelDataCommand ||
+          !(osName === 'linux' || osName === 'android')
+        ) &&
+        !(osName === 'macos' && location.protocol === 'https:')
+      ) {
+        console.log('process')
+        const {
+          contentType,
+          data
+        } = processIpcMessage(payload)
         fetch(window.__TAURI__.convertFileSrc(cmd, 'ipc'), {
           method: 'POST',
           body: data,
@@ -44,7 +66,15 @@
         })
       } else {
         // otherwise use the postMessage interface
-        const { data } = processIpcMessage({ cmd, callback, error, options, payload })
+        const {
+          data
+        } = processIpcMessage({
+          cmd,
+          callback,
+          error,
+          options,
+          payload
+        })
         window.ipc.postMessage(data)
       }
     }

+ 0 - 1
core/tauri/src/ipc/mod.rs

@@ -21,7 +21,6 @@ use crate::{
 };
 
 pub(crate) mod channel;
-#[cfg(not(ipc_custom_protocol))]
 pub(crate) mod format_callback;
 pub(crate) mod protocol;
 

+ 2 - 2
core/tauri/src/ipc/protocol.rs

@@ -19,7 +19,7 @@ use super::{CallbackFn, InvokeBody, InvokeResponse};
 const TAURI_CALLBACK_HEADER_NAME: &str = "Tauri-Callback";
 const TAURI_ERROR_HEADER_NAME: &str = "Tauri-Error";
 
-#[cfg(not(ipc_custom_protocol))]
+#[cfg(any(target_os = "macos", not(ipc_custom_protocol)))]
 pub fn message_handler<R: Runtime>(
   manager: WindowManager<R>,
 ) -> crate::runtime::webview::WebviewIpcHandler<crate::EventLoopMessage, R> {
@@ -87,7 +87,7 @@ pub fn get<R: Runtime>(manager: WindowManager<R>, label: String) -> UriSchemePro
   })
 }
 
-#[cfg(not(ipc_custom_protocol))]
+#[cfg(any(target_os = "macos", not(ipc_custom_protocol)))]
 fn handle_ipc_message<R: Runtime>(message: String, manager: &WindowManager<R>, label: &str) {
   if let Some(window) = manager.get_window(label) {
     use serde::{Deserialize, Deserializer};

+ 2 - 1
core/tauri/src/lib.rs

@@ -919,7 +919,8 @@ macro_rules! run_main_thread {
     let (tx, rx) = channel();
     let self_ = $self.clone();
     let task = move || {
-      let _ = tx.send($ex(self_));
+      let f = $ex;
+      let _ = tx.send(f(self_));
     };
     $self.app_handle.run_on_main_thread(Box::new(task))?;
     rx.recv().map_err(|_| crate::Error::FailedToReceiveMessage)

+ 2 - 1
core/tauri/src/manager.rs

@@ -1188,7 +1188,8 @@ impl<R: Runtime> WindowManager<R> {
       #[allow(clippy::redundant_clone)]
       app_handle.clone(),
     )?;
-    #[cfg(not(ipc_custom_protocol))]
+
+    #[cfg(any(target_os = "macos", not(ipc_custom_protocol)))]
     {
       pending.ipc_handler = Some(crate::ipc::protocol::message_handler(self.clone()));
     }

+ 2 - 1
core/tauri/src/window.rs

@@ -2099,7 +2099,8 @@ impl<R: Runtime> Window<R> {
       Arc::new(
         #[allow(unused_variables)]
         move |window: Window<R>, cmd, response, callback, error| {
-          #[cfg(not(ipc_custom_protocol))]
+          if (cfg!(target_os = "macos") && window.url().scheme() == "https")
+            || !cfg!(ipc_custom_protocol)
           {
             use crate::ipc::{
               format_callback::{