@@ -66,8 +66,8 @@ use tauri_utils::TitleBarStyle;
66
66
use tauri_utils:: { config:: WindowConfig , Theme } ;
67
67
use url:: Url ;
68
68
use wry:: {
69
- DragDropEvent as WryDragDropEvent , ProxyConfig , ProxyEndpoint , WebContext , WebView ,
70
- WebViewBuilder ,
69
+ DragDropEvent as WryDragDropEvent , ProxyConfig , ProxyEndpoint , WebContext as WryWebContext ,
70
+ WebView , WebViewBuilder ,
71
71
} ;
72
72
73
73
pub use tao;
@@ -101,7 +101,7 @@ use std::{
101
101
cell:: RefCell ,
102
102
collections:: {
103
103
hash_map:: Entry :: { Occupied , Vacant } ,
104
- BTreeMap , HashMap ,
104
+ BTreeMap , HashMap , HashSet ,
105
105
} ,
106
106
fmt,
107
107
ops:: Deref ,
@@ -131,6 +131,15 @@ mod undecorated_resizing;
131
131
mod webview;
132
132
pub use webview:: Webview ;
133
133
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
+
134
143
pub type WebContextStore = Arc < Mutex < HashMap < Option < PathBuf > , WebContext > > > ;
135
144
// window
136
145
pub type WindowEventHandler = Box < dyn Fn ( & WindowEvent ) + Send > ;
@@ -216,7 +225,6 @@ pub struct Context<T: UserEvent> {
216
225
next_webview_id : Arc < AtomicU32 > ,
217
226
next_window_event_id : Arc < AtomicU32 > ,
218
227
next_webview_event_id : Arc < AtomicU32 > ,
219
- next_webcontext_id : Arc < AtomicU32 > ,
220
228
}
221
229
222
230
impl < T : UserEvent > Context < T > {
@@ -246,10 +254,6 @@ impl<T: UserEvent> Context<T> {
246
254
fn next_webview_event_id ( & self ) -> u32 {
247
255
self . next_webview_event_id . fetch_add ( 1 , Ordering :: Relaxed )
248
256
}
249
-
250
- fn next_webcontext_id ( & self ) -> u32 {
251
- self . next_webcontext_id . fetch_add ( 1 , Ordering :: Relaxed )
252
- }
253
257
}
254
258
255
259
impl < T : UserEvent > Context < T > {
@@ -2048,7 +2052,15 @@ impl Deref for WebviewWrapper {
2048
2052
impl Drop for WebviewWrapper {
2049
2053
fn drop ( & mut self ) {
2050
2054
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
+ }
2052
2064
}
2053
2065
}
2054
2066
}
@@ -2357,7 +2369,6 @@ impl<T: UserEvent> Wry<T> {
2357
2369
next_webview_id : Default :: default ( ) ,
2358
2370
next_window_event_id : Default :: default ( ) ,
2359
2371
next_webview_event_id : Default :: default ( ) ,
2360
- next_webcontext_id : Default :: default ( ) ,
2361
2372
} ;
2362
2373
2363
2374
Ok ( Self {
@@ -4104,16 +4115,6 @@ fn create_webview<T: UserEvent>(
4104
4115
ipc_handler,
4105
4116
) ) ;
4106
4117
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
-
4117
4118
for script in webview_attributes. initialization_scripts {
4118
4119
webview_builder = webview_builder. with_initialization_script ( & script) ;
4119
4120
}
@@ -4124,30 +4125,59 @@ fn create_webview<T: UserEvent>(
4124
4125
. lock ( )
4125
4126
. expect ( "poisoned WebContext store" ) ;
4126
4127
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
4127
4129
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 ;
4137
4131
let entry = web_context. entry ( web_context_key. clone ( ) ) ;
4138
4132
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
+ }
4140
4138
Vacant ( vacant) => {
4141
- let mut web_context = WebContext :: new ( webview_attributes . data_directory ) ;
4139
+ let mut web_context = WryWebContext :: new ( web_context_key . clone ( ) ) ;
4142
4140
web_context. set_allows_automation ( if automation_enabled {
4143
4141
is_first_context
4144
4142
} else {
4145
4143
false
4146
4144
} ) ;
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
+ } )
4148
4150
}
4149
4151
} ;
4150
4152
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
+
4151
4181
if webview_attributes. clipboard {
4152
4182
webview_builder. attrs . clipboard = true ;
4153
4183
}
@@ -4175,7 +4205,7 @@ fn create_webview<T: UserEvent>(
4175
4205
}
4176
4206
4177
4207
let webview = webview_builder
4178
- . with_web_context ( web_context)
4208
+ . with_web_context ( & mut web_context. inner )
4179
4209
. build ( )
4180
4210
. map_err ( |e| Error :: CreateWebview ( Box :: new ( e) ) ) ?;
4181
4211
0 commit comments