@@ -27,7 +27,11 @@ use raw_window_handle::RawWindowHandle;
27
27
use std:: ffi:: c_ulong;
28
28
#[ cfg( any( debug_assertions, feature = "devtools" ) ) ]
29
29
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
30
- use std:: sync:: { Arc , Mutex } ;
30
+ use std:: {
31
+ collections:: HashMap ,
32
+ rc:: Rc ,
33
+ sync:: { Arc , Mutex } ,
34
+ } ;
31
35
#[ cfg( any( debug_assertions, feature = "devtools" ) ) ]
32
36
use webkit2gtk:: WebInspectorExt ;
33
37
use webkit2gtk:: {
@@ -275,11 +279,11 @@ impl InnerWebView {
275
279
}
276
280
277
281
// Extension loading
278
- if let Some ( extension_path) = pl_attrs. extension_path {
279
- web_context. os . set_web_extensions_directory ( & extension_path) ;
282
+ if let Some ( extension_path) = & pl_attrs. extension_path {
283
+ web_context. os . set_web_extensions_directory ( extension_path) ;
280
284
}
281
285
282
- let webview = Self :: create_webview ( web_context, & attributes) ;
286
+ let webview = Self :: create_webview ( web_context, & attributes, & pl_attrs ) ;
283
287
284
288
// Transparent
285
289
if attributes. transparent {
@@ -379,10 +383,13 @@ impl InnerWebView {
379
383
Ok ( w)
380
384
}
381
385
382
- fn create_webview ( web_context : & WebContext , attributes : & WebViewAttributes ) -> WebView {
386
+ fn create_webview (
387
+ web_context : & WebContext ,
388
+ attributes : & WebViewAttributes ,
389
+ pl_attrs : & super :: PlatformSpecificWebViewAttributes ,
390
+ ) -> WebView {
383
391
let mut builder = WebView :: builder ( )
384
392
. user_content_manager ( & UserContentManager :: new ( ) )
385
- . web_context ( web_context. context ( ) )
386
393
. is_controlled_by_automation ( web_context. allows_automation ( ) ) ;
387
394
388
395
if attributes. autoplay {
@@ -393,6 +400,12 @@ impl InnerWebView {
393
400
) ;
394
401
}
395
402
403
+ if let Some ( related_view) = & pl_attrs. related_view {
404
+ builder = builder. related_view ( related_view) ;
405
+ } else {
406
+ builder = builder. web_context ( web_context. context ( ) ) ;
407
+ }
408
+
396
409
builder. build ( )
397
410
}
398
411
@@ -468,35 +481,79 @@ impl InnerWebView {
468
481
} ) ;
469
482
}
470
483
471
- // Navigation handler && New window handler
472
- if attributes. navigation_handler . is_some ( ) || attributes. new_window_req_handler . is_some ( ) {
473
- let new_window_req_handler = attributes. new_window_req_handler . take ( ) ;
474
- let navigation_handler = attributes. navigation_handler . take ( ) ;
484
+ // window creation handler
485
+ if let Some ( new_window_req_handler) = attributes. new_window_req_handler . take ( ) {
486
+ let related_webviews = Rc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
487
+ webview. connect_create ( move |webview, action| {
488
+ let url = action
489
+ . request ( )
490
+ . and_then ( |request| request. uri ( ) )
491
+ . map ( |uri| uri. as_str ( ) . to_string ( ) ) ?;
492
+ if new_window_req_handler ( url. clone ( ) ) {
493
+ let related_webviews = related_webviews. clone ( ) ;
494
+ let toplevel = webview. toplevel ( ) . unwrap ( ) ;
495
+ let window = toplevel. downcast :: < gtk:: ApplicationWindow > ( ) . unwrap ( ) ;
496
+ let id = window. id ( ) ;
497
+ let app = window. application ( ) . unwrap ( ) ;
498
+
499
+ let window = gtk:: ApplicationWindow :: builder ( )
500
+ . application ( & app)
501
+ . title ( & url)
502
+ . build ( ) ;
503
+ let box_ = gtk:: Box :: new ( gtk:: Orientation :: Vertical , 0 ) ;
504
+ window. add ( & box_) ;
505
+
506
+ let related_webviews_ = related_webviews. clone ( ) ;
507
+ window. connect_destroy ( move |_| {
508
+ related_webviews_. lock ( ) . unwrap ( ) . remove ( & id) ;
509
+ } ) ;
475
510
511
+ window. show_all ( ) ;
512
+ Self :: new_gtk (
513
+ & box_,
514
+ WebViewAttributes {
515
+ ..Default :: default ( )
516
+ } ,
517
+ super :: PlatformSpecificWebViewAttributes {
518
+ related_view : Some ( webview. clone ( ) ) ,
519
+ ..Default :: default ( )
520
+ } ,
521
+ )
522
+ . map ( |webview| {
523
+ let widget = webview. webview . upcast_ref :: < gtk:: Widget > ( ) . clone ( ) ;
524
+ related_webviews. lock ( ) . unwrap ( ) . insert ( id, webview) ;
525
+ widget
526
+ } )
527
+ . ok ( )
528
+ } else {
529
+ None
530
+ }
531
+ } ) ;
532
+ }
533
+
534
+ // Navigation handler
535
+ if let Some ( navigation_handler) = attributes. navigation_handler . take ( ) {
476
536
webview. connect_decide_policy ( move |_webview, policy_decision, policy_type| {
477
537
let handler = match policy_type {
478
538
PolicyDecisionType :: NavigationAction => & navigation_handler,
479
- PolicyDecisionType :: NewWindowAction => & new_window_req_handler,
480
539
_ => return false ,
481
540
} ;
482
541
483
- if let Some ( handler) = handler {
484
- if let Some ( policy) = policy_decision. dynamic_cast_ref :: < NavigationPolicyDecision > ( ) {
485
- if let Some ( nav_action) = policy. navigation_action ( ) {
486
- if let Some ( uri_req) = nav_action. request ( ) {
487
- if let Some ( uri) = uri_req. uri ( ) {
488
- let allow = handler ( uri. to_string ( ) ) ;
489
- let pointer = policy_decision. as_ptr ( ) ;
490
- unsafe {
491
- if allow {
492
- webkit_policy_decision_use ( pointer)
493
- } else {
494
- webkit_policy_decision_ignore ( pointer)
495
- }
542
+ if let Some ( policy) = policy_decision. dynamic_cast_ref :: < NavigationPolicyDecision > ( ) {
543
+ if let Some ( nav_action) = policy. navigation_action ( ) {
544
+ if let Some ( uri_req) = nav_action. request ( ) {
545
+ if let Some ( uri) = uri_req. uri ( ) {
546
+ let allow = handler ( uri. to_string ( ) ) ;
547
+ let pointer = policy_decision. as_ptr ( ) ;
548
+ unsafe {
549
+ if allow {
550
+ webkit_policy_decision_use ( pointer)
551
+ } else {
552
+ webkit_policy_decision_ignore ( pointer)
496
553
}
497
-
498
- return true ;
499
554
}
555
+
556
+ return true ;
500
557
}
501
558
}
502
559
}
@@ -936,21 +993,21 @@ impl InnerWebView {
936
993
937
994
pub fn cookies_for_url ( & self , url : & str ) -> Result < Vec < cookie:: Cookie < ' static > > > {
938
995
let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
939
- self
996
+ if let Some ( cookies_manager ) = self
940
997
. webview
941
998
. website_data_manager ( )
942
999
. and_then ( |manager| manager. cookie_manager ( ) )
943
- . map ( |cookies_manager| {
944
- cookies_manager. cookies ( url, None :: < & Cancellable > , move |cookies| {
945
- let cookies = cookies. map ( |cookies| {
946
- cookies
947
- . into_iter ( )
948
- . map ( Self :: cookie_from_soup_cookie)
949
- . collect ( )
950
- } ) ;
951
- let _ = tx. send ( cookies) ;
952
- } )
953
- } ) ;
1000
+ {
1001
+ cookies_manager. cookies ( url, None :: < & Cancellable > , move |cookies| {
1002
+ let cookies = cookies. map ( |cookies| {
1003
+ cookies
1004
+ . into_iter ( )
1005
+ . map ( Self :: cookie_from_soup_cookie)
1006
+ . collect ( )
1007
+ } ) ;
1008
+ let _ = tx. send ( cookies) ;
1009
+ } )
1010
+ }
954
1011
955
1012
loop {
956
1013
gtk:: main_iteration ( ) ;
@@ -963,21 +1020,21 @@ impl InnerWebView {
963
1020
964
1021
pub fn cookies ( & self ) -> Result < Vec < cookie:: Cookie < ' static > > > {
965
1022
let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
966
- self
1023
+ if let Some ( cookies_manager ) = self
967
1024
. webview
968
1025
. website_data_manager ( )
969
1026
. and_then ( |manager| manager. cookie_manager ( ) )
970
- . map ( |cookies_manager| {
971
- cookies_manager. all_cookies ( None :: < & Cancellable > , move |cookies| {
972
- let cookies = cookies. map ( |cookies| {
973
- cookies
974
- . into_iter ( )
975
- . map ( Self :: cookie_from_soup_cookie)
976
- . collect ( )
977
- } ) ;
978
- let _ = tx. send ( cookies) ;
979
- } )
980
- } ) ;
1027
+ {
1028
+ cookies_manager. all_cookies ( None :: < & Cancellable > , move |cookies| {
1029
+ let cookies = cookies. map ( |cookies| {
1030
+ cookies
1031
+ . into_iter ( )
1032
+ . map ( Self :: cookie_from_soup_cookie)
1033
+ . collect ( )
1034
+ } ) ;
1035
+ let _ = tx. send ( cookies) ;
1036
+ } )
1037
+ }
981
1038
982
1039
loop {
983
1040
gtk:: main_iteration ( ) ;
@@ -990,16 +1047,16 @@ impl InnerWebView {
990
1047
991
1048
pub fn set_cookie ( & self , cookie : & cookie:: Cookie < ' _ > ) -> Result < ( ) > {
992
1049
let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
993
- self
1050
+ if let Some ( cookies_manager ) = self
994
1051
. webview
995
1052
. website_data_manager ( )
996
1053
. and_then ( |manager| manager. cookie_manager ( ) )
997
- . map ( |cookies_manager| {
998
- let mut soup_cookie = Self :: cookie_into_soup_cookie ( cookie) ;
999
- cookies_manager. add_cookie ( & mut soup_cookie, None :: < & Cancellable > , move |ret| {
1000
- let _ = tx. send ( ret) ;
1001
- } ) ;
1054
+ {
1055
+ let mut soup_cookie = Self :: cookie_into_soup_cookie ( cookie) ;
1056
+ cookies_manager. add_cookie ( & mut soup_cookie, None :: < & Cancellable > , move |ret| {
1057
+ let _ = tx. send ( ret) ;
1002
1058
} ) ;
1059
+ }
1003
1060
1004
1061
loop {
1005
1062
gtk:: main_iteration ( ) ;
@@ -1012,16 +1069,16 @@ impl InnerWebView {
1012
1069
1013
1070
pub fn delete_cookie ( & self , cookie : & cookie:: Cookie < ' _ > ) -> Result < ( ) > {
1014
1071
let ( tx, rx) = std:: sync:: mpsc:: channel ( ) ;
1015
- self
1072
+ if let Some ( cookies_manager ) = self
1016
1073
. webview
1017
1074
. website_data_manager ( )
1018
1075
. and_then ( |manager| manager. cookie_manager ( ) )
1019
- . map ( |cookies_manager| {
1020
- let mut soup_cookie = Self :: cookie_into_soup_cookie ( cookie) ;
1021
- cookies_manager. delete_cookie ( & mut soup_cookie, None :: < & Cancellable > , move |ret| {
1022
- let _ = tx. send ( ret) ;
1023
- } ) ;
1076
+ {
1077
+ let mut soup_cookie = Self :: cookie_into_soup_cookie ( cookie) ;
1078
+ cookies_manager. delete_cookie ( & mut soup_cookie, None :: < & Cancellable > , move |ret| {
1079
+ let _ = tx. send ( ret) ;
1024
1080
} ) ;
1081
+ }
1025
1082
1026
1083
loop {
1027
1084
gtk:: main_iteration ( ) ;
0 commit comments