1use std::path::PathBuf;
6use std::rc::Rc;
7
8use embedder_traits::{
9 AlertResponse, AllowOrDeny, AuthenticationResponse, BluetoothDeviceDescription,
10 ConfirmResponse, ConsoleLogLevel, ContextMenuAction, ContextMenuElementInformation,
11 ContextMenuItem, Cursor, EmbedderControlId, EmbedderControlResponse, FilePickerRequest,
12 FilterPattern, InputEventId, InputEventResult, InputMethodType, LoadStatus, MediaSessionEvent,
13 NewWebViewDetails, Notification, PermissionFeature, PromptResponse, RgbColor, ScreenGeometry,
14 SelectElementOptionOrOptgroup, SelectElementRequest, SimpleDialogRequest, TraversalId,
15 WebResourceRequest, WebResourceResponse, WebResourceResponseMsg,
16};
17use paint_api::rendering_context::RenderingContext;
18use servo_base::generic_channel::{GenericCallback, GenericSender, SendError};
19use servo_base::id::PipelineId;
20use servo_constellation_traits::EmbedderToConstellationMessage;
21use tokio::sync::mpsc::UnboundedSender as TokioSender;
22use tokio::sync::oneshot::Sender;
23use url::Url;
24use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
25
26use crate::proxies::ConstellationProxy;
27use crate::responders::{IpcResponder, OneshotSender, ServoErrorSender};
28use crate::{RegisterOrUnregister, Servo, WebView, WebViewBuilder};
29
30pub struct NavigationRequest {
33 pub url: Url,
34 pub(crate) pipeline_id: PipelineId,
35 pub(crate) constellation_proxy: ConstellationProxy,
36 pub(crate) response_sent: bool,
37}
38
39impl NavigationRequest {
40 pub fn allow(mut self) {
41 self.constellation_proxy
42 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
43 self.pipeline_id,
44 true,
45 ));
46 self.response_sent = true;
47 }
48
49 pub fn deny(mut self) {
50 self.constellation_proxy
51 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
52 self.pipeline_id,
53 false,
54 ));
55 self.response_sent = true;
56 }
57}
58
59impl Drop for NavigationRequest {
60 fn drop(&mut self) {
61 if !self.response_sent {
62 self.constellation_proxy
63 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
64 self.pipeline_id,
65 true,
66 ));
67 }
68 }
69}
70
71pub struct PermissionRequest {
75 pub(crate) requested_feature: PermissionFeature,
76 pub(crate) allow_deny_request: AllowOrDenyRequest,
77}
78
79impl PermissionRequest {
80 pub fn feature(&self) -> PermissionFeature {
81 self.requested_feature
82 }
83
84 pub fn allow(self) {
85 self.allow_deny_request.allow();
86 }
87
88 pub fn deny(self) {
89 self.allow_deny_request.deny();
90 }
91}
92
93pub struct AllowOrDenyRequest(IpcResponder<AllowOrDeny>, ServoErrorSender);
94
95impl AllowOrDenyRequest {
96 pub(crate) fn new(
97 response_sender: GenericSender<AllowOrDeny>,
98 default_response: AllowOrDeny,
99 error_sender: ServoErrorSender,
100 ) -> Self {
101 Self(
102 IpcResponder::new(response_sender, default_response),
103 error_sender,
104 )
105 }
106
107 pub(crate) fn new_from_callback(
108 callback: GenericCallback<AllowOrDeny>,
109 default_response: AllowOrDeny,
110 error_sender: ServoErrorSender,
111 ) -> Self {
112 Self(
113 IpcResponder::new_same_process(Box::new(callback), default_response),
114 error_sender,
115 )
116 }
117
118 pub fn allow(mut self) {
119 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
120 self.1.raise_response_send_error(error);
121 }
122 }
123
124 pub fn deny(mut self) {
125 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
126 self.1.raise_response_send_error(error);
127 }
128 }
129}
130
131#[derive(Clone, Debug, Eq, PartialEq)]
132pub struct ProtocolHandlerRegistration {
133 pub scheme: String,
134 pub url: Url,
135 pub register_or_unregister: RegisterOrUnregister,
136}
137
138pub struct BluetoothDeviceSelectionRequest {
140 devices: Vec<BluetoothDeviceDescription>,
141 responder: IpcResponder<Option<String>>,
142}
143
144impl BluetoothDeviceSelectionRequest {
145 pub(crate) fn new(
146 devices: Vec<BluetoothDeviceDescription>,
147 responder: GenericSender<Option<String>>,
148 ) -> Self {
149 Self {
150 devices,
151 responder: IpcResponder::new(responder, None),
152 }
153 }
154
155 pub fn pick_device(mut self, device: &BluetoothDeviceDescription) -> Result<(), SendError> {
157 self.responder.send(Some(device.address.clone()))
158 }
159
160 pub fn cancel(mut self) -> Result<(), SendError> {
162 self.responder.send(None)
163 }
164
165 pub fn devices(&self) -> &Vec<BluetoothDeviceDescription> {
167 &self.devices
168 }
169}
170
171pub struct AuthenticationRequest {
175 pub(crate) url: Url,
176 pub(crate) for_proxy: bool,
177 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
178 pub(crate) error_sender: ServoErrorSender,
179}
180
181impl AuthenticationRequest {
182 pub(crate) fn new(
183 url: Url,
184 for_proxy: bool,
185 response_sender: Sender<Option<AuthenticationResponse>>,
186 error_sender: ServoErrorSender,
187 ) -> Self {
188 Self {
189 url,
190 for_proxy,
191 responder: IpcResponder::new_same_process(
192 Box::new(OneshotSender::from(response_sender)),
193 None,
194 ),
195 error_sender,
196 }
197 }
198
199 pub fn url(&self) -> &Url {
201 &self.url
202 }
203 pub fn for_proxy(&self) -> bool {
205 self.for_proxy
206 }
207 pub fn authenticate(mut self, username: String, password: String) {
209 if let Err(error) = self
210 .responder
211 .send(Some(AuthenticationResponse { username, password }))
212 {
213 self.error_sender.raise_response_send_error(error);
214 }
215 }
216}
217
218pub struct WebResourceLoad {
222 pub request: WebResourceRequest,
223 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
224 pub(crate) error_sender: ServoErrorSender,
225}
226
227impl WebResourceLoad {
228 pub(crate) fn new(
229 web_resource_request: WebResourceRequest,
230 response_sender: TokioSender<WebResourceResponseMsg>,
231 error_sender: ServoErrorSender,
232 ) -> Self {
233 Self {
234 request: web_resource_request,
235 responder: IpcResponder::new_same_process(
236 Box::new(response_sender),
237 WebResourceResponseMsg::DoNotIntercept,
238 ),
239 error_sender,
240 }
241 }
242
243 pub fn request(&self) -> &WebResourceRequest {
245 &self.request
246 }
247
248 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
251 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
252 self.error_sender.raise_response_send_error(error);
253 }
254 InterceptedWebResourceLoad {
255 request: self.request.clone(),
256 response_sender: self.responder,
257 finished: false,
258 error_sender: self.error_sender,
259 }
260 }
261}
262
263pub struct InterceptedWebResourceLoad {
269 pub request: WebResourceRequest,
270 pub(crate) response_sender: IpcResponder<WebResourceResponseMsg>,
271 pub(crate) finished: bool,
272 pub(crate) error_sender: ServoErrorSender,
273}
274
275impl InterceptedWebResourceLoad {
276 pub fn send_body_data(&mut self, data: Vec<u8>) {
279 if let Err(error) = self
280 .response_sender
281 .send(WebResourceResponseMsg::SendBodyData(data))
282 {
283 self.error_sender.raise_response_send_error(error);
284 }
285 }
286 pub fn finish(mut self) {
288 if let Err(error) = self
289 .response_sender
290 .send(WebResourceResponseMsg::FinishLoad)
291 {
292 self.error_sender.raise_response_send_error(error);
293 }
294 self.finished = true;
295 }
296 pub fn cancel(mut self) {
298 if let Err(error) = self
299 .response_sender
300 .send(WebResourceResponseMsg::CancelLoad)
301 {
302 self.error_sender.raise_response_send_error(error);
303 }
304 self.finished = true;
305 }
306}
307
308impl Drop for InterceptedWebResourceLoad {
309 fn drop(&mut self) {
310 if !self.finished &&
311 let Err(error) = self
312 .response_sender
313 .send(WebResourceResponseMsg::FinishLoad)
314 {
315 self.error_sender.raise_response_send_error(error);
316 }
317 }
318}
319
320pub enum EmbedderControl {
322 SelectElement(SelectElement),
324 ColorPicker(ColorPicker),
326 FilePicker(FilePicker),
328 InputMethod(InputMethodControl),
331 SimpleDialog(SimpleDialog),
336 ContextMenu(ContextMenu),
340}
341
342impl EmbedderControl {
343 pub fn id(&self) -> EmbedderControlId {
344 match self {
345 EmbedderControl::SelectElement(select_element) => select_element.id,
346 EmbedderControl::ColorPicker(color_picker) => color_picker.id,
347 EmbedderControl::FilePicker(file_picker) => file_picker.id,
348 EmbedderControl::InputMethod(input_method) => input_method.id,
349 EmbedderControl::SimpleDialog(simple_dialog) => simple_dialog.id(),
350 EmbedderControl::ContextMenu(context_menu) => context_menu.id,
351 }
352 }
353}
354
355pub struct ContextMenu {
357 pub(crate) id: EmbedderControlId,
358 pub(crate) position: DeviceIntRect,
359 pub(crate) items: Vec<ContextMenuItem>,
360 pub(crate) element_info: ContextMenuElementInformation,
361 pub(crate) response_sent: bool,
362 pub(crate) constellation_proxy: ConstellationProxy,
363}
364
365impl ContextMenu {
366 pub fn id(&self) -> EmbedderControlId {
368 self.id
369 }
370
371 pub fn position(&self) -> DeviceIntRect {
375 self.position
376 }
377
378 pub fn element_info(&self) -> &ContextMenuElementInformation {
381 &self.element_info
382 }
383
384 pub fn items(&self) -> &[ContextMenuItem] {
386 &self.items
387 }
388
389 pub fn select(mut self, action: ContextMenuAction) {
391 self.constellation_proxy
392 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
393 self.id,
394 EmbedderControlResponse::ContextMenu(Some(action)),
395 ));
396 self.response_sent = true;
397 }
398
399 pub fn dismiss(mut self) {
401 self.constellation_proxy
402 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
403 self.id,
404 EmbedderControlResponse::ContextMenu(None),
405 ));
406 self.response_sent = true;
407 }
408}
409
410impl Drop for ContextMenu {
411 fn drop(&mut self) {
412 if !self.response_sent {
413 self.constellation_proxy
414 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
415 self.id,
416 EmbedderControlResponse::ContextMenu(None),
417 ));
418 }
419 }
420}
421
422pub struct SelectElement {
424 pub(crate) id: EmbedderControlId,
425 pub(crate) position: DeviceIntRect,
426 pub(crate) constellation_proxy: ConstellationProxy,
427 pub(crate) select_element_request: SelectElementRequest,
428 pub(crate) response_sent: bool,
429}
430
431impl SelectElement {
432 pub fn id(&self) -> EmbedderControlId {
434 self.id
435 }
436
437 pub fn position(&self) -> DeviceIntRect {
441 self.position
442 }
443
444 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
447 &self.select_element_request.options
448 }
449
450 pub fn select(&mut self, selected_options: Vec<usize>) {
455 self.select_element_request.selected_options = selected_options
456 }
457
458 pub fn selected_options(&self) -> Vec<usize> {
459 self.select_element_request.selected_options.clone()
460 }
461
462 pub fn allow_select_multiple(&self) -> bool {
463 self.select_element_request.allow_select_multiple
464 }
465
466 pub fn submit(mut self) {
468 self.response_sent = true;
469 self.constellation_proxy
470 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
471 self.id,
472 EmbedderControlResponse::SelectElement(self.selected_options()),
473 ));
474 }
475}
476
477impl Drop for SelectElement {
478 fn drop(&mut self) {
479 if !self.response_sent {
480 self.constellation_proxy
481 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
482 self.id,
483 EmbedderControlResponse::SelectElement(self.selected_options()),
484 ));
485 }
486 }
487}
488
489pub struct ColorPicker {
491 pub(crate) id: EmbedderControlId,
492 pub(crate) current_color: Option<RgbColor>,
493 pub(crate) position: DeviceIntRect,
494 pub(crate) constellation_proxy: ConstellationProxy,
495 pub(crate) response_sent: bool,
496}
497
498impl ColorPicker {
499 pub fn id(&self) -> EmbedderControlId {
501 self.id
502 }
503
504 pub fn position(&self) -> DeviceIntRect {
508 self.position
509 }
510
511 pub fn current_color(&self) -> Option<RgbColor> {
514 self.current_color
515 }
516
517 pub fn select(&mut self, color: Option<RgbColor>) {
518 self.current_color = color;
519 }
520
521 pub fn submit(mut self) {
523 self.response_sent = true;
524 self.constellation_proxy
525 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
526 self.id,
527 EmbedderControlResponse::ColorPicker(self.current_color),
528 ));
529 }
530}
531
532impl Drop for ColorPicker {
533 fn drop(&mut self) {
534 if !self.response_sent {
535 self.constellation_proxy
536 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
537 self.id,
538 EmbedderControlResponse::ColorPicker(self.current_color),
539 ));
540 }
541 }
542}
543
544pub struct FilePicker {
546 pub(crate) id: EmbedderControlId,
547 pub(crate) file_picker_request: FilePickerRequest,
548 pub(crate) response_sender: Option<Sender<Option<Vec<PathBuf>>>>,
549}
550
551impl FilePicker {
552 pub fn id(&self) -> EmbedderControlId {
554 self.id
555 }
556
557 pub fn filter_patterns(&self) -> &[FilterPattern] {
558 &self.file_picker_request.filter_patterns
559 }
560
561 pub fn allow_select_multiple(&self) -> bool {
562 self.file_picker_request.allow_select_multiple
563 }
564
565 pub fn current_paths(&self) -> &[PathBuf] {
568 &self.file_picker_request.current_paths
569 }
570
571 pub fn select(&mut self, paths: &[PathBuf]) {
572 self.file_picker_request.current_paths = paths.to_owned();
573 }
574
575 pub fn submit(mut self) {
577 if let Some(sender) = self.response_sender.take() {
578 let _ = sender.send(Some(std::mem::take(
579 &mut self.file_picker_request.current_paths,
580 )));
581 }
582 }
583
584 pub fn dismiss(mut self) {
586 if let Some(sender) = self.response_sender.take() {
587 let _ = sender.send(None);
588 }
589 }
590}
591
592impl Drop for FilePicker {
593 fn drop(&mut self) {
594 if let Some(sender) = self.response_sender.take() {
595 let _ = sender.send(None);
596 }
597 }
598}
599
600pub struct InputMethodControl {
602 pub(crate) id: EmbedderControlId,
603 pub(crate) input_method_type: InputMethodType,
604 pub(crate) text: String,
605 pub(crate) insertion_point: Option<u32>,
606 pub(crate) position: DeviceIntRect,
607 pub(crate) multiline: bool,
608 pub(crate) allow_virtual_keyboard: bool,
609}
610
611impl InputMethodControl {
612 pub fn id(&self) -> EmbedderControlId {
614 self.id
615 }
616
617 pub fn input_method_type(&self) -> InputMethodType {
619 self.input_method_type
620 }
621
622 pub fn text(&self) -> String {
624 self.text.clone()
625 }
626
627 pub fn insertion_point(&self) -> Option<u32> {
630 self.insertion_point
631 }
632
633 pub fn position(&self) -> DeviceIntRect {
638 self.position
639 }
640
641 pub fn multiline(&self) -> bool {
643 self.multiline
644 }
645
646 pub fn allow_virtual_keyboard(&self) -> bool {
650 self.allow_virtual_keyboard
651 }
652}
653
654pub enum SimpleDialog {
658 Alert(AlertDialog),
659 Confirm(ConfirmDialog),
660 Prompt(PromptDialog),
661}
662
663impl SimpleDialog {
664 pub fn message(&self) -> &str {
665 match self {
666 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
667 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
668 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
669 }
670 }
671
672 pub fn confirm(self) {
673 match self {
674 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
675 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
676 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
677 }
678 }
679
680 pub fn dismiss(self) {
681 match self {
682 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
683 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
684 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
685 }
686 }
687}
688
689impl SimpleDialog {
690 fn id(&self) -> EmbedderControlId {
691 match self {
692 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
693 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
694 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
695 }
696 }
697}
698
699impl From<SimpleDialogRequest> for SimpleDialog {
700 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
701 match simple_dialog_request {
702 SimpleDialogRequest::Alert {
703 id,
704 message,
705 response_sender,
706 } => Self::Alert(AlertDialog {
707 id,
708 message,
709 response_sender,
710 response_sent: false,
711 }),
712 SimpleDialogRequest::Confirm {
713 id,
714 message,
715 response_sender,
716 } => Self::Confirm(ConfirmDialog {
717 id,
718 message,
719 response_sender,
720 response_sent: false,
721 }),
722 SimpleDialogRequest::Prompt {
723 id,
724 message,
725 default,
726 response_sender,
727 } => Self::Prompt(PromptDialog {
728 id,
729 message,
730 current_value: default,
731 response_sender,
732 response_sent: false,
733 }),
734 }
735 }
736}
737
738pub struct AlertDialog {
743 id: EmbedderControlId,
744 message: String,
745 response_sender: GenericSender<AlertResponse>,
746 response_sent: bool,
747}
748
749impl Drop for AlertDialog {
750 fn drop(&mut self) {
751 if !self.response_sent {
752 let _ = self.response_sender.send(AlertResponse::Ok);
753 }
754 }
755}
756
757impl AlertDialog {
758 pub fn message(&self) -> &str {
759 &self.message
760 }
761
762 pub fn confirm(self) {
764 }
766}
767
768pub struct ConfirmDialog {
774 id: EmbedderControlId,
775 message: String,
776 response_sender: GenericSender<ConfirmResponse>,
777 response_sent: bool,
778}
779
780impl ConfirmDialog {
781 pub fn message(&self) -> &str {
782 &self.message
783 }
784
785 pub fn dismiss(mut self) {
787 let _ = self.response_sender.send(ConfirmResponse::Cancel);
788 self.response_sent = true;
789 }
790
791 pub fn confirm(mut self) {
793 let _ = self.response_sender.send(ConfirmResponse::Ok);
794 self.response_sent = true;
795 }
796}
797
798impl Drop for ConfirmDialog {
799 fn drop(&mut self) {
800 if !self.response_sent {
801 let _ = self.response_sender.send(ConfirmResponse::Cancel);
802 }
803 }
804}
805
806pub struct PromptDialog {
815 id: EmbedderControlId,
816 message: String,
817 current_value: String,
818 response_sender: GenericSender<PromptResponse>,
819 response_sent: bool,
820}
821
822impl Drop for PromptDialog {
823 fn drop(&mut self) {
824 if !self.response_sent {
825 let _ = self.response_sender.send(PromptResponse::Cancel);
826 }
827 }
828}
829
830impl PromptDialog {
831 pub fn message(&self) -> &str {
832 &self.message
833 }
834
835 pub fn current_value(&self) -> &str {
836 &self.current_value
837 }
838
839 pub fn set_current_value(&mut self, new_value: &str) {
840 self.current_value = new_value.to_owned()
841 }
842
843 pub fn dismiss(mut self) {
845 let _ = self.response_sender.send(PromptResponse::Cancel);
846 self.response_sent = true;
847 }
848
849 pub fn confirm(mut self) {
852 let _ = self
853 .response_sender
854 .send(PromptResponse::Ok(self.current_value.clone()));
855 self.response_sent = true;
856 }
857}
858
859pub struct CreateNewWebViewRequest {
860 pub(crate) servo: Servo,
861 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
862}
863
864impl CreateNewWebViewRequest {
865 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
866 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
867 }
868}
869
870pub trait WebViewDelegate {
871 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
875 None
876 }
877 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
880 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
883 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
886 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
889 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
894 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
897 fn notify_cursor_changed(&self, _webview: WebView, _cursor: Cursor) {}
900 fn notify_favicon_changed(&self, _webview: WebView) {}
903 fn notify_new_frame_ready(&self, _webview: WebView) {}
905 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
909 fn notify_traversal_complete(&self, _webview: WebView, _traversal_id: TraversalId) {}
911 fn notify_closed(&self, _webview: WebView) {}
915
916 fn notify_input_event_handled(
920 &self,
921 _webview: WebView,
922 _event_id: InputEventId,
923 _result: InputEventResult,
924 ) {
925 }
926 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
928 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
931 fn notify_fullscreen_state_changed(&self, _webview: WebView, _is_fullscreen: bool) {}
937
938 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
941 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
944 fn request_move_to(&self, _webview: WebView, _point: DeviceIntPoint) {}
946 fn request_protocol_handler(
952 &self,
953 _webview: WebView,
954 _protocol_handler_registration: ProtocolHandlerRegistration,
955 _allow_deny_request: AllowOrDenyRequest,
956 ) {
957 }
958 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
964 fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {}
984 fn request_permission(&self, _webview: WebView, _request: PermissionRequest) {}
988
989 fn request_authentication(
990 &self,
991 _webview: WebView,
992 _authentication_request: AuthenticationRequest,
993 ) {
994 }
995
996 fn show_bluetooth_device_dialog(
998 &self,
999 _webview: WebView,
1000 _request: BluetoothDeviceSelectionRequest,
1001 ) {
1002 }
1003
1004 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
1007
1008 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
1013
1014 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
1022
1023 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
1025
1026 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
1029
1030 fn notify_accessibility_tree_update(
1037 &self,
1038 _webview: WebView,
1039 _tree_update: accesskit::TreeUpdate,
1040 ) {
1041 }
1042}
1043
1044pub(crate) struct DefaultWebViewDelegate;
1045impl WebViewDelegate for DefaultWebViewDelegate {}
1046
1047#[cfg(test)]
1048mod test {
1049 use super::*;
1050
1051 #[test]
1052 fn test_allow_deny_request() {
1053 use servo_base::generic_channel;
1054
1055 use crate::responders::ServoErrorChannel;
1056
1057 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
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 request.allow();
1064 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1065 assert_eq!(receiver.try_recv().ok(), None);
1066 assert!(errors.try_recv().is_none());
1067
1068 let errors = ServoErrorChannel::default();
1070 let (sender, receiver) =
1071 generic_channel::channel().expect("Failed to create IPC channel");
1072 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1073 request.deny();
1074 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1075 assert_eq!(receiver.try_recv().ok(), None);
1076 assert!(errors.try_recv().is_none());
1077
1078 let errors = ServoErrorChannel::default();
1080 let (sender, receiver) =
1081 generic_channel::channel().expect("Failed to create IPC channel");
1082 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1083 drop(request);
1084 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1085 assert_eq!(receiver.try_recv().ok(), None);
1086 assert!(errors.try_recv().is_none());
1087
1088 let errors = ServoErrorChannel::default();
1090 let (sender, receiver) =
1091 generic_channel::channel().expect("Failed to create IPC channel");
1092 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1093 drop(receiver);
1094 request.allow();
1095 assert!(errors.try_recv().is_some());
1096
1097 let errors = ServoErrorChannel::default();
1099 let (sender, receiver) =
1100 generic_channel::channel().expect("Failed to create IPC channel");
1101 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1102 drop(receiver);
1103 request.deny();
1104 assert!(errors.try_recv().is_some());
1105
1106 let errors = ServoErrorChannel::default();
1108 let (sender, receiver) =
1109 generic_channel::channel().expect("Failed to create IPC channel");
1110 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1111 drop(receiver);
1112 drop(request);
1113 assert!(errors.try_recv().is_none());
1114 }
1115 }
1116
1117 #[test]
1118 fn test_authentication_request() {
1119 use crate::responders::ServoErrorChannel;
1120
1121 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1122
1123 let errors = ServoErrorChannel::default();
1125 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1126 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1127 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1128 assert_eq!(
1129 receiver.try_recv().ok(),
1130 Some(Some(AuthenticationResponse {
1131 username: "diffie".to_owned(),
1132 password: "hunter2".to_owned(),
1133 }))
1134 );
1135 assert_eq!(receiver.try_recv().ok(), None);
1136 assert!(errors.try_recv().is_none());
1137
1138 let errors = ServoErrorChannel::default();
1140 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1141 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1142 drop(request);
1143 assert_eq!(receiver.try_recv().ok(), Some(None));
1144 assert_eq!(receiver.try_recv().ok(), None);
1145 assert!(errors.try_recv().is_none());
1146
1147 let errors = ServoErrorChannel::default();
1149 let (sender, receiver) = tokio::sync::oneshot::channel();
1150 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1151 drop(receiver);
1152 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1153 assert!(errors.try_recv().is_some());
1154
1155 let errors = ServoErrorChannel::default();
1157 let (sender, receiver) = tokio::sync::oneshot::channel();
1158 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1159 drop(receiver);
1160 drop(request);
1161 assert!(errors.try_recv().is_none());
1162 }
1163
1164 #[test]
1165 fn test_web_resource_load() {
1166 use http::{HeaderMap, Method, StatusCode};
1167
1168 use crate::responders::ServoErrorChannel;
1169
1170 let web_resource_request = || WebResourceRequest {
1171 method: Method::GET,
1172 headers: HeaderMap::default(),
1173 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1174 destination: content_security_policy::Destination::Document,
1175 referrer_url: None,
1176 is_for_main_frame: false,
1177 is_redirect: false,
1178 };
1179 let web_resource_response = || {
1180 WebResourceResponse::new(
1181 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1182 )
1183 .status_code(StatusCode::IM_A_TEAPOT)
1184 };
1185
1186 let errors = ServoErrorChannel::default();
1188 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1189 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1190 request.intercept(web_resource_response()).cancel();
1191 assert!(matches!(
1192 receiver.try_recv(),
1193 Ok(WebResourceResponseMsg::Start(_))
1194 ));
1195 assert!(matches!(
1196 receiver.try_recv(),
1197 Ok(WebResourceResponseMsg::CancelLoad)
1198 ));
1199 assert!(matches!(receiver.try_recv(), Err(_)));
1200 assert!(errors.try_recv().is_none());
1201
1202 let errors = ServoErrorChannel::default();
1204 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1205 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1206 drop(request.intercept(web_resource_response()));
1207 assert!(matches!(
1208 receiver.try_recv(),
1209 Ok(WebResourceResponseMsg::Start(_))
1210 ));
1211 assert!(matches!(
1212 receiver.try_recv(),
1213 Ok(WebResourceResponseMsg::FinishLoad)
1214 ));
1215 assert!(matches!(receiver.try_recv(), Err(_)));
1216 assert!(errors.try_recv().is_none());
1217
1218 let errors = ServoErrorChannel::default();
1220 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1221 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1222 drop(request);
1223 assert!(matches!(
1224 receiver.try_recv(),
1225 Ok(WebResourceResponseMsg::DoNotIntercept)
1226 ));
1227 assert!(matches!(receiver.try_recv(), Err(_)));
1228 assert!(errors.try_recv().is_none());
1229
1230 let errors = ServoErrorChannel::default();
1232 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1233 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1234 drop(receiver);
1235 request.intercept(web_resource_response()).cancel();
1236 assert!(errors.try_recv().is_some());
1237
1238 let errors = ServoErrorChannel::default();
1240 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1241 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1242 drop(receiver);
1243 drop(request.intercept(web_resource_response()));
1244 assert!(errors.try_recv().is_some());
1245
1246 let errors = ServoErrorChannel::default();
1248 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1249 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1250 drop(receiver);
1251 drop(request);
1252 assert!(errors.try_recv().is_none());
1253 }
1254}