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

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
This commit is contained in:
Lucas Fernandes Nogueira 2023-09-05 12:41:05 -03:00 committed by GitHub
parent e98393e499
commit 29818de682
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 20 deletions

View File

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

View File

@ -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

View File

@ -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)
}
}

View File

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

View File

@ -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};

View File

@ -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)

View File

@ -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()));
}

View File

@ -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::{