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
61		let mut last_error = String::new();
62
63		for handler in handlers.iter() {
64			let result = Command::new(handler).arg(url_str).output();
65
66			match result {
67				Ok(output) if output.status.success() => {
68					dev_log!("lifecycle", "opened with {}", handler);
69
70					break;
71				},
72
73				Err(e) => {
74					last_error = e.to_string();
75
76					continue;
77				},
78
79				_ => continue,
80			}
81		}
82
83		if !last_error.is_empty() {
84			return Err(format!("Failed to open URL with any handler: {}", last_error));
85		}
86	}
87
88	dev_log!("lifecycle", "opened URL: {}", url_str);
89
90	Ok(Value::Bool(true))
91}