Skip to content

Commit 9aa34ad

Browse files
FabianLarslucasfernog-crabnebulalucasfernog
authored
feat(core): Allow http origin on Windows, fixes: #3007 (#7645)
Co-authored-by: Lucas Nogueira <118899497+lucasfernog-crabnebula@users.noreply.github.com> Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent e8ff6b1 commit 9aa34ad

13 files changed

Lines changed: 112 additions & 25 deletions

File tree

.changes/windows-http-scheme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'tauri': 'patch:enhance'
3+
'tauri-runtime': 'patch:enhance'
4+
'tauri-runtime-wry': 'patch:enhance'
5+
'tauri-utils': 'patch:enhance'
6+
---
7+
8+
Add setting to switch to `http://<scheme>.localhost/` for custom protocols on Windows.

core/tauri-config-schema/schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
"security": {
168168
"dangerousDisableAssetCspModification": false,
169169
"dangerousRemoteDomainIpcAccess": [],
170+
"dangerousUseHttpScheme": false,
170171
"freezePrototype": false
171172
},
172173
"updater": {
@@ -423,6 +424,7 @@
423424
"default": {
424425
"dangerousDisableAssetCspModification": false,
425426
"dangerousRemoteDomainIpcAccess": [],
427+
"dangerousUseHttpScheme": false,
426428
"freezePrototype": false
427429
},
428430
"allOf": [
@@ -2740,6 +2742,11 @@
27402742
"items": {
27412743
"$ref": "#/definitions/RemoteDomainAccessScope"
27422744
}
2745+
},
2746+
"dangerousUseHttpScheme": {
2747+
"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.",
2748+
"default": false,
2749+
"type": "boolean"
27432750
}
27442751
},
27452752
"additionalProperties": false

core/tauri-runtime-wry/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,11 @@ fn create_webview<T: UserEvent>(
31963196
});
31973197
}
31983198

3199+
#[cfg(windows)]
3200+
{
3201+
webview_builder = webview_builder.with_https_scheme(!pending.http_scheme);
3202+
}
3203+
31993204
if let Some(handler) = ipc_handler {
32003205
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
32013206
context,

core/tauri-runtime/src/window.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
224224

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

227+
// Whether custom protocols on windows should use http://<scheme>.localhost/ instead of https://<scheme>.localhost/
228+
pub http_scheme: bool,
229+
227230
/// How to handle IPC calls on the webview window.
228231
pub ipc_handler: Option<WebviewIpcHandler<T, R>>,
229232

@@ -281,6 +284,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
281284
navigation_handler: Default::default(),
282285
web_resource_request_handler: Default::default(),
283286
url: "tauri://localhost".to_string(),
287+
http_scheme: false,
284288
})
285289
}
286290
}
@@ -312,6 +316,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
312316
navigation_handler: Default::default(),
313317
web_resource_request_handler: Default::default(),
314318
url: "tauri://localhost".to_string(),
319+
http_scheme: false,
315320
})
316321
}
317322
}

core/tauri-utils/src/config.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,11 @@ pub struct SecurityConfig {
13261326
/// vulnerable to dangerous Tauri command related attacks otherwise.
13271327
#[serde(default, alias = "dangerous-remote-domain-ipc-access")]
13281328
pub dangerous_remote_domain_ipc_access: Vec<RemoteDomainAccessScope>,
1329+
/// Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.
1330+
///
1331+
/// **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.
1332+
#[serde(default, alias = "dangerous-use-http-scheme")]
1333+
pub dangerous_use_http_scheme: bool,
13291334
}
13301335

13311336
/// Defines an allowlist type.
@@ -3736,6 +3741,7 @@ mod build {
37363741
let dev_csp = opt_lit(self.dev_csp.as_ref());
37373742
let freeze_prototype = self.freeze_prototype;
37383743
let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
3744+
let dangerous_use_http_scheme = &self.dangerous_use_http_scheme;
37393745
let dangerous_remote_domain_ipc_access =
37403746
vec_lit(&self.dangerous_remote_domain_ipc_access, identity);
37413747

@@ -3746,7 +3752,8 @@ mod build {
37463752
dev_csp,
37473753
freeze_prototype,
37483754
dangerous_disable_asset_csp_modification,
3749-
dangerous_remote_domain_ipc_access
3755+
dangerous_remote_domain_ipc_access,
3756+
dangerous_use_http_scheme
37503757
);
37513758
}
37523759
}
@@ -4013,6 +4020,7 @@ mod test {
40134020
freeze_prototype: false,
40144021
dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
40154022
dangerous_remote_domain_ipc_access: Vec::new(),
4023+
dangerous_use_http_scheme: false,
40164024
},
40174025
allowlist: AllowlistConfig::default(),
40184026
system_tray: None,

core/tauri/scripts/bundle.global.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/tauri/scripts/core.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
})
1414
}
1515

16+
const osName = __TEMPLATE_os_name__
17+
const protocolScheme = __TEMPLATE_protocol_scheme__
18+
19+
window.__TAURI__.convertFileSrc = function convertFileSrc(filePath, protocol = 'asset') {
20+
const path = encodeURIComponent(filePath)
21+
return osName === 'windows'
22+
? `${protocolScheme}://${protocol}.localhost/${path}`
23+
: `${protocol}://localhost/${path}`
24+
}
25+
1626
window.__TAURI__.transformCallback = function transformCallback(
1727
callback,
1828
once

core/tauri/src/app.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,16 +1573,17 @@ impl<R: Runtime> Builder<R> {
15731573
(self.invoke_responder, self.invoke_initialization_script),
15741574
);
15751575

1576+
let http_scheme = manager.config().tauri.security.dangerous_use_http_scheme;
1577+
15761578
// set up all the windows defined in the config
15771579
for config in manager.config().tauri.windows.clone() {
15781580
let label = config.label.clone();
15791581
let webview_attributes = WebviewAttributes::from(&config);
15801582

1581-
self.pending_windows.push(PendingWindow::with_config(
1582-
config,
1583-
webview_attributes,
1584-
label,
1585-
)?);
1583+
let mut pending = PendingWindow::with_config(config, webview_attributes, label)?;
1584+
pending.http_scheme = http_scheme;
1585+
1586+
self.pending_windows.push(pending);
15861587
}
15871588

15881589
#[cfg(any(windows, target_os = "linux"))]

core/tauri/src/manager.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ fn set_csp<R: Runtime>(
142142
let default_src = csp
143143
.entry("default-src".into())
144144
.or_insert_with(Default::default);
145-
default_src.push(crate::pattern::format_real_schema(schema));
145+
default_src.push(crate::pattern::format_real_schema(
146+
schema,
147+
manager.config().tauri.security.dangerous_use_http_scheme,
148+
));
146149
}
147150

148151
Csp::DirectiveMap(csp).to_string()
@@ -388,7 +391,14 @@ impl<R: Runtime> WindowManager<R> {
388391
match self.base_path() {
389392
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
390393
#[cfg(windows)]
391-
_ => Cow::Owned(Url::parse("https://tauri.localhost").unwrap()),
394+
_ => {
395+
let scheme = if self.inner.config.tauri.security.dangerous_use_http_scheme {
396+
"http"
397+
} else {
398+
"https"
399+
};
400+
Cow::Owned(Url::parse(&format!("{scheme}://tauri.localhost")).unwrap())
401+
}
392402
#[cfg(not(windows))]
393403
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
394404
}
@@ -429,17 +439,19 @@ impl<R: Runtime> WindowManager<R> {
429439
}
430440
.render_default(&Default::default())?;
431441

442+
let mut webview_attributes = pending.webview_attributes;
443+
432444
let ipc_init = IpcJavascript {
433445
isolation_origin: &match self.pattern() {
434446
#[cfg(feature = "isolation")]
435-
Pattern::Isolation { schema, .. } => crate::pattern::format_real_schema(schema),
447+
Pattern::Isolation { schema, .. } => {
448+
crate::pattern::format_real_schema(schema, pending.http_scheme)
449+
}
436450
_ => "".to_string(),
437451
},
438452
}
439453
.render_default(&Default::default())?;
440454

441-
let mut webview_attributes = pending.webview_attributes;
442-
443455
let mut window_labels = window_labels.to_vec();
444456
let l = label.to_string();
445457
if !window_labels.contains(&l) {
@@ -466,7 +478,7 @@ impl<R: Runtime> WindowManager<R> {
466478
if let Pattern::Isolation { schema, .. } = self.pattern() {
467479
webview_attributes = webview_attributes.initialization_script(
468480
&IsolationJavascript {
469-
isolation_src: &crate::pattern::format_real_schema(schema),
481+
isolation_src: &crate::pattern::format_real_schema(schema, pending.http_scheme),
470482
style: tauri_utils::pattern::isolation::IFRAME_STYLE,
471483
}
472484
.render_default(&Default::default())?
@@ -491,7 +503,8 @@ impl<R: Runtime> WindowManager<R> {
491503
let window_origin = if window_url.scheme() == "data" {
492504
"null".into()
493505
} else if cfg!(windows) && window_url.scheme() != "http" && window_url.scheme() != "https" {
494-
format!("https://{}.localhost", window_url.scheme())
506+
let scheme = if pending.http_scheme { "http" } else { "https" };
507+
format!("{scheme}://{}.localhost", window_url.scheme())
495508
} else {
496509
format!(
497510
"{}://{}{}",
@@ -782,6 +795,13 @@ impl<R: Runtime> WindowManager<R> {
782795
hotkeys: &'a str,
783796
}
784797

798+
#[derive(Template)]
799+
#[default_template("../scripts/core.js")]
800+
struct CoreJavascript<'a> {
801+
os_name: &'a str,
802+
protocol_scheme: &'a str,
803+
}
804+
785805
let bundle_script = if with_global_tauri {
786806
include_str!("../scripts/bundle.global.js")
787807
} else {
@@ -813,7 +833,16 @@ impl<R: Runtime> WindowManager<R> {
813833
"window['_' + window.__TAURI__.transformCallback(cb) ]".into()
814834
)
815835
),
816-
core_script: include_str!("../scripts/core.js"),
836+
core_script: &CoreJavascript {
837+
os_name: std::env::consts::OS,
838+
protocol_scheme: if self.inner.config.tauri.security.dangerous_use_http_scheme {
839+
"http"
840+
} else {
841+
"https"
842+
},
843+
}
844+
.render_default(&Default::default())?
845+
.into_string(),
817846
event_initialization_script: &self.event_initialization_script(),
818847
plugin_initialization_script,
819848
freeze_prototype,

core/tauri/src/pattern.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,10 @@ pub(crate) struct PatternJavascript {
108108
}
109109

110110
#[allow(dead_code)]
111-
pub(crate) fn format_real_schema(schema: &str) -> String {
111+
pub(crate) fn format_real_schema(schema: &str, _http: bool) -> String {
112112
if cfg!(windows) {
113-
format!("https://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
113+
let http = if _http { "http" } else { "https" };
114+
format!("{http}://{schema}.{ISOLATION_IFRAME_SRC_DOMAIN}")
114115
} else {
115116
format!("{schema}://{ISOLATION_IFRAME_SRC_DOMAIN}")
116117
}

0 commit comments

Comments
 (0)