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) {
42 self.constellation_proxy
43 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
44 self.pipeline_id,
45 true,
46 ));
47 self.response_sent = true;
48 }
49
50 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 {
84 self.requested_feature
85 }
86
87 pub fn allow(self) {
89 self.allow_deny_request.allow();
90 }
91
92 pub fn deny(self) {
94 self.allow_deny_request.deny();
95 }
96}
97
98pub struct AllowOrDenyRequest(IpcResponder<AllowOrDeny>, ServoErrorSender);
103
104impl AllowOrDenyRequest {
105 pub(crate) fn new(
106 response_sender: GenericSender<AllowOrDeny>,
107 default_response: AllowOrDeny,
108 error_sender: ServoErrorSender,
109 ) -> Self {
110 Self(
111 IpcResponder::new(response_sender, default_response),
112 error_sender,
113 )
114 }
115
116 pub(crate) fn new_from_callback(
117 callback: GenericCallback<AllowOrDeny>,
118 default_response: AllowOrDeny,
119 error_sender: ServoErrorSender,
120 ) -> Self {
121 Self(
122 IpcResponder::new_same_process(Box::new(callback), default_response),
123 error_sender,
124 )
125 }
126
127 pub fn allow(mut self) {
129 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
130 self.1.raise_response_send_error(error);
131 }
132 }
133
134 pub fn deny(mut self) {
136 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
137 self.1.raise_response_send_error(error);
138 }
139 }
140}
141
142#[derive(Clone, Debug, Eq, PartialEq)]
145pub struct ProtocolHandlerRegistration {
146 pub scheme: String,
148 pub url: Url,
152 pub register_or_unregister: RegisterOrUnregister,
155}
156
157pub struct BluetoothDeviceSelectionRequest {
159 devices: Vec<BluetoothDeviceDescription>,
160 responder: IpcResponder<Option<String>>,
161}
162
163impl BluetoothDeviceSelectionRequest {
164 pub(crate) fn new(
165 devices: Vec<BluetoothDeviceDescription>,
166 responder: GenericSender<Option<String>>,
167 ) -> Self {
168 Self {
169 devices,
170 responder: IpcResponder::new(responder, None),
171 }
172 }
173
174 pub fn pick_device(mut self, device: &BluetoothDeviceDescription) -> Result<(), SendError> {
176 self.responder.send(Some(device.address.clone()))
177 }
178
179 pub fn cancel(mut self) -> Result<(), SendError> {
181 self.responder.send(None)
182 }
183
184 pub fn devices(&self) -> &Vec<BluetoothDeviceDescription> {
186 &self.devices
187 }
188}
189
190pub struct AuthenticationRequest {
194 pub(crate) url: Url,
195 pub(crate) for_proxy: bool,
196 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
197 pub(crate) error_sender: ServoErrorSender,
198}
199
200impl AuthenticationRequest {
201 pub(crate) fn new(
202 url: Url,
203 for_proxy: bool,
204 response_sender: Sender<Option<AuthenticationResponse>>,
205 error_sender: ServoErrorSender,
206 ) -> Self {
207 Self {
208 url,
209 for_proxy,
210 responder: IpcResponder::new_same_process(
211 Box::new(OneshotSender::from(response_sender)),
212 None,
213 ),
214 error_sender,
215 }
216 }
217
218 pub fn url(&self) -> &Url {
220 &self.url
221 }
222 pub fn for_proxy(&self) -> bool {
224 self.for_proxy
225 }
226 pub fn authenticate(mut self, username: String, password: String) {
228 if let Err(error) = self
229 .responder
230 .send(Some(AuthenticationResponse { username, password }))
231 {
232 self.error_sender.raise_response_send_error(error);
233 }
234 }
235}
236
237pub struct WebResourceLoad {
241 pub request: WebResourceRequest,
242 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
243 pub(crate) error_sender: ServoErrorSender,
244}
245
246impl WebResourceLoad {
247 pub(crate) fn new(
248 web_resource_request: WebResourceRequest,
249 response_sender: TokioSender<WebResourceResponseMsg>,
250 error_sender: ServoErrorSender,
251 ) -> Self {
252 Self {
253 request: web_resource_request,
254 responder: IpcResponder::new_same_process(
255 Box::new(response_sender),
256 WebResourceResponseMsg::DoNotIntercept,
257 ),
258 error_sender,
259 }
260 }
261
262 pub fn request(&self) -> &WebResourceRequest {
264 &self.request
265 }
266
267 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
270 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
271 self.error_sender.raise_response_send_error(error);
272 }
273 InterceptedWebResourceLoad {
274 request: self.request.clone(),
275 response_sender: self.responder,
276 finished: false,
277 error_sender: self.error_sender,
278 }
279 }
280}
281
282pub struct InterceptedWebResourceLoad {
288 pub request: WebResourceRequest,
289 pub(crate) response_sender: IpcResponder<WebResourceResponseMsg>,
290 pub(crate) finished: bool,
291 pub(crate) error_sender: ServoErrorSender,
292}
293
294impl InterceptedWebResourceLoad {
295 pub fn send_body_data(&mut self, data: Vec<u8>) {
298 if let Err(error) = self
299 .response_sender
300 .send(WebResourceResponseMsg::SendBodyData(data))
301 {
302 self.error_sender.raise_response_send_error(error);
303 }
304 }
305 pub fn finish(mut self) {
307 if let Err(error) = self
308 .response_sender
309 .send(WebResourceResponseMsg::FinishLoad)
310 {
311 self.error_sender.raise_response_send_error(error);
312 }
313 self.finished = true;
314 }
315 pub fn cancel(mut self) {
317 if let Err(error) = self
318 .response_sender
319 .send(WebResourceResponseMsg::CancelLoad)
320 {
321 self.error_sender.raise_response_send_error(error);
322 }
323 self.finished = true;
324 }
325}
326
327impl Drop for InterceptedWebResourceLoad {
328 fn drop(&mut self) {
329 if !self.finished &&
330 let Err(error) = self
331 .response_sender
332 .send(WebResourceResponseMsg::FinishLoad)
333 {
334 self.error_sender.raise_response_send_error(error);
335 }
336 }
337}
338
339pub enum EmbedderControl {
341 SelectElement(SelectElement),
343 ColorPicker(ColorPicker),
345 FilePicker(FilePicker),
347 InputMethod(InputMethodControl),
350 SimpleDialog(SimpleDialog),
355 ContextMenu(ContextMenu),
359}
360
361impl EmbedderControl {
362 pub fn id(&self) -> EmbedderControlId {
364 match self {
365 EmbedderControl::SelectElement(select_element) => select_element.id,
366 EmbedderControl::ColorPicker(color_picker) => color_picker.id,
367 EmbedderControl::FilePicker(file_picker) => file_picker.id,
368 EmbedderControl::InputMethod(input_method) => input_method.id,
369 EmbedderControl::SimpleDialog(simple_dialog) => simple_dialog.id(),
370 EmbedderControl::ContextMenu(context_menu) => context_menu.id,
371 }
372 }
373}
374
375pub struct ContextMenu {
377 pub(crate) id: EmbedderControlId,
378 pub(crate) position: DeviceIntRect,
379 pub(crate) items: Vec<ContextMenuItem>,
380 pub(crate) element_info: ContextMenuElementInformation,
381 pub(crate) response_sent: bool,
382 pub(crate) constellation_proxy: ConstellationProxy,
383}
384
385impl ContextMenu {
386 pub fn id(&self) -> EmbedderControlId {
388 self.id
389 }
390
391 pub fn position(&self) -> DeviceIntRect {
395 self.position
396 }
397
398 pub fn element_info(&self) -> &ContextMenuElementInformation {
401 &self.element_info
402 }
403
404 pub fn items(&self) -> &[ContextMenuItem] {
406 &self.items
407 }
408
409 pub fn select(mut self, action: ContextMenuAction) {
411 self.constellation_proxy
412 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
413 self.id,
414 EmbedderControlResponse::ContextMenu(Some(action)),
415 ));
416 self.response_sent = true;
417 }
418
419 pub fn dismiss(mut self) {
421 self.constellation_proxy
422 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
423 self.id,
424 EmbedderControlResponse::ContextMenu(None),
425 ));
426 self.response_sent = true;
427 }
428}
429
430impl Drop for ContextMenu {
431 fn drop(&mut self) {
432 if !self.response_sent {
433 self.constellation_proxy
434 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
435 self.id,
436 EmbedderControlResponse::ContextMenu(None),
437 ));
438 }
439 }
440}
441
442pub struct SelectElement {
444 pub(crate) id: EmbedderControlId,
445 pub(crate) position: DeviceIntRect,
446 pub(crate) constellation_proxy: ConstellationProxy,
447 pub(crate) select_element_request: SelectElementRequest,
448 pub(crate) response_sent: bool,
449}
450
451impl SelectElement {
452 pub fn id(&self) -> EmbedderControlId {
454 self.id
455 }
456
457 pub fn position(&self) -> DeviceIntRect {
461 self.position
462 }
463
464 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
467 &self.select_element_request.options
468 }
469
470 pub fn select(&mut self, selected_options: Vec<usize>) {
477 self.select_element_request.selected_options = selected_options
478 }
479
480 pub fn selected_options(&self) -> Vec<usize> {
483 self.select_element_request.selected_options.clone()
484 }
485
486 pub fn allow_select_multiple(&self) -> bool {
488 self.select_element_request.allow_select_multiple
489 }
490
491 pub fn submit(mut self) {
493 self.response_sent = true;
494 self.constellation_proxy
495 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
496 self.id,
497 EmbedderControlResponse::SelectElement(self.selected_options()),
498 ));
499 }
500}
501
502impl Drop for SelectElement {
503 fn drop(&mut self) {
504 if !self.response_sent {
505 self.constellation_proxy
506 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
507 self.id,
508 EmbedderControlResponse::SelectElement(self.selected_options()),
509 ));
510 }
511 }
512}
513
514pub struct ColorPicker {
516 pub(crate) id: EmbedderControlId,
517 pub(crate) current_color: Option<RgbColor>,
518 pub(crate) position: DeviceIntRect,
519 pub(crate) constellation_proxy: ConstellationProxy,
520 pub(crate) response_sent: bool,
521}
522
523impl ColorPicker {
524 pub fn id(&self) -> EmbedderControlId {
526 self.id
527 }
528
529 pub fn position(&self) -> DeviceIntRect {
533 self.position
534 }
535
536 pub fn current_color(&self) -> Option<RgbColor> {
539 self.current_color
540 }
541
542 pub fn select(&mut self, color: Option<RgbColor>) {
545 self.current_color = color;
546 }
547
548 pub fn submit(mut self) {
550 self.response_sent = true;
551 self.constellation_proxy
552 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
553 self.id,
554 EmbedderControlResponse::ColorPicker(self.current_color),
555 ));
556 }
557}
558
559impl Drop for ColorPicker {
560 fn drop(&mut self) {
561 if !self.response_sent {
562 self.constellation_proxy
563 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
564 self.id,
565 EmbedderControlResponse::ColorPicker(self.current_color),
566 ));
567 }
568 }
569}
570
571pub struct FilePicker {
573 pub(crate) id: EmbedderControlId,
574 pub(crate) file_picker_request: FilePickerRequest,
575 pub(crate) response_sender: Option<Sender<Option<Vec<PathBuf>>>>,
576}
577
578impl FilePicker {
579 pub fn id(&self) -> EmbedderControlId {
581 self.id
582 }
583
584 pub fn filter_patterns(&self) -> &[FilterPattern] {
587 &self.file_picker_request.filter_patterns
588 }
589
590 pub fn allow_select_multiple(&self) -> bool {
592 self.file_picker_request.allow_select_multiple
593 }
594
595 pub fn current_paths(&self) -> &[PathBuf] {
598 &self.file_picker_request.current_paths
599 }
600
601 pub fn select(&mut self, paths: &[PathBuf]) {
603 self.file_picker_request.current_paths = paths.to_owned();
604 }
605
606 pub fn submit(mut self) {
608 if let Some(sender) = self.response_sender.take() {
609 let _ = sender.send(Some(std::mem::take(
610 &mut self.file_picker_request.current_paths,
611 )));
612 }
613 }
614
615 pub fn dismiss(mut self) {
617 if let Some(sender) = self.response_sender.take() {
618 let _ = sender.send(None);
619 }
620 }
621}
622
623impl Drop for FilePicker {
624 fn drop(&mut self) {
625 if let Some(sender) = self.response_sender.take() {
626 let _ = sender.send(None);
627 }
628 }
629}
630
631pub struct InputMethodControl {
633 pub(crate) id: EmbedderControlId,
634 pub(crate) input_method_type: InputMethodType,
635 pub(crate) text: String,
636 pub(crate) insertion_point: Option<u32>,
637 pub(crate) position: DeviceIntRect,
638 pub(crate) multiline: bool,
639 pub(crate) allow_virtual_keyboard: bool,
640}
641
642impl InputMethodControl {
643 pub fn id(&self) -> EmbedderControlId {
645 self.id
646 }
647
648 pub fn input_method_type(&self) -> InputMethodType {
650 self.input_method_type
651 }
652
653 pub fn text(&self) -> String {
655 self.text.clone()
656 }
657
658 pub fn insertion_point(&self) -> Option<u32> {
661 self.insertion_point
662 }
663
664 pub fn position(&self) -> DeviceIntRect {
669 self.position
670 }
671
672 pub fn multiline(&self) -> bool {
674 self.multiline
675 }
676
677 pub fn allow_virtual_keyboard(&self) -> bool {
681 self.allow_virtual_keyboard
682 }
683}
684
685pub enum SimpleDialog {
689 Alert(AlertDialog),
690 Confirm(ConfirmDialog),
691 Prompt(PromptDialog),
692}
693
694impl SimpleDialog {
695 #[doc(hidden)]
696 pub fn message(&self) -> &str {
697 match self {
698 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
699 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
700 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
701 }
702 }
703
704 #[doc(hidden)]
705 pub fn confirm(self) {
706 match self {
707 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
708 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
709 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
710 }
711 }
712
713 #[doc(hidden)]
714 pub fn dismiss(self) {
715 match self {
716 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
717 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
718 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
719 }
720 }
721}
722
723impl SimpleDialog {
724 fn id(&self) -> EmbedderControlId {
725 match self {
726 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
727 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
728 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
729 }
730 }
731}
732
733impl From<SimpleDialogRequest> for SimpleDialog {
734 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
735 match simple_dialog_request {
736 SimpleDialogRequest::Alert {
737 id,
738 message,
739 response_sender,
740 } => Self::Alert(AlertDialog {
741 id,
742 message,
743 response_sender,
744 response_sent: false,
745 }),
746 SimpleDialogRequest::Confirm {
747 id,
748 message,
749 response_sender,
750 } => Self::Confirm(ConfirmDialog {
751 id,
752 message,
753 response_sender,
754 response_sent: false,
755 }),
756 SimpleDialogRequest::Prompt {
757 id,
758 message,
759 default,
760 response_sender,
761 } => Self::Prompt(PromptDialog {
762 id,
763 message,
764 current_value: default,
765 response_sender,
766 response_sent: false,
767 }),
768 }
769 }
770}
771
772pub struct AlertDialog {
777 id: EmbedderControlId,
778 message: String,
779 response_sender: GenericSender<AlertResponse>,
780 response_sent: bool,
781}
782
783impl Drop for AlertDialog {
784 fn drop(&mut self) {
785 if !self.response_sent {
786 let _ = self.response_sender.send(AlertResponse::Ok);
787 }
788 }
789}
790
791impl AlertDialog {
792 pub fn message(&self) -> &str {
794 &self.message
795 }
796
797 pub fn confirm(self) {
799 }
801}
802
803pub struct ConfirmDialog {
809 id: EmbedderControlId,
810 message: String,
811 response_sender: GenericSender<ConfirmResponse>,
812 response_sent: bool,
813}
814
815impl ConfirmDialog {
816 pub fn message(&self) -> &str {
818 &self.message
819 }
820
821 pub fn dismiss(mut self) {
823 let _ = self.response_sender.send(ConfirmResponse::Cancel);
824 self.response_sent = true;
825 }
826
827 pub fn confirm(mut self) {
829 let _ = self.response_sender.send(ConfirmResponse::Ok);
830 self.response_sent = true;
831 }
832}
833
834impl Drop for ConfirmDialog {
835 fn drop(&mut self) {
836 if !self.response_sent {
837 let _ = self.response_sender.send(ConfirmResponse::Cancel);
838 }
839 }
840}
841
842pub struct PromptDialog {
851 id: EmbedderControlId,
852 message: String,
853 current_value: String,
854 response_sender: GenericSender<PromptResponse>,
855 response_sent: bool,
856}
857
858impl Drop for PromptDialog {
859 fn drop(&mut self) {
860 if !self.response_sent {
861 let _ = self.response_sender.send(PromptResponse::Cancel);
862 }
863 }
864}
865
866impl PromptDialog {
867 pub fn message(&self) -> &str {
869 &self.message
870 }
871
872 pub fn current_value(&self) -> &str {
874 &self.current_value
875 }
876
877 pub fn set_current_value(&mut self, new_value: &str) {
879 self.current_value = new_value.to_owned()
880 }
881
882 pub fn dismiss(mut self) {
884 let _ = self.response_sender.send(PromptResponse::Cancel);
885 self.response_sent = true;
886 }
887
888 pub fn confirm(mut self) {
891 let _ = self
892 .response_sender
893 .send(PromptResponse::Ok(self.current_value.clone()));
894 self.response_sent = true;
895 }
896}
897
898pub struct CreateNewWebViewRequest {
903 pub(crate) servo: Servo,
904 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
905}
906
907impl CreateNewWebViewRequest {
908 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
910 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
911 }
912}
913
914pub trait WebViewDelegate {
915 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
919 None
920 }
921 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
924 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
927 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
930 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
933 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
938 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
941 fn notify_cursor_changed(&self, _webview: WebView, _cursor: Cursor) {}
944 fn notify_favicon_changed(&self, _webview: WebView) {}
947 fn notify_new_frame_ready(&self, _webview: WebView) {}
949 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
953 fn notify_traversal_complete(&self, _webview: WebView, _traversal_id: TraversalId) {}
955 fn notify_closed(&self, _webview: WebView) {}
959
960 fn notify_input_event_handled(
964 &self,
965 _webview: WebView,
966 _event_id: InputEventId,
967 _result: InputEventResult,
968 ) {
969 }
970 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
972 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
975 fn notify_fullscreen_state_changed(&self, _webview: WebView, _is_fullscreen: bool) {}
981
982 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
985 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
988 fn request_move_to(&self, _webview: WebView, _point: DeviceIntPoint) {}
990 fn request_protocol_handler(
996 &self,
997 _webview: WebView,
998 _protocol_handler_registration: ProtocolHandlerRegistration,
999 _allow_deny_request: AllowOrDenyRequest,
1000 ) {
1001 }
1002 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
1008 fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {}
1028 fn request_permission(&self, _webview: WebView, _request: PermissionRequest) {}
1032
1033 fn request_authentication(
1035 &self,
1036 _webview: WebView,
1037 _authentication_request: AuthenticationRequest,
1038 ) {
1039 }
1040
1041 fn show_bluetooth_device_dialog(
1043 &self,
1044 _webview: WebView,
1045 _request: BluetoothDeviceSelectionRequest,
1046 ) {
1047 }
1048
1049 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
1052
1053 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
1058
1059 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
1067
1068 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
1070
1071 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
1074
1075 fn notify_accessibility_tree_update(
1082 &self,
1083 _webview: WebView,
1084 _tree_update: accesskit::TreeUpdate,
1085 ) {
1086 }
1087}
1088
1089pub(crate) struct DefaultWebViewDelegate;
1090impl WebViewDelegate for DefaultWebViewDelegate {}
1091
1092#[cfg(test)]
1093mod test {
1094 use super::*;
1095
1096 #[test]
1097 fn test_allow_deny_request() {
1098 use servo_base::generic_channel;
1099
1100 use crate::responders::ServoErrorChannel;
1101
1102 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1103 let errors = ServoErrorChannel::default();
1105 let (sender, receiver) =
1106 generic_channel::channel().expect("Failed to create IPC channel");
1107 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1108 request.allow();
1109 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1110 assert_eq!(receiver.try_recv().ok(), None);
1111 assert!(errors.try_recv().is_none());
1112
1113 let errors = ServoErrorChannel::default();
1115 let (sender, receiver) =
1116 generic_channel::channel().expect("Failed to create IPC channel");
1117 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1118 request.deny();
1119 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1120 assert_eq!(receiver.try_recv().ok(), None);
1121 assert!(errors.try_recv().is_none());
1122
1123 let errors = ServoErrorChannel::default();
1125 let (sender, receiver) =
1126 generic_channel::channel().expect("Failed to create IPC channel");
1127 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1128 drop(request);
1129 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1130 assert_eq!(receiver.try_recv().ok(), None);
1131 assert!(errors.try_recv().is_none());
1132
1133 let errors = ServoErrorChannel::default();
1135 let (sender, receiver) =
1136 generic_channel::channel().expect("Failed to create IPC channel");
1137 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1138 drop(receiver);
1139 request.allow();
1140 assert!(errors.try_recv().is_some());
1141
1142 let errors = ServoErrorChannel::default();
1144 let (sender, receiver) =
1145 generic_channel::channel().expect("Failed to create IPC channel");
1146 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1147 drop(receiver);
1148 request.deny();
1149 assert!(errors.try_recv().is_some());
1150
1151 let errors = ServoErrorChannel::default();
1153 let (sender, receiver) =
1154 generic_channel::channel().expect("Failed to create IPC channel");
1155 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1156 drop(receiver);
1157 drop(request);
1158 assert!(errors.try_recv().is_none());
1159 }
1160 }
1161
1162 #[test]
1163 fn test_authentication_request() {
1164 use crate::responders::ServoErrorChannel;
1165
1166 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1167
1168 let errors = ServoErrorChannel::default();
1170 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1171 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1172 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1173 assert_eq!(
1174 receiver.try_recv().ok(),
1175 Some(Some(AuthenticationResponse {
1176 username: "diffie".to_owned(),
1177 password: "hunter2".to_owned(),
1178 }))
1179 );
1180 assert_eq!(receiver.try_recv().ok(), None);
1181 assert!(errors.try_recv().is_none());
1182
1183 let errors = ServoErrorChannel::default();
1185 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1186 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1187 drop(request);
1188 assert_eq!(receiver.try_recv().ok(), Some(None));
1189 assert_eq!(receiver.try_recv().ok(), None);
1190 assert!(errors.try_recv().is_none());
1191
1192 let errors = ServoErrorChannel::default();
1194 let (sender, receiver) = tokio::sync::oneshot::channel();
1195 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1196 drop(receiver);
1197 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1198 assert!(errors.try_recv().is_some());
1199
1200 let errors = ServoErrorChannel::default();
1202 let (sender, receiver) = tokio::sync::oneshot::channel();
1203 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1204 drop(receiver);
1205 drop(request);
1206 assert!(errors.try_recv().is_none());
1207 }
1208
1209 #[test]
1210 fn test_web_resource_load() {
1211 use http::{HeaderMap, Method, StatusCode};
1212
1213 use crate::responders::ServoErrorChannel;
1214
1215 let web_resource_request = || WebResourceRequest {
1216 method: Method::GET,
1217 headers: HeaderMap::default(),
1218 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1219 destination: content_security_policy::Destination::Document,
1220 referrer_url: None,
1221 is_for_main_frame: false,
1222 is_redirect: false,
1223 };
1224 let web_resource_response = || {
1225 WebResourceResponse::new(
1226 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1227 )
1228 .status_code(StatusCode::IM_A_TEAPOT)
1229 };
1230
1231 let errors = ServoErrorChannel::default();
1233 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1234 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1235 request.intercept(web_resource_response()).cancel();
1236 assert!(matches!(
1237 receiver.try_recv(),
1238 Ok(WebResourceResponseMsg::Start(_))
1239 ));
1240 assert!(matches!(
1241 receiver.try_recv(),
1242 Ok(WebResourceResponseMsg::CancelLoad)
1243 ));
1244 assert!(matches!(receiver.try_recv(), Err(_)));
1245 assert!(errors.try_recv().is_none());
1246
1247 let errors = ServoErrorChannel::default();
1249 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1250 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1251 drop(request.intercept(web_resource_response()));
1252 assert!(matches!(
1253 receiver.try_recv(),
1254 Ok(WebResourceResponseMsg::Start(_))
1255 ));
1256 assert!(matches!(
1257 receiver.try_recv(),
1258 Ok(WebResourceResponseMsg::FinishLoad)
1259 ));
1260 assert!(matches!(receiver.try_recv(), Err(_)));
1261 assert!(errors.try_recv().is_none());
1262
1263 let errors = ServoErrorChannel::default();
1265 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1266 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1267 drop(request);
1268 assert!(matches!(
1269 receiver.try_recv(),
1270 Ok(WebResourceResponseMsg::DoNotIntercept)
1271 ));
1272 assert!(matches!(receiver.try_recv(), Err(_)));
1273 assert!(errors.try_recv().is_none());
1274
1275 let errors = ServoErrorChannel::default();
1277 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1278 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1279 drop(receiver);
1280 request.intercept(web_resource_response()).cancel();
1281 assert!(errors.try_recv().is_some());
1282
1283 let errors = ServoErrorChannel::default();
1285 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1286 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1287 drop(receiver);
1288 drop(request.intercept(web_resource_response()));
1289 assert!(errors.try_recv().is_some());
1290
1291 let errors = ServoErrorChannel::default();
1293 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1294 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1295 drop(receiver);
1296 drop(request);
1297 assert!(errors.try_recv().is_none());
1298 }
1299}