@@ -66,8 +66,8 @@ use tauri_utils::TitleBarStyle;
6666use tauri_utils:: { config:: WindowConfig , Theme } ;
6767use url:: Url ;
6868use wry:: {
69- DragDropEvent as WryDragDropEvent , ProxyConfig , ProxyEndpoint , WebContext , WebView ,
70- WebViewBuilder ,
69+ DragDropEvent as WryDragDropEvent , ProxyConfig , ProxyEndpoint , WebContext as WryWebContext ,
70+ WebView , WebViewBuilder ,
7171} ;
7272
7373pub use tao;
@@ -101,7 +101,7 @@ use std::{
101101 cell:: RefCell ,
102102 collections:: {
103103 hash_map:: Entry :: { Occupied , Vacant } ,
104- BTreeMap , HashMap ,
104+ BTreeMap , HashMap , HashSet ,
105105 } ,
106106 fmt,
107107 ops:: Deref ,
@@ -131,6 +131,15 @@ mod undecorated_resizing;
131131mod webview;
132132pub use webview:: Webview ;
133133
134+ #[ derive( Debug ) ]
135+ pub struct WebContext {
136+ pub inner : WryWebContext ,
137+ pub referenced_by_webviews : HashSet < String > ,
138+ // on Linux the custom protocols are associated with the context
139+ // and you cannot register a URI scheme more than once
140+ pub registered_custom_protocols : HashSet < String > ,
141+ }
142+
134143pub type WebContextStore = Arc < Mutex < HashMap < Option < PathBuf > , WebContext > > > ;
135144// window
136145pub type WindowEventHandler = Box < dyn Fn ( & WindowEvent ) + Send > ;
@@ -216,7 +225,6 @@ pub struct Context<T: UserEvent> {
216225 next_webview_id : Arc < AtomicU32 > ,
217226 next_window_event_id : Arc < AtomicU32 > ,
218227 next_webview_event_id : Arc < AtomicU32 > ,
219- next_webcontext_id : Arc < AtomicU32 > ,
220228}
221229
222230impl < T : UserEvent > Context < T > {
@@ -246,10 +254,6 @@ impl<T: UserEvent> Context<T> {
246254 fn next_webview_event_id ( & self ) -> u32 {
247255 self . next_webview_event_id . fetch_add ( 1 , Ordering :: Relaxed )
248256 }
249-
250- fn next_webcontext_id ( & self ) -> u32 {
251- self . next_webcontext_id . fetch_add ( 1 , Ordering :: Relaxed )
252- }
253257}
254258
255259impl < T : UserEvent > Context < T > {
@@ -2048,7 +2052,15 @@ impl Deref for WebviewWrapper {
20482052impl Drop for WebviewWrapper {
20492053 fn drop ( & mut self ) {
20502054 if Rc :: get_mut ( & mut self . inner ) . is_some ( ) {
2051- self . context_store . lock ( ) . unwrap ( ) . remove ( & self . context_key ) ;
2055+ let mut context_store = self . context_store . lock ( ) . unwrap ( ) ;
2056+
2057+ if let Some ( web_context) = context_store. get_mut ( & self . context_key ) {
2058+ web_context. referenced_by_webviews . remove ( & self . label ) ;
2059+
2060+ if web_context. referenced_by_webviews . is_empty ( ) {
2061+ context_store. remove ( & self . context_key ) ;
2062+ }
2063+ }
20522064 }
20532065 }
20542066}
@@ -2357,7 +2369,6 @@ impl<T: UserEvent> Wry<T> {
23572369 next_webview_id : Default :: default ( ) ,
23582370 next_window_event_id : Default :: default ( ) ,
23592371 next_webview_event_id : Default :: default ( ) ,
2360- next_webcontext_id : Default :: default ( ) ,
23612372 } ;
23622373
23632374 Ok ( Self {
@@ -4104,16 +4115,6 @@ fn create_webview<T: UserEvent>(
41044115 ipc_handler,
41054116 ) ) ;
41064117
4107- for ( scheme, protocol) in uri_scheme_protocols {
4108- webview_builder =
4109- webview_builder. with_asynchronous_custom_protocol ( scheme, move |request, responder| {
4110- protocol (
4111- request,
4112- Box :: new ( move |response| responder. respond ( response) ) ,
4113- )
4114- } ) ;
4115- }
4116-
41174118 for script in webview_attributes. initialization_scripts {
41184119 webview_builder = webview_builder. with_initialization_script ( & script) ;
41194120 }
@@ -4124,30 +4125,59 @@ fn create_webview<T: UserEvent>(
41244125 . lock ( )
41254126 . expect ( "poisoned WebContext store" ) ;
41264127 let is_first_context = web_context. is_empty ( ) ;
4128+ // the context must be stored on the HashMap because it must outlive the WebView on macOS
41274129 let automation_enabled = std:: env:: var ( "TAURI_WEBVIEW_AUTOMATION" ) . as_deref ( ) == Ok ( "true" ) ;
4128- let web_context_key = // force a unique WebContext when automation is false;
4129- // the context must be stored on the HashMap because it must outlive the WebView on macOS
4130- if automation_enabled {
4131- webview_attributes. data_directory . clone ( )
4132- } else {
4133- // unique key
4134- let key = context. next_webcontext_id ( ) . to_string ( ) . into ( ) ;
4135- Some ( key)
4136- } ;
4130+ let web_context_key = webview_attributes. data_directory ;
41374131 let entry = web_context. entry ( web_context_key. clone ( ) ) ;
41384132 let web_context = match entry {
4139- Occupied ( occupied) => occupied. into_mut ( ) ,
4133+ Occupied ( occupied) => {
4134+ let occupied = occupied. into_mut ( ) ;
4135+ occupied. referenced_by_webviews . insert ( label. clone ( ) ) ;
4136+ occupied
4137+ }
41404138 Vacant ( vacant) => {
4141- let mut web_context = WebContext :: new ( webview_attributes . data_directory ) ;
4139+ let mut web_context = WryWebContext :: new ( web_context_key . clone ( ) ) ;
41424140 web_context. set_allows_automation ( if automation_enabled {
41434141 is_first_context
41444142 } else {
41454143 false
41464144 } ) ;
4147- vacant. insert ( web_context)
4145+ vacant. insert ( WebContext {
4146+ inner : web_context,
4147+ referenced_by_webviews : [ label. clone ( ) ] . into ( ) ,
4148+ registered_custom_protocols : HashSet :: new ( ) ,
4149+ } )
41484150 }
41494151 } ;
41504152
4153+ for ( scheme, protocol) in uri_scheme_protocols {
4154+ // on Linux the custom protocols are associated with the web context
4155+ // and you cannot register a scheme more than once
4156+ if cfg ! ( any(
4157+ target_os = "linux" ,
4158+ target_os = "dragonfly" ,
4159+ target_os = "freebsd" ,
4160+ target_os = "netbsd" ,
4161+ target_os = "openbsd"
4162+ ) ) {
4163+ if web_context. registered_custom_protocols . contains ( & scheme) {
4164+ continue ;
4165+ }
4166+
4167+ web_context
4168+ . registered_custom_protocols
4169+ . insert ( scheme. clone ( ) ) ;
4170+ }
4171+
4172+ webview_builder =
4173+ webview_builder. with_asynchronous_custom_protocol ( scheme, move |request, responder| {
4174+ protocol (
4175+ request,
4176+ Box :: new ( move |response| responder. respond ( response) ) ,
4177+ )
4178+ } ) ;
4179+ }
4180+
41514181 if webview_attributes. clipboard {
41524182 webview_builder. attrs . clipboard = true ;
41534183 }
@@ -4175,7 +4205,7 @@ fn create_webview<T: UserEvent>(
41754205 }
41764206
41774207 let webview = webview_builder
4178- . with_web_context ( web_context)
4208+ . with_web_context ( & mut web_context. inner )
41794209 . build ( )
41804210 . map_err ( |e| Error :: CreateWebview ( Box :: new ( e) ) ) ?;
41814211
0 commit comments