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
15				let lower = uri.to_ascii_lowercase();
16
17				const BlockedSchemes:&[&str] = &["javascript:", "data:", "vbscript:", "file:"];
18
19				for scheme in BlockedSchemes {
20					if lower.starts_with(scheme) {
21						dev_log!("ipc", "warn: [NativeHost.OpenExternal] rejected scheme '{}': {}", scheme, uri);
22
23						return Err(format!("NativeHost.OpenExternal: scheme '{}' is not allowed", scheme));
24					}
25				}
26
27				if uri.is_empty() {
28					return Err("NativeHost.OpenExternal: empty URI".to_string());
29				}
30
31				let uri_owned = uri.clone();
32
33				let result = tokio::task::spawn_blocking(move || open::that_detached(uri_owned))
34					.await
35					.map_err(|e| format!("NativeHost.OpenExternal join error: {}", e))?;
36
37				match result {
38					Ok(()) => {
39						dev_log!("ipc", "[NativeHost.OpenExternal] opened {}", uri);
40
41						Ok(json!(true))
42					},
43					Err(e) => {
44						dev_log!("ipc", "warn: [NativeHost.OpenExternal] failed uri={} error={}", uri, e);
45
46						Err(e.to_string())
47					},
48				}
49			})
50		},
51
52		_ => None,
53	}
54}