diff --git a/src-tauri/src/extension/web/mod.rs b/src-tauri/src/extension/web/mod.rs index 14426a1..a978519 100644 --- a/src-tauri/src/extension/web/mod.rs +++ b/src-tauri/src/extension/web/mod.rs @@ -33,6 +33,43 @@ pub struct WebFetchResponse { pub url: String, } +#[tauri::command] +pub async fn extension_web_open( + url: String, + public_key: String, + name: String, + state: State<'_, AppState>, +) -> Result<(), ExtensionError> { + // Get extension to validate it exists + let _extension = state + .extension_manager + .get_extension_by_public_key_and_name(&public_key, &name)? + .ok_or_else(|| ExtensionError::NotFound { + public_key: public_key.clone(), + name: name.clone(), + })?; + + // Validate URL format + let parsed_url = url::Url::parse(&url).map_err(|e| ExtensionError::WebError { + reason: format!("Invalid URL: {}", e), + })?; + + // Only allow http and https URLs + let scheme = parsed_url.scheme(); + if scheme != "http" && scheme != "https" { + return Err(ExtensionError::WebError { + reason: format!("Unsupported URL scheme: {}. Only http and https are allowed.", scheme), + }); + } + + // Open URL in default browser using tauri-plugin-opener + tauri_plugin_opener::open_url(&url, None::<&str>).map_err(|e| ExtensionError::WebError { + reason: format!("Failed to open URL in browser: {}", e), + })?; + + Ok(()) +} + #[tauri::command] pub async fn extension_web_fetch( url: String, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 031d8f0..6002597 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -79,6 +79,7 @@ pub fn run() { extension::database::extension_sql_execute, extension::database::extension_sql_select, extension::web::extension_web_fetch, + extension::web::extension_web_open, extension::get_all_dev_extensions, extension::get_all_extensions, extension::get_extension_info, diff --git a/src/composables/handlers/web.ts b/src/composables/handlers/web.ts index 61f80ed..e6d9ea8 100644 --- a/src/composables/handlers/web.ts +++ b/src/composables/handlers/web.ts @@ -16,6 +16,10 @@ export async function handleWebMethodAsync( return await handleWebFetchAsync(params, extension) } + if (method === 'haextension.web.open') { + return await handleWebOpenAsync(params, extension) + } + throw new Error(`Unknown web method: ${method}`) } @@ -65,3 +69,28 @@ async function handleWebFetchAsync( throw new Error('Web request failed with unknown error') } } + +async function handleWebOpenAsync( + params: Record, + extension: IHaexHubExtension, +) { + const url = params.url as string + + if (!url) { + throw new Error('URL is required') + } + + try { + // Call Rust backend to open URL in default browser + await invoke('extension_web_open', { + url, + publicKey: extension.publicKey, + name: extension.name, + }) + } catch (error) { + if (error instanceof Error) { + throw new Error(`Failed to open URL: ${error.message}`) + } + throw new Error('Failed to open URL with unknown error') + } +}