Skip to content

Commit

Permalink
feat(core): Allow http origin on Windows, fixes: #3007 (#7645)
Browse files Browse the repository at this point in the history
Co-authored-by: Lucas Nogueira <[email protected]>
Co-authored-by: Lucas Nogueira <[email protected]>
  • Loading branch information
3 people authored Sep 26, 2023
1 parent e8ff6b1 commit 9aa34ad
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 25 deletions.
8 changes: 8 additions & 0 deletions .changes/windows-http-scheme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'tauri': 'patch:enhance'
'tauri-runtime': 'patch:enhance'
'tauri-runtime-wry': 'patch:enhance'
'tauri-utils': 'patch:enhance'
---

Add setting to switch to `http://<scheme>.localhost/` for custom protocols on Windows.
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 @@ -2740,6 +2742,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 @@ -3196,6 +3196,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 @@ -1326,6 +1326,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 @@ -3736,6 +3741,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 @@ -3746,7 +3752,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 @@ -4013,6 +4020,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
10 changes: 5 additions & 5 deletions core/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions core/tauri/scripts/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
})
}

const osName = __TEMPLATE_os_name__
const protocolScheme = __TEMPLATE_protocol_scheme__

window.__TAURI__.convertFileSrc = function convertFileSrc(filePath, protocol = 'asset') {
const path = encodeURIComponent(filePath)
return osName === 'windows'
? `${protocolScheme}://${protocol}.localhost/${path}`
: `${protocol}://localhost/${path}`
}

window.__TAURI__.transformCallback = function transformCallback(
callback,
once
Expand Down
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
45 changes: 37 additions & 8 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 Expand Up @@ -782,6 +795,13 @@ impl<R: Runtime> WindowManager<R> {
hotkeys: &'a str,
}

#[derive(Template)]
#[default_template("../scripts/core.js")]
struct CoreJavascript<'a> {
os_name: &'a str,
protocol_scheme: &'a str,
}

let bundle_script = if with_global_tauri {
include_str!("../scripts/bundle.global.js")
} else {
Expand Down Expand Up @@ -813,7 +833,16 @@ impl<R: Runtime> WindowManager<R> {
"window['_' + window.__TAURI__.transformCallback(cb) ]".into()
)
),
core_script: include_str!("../scripts/core.js"),
core_script: &CoreJavascript {
os_name: std::env::consts::OS,
protocol_scheme: if self.inner.config.tauri.security.dangerous_use_http_scheme {
"http"
} else {
"https"
},
}
.render_default(&Default::default())?
.into_string(),
event_initialization_script: &self.event_initialization_script(),
plugin_initialization_script,
freeze_prototype,
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
8 changes: 4 additions & 4 deletions tooling/api/src/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ declare global {
ipc: {
postMessage: (args: string) => void
}
__TAURI__: {
convertFileSrc: (src: string, protocol: string) => string
}
}
}

Expand Down Expand Up @@ -127,10 +130,7 @@ async function invoke<T>(cmd: string, args: InvokeArgs = {}): Promise<T> {
* @since 1.0.0
*/
function convertFileSrc(filePath: string, protocol = 'asset'): string {
const path = encodeURIComponent(filePath)
return navigator.userAgent.includes('Windows')
? `https://${protocol}.localhost/${path}`
: `${protocol}://localhost/${path}`
return window.__TAURI__.convertFileSrc(filePath, protocol)
}

export type { InvokeArgs }
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 @@ -2740,6 +2742,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

0 comments on commit 9aa34ad

Please sign in to comment.