Skip to content

Commit

Permalink
fix(android): allow static handlers to be replaced (#1414)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog authored Nov 8, 2024
1 parent 9a2a2d4 commit 0c192f4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changes/fix-android-statics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": patch
---

Fix Android static handlers not being replaced when the application UI is relaunched while still running in the foreground.
17 changes: 9 additions & 8 deletions src/android/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fn handle_request(
request: JObject,
is_document_start_script_enabled: jboolean,
) -> JniResult<jobject> {
if let Some(handler) = REQUEST_HANDLER.get() {
if let Some(handler) = REQUEST_HANDLER.borrow().as_ref() {
#[cfg(feature = "tracing")]
let span =
tracing::info_span!(parent: None, "wry::custom_protocol::handle", uri = tracing::field::Empty).entered();
Expand Down Expand Up @@ -287,7 +287,8 @@ pub unsafe fn shouldOverride(mut env: JNIEnv, _: JClass, url: JString) -> jboole
Ok(url) => {
let url = url.to_string_lossy().to_string();
URL_LOADING_OVERRIDE
.get()
.borrow()
.as_ref()
// We negate the result of the function because the logic for the android
// client is different from how the navigation_handler is defined.
//
Expand Down Expand Up @@ -332,7 +333,7 @@ pub unsafe fn ipc(mut env: JNIEnv, _: JClass, url: JString, body: JString) {

let url = url.to_string_lossy().to_string();
let body = body.to_string_lossy().to_string();
if let Some(ipc) = IPC.get() {
if let Some(ipc) = IPC.borrow().as_ref() {
(ipc.handler)(Request::builder().uri(url).body(body).unwrap())
}
}
Expand All @@ -348,7 +349,7 @@ pub unsafe fn handleReceivedTitle(mut env: JNIEnv, _: JClass, _webview: JObject,
match env.get_string(&title) {
Ok(title) => {
let title = title.to_string_lossy().to_string();
if let Some(title_handler) = TITLE_CHANGE_HANDLER.get() {
if let Some(title_handler) = TITLE_CHANGE_HANDLER.borrow().as_ref() {
(title_handler.handler)(title)
}
}
Expand All @@ -361,12 +362,12 @@ pub unsafe fn handleReceivedTitle(mut env: JNIEnv, _: JClass, _webview: JObject,

#[allow(non_snake_case)]
pub unsafe fn withAssetLoader(_: JNIEnv, _: JClass) -> jboolean {
(*WITH_ASSET_LOADER.get().unwrap_or(&false)).into()
(*WITH_ASSET_LOADER.borrow().as_ref().unwrap_or(&false)).into()
}

#[allow(non_snake_case)]
pub unsafe fn assetLoaderDomain(env: JNIEnv, _: JClass) -> jstring {
if let Some(domain) = ASSET_LOADER_DOMAIN.get() {
if let Some(domain) = ASSET_LOADER_DOMAIN.borrow().as_ref() {
env.new_string(domain).unwrap().as_raw()
} else {
env.new_string("wry.assets").unwrap().as_raw()
Expand All @@ -378,7 +379,7 @@ pub unsafe fn onPageLoading(mut env: JNIEnv, _: JClass, url: JString) {
match env.get_string(&url) {
Ok(url) => {
let url = url.to_string_lossy().to_string();
if let Some(on_load) = ON_LOAD_HANDLER.get() {
if let Some(on_load) = ON_LOAD_HANDLER.borrow().as_ref() {
(on_load.handler)(PageLoadEvent::Started, url)
}
}
Expand All @@ -394,7 +395,7 @@ pub unsafe fn onPageLoaded(mut env: JNIEnv, _: JClass, url: JString) {
match env.get_string(&url) {
Ok(url) => {
let url = url.to_string_lossy().to_string();
if let Some(on_load) = ON_LOAD_HANDLER.get() {
if let Some(on_load) = ON_LOAD_HANDLER.borrow().as_ref() {
(on_load.handler)(PageLoadEvent::Finished, url)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/android/main_pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use jni::{
JNIEnv,
};
use once_cell::sync::Lazy;
use std::{os::unix::prelude::*, str::FromStr, sync::atomic::Ordering};
use std::os::unix::prelude::*;

use super::{find_class, EvalCallback, EVAL_CALLBACKS, EVAL_ID_GENERATOR, PACKAGE};

Expand Down
39 changes: 26 additions & 13 deletions src/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use raw_window_handle::HasWindowHandle;
use sha2::{Digest, Sha256};
use std::{
borrow::Cow,
cell::RefCell,
collections::HashMap,
os::fd::{AsFd as _, AsRawFd as _},
sync::{mpsc::channel, Mutex},
Expand All @@ -42,9 +43,22 @@ pub struct Context<'a, 'b> {
pub webview: &'a JObject<'b>,
}

pub(crate) struct StaticCell<T>(RefCell<T>);

unsafe impl<T> Send for StaticCell<T> {}
unsafe impl<T> Sync for StaticCell<T> {}

impl<T> std::ops::Deref for StaticCell<T> {
type Target = RefCell<T>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

macro_rules! define_static_handlers {
($($var:ident = $type_name:ident { $($fields:ident:$types:ty),+ $(,)? });+ $(;)?) => {
$(pub static $var: once_cell::sync::OnceCell<$type_name> = once_cell::sync::OnceCell::new();
$(pub static $var: StaticCell<Option<$type_name>> = StaticCell(RefCell::new(None));
pub struct $type_name {
$($fields: $types,)*
}
Expand All @@ -68,16 +82,15 @@ define_static_handlers! {
ON_LOAD_HANDLER = UnsafeOnPageLoadHandler { handler: Box<dyn Fn(PageLoadEvent, String)> };
}

pub static WITH_ASSET_LOADER: OnceCell<bool> = OnceCell::new();
pub static ASSET_LOADER_DOMAIN: OnceCell<String> = OnceCell::new();
pub static WITH_ASSET_LOADER: StaticCell<Option<bool>> = StaticCell(RefCell::new(None));
pub static ASSET_LOADER_DOMAIN: StaticCell<Option<String>> = StaticCell(RefCell::new(None));

pub(crate) static PACKAGE: OnceCell<String> = OnceCell::new();

type EvalCallback = Box<dyn Fn(String) + Send + 'static>;

pub static EVAL_ID_GENERATOR: Counter = Counter::new();
pub static EVAL_CALLBACKS: once_cell::sync::OnceCell<Mutex<HashMap<i32, EvalCallback>>> =
once_cell::sync::OnceCell::new();
pub static EVAL_CALLBACKS: OnceCell<Mutex<HashMap<i32, EvalCallback>>> = OnceCell::new();

/// Sets up the necessary logic for wry to be able to create the webviews later.
///
Expand Down Expand Up @@ -205,12 +218,12 @@ impl InnerWebView {
initialization_scripts: initialization_scripts.clone(),
}));

WITH_ASSET_LOADER.get_or_init(move || with_asset_loader);
WITH_ASSET_LOADER.replace(Some(with_asset_loader));
if let Some(domain) = asset_loader_domain {
ASSET_LOADER_DOMAIN.get_or_init(move || domain);
ASSET_LOADER_DOMAIN.replace(Some(domain));
}

REQUEST_HANDLER.get_or_init(move || {
REQUEST_HANDLER.replace(Some(
UnsafeRequestHandler::new(Box::new(
move |webview_id: &str, mut request, is_document_start_script_enabled| {
let uri = request.uri().to_string();
Expand Down Expand Up @@ -292,22 +305,22 @@ impl InnerWebView {
None
},
))
});
));

if let Some(i) = ipc_handler {
IPC.get_or_init(move || UnsafeIpc::new(Box::new(i)));
IPC.replace(Some(UnsafeIpc::new(Box::new(i))));
}

if let Some(i) = attributes.document_title_changed_handler {
TITLE_CHANGE_HANDLER.get_or_init(move || UnsafeTitleHandler::new(i));
TITLE_CHANGE_HANDLER.replace(Some(UnsafeTitleHandler::new(i)));
}

if let Some(i) = attributes.navigation_handler {
URL_LOADING_OVERRIDE.get_or_init(move || UnsafeUrlLoadingOverride::new(i));
URL_LOADING_OVERRIDE.replace(Some(UnsafeUrlLoadingOverride::new(i)));
}

if let Some(h) = attributes.on_page_load_handler {
ON_LOAD_HANDLER.get_or_init(move || UnsafeOnPageLoadHandler::new(h));
ON_LOAD_HANDLER.replace(Some(UnsafeOnPageLoadHandler::new(h)));
}

Ok(Self { id })
Expand Down

0 comments on commit 0c192f4

Please sign in to comment.