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 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}