Skip to main content

Mountain/Track/Effect/CreateEffectForRequest/
NativeHost.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3use std::{future::Future, pin::Pin, sync::Arc};
4
5use serde_json::{Value, json};
6use tauri::Runtime;
7
8use crate::{RunTime::ApplicationRunTime::ApplicationRunTime, Track::Effect::MappedEffectType::MappedEffect, dev_log};
9
10pub fn CreateEffect<R:Runtime>(MethodName:&str, Parameters:Value) -> Option<Result<MappedEffect, String>> {
11	match MethodName {
12		"NativeHost.OpenExternal" => {
13			let effect =
14				move |_run_time:Arc<ApplicationRunTime>| -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
15					Box::pin(async move {
16						let uri = Parameters
17							.get(0)
18							.and_then(Value::as_str)
19							.unwrap_or("")
20							.to_string();
21						let lower = uri.to_ascii_lowercase();
22						const BlockedSchemes:&[&str] =
23							&["javascript:", "data:", "vbscript:", "file:"];
24						for scheme in BlockedSchemes {
25							if lower.starts_with(scheme) {
26								dev_log!(
27									"ipc",
28									"warn: [NativeHost.OpenExternal] rejected scheme '{}': {}",
29									scheme,
30									uri
31								);
32								return Err(format!(
33									"NativeHost.OpenExternal: scheme '{}' is not allowed",
34									scheme
35								));
36							}
37						}
38						if uri.is_empty() {
39							return Err("NativeHost.OpenExternal: empty URI".to_string());
40						}
41						let uri_owned = uri.clone();
42						let result =
43							tokio::task::spawn_blocking(move || open::that_detached(uri_owned))
44								.await
45								.map_err(|e| format!("NativeHost.OpenExternal join error: {}", e))?;
46						match result {
47							Ok(()) => {
48								dev_log!("ipc", "[NativeHost.OpenExternal] opened {}", uri);
49								Ok(json!(true))
50							},
51							Err(e) => {
52								dev_log!(
53									"ipc",
54									"warn: [NativeHost.OpenExternal] failed uri={} error={}",
55									uri,
56									e
57								);
58								Err(e.to_string())
59							},
60						}
61					})
62				};
63			Some(Ok(Box::new(effect)))
64		},
65
66		_ => None,
67	}
68}