mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-11 07:55:34 +03:00
feat(core): block remote URLs from accessing the IPC
This was cherry picked from ee71c31fd0
, keeping only the logic to block remote URLs from using the IPC.
PR: #5918
This commit is contained in:
parent
34e03b8455
commit
fa90214b05
7
.changes/remote-urls.md
Normal file
7
.changes/remote-urls.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch
|
||||||
|
"tauri-runtime": patch
|
||||||
|
"tauri-runtime-wry": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Block remote URLs from accessing the IPC.
|
@ -54,5 +54,5 @@ fn override_msvcrt_lib() {
|
|||||||
f.write_all(bytes).unwrap();
|
f.write_all(bytes).unwrap();
|
||||||
}
|
}
|
||||||
// Add the output directory to the native library path.
|
// Add the output directory to the native library path.
|
||||||
println!("cargo:rustc-link-search=native={}", out_dir);
|
println!("cargo:rustc-link-search=native={out_dir}");
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ tauri-utils = { version = "1.0.3", path = "../tauri-utils" }
|
|||||||
uuid = { version = "1", features = [ "v4" ] }
|
uuid = { version = "1", features = [ "v4" ] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
raw-window-handle = "0.4.3"
|
raw-window-handle = "0.4.3"
|
||||||
|
url = "2"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
webview2-com = "0.16.0"
|
webview2-com = "0.16.0"
|
||||||
|
@ -41,6 +41,7 @@ use wry::application::platform::windows::{WindowBuilderExtWindows, WindowExtWind
|
|||||||
use wry::application::system_tray::{SystemTray as WrySystemTray, SystemTrayBuilder};
|
use wry::application::system_tray::{SystemTray as WrySystemTray, SystemTrayBuilder};
|
||||||
|
|
||||||
use tauri_utils::{config::WindowConfig, debug_eprintln, Theme};
|
use tauri_utils::{config::WindowConfig, debug_eprintln, Theme};
|
||||||
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use wry::{
|
use wry::{
|
||||||
application::{
|
application::{
|
||||||
@ -216,6 +217,7 @@ impl<T: UserEvent> Context<T> {
|
|||||||
impl<T: UserEvent> Context<T> {
|
impl<T: UserEvent> Context<T> {
|
||||||
fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> {
|
fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> {
|
||||||
let label = pending.label.clone();
|
let label = pending.label.clone();
|
||||||
|
let current_url = pending.current_url.clone();
|
||||||
let menu_ids = pending.menu_ids.clone();
|
let menu_ids = pending.menu_ids.clone();
|
||||||
let js_event_listeners = pending.js_event_listeners.clone();
|
let js_event_listeners = pending.js_event_listeners.clone();
|
||||||
let context = self.clone();
|
let context = self.clone();
|
||||||
@ -237,6 +239,7 @@ impl<T: UserEvent> Context<T> {
|
|||||||
};
|
};
|
||||||
Ok(DetachedWindow {
|
Ok(DetachedWindow {
|
||||||
label,
|
label,
|
||||||
|
current_url,
|
||||||
dispatcher,
|
dispatcher,
|
||||||
menu_ids,
|
menu_ids,
|
||||||
js_event_listeners,
|
js_event_listeners,
|
||||||
@ -1862,6 +1865,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
|||||||
|
|
||||||
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
|
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
|
||||||
let label = pending.label.clone();
|
let label = pending.label.clone();
|
||||||
|
let current_url = pending.current_url.clone();
|
||||||
let menu_ids = pending.menu_ids.clone();
|
let menu_ids = pending.menu_ids.clone();
|
||||||
let js_event_listeners = pending.js_event_listeners.clone();
|
let js_event_listeners = pending.js_event_listeners.clone();
|
||||||
let window_id = rand::random();
|
let window_id = rand::random();
|
||||||
@ -1889,6 +1893,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
|||||||
|
|
||||||
Ok(DetachedWindow {
|
Ok(DetachedWindow {
|
||||||
label,
|
label,
|
||||||
|
current_url,
|
||||||
dispatcher,
|
dispatcher,
|
||||||
menu_ids,
|
menu_ids,
|
||||||
js_event_listeners,
|
js_event_listeners,
|
||||||
@ -2833,7 +2838,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
mut window_builder,
|
mut window_builder,
|
||||||
ipc_handler,
|
ipc_handler,
|
||||||
label,
|
label,
|
||||||
url,
|
current_url,
|
||||||
menu_ids,
|
menu_ids,
|
||||||
js_event_listeners,
|
js_event_listeners,
|
||||||
..
|
..
|
||||||
@ -2871,16 +2876,22 @@ fn create_webview<T: UserEvent>(
|
|||||||
}
|
}
|
||||||
let mut webview_builder = WebViewBuilder::new(window)
|
let mut webview_builder = WebViewBuilder::new(window)
|
||||||
.map_err(|e| Error::CreateWebview(Box::new(e)))?
|
.map_err(|e| Error::CreateWebview(Box::new(e)))?
|
||||||
.with_url(&url)
|
.with_url(current_url.lock().unwrap().as_str())
|
||||||
.unwrap() // safe to unwrap because we validate the URL beforehand
|
.unwrap() // safe to unwrap because we validate the URL beforehand
|
||||||
.with_transparent(is_window_transparent);
|
.with_transparent(is_window_transparent);
|
||||||
if webview_attributes.file_drop_handler_enabled {
|
if webview_attributes.file_drop_handler_enabled {
|
||||||
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(&context));
|
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(&context));
|
||||||
}
|
}
|
||||||
|
if let Some(navigation_handler) = pending.navigation_handler {
|
||||||
|
webview_builder = webview_builder.with_navigation_handler(move |url| {
|
||||||
|
Url::parse(&url).map(&navigation_handler).unwrap_or(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
if let Some(handler) = ipc_handler {
|
if let Some(handler) = ipc_handler {
|
||||||
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
||||||
context,
|
context,
|
||||||
label.clone(),
|
label.clone(),
|
||||||
|
current_url,
|
||||||
menu_ids,
|
menu_ids,
|
||||||
js_event_listeners,
|
js_event_listeners,
|
||||||
handler,
|
handler,
|
||||||
@ -2984,6 +2995,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
fn create_ipc_handler<T: UserEvent>(
|
fn create_ipc_handler<T: UserEvent>(
|
||||||
context: Context<T>,
|
context: Context<T>,
|
||||||
label: String,
|
label: String,
|
||||||
|
current_url: Arc<Mutex<Url>>,
|
||||||
menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
|
menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
|
||||||
js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
|
js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
|
||||||
handler: WebviewIpcHandler<T, Wry<T>>,
|
handler: WebviewIpcHandler<T, Wry<T>>,
|
||||||
@ -2992,6 +3004,7 @@ fn create_ipc_handler<T: UserEvent>(
|
|||||||
let window_id = context.webview_id_map.get(&window.id());
|
let window_id = context.webview_id_map.get(&window.id());
|
||||||
handler(
|
handler(
|
||||||
DetachedWindow {
|
DetachedWindow {
|
||||||
|
current_url: current_url.clone(),
|
||||||
dispatcher: WryDispatcher {
|
dispatcher: WryDispatcher {
|
||||||
window_id,
|
window_id,
|
||||||
context: context.clone(),
|
context: context.clone(),
|
||||||
|
@ -32,6 +32,7 @@ http = "0.2.4"
|
|||||||
http-range = "0.1.4"
|
http-range = "0.1.4"
|
||||||
infer = "0.7"
|
infer = "0.7"
|
||||||
raw-window-handle = "0.4.3"
|
raw-window-handle = "0.4.3"
|
||||||
|
url = "2"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
webview2-com = "0.16.0"
|
webview2-com = "0.16.0"
|
||||||
|
@ -12,6 +12,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use tauri_utils::{config::WindowConfig, Theme};
|
use tauri_utils::{config::WindowConfig, Theme};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
@ -226,14 +227,17 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
|
|||||||
/// How to handle IPC calls on the webview window.
|
/// How to handle IPC calls on the webview window.
|
||||||
pub ipc_handler: Option<WebviewIpcHandler<T, R>>,
|
pub ipc_handler: Option<WebviewIpcHandler<T, R>>,
|
||||||
|
|
||||||
/// The resolved URL to load on the webview.
|
|
||||||
pub url: String,
|
|
||||||
|
|
||||||
/// Maps runtime id to a string menu id.
|
/// Maps runtime id to a string menu id.
|
||||||
pub menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
|
pub menu_ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
|
||||||
|
|
||||||
/// A HashMap mapping JS event names with associated listener ids.
|
/// A HashMap mapping JS event names with associated listener ids.
|
||||||
pub js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
|
pub js_event_listeners: Arc<Mutex<HashMap<JsEventListenerKey, HashSet<u64>>>>,
|
||||||
|
|
||||||
|
/// A handler to decide if incoming url is allowed to navigate.
|
||||||
|
pub navigation_handler: Option<Box<dyn Fn(Url) -> bool + Send>>,
|
||||||
|
|
||||||
|
/// The current webview URL.
|
||||||
|
pub current_url: Arc<Mutex<Url>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_label_valid(label: &str) -> bool {
|
pub fn is_label_valid(label: &str) -> bool {
|
||||||
@ -270,9 +274,10 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
|
|||||||
uri_scheme_protocols: Default::default(),
|
uri_scheme_protocols: Default::default(),
|
||||||
label,
|
label,
|
||||||
ipc_handler: None,
|
ipc_handler: None,
|
||||||
url: "tauri://localhost".to_string(),
|
|
||||||
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
||||||
js_event_listeners: Default::default(),
|
js_event_listeners: Default::default(),
|
||||||
|
navigation_handler: Default::default(),
|
||||||
|
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,9 +304,10 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
|
|||||||
uri_scheme_protocols: Default::default(),
|
uri_scheme_protocols: Default::default(),
|
||||||
label,
|
label,
|
||||||
ipc_handler: None,
|
ipc_handler: None,
|
||||||
url: "tauri://localhost".to_string(),
|
|
||||||
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
menu_ids: Arc::new(Mutex::new(menu_ids)),
|
||||||
js_event_listeners: Default::default(),
|
js_event_listeners: Default::default(),
|
||||||
|
navigation_handler: Default::default(),
|
||||||
|
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,6 +348,9 @@ pub struct JsEventListenerKey {
|
|||||||
/// A webview window that is not yet managed by Tauri.
|
/// A webview window that is not yet managed by Tauri.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
|
pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
|
||||||
|
/// The current webview URL.
|
||||||
|
pub current_url: Arc<Mutex<Url>>,
|
||||||
|
|
||||||
/// Name of the window
|
/// Name of the window
|
||||||
pub label: String,
|
pub label: String,
|
||||||
|
|
||||||
@ -358,6 +367,7 @@ pub struct DetachedWindow<T: UserEvent, R: Runtime<T>> {
|
|||||||
impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindow<T, R> {
|
impl<T: UserEvent, R: Runtime<T>> Clone for DetachedWindow<T, R> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
current_url: self.current_url.clone(),
|
||||||
label: self.label.clone(),
|
label: self.label.clone(),
|
||||||
dispatcher: self.dispatcher.clone(),
|
dispatcher: self.dispatcher.clone(),
|
||||||
menu_ids: self.menu_ids.clone(),
|
menu_ids: self.menu_ids.clone(),
|
||||||
|
@ -902,7 +902,7 @@ impl<R: Runtime> Builder<R> {
|
|||||||
#[cfg(any(windows, target_os = "linux"))]
|
#[cfg(any(windows, target_os = "linux"))]
|
||||||
runtime_any_thread: false,
|
runtime_any_thread: false,
|
||||||
setup: Box::new(|_| Ok(())),
|
setup: Box::new(|_| Ok(())),
|
||||||
invoke_handler: Box::new(|_| ()),
|
invoke_handler: Box::new(|invoke| invoke.resolver.reject("not implemented")),
|
||||||
invoke_responder: Arc::new(window_invoke_responder),
|
invoke_responder: Arc::new(window_invoke_responder),
|
||||||
invoke_initialization_script:
|
invoke_initialization_script:
|
||||||
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (message) => window.ipc.postMessage(JSON.stringify(message)) })".into(),
|
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (message) => window.ipc.postMessage(JSON.stringify(message)) })".into(),
|
||||||
|
@ -25,10 +25,9 @@ use tauri_utils::{
|
|||||||
html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
|
html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::hooks::IpcJavascript;
|
|
||||||
#[cfg(feature = "isolation")]
|
#[cfg(feature = "isolation")]
|
||||||
use crate::hooks::IsolationJavascript;
|
use crate::hooks::IsolationJavascript;
|
||||||
use crate::pattern::{format_real_schema, PatternJavascript};
|
use crate::pattern::PatternJavascript;
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener},
|
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener},
|
||||||
event::{assert_event_name_is_valid, Event, EventHandler, Listeners},
|
event::{assert_event_name_is_valid, Event, EventHandler, Listeners},
|
||||||
@ -54,6 +53,7 @@ use crate::{
|
|||||||
app::{GlobalMenuEventListener, WindowMenuEvent},
|
app::{GlobalMenuEventListener, WindowMenuEvent},
|
||||||
window::WebResourceRequestHandler,
|
window::WebResourceRequestHandler,
|
||||||
};
|
};
|
||||||
|
use crate::{hooks::IpcJavascript, pattern::format_real_schema};
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||||
use crate::api::path::{resolve_path, BaseDirectory};
|
use crate::api::path::{resolve_path, BaseDirectory};
|
||||||
@ -136,7 +136,7 @@ fn set_csp<R: Runtime>(
|
|||||||
let default_src = csp
|
let default_src = csp
|
||||||
.entry("default-src".into())
|
.entry("default-src".into())
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default);
|
||||||
default_src.push(format_real_schema(schema));
|
default_src.push(crate::pattern::format_real_schema(schema));
|
||||||
}
|
}
|
||||||
|
|
||||||
Csp::DirectiveMap(csp).to_string()
|
Csp::DirectiveMap(csp).to_string()
|
||||||
@ -225,7 +225,7 @@ pub struct InnerWindowManager<R: Runtime> {
|
|||||||
/// The script that initializes the invoke system.
|
/// The script that initializes the invoke system.
|
||||||
invoke_initialization_script: String,
|
invoke_initialization_script: String,
|
||||||
/// Application pattern.
|
/// Application pattern.
|
||||||
pattern: Pattern,
|
pub(crate) pattern: Pattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
|
||||||
@ -357,9 +357,12 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
/// Get the base URL to use for webview requests.
|
/// Get the base URL to use for webview requests.
|
||||||
///
|
///
|
||||||
/// In dev mode, this will be based on the `devPath` configuration value.
|
/// In dev mode, this will be based on the `devPath` configuration value.
|
||||||
fn get_url(&self) -> Cow<'_, Url> {
|
pub(crate) fn get_url(&self) -> Cow<'_, Url> {
|
||||||
match self.base_path() {
|
match self.base_path() {
|
||||||
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
|
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
|
||||||
|
#[cfg(windows)]
|
||||||
|
_ => Cow::Owned(Url::parse("https://tauri.localhost").unwrap()),
|
||||||
|
#[cfg(not(windows))]
|
||||||
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
|
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,7 +470,7 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let window_url = Url::parse(&pending.url).unwrap();
|
let window_url = pending.current_url.lock().unwrap().clone();
|
||||||
let window_origin =
|
let window_origin =
|
||||||
if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" {
|
if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" {
|
||||||
format!("https://{}.localhost", window_url.scheme())
|
format!("https://{}.localhost", window_url.scheme())
|
||||||
@ -1001,7 +1004,16 @@ mod test {
|
|||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(custom_protocol)]
|
#[cfg(custom_protocol)]
|
||||||
assert_eq!(manager.get_url().to_string(), "tauri://localhost");
|
{
|
||||||
|
assert_eq!(
|
||||||
|
manager.get_url().to_string(),
|
||||||
|
if cfg!(windows) {
|
||||||
|
"https://tauri.localhost/"
|
||||||
|
} else {
|
||||||
|
"tauri://localhost"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(dev)]
|
#[cfg(dev)]
|
||||||
assert_eq!(manager.get_url().to_string(), "http://localhost:4000/");
|
assert_eq!(manager.get_url().to_string(), "http://localhost:4000/");
|
||||||
@ -1052,27 +1064,21 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
return Err(crate::Error::WindowLabelAlreadyExists(pending.label));
|
return Err(crate::Error::WindowLabelAlreadyExists(pending.label));
|
||||||
}
|
}
|
||||||
#[allow(unused_mut)] // mut url only for the data-url parsing
|
#[allow(unused_mut)] // mut url only for the data-url parsing
|
||||||
let (is_local, mut url) = match &pending.webview_attributes.url {
|
let mut url = match &pending.webview_attributes.url {
|
||||||
WindowUrl::App(path) => {
|
WindowUrl::App(path) => {
|
||||||
let url = self.get_url();
|
let url = self.get_url();
|
||||||
(
|
// ignore "index.html" just to simplify the url
|
||||||
true,
|
if path.to_str() != Some("index.html") {
|
||||||
// ignore "index.html" just to simplify the url
|
url
|
||||||
if path.to_str() != Some("index.html") {
|
.join(&*path.to_string_lossy())
|
||||||
url
|
.map_err(crate::Error::InvalidUrl)
|
||||||
.join(&*path.to_string_lossy())
|
// this will never fail
|
||||||
.map_err(crate::Error::InvalidUrl)
|
.unwrap()
|
||||||
// this will never fail
|
} else {
|
||||||
.unwrap()
|
url.into_owned()
|
||||||
} else {
|
}
|
||||||
url.into_owned()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
WindowUrl::External(url) => {
|
|
||||||
let config_url = self.get_url();
|
|
||||||
(config_url.make_relative(url).is_some(), url.clone())
|
|
||||||
}
|
}
|
||||||
|
WindowUrl::External(url) => url.clone(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1099,7 +1105,7 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pending.url = url.to_string();
|
*pending.current_url.lock().unwrap() = url;
|
||||||
|
|
||||||
if !pending.window_builder.has_icon() {
|
if !pending.window_builder.has_icon() {
|
||||||
if let Some(default_window_icon) = self.inner.default_window_icon.clone() {
|
if let Some(default_window_icon) = self.inner.default_window_icon.clone() {
|
||||||
@ -1115,17 +1121,15 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_local {
|
let label = pending.label.clone();
|
||||||
let label = pending.label.clone();
|
pending = self.prepare_pending_window(
|
||||||
pending = self.prepare_pending_window(
|
pending,
|
||||||
pending,
|
&label,
|
||||||
&label,
|
window_labels,
|
||||||
window_labels,
|
app_handle.clone(),
|
||||||
app_handle.clone(),
|
web_resource_request_handler,
|
||||||
web_resource_request_handler,
|
)?;
|
||||||
)?;
|
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle));
|
||||||
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle));
|
|
||||||
}
|
|
||||||
|
|
||||||
// in `Windows`, we need to force a data_directory
|
// in `Windows`, we need to force a data_directory
|
||||||
// but we do respect user-specification
|
// but we do respect user-specification
|
||||||
@ -1150,6 +1154,17 @@ impl<R: Runtime> WindowManager<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let current_url_ = pending.current_url.clone();
|
||||||
|
let navigation_handler = pending.navigation_handler.take();
|
||||||
|
pending.navigation_handler = Some(Box::new(move |url| {
|
||||||
|
*current_url_.lock().unwrap() = url.clone();
|
||||||
|
if let Some(handler) = &navigation_handler {
|
||||||
|
handler(url)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
Ok(pending)
|
Ok(pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ use serialize_to_javascript::{default_template, Template};
|
|||||||
|
|
||||||
use tauri_utils::assets::{Assets, EmbeddedAssets};
|
use tauri_utils::assets::{Assets, EmbeddedAssets};
|
||||||
|
|
||||||
|
/// The domain of the isolation iframe source.
|
||||||
|
pub const ISOLATION_IFRAME_SRC_DOMAIN: &str = "localhost";
|
||||||
|
|
||||||
/// An application pattern.
|
/// An application pattern.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Pattern<A: Assets = EmbeddedAssets> {
|
pub enum Pattern<A: Assets = EmbeddedAssets> {
|
||||||
@ -87,8 +90,8 @@ pub(crate) struct PatternJavascript {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn format_real_schema(schema: &str) -> String {
|
pub(crate) fn format_real_schema(schema: &str) -> String {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
format!("https://{}.localhost", schema)
|
format!("https://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
|
||||||
} else {
|
} else {
|
||||||
format!("{}://localhost", schema)
|
format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
|
|||||||
) -> Result<DetachedWindow<T, Self::Runtime>> {
|
) -> Result<DetachedWindow<T, Self::Runtime>> {
|
||||||
Ok(DetachedWindow {
|
Ok(DetachedWindow {
|
||||||
label: pending.label,
|
label: pending.label,
|
||||||
|
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
|
||||||
dispatcher: MockDispatcher {
|
dispatcher: MockDispatcher {
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
},
|
},
|
||||||
@ -616,6 +617,7 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
|
|||||||
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
|
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
|
||||||
Ok(DetachedWindow {
|
Ok(DetachedWindow {
|
||||||
label: pending.label,
|
label: pending.label,
|
||||||
|
current_url: Arc::new(Mutex::new("tauri://localhost".parse().unwrap())),
|
||||||
dispatcher: MockDispatcher {
|
dispatcher: MockDispatcher {
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
},
|
},
|
||||||
|
@ -33,6 +33,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use url::Url;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use windows::Win32::Foundation::HWND;
|
use windows::Win32::Foundation::HWND;
|
||||||
|
|
||||||
@ -483,7 +484,7 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Window<R: Runtime> {
|
pub struct Window<R: Runtime> {
|
||||||
/// The webview window created by the runtime.
|
/// The webview window created by the runtime.
|
||||||
window: DetachedWindow<EventLoopMessage, R>,
|
pub(crate) window: DetachedWindow<EventLoopMessage, R>,
|
||||||
/// The manager to associate this webview window with.
|
/// The manager to associate this webview window with.
|
||||||
manager: WindowManager<R>,
|
manager: WindowManager<R>,
|
||||||
pub(crate) app_handle: AppHandle<R>,
|
pub(crate) app_handle: AppHandle<R>,
|
||||||
@ -1157,9 +1158,18 @@ impl<R: Runtime> Window<R> {
|
|||||||
|
|
||||||
/// Webview APIs.
|
/// Webview APIs.
|
||||||
impl<R: Runtime> Window<R> {
|
impl<R: Runtime> Window<R> {
|
||||||
|
/// Returns the current url of the webview.
|
||||||
|
pub fn url(&self) -> Url {
|
||||||
|
self.window.current_url.lock().unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// 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();
|
||||||
|
let current_url = self.url();
|
||||||
|
let config_url = manager.get_url();
|
||||||
|
let is_local = config_url.make_relative(¤t_url).is_some();
|
||||||
|
|
||||||
match payload.cmd.as_str() {
|
match payload.cmd.as_str() {
|
||||||
"__initialized" => {
|
"__initialized" => {
|
||||||
let payload: PageLoadPayload = serde_json::from_value(payload.inner)?;
|
let payload: PageLoadPayload = serde_json::from_value(payload.inner)?;
|
||||||
@ -1173,8 +1183,15 @@ impl<R: Runtime> Window<R> {
|
|||||||
payload.inner,
|
payload.inner,
|
||||||
);
|
);
|
||||||
let resolver = InvokeResolver::new(self, payload.callback, payload.error);
|
let resolver = InvokeResolver::new(self, payload.callback, payload.error);
|
||||||
|
|
||||||
let invoke = Invoke { message, resolver };
|
let invoke = Invoke { message, resolver };
|
||||||
|
|
||||||
|
if !is_local {
|
||||||
|
invoke
|
||||||
|
.resolver
|
||||||
|
.reject("Remote URLs are not allowed to access the IPC");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(module) = &payload.tauri_module {
|
if let Some(module) = &payload.tauri_module {
|
||||||
crate::endpoints::handle(
|
crate::endpoints::handle(
|
||||||
module.to_string(),
|
module.to_string(),
|
||||||
|
16
examples/api/src-tauri/Cargo.lock
generated
16
examples/api/src-tauri/Cargo.lock
generated
@ -3132,7 +3132,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "1.0.2"
|
version = "1.0.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"attohttpc",
|
"attohttpc",
|
||||||
@ -3194,7 +3194,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-build"
|
name = "tauri-build"
|
||||||
version = "1.0.2"
|
version = "1.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
@ -3209,7 +3209,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "1.0.2"
|
version = "1.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -3233,7 +3233,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "1.0.2"
|
version = "1.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.4.0",
|
"heck 0.4.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -3245,7 +3245,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime"
|
name = "tauri-runtime"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@ -3256,6 +3256,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"url",
|
||||||
"uuid 1.1.2",
|
"uuid 1.1.2",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows 0.37.0",
|
"windows 0.37.0",
|
||||||
@ -3263,7 +3264,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"gtk",
|
"gtk",
|
||||||
@ -3272,6 +3273,7 @@ dependencies = [
|
|||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"tauri-runtime",
|
"tauri-runtime",
|
||||||
"tauri-utils",
|
"tauri-utils",
|
||||||
|
"url",
|
||||||
"uuid 1.1.2",
|
"uuid 1.1.2",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
@ -3281,7 +3283,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-utils"
|
name = "tauri-utils"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"brotli",
|
"brotli",
|
||||||
|
Loading…
Reference in New Issue
Block a user