Skip to content

Commit

Permalink
fix: wrap Box<dyn FnMut(..)> with RefCell
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Tsai committed Aug 29, 2024
1 parent 880e798 commit 23444cb
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 53 deletions.
18 changes: 5 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ use self::webview2::*;
#[cfg(target_os = "windows")]
use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Controller;

use std::{borrow::Cow, path::PathBuf, rc::Rc};
use std::{borrow::Cow, cell::RefCell, path::PathBuf, rc::Rc};

use http::{Request, Response};

Expand Down Expand Up @@ -414,7 +414,8 @@ pub struct WebViewAttributes {
/// second is a mutable `PathBuf` reference that (possibly) represents where the file will be downloaded to. The latter
/// parameter can be used to set the download location by assigning a new path to it, the assigned path _must_ be
/// absolute. The closure returns a `bool` to allow or deny the download.
pub download_started_handler: Option<Box<dyn FnMut(String, &mut PathBuf) -> bool>>,
pub download_started_handler:
Option<RefCell<Box<dyn FnMut(String, &mut PathBuf) -> bool + 'static>>>,

/// A download completion handler to manage downloads that have finished.
///
Expand Down Expand Up @@ -912,7 +913,7 @@ impl<'a> WebViewBuilder<'a> {
mut self,
started_handler: impl FnMut(String, &mut PathBuf) -> bool + 'static,
) -> Self {
self.attrs.download_started_handler = Some(Box::new(started_handler));
self.attrs.download_started_handler = Some(RefCell::new(Box::new(started_handler)));
self
}

Expand Down Expand Up @@ -1058,20 +1059,11 @@ impl<'a> WebViewBuilder<'a> {
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
#[derive(Clone)]
#[derive(Clone, Default)]
pub(crate) struct PlatformSpecificWebViewAttributes {
data_store_identifier: Option<[u8; 16]>,
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
impl Default for PlatformSpecificWebViewAttributes {
fn default() -> Self {
Self {
data_store_identifier: None,
}
}
}

#[cfg(any(target_os = "macos", target_os = "ios",))]
pub trait WebViewBuilderExtDarwin {
/// Initialize the WebView with a custom data store identifier.
Expand Down
40 changes: 11 additions & 29 deletions src/wkwebview/class/wry_download_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use std::{path::PathBuf, ptr::null_mut, rc::Rc};
use std::{cell::RefCell, path::PathBuf, rc::Rc};

use objc2::{
declare_class, msg_send_id, mutability::MainThreadOnly, rc::Retained, runtime::NSObject,
Expand All @@ -16,8 +16,8 @@ use objc2_web_kit::{WKDownload, WKDownloadDelegate};
use crate::wkwebview::download::{download_did_fail, download_did_finish, download_policy};

pub struct WryDownloadDelegateIvars {
pub started: *mut Box<dyn FnMut(String, &mut PathBuf) -> bool>,
pub completed: *mut Rc<dyn Fn(String, Option<PathBuf>, bool)>,
pub started: Option<RefCell<Box<dyn FnMut(String, &mut PathBuf) -> bool + 'static>>>,
pub completed: Option<Rc<dyn Fn(String, Option<PathBuf>, bool) + 'static>>,
}

declare_class!(
Expand Down Expand Up @@ -66,37 +66,19 @@ declare_class!(

impl WryDownloadDelegate {
pub fn new(
download_started_handler: Option<Box<dyn FnMut(String, &mut PathBuf) -> bool>>,
download_completed_handler: Option<Rc<dyn Fn(String, Option<PathBuf>, bool)>>,
download_started_handler: Option<
RefCell<Box<dyn FnMut(String, &mut PathBuf) -> bool + 'static>>,
>,
download_completed_handler: Option<Rc<dyn Fn(String, Option<PathBuf>, bool) + 'static>>,
mtm: MainThreadMarker,
) -> Retained<Self> {
let started = match download_started_handler {
Some(handler) => Box::into_raw(Box::new(handler)),
None => null_mut(),
};
let completed = match download_completed_handler {
Some(handler) => Box::into_raw(Box::new(handler)),
None => null_mut(),
};
let delegate = mtm
.alloc::<WryDownloadDelegate>()
.set_ivars(WryDownloadDelegateIvars { started, completed });
.set_ivars(WryDownloadDelegateIvars {
started: download_started_handler,
completed: download_completed_handler,
});

unsafe { msg_send_id![super(delegate), init] }
}
}

impl Drop for WryDownloadDelegate {
fn drop(&mut self) {
if !self.ivars().started.is_null() {
unsafe {
drop(Box::from_raw(self.ivars().started));
}
}
if !self.ivars().completed.is_null() {
unsafe {
drop(Box::from_raw(self.ivars().completed));
}
}
}
}
1 change: 1 addition & 0 deletions src/wkwebview/class/wry_navigation_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ declare_class!(
);

impl WryNavigationDelegate {
#[allow(clippy::too_many_arguments)]
pub fn new(
webview: Retained<WryWebView>,
pending_scripts: Arc<Mutex<Option<Vec<String>>>>,
Expand Down
2 changes: 1 addition & 1 deletion src/wkwebview/class/wry_web_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use objc2::{
declare_class,
mutability::MainThreadOnly,
rc::Retained,
runtime::{Bool, MessageReceiver, ProtocolObject},
runtime::{Bool, ProtocolObject},
ClassType, DeclaredClass,
};
use objc2_app_kit::{NSDraggingDestination, NSEvent};
Expand Down
18 changes: 8 additions & 10 deletions src/wkwebview/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ pub(crate) fn download_policy(
let url = request.URL().unwrap().absoluteString().unwrap();
let mut path = PathBuf::from(suggested_path.to_string());

let function = this.ivars().started;
if !function.is_null() {
match (*function)(url.to_string().to_string(), &mut path) {
let started_fn = &this.ivars().started;
if let Some(started_fn) = started_fn {
let mut started_fn = started_fn.borrow_mut();
match started_fn(url.to_string().to_string(), &mut path) {
true => {
let path = NSString::from_str(&path.display().to_string());
let ns_url = NSURL::fileURLWithPath_isDirectory(&path, false);
Expand All @@ -72,9 +73,8 @@ pub(crate) fn download_did_finish(this: &WryDownloadDelegate, download: &WKDownl
unsafe {
let original_request = download.originalRequest().unwrap();
let url = original_request.URL().unwrap().absoluteString().unwrap();
let function = this.ivars().completed;
if !function.is_null() {
(*function)(url.to_string(), None, true);
if let Some(completed_fn) = this.ivars().completed.clone() {
completed_fn(url.to_string(), None, true);
}
}
}
Expand All @@ -94,10 +94,8 @@ pub(crate) fn download_did_fail(

let original_request = download.originalRequest().unwrap();
let url = original_request.URL().unwrap().absoluteString().unwrap();

let function = this.ivars().completed;
if !function.is_null() {
(*function)(url.to_string(), None, false);
if let Some(completed_fn) = this.ivars().completed.clone() {
completed_fn(url.to_string(), None, false);
}
}
}

0 comments on commit 23444cb

Please sign in to comment.