@@ -395,7 +395,9 @@ pub use self::webview2::ScrollBarStyle;
395
395
#[ cfg( target_os = "windows" ) ]
396
396
use self :: webview2:: * ;
397
397
#[ cfg( target_os = "windows" ) ]
398
- use webview2_com:: Microsoft :: Web :: WebView2 :: Win32 :: ICoreWebView2Controller ;
398
+ use webview2_com:: Microsoft :: Web :: WebView2 :: Win32 :: {
399
+ ICoreWebView2 , ICoreWebView2Controller , ICoreWebView2Environment ,
400
+ } ;
399
401
400
402
use std:: { borrow:: Cow , collections:: HashMap , path:: PathBuf , rc:: Rc } ;
401
403
@@ -450,6 +452,87 @@ impl RequestAsyncResponder {
450
452
}
451
453
}
452
454
455
+ /// Response for the new window request handler.
456
+ ///
457
+ /// See [`WebViewBuilder::with_new_window_req_handler`].
458
+ pub enum NewWindowResponse {
459
+ /// Allow the window to be opened with the default implementation.
460
+ Allow ,
461
+ /// Allow the window to be opened, with the given platform webview instance.
462
+ ///
463
+ /// ## Platform-specific:
464
+ ///
465
+ /// **Linux**: The webview must be related to the caller webview. See [`WebViewBuilderExtUnix::with_related_view`].
466
+ /// **Windows**: The webview must use the same environment as the caller webview. See [`WebViewBuilderExtWindows::with_environment`].
467
+ /// **macOS**: The webview must use the same configuration as the caller webview. See [`WebViewBuilderExtMacos::with_webview_configuration`].
468
+ #[ cfg( not( any( target_os = "android" , target_os = "ios" ) ) ) ]
469
+ Create {
470
+ #[ cfg( any(
471
+ target_os = "linux" ,
472
+ target_os = "dragonfly" ,
473
+ target_os = "freebsd" ,
474
+ target_os = "netbsd" ,
475
+ target_os = "openbsd" ,
476
+ ) ) ]
477
+ webview : webkit2gtk:: WebView ,
478
+ #[ cfg( windows) ]
479
+ webview : ICoreWebView2 ,
480
+ #[ cfg( target_os = "macos" ) ]
481
+ webview : Retained < objc2_web_kit:: WKWebView > ,
482
+ } ,
483
+ /// Deny the window from being opened.
484
+ Deny ,
485
+ }
486
+
487
+ /// Information about the webview that initiated a new window request.
488
+ #[ derive( Debug ) ]
489
+ pub struct NewWindowOpener {
490
+ /// The instance of the webview that initiated the new window request.
491
+ ///
492
+ /// This must be set as the related view of the new webview. See [`WebViewBuilderExtUnix::with_related_view`].
493
+ #[ cfg( any(
494
+ target_os = "linux" ,
495
+ target_os = "dragonfly" ,
496
+ target_os = "freebsd" ,
497
+ target_os = "netbsd" ,
498
+ target_os = "openbsd" ,
499
+ ) ) ]
500
+ pub webview : webkit2gtk:: WebView ,
501
+ /// The instance of the webview that initiated the new window request.
502
+ #[ cfg( windows) ]
503
+ pub webview : ICoreWebView2 ,
504
+ /// The environment of the webview that initiated the new window request.
505
+ ///
506
+ /// The target webview environment **MUST** match the environment of the opener webview. See [`WebViewBuilderExtWindows::with_environment`].
507
+ #[ cfg( windows) ]
508
+ pub environment : ICoreWebView2Environment ,
509
+ /// The instance of the webview that initiated the new window request.
510
+ #[ cfg( target_os = "macos" ) ]
511
+ pub webview : Retained < objc2_web_kit:: WKWebView > ,
512
+ /// Configuration of the target webview.
513
+ ///
514
+ /// This **MUST** be used when creating the target webview. See [`WebViewBuilderExtMacos::with_webview_configuration`].
515
+ #[ cfg( target_os = "macos" ) ]
516
+ pub target_configuration : Retained < objc2_web_kit:: WKWebViewConfiguration > ,
517
+ }
518
+
519
+ unsafe impl Send for NewWindowOpener { }
520
+ unsafe impl Sync for NewWindowOpener { }
521
+
522
+ /// Window features of a window requested to open.
523
+ #[ non_exhaustive]
524
+ #[ derive( Debug ) ]
525
+ pub struct NewWindowFeatures {
526
+ /// Specifies the size of the content area
527
+ /// as defined by the user's operating system where the new window will be generated.
528
+ pub size : Option < dpi:: LogicalSize < f64 > > ,
529
+ /// Specifies the position of the window relative to the work area
530
+ /// as defined by the user's operating system where the new window will be generated.
531
+ pub position : Option < dpi:: LogicalPosition < f64 > > ,
532
+ /// Information about the webview opener containing data that must be used when creating the new webview.
533
+ pub opener : NewWindowOpener ,
534
+ }
535
+
453
536
/// An id for a webview
454
537
pub type WebViewId < ' a > = & ' a str ;
455
538
@@ -604,11 +687,19 @@ pub struct WebViewAttributes<'a> {
604
687
/// due to API limitations.
605
688
pub download_completed_handler : Option < Rc < dyn Fn ( String , Option < PathBuf > , bool ) + ' static > > ,
606
689
607
- /// A new window handler to decide if incoming url is allowed to open in a new window.
690
+ /// A new window request handler to decide if incoming url is allowed to be opened.
691
+ ///
692
+ /// A new window is requested to be opened by the [window.open] API.
608
693
///
609
- /// The closure take a `String` parameter as url and return `bool` to determine whether the window should open.
610
- /// `true` allows to open and `false` does not.
611
- pub new_window_req_handler : Option < Box < dyn Fn ( String ) -> bool > > ,
694
+ /// The closure take the URL to open and the window features object and returns [`NewWindowResponse`] to determine whether the window should open.
695
+ ///
696
+ /// ## Platform-specific:
697
+ ///
698
+ /// - **Windows**: The closure is executed on a separate thread to prevent a deadlock.
699
+ ///
700
+ /// [window.open]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open
701
+ pub new_window_req_handler :
702
+ Option < Box < dyn Fn ( String , NewWindowFeatures ) -> NewWindowResponse + Send + Sync > > ,
612
703
613
704
/// Enables clipboard access for the page rendered on **Linux** and **Windows**.
614
705
///
@@ -1203,11 +1294,18 @@ impl<'a> WebViewBuilder<'a> {
1203
1294
1204
1295
/// Set a new window request handler to decide if incoming url is allowed to be opened.
1205
1296
///
1206
- /// The closure take a `String` parameter as url and return `bool` to determine whether the window should open.
1207
- /// `true` allows to open and `false` does not.
1297
+ /// A new window is requested to be opened by the [window.open] API.
1298
+ ///
1299
+ /// The closure take the URL to open and the window features object and returns [`NewWindowResponse`] to determine whether the window should open.
1300
+ ///
1301
+ /// ## Platform-specific:
1302
+ ///
1303
+ /// - **Windows**: The closure is executed on a separate thread to prevent a deadlock.
1304
+ ///
1305
+ /// [window.open]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open
1208
1306
pub fn with_new_window_req_handler (
1209
1307
mut self ,
1210
- callback : impl Fn ( String ) -> bool + ' static ,
1308
+ callback : impl Fn ( String , NewWindowFeatures ) -> NewWindowResponse + Send + Sync + ' static ,
1211
1309
) -> Self {
1212
1310
self . attrs . new_window_req_handler = Some ( Box :: new ( callback) ) ;
1213
1311
self
@@ -1368,6 +1466,8 @@ pub(crate) struct PlatformSpecificWebViewAttributes {
1368
1466
input_accessory_view_builder : Option < Box < InputAccessoryViewBuilder > > ,
1369
1467
#[ cfg( target_os = "ios" ) ]
1370
1468
limit_navigations_to_app_bound_domains : bool ,
1469
+ #[ cfg( target_os = "macos" ) ]
1470
+ webview_configuration : Option < Retained < objc2_web_kit:: WKWebViewConfiguration > > ,
1371
1471
}
1372
1472
1373
1473
#[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
@@ -1382,6 +1482,8 @@ impl Default for PlatformSpecificWebViewAttributes {
1382
1482
input_accessory_view_builder : None ,
1383
1483
#[ cfg( target_os = "ios" ) ]
1384
1484
limit_navigations_to_app_bound_domains : false ,
1485
+ #[ cfg( target_os = "macos" ) ]
1486
+ webview_configuration : None ,
1385
1487
}
1386
1488
}
1387
1489
}
@@ -1427,6 +1529,29 @@ impl WebViewBuilderExtDarwin for WebViewBuilder<'_> {
1427
1529
}
1428
1530
}
1429
1531
1532
+ #[ cfg( target_os = "macos" ) ]
1533
+ pub trait WebViewBuilderExtMacos {
1534
+ /// Set the webview configuration that must be used to create the new webview.
1535
+ fn with_webview_configuration (
1536
+ self ,
1537
+ configuration : Retained < objc2_web_kit:: WKWebViewConfiguration > ,
1538
+ ) -> Self ;
1539
+ }
1540
+
1541
+ #[ cfg( target_os = "macos" ) ]
1542
+ impl WebViewBuilderExtMacos for WebViewBuilder < ' _ > {
1543
+ fn with_webview_configuration (
1544
+ mut self ,
1545
+ configuration : Retained < objc2_web_kit:: WKWebViewConfiguration > ,
1546
+ ) -> Self {
1547
+ self
1548
+ . platform_specific
1549
+ . webview_configuration
1550
+ . replace ( configuration) ;
1551
+ self
1552
+ }
1553
+ }
1554
+
1430
1555
#[ cfg( target_os = "ios" ) ]
1431
1556
pub trait WebViewBuilderExtIos {
1432
1557
/// Allows overriding the the keyboard accessory view on iOS.
@@ -1501,6 +1626,7 @@ pub(crate) struct PlatformSpecificWebViewAttributes {
1501
1626
browser_extensions_enabled : bool ,
1502
1627
extension_path : Option < PathBuf > ,
1503
1628
default_context_menus : bool ,
1629
+ environment : Option < ICoreWebView2Environment > ,
1504
1630
}
1505
1631
1506
1632
#[ cfg( windows) ]
@@ -1515,6 +1641,7 @@ impl Default for PlatformSpecificWebViewAttributes {
1515
1641
scroll_bar_style : ScrollBarStyle :: default ( ) ,
1516
1642
browser_extensions_enabled : false ,
1517
1643
extension_path : None ,
1644
+ environment : None ,
1518
1645
}
1519
1646
}
1520
1647
}
@@ -1587,6 +1714,10 @@ pub trait WebViewBuilderExtWindows {
1587
1714
///
1588
1715
/// Does nothing if browser extensions are disabled. See [`with_browser_extensions_enabled`](Self::with_browser_extensions_enabled)
1589
1716
fn with_extensions_path ( self , path : impl Into < PathBuf > ) -> Self ;
1717
+
1718
+ /// Set the environment for the webview.
1719
+ /// Useful if you need to share the same environment, for instance when using the [`WebViewBuilder::with_new_window_req_handler`].
1720
+ fn with_environment ( self , environment : ICoreWebView2Environment ) -> Self ;
1590
1721
}
1591
1722
1592
1723
#[ cfg( windows) ]
@@ -1630,6 +1761,11 @@ impl WebViewBuilderExtWindows for WebViewBuilder<'_> {
1630
1761
self . platform_specific . extension_path = Some ( path. into ( ) ) ;
1631
1762
self
1632
1763
}
1764
+
1765
+ fn with_environment ( mut self , environment : ICoreWebView2Environment ) -> Self {
1766
+ self . platform_specific . environment . replace ( environment) ;
1767
+ self
1768
+ }
1633
1769
}
1634
1770
1635
1771
#[ cfg( target_os = "android" ) ]
@@ -1742,6 +1878,7 @@ pub trait WebViewBuilderExtUnix<'a> {
1742
1878
fn with_extensions_path ( self , path : impl Into < PathBuf > ) -> Self ;
1743
1879
1744
1880
/// Creates a new webview sharing the same web process with the provided webview.
1881
+ /// Useful if you need to link a webview to another, for instance when using the [`WebViewBuilder::with_new_window_req_handler`].
1745
1882
fn with_related_view ( self , webview : webkit2gtk:: WebView ) -> Self ;
1746
1883
}
1747
1884
@@ -2065,9 +2202,15 @@ pub enum MemoryUsageLevel {
2065
2202
/// Additional methods on `WebView` that are specific to Windows.
2066
2203
#[ cfg( target_os = "windows" ) ]
2067
2204
pub trait WebViewExtWindows {
2068
- /// Returns WebView2 Controller
2205
+ /// Returns the WebView2 controller.
2069
2206
fn controller ( & self ) -> ICoreWebView2Controller ;
2070
2207
2208
+ /// Webview environment.
2209
+ fn environment ( & self ) -> ICoreWebView2Environment ;
2210
+
2211
+ /// Webview instance.
2212
+ fn webview ( & self ) -> ICoreWebView2 ;
2213
+
2071
2214
/// Changes the webview2 theme.
2072
2215
///
2073
2216
/// Requires WebView2 Runtime version 101.0.1210.39 or higher, returns error on older versions,
@@ -2098,6 +2241,14 @@ impl WebViewExtWindows for WebView {
2098
2241
self . webview . controller . clone ( )
2099
2242
}
2100
2243
2244
+ fn environment ( & self ) -> ICoreWebView2Environment {
2245
+ self . webview . env . clone ( )
2246
+ }
2247
+
2248
+ fn webview ( & self ) -> ICoreWebView2 {
2249
+ self . webview . webview . clone ( )
2250
+ }
2251
+
2101
2252
fn set_theme ( & self , theme : Theme ) -> Result < ( ) > {
2102
2253
self . webview . set_theme ( theme)
2103
2254
}
0 commit comments