Skip to main content

Mountain/Track/Effect/CreateEffectForRequest/
NativeHost.rs

1use serde_json::{Value, json};
2use tauri::Runtime;
3
4use crate::{
5	Track::Effect::{CreateEffectForRequest::Utilities::Params::string_at, MappedEffectType::MappedEffect},
6	dev_log,
7};
8
9pub fn CreateEffect<R:Runtime>(MethodName:&str, Parameters:Value) -> Option<Result<MappedEffect, String>> {
10	match MethodName {
11		"NativeHost.OpenExternal" => {
12			crate::effect!(_run_time, {
13				let uri = string_at(&Parameters, 0);
14				let lower = uri.to_ascii_lowercase();
15				const BlockedSchemes:&[&str] = &["javascript:", "data:", "vbscript:", "file:"];
16				for scheme in BlockedSchemes {
17					if lower.starts_with(scheme) {
18						dev_log!("ipc", "warn: [NativeHost.OpenExternal] rejected scheme '{}': {}", scheme, uri);
19						return Err(format!("NativeHost.OpenExternal: scheme '{}' is not allowed", scheme));
20					}
21				}
22				if uri.is_empty() {
23					return Err("NativeHost.OpenExternal: empty URI".to_string());
24				}
25				let uri_owned = uri.clone();
26				let result = tokio::task::spawn_blocking(move || open::that_detached(uri_owned))
27					.await
28					.map_err(|e| format!("NativeHost.OpenExternal join error: {}", e))?;
29				match result {
30					Ok(()) => {
31						dev_log!("ipc", "[NativeHost.OpenExternal] opened {}", uri);
32						Ok(json!(true))
33					},
34					Err(e) => {
35						dev_log!("ipc", "warn: [NativeHost.OpenExternal] failed uri={} error={}", uri, e);
36						Err(e.to_string())
37					},
38				}
39			})
40		},
41
42		_ => None,
43	}
44}