From 3a8ab249c0c56cdc5f27b35c3773043a79cf478d Mon Sep 17 00:00:00 2001 From: amrbashir Date: Thu, 24 Oct 2024 10:59:42 +0300 Subject: [PATCH 1/9] feat: add `use_https_scheme` for Windows and Android closes #11252 --- .../use_https_windows-and-android-config.md | 9 ++++++ .changes/use_https_windows-and-android.md | 10 +++++++ crates/tauri-cli/config.schema.json | 5 ++++ crates/tauri-runtime-wry/src/lib.rs | 14 +++++---- crates/tauri-runtime/src/webview.rs | 19 ++++++++++++ .../schemas/config.schema.json | 5 ++++ crates/tauri-utils/src/config.rs | 17 ++++++++++- crates/tauri/scripts/core.js | 3 +- crates/tauri/src/app.rs | 12 ++++++-- crates/tauri/src/manager/mod.rs | 29 ++++++++++++++----- crates/tauri/src/manager/webview.rs | 20 +++++++++---- crates/tauri/src/pattern.rs | 5 ++-- crates/tauri/src/protocol/isolation.rs | 4 ++- crates/tauri/src/protocol/tauri.rs | 3 +- crates/tauri/src/webview/mod.rs | 23 +++++++++++++-- crates/tauri/src/webview/webview_window.rs | 15 ++++++++++ packages/api/src/webview.ts | 15 ++++++++++ 17 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 .changes/use_https_windows-and-android-config.md create mode 100644 .changes/use_https_windows-and-android.md diff --git a/.changes/use_https_windows-and-android-config.md b/.changes/use_https_windows-and-android-config.md new file mode 100644 index 000000000000..3ed79b05a8a4 --- /dev/null +++ b/.changes/use_https_windows-and-android-config.md @@ -0,0 +1,9 @@ +--- +"tauri": "minor:feat" +"tauri-utils": "minor:feat" +--- + +Add `app > windows > useHttpsScheme` config option to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android + + + diff --git a/.changes/use_https_windows-and-android.md b/.changes/use_https_windows-and-android.md new file mode 100644 index 000000000000..ca68350686b9 --- /dev/null +++ b/.changes/use_https_windows-and-android.md @@ -0,0 +1,10 @@ +--- +"tauri": "minor:feat" +"tauri-runtime": "minor:feat" +"tauri-runtime-wry": "minor:feat" +--- + +Add `WebviewWindowBuilder/WebviewBuilder::use_https_scheme` to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android + + + diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index a05ba79935ed..0afd069e6d9c 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -486,6 +486,11 @@ "description": "Whether browser extensions can be installed for the webview process\n\n ## Platform-specific:\n\n - **Windows**: Enables the WebView2 environment's [`AreBrowserExtensionsEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2environmentoptions?view=webview2-winrt-1.0.2739.15#arebrowserextensionsenabled)\n - **MacOS / Linux / iOS / Android** - Unsupported.", "default": false, "type": "boolean" + }, + "useHttpsScheme": { + "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them.", + "default": false, + "type": "boolean" } }, "additionalProperties": false diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 4dd17d494910..31580f5257f9 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -746,6 +746,8 @@ impl WindowBuilder for WindowBuilderWrapper { builder = builder.title_bar_style(TitleBarStyle::Visible); } + builder = builder.title("Tauri App"); + builder } @@ -4025,6 +4027,11 @@ fn create_webview( .with_clipboard(webview_attributes.clipboard) .with_hotkeys_zoom(webview_attributes.zoom_hotkeys_enabled); + #[cfg(any(target_os = "windows", target_os = "android"))] + { + webview_builder = webview_builder.with_https_scheme(webview_attributes.use_https_scheme); + } + if webview_attributes.drag_drop_handler_enabled { let proxy = context.proxy.clone(); let window_id_ = window_id.clone(); @@ -4167,11 +4174,6 @@ fn create_webview( }); } - #[cfg(windows)] - { - webview_builder = webview_builder.with_https_scheme(false); - } - #[cfg(windows)] { webview_builder = webview_builder @@ -4281,7 +4283,7 @@ fn create_webview( builder } } - .map_err(|e| Error::CreateWebview(Box::new(dbg!(e))))?; + .map_err(|e| Error::CreateWebview(Box::new(e)))?; if kind == WebviewKind::WindowContent { #[cfg(any( diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index 4c4c83e3ea8a..6a592a0cbeeb 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -209,6 +209,7 @@ pub struct WebviewAttributes { pub proxy_url: Option, pub zoom_hotkeys_enabled: bool, pub browser_extensions_enabled: bool, + pub use_https_scheme: bool, } impl From<&WindowConfig> for WebviewAttributes { @@ -236,6 +237,7 @@ impl From<&WindowConfig> for WebviewAttributes { builder = builder.proxy_url(url.to_owned()); } builder = builder.zoom_hotkeys_enabled(config.zoom_hotkeys_enabled); + builder = builder.use_https_scheme(config.use_https_scheme); builder = builder.browser_extensions_enabled(config.browser_extensions_enabled); builder } @@ -261,6 +263,7 @@ impl WebviewAttributes { proxy_url: None, zoom_hotkeys_enabled: false, browser_extensions_enabled: false, + use_https_scheme: false, } } @@ -378,6 +381,22 @@ impl WebviewAttributes { self.browser_extensions_enabled = enabled; self } + + /// Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. + /// + /// ## Note + /// + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// + /// ## Warning + /// + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + #[must_use] + pub fn use_https_scheme(mut self, enabled: bool) -> Self { + self.use_https_scheme = enabled; + self + } + } /// IPC handler. diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index a05ba79935ed..0afd069e6d9c 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -486,6 +486,11 @@ "description": "Whether browser extensions can be installed for the webview process\n\n ## Platform-specific:\n\n - **Windows**: Enables the WebView2 environment's [`AreBrowserExtensionsEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2environmentoptions?view=webview2-winrt-1.0.2739.15#arebrowserextensionsenabled)\n - **MacOS / Linux / iOS / Android** - Unsupported.", "default": false, "type": "boolean" + }, + "useHttpsScheme": { + "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them.", + "default": false, + "type": "boolean" } }, "additionalProperties": false diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 3780079bf1e5..93daba2189fc 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -1486,6 +1486,18 @@ pub struct WindowConfig { /// - **MacOS / Linux / iOS / Android** - Unsupported. #[serde(default)] pub browser_extensions_enabled: bool, + + /// Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. + /// + /// ## Note + /// + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// + /// ## Warning + /// + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + #[serde(default, alias = "use-https-scheme")] + pub use_https_scheme: bool, } impl Default for WindowConfig { @@ -1534,6 +1546,7 @@ impl Default for WindowConfig { proxy_url: None, zoom_hotkeys_enabled: false, browser_extensions_enabled: false, + use_https_scheme: false, } } } @@ -2505,6 +2518,7 @@ mod build { let parent = opt_str_lit(self.parent.as_ref()); let zoom_hotkeys_enabled = self.zoom_hotkeys_enabled; let browser_extensions_enabled = self.browser_extensions_enabled; + let use_https_scheme = self.use_https_scheme; literal_struct!( tokens, @@ -2551,7 +2565,8 @@ mod build { incognito, parent, zoom_hotkeys_enabled, - browser_extensions_enabled + browser_extensions_enabled, + use_https_scheme ); } } diff --git a/crates/tauri/scripts/core.js b/crates/tauri/scripts/core.js index 6f4523c8d67a..b68b6039195b 100644 --- a/crates/tauri/scripts/core.js +++ b/crates/tauri/scripts/core.js @@ -8,12 +8,13 @@ } const osName = __TEMPLATE_os_name__ + const protocolScheme = __TEMPLATE_protocol_scheme__ Object.defineProperty(window.__TAURI_INTERNALS__, 'convertFileSrc', { value: function (filePath, protocol = 'asset') { const path = encodeURIComponent(filePath) return osName === 'windows' || osName === 'android' - ? `http://${protocol}.localhost/${path}` + ? `${protocolScheme}://${protocol}.localhost/${path}` : `${protocol}://localhost/${path}` } }) diff --git a/crates/tauri/src/app.rs b/crates/tauri/src/app.rs index b513ed7f8964..e7f7a36a3208 100644 --- a/crates/tauri/src/app.rs +++ b/crates/tauri/src/app.rs @@ -266,6 +266,11 @@ pub struct AssetResolver { } impl AssetResolver { + /// Same as [AssetResolver::get_for_scheme] but always resolves with csp header for `http` scheme. + pub fn get(&self, path: String) -> Option { + self.get_for_scheme(path, false) + } + /// Gets the app asset associated with the given path. /// /// Resolves to the embedded asset that is part of the app @@ -275,7 +280,10 @@ impl AssetResolver { /// /// Fallbacks to reading the asset from the [distDir] folder so the behavior is consistent in development. /// Note that the dist directory must exist so you might need to build your frontend assets first. - pub fn get(&self, path: String) -> Option { + /// + /// - `use_https_scheme`: If `true` when using [`Pattern::Isolation`](tauri::Pattern::Isolation), + /// the csp header will contain `https://tauri.localhost` instead of `http://tauri.localhost` + pub fn get_for_scheme(&self, path: String, use_https_scheme: bool) -> Option { #[cfg(dev)] { // on dev if the devPath is a path to a directory we have the embedded assets @@ -306,7 +314,7 @@ impl AssetResolver { } } - self.manager.get_asset(path).ok() + self.manager.get_asset(path, use_https_scheme).ok() } /// Iterate on all assets. diff --git a/crates/tauri/src/manager/mod.rs b/crates/tauri/src/manager/mod.rs index 7353c3ae36f4..b363b677e52b 100644 --- a/crates/tauri/src/manager/mod.rs +++ b/crates/tauri/src/manager/mod.rs @@ -340,9 +340,10 @@ impl AppManager { self.config.build.dev_url.as_ref() } - pub(crate) fn protocol_url(&self) -> Cow<'_, Url> { + pub(crate) fn protocol_url(&self, https: bool) -> Cow<'_, Url> { if cfg!(windows) || cfg!(target_os = "android") { - Cow::Owned(Url::parse("http://tauri.localhost").unwrap()) + let https = if https { "https" } else { "http" }; + Cow::Owned(Url::parse(&format!("{https}://tauri.localhost")).unwrap()) } else { Cow::Owned(Url::parse("tauri://localhost").unwrap()) } @@ -351,10 +352,10 @@ impl AppManager { /// Get the base URL to use for webview requests. /// /// In dev mode, this will be based on the `devUrl` configuration value. - pub(crate) fn get_url(&self) -> Cow<'_, Url> { + pub(crate) fn get_url(&self, https: bool) -> Cow<'_, Url> { match self.base_path() { Some(url) => Cow::Borrowed(url), - _ => self.protocol_url(), + _ => self.protocol_url(https), } } @@ -372,7 +373,11 @@ impl AppManager { } } - pub fn get_asset(&self, mut path: String) -> Result> { + pub fn get_asset( + &self, + mut path: String, + use_https_schema: bool, + ) -> Result> { let assets = &self.assets; if path.ends_with('/') { path.pop(); @@ -435,7 +440,7 @@ impl AppManager { let default_src = csp_map .entry("default-src".into()) .or_insert_with(Default::default); - default_src.push(crate::pattern::format_real_schema(schema)); + default_src.push(crate::pattern::format_real_schema(schema, use_https_schema)); } csp_header.replace(Csp::DirectiveMap(csp_map).to_string()); @@ -747,17 +752,25 @@ mod test { #[cfg(custom_protocol)] { assert_eq!( - manager.get_url().to_string(), + manager.get_url(false).to_string(), if cfg!(windows) || cfg!(target_os = "android") { "http://tauri.localhost/" } else { "tauri://localhost" } ); + assert_eq!( + manager.get_url(true).to_string(), + if cfg!(windows) || cfg!(target_os = "android") { + "https://tauri.localhost/" + } else { + "tauri://localhost" + } + ); } #[cfg(dev)] - assert_eq!(manager.get_url().to_string(), "http://localhost:4000/"); + assert_eq!(manager.get_url(false).to_string(), "http://localhost:4000/"); } struct EventSetup { diff --git a/crates/tauri/src/manager/webview.rs b/crates/tauri/src/manager/webview.rs index 5eb4ba8de2a3..1d150269d939 100644 --- a/crates/tauri/src/manager/webview.rs +++ b/crates/tauri/src/manager/webview.rs @@ -137,10 +137,14 @@ impl WebviewManager { let mut webview_attributes = pending.webview_attributes; + let use_https_scheme = webview_attributes.use_https_scheme; + let ipc_init = IpcJavascript { isolation_origin: &match &*app_manager.pattern { #[cfg(feature = "isolation")] - crate::Pattern::Isolation { schema, .. } => crate::pattern::format_real_schema(schema), + crate::Pattern::Isolation { schema, .. } => { + crate::pattern::format_real_schema(schema, use_https_scheme) + } _ => "".to_string(), }, } @@ -180,6 +184,7 @@ impl WebviewManager { &ipc_init.into_string(), &pattern_init.into_string(), is_init_global, + use_https_scheme, )?); for plugin_init_script in plugin_init_scripts { @@ -190,7 +195,7 @@ impl WebviewManager { if let crate::Pattern::Isolation { schema, .. } = &*app_manager.pattern { webview_attributes = webview_attributes.initialization_script( &IsolationJavascript { - isolation_src: &crate::pattern::format_real_schema(schema), + isolation_src: &crate::pattern::format_real_schema(schema, use_https_scheme), style: tauri_utils::pattern::isolation::IFRAME_STYLE, } .render_default(&Default::default())? @@ -232,7 +237,8 @@ impl WebviewManager { && window_url.scheme() != "http" && window_url.scheme() != "https" { - format!("http://{}.localhost", window_url.scheme()) + let https = if use_https_scheme { "https" } else { "http" }; + format!("{https}://{}.localhost", window_url.scheme()) } else if let Some(host) = window_url.host() { format!( "{}://{}{}", @@ -320,6 +326,7 @@ impl WebviewManager { assets.clone(), *crypto_keys.aes_gcm().raw(), window_origin, + use_https_scheme, ); pending.register_uri_scheme_protocol(schema, move |webview_id, request, responder| { protocol(webview_id, request, UriSchemeResponder(responder)) @@ -335,6 +342,7 @@ impl WebviewManager { ipc_script: &str, pattern_script: &str, with_global_tauri: bool, + use_https_scheme: bool, ) -> crate::Result { #[derive(Template)] #[default_template("../../scripts/init.js")] @@ -357,6 +365,7 @@ impl WebviewManager { #[default_template("../../scripts/core.js")] struct CoreJavascript<'a> { os_name: &'a str, + protocol_scheme: &'a str, invoke_key: &'a str, } @@ -378,6 +387,7 @@ impl WebviewManager { bundle_script, core_script: &CoreJavascript { os_name: std::env::consts::OS, + protocol_scheme: if use_https_scheme { "https" } else { "http" }, invoke_key: self.invoke_key(), } .render_default(&Default::default())? @@ -411,7 +421,7 @@ impl WebviewManager { let url = if PROXY_DEV_SERVER { Cow::Owned(Url::parse("tauri://localhost").unwrap()) } else { - app_manager.get_url() + app_manager.get_url(pending.webview_attributes.use_https_scheme) }; // ignore "index.html" just to simplify the url if path.to_str() != Some("index.html") { @@ -425,7 +435,7 @@ impl WebviewManager { } } WebviewUrl::External(url) => { - let config_url = app_manager.get_url(); + let config_url = app_manager.get_url(pending.webview_attributes.use_https_scheme); let is_local = config_url.make_relative(url).is_some(); let mut url = url.clone(); if is_local && PROXY_DEV_SERVER { diff --git a/crates/tauri/src/pattern.rs b/crates/tauri/src/pattern.rs index 221fce9fb1c2..04b89afb539a 100644 --- a/crates/tauri/src/pattern.rs +++ b/crates/tauri/src/pattern.rs @@ -85,9 +85,10 @@ pub(crate) struct PatternJavascript { } #[allow(dead_code)] -pub(crate) fn format_real_schema(schema: &str) -> String { +pub(crate) fn format_real_schema(schema: &str, https: bool) -> String { if cfg!(windows) || cfg!(target_os = "android") { - format!("http://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}") + let https = if https { "https" } else { "http" }; + format!("{https}://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}") } else { format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}") } diff --git a/crates/tauri/src/protocol/isolation.rs b/crates/tauri/src/protocol/isolation.rs index 6d546d288695..f85f8e6cd3a7 100644 --- a/crates/tauri/src/protocol/isolation.rs +++ b/crates/tauri/src/protocol/isolation.rs @@ -21,9 +21,11 @@ pub fn get( assets: Arc, aes_gcm_key: [u8; 32], window_origin: String, + use_https_scheme: bool, ) -> UriSchemeProtocolHandler { let frame_src = if cfg!(any(windows, target_os = "android")) { - format!("http://{schema}.localhost") + let https = if use_https_scheme { "https" } else { "http" }; + format!("{https}://{schema}.localhost") } else { format!("{schema}:") }; diff --git a/crates/tauri/src/protocol/tauri.rs b/crates/tauri/src/protocol/tauri.rs index 2d33c4a00f7f..db47576582d5 100644 --- a/crates/tauri/src/protocol/tauri.rs +++ b/crates/tauri/src/protocol/tauri.rs @@ -152,7 +152,8 @@ fn get_response( #[cfg(not(all(dev, mobile)))] let mut response = { - let asset = manager.get_asset(path)?; + let use_https_scheme = request.uri().scheme() == Some(&http::uri::Scheme::HTTPS); + let asset = manager.get_asset(path, use_https_scheme)?; builder = builder.header(CONTENT_TYPE, &asset.mime_type); if let Some(csp) = &asset.csp_header { builder = builder.header("Content-Security-Policy", csp); diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index e0df92ecea08..cadc6d1d8ab9 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -787,6 +787,21 @@ fn main() { self.webview_attributes.browser_extensions_enabled = enabled; self } + + /// Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. + /// + /// ## Note + /// + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// + /// ## Warning + /// + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + #[must_use] + pub fn use_https_scheme(mut self, enabled: bool) -> Self { + self.webview_attributes.use_https_scheme = enabled; + self + } } /// Webview. @@ -1173,9 +1188,11 @@ fn main() { } fn is_local_url(&self, current_url: &Url) -> bool { + let uses_https = current_url.scheme() == "https"; + // if from `tauri://` custom protocol ({ - let protocol_url = self.manager().protocol_url(); + let protocol_url = self.manager().protocol_url(uses_https); current_url.scheme() == protocol_url.scheme() && current_url.domain() == protocol_url.domain() }) || @@ -1183,7 +1200,7 @@ fn main() { // or if relative to `devUrl` or `frontendDist` self .manager() - .get_url() + .get_url(uses_https) .make_relative(current_url) .is_some() @@ -1199,7 +1216,7 @@ fn main() { // so we check using the first part of the domain #[cfg(any(windows, target_os = "android"))] let local = { - let protocol_url = self.manager().protocol_url(); + let protocol_url = self.manager().protocol_url(uses_https); let maybe_protocol = current_url .domain() .and_then(|d| d .split_once('.')) diff --git a/crates/tauri/src/webview/webview_window.rs b/crates/tauri/src/webview/webview_window.rs index ee1878e72252..c6837661468d 100644 --- a/crates/tauri/src/webview/webview_window.rs +++ b/crates/tauri/src/webview/webview_window.rs @@ -896,6 +896,21 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { self.webview_builder = self.webview_builder.browser_extensions_enabled(enabled); self } + + /// Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. + /// + /// ## Note + /// + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// + /// ## Warning + /// + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + #[must_use] + pub fn use_https_scheme(mut self, enabled: bool) -> Self { + self.webview_builder = self.webview_builder.use_https_scheme(enabled); + self + } } /// A type that wraps a [`Window`] together with a [`Webview`]. diff --git a/packages/api/src/webview.ts b/packages/api/src/webview.ts index 5b16f058b48e..9861a6b95f7b 100644 --- a/packages/api/src/webview.ts +++ b/packages/api/src/webview.ts @@ -728,6 +728,21 @@ interface WebviewOptions { * - **Android / iOS**: Unsupported. */ zoomHotkeysEnabled?: boolean + + /** + * Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. + * + * #### Note + * + * Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + * + * #### Warning + * + * Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + * + * @since 2.1.0 + */ + useHttpsScheme?: boolean } export { Webview, getCurrentWebview, getAllWebviews } From 55ff7d5f2c78e933a04195cc9455c0d093826286 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Thu, 24 Oct 2024 11:14:46 +0300 Subject: [PATCH 2/9] fix compilation --- crates/tauri-runtime/src/webview.rs | 1 - crates/tauri/src/protocol/tauri.rs | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index 6a592a0cbeeb..45d85fa271ea 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -396,7 +396,6 @@ impl WebviewAttributes { self.use_https_scheme = enabled; self } - } /// IPC handler. diff --git a/crates/tauri/src/protocol/tauri.rs b/crates/tauri/src/protocol/tauri.rs index db47576582d5..ac33b5be2de7 100644 --- a/crates/tauri/src/protocol/tauri.rs +++ b/crates/tauri/src/protocol/tauri.rs @@ -30,7 +30,10 @@ pub fn get( ) -> UriSchemeProtocolHandler { #[cfg(all(dev, mobile))] let url = { - let mut url = manager.get_url().as_str().to_string(); + let mut url = manager + .get_url(window_origin.starts_with("https")) + .as_str() + .to_string(); if url.ends_with('/') { url.pop(); } From 0241768661fa3fd6d8b7e3608b4045823df79a30 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Mon, 4 Nov 2024 16:14:08 +0200 Subject: [PATCH 3/9] Apply suggestions from code review Co-authored-by: Fabian-Lars --- crates/tauri-runtime/src/webview.rs | 2 +- crates/tauri-utils/src/config.rs | 2 +- crates/tauri/src/webview/mod.rs | 2 +- crates/tauri/src/webview/webview_window.rs | 2 +- packages/api/src/webview.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index 45d85fa271ea..6be490680f1e 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -386,7 +386,7 @@ impl WebviewAttributes { /// /// ## Note /// - /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. /// /// ## Warning /// diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 93daba2189fc..03936b9d65b8 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -1491,7 +1491,7 @@ pub struct WindowConfig { /// /// ## Note /// - /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. /// /// ## Warning /// diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index cadc6d1d8ab9..f6882b647570 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -792,7 +792,7 @@ fn main() { /// /// ## Note /// - /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. /// /// ## Warning /// diff --git a/crates/tauri/src/webview/webview_window.rs b/crates/tauri/src/webview/webview_window.rs index c6837661468d..83ab6780fe51 100644 --- a/crates/tauri/src/webview/webview_window.rs +++ b/crates/tauri/src/webview/webview_window.rs @@ -901,7 +901,7 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// /// ## Note /// - /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. /// /// ## Warning /// diff --git a/packages/api/src/webview.ts b/packages/api/src/webview.ts index 9861a6b95f7b..0b54eeddca26 100644 --- a/packages/api/src/webview.ts +++ b/packages/api/src/webview.ts @@ -734,7 +734,7 @@ interface WebviewOptions { * * #### Note * - * Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. + * Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. * * #### Warning * From 3aee85ed92cdba8e9678d6e375e9cc4ce560b3dc Mon Sep 17 00:00:00 2001 From: amrbashir Date: Mon, 4 Nov 2024 16:18:41 +0200 Subject: [PATCH 4/9] change wording --- crates/tauri-cli/config.schema.json | 2 +- crates/tauri-runtime/src/webview.rs | 2 +- crates/tauri-schema-generator/schemas/config.schema.json | 2 +- crates/tauri-utils/src/config.rs | 2 +- crates/tauri/src/webview/mod.rs | 2 +- crates/tauri/src/webview/webview_window.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index 0afd069e6d9c..c3c0bc75a73a 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -488,7 +488,7 @@ "type": "boolean" }, "useHttpsScheme": { - "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them.", + "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data.", "default": false, "type": "boolean" } diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index 6be490680f1e..3b4259783398 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -390,7 +390,7 @@ impl WebviewAttributes { /// /// ## Warning /// - /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data. #[must_use] pub fn use_https_scheme(mut self, enabled: bool) -> Self { self.use_https_scheme = enabled; diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index 0afd069e6d9c..c3c0bc75a73a 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -488,7 +488,7 @@ "type": "boolean" }, "useHttpsScheme": { - "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and is therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them.", + "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data.", "default": false, "type": "boolean" } diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 03936b9d65b8..c589bf340689 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -1495,7 +1495,7 @@ pub struct WindowConfig { /// /// ## Warning /// - /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data. #[serde(default, alias = "use-https-scheme")] pub use_https_scheme: bool, } diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index f6882b647570..675556f60241 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -796,7 +796,7 @@ fn main() { /// /// ## Warning /// - /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data. #[must_use] pub fn use_https_scheme(mut self, enabled: bool) -> Self { self.webview_attributes.use_https_scheme = enabled; diff --git a/crates/tauri/src/webview/webview_window.rs b/crates/tauri/src/webview/webview_window.rs index 83ab6780fe51..13eda40d0736 100644 --- a/crates/tauri/src/webview/webview_window.rs +++ b/crates/tauri/src/webview/webview_window.rs @@ -905,7 +905,7 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// /// ## Warning /// - /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. + /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data. #[must_use] pub fn use_https_scheme(mut self, enabled: bool) -> Self { self.webview_builder = self.webview_builder.use_https_scheme(enabled); From 7c499dae21874b38a52e858cc014c98ed1e6143e Mon Sep 17 00:00:00 2001 From: amrbashir Date: Mon, 4 Nov 2024 16:39:17 +0200 Subject: [PATCH 5/9] add migrations --- .../src/migrate/migrations/v1/config.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/tauri-cli/src/migrate/migrations/v1/config.rs b/crates/tauri-cli/src/migrate/migrations/v1/config.rs index ab956e76aa19..a38cb676b966 100644 --- a/crates/tauri-cli/src/migrate/migrations/v1/config.rs +++ b/crates/tauri-cli/src/migrate/migrations/v1/config.rs @@ -79,6 +79,18 @@ fn migrate_config(config: &mut Value) -> Result { .clone(); if let Some(tauri_config) = config.get_mut("tauri").and_then(|c| c.as_object_mut()) { + // useHttpsScheme + if let Some(windows) = tauri_config + .get_mut("windows") + .and_then(|w| w.as_array_mut()) + { + for window in windows { + if let Some(window) = window.as_object_mut() { + window.insert("useHttpsScheme".to_string(), true.into()); + } + } + } + // allowlist if let Some(allowlist) = tauri_config.remove("allowlist") { let allowlist = process_allowlist(tauri_config, allowlist)?; @@ -802,7 +814,10 @@ mod test { "pattern": { "use": "brownfield" }, "security": { "csp": "default-src 'self' tauri:" - } + }, + "windows": [{ + "label": "asd", + }] } }); @@ -907,6 +922,8 @@ mod test { migrated["app"]["withGlobalTauri"], original["build"]["withGlobalTauri"] ); + + assert_eq!(migrated["app"]["windows"][0]["useHttpsScheme"], true); } #[test] From 1ead0895a3c908c59d0a8de2d9c3b015aae77bf6 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Mon, 4 Nov 2024 17:14:14 +0200 Subject: [PATCH 6/9] migrate `dangerousUseHttpScheme` --- .../src/migrate/migrations/v1/config.rs | 56 ++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/crates/tauri-cli/src/migrate/migrations/v1/config.rs b/crates/tauri-cli/src/migrate/migrations/v1/config.rs index a38cb676b966..2b211470a096 100644 --- a/crates/tauri-cli/src/migrate/migrations/v1/config.rs +++ b/crates/tauri-cli/src/migrate/migrations/v1/config.rs @@ -79,26 +79,36 @@ fn migrate_config(config: &mut Value) -> Result { .clone(); if let Some(tauri_config) = config.get_mut("tauri").and_then(|c| c.as_object_mut()) { - // useHttpsScheme + // allowlist + if let Some(allowlist) = tauri_config.remove("allowlist") { + let allowlist = process_allowlist(tauri_config, allowlist)?; + let permissions = allowlist_to_permissions(allowlist); + migrated.plugins = plugins_from_permissions(&permissions); + migrated.permissions = permissions; + } + + // dangerousUseHttpScheme/useHttpsScheme + let dangerouse_use_http = tauri_config + .get("security") + .and_then(|w| w.as_object()) + .and_then(|w| { + w.get("dangerousUseHttpScheme") + .or_else(|| w.get("dangerous-use-http-scheme")) + }) + .and_then(|v| v.as_bool()) + .unwrap_or_default(); + if let Some(windows) = tauri_config .get_mut("windows") .and_then(|w| w.as_array_mut()) { for window in windows { if let Some(window) = window.as_object_mut() { - window.insert("useHttpsScheme".to_string(), true.into()); + window.insert("useHttpsScheme".to_string(), (!dangerouse_use_http).into()); } } } - // allowlist - if let Some(allowlist) = tauri_config.remove("allowlist") { - let allowlist = process_allowlist(tauri_config, allowlist)?; - let permissions = allowlist_to_permissions(allowlist); - migrated.plugins = plugins_from_permissions(&permissions); - migrated.permissions = permissions; - } - // security if let Some(security) = tauri_config .get_mut("security") @@ -815,9 +825,7 @@ mod test { "security": { "csp": "default-src 'self' tauri:" }, - "windows": [{ - "label": "asd", - }] + "windows": [{}] } }); @@ -958,6 +966,28 @@ mod test { ); } + #[test] + fn migrate_dangerous_use_http_scheme() { + let original = serde_json::json!({ + "tauri": { + "windows": [{}], + "security": { + "dangerousUseHttpScheme": true, + } + } + }); + + let migrated = migrate(&original); + assert_eq!( + !migrated["app"]["windows"][0]["useHttpsScheme"] + .as_bool() + .unwrap(), + original["tauri"]["security"]["dangerousUseHttpScheme"] + .as_bool() + .unwrap() + ); + } + #[test] fn can_migrate_default_config() { let original = serde_json::to_value(tauri_utils_v1::config::Config::default()).unwrap(); From dfb804430253f13165873033cf1555cda2a7e994 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 5 Nov 2024 07:35:46 -0300 Subject: [PATCH 7/9] fmt --- .changes/use_https_windows-and-android-config.md | 3 --- .changes/use_https_windows-and-android.md | 3 --- 2 files changed, 6 deletions(-) diff --git a/.changes/use_https_windows-and-android-config.md b/.changes/use_https_windows-and-android-config.md index 3ed79b05a8a4..3e5598a89e42 100644 --- a/.changes/use_https_windows-and-android-config.md +++ b/.changes/use_https_windows-and-android-config.md @@ -4,6 +4,3 @@ --- Add `app > windows > useHttpsScheme` config option to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - - - diff --git a/.changes/use_https_windows-and-android.md b/.changes/use_https_windows-and-android.md index ca68350686b9..0e1bbb1a6c6d 100644 --- a/.changes/use_https_windows-and-android.md +++ b/.changes/use_https_windows-and-android.md @@ -5,6 +5,3 @@ --- Add `WebviewWindowBuilder/WebviewBuilder::use_https_scheme` to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - - - From d803579d7b5342507a20a10f265961cb8a14de2f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Tue, 5 Nov 2024 08:12:16 -0300 Subject: [PATCH 8/9] infer AssetResolver::get https scheme config --- crates/tauri-runtime-wry/src/lib.rs | 65 ++++++++++++++++++++--------- crates/tauri-runtime/src/window.rs | 18 +++++++- crates/tauri/src/app.rs | 19 ++++++--- crates/tauri/src/manager/mod.rs | 4 +- crates/tauri/src/manager/webview.rs | 3 +- crates/tauri/src/pattern.rs | 4 +- crates/tauri/src/webview/mod.rs | 23 +++++++++- crates/tauri/src/window/mod.rs | 6 ++- examples/api/src-tauri/src/lib.rs | 3 +- 9 files changed, 111 insertions(+), 34 deletions(-) diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index db8ad88095ba..838def7790ec 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -22,8 +22,8 @@ use tauri_runtime::{ monitor::Monitor, webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler}, window::{ - CursorIcon, DetachedWindow, DragDropEvent, PendingWindow, RawWindow, WebviewEvent, - WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, WindowSizeConstraints, + CursorIcon, DetachedWindow, DetachedWindowWebview, DragDropEvent, PendingWindow, RawWindow, + WebviewEvent, WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, WindowSizeConstraints, }, DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState, ProgressBarStatus, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, @@ -276,7 +276,16 @@ impl Context { let label = pending.label.clone(); let context = self.clone(); let window_id = self.next_window_id(); - let webview_id = pending.webview.as_ref().map(|_| context.next_webview_id()); + let (webview_id, use_https_scheme) = pending + .webview + .as_ref() + .map(|w| { + ( + Some(context.next_webview_id()), + w.webview_attributes.use_https_scheme, + ) + }) + .unwrap_or((None, false)); send_user_message( self, @@ -300,13 +309,19 @@ impl Context { context: self.clone(), }; - let detached_webview = webview_id.map(|id| DetachedWebview { - label: label.clone(), - dispatcher: WryWebviewDispatcher { - window_id: Arc::new(Mutex::new(window_id)), - webview_id: id, - context: self.clone(), - }, + let detached_webview = webview_id.map(|id| { + let webview = DetachedWebview { + label: label.clone(), + dispatcher: WryWebviewDispatcher { + window_id: Arc::new(Mutex::new(window_id)), + webview_id: id, + context: self.clone(), + }, + }; + DetachedWindowWebview { + webview, + use_https_scheme, + } }); Ok(DetachedWindow { @@ -2499,10 +2514,16 @@ impl Runtime for Wry { ) -> Result> { let label = pending.label.clone(); let window_id = self.context.next_window_id(); - let webview_id = pending + let (webview_id, use_https_scheme) = pending .webview .as_ref() - .map(|_| self.context.next_webview_id()); + .map(|w| { + ( + Some(self.context.next_webview_id()), + w.webview_attributes.use_https_scheme, + ) + }) + .unwrap_or((None, false)); let window = create_window( window_id, @@ -2526,13 +2547,19 @@ impl Runtime for Wry { .borrow_mut() .insert(window_id, window); - let detached_webview = webview_id.map(|id| DetachedWebview { - label: label.clone(), - dispatcher: WryWebviewDispatcher { - window_id: Arc::new(Mutex::new(window_id)), - webview_id: id, - context: self.context.clone(), - }, + let detached_webview = webview_id.map(|id| { + let webview = DetachedWebview { + label: label.clone(), + dispatcher: WryWebviewDispatcher { + window_id: Arc::new(Mutex::new(window_id)), + webview_id: id, + context: self.context.clone(), + }, + }; + DetachedWindowWebview { + webview, + use_https_scheme, + } }); Ok(DetachedWindow { diff --git a/crates/tauri-runtime/src/window.rs b/crates/tauri-runtime/src/window.rs index 54676ef65bf9..cea526f5f120 100644 --- a/crates/tauri-runtime/src/window.rs +++ b/crates/tauri-runtime/src/window.rs @@ -512,7 +512,23 @@ pub struct DetachedWindow> { pub dispatcher: R::WindowDispatcher, /// The webview dispatcher in case this window has an attached webview. - pub webview: Option>, + pub webview: Option>, +} + +/// A detached webview associated with a window. +#[derive(Debug)] +pub struct DetachedWindowWebview> { + pub webview: DetachedWebview, + pub use_https_scheme: bool, +} + +impl> Clone for DetachedWindowWebview { + fn clone(&self) -> Self { + Self { + webview: self.webview.clone(), + use_https_scheme: self.use_https_scheme, + } + } } impl> Clone for DetachedWindow { diff --git a/crates/tauri/src/app.rs b/crates/tauri/src/app.rs index e7f7a36a3208..509ba340c8f4 100644 --- a/crates/tauri/src/app.rs +++ b/crates/tauri/src/app.rs @@ -266,13 +266,12 @@ pub struct AssetResolver { } impl AssetResolver { - /// Same as [AssetResolver::get_for_scheme] but always resolves with csp header for `http` scheme. - pub fn get(&self, path: String) -> Option { - self.get_for_scheme(path, false) - } - /// Gets the app asset associated with the given path. /// + /// By default it tries to infer your application's URL scheme in production by checking if all webviews + /// were configured with [`crate::webview::WebviewBuilder::use_https_scheme`] or `tauri.conf.json > app > windows > useHttpsScheme`. + /// If you are resolving an asset for a webview with a more dynamic configuration, see [`AssetResolver::get_for_scheme`]. + /// /// Resolves to the embedded asset that is part of the app /// in dev when [`devUrl`](https://v2.tauri.app/reference/config/#devurl) points to a folder in your filesystem /// or in production when [`frontendDist`](https://v2.tauri.app/reference/config/#frontenddist) @@ -280,6 +279,16 @@ impl AssetResolver { /// /// Fallbacks to reading the asset from the [distDir] folder so the behavior is consistent in development. /// Note that the dist directory must exist so you might need to build your frontend assets first. + pub fn get(&self, path: String) -> Option { + let use_https_scheme = self + .manager + .webviews() + .values() + .all(|webview| webview.use_https_scheme()); + self.get_for_scheme(path, use_https_scheme) + } + + /// Same as [AssetResolver::get] but resolves the custom protocol scheme based on a parameter. /// /// - `use_https_scheme`: If `true` when using [`Pattern::Isolation`](tauri::Pattern::Isolation), /// the csp header will contain `https://tauri.localhost` instead of `http://tauri.localhost` diff --git a/crates/tauri/src/manager/mod.rs b/crates/tauri/src/manager/mod.rs index 585f60921326..81f0eaae284d 100644 --- a/crates/tauri/src/manager/mod.rs +++ b/crates/tauri/src/manager/mod.rs @@ -342,8 +342,8 @@ impl AppManager { pub(crate) fn protocol_url(&self, https: bool) -> Cow<'_, Url> { if cfg!(windows) || cfg!(target_os = "android") { - let https = if https { "https" } else { "http" }; - Cow::Owned(Url::parse(&format!("{https}://tauri.localhost")).unwrap()) + let scheme = if https { "https" } else { "http" }; + Cow::Owned(Url::parse(&format!("{scheme}://tauri.localhost")).unwrap()) } else { Cow::Owned(Url::parse("tauri://localhost").unwrap()) } diff --git a/crates/tauri/src/manager/webview.rs b/crates/tauri/src/manager/webview.rs index 1d150269d939..8773600dca2e 100644 --- a/crates/tauri/src/manager/webview.rs +++ b/crates/tauri/src/manager/webview.rs @@ -582,8 +582,9 @@ impl WebviewManager { &self, window: Window, webview: DetachedWebview, + use_https_scheme: bool, ) -> Webview { - let webview = Webview::new(window, webview); + let webview = Webview::new(window, webview, use_https_scheme); let webview_event_listeners = self.event_listeners.clone(); let webview_ = webview.clone(); diff --git a/crates/tauri/src/pattern.rs b/crates/tauri/src/pattern.rs index 04b89afb539a..d0cd132c21b9 100644 --- a/crates/tauri/src/pattern.rs +++ b/crates/tauri/src/pattern.rs @@ -87,8 +87,8 @@ pub(crate) struct PatternJavascript { #[allow(dead_code)] pub(crate) fn format_real_schema(schema: &str, https: bool) -> String { if cfg!(windows) || cfg!(target_os = "android") { - let https = if https { "https" } else { "http" }; - format!("{https}://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}") + let scheme = if https { "https" } else { "http" }; + format!("{scheme}://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}") } else { format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}") } diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index 53e204dfbc40..199d5a8f90d8 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -605,11 +605,17 @@ tauri::Builder::default() pending.webview_attributes.bounds = Some(tauri_runtime::Rect { size, position }); + let use_https_scheme = pending.webview_attributes.use_https_scheme; + let webview = match &mut window.runtime() { RuntimeOrDispatch::Dispatch(dispatcher) => dispatcher.create_webview(pending), _ => unimplemented!(), } - .map(|webview| app_manager.webview.attach_webview(window.clone(), webview))?; + .map(|webview| { + app_manager + .webview + .attach_webview(window.clone(), webview, use_https_scheme) + })?; Ok(webview) } @@ -821,6 +827,7 @@ pub struct Webview { pub(crate) manager: Arc>, pub(crate) app_handle: AppHandle, pub(crate) resources_table: Arc>, + use_https_scheme: bool, } impl std::fmt::Debug for Webview { @@ -828,6 +835,7 @@ impl std::fmt::Debug for Webview { f.debug_struct("Window") .field("window", &self.window.lock().unwrap()) .field("webview", &self.webview) + .field("use_https_scheme", &self.use_https_scheme) .finish() } } @@ -840,6 +848,7 @@ impl Clone for Webview { manager: self.manager.clone(), app_handle: self.app_handle.clone(), resources_table: self.resources_table.clone(), + use_https_scheme: self.use_https_scheme, } } } @@ -862,13 +871,18 @@ impl PartialEq for Webview { /// Base webview functions. impl Webview { /// Create a new webview that is attached to the window. - pub(crate) fn new(window: Window, webview: DetachedWebview) -> Self { + pub(crate) fn new( + window: Window, + webview: DetachedWebview, + use_https_scheme: bool, + ) -> Self { Self { manager: window.manager.clone(), app_handle: window.app_handle.clone(), window: Arc::new(Mutex::new(window)), webview, resources_table: Default::default(), + use_https_scheme, } } @@ -895,6 +909,11 @@ impl Webview { &self.webview.label } + /// Whether the webview was configured to use the HTTPS scheme or not. + pub(crate) fn use_https_scheme(&self) -> bool { + self.use_https_scheme + } + /// Registers a window event listener. pub fn on_webview_event(&self, f: F) { self diff --git a/crates/tauri/src/window/mod.rs b/crates/tauri/src/window/mod.rs index 9b8e02b8ef7a..f1292b37ab94 100644 --- a/crates/tauri/src/window/mod.rs +++ b/crates/tauri/src/window/mod.rs @@ -381,7 +381,11 @@ tauri::Builder::default() ); if let Some(webview) = detached_window.webview { - app_manager.webview.attach_webview(window.clone(), webview); + app_manager.webview.attach_webview( + window.clone(), + webview.webview, + webview.use_https_scheme, + ); } window diff --git a/examples/api/src-tauri/src/lib.rs b/examples/api/src-tauri/src/lib.rs index 512f43c0aac0..7f7007eef558 100644 --- a/examples/api/src-tauri/src/lib.rs +++ b/examples/api/src-tauri/src/lib.rs @@ -66,7 +66,8 @@ pub fn run_app) + Send + 'static>( .build()?, )); - let mut window_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()); + let mut window_builder = + WebviewWindowBuilder::new(app, "main", WebviewUrl::default()).use_https_scheme(true); #[cfg(all(desktop, not(test)))] { From 57511b141d2d41e459473d5ddd234754b57d026f Mon Sep 17 00:00:00 2001 From: amrbashir Date: Tue, 5 Nov 2024 14:22:04 +0200 Subject: [PATCH 9/9] fix tests --- crates/tauri/src/test/mock_runtime.rs | 57 ++++++++++++++++----------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/crates/tauri/src/test/mock_runtime.rs b/crates/tauri/src/test/mock_runtime.rs index 80c32e26d8ed..7f51b1902077 100644 --- a/crates/tauri/src/test/mock_runtime.rs +++ b/crates/tauri/src/test/mock_runtime.rs @@ -9,8 +9,10 @@ use tauri_runtime::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, monitor::Monitor, webview::{DetachedWebview, PendingWebview}, - window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WindowEvent, WindowId}, - window::{WindowBuilder, WindowBuilderBase}, + window::{ + CursorIcon, DetachedWindow, DetachedWindowWebview, PendingWindow, RawWindow, WindowBuilder, + WindowBuilderBase, WindowEvent, WindowId, + }, DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent, WebviewDispatch, WindowDispatch, WindowEventId, @@ -158,14 +160,17 @@ impl RuntimeHandle for MockRuntimeHandle { }, ); - let webview = webview_id.map(|id| DetachedWebview { - label: pending.label.clone(), - dispatcher: MockWebviewDispatcher { - id, - context: self.context.clone(), - url: Arc::new(Mutex::new(pending.webview.unwrap().url)), - last_evaluated_script: Default::default(), + let webview = webview_id.map(|id| DetachedWindowWebview { + webview: DetachedWebview { + label: pending.label.clone(), + dispatcher: MockWebviewDispatcher { + id, + context: self.context.clone(), + url: Arc::new(Mutex::new(pending.webview.unwrap().url)), + last_evaluated_script: Default::default(), + }, }, + use_https_scheme: false, }); Ok(DetachedWindow { @@ -773,14 +778,17 @@ impl WindowDispatch for MockWindowDispatcher { }, ); - let webview = webview_id.map(|id| DetachedWebview { - label: pending.label.clone(), - dispatcher: MockWebviewDispatcher { - id, - context: self.context.clone(), - url: Arc::new(Mutex::new(pending.webview.unwrap().url)), - last_evaluated_script: Default::default(), + let webview = webview_id.map(|id| DetachedWindowWebview { + webview: DetachedWebview { + label: pending.label.clone(), + dispatcher: MockWebviewDispatcher { + id, + context: self.context.clone(), + url: Arc::new(Mutex::new(pending.webview.unwrap().url)), + last_evaluated_script: Default::default(), + }, }, + use_https_scheme: false, }); Ok(DetachedWindow { @@ -1065,14 +1073,17 @@ impl Runtime for MockRuntime { }, ); - let webview = webview_id.map(|id| DetachedWebview { - label: pending.label.clone(), - dispatcher: MockWebviewDispatcher { - id, - context: self.context.clone(), - url: Arc::new(Mutex::new(pending.webview.unwrap().url)), - last_evaluated_script: Default::default(), + let webview = webview_id.map(|id| DetachedWindowWebview { + webview: DetachedWebview { + label: pending.label.clone(), + dispatcher: MockWebviewDispatcher { + id, + context: self.context.clone(), + url: Arc::new(Mutex::new(pending.webview.unwrap().url)), + last_evaluated_script: Default::default(), + }, }, + use_https_scheme: false, }); Ok(DetachedWindow {