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}
564
565impl InputMethodControl {
566 pub fn input_method_type(&self) -> InputMethodType {
568 self.input_method_type
569 }
570
571 pub fn text(&self) -> String {
573 self.text.clone()
574 }
575
576 pub fn insertion_point(&self) -> Option<u32> {
579 self.insertion_point
580 }
581
582 pub fn position(&self) -> DeviceIntRect {
587 self.position
588 }
589
590 pub fn multiline(&self) -> bool {
592 self.multiline
593 }
594}
595
596pub enum SimpleDialog {
600 Alert(AlertDialog),
601 Confirm(ConfirmDialog),
602 Prompt(PromptDialog),
603}
604
605impl SimpleDialog {
606 pub fn message(&self) -> &str {
607 match self {
608 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
609 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
610 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
611 }
612 }
613
614 pub fn confirm(self) {
615 match self {
616 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
617 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
618 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
619 }
620 }
621
622 pub fn dismiss(self) {
623 match self {
624 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
625 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
626 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
627 }
628 }
629}
630
631impl SimpleDialog {
632 fn id(&self) -> EmbedderControlId {
633 match self {
634 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
635 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
636 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
637 }
638 }
639}
640
641impl From<SimpleDialogRequest> for SimpleDialog {
642 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
643 match simple_dialog_request {
644 SimpleDialogRequest::Alert {
645 id,
646 message,
647 response_sender,
648 } => Self::Alert(AlertDialog {
649 id,
650 message,
651 response_sender,
652 response_sent: false,
653 }),
654 SimpleDialogRequest::Confirm {
655 id,
656 message,
657 response_sender,
658 } => Self::Confirm(ConfirmDialog {
659 id,
660 message,
661 response_sender,
662 response_sent: false,
663 }),
664 SimpleDialogRequest::Prompt {
665 id,
666 message,
667 default,
668 response_sender,
669 } => Self::Prompt(PromptDialog {
670 id,
671 message,
672 current_value: default,
673 response_sender,
674 response_sent: false,
675 }),
676 }
677 }
678}
679
680pub struct AlertDialog {
685 id: EmbedderControlId,
686 message: String,
687 response_sender: GenericSender<AlertResponse>,
688 response_sent: bool,
689}
690
691impl Drop for AlertDialog {
692 fn drop(&mut self) {
693 if !self.response_sent {
694 let _ = self.response_sender.send(AlertResponse::Ok);
695 }
696 }
697}
698
699impl AlertDialog {
700 pub fn message(&self) -> &str {
701 &self.message
702 }
703
704 pub fn confirm(self) {
706 }
708}
709
710pub struct ConfirmDialog {
716 id: EmbedderControlId,
717 message: String,
718 response_sender: GenericSender<ConfirmResponse>,
719 response_sent: bool,
720}
721
722impl ConfirmDialog {
723 pub fn message(&self) -> &str {
724 &self.message
725 }
726
727 pub fn dismiss(mut self) {
729 let _ = self.response_sender.send(ConfirmResponse::Cancel);
730 self.response_sent = true;
731 }
732
733 pub fn confirm(mut self) {
735 let _ = self.response_sender.send(ConfirmResponse::Ok);
736 self.response_sent = true;
737 }
738}
739
740impl Drop for ConfirmDialog {
741 fn drop(&mut self) {
742 if !self.response_sent {
743 let _ = self.response_sender.send(ConfirmResponse::Cancel);
744 }
745 }
746}
747
748pub struct PromptDialog {
757 id: EmbedderControlId,
758 message: String,
759 current_value: String,
760 response_sender: GenericSender<PromptResponse>,
761 response_sent: bool,
762}
763
764impl Drop for PromptDialog {
765 fn drop(&mut self) {
766 if !self.response_sent {
767 let _ = self.response_sender.send(PromptResponse::Cancel);
768 }
769 }
770}
771
772impl PromptDialog {
773 pub fn message(&self) -> &str {
774 &self.message
775 }
776
777 pub fn current_value(&self) -> &str {
778 &self.current_value
779 }
780
781 pub fn set_current_value(&mut self, new_value: &str) {
782 self.current_value = new_value.to_owned()
783 }
784
785 pub fn dismiss(mut self) {
787 let _ = self.response_sender.send(PromptResponse::Cancel);
788 self.response_sent = true;
789 }
790
791 pub fn confirm(mut self) {
794 let _ = self
795 .response_sender
796 .send(PromptResponse::Ok(self.current_value.clone()));
797 self.response_sent = true;
798 }
799}
800
801pub struct CreateNewWebViewRequest {
802 pub(crate) servo: Servo,
803 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
804}
805
806impl CreateNewWebViewRequest {
807 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
808 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
809 }
810}
811
812pub trait WebViewDelegate {
813 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
817 None
818 }
819 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
822 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
825 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
828 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
831 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
836 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
839 fn notify_cursor_changed(&self, _webview: WebView, _: Cursor) {}
842 fn notify_favicon_changed(&self, _webview: WebView) {}
845 fn notify_new_frame_ready(&self, _webview: WebView) {}
847 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
851 fn notify_traversal_complete(&self, _webview: WebView, _: TraversalId) {}
853 fn notify_closed(&self, _webview: WebView) {}
857
858 fn notify_input_event_handled(&self, _webview: WebView, _: InputEventId, _: InputEventResult) {}
862 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
864 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
867 fn notify_fullscreen_state_changed(&self, _webview: WebView, _: bool) {}
873
874 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
877 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
880 fn request_move_to(&self, _webview: WebView, _: DeviceIntPoint) {}
882 fn request_protocol_handler(
888 &self,
889 _webview: WebView,
890 _protocol_handler_registration: ProtocolHandlerRegistration,
891 _allow_deny_request: AllowOrDenyRequest,
892 ) {
893 }
894 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
900 fn request_create_new(&self, _parent_webview: WebView, _: CreateNewWebViewRequest) {}
920 fn request_permission(&self, _webview: WebView, _: PermissionRequest) {}
924
925 fn request_authentication(
926 &self,
927 _webview: WebView,
928 _authentication_request: AuthenticationRequest,
929 ) {
930 }
931
932 fn show_bluetooth_device_dialog(
935 &self,
936 _webview: WebView,
937 _: Vec<String>,
938 response_sender: GenericSender<Option<String>>,
939 ) {
940 let _ = response_sender.send(None);
941 }
942
943 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
946
947 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
952
953 #[cfg(feature = "gamepad")]
957 fn play_gamepad_haptic_effect(
958 &self,
959 _webview: WebView,
960 _: usize,
961 _: GamepadHapticEffectType,
962 _: Box<dyn FnOnce(bool)>,
963 ) {
964 }
965 #[cfg(feature = "gamepad")]
969 fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: Box<dyn FnOnce(bool)>) {}
970
971 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
979
980 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
982
983 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
986
987 fn notify_accessibility_tree_update(
989 &self,
990 _webview: WebView,
991 _tree_update: accesskit::TreeUpdate,
992 ) {
993 }
994}
995
996pub(crate) struct DefaultWebViewDelegate;
997impl WebViewDelegate for DefaultWebViewDelegate {}
998
999#[cfg(test)]
1000mod test {
1001 use super::*;
1002
1003 #[test]
1004 fn test_allow_deny_request() {
1005 use base::generic_channel;
1006
1007 use crate::responders::ServoErrorChannel;
1008
1009 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1010 let errors = ServoErrorChannel::default();
1012 let (sender, receiver) =
1013 generic_channel::channel().expect("Failed to create IPC channel");
1014 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1015 request.allow();
1016 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1017 assert_eq!(receiver.try_recv().ok(), None);
1018 assert!(errors.try_recv().is_none());
1019
1020 let errors = ServoErrorChannel::default();
1022 let (sender, receiver) =
1023 generic_channel::channel().expect("Failed to create IPC channel");
1024 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1025 request.deny();
1026 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1027 assert_eq!(receiver.try_recv().ok(), None);
1028 assert!(errors.try_recv().is_none());
1029
1030 let errors = ServoErrorChannel::default();
1032 let (sender, receiver) =
1033 generic_channel::channel().expect("Failed to create IPC channel");
1034 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1035 drop(request);
1036 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1037 assert_eq!(receiver.try_recv().ok(), None);
1038 assert!(errors.try_recv().is_none());
1039
1040 let errors = ServoErrorChannel::default();
1042 let (sender, receiver) =
1043 generic_channel::channel().expect("Failed to create IPC channel");
1044 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1045 drop(receiver);
1046 request.allow();
1047 assert!(errors.try_recv().is_some());
1048
1049 let errors = ServoErrorChannel::default();
1051 let (sender, receiver) =
1052 generic_channel::channel().expect("Failed to create IPC channel");
1053 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1054 drop(receiver);
1055 request.deny();
1056 assert!(errors.try_recv().is_some());
1057
1058 let errors = ServoErrorChannel::default();
1060 let (sender, receiver) =
1061 generic_channel::channel().expect("Failed to create IPC channel");
1062 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1063 drop(receiver);
1064 drop(request);
1065 assert!(errors.try_recv().is_none());
1066 }
1067 }
1068
1069 #[test]
1070 fn test_authentication_request() {
1071 use crate::responders::ServoErrorChannel;
1072
1073 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1074
1075 let errors = ServoErrorChannel::default();
1077 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1078 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1079 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1080 assert_eq!(
1081 receiver.try_recv().ok(),
1082 Some(Some(AuthenticationResponse {
1083 username: "diffie".to_owned(),
1084 password: "hunter2".to_owned(),
1085 }))
1086 );
1087 assert_eq!(receiver.try_recv().ok(), None);
1088 assert!(errors.try_recv().is_none());
1089
1090 let errors = ServoErrorChannel::default();
1092 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1093 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1094 drop(request);
1095 assert_eq!(receiver.try_recv().ok(), Some(None));
1096 assert_eq!(receiver.try_recv().ok(), None);
1097 assert!(errors.try_recv().is_none());
1098
1099 let errors = ServoErrorChannel::default();
1101 let (sender, receiver) = tokio::sync::oneshot::channel();
1102 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1103 drop(receiver);
1104 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1105 assert!(errors.try_recv().is_some());
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 drop(request);
1113 assert!(errors.try_recv().is_none());
1114 }
1115
1116 #[test]
1117 fn test_web_resource_load() {
1118 use http::{HeaderMap, Method, StatusCode};
1119
1120 use crate::responders::ServoErrorChannel;
1121
1122 let web_resource_request = || WebResourceRequest {
1123 method: Method::GET,
1124 headers: HeaderMap::default(),
1125 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1126 is_for_main_frame: false,
1127 is_redirect: false,
1128 };
1129 let web_resource_response = || {
1130 WebResourceResponse::new(
1131 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1132 )
1133 .status_code(StatusCode::IM_A_TEAPOT)
1134 };
1135
1136 let errors = ServoErrorChannel::default();
1138 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1139 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1140 request.intercept(web_resource_response()).cancel();
1141 assert!(matches!(
1142 receiver.try_recv(),
1143 Ok(WebResourceResponseMsg::Start(_))
1144 ));
1145 assert!(matches!(
1146 receiver.try_recv(),
1147 Ok(WebResourceResponseMsg::CancelLoad)
1148 ));
1149 assert!(matches!(receiver.try_recv(), Err(_)));
1150 assert!(errors.try_recv().is_none());
1151
1152 let errors = ServoErrorChannel::default();
1154 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1155 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1156 drop(request.intercept(web_resource_response()));
1157 assert!(matches!(
1158 receiver.try_recv(),
1159 Ok(WebResourceResponseMsg::Start(_))
1160 ));
1161 assert!(matches!(
1162 receiver.try_recv(),
1163 Ok(WebResourceResponseMsg::FinishLoad)
1164 ));
1165 assert!(matches!(receiver.try_recv(), Err(_)));
1166 assert!(errors.try_recv().is_none());
1167
1168 let errors = ServoErrorChannel::default();
1170 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1171 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1172 drop(request);
1173 assert!(matches!(
1174 receiver.try_recv(),
1175 Ok(WebResourceResponseMsg::DoNotIntercept)
1176 ));
1177 assert!(matches!(receiver.try_recv(), Err(_)));
1178 assert!(errors.try_recv().is_none());
1179
1180 let errors = ServoErrorChannel::default();
1182 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1183 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1184 drop(receiver);
1185 request.intercept(web_resource_response()).cancel();
1186 assert!(errors.try_recv().is_some());
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 drop(request.intercept(web_resource_response()));
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);
1202 assert!(errors.try_recv().is_none());
1203 }
1204}