mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-10-26 09:58:16 +03:00
Merge pull request from GHSA-57fm-592m-34r7
* add __TAURI_INVOKE_KEY__ to ipc calls to detect initialized frames * move ipc key check to start of on_message * cargo +nightly fmt * undo Cargo.toml formatting changes * undo Cargo.toml formatting changes * undo Cargo.toml formatting changes * remove merged changefiles * undo formatting changes to js files * undo formatting changes to js files * Update to patched wry release * fix: optional chaining is not supported on older webviews (#9529) * Revert "undo formatting changes to js files" This reverts commit a7ef0d91ea1b183e091ea65a2b201d65522cc1d5. * Revert "undo formatting changes to js files" This reverts commit 0fcfd4664b915af51b71e7ea68929fd5b6cb5fc3. * revert core.js * inject __TAURI_INVOKE_KEY__ to __TAURI_IPC__ instead * remove unrelated changes file * remove left over dbg! call * change file --------- Co-authored-by: Tillmann <28728469+tweidinger@users.noreply.github.com> Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
This commit is contained in:
parent
50aabad1f6
commit
f6d81dfe08
6
.changes/ipc-only-main-frame.md
Normal file
6
.changes/ipc-only-main-frame.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:sec
|
||||||
|
"tauri-runtime-wry": patch:sec
|
||||||
|
---
|
||||||
|
|
||||||
|
Only process IPC commands from the main frame.
|
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -4036,6 +4036,7 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"flate2",
|
"flate2",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"getrandom 0.2.14",
|
||||||
"glib",
|
"glib",
|
||||||
"glob",
|
"glob",
|
||||||
"gtk",
|
"gtk",
|
||||||
@ -5515,9 +5516,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.24.8"
|
version = "0.24.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a04e72739ee84a218e3dbf8625888eadc874285637003ed21ab96a1bbbb538ec"
|
checksum = "00711278ed357350d44c749c286786ecac644e044e4da410d466212152383b45"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"block",
|
"block",
|
||||||
|
@ -13,7 +13,7 @@ exclude = [ "CHANGELOG.md", "/target" ]
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wry = { version = "0.24.6", default-features = false, features = [ "file-drop", "protocol" ] }
|
wry = { version = "0.24.10", default-features = false, features = [ "file-drop", "protocol" ] }
|
||||||
tauri-runtime = { version = "0.14.3", path = "../tauri-runtime" }
|
tauri-runtime = { version = "0.14.3", path = "../tauri-runtime" }
|
||||||
tauri-utils = { version = "1.5.4", path = "../tauri-utils" }
|
tauri-utils = { version = "1.5.4", path = "../tauri-utils" }
|
||||||
uuid = { version = "1", features = [ "v4" ] }
|
uuid = { version = "1", features = [ "v4" ] }
|
||||||
|
@ -96,6 +96,7 @@ encoding_rs = "0.8.31"
|
|||||||
sys-locale = { version = "0.2.3", optional = true }
|
sys-locale = { version = "0.2.3", optional = true }
|
||||||
tracing = { version = "0.1", optional = true }
|
tracing = { version = "0.1", optional = true }
|
||||||
indexmap = { version = "1", features = [ "std", "serde" ], optional = true }
|
indexmap = { version = "1", features = [ "std", "serde" ], optional = true }
|
||||||
|
getrandom = { version = "0.2", features = [ "std" ] }
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||||
rfd = { version = "0.10", optional = true, features = [ "gtk3", "common-controls-v6" ] }
|
rfd = { version = "0.10", optional = true, features = [ "gtk3", "common-controls-v6" ] }
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
; (function () {
|
;(function() {
|
||||||
__RAW_freeze_prototype__
|
__RAW_freeze_prototype__
|
||||||
|
|
||||||
; (function () {
|
;(function() {
|
||||||
__RAW_hotkeys__
|
__RAW_hotkeys__
|
||||||
})()
|
})()
|
||||||
|
|
||||||
__RAW_pattern_script__
|
__RAW_pattern_script__
|
||||||
|
|
||||||
__RAW_ipc_script__
|
__RAW_ipc_script__
|
||||||
; (function () {
|
;(function() {
|
||||||
__RAW_bundle_script__
|
__RAW_bundle_script__
|
||||||
})()
|
})()
|
||||||
|
|
||||||
__RAW_listen_function__
|
__RAW_listen_function__
|
||||||
|
|
||||||
@ -22,11 +22,5 @@
|
|||||||
|
|
||||||
__RAW_event_initialization_script__
|
__RAW_event_initialization_script__
|
||||||
|
|
||||||
if (window.ipc) {
|
window.__TAURI_INVOKE__('__initialized', { url: window.location.href })
|
||||||
window.__TAURI_INVOKE__('__initialized', { url: window.location.href })
|
|
||||||
} else {
|
|
||||||
window.addEventListener('DOMContentLoaded', function () {
|
|
||||||
window.__TAURI_INVOKE__('__initialized', { url: window.location.href })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})()
|
})()
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
;
|
;
|
||||||
(function () {
|
(function() {
|
||||||
/**
|
/**
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
@ -18,6 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
const isolationOrigin = __TEMPLATE_isolation_origin__
|
const isolationOrigin = __TEMPLATE_isolation_origin__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A runtime generated key to ensure an IPC call comes from an initialized frame.
|
||||||
|
*
|
||||||
|
* This is declared outside the `window.__TAURI_INVOKE__` definition to prevent
|
||||||
|
* the key from being leaked by `window.__TAURI_INVOKE__.toString()`.
|
||||||
|
* @var {string} __TEMPLATE_invoke_key__
|
||||||
|
*/
|
||||||
|
const __TAURI_INVOKE_KEY__ = __TEMPLATE_invoke_key__
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {{queue: object[], ready: boolean, frame: HTMLElement | null}}
|
* @type {{queue: object[], ready: boolean, frame: HTMLElement | null}}
|
||||||
*/
|
*/
|
||||||
@ -85,6 +94,7 @@
|
|||||||
Object.defineProperty(window, '__TAURI_IPC__', {
|
Object.defineProperty(window, '__TAURI_IPC__', {
|
||||||
// todo: JSDoc this function
|
// todo: JSDoc this function
|
||||||
value: Object.freeze((message) => {
|
value: Object.freeze((message) => {
|
||||||
|
message.__TAURI_INVOKE_KEY__ = __TAURI_INVOKE_KEY__
|
||||||
switch (pattern) {
|
switch (pattern) {
|
||||||
case 'brownfield':
|
case 'brownfield':
|
||||||
window.__TAURI_POST_MESSAGE__(message)
|
window.__TAURI_POST_MESSAGE__(message)
|
||||||
|
@ -1569,6 +1569,7 @@ impl<R: Runtime> Builder<R> {
|
|||||||
self.window_event_listeners,
|
self.window_event_listeners,
|
||||||
(self.menu, self.menu_event_listeners),
|
(self.menu, self.menu_event_listeners),
|
||||||
(self.invoke_responder, self.invoke_initialization_script),
|
(self.invoke_responder, self.invoke_initialization_script),
|
||||||
|
crate::generate_invoke_key()?,
|
||||||
);
|
);
|
||||||
|
|
||||||
let http_scheme = manager.config().tauri.security.dangerous_use_http_scheme;
|
let http_scheme = manager.config().tauri.security.dangerous_use_http_scheme;
|
||||||
|
@ -131,6 +131,12 @@ pub enum Error {
|
|||||||
/// The Window's raw handle is invalid for the platform.
|
/// The Window's raw handle is invalid for the platform.
|
||||||
#[error("Unexpected `raw_window_handle` for the current platform")]
|
#[error("Unexpected `raw_window_handle` for the current platform")]
|
||||||
InvalidWindowHandle,
|
InvalidWindowHandle,
|
||||||
|
/// Something went wrong with the CSPRNG.
|
||||||
|
#[error("unable to generate random bytes from the operating system: {0}")]
|
||||||
|
Csprng(#[from] getrandom::Error),
|
||||||
|
/// Bad `__TAURI_INVOKE_KEY__` value received in ipc message.
|
||||||
|
#[error("bad __TAURI_INVOKE_KEY__ value received in ipc message")]
|
||||||
|
InvokeKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_anyhow<T: std::fmt::Display>(err: T) -> anyhow::Error {
|
pub(crate) fn into_anyhow<T: std::fmt::Display>(err: T) -> anyhow::Error {
|
||||||
|
@ -35,6 +35,7 @@ pub type OnPageLoad<R> = dyn Fn(Window<R>, PageLoadPayload) + Send + Sync + 'sta
|
|||||||
#[default_template("../scripts/ipc.js")]
|
#[default_template("../scripts/ipc.js")]
|
||||||
pub(crate) struct IpcJavascript<'a> {
|
pub(crate) struct IpcJavascript<'a> {
|
||||||
pub(crate) isolation_origin: &'a str,
|
pub(crate) isolation_origin: &'a str,
|
||||||
|
pub(crate) invoke_key: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "isolation")]
|
#[cfg(feature = "isolation")]
|
||||||
@ -66,6 +67,10 @@ pub struct InvokePayload {
|
|||||||
#[serde(rename = "__tauriModule")]
|
#[serde(rename = "__tauriModule")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub tauri_module: Option<String>,
|
pub tauri_module: Option<String>,
|
||||||
|
/// A secret key that only Tauri initialized frames have.
|
||||||
|
#[serde(rename = "__TAURI_INVOKE_KEY__")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub invoke_key: Option<String>,
|
||||||
/// The success callback.
|
/// The success callback.
|
||||||
pub callback: CallbackFn,
|
pub callback: CallbackFn,
|
||||||
/// The error callback.
|
/// The error callback.
|
||||||
|
@ -1091,3 +1091,52 @@ mod test_utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Simple dependency-free string encoder using [Z85].
|
||||||
|
mod z85 {
|
||||||
|
const TABLE: &[u8; 85] =
|
||||||
|
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#";
|
||||||
|
|
||||||
|
/// Encode bytes with [Z85].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Will panic if the input bytes are not a multiple of 4.
|
||||||
|
pub fn encode(bytes: &[u8]) -> String {
|
||||||
|
assert_eq!(bytes.len() % 4, 0);
|
||||||
|
|
||||||
|
let mut buf = String::with_capacity(bytes.len() * 5 / 4);
|
||||||
|
for chunk in bytes.chunks_exact(4) {
|
||||||
|
let mut chars = [0u8; 5];
|
||||||
|
let mut chunk = u32::from_be_bytes(chunk.try_into().unwrap()) as usize;
|
||||||
|
for byte in chars.iter_mut().rev() {
|
||||||
|
*byte = TABLE[chunk % 85];
|
||||||
|
chunk /= 85;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.push_str(std::str::from_utf8(&chars).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn encode() {
|
||||||
|
assert_eq!(
|
||||||
|
super::encode(&[0x86, 0x4F, 0xD2, 0x6F, 0xB5, 0x59, 0xF7, 0x5B]),
|
||||||
|
"HelloWorld"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a random 128-bit [Z85] encoded [`String`].
|
||||||
|
///
|
||||||
|
/// [Z85]: https://rfc.zeromq.org/spec/32/
|
||||||
|
pub(crate) fn generate_invoke_key() -> Result<String> {
|
||||||
|
let mut bytes = [0u8; 16];
|
||||||
|
getrandom::getrandom(&mut bytes)?;
|
||||||
|
Ok(z85::encode(&bytes))
|
||||||
|
}
|
||||||
|
@ -238,6 +238,8 @@ pub struct InnerWindowManager<R: Runtime> {
|
|||||||
invoke_initialization_script: String,
|
invoke_initialization_script: String,
|
||||||
/// Application pattern.
|
/// Application pattern.
|
||||||
pub(crate) pattern: Pattern,
|
pub(crate) pattern: Pattern,
|
||||||
|
/// A runtime generated key to ensure an IPC call comes from an initialized frame.
|
||||||
|
invoke_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
||||||
@ -252,6 +254,7 @@ impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
|||||||
.field("package_info", &self.package_info)
|
.field("package_info", &self.package_info)
|
||||||
.field("menu", &self.menu)
|
.field("menu", &self.menu)
|
||||||
.field("pattern", &self.pattern)
|
.field("pattern", &self.pattern)
|
||||||
|
.field("invoke_key", &self.invoke_key)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,6 +306,7 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
window_event_listeners: Vec<GlobalWindowEventListener<R>>,
|
window_event_listeners: Vec<GlobalWindowEventListener<R>>,
|
||||||
(menu, menu_event_listeners): (Option<Menu>, Vec<GlobalMenuEventListener<R>>),
|
(menu, menu_event_listeners): (Option<Menu>, Vec<GlobalMenuEventListener<R>>),
|
||||||
(invoke_responder, invoke_initialization_script): (Arc<InvokeResponder<R>>, String),
|
(invoke_responder, invoke_initialization_script): (Arc<InvokeResponder<R>>, String),
|
||||||
|
invoke_key: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// generate a random isolation key at runtime
|
// generate a random isolation key at runtime
|
||||||
#[cfg(feature = "isolation")]
|
#[cfg(feature = "isolation")]
|
||||||
@ -333,6 +337,7 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
window_event_listeners: Arc::new(window_event_listeners),
|
window_event_listeners: Arc::new(window_event_listeners),
|
||||||
invoke_responder,
|
invoke_responder,
|
||||||
invoke_initialization_script,
|
invoke_initialization_script,
|
||||||
|
invoke_key,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,6 +454,7 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
}
|
}
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
},
|
},
|
||||||
|
invoke_key: self.invoke_key(),
|
||||||
}
|
}
|
||||||
.render_default(&Default::default())?;
|
.render_default(&Default::default())?;
|
||||||
|
|
||||||
@ -896,6 +902,10 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
listeners = self.event_listeners_object_name()
|
listeners = self.event_listeners_object_name()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn invoke_key(&self) -> &str {
|
||||||
|
&self.inner.invoke_key
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -917,6 +927,7 @@ mod test {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
(std::sync::Arc::new(|_, _, _, _| ()), "".into()),
|
(std::sync::Arc::new(|_, _, _, _| ()), "".into()),
|
||||||
|
crate::generate_invoke_key().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(custom_protocol)]
|
#[cfg(custom_protocol)]
|
||||||
|
@ -171,6 +171,7 @@ impl Scope {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::RemoteDomainAccessScope;
|
use super::RemoteDomainAccessScope;
|
||||||
|
use crate::sealed::ManagerBase;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::ipc::CallbackFn,
|
api::ipc::CallbackFn,
|
||||||
test::{assert_ipc_response, mock_app, MockRuntime},
|
test::{assert_ipc_response, mock_app, MockRuntime},
|
||||||
@ -190,7 +191,7 @@ mod tests {
|
|||||||
(app, window)
|
(app, window)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_version_payload() -> InvokePayload {
|
fn app_version_payload(invoke_key: &str) -> InvokePayload {
|
||||||
let callback = CallbackFn(0);
|
let callback = CallbackFn(0);
|
||||||
let error = CallbackFn(1);
|
let error = CallbackFn(1);
|
||||||
|
|
||||||
@ -208,10 +209,11 @@ mod tests {
|
|||||||
callback,
|
callback,
|
||||||
error,
|
error,
|
||||||
inner: serde_json::Value::Object(payload),
|
inner: serde_json::Value::Object(payload),
|
||||||
|
invoke_key: Some(invoke_key.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plugin_test_payload() -> InvokePayload {
|
fn plugin_test_payload(invoke_key: &str) -> InvokePayload {
|
||||||
let callback = CallbackFn(0);
|
let callback = CallbackFn(0);
|
||||||
let error = CallbackFn(1);
|
let error = CallbackFn(1);
|
||||||
|
|
||||||
@ -221,19 +223,25 @@ mod tests {
|
|||||||
callback,
|
callback,
|
||||||
error,
|
error,
|
||||||
inner: Default::default(),
|
inner: Default::default(),
|
||||||
|
invoke_key: Some(invoke_key.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invoke_key(app: &App<MockRuntime>) -> &str {
|
||||||
|
app.manager().invoke_key()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_not_defined() {
|
fn scope_not_defined() {
|
||||||
let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("app.tauri.app")
|
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("app.tauri.app")
|
||||||
.add_window("other")
|
.add_window("other")
|
||||||
.enable_tauri_api()]);
|
.enable_tauri_api()]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(&crate::window::ipc_scope_not_found_error_message(
|
Err(&crate::window::ipc_scope_not_found_error_message(
|
||||||
"main",
|
"main",
|
||||||
"https://tauri.app/",
|
"https://tauri.app/",
|
||||||
@ -243,28 +251,30 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_not_defined_for_window() {
|
fn scope_not_defined_for_window() {
|
||||||
let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
||||||
.add_window("second")
|
.add_window("second")
|
||||||
.enable_tauri_api()]);
|
.enable_tauri_api()]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(&crate::window::ipc_scope_window_error_message("main")),
|
Err(&crate::window::ipc_scope_window_error_message("main")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_not_defined_for_url() {
|
fn scope_not_defined_for_url() {
|
||||||
let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("github.com")
|
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("github.com")
|
||||||
.add_window("main")
|
.add_window("main")
|
||||||
.enable_tauri_api()]);
|
.enable_tauri_api()]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(&crate::window::ipc_scope_domain_error_message(
|
Err(&crate::window::ipc_scope_domain_error_message(
|
||||||
"https://tauri.app/",
|
"https://tauri.app/",
|
||||||
)),
|
)),
|
||||||
@ -281,18 +291,19 @@ mod tests {
|
|||||||
.add_window("main")
|
.add_window("main")
|
||||||
.enable_tauri_api(),
|
.enable_tauri_api(),
|
||||||
]);
|
]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Ok(app.package_info().version.to_string().as_str()),
|
Ok(app.package_info().version.to_string().as_str()),
|
||||||
);
|
);
|
||||||
|
|
||||||
window.navigate("https://blog.tauri.app".parse().unwrap());
|
window.navigate("https://blog.tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(&crate::window::ipc_scope_domain_error_message(
|
Err(&crate::window::ipc_scope_domain_error_message(
|
||||||
"https://blog.tauri.app/",
|
"https://blog.tauri.app/",
|
||||||
)),
|
)),
|
||||||
@ -301,7 +312,7 @@ mod tests {
|
|||||||
window.navigate("https://sub.tauri.app".parse().unwrap());
|
window.navigate("https://sub.tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Ok(app.package_info().version.to_string().as_str()),
|
Ok(app.package_info().version.to_string().as_str()),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -309,7 +320,7 @@ mod tests {
|
|||||||
window.navigate("https://dev.tauri.app".parse().unwrap());
|
window.navigate("https://dev.tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(&crate::window::ipc_scope_not_found_error_message(
|
Err(&crate::window::ipc_scope_not_found_error_message(
|
||||||
"test",
|
"test",
|
||||||
"https://dev.tauri.app/",
|
"https://dev.tauri.app/",
|
||||||
@ -322,53 +333,57 @@ mod tests {
|
|||||||
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
||||||
.add_window("main")
|
.add_window("main")
|
||||||
.enable_tauri_api()]);
|
.enable_tauri_api()]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app/inner/path".parse().unwrap());
|
window.navigate("https://tauri.app/inner/path".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Ok(app.package_info().version.to_string().as_str()),
|
Ok(app.package_info().version.to_string().as_str()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tauri_api_not_allowed() {
|
fn tauri_api_not_allowed() {
|
||||||
let (_app, mut window) = test_context(vec![
|
let (app, mut window) = test_context(vec![
|
||||||
RemoteDomainAccessScope::new("tauri.app").add_window("main")
|
RemoteDomainAccessScope::new("tauri.app").add_window("main")
|
||||||
]);
|
]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
app_version_payload(),
|
app_version_payload(invoke_key),
|
||||||
Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW),
|
Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn plugin_allowed() {
|
fn plugin_allowed() {
|
||||||
let (_app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
let (app, mut window) = test_context(vec![RemoteDomainAccessScope::new("tauri.app")
|
||||||
.add_window("main")
|
.add_window("main")
|
||||||
.add_plugin(PLUGIN_NAME)]);
|
.add_plugin(PLUGIN_NAME)]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
plugin_test_payload(),
|
plugin_test_payload(invoke_key),
|
||||||
Err(&format!("plugin {PLUGIN_NAME} not found")),
|
Err(&format!("plugin {PLUGIN_NAME} not found")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn plugin_not_allowed() {
|
fn plugin_not_allowed() {
|
||||||
let (_app, mut window) = test_context(vec![
|
let (app, mut window) = test_context(vec![
|
||||||
RemoteDomainAccessScope::new("tauri.app").add_window("main")
|
RemoteDomainAccessScope::new("tauri.app").add_window("main")
|
||||||
]);
|
]);
|
||||||
|
let invoke_key = invoke_key(&app);
|
||||||
|
|
||||||
window.navigate("https://tauri.app".parse().unwrap());
|
window.navigate("https://tauri.app".parse().unwrap());
|
||||||
assert_ipc_response(
|
assert_ipc_response(
|
||||||
&window,
|
&window,
|
||||||
plugin_test_payload(),
|
plugin_test_payload(invoke_key),
|
||||||
Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW),
|
Err(crate::window::IPC_SCOPE_DOES_NOT_ALLOW),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ use crate::{
|
|||||||
sealed::ManagerBase,
|
sealed::ManagerBase,
|
||||||
sealed::RuntimeOrDispatch,
|
sealed::RuntimeOrDispatch,
|
||||||
utils::config::{WindowConfig, WindowUrl},
|
utils::config::{WindowConfig, WindowUrl},
|
||||||
CursorIcon, EventLoopMessage, Icon, Invoke, InvokeError, InvokeMessage, InvokeResolver, Manager,
|
CursorIcon, Error, EventLoopMessage, Icon, Invoke, InvokeError, InvokeMessage, InvokeResolver,
|
||||||
PageLoadPayload, Runtime, Theme, WindowEvent,
|
Manager, Runtime, Theme, WindowEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -1550,9 +1550,35 @@ impl<R: Runtime> Window<R> {
|
|||||||
self.current_url = url;
|
self.current_url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument("window::on_message"))]
|
||||||
/// Handles this window receiving an [`InvokeMessage`].
|
/// Handles this window receiving an [`InvokeMessage`].
|
||||||
pub fn on_message(self, payload: InvokePayload) -> crate::Result<()> {
|
pub fn on_message(self, payload: InvokePayload) -> crate::Result<()> {
|
||||||
let manager = self.manager.clone();
|
let manager = self.manager.clone();
|
||||||
|
|
||||||
|
// ensure the passed key matches what our manager should have injected
|
||||||
|
let expected = manager.invoke_key();
|
||||||
|
match payload.invoke_key.as_deref() {
|
||||||
|
Some(sent) if sent == expected => { /* good */ }
|
||||||
|
Some(sent) => {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
tracing::error!("__TAURI_INVOKE_KEY__ expected {expected} but received {sent}");
|
||||||
|
|
||||||
|
#[cfg(not(feature = "tracing"))]
|
||||||
|
eprintln!("__TAURI_INVOKE_KEY__ expected {expected} but received {sent}");
|
||||||
|
|
||||||
|
return Err(Error::InvokeKey);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
tracing::error!("received ipc message without a __TAURI_INVOKE_KEY__");
|
||||||
|
|
||||||
|
#[cfg(not(feature = "tracing"))]
|
||||||
|
eprintln!("received ipc message without a __TAURI_INVOKE_KEY__");
|
||||||
|
|
||||||
|
return Err(Error::InvokeKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let current_url = self.url();
|
let current_url = self.url();
|
||||||
let config_url = manager.get_url();
|
let config_url = manager.get_url();
|
||||||
let is_local = config_url.make_relative(¤t_url).is_some();
|
let is_local = config_url.make_relative(¤t_url).is_some();
|
||||||
@ -1574,54 +1600,53 @@ impl<R: Runtime> Window<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match payload.cmd.as_str() {
|
|
||||||
"__initialized" => {
|
|
||||||
let payload: PageLoadPayload = serde_json::from_value(payload.inner)?;
|
|
||||||
manager.run_on_page_load(self, payload);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let message = InvokeMessage::new(
|
|
||||||
self.clone(),
|
|
||||||
manager.state(),
|
|
||||||
payload.cmd.to_string(),
|
|
||||||
payload.inner,
|
|
||||||
);
|
|
||||||
let resolver = InvokeResolver::new(self, payload.callback, payload.error);
|
|
||||||
let invoke = Invoke { message, resolver };
|
|
||||||
|
|
||||||
if !is_local && scope.is_none() {
|
if "__initialized" == &payload.cmd {
|
||||||
invoke.resolver.reject(scope_not_found_error_message);
|
let payload = serde_json::from_value(payload.inner)?;
|
||||||
|
manager.run_on_page_load(self, payload);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = InvokeMessage::new(
|
||||||
|
self.clone(),
|
||||||
|
manager.state(),
|
||||||
|
payload.cmd.to_string(),
|
||||||
|
payload.inner,
|
||||||
|
);
|
||||||
|
let resolver = InvokeResolver::new(self, payload.callback, payload.error);
|
||||||
|
let invoke = Invoke { message, resolver };
|
||||||
|
|
||||||
|
if !is_local && scope.is_none() {
|
||||||
|
invoke.resolver.reject(scope_not_found_error_message);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(module) = &payload.tauri_module {
|
||||||
|
if !is_local && scope.map(|s| !s.enables_tauri_api()).unwrap_or_default() {
|
||||||
|
invoke.resolver.reject(IPC_SCOPE_DOES_NOT_ALLOW);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
crate::endpoints::handle(
|
||||||
|
module.to_string(),
|
||||||
|
invoke,
|
||||||
|
manager.config(),
|
||||||
|
manager.package_info(),
|
||||||
|
);
|
||||||
|
} else if payload.cmd.starts_with("plugin:") {
|
||||||
|
if !is_local {
|
||||||
|
let command = invoke.message.command.replace("plugin:", "");
|
||||||
|
let plugin_name = command.split('|').next().unwrap().to_string();
|
||||||
|
if !scope
|
||||||
|
.map(|s| s.plugins().contains(&plugin_name))
|
||||||
|
.unwrap_or(true)
|
||||||
|
{
|
||||||
|
invoke.resolver.reject(IPC_SCOPE_DOES_NOT_ALLOW);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(module) = &payload.tauri_module {
|
|
||||||
if !is_local && scope.map(|s| !s.enables_tauri_api()).unwrap_or_default() {
|
|
||||||
invoke.resolver.reject(IPC_SCOPE_DOES_NOT_ALLOW);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
crate::endpoints::handle(
|
|
||||||
module.to_string(),
|
|
||||||
invoke,
|
|
||||||
manager.config(),
|
|
||||||
manager.package_info(),
|
|
||||||
);
|
|
||||||
} else if payload.cmd.starts_with("plugin:") {
|
|
||||||
if !is_local {
|
|
||||||
let command = invoke.message.command.replace("plugin:", "");
|
|
||||||
let plugin_name = command.split('|').next().unwrap().to_string();
|
|
||||||
if !scope
|
|
||||||
.map(|s| s.plugins().contains(&plugin_name))
|
|
||||||
.unwrap_or(true)
|
|
||||||
{
|
|
||||||
invoke.resolver.reject(IPC_SCOPE_DOES_NOT_ALLOW);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
manager.extend_api(invoke);
|
|
||||||
} else {
|
|
||||||
manager.run_invoke_handler(invoke);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
manager.extend_api(invoke);
|
||||||
|
} else {
|
||||||
|
manager.run_invoke_handler(invoke);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
33
examples/api/src-tauri/Cargo.lock
generated
33
examples/api/src-tauri/Cargo.lock
generated
@ -1806,6 +1806,12 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@ -4018,7 +4024,7 @@ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "1.6.0"
|
version = "1.6.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
@ -4031,10 +4037,11 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"flate2",
|
"flate2",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"getrandom 0.2.12",
|
||||||
"glib",
|
"glib",
|
||||||
"glob",
|
"glob",
|
||||||
"gtk",
|
"gtk",
|
||||||
"heck 0.4.1",
|
"heck 0.5.0",
|
||||||
"http",
|
"http",
|
||||||
"ico 0.2.0",
|
"ico 0.2.0",
|
||||||
"ignore",
|
"ignore",
|
||||||
@ -4083,12 +4090,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-build"
|
name = "tauri-build"
|
||||||
version = "1.5.1"
|
version = "1.5.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"heck 0.4.1",
|
"heck 0.5.0",
|
||||||
"json-patch",
|
"json-patch",
|
||||||
"quote",
|
"quote",
|
||||||
"semver",
|
"semver",
|
||||||
@ -4102,7 +4109,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "1.4.2"
|
version = "1.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -4126,9 +4133,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "1.4.3"
|
version = "1.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.4.1",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
@ -4138,7 +4145,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime"
|
name = "tauri-runtime"
|
||||||
version = "0.14.2"
|
version = "0.14.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@ -4157,7 +4164,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "0.14.4"
|
version = "0.14.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"cocoa 0.24.1",
|
"cocoa 0.24.1",
|
||||||
@ -4176,7 +4183,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-utils"
|
name = "tauri-utils"
|
||||||
version = "1.5.3"
|
version = "1.5.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -4184,7 +4191,7 @@ dependencies = [
|
|||||||
"dunce",
|
"dunce",
|
||||||
"getrandom 0.2.12",
|
"getrandom 0.2.12",
|
||||||
"glob",
|
"glob",
|
||||||
"heck 0.4.1",
|
"heck 0.5.0",
|
||||||
"html5ever",
|
"html5ever",
|
||||||
"infer 0.13.0",
|
"infer 0.13.0",
|
||||||
"json-patch",
|
"json-patch",
|
||||||
@ -5494,9 +5501,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.24.7"
|
version = "0.24.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ad85d0e067359e409fcb88903c3eac817c392e5d638258abfb3da5ad8ba6fc4"
|
checksum = "00711278ed357350d44c749c286786ecac644e044e4da410d466212152383b45"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"block",
|
"block",
|
||||||
|
Loading…
Reference in New Issue
Block a user