Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): Allow http origin on Windows, fixes: #3007 #7645

Merged
merged 12 commits into from
Sep 26, 2023
5 changes: 5 additions & 0 deletions .changes/windows-http-scheme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri': 'patch:enhance'
lucasfernog marked this conversation as resolved.
Show resolved Hide resolved
---

Add setting to switch to `http://<scheme>.localhost/` for custom protocols on Windows.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ codegen-units = 1
lto = true
incremental = false
opt-level = "s"

[patch.crates-io]
wry = { git = "https://github.com/tauri-apps/wry", branch = "v0.24.1" }
2 changes: 1 addition & 1 deletion core/tauri-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {

if let Some(sdk_dir) = &attributes.windows_attributes.sdk_dir {
if let Some(sdk_dir_str) = sdk_dir.to_str() {
res.set_toolkit_path(sdk_dir_str);
// res.set_toolkit_path(sdk_dir_str);
} else {
return Err(anyhow!(
"sdk_dir path is not valid; only UTF-8 characters are allowed"
Expand Down
7 changes: 7 additions & 0 deletions core/tauri-config-schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
"security": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"updater": {
Expand Down Expand Up @@ -423,6 +424,7 @@
"default": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"allOf": [
Expand Down Expand Up @@ -2703,6 +2705,11 @@
"items": {
"$ref": "#/definitions/RemoteDomainAccessScope"
}
},
"dangerousUseHttpScheme": {
"description": "Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.\n\n**WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
Expand Down
5 changes: 5 additions & 0 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,11 @@ fn create_webview<T: UserEvent>(
});
}

#[cfg(windows)]
{
webview_builder = webview_builder.with_https_scheme(!pending.http_scheme);
}

if let Some(handler) = ipc_handler {
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
context,
Expand Down
5 changes: 5 additions & 0 deletions core/tauri-runtime/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {

pub uri_scheme_protocols: HashMap<String, Box<UriSchemeProtocol>>,

// Whether custom protocols on windows should use http://<scheme>.localhost/ instead of https://<scheme>.localhost/
pub http_scheme: bool,

/// How to handle IPC calls on the webview window.
pub ipc_handler: Option<WebviewIpcHandler<T, R>>,

Expand Down Expand Up @@ -281,6 +284,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
navigation_handler: Default::default(),
web_resource_request_handler: Default::default(),
url: "tauri://localhost".to_string(),
http_scheme: false,
})
}
}
Expand Down Expand Up @@ -312,6 +316,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
navigation_handler: Default::default(),
web_resource_request_handler: Default::default(),
url: "tauri://localhost".to_string(),
http_scheme: false,
})
}
}
Expand Down
10 changes: 9 additions & 1 deletion core/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,11 @@ pub struct SecurityConfig {
/// vulnerable to dangerous Tauri command related attacks otherwise.
#[serde(default, alias = "dangerous-remote-domain-ipc-access")]
pub dangerous_remote_domain_ipc_access: Vec<RemoteDomainAccessScope>,
/// Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.
///
/// **WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.
#[serde(default, alias = "dangerous-use-http-scheme")]
pub dangerous_use_http_scheme: bool,
}

/// Defines an allowlist type.
Expand Down Expand Up @@ -3717,6 +3722,7 @@ mod build {
let dev_csp = opt_lit(self.dev_csp.as_ref());
let freeze_prototype = self.freeze_prototype;
let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
let dangerous_use_http_scheme = &self.dangerous_use_http_scheme;
let dangerous_remote_domain_ipc_access =
vec_lit(&self.dangerous_remote_domain_ipc_access, identity);

Expand All @@ -3727,7 +3733,8 @@ mod build {
dev_csp,
freeze_prototype,
dangerous_disable_asset_csp_modification,
dangerous_remote_domain_ipc_access
dangerous_remote_domain_ipc_access,
dangerous_use_http_scheme
);
}
}
Expand Down Expand Up @@ -3994,6 +4001,7 @@ mod test {
freeze_prototype: false,
dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
dangerous_remote_domain_ipc_access: Vec::new(),
dangerous_use_http_scheme: false,
},
allowlist: AllowlistConfig::default(),
system_tray: None,
Expand Down
8 changes: 4 additions & 4 deletions core/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1573,16 +1573,17 @@ impl<R: Runtime> Builder<R> {
(self.invoke_responder, self.invoke_initialization_script),
);

let http_scheme = manager.config().tauri.security.dangerous_use_http_scheme;

// set up all the windows defined in the config
for config in manager.config().tauri.windows.clone() {
let label = config.label.clone();
let webview_attributes = WebviewAttributes::from(&config);

self.pending_windows.push(PendingWindow::with_config(
config,
webview_attributes,
label,
)?);
let mut pending = PendingWindow::with_config(config, webview_attributes, label)?;
pending.http_scheme = http_scheme;

self.pending_windows.push(pending);
}

#[cfg(any(windows, target_os = "linux"))]
Expand Down
27 changes: 20 additions & 7 deletions core/tauri/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ fn set_csp<R: Runtime>(
let default_src = csp
.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,
manager.config().tauri.security.dangerous_use_http_scheme,
));
}

Csp::DirectiveMap(csp).to_string()
Expand Down Expand Up @@ -388,7 +391,14 @@ impl<R: Runtime> WindowManager<R> {
match self.base_path() {
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
#[cfg(windows)]
_ => Cow::Owned(Url::parse("https://tauri.localhost").unwrap()),
_ => {
let scheme = if self.inner.config.tauri.security.dangerous_use_http_scheme {
"http"
} else {
"https"
};
Cow::Owned(Url::parse(&format!("{scheme}://tauri.localhost")).unwrap())
}
#[cfg(not(windows))]
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
}
Expand Down Expand Up @@ -429,17 +439,19 @@ impl<R: Runtime> WindowManager<R> {
}
.render_default(&Default::default())?;

let mut webview_attributes = pending.webview_attributes;

let ipc_init = IpcJavascript {
isolation_origin: &match self.pattern() {
#[cfg(feature = "isolation")]
Pattern::Isolation { schema, .. } => crate::pattern::format_real_schema(schema),
Pattern::Isolation { schema, .. } => {
crate::pattern::format_real_schema(schema, pending.http_scheme)
}
_ => "".to_string(),
},
}
.render_default(&Default::default())?;

let mut webview_attributes = pending.webview_attributes;

let mut window_labels = window_labels.to_vec();
let l = label.to_string();
if !window_labels.contains(&l) {
Expand All @@ -466,7 +478,7 @@ impl<R: Runtime> WindowManager<R> {
if let Pattern::Isolation { schema, .. } = self.pattern() {
webview_attributes = webview_attributes.initialization_script(
&IsolationJavascript {
isolation_src: &crate::pattern::format_real_schema(schema),
isolation_src: &crate::pattern::format_real_schema(schema, pending.http_scheme),
style: tauri_utils::pattern::isolation::IFRAME_STYLE,
}
.render_default(&Default::default())?
Expand All @@ -491,7 +503,8 @@ impl<R: Runtime> WindowManager<R> {
let window_origin = if window_url.scheme() == "data" {
"null".into()
} else if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" {
format!("https://{}.localhost", window_url.scheme())
let scheme = if pending.http_scheme { "http" } else { "https" };
format!("{scheme}://{}.localhost", window_url.scheme())
} else {
format!(
"{}://{}{}",
Expand Down
5 changes: 3 additions & 2 deletions core/tauri/src/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,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, _http: bool) -> String {
if cfg!(windows) {
format!("https://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
let http = if _http { "http" } else { "https" };
format!("{http}://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
} else {
format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}")
}
Expand Down
6 changes: 6 additions & 0 deletions core/tauri/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ impl<'a, R: Runtime> WindowBuilder<'a, R> {
)?;
pending.navigation_handler = self.navigation_handler.take();
pending.web_resource_request_handler = self.web_resource_request_handler.take();
pending.http_scheme = self
.manager
.config()
.tauri
.security
.dangerous_use_http_scheme;

let labels = self.manager.labels().into_iter().collect::<Vec<_>>();
let pending = self
Expand Down
19 changes: 17 additions & 2 deletions tooling/api/src/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ async function invoke<T>(cmd: string, args: InvokeArgs = {}): Promise<T> {
*
* @param filePath The file path.
* @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol.
* @param http Whether to use `http://<scheme>.localhost/` as the base on Windows instead of `https://<scheme>.localhost`. Must match the value of `dangerousUseHttpScheme` in tauri.conf.json if the origin differs from `http(s)://tauri.localhost`.
* @example
* ```typescript
* import { appDataDir, join } from '@tauri-apps/api/path';
Expand All @@ -126,10 +127,24 @@ async function invoke<T>(cmd: string, args: InvokeArgs = {}): Promise<T> {
*
* @since 1.0.0
*/
function convertFileSrc(filePath: string, protocol = 'asset'): string {
function convertFileSrc(
filePath: string,
protocol = 'asset',
http?: boolean
): string {
const path = encodeURIComponent(filePath)

let scheme =
window.location.origin === 'http://tauri.localhost' ? 'http' : 'https'
if (http === true) {
scheme = 'http'
}
if (http === false) {
scheme = 'https'
}
FabianLars marked this conversation as resolved.
Show resolved Hide resolved

return navigator.userAgent.includes('Windows')
? `https://${protocol}.localhost/${path}`
? `${scheme}://${protocol}.localhost/${path}`
: `${protocol}://localhost/${path}`
}

Expand Down
7 changes: 7 additions & 0 deletions tooling/cli/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
"security": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"updater": {
Expand Down Expand Up @@ -423,6 +424,7 @@
"default": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"allOf": [
Expand Down Expand Up @@ -2703,6 +2705,11 @@
"items": {
"$ref": "#/definitions/RemoteDomainAccessScope"
}
},
"dangerousUseHttpScheme": {
"description": "Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.\n\n**WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
Expand Down
Loading