Mountain/Track/Effect/CreateEffectForRequest/
NativeHost.rs1use 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}