mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-16 11:20:28 +03:00
This commit is contained in:
parent
c68218b362
commit
a77be97474
5
.changes/ipc-post-message-fallback.md
Normal file
5
.changes/ipc-post-message-fallback.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:enhance
|
||||
---
|
||||
|
||||
Fallback to the postMessage IPC interface if we cannot reach the IPC custom protocol.
|
@ -217,11 +217,6 @@ fn main() {
|
||||
alias("desktop", !mobile);
|
||||
alias("mobile", mobile);
|
||||
|
||||
alias(
|
||||
"ipc_custom_protocol",
|
||||
target_os != "android" && (target_os != "linux" || has_feature("linux-ipc-protocol")),
|
||||
);
|
||||
|
||||
let out_dir = PathBuf::from(var("OUT_DIR").unwrap());
|
||||
|
||||
let checked_features_out_path = out_dir.join("checked_features");
|
||||
|
@ -6,26 +6,20 @@
|
||||
const processIpcMessage = __RAW_process_ipc_message_fn__
|
||||
const osName = __TEMPLATE_os_name__
|
||||
const fetchChannelDataCommand = __TEMPLATE_fetch_channel_data_command__
|
||||
const useCustomProtocol = __TEMPLATE_use_custom_protocol__
|
||||
const linuxIpcProtocolEnabled = __TEMPLATE_linux_ipc_protocol_enabled__
|
||||
let customProtocolIpcFailed = false
|
||||
|
||||
Object.defineProperty(window.__TAURI_INTERNALS__, 'postMessage', {
|
||||
value: (message) => {
|
||||
// on Linux we only use the custom-protocol-based IPC if the the linux-ipc-protocol Cargo feature is enabled
|
||||
// on Android we never use it because Android does not have support to reading the request body
|
||||
const canUseCustomProtocol =
|
||||
osName === 'linux' ? linuxIpcProtocolEnabled : osName !== 'android'
|
||||
|
||||
function sendIpcMessage(message) {
|
||||
const { cmd, callback, error, payload, options } = message
|
||||
|
||||
// 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' || osName === 'ios') &&
|
||||
location.protocol === 'https:'
|
||||
)
|
||||
!customProtocolIpcFailed &&
|
||||
(canUseCustomProtocol || cmd === fetchChannelDataCommand)
|
||||
) {
|
||||
const { contentType, data } = processIpcMessage(payload)
|
||||
fetch(window.__TAURI_INTERNALS__.convertFileSrc(cmd, 'ipc'), {
|
||||
@ -41,9 +35,7 @@
|
||||
.then((response) => {
|
||||
const cb = response.ok ? callback : error
|
||||
// we need to split here because on Android the content-type gets duplicated
|
||||
switch (
|
||||
(response.headers.get('content-type') || '').split(',')[0]
|
||||
) {
|
||||
switch ((response.headers.get('content-type') || '').split(',')[0]) {
|
||||
case 'application/json':
|
||||
return response.json().then((r) => [cb, r])
|
||||
case 'text/plain':
|
||||
@ -61,6 +53,12 @@
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// failed to use the custom protocol IPC (either the webview blocked a custom protocol or it was a CSP error)
|
||||
// so we need to fallback to the postMessage interface
|
||||
customProtocolIpcFailed = true
|
||||
sendIpcMessage(message)
|
||||
})
|
||||
} else {
|
||||
// otherwise use the postMessage interface
|
||||
const { data } = processIpcMessage({
|
||||
@ -73,5 +71,8 @@
|
||||
window.ipc.postMessage(data)
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(window.__TAURI_INTERNALS__, 'postMessage', {
|
||||
value: sendIpcMessage
|
||||
})
|
||||
})()
|
||||
|
@ -1084,7 +1084,7 @@ struct InvokeInitializationScript<'a> {
|
||||
process_ipc_message_fn: &'a str,
|
||||
os_name: &'a str,
|
||||
fetch_channel_data_command: &'a str,
|
||||
use_custom_protocol: bool,
|
||||
linux_ipc_protocol_enabled: bool,
|
||||
}
|
||||
|
||||
/// Make `Wry` the default `Runtime` for `Builder`
|
||||
@ -1117,7 +1117,7 @@ impl<R: Runtime> Builder<R> {
|
||||
process_ipc_message_fn: crate::manager::webview::PROCESS_IPC_MESSAGE_FN,
|
||||
os_name: std::env::consts::OS,
|
||||
fetch_channel_data_command: crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND,
|
||||
use_custom_protocol: cfg!(ipc_custom_protocol),
|
||||
linux_ipc_protocol_enabled: cfg!(feature = "linux-ipc-protocol"),
|
||||
}
|
||||
.render_default(&Default::default())
|
||||
.unwrap()
|
||||
|
@ -21,7 +21,6 @@ use crate::{webview::Webview, Runtime, StateManager};
|
||||
mod authority;
|
||||
pub(crate) mod channel;
|
||||
mod command;
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", not(ipc_custom_protocol)))]
|
||||
pub(crate) mod format_callback;
|
||||
pub(crate) mod protocol;
|
||||
|
||||
|
@ -19,7 +19,6 @@ use super::{CallbackFn, InvokeBody, InvokeResponse};
|
||||
const TAURI_CALLBACK_HEADER_NAME: &str = "Tauri-Callback";
|
||||
const TAURI_ERROR_HEADER_NAME: &str = "Tauri-Error";
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", not(ipc_custom_protocol)))]
|
||||
pub fn message_handler<R: Runtime>(
|
||||
manager: Arc<AppManager<R>>,
|
||||
) -> crate::runtime::webview::WebviewIpcHandler<crate::EventLoopMessage, R> {
|
||||
@ -162,7 +161,6 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", not(ipc_custom_protocol)))]
|
||||
fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, label: &str) {
|
||||
if let Some(webview) = manager.get_webview(label) {
|
||||
#[cfg(feature = "tracing")]
|
||||
@ -374,9 +372,14 @@ fn parse_invoke_request<R: Runtime>(
|
||||
.decode_utf8_lossy()
|
||||
.to_string();
|
||||
|
||||
// the body is not set if ipc_custom_protocol is not enabled so we'll just ignore it
|
||||
#[cfg(all(feature = "isolation", ipc_custom_protocol))]
|
||||
// on Android and on Linux (without the linux-ipc-protocol Cargo feature) we cannot read the request body
|
||||
// so we must ignore it because some commands use the IPC for faster response
|
||||
let has_payload = !body.is_empty();
|
||||
|
||||
#[cfg(feature = "isolation")]
|
||||
if let crate::Pattern::Isolation { crypto_keys, .. } = &*manager.pattern {
|
||||
// if the platform does not support request body, we ignore it
|
||||
if has_payload {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered();
|
||||
|
||||
@ -384,6 +387,7 @@ fn parse_invoke_request<R: Runtime>(
|
||||
.and_then(|raw| crypto_keys.decrypt(raw))
|
||||
.map_err(|e| e.to_string())?;
|
||||
}
|
||||
}
|
||||
|
||||
let callback = CallbackFn(
|
||||
parts
|
||||
@ -420,12 +424,12 @@ fn parse_invoke_request<R: Runtime>(
|
||||
let body = if content_type == mime::APPLICATION_OCTET_STREAM {
|
||||
body.into()
|
||||
} else if content_type == mime::APPLICATION_JSON {
|
||||
if cfg!(ipc_custom_protocol) {
|
||||
// if the platform does not support request body, we ignore it
|
||||
if has_payload {
|
||||
serde_json::from_slice::<serde_json::Value>(&body)
|
||||
.map_err(|e| e.to_string())?
|
||||
.into()
|
||||
} else {
|
||||
// the body is not set if ipc_custom_protocol is not enabled so we'll just ignore it
|
||||
serde_json::Value::Object(Default::default()).into()
|
||||
}
|
||||
} else {
|
||||
|
@ -496,12 +496,9 @@ impl<R: Runtime> WebviewManager<R> {
|
||||
manager,
|
||||
)?;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", not(ipc_custom_protocol)))]
|
||||
{
|
||||
pending.ipc_handler = Some(crate::ipc::protocol::message_handler(
|
||||
manager.manager_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
// in `windows`, we need to force a data_directory
|
||||
// but we do respect user-specification
|
||||
|
Loading…
Reference in New Issue
Block a user