From 0c8631bae14ab47c458241ca619d4a8e4325c740 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Wed, 12 Feb 2025 15:23:09 -0600 Subject: [PATCH 1/5] add android::init_with_refs function --- rustls-platform-verifier/src/android.rs | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index f50db6c..b5c98e7 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -103,6 +103,36 @@ pub fn init_external(runtime: &'static dyn Runtime) { GLOBAL.get_or_init(|| Global::External(runtime)); } +/// Initialize with references to the JVM, context, and class loader. +/// +/// This is useful when you're already interacting with `jni-rs` wrapped objects and want to use +/// global references to objects for efficiency. +/// +/// This function will never panic. +/// +/// # Examples +/// +/// ``` +/// pub fn android_init(raw_env: *mut c_void, raw_context: *mut c_void) -> Result<(), jni::errors::Error> { +/// let mut env = unsafe { jni::JNIEnv::from_raw(raw_env as *mut jni::sys::JNIEnv).unwrap() }; +/// let context = unsafe { JObject::from_raw(raw_context as jni::sys::jobject) }; +/// let loader = env.call_method(&context, "getClassLoader", "()Ljava/lang/ClassLoader;", &[])?; +/// +/// rustls_platform_verifier::android::init_with_refs( +/// env.get_java_vm()?, +/// env.new_global_ref(context)?, +/// env.new_global_ref(JObject::try_from(loader)?)?, +/// ); +/// } +/// ``` +pub fn init_with_refs(java_vm: JavaVM, context: GlobalRef, loader: GlobalRef) { + GLOBAL.get_or_init(|| Global::Internal { + java_vm, + context, + loader, + }); +} + /// Wrapper for JNI errors that will log and clear exceptions /// It should generally be preferred to `jni::errors::Error` #[derive(Debug)] From 1530f5eb16c87eb1b52768c8f655781d58ed493e Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Wed, 12 Feb 2025 15:26:38 -0600 Subject: [PATCH 2/5] rename android::{init_hosted => init_with_env} this is a soft deprecation, only noted as a rustdoc. --- rustls-platform-verifier/src/android.rs | 30 ++++++++++++----------- rustls-platform-verifier/src/tests/ffi.rs | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index b5c98e7..79086b6 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -68,33 +68,35 @@ fn global() -> &'static Global { .expect("Expect rustls-platform-verifier to be initialized") } -/// Initializes and stores the required context for the Android platform. -/// -/// This method will setup and store an environment locally. This is useful if -/// nothing else in your application needs access the Android runtime. +/// Initialize given a typical Android NDK `JNIEnv` and `jobject` context. /// -/// Initialization must be done before any verification is attempted. -pub fn init_hosted(env: &mut JNIEnv, context: JObject) -> Result<(), JNIError> { +/// This method will setup and store an environment locally. This is useful if nothing else in your +/// application needs access the Android runtime. +pub fn init_with_env(env: &mut JNIEnv, context: JObject) -> Result<(), JNIError> { GLOBAL.get_or_try_init(|| -> Result<_, JNIError> { let loader = env.call_method(&context, "getClassLoader", "()Ljava/lang/ClassLoader;", &[])?; - let global = Global::Internal { + + Ok(Global::Internal { java_vm: env.get_java_vm()?, context: env.new_global_ref(context)?, loader: env.new_global_ref(JObject::try_from(loader)?)?, - }; - - Ok(global) + }) })?; - Ok(()) } +/// *Deprecated*: This is the original method name for [`init_with_env`] and is functionally +/// identical. +pub fn init_hosted(env: &mut JNIEnv, context: JObject) -> Result<(), JNIError> { + init_with_env(env, context) +} + /// Initializes and stores the required context for the Android platform. /// -/// This method utilizes an existing Android runtime environment and set anything -/// else up on its own. This is useful if your application already interacts with -/// the runtime and has pre-existing handles. +/// This method utilizes an existing Android runtime environment and set anything else up on its +/// own. This is useful if your application already interacts with the runtime and has pre-existing +/// handles. /// /// This function will never panic, and is therefore safe to use at FFI boundaries. /// diff --git a/rustls-platform-verifier/src/tests/ffi.rs b/rustls-platform-verifier/src/tests/ffi.rs index 9030cc3..70ab573 100644 --- a/rustls-platform-verifier/src/tests/ffi.rs +++ b/rustls-platform-verifier/src/tests/ffi.rs @@ -46,7 +46,7 @@ mod android { .with_max_level(log::Level::Trace.to_level_filter()) .with_filter(log_filter), ); - crate::android::init_hosted(env, cx).unwrap(); + crate::android::init_with_env(env, cx).unwrap(); crate::tests::ensure_global_state(); std::panic::set_hook(Box::new(|info| { let msg = if let Some(msg) = info.payload().downcast_ref::<&'static str>() { From cab55feaea52cb8586ebf8f5ccb330aa7df09918 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Wed, 12 Feb 2025 15:27:18 -0600 Subject: [PATCH 3/5] rename android::{init_external => init_with_runtime} this is a soft deprecation, only noted as a rustdoc. --- rustls-platform-verifier/src/android.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index 79086b6..cdf46a3 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -92,19 +92,22 @@ pub fn init_hosted(env: &mut JNIEnv, context: JObject) -> Result<(), JNIError> { init_with_env(env, context) } -/// Initializes and stores the required context for the Android platform. +/// Initialize with a runtime that can dynamically serve references to +/// the JVM, context, and class loader. /// -/// This method utilizes an existing Android runtime environment and set anything else up on its -/// own. This is useful if your application already interacts with the runtime and has pre-existing -/// handles. +/// This is the most flexible option, and is useful for advanced use cases. /// -/// This function will never panic, and is therefore safe to use at FFI boundaries. -/// -/// Initialization must be done before any verification is attempted. -pub fn init_external(runtime: &'static dyn Runtime) { +/// This function will never panic. +pub fn init_with_runtime(runtime: &'static dyn Runtime) { GLOBAL.get_or_init(|| Global::External(runtime)); } +/// *Deprecated*: This is the original method name for [`init_with_runtime`] and is functionally +/// identical. +pub fn init_external(runtime: &'static dyn Runtime) { + init_with_runtime(runtime); +} + /// Initialize with references to the JVM, context, and class loader. /// /// This is useful when you're already interacting with `jni-rs` wrapped objects and want to use From e66f07587156e6062b367f83946bfb7adcd674b7 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Wed, 12 Feb 2025 15:28:25 -0600 Subject: [PATCH 4/5] add more detailed android module rustdocs --- rustls-platform-verifier/src/android.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index cdf46a3..695fe5f 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -1,4 +1,23 @@ -//! A small wrapper over interacting with the JNI in a type-safe way. +//! On Android, initialization must be done before any verification is attempted. +//! +//!
+//! Some manual setup is required, outside of cargo, to use this crate on Android. In order to use +//! Android’s certificate verifier, the crate needs to call into the JVM. A small Kotlin component +//! must be included in your app’s build to support `rustls-platform-verifier`. +//! +//! See the [crate's Android section][crate#android] for more details. +//!
+//! +//! # Examples +//! +//! ``` +//! // A typical entrypoint signature for obtaining the necessary pointers +//! pub fn android_init(raw_env: *mut c_void, raw_context: *mut c_void) -> Result<(), jni::errors::Error> { +//! let mut env = unsafe { JNIEnv::from_raw(raw_env as *mut jni::sys::JNIEnv).unwrap() }; +//! let context = unsafe { JObject::from_raw(raw_context as jni::sys::jobject) }; +//! rustls_platform_verifier::android::init_with_env(&mut env, context)?; +//! } +//! ``` use jni::errors::Error as JNIError; use jni::objects::{GlobalRef, JClass, JObject, JValue}; From c72146eb9b5be06e909cd12a383b195b8d908fcd Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Fri, 14 Feb 2025 13:29:22 -0600 Subject: [PATCH 5/5] android rustdoc typo and grammar fixes --- rustls-platform-verifier/src/android.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rustls-platform-verifier/src/android.rs b/rustls-platform-verifier/src/android.rs index 695fe5f..50db61e 100644 --- a/rustls-platform-verifier/src/android.rs +++ b/rustls-platform-verifier/src/android.rs @@ -1,9 +1,9 @@ //! On Android, initialization must be done before any verification is attempted. //! //!
-//! Some manual setup is required, outside of cargo, to use this crate on Android. In order to use +//! Some manual setup is required outside of cargo to use this crate on Android. In order to use //! Android’s certificate verifier, the crate needs to call into the JVM. A small Kotlin component -//! must be included in your app’s build to support `rustls-platform-verifier`. +//! must be included in your app’s build to support rustls-platform-verifier. //! //! See the [crate's Android section][crate#android] for more details. //!
@@ -87,10 +87,10 @@ fn global() -> &'static Global { .expect("Expect rustls-platform-verifier to be initialized") } -/// Initialize given a typical Android NDK `JNIEnv` and `jobject` context. +/// Initialize given a typical Android NDK [`JNIEnv`] and [`JObject`] context. /// /// This method will setup and store an environment locally. This is useful if nothing else in your -/// application needs access the Android runtime. +/// application needs to access the Android runtime. pub fn init_with_env(env: &mut JNIEnv, context: JObject) -> Result<(), JNIError> { GLOBAL.get_or_try_init(|| -> Result<_, JNIError> { let loader =