1use std::path::PathBuf;
6use std::rc::Rc;
7
8use base::generic_channel::GenericSender;
9use base::id::PipelineId;
10use constellation_traits::EmbedderToConstellationMessage;
11#[cfg(feature = "gamepad")]
12use embedder_traits::GamepadHapticEffectType;
13use embedder_traits::{
14 AlertResponse, AllowOrDeny, AuthenticationResponse, ConfirmResponse, ConsoleLogLevel,
15 ContextMenuAction, ContextMenuElementInformation, ContextMenuItem, Cursor, EmbedderControlId,
16 EmbedderControlResponse, FilePickerRequest, FilterPattern, InputEventId, InputEventResult,
17 InputMethodType, LoadStatus, MediaSessionEvent, NewWebViewDetails, Notification,
18 PermissionFeature, PromptResponse, RgbColor, ScreenGeometry, SelectElementOptionOrOptgroup,
19 SimpleDialogRequest, TraversalId, WebResourceRequest, WebResourceResponse,
20 WebResourceResponseMsg,
21};
22use paint_api::rendering_context::RenderingContext;
23use tokio::sync::mpsc::UnboundedSender as TokioSender;
24use tokio::sync::oneshot::Sender;
25use url::Url;
26use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
27
28use crate::proxies::ConstellationProxy;
29use crate::responders::{IpcResponder, OneshotSender, ServoErrorSender};
30use crate::{RegisterOrUnregister, Servo, WebView, WebViewBuilder};
31
32pub struct NavigationRequest {
35 pub url: Url,
36 pub(crate) pipeline_id: PipelineId,
37 pub(crate) constellation_proxy: ConstellationProxy,
38 pub(crate) response_sent: bool,
39}
40
41impl NavigationRequest {
42 pub fn allow(mut self) {
43 self.constellation_proxy
44 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
45 self.pipeline_id,
46 true,
47 ));
48 self.response_sent = true;
49 }
50
51 pub fn deny(mut self) {
52 self.constellation_proxy
53 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
54 self.pipeline_id,
55 false,
56 ));
57 self.response_sent = true;
58 }
59}
60
61impl Drop for NavigationRequest {
62 fn drop(&mut self) {
63 if !self.response_sent {
64 self.constellation_proxy
65 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
66 self.pipeline_id,
67 true,
68 ));
69 }
70 }
71}
72
73pub struct PermissionRequest {
77 pub(crate) requested_feature: PermissionFeature,
78 pub(crate) allow_deny_request: AllowOrDenyRequest,
79}
80
81impl PermissionRequest {
82 pub fn feature(&self) -> PermissionFeature {
83 self.requested_feature
84 }
85
86 pub fn allow(self) {
87 self.allow_deny_request.allow();
88 }
89
90 pub fn deny(self) {
91 self.allow_deny_request.deny();
92 }
93}
94
95pub struct AllowOrDenyRequest(IpcResponder<AllowOrDeny>, ServoErrorSender);
96
97impl AllowOrDenyRequest {
98 pub(crate) fn new(
99 response_sender: GenericSender<AllowOrDeny>,
100 default_response: AllowOrDeny,
101 error_sender: ServoErrorSender,
102 ) -> Self {
103 Self(
104 IpcResponder::new(response_sender, default_response),
105 error_sender,
106 )
107 }
108
109 pub fn allow(mut self) {
110 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
111 self.1.raise_response_send_error(error);
112 }
113 }
114
115 pub fn deny(mut self) {
116 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
117 self.1.raise_response_send_error(error);
118 }
119 }
120}
121
122#[derive(Clone, Debug, Eq, PartialEq)]
123pub struct ProtocolHandlerRegistration {
124 pub scheme: String,
125 pub url: Url,
126 pub register_or_unregister: RegisterOrUnregister,
127}
128
129pub struct AuthenticationRequest {
133 pub(crate) url: Url,
134 pub(crate) for_proxy: bool,
135 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
136 pub(crate) error_sender: ServoErrorSender,
137}
138
139impl AuthenticationRequest {
140 pub(crate) fn new(
141 url: Url,
142 for_proxy: bool,
143 response_sender: Sender<Option<AuthenticationResponse>>,
144 error_sender: ServoErrorSender,
145 ) -> Self {
146 Self {
147 url,
148 for_proxy,
149 responder: IpcResponder::new_same_process(
150 Box::new(OneshotSender::from(response_sender)),
151 None,
152 ),
153 error_sender,
154 }
155 }
156
157 pub fn url(&self) -> &Url {
159 &self.url
160 }
161 pub fn for_proxy(&self) -> bool {
163 self.for_proxy
164 }
165 pub fn authenticate(mut self, username: String, password: String) {
167 if let Err(error) = self
168 .responder
169 .send(Some(AuthenticationResponse { username, password }))
170 {
171 self.error_sender.raise_response_send_error(error);
172 }
173 }
174}
175
176pub struct WebResourceLoad {
180 pub request: WebResourceRequest,
181 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
182 pub(crate) error_sender: ServoErrorSender,
183}
184
185impl WebResourceLoad {
186 pub(crate) fn new(
187 web_resource_request: WebResourceRequest,
188 response_sender: TokioSender<WebResourceResponseMsg>,
189 error_sender: ServoErrorSender,
190 ) -> Self {
191 Self {
192 request: web_resource_request,
193 responder: IpcResponder::new_same_process(
194 Box::new(response_sender),
195 WebResourceResponseMsg::DoNotIntercept,
196 ),
197 error_sender,
198 }
199 }
200
201 pub fn request(&self) -> &WebResourceRequest {
203 &self.request
204 }
205 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
208 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
209 self.error_sender.raise_response_send_error(error);
210 }
211 InterceptedWebResourceLoad {
212 request: self.request.clone(),
213 response_sender: self.responder,
214 finished: false,
215 error_sender: self.error_sender,
216 }
217 }
218}
219
220pub struct InterceptedWebResourceLoad {
226 pub request: WebResourceRequest,
227 pub(crate) response_sender: IpcResponder<WebResourceResponseMsg>,
228 pub(crate) finished: bool,
229 pub(crate) error_sender: ServoErrorSender,
230}
231
232impl InterceptedWebResourceLoad {
233 pub fn send_body_data(&mut self, data: Vec<u8>) {
236 if let Err(error) = self
237 .response_sender
238 .send(WebResourceResponseMsg::SendBodyData(data))
239 {
240 self.error_sender.raise_response_send_error(error);
241 }
242 }
243 pub fn finish(mut self) {
245 if let Err(error) = self
246 .response_sender
247 .send(WebResourceResponseMsg::FinishLoad)
248 {
249 self.error_sender.raise_response_send_error(error);
250 }
251 self.finished = true;
252 }
253 pub fn cancel(mut self) {
255 if let Err(error) = self
256 .response_sender
257 .send(WebResourceResponseMsg::CancelLoad)
258 {
259 self.error_sender.raise_response_send_error(error);
260 }
261 self.finished = true;
262 }
263}
264
265impl Drop for InterceptedWebResourceLoad {
266 fn drop(&mut self) {
267 if !self.finished {
268 if let Err(error) = self
269 .response_sender
270 .send(WebResourceResponseMsg::FinishLoad)
271 {
272 self.error_sender.raise_response_send_error(error);
273 }
274 }
275 }
276}
277
278pub enum EmbedderControl {
280 SelectElement(SelectElement),
282 ColorPicker(ColorPicker),
284 FilePicker(FilePicker),
286 InputMethod(InputMethodControl),
289 SimpleDialog(SimpleDialog),
294 ContextMenu(ContextMenu),
298}
299
300impl EmbedderControl {
301 pub fn id(&self) -> EmbedderControlId {
302 match self {
303 EmbedderControl::SelectElement(select_element) => select_element.id,
304 EmbedderControl::ColorPicker(color_picker) => color_picker.id,
305 EmbedderControl::FilePicker(file_picker) => file_picker.id,
306 EmbedderControl::InputMethod(input_method) => input_method.id,
307 EmbedderControl::SimpleDialog(simple_dialog) => simple_dialog.id(),
308 EmbedderControl::ContextMenu(context_menu) => context_menu.id,
309 }
310 }
311}
312
313pub struct ContextMenu {
315 pub(crate) id: EmbedderControlId,
316 pub(crate) position: DeviceIntRect,
317 pub(crate) items: Vec<ContextMenuItem>,
318 pub(crate) element_info: ContextMenuElementInformation,
319 pub(crate) response_sent: bool,
320 pub(crate) constellation_proxy: ConstellationProxy,
321}
322
323impl ContextMenu {
324 pub fn id(&self) -> EmbedderControlId {
326 self.id
327 }
328
329 pub fn position(&self) -> DeviceIntRect {
333 self.position
334 }
335
336 pub fn element_info(&self) -> &ContextMenuElementInformation {
339 &self.element_info
340 }
341
342 pub fn items(&self) -> &[ContextMenuItem] {
344 &self.items
345 }
346
347 pub fn select(mut self, action: ContextMenuAction) {
349 self.constellation_proxy
350 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
351 self.id,
352 EmbedderControlResponse::ContextMenu(Some(action)),
353 ));
354 self.response_sent = true;
355 }
356
357 pub fn dismiss(mut self) {
359 self.constellation_proxy
360 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
361 self.id,
362 EmbedderControlResponse::ContextMenu(None),
363 ));
364 self.response_sent = true;
365 }
366}
367
368impl Drop for ContextMenu {
369 fn drop(&mut self) {
370 if !self.response_sent {
371 self.constellation_proxy
372 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
373 self.id,
374 EmbedderControlResponse::ContextMenu(None),
375 ));
376 }
377 }
378}
379
380pub struct SelectElement {
382 pub(crate) id: EmbedderControlId,
383 pub(crate) options: Vec<SelectElementOptionOrOptgroup>,
384 pub(crate) selected_option: Option<usize>,
385 pub(crate) position: DeviceIntRect,
386 pub(crate) constellation_proxy: ConstellationProxy,
387 pub(crate) response_sent: bool,
388}
389
390impl SelectElement {
391 pub fn id(&self) -> EmbedderControlId {
393 self.id
394 }
395
396 pub fn position(&self) -> DeviceIntRect {
400 self.position
401 }
402
403 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
406 &self.options
407 }
408
409 pub fn select(&mut self, id: Option<usize>) {
414 self.selected_option = id;
415 }
416
417 pub fn selected_option(&self) -> Option<usize> {
418 self.selected_option
419 }
420
421 pub fn submit(mut self) {
423 self.response_sent = true;
424 self.constellation_proxy
425 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
426 self.id,
427 EmbedderControlResponse::SelectElement(self.selected_option()),
428 ));
429 }
430}
431
432impl Drop for SelectElement {
433 fn drop(&mut self) {
434 if !self.response_sent {
435 self.constellation_proxy
436 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
437 self.id,
438 EmbedderControlResponse::SelectElement(self.selected_option()),
439 ));
440 }
441 }
442}
443
444pub struct ColorPicker {
446 pub(crate) id: EmbedderControlId,
447 pub(crate) current_color: Option<RgbColor>,
448 pub(crate) position: DeviceIntRect,
449 pub(crate) constellation_proxy: ConstellationProxy,
450 pub(crate) response_sent: bool,
451}
452
453impl ColorPicker {
454 pub fn id(&self) -> EmbedderControlId {
456 self.id
457 }
458
459 pub fn position(&self) -> DeviceIntRect {
463 self.position
464 }
465
466 pub fn current_color(&self) -> Option<RgbColor> {
469 self.current_color
470 }
471
472 pub fn select(&mut self, color: Option<RgbColor>) {
473 self.current_color = color;
474 }
475
476 pub fn submit(mut self) {
478 self.response_sent = true;
479 self.constellation_proxy
480 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
481 self.id,
482 EmbedderControlResponse::ColorPicker(self.current_color),
483 ));
484 }
485}
486
487impl Drop for ColorPicker {
488 fn drop(&mut self) {
489 if !self.response_sent {
490 self.constellation_proxy
491 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
492 self.id,
493 EmbedderControlResponse::ColorPicker(self.current_color),
494 ));
495 }
496 }
497}
498
499pub struct FilePicker {
501 pub(crate) id: EmbedderControlId,
502 pub(crate) file_picker_request: FilePickerRequest,
503 pub(crate) response_sender: Option<Sender<Option<Vec<PathBuf>>>>,
504}
505
506impl FilePicker {
507 pub fn id(&self) -> EmbedderControlId {
509 self.id
510 }
511
512 pub fn filter_patterns(&self) -> &[FilterPattern] {
513 &self.file_picker_request.filter_patterns
514 }
515
516 pub fn allow_select_multiple(&self) -> bool {
517 self.file_picker_request.allow_select_multiple
518 }
519
520 pub fn current_paths(&self) -> &[PathBuf] {
523 &self.file_picker_request.current_paths
524 }
525
526 pub fn select(&mut self, paths: &[PathBuf]) {
527 self.file_picker_request.current_paths = paths.to_owned();
528 }
529
530 pub fn submit(mut self) {
532 if let Some(sender) = self.response_sender.take() {
533 let _ = sender.send(Some(std::mem::take(
534 &mut self.file_picker_request.current_paths,
535 )));
536 }
537 }
538
539 pub fn dismiss(mut self) {
541 if let Some(sender) = self.response_sender.take() {
542 let _ = sender.send(None);
543 }
544 }
545}
546
547impl Drop for FilePicker {
548 fn drop(&mut self) {
549 if let Some(sender) = self.response_sender.take() {
550 let _ = sender.send(None);
551 }
552 }
553}
554
555pub struct InputMethodControl {
557 pub(crate) id: EmbedderControlId,
558 pub(crate) input_method_type: InputMethodType,
559 pub(crate) text: String,
560 pub(crate) insertion_point: Option<u32>,
561 pub(crate) position: DeviceIntRect,
562 pub(crate) multiline: bool,
563 pub(crate) allow_virtual_keyboard: bool,
564}
565
566impl InputMethodControl {
567 pub fn input_method_type(&self) -> InputMethodType {
569 self.input_method_type
570 }
571
572 pub fn text(&self) -> String {
574 self.text.clone()
575 }
576
577 pub fn insertion_point(&self) -> Option<u32> {
580 self.insertion_point
581 }
582
583 pub fn position(&self) -> DeviceIntRect {
588 self.position
589 }
590
591 pub fn multiline(&self) -> bool {
593 self.multiline
594 }
595
596 pub fn allow_virtual_keyboard(&self) -> bool {
600 self.allow_virtual_keyboard
601 }
602}
603
604pub enum SimpleDialog {
608 Alert(AlertDialog),
609 Confirm(ConfirmDialog),
610 Prompt(PromptDialog),
611}
612
613impl SimpleDialog {
614 pub fn message(&self) -> &str {
615 match self {
616 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
617 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
618 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
619 }
620 }
621
622 pub fn confirm(self) {
623 match self {
624 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
625 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
626 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
627 }
628 }
629
630 pub fn dismiss(self) {
631 match self {
632 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
633 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
634 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
635 }
636 }
637}
638
639impl SimpleDialog {
640 fn id(&self) -> EmbedderControlId {
641 match self {
642 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
643 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
644 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
645 }
646 }
647}
648
649impl From<SimpleDialogRequest> for SimpleDialog {
650 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
651 match simple_dialog_request {
652 SimpleDialogRequest::Alert {
653 id,
654 message,
655 response_sender,
656 } => Self::Alert(AlertDialog {
657 id,
658 message,
659 response_sender,
660 response_sent: false,
661 }),
662 SimpleDialogRequest::Confirm {
663 id,
664 message,
665 response_sender,
666 } => Self::Confirm(ConfirmDialog {
667 id,
668 message,
669 response_sender,
670 response_sent: false,
671 }),
672 SimpleDialogRequest::Prompt {
673 id,
674 message,
675 default,
676 response_sender,
677 } => Self::Prompt(PromptDialog {
678 id,
679 message,
680 current_value: default,
681 response_sender,
682 response_sent: false,
683 }),
684 }
685 }
686}
687
688pub struct AlertDialog {
693 id: EmbedderControlId,
694 message: String,
695 response_sender: GenericSender<AlertResponse>,
696 response_sent: bool,
697}
698
699impl Drop for AlertDialog {
700 fn drop(&mut self) {
701 if !self.response_sent {
702 let _ = self.response_sender.send(AlertResponse::Ok);
703 }
704 }
705}
706
707impl AlertDialog {
708 pub fn message(&self) -> &str {
709 &self.message
710 }
711
712 pub fn confirm(self) {
714 }
716}
717
718pub struct ConfirmDialog {
724 id: EmbedderControlId,
725 message: String,
726 response_sender: GenericSender<ConfirmResponse>,
727 response_sent: bool,
728}
729
730impl ConfirmDialog {
731 pub fn message(&self) -> &str {
732 &self.message
733 }
734
735 pub fn dismiss(mut self) {
737 let _ = self.response_sender.send(ConfirmResponse::Cancel);
738 self.response_sent = true;
739 }
740
741 pub fn confirm(mut self) {
743 let _ = self.response_sender.send(ConfirmResponse::Ok);
744 self.response_sent = true;
745 }
746}
747
748impl Drop for ConfirmDialog {
749 fn drop(&mut self) {
750 if !self.response_sent {
751 let _ = self.response_sender.send(ConfirmResponse::Cancel);
752 }
753 }
754}
755
756pub struct PromptDialog {
765 id: EmbedderControlId,
766 message: String,
767 current_value: String,
768 response_sender: GenericSender<PromptResponse>,
769 response_sent: bool,
770}
771
772impl Drop for PromptDialog {
773 fn drop(&mut self) {
774 if !self.response_sent {
775 let _ = self.response_sender.send(PromptResponse::Cancel);
776 }
777 }
778}
779
780impl PromptDialog {
781 pub fn message(&self) -> &str {
782 &self.message
783 }
784
785 pub fn current_value(&self) -> &str {
786 &self.current_value
787 }
788
789 pub fn set_current_value(&mut self, new_value: &str) {
790 self.current_value = new_value.to_owned()
791 }
792
793 pub fn dismiss(mut self) {
795 let _ = self.response_sender.send(PromptResponse::Cancel);
796 self.response_sent = true;
797 }
798
799 pub fn confirm(mut self) {
802 let _ = self
803 .response_sender
804 .send(PromptResponse::Ok(self.current_value.clone()));
805 self.response_sent = true;
806 }
807}
808
809pub struct CreateNewWebViewRequest {
810 pub(crate) servo: Servo,
811 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
812}
813
814impl CreateNewWebViewRequest {
815 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
816 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
817 }
818}
819
820pub trait WebViewDelegate {
821 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
825 None
826 }
827 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
830 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
833 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
836 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
839 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
844 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
847 fn notify_cursor_changed(&self, _webview: WebView, _: Cursor) {}
850 fn notify_favicon_changed(&self, _webview: WebView) {}
853 fn notify_new_frame_ready(&self, _webview: WebView) {}
855 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
859 fn notify_traversal_complete(&self, _webview: WebView, _: TraversalId) {}
861 fn notify_closed(&self, _webview: WebView) {}
865
866 fn notify_input_event_handled(&self, _webview: WebView, _: InputEventId, _: InputEventResult) {}
870 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
872 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
875 fn notify_fullscreen_state_changed(&self, _webview: WebView, _: bool) {}
881
882 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
885 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
888 fn request_move_to(&self, _webview: WebView, _: DeviceIntPoint) {}
890 fn request_protocol_handler(
896 &self,
897 _webview: WebView,
898 _protocol_handler_registration: ProtocolHandlerRegistration,
899 _allow_deny_request: AllowOrDenyRequest,
900 ) {
901 }
902 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
908 fn request_create_new(&self, _parent_webview: WebView, _: CreateNewWebViewRequest) {}
928 fn request_permission(&self, _webview: WebView, _: PermissionRequest) {}
932
933 fn request_authentication(
934 &self,
935 _webview: WebView,
936 _authentication_request: AuthenticationRequest,
937 ) {
938 }
939
940 fn show_bluetooth_device_dialog(
943 &self,
944 _webview: WebView,
945 _: Vec<String>,
946 response_sender: GenericSender<Option<String>>,
947 ) {
948 let _ = response_sender.send(None);
949 }
950
951 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
954
955 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
960
961 #[cfg(feature = "gamepad")]
965 fn play_gamepad_haptic_effect(
966 &self,
967 _webview: WebView,
968 _: usize,
969 _: GamepadHapticEffectType,
970 _: Box<dyn FnOnce(bool)>,
971 ) {
972 }
973 #[cfg(feature = "gamepad")]
977 fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: Box<dyn FnOnce(bool)>) {}
978
979 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
987
988 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
990
991 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
994
995 fn notify_accessibility_tree_update(
997 &self,
998 _webview: WebView,
999 _tree_update: accesskit::TreeUpdate,
1000 ) {
1001 }
1002}
1003
1004pub(crate) struct DefaultWebViewDelegate;
1005impl WebViewDelegate for DefaultWebViewDelegate {}
1006
1007#[cfg(test)]
1008mod test {
1009 use super::*;
1010
1011 #[test]
1012 fn test_allow_deny_request() {
1013 use base::generic_channel;
1014
1015 use crate::responders::ServoErrorChannel;
1016
1017 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1018 let errors = ServoErrorChannel::default();
1020 let (sender, receiver) =
1021 generic_channel::channel().expect("Failed to create IPC channel");
1022 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1023 request.allow();
1024 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1025 assert_eq!(receiver.try_recv().ok(), None);
1026 assert!(errors.try_recv().is_none());
1027
1028 let errors = ServoErrorChannel::default();
1030 let (sender, receiver) =
1031 generic_channel::channel().expect("Failed to create IPC channel");
1032 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1033 request.deny();
1034 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1035 assert_eq!(receiver.try_recv().ok(), None);
1036 assert!(errors.try_recv().is_none());
1037
1038 let errors = ServoErrorChannel::default();
1040 let (sender, receiver) =
1041 generic_channel::channel().expect("Failed to create IPC channel");
1042 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1043 drop(request);
1044 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1045 assert_eq!(receiver.try_recv().ok(), None);
1046 assert!(errors.try_recv().is_none());
1047
1048 let errors = ServoErrorChannel::default();
1050 let (sender, receiver) =
1051 generic_channel::channel().expect("Failed to create IPC channel");
1052 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1053 drop(receiver);
1054 request.allow();
1055 assert!(errors.try_recv().is_some());
1056
1057 let errors = ServoErrorChannel::default();
1059 let (sender, receiver) =
1060 generic_channel::channel().expect("Failed to create IPC channel");
1061 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1062 drop(receiver);
1063 request.deny();
1064 assert!(errors.try_recv().is_some());
1065
1066 let errors = ServoErrorChannel::default();
1068 let (sender, receiver) =
1069 generic_channel::channel().expect("Failed to create IPC channel");
1070 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1071 drop(receiver);
1072 drop(request);
1073 assert!(errors.try_recv().is_none());
1074 }
1075 }
1076
1077 #[test]
1078 fn test_authentication_request() {
1079 use crate::responders::ServoErrorChannel;
1080
1081 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1082
1083 let errors = ServoErrorChannel::default();
1085 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1086 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1087 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1088 assert_eq!(
1089 receiver.try_recv().ok(),
1090 Some(Some(AuthenticationResponse {
1091 username: "diffie".to_owned(),
1092 password: "hunter2".to_owned(),
1093 }))
1094 );
1095 assert_eq!(receiver.try_recv().ok(), None);
1096 assert!(errors.try_recv().is_none());
1097
1098 let errors = ServoErrorChannel::default();
1100 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1101 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1102 drop(request);
1103 assert_eq!(receiver.try_recv().ok(), Some(None));
1104 assert_eq!(receiver.try_recv().ok(), None);
1105 assert!(errors.try_recv().is_none());
1106
1107 let errors = ServoErrorChannel::default();
1109 let (sender, receiver) = tokio::sync::oneshot::channel();
1110 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1111 drop(receiver);
1112 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1113 assert!(errors.try_recv().is_some());
1114
1115 let errors = ServoErrorChannel::default();
1117 let (sender, receiver) = tokio::sync::oneshot::channel();
1118 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1119 drop(receiver);
1120 drop(request);
1121 assert!(errors.try_recv().is_none());
1122 }
1123
1124 #[test]
1125 fn test_web_resource_load() {
1126 use http::{HeaderMap, Method, StatusCode};
1127
1128 use crate::responders::ServoErrorChannel;
1129
1130 let web_resource_request = || WebResourceRequest {
1131 method: Method::GET,
1132 headers: HeaderMap::default(),
1133 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1134 is_for_main_frame: false,
1135 is_redirect: false,
1136 };
1137 let web_resource_response = || {
1138 WebResourceResponse::new(
1139 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1140 )
1141 .status_code(StatusCode::IM_A_TEAPOT)
1142 };
1143
1144 let errors = ServoErrorChannel::default();
1146 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1147 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1148 request.intercept(web_resource_response()).cancel();
1149 assert!(matches!(
1150 receiver.try_recv(),
1151 Ok(WebResourceResponseMsg::Start(_))
1152 ));
1153 assert!(matches!(
1154 receiver.try_recv(),
1155 Ok(WebResourceResponseMsg::CancelLoad)
1156 ));
1157 assert!(matches!(receiver.try_recv(), Err(_)));
1158 assert!(errors.try_recv().is_none());
1159
1160 let errors = ServoErrorChannel::default();
1162 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1163 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1164 drop(request.intercept(web_resource_response()));
1165 assert!(matches!(
1166 receiver.try_recv(),
1167 Ok(WebResourceResponseMsg::Start(_))
1168 ));
1169 assert!(matches!(
1170 receiver.try_recv(),
1171 Ok(WebResourceResponseMsg::FinishLoad)
1172 ));
1173 assert!(matches!(receiver.try_recv(), Err(_)));
1174 assert!(errors.try_recv().is_none());
1175
1176 let errors = ServoErrorChannel::default();
1178 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1179 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1180 drop(request);
1181 assert!(matches!(
1182 receiver.try_recv(),
1183 Ok(WebResourceResponseMsg::DoNotIntercept)
1184 ));
1185 assert!(matches!(receiver.try_recv(), Err(_)));
1186 assert!(errors.try_recv().is_none());
1187
1188 let errors = ServoErrorChannel::default();
1190 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1191 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1192 drop(receiver);
1193 request.intercept(web_resource_response()).cancel();
1194 assert!(errors.try_recv().is_some());
1195
1196 let errors = ServoErrorChannel::default();
1198 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1199 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1200 drop(receiver);
1201 drop(request.intercept(web_resource_response()));
1202 assert!(errors.try_recv().is_some());
1203
1204 let errors = ServoErrorChannel::default();
1206 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1207 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1208 drop(receiver);
1209 drop(request);
1210 assert!(errors.try_recv().is_none());
1211 }
1212}