diff --git a/src/lib.rs b/src/lib.rs index 77a54ccd8..876a1ef92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -792,6 +792,13 @@ pub struct WebViewAttributes<'a> { /// Whether JavaScript should be disabled. pub javascript_disabled: bool, + + /// Set a handler closure to respond to web content process termination. + /// + /// ## Platform-specific: + /// + /// - **Linux / Windows / Android**: Unsupported. + pub on_web_content_process_terminate_handler: Option>, } impl Default for WebViewAttributes<'_> { @@ -834,6 +841,7 @@ impl Default for WebViewAttributes<'_> { }), background_throttling: None, javascript_disabled: false, + on_web_content_process_terminate_handler: None, } } } @@ -1405,6 +1413,15 @@ impl<'a> WebViewBuilder<'a> { self } + /// Set a handler to respond to web content process termination. + pub fn with_on_web_content_process_terminate_handler( + mut self, + handler: impl Fn() + 'static, + ) -> Self { + self.attrs.on_web_content_process_terminate_handler = Some(Box::new(handler)); + self + } + /// Consume the builder and create the [`WebView`] from a type that implements [`HasWindowHandle`]. /// /// # Platform-specific: diff --git a/src/wkwebview/class/wry_navigation_delegate.rs b/src/wkwebview/class/wry_navigation_delegate.rs index 5919949b6..6fb870f5e 100644 --- a/src/wkwebview/class/wry_navigation_delegate.rs +++ b/src/wkwebview/class/wry_navigation_delegate.rs @@ -22,6 +22,7 @@ use crate::{ download::{navigation_download_action, navigation_download_response}, navigation::{ did_commit_navigation, did_finish_navigation, navigation_policy, navigation_policy_response, + web_content_process_did_terminate, }, }, PageLoadEvent, WryWebView, @@ -35,6 +36,7 @@ pub struct WryNavigationDelegateIvars { pub navigation_policy_function: Box bool>, pub download_delegate: Option>, pub on_page_load_handler: Option>, + pub on_web_content_process_terminate_handler: Option>, } define_class!( @@ -96,6 +98,11 @@ define_class!( ) { navigation_download_response(self, webview, response, download); } + + #[unsafe(method(webViewWebContentProcessDidTerminate:))] + fn web_content_process_did_terminate(&self, webview: &WKWebView) { + web_content_process_did_terminate(self, webview); + } } ); @@ -108,6 +115,7 @@ impl WryNavigationDelegate { navigation_handler: Option bool>>, download_delegate: Option>, on_page_load_handler: Option>, + on_web_content_process_terminate_handler: Option>, mtm: MainThreadMarker, ) -> Retained { let navigation_policy_function = Box::new(move |url: String| -> bool { @@ -125,6 +133,15 @@ impl WryNavigationDelegate { None }; + let on_web_content_process_terminate_handler = if let Some(handler) = on_web_content_process_terminate_handler { + let custom_handler = Box::new(move || { + handler(); + }) as Box; + Some(custom_handler) + } else { + None + }; + let delegate = mtm .alloc::() .set_ivars(WryNavigationDelegateIvars { @@ -133,6 +150,7 @@ impl WryNavigationDelegate { has_download_handler, download_delegate, on_page_load_handler, + on_web_content_process_terminate_handler, }); unsafe { msg_send![super(delegate), init] } diff --git a/src/wkwebview/mod.rs b/src/wkwebview/mod.rs index 0bbf6711a..0e60c1e85 100644 --- a/src/wkwebview/mod.rs +++ b/src/wkwebview/mod.rs @@ -542,6 +542,7 @@ impl InnerWebView { attributes.navigation_handler, download_delegate.clone(), attributes.on_page_load_handler, + attributes.on_web_content_process_terminate_handler, mtm, ); diff --git a/src/wkwebview/navigation.rs b/src/wkwebview/navigation.rs index 358353697..c1410dfae 100644 --- a/src/wkwebview/navigation.rs +++ b/src/wkwebview/navigation.rs @@ -102,3 +102,12 @@ pub(crate) fn navigation_policy_response( (*handler).call((WKNavigationResponsePolicy::Allow,)); } } + +pub(crate) fn web_content_process_did_terminate( + this: &WryNavigationDelegate, + _webview: &WKWebView, +) { + if let Some(on_web_content_process_terminate) = &this.ivars().on_web_content_process_terminate_handler { + on_web_content_process_terminate(); + } +}