From c250df685b451a7f05c5492a91b8809b27c03ada Mon Sep 17 00:00:00 2001 From: Amod Malviya Date: Sun, 6 Nov 2022 23:24:54 +0530 Subject: [PATCH 1/2] android: address failure on termux in absence of vm context --- src/android.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/android.rs b/src/android.rs index 767e7dd..03ae57a 100644 --- a/src/android.rs +++ b/src/android.rs @@ -1,6 +1,6 @@ use crate::{Browser, BrowserOptions, Error, ErrorKind, Result}; use jni::objects::JValue; -pub use std::os::unix::process::ExitStatusExt; +use std::process::{Command, Stdio}; /// Deal with opening of browsers on Android. Only [Browser::Default] is supported, and /// in options, only [BrowserOptions::dry_run] is honoured. @@ -17,7 +17,7 @@ pub fn open_browser_internal(browser: Browser, url: &str, options: &BrowserOptio /// Open the default browser #[inline] -pub fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> { +fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> { // always return true for a dry run if options.dry_run { return Ok(()); @@ -25,9 +25,20 @@ pub fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> { // Create a VM for executing Java calls let ctx = ndk_context::android_context(); - let vm = unsafe { - jni::JavaVM::from_raw(ctx.vm() as _).expect("Expected to find JVM via ndk_context crate") + let vm = match unsafe { jni::JavaVM::from_raw(ctx.vm() as _) } { + Ok(x) => x, + Err(_) => { + // if we didn't get the vm instance, maybe we're running + // inside a termux, so try with that + return try_for_termux(url, options).map_err(|_| -> Error { + Error::new( + ErrorKind::NotFound, + "Expected to find JVM via ndk_context crate", + ) + }); + } }; + let activity = unsafe { jni::objects::JObject::from_raw(ctx.context() as _) }; let env = vm.attach_current_thread().map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to attach current thread") @@ -82,3 +93,36 @@ pub fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> { Ok(()) } + +/// Attemps to open a browser assuming a termux environment +/// +/// See [issue #53](https://github.com/amodm/webbrowser-rs/issues/53) +#[inline] +fn try_for_termux(url: &str, options: &BrowserOptions) -> Result<()> { + use std::env; + if env::var("TERMUX_VERSION").is_ok() { + // return true on dry-run given that termux-open command is guaranteed to be present + if options.dry_run { + return Ok(()); + } + let mut cmd = Command::new("termux-open"); + cmd.arg(url); + if options.suppress_output { + cmd.stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + } + cmd.status().and_then(|status| { + if status.success() { + Ok(()) + } else { + Err(Error::new( + ErrorKind::Other, + "command present but exited unsuccessfully", + )) + } + }) + } else { + Err(Error::new(ErrorKind::Other, "Not a termux environment")) + } +} From 348dc64caa2390e8df03155a84aa406f44f463d3 Mon Sep 17 00:00:00 2001 From: Amod Malviya Date: Sun, 6 Nov 2022 23:46:12 +0530 Subject: [PATCH 2/2] check for termux before invoking android context --- src/android.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/android.rs b/src/android.rs index 03ae57a..d001502 100644 --- a/src/android.rs +++ b/src/android.rs @@ -23,21 +23,20 @@ fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> { return Ok(()); } + // first we try to see if we're in a termux env, because if we are, then + // the android context may not have been initialized, and it'll panic + if try_for_termux(url, options).is_ok() { + return Ok(()); + } + // Create a VM for executing Java calls let ctx = ndk_context::android_context(); - let vm = match unsafe { jni::JavaVM::from_raw(ctx.vm() as _) } { - Ok(x) => x, - Err(_) => { - // if we didn't get the vm instance, maybe we're running - // inside a termux, so try with that - return try_for_termux(url, options).map_err(|_| -> Error { - Error::new( - ErrorKind::NotFound, - "Expected to find JVM via ndk_context crate", - ) - }); - } - }; + let vm = unsafe { jni::JavaVM::from_raw(ctx.vm() as _) }.map_err(|_| -> Error { + Error::new( + ErrorKind::NotFound, + "Expected to find JVM via ndk_context crate", + ) + })?; let activity = unsafe { jni::objects::JObject::from_raw(ctx.context() as _) }; let env = vm.attach_current_thread().map_err(|_| -> Error {