Skip to main content

Mountain/IPC/WindServiceHandlers/NativeHost/
OpenExternal.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Wire method: `native:openExternal`, `nativeHost:openExternal`.
4//! Opens an http/https URL in the platform default browser.
5
6use std::sync::Arc;
7
8use serde_json::Value;
9
10use crate::{RunTime::ApplicationRunTime::ApplicationRunTime, dev_log};
11
12pub async fn OpenExternal(RunTime:Arc<ApplicationRunTime>, Arguments:Vec<Value>) -> Result<Value, String> {
13	let url_str = Arguments
14		.get(0)
15		.ok_or("Missing URL".to_string())?
16		.as_str()
17		.ok_or("URL must be a string".to_string())?;
18
19	dev_log!("lifecycle", "openExternal: {}", url_str);
20
21	if !url_str.starts_with("http://") && !url_str.starts_with("https://") {
22		return Err(format!("Invalid URL format. Must start with http:// or https://: {}", url_str));
23	}
24
25	#[cfg(target_os = "macos")]
26	{
27		use std::process::Command;
28
29		let result = Command::new("open")
30			.arg(url_str)
31			.output()
32			.map_err(|Error| format!("Failed to execute open command: {}", Error))?;
33
34		if !result.status.success() {
35			return Err(format!("Failed to open URL: {}", String::from_utf8_lossy(&result.stderr)));
36		}
37	}
38
39	#[cfg(target_os = "windows")]
40	{
41		use std::process::Command;
42
43		let result = Command::new("cmd")
44			.arg("/c")
45			.arg("start")
46			.arg(url_str)
47			.output()
48			.map_err(|Error| format!("Failed to execute start command: {}", Error))?;
49
50		if !result.status.success() {
51			return Err(format!("Failed to open URL: {}", String::from_utf8_lossy(&result.stderr)));
52		}
53	}
54
55	#[cfg(target_os = "linux")]
56	{
57		use std::process::Command;
58
59		let handlers = ["xdg-open", "gnome-open", "kde-open", "x-www-browser"];
60		let mut last_error = String::new();
61
62		for handler in handlers.iter() {
63			let result = Command::new(handler).arg(url_str).output();
64
65			match result {
66				Ok(output) if output.status.success() => {
67					dev_log!("lifecycle", "opened with {}", handler);
68					break;
69				},
70				Err(e) => {
71					last_error = e.to_string();
72					continue;
73				},
74				_ => continue,
75			}
76		}
77
78		if !last_error.is_empty() {
79			return Err(format!("Failed to open URL with any handler: {}", last_error));
80		}
81	}
82
83	dev_log!("lifecycle", "opened URL: {}", url_str);
84	Ok(Value::Bool(true))
85}