Skip to main content

origin_tauri/
opener.rs

1use async_trait::async_trait;
2use origin_domain::{AppError, Result};
3use origin_platform::Opener;
4use tauri::{AppHandle, Runtime};
5use tauri_plugin_opener::OpenerExt;
6
7/// Opens URLs in the user's default browser.
8///
9/// Deliberately limited to URLs: this is not a general shell escape, and a product
10/// that needs to run local programs must define its own contract and capability
11/// (ADR-0007).
12#[derive(Debug, Clone)]
13pub struct TauriOpener<R: Runtime> {
14    app: AppHandle<R>,
15}
16
17impl<R: Runtime> TauriOpener<R> {
18    pub fn new(app: AppHandle<R>) -> Self {
19        Self { app }
20    }
21}
22
23#[async_trait]
24impl<R: Runtime> Opener for TauriOpener<R> {
25    async fn open_url(&self, url: &str) -> Result<()> {
26        // Refuse anything that is not http(s) before it reaches the OS: `file://`
27        // and custom schemes are how "open a link" turns into "launch a program".
28        if !(url.starts_with("https://") || url.starts_with("http://")) {
29            return Err(AppError::validation(format!(
30                "refusing to open {url:?}: only http and https URLs are allowed"
31            )));
32        }
33
34        self.app
35            .opener()
36            .open_url(url, None::<&str>)
37            .map_err(|error| AppError::internal(format!("cannot open url: {error}")))
38    }
39}