From 29818de682146a75cd9a886f7b215154cad1d42d Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Tue, 5 Sep 2023 12:41:05 -0300 Subject: [PATCH] fix(core): use postMessage IPC for remote URLs on macOS closes #7662 (#7751) Co-authored-by: Amr Bashir --- .changes/fix-ipc-remote-url-macos.md | 5 ++++ core/tauri-runtime-wry/src/lib.rs | 19 ++++++------- core/tauri/scripts/ipc-protocol.js | 40 ++++++++++++++++++++++++---- core/tauri/src/ipc/mod.rs | 1 - core/tauri/src/ipc/protocol.rs | 4 +-- core/tauri/src/lib.rs | 3 ++- core/tauri/src/manager.rs | 3 ++- core/tauri/src/window.rs | 3 ++- 8 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 .changes/fix-ipc-remote-url-macos.md diff --git a/.changes/fix-ipc-remote-url-macos.md b/.changes/fix-ipc-remote-url-macos.md new file mode 100644 index 000000000..915ebee4e --- /dev/null +++ b/.changes/fix-ipc-remote-url-macos.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:bug +--- + +Fixes IPC failing to communicate for remote URLs on macOS. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index f19c7435a..2e9752c9e 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/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 Context { pub struct DispatcherMainThreadContext { pub window_target: EventLoopWindowTarget>, pub web_context: WebContextStore, - pub windows: Arc>>, + pub windows: Rc>>, } impl std::fmt::Debug for DispatcherMainThreadContext { @@ -1544,7 +1545,7 @@ impl Dispatch for WryDispatcher { #[derive(Clone)] enum WindowHandle { Webview { - inner: Arc, + inner: Rc, context_store: WebContextStore, // the key of the WebContext if it's not shared context_key: Option, @@ -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 Wry { 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 Runtime for Wry { pub struct EventLoopIterationContext<'a, T: UserEvent> { pub callback: &'a mut (dyn FnMut(RunEvent) + 'static), pub webview_id_map: WebviewIdStore, - pub windows: Arc>>, + pub windows: Rc>>, } struct UserMessageContext { - windows: Arc>>, + windows: Rc>>, webview_id_map: WebviewIdStore, } @@ -2529,7 +2530,7 @@ fn handle_event_loop( fn on_close_requested<'a, T: UserEvent>( callback: &'a mut (dyn FnMut(RunEvent) + 'static), window_id: WebviewId, - windows: Arc>>, + windows: Rc>>, ) { 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>>) { +fn on_window_close(window_id: WebviewId, windows: Rc>>) { if let Some(window_wrapper) = windows.borrow_mut().get_mut(&window_id) { window_wrapper.inner = None; } @@ -2803,7 +2804,7 @@ fn create_webview( 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 diff --git a/core/tauri/scripts/ipc-protocol.js b/core/tauri/scripts/ipc-protocol.js index 8d3ac764e..b2af9c478 100644 --- a/core/tauri/scripts/ipc-protocol.js +++ b/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) } } diff --git a/core/tauri/src/ipc/mod.rs b/core/tauri/src/ipc/mod.rs index c55db11c2..66579fbbe 100644 --- a/core/tauri/src/ipc/mod.rs +++ b/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; diff --git a/core/tauri/src/ipc/protocol.rs b/core/tauri/src/ipc/protocol.rs index f0cd1d06e..e2a0330d1 100644 --- a/core/tauri/src/ipc/protocol.rs +++ b/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( manager: WindowManager, ) -> crate::runtime::webview::WebviewIpcHandler { @@ -87,7 +87,7 @@ pub fn get(manager: WindowManager, label: String) -> UriSchemePro }) } -#[cfg(not(ipc_custom_protocol))] +#[cfg(any(target_os = "macos", not(ipc_custom_protocol)))] fn handle_ipc_message(message: String, manager: &WindowManager, label: &str) { if let Some(window) = manager.get_window(label) { use serde::{Deserialize, Deserializer}; diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 2665821b5..a6135c181 100644 --- a/core/tauri/src/lib.rs +++ b/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) diff --git a/core/tauri/src/manager.rs b/core/tauri/src/manager.rs index b5cccd324..90886ec3d 100644 --- a/core/tauri/src/manager.rs +++ b/core/tauri/src/manager.rs @@ -1188,7 +1188,8 @@ impl WindowManager { #[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())); } diff --git a/core/tauri/src/window.rs b/core/tauri/src/window.rs index 55a91154d..bfb22f47c 100644 --- a/core/tauri/src/window.rs +++ b/core/tauri/src/window.rs @@ -2099,7 +2099,8 @@ impl Window { Arc::new( #[allow(unused_variables)] move |window: Window, 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::{