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 {
919 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
923 None
924 }
925 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
928 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
931 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
934 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
937 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
942 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
945 fn notify_cursor_changed(&self, _webview: WebView, _cursor: Cursor) {}
948 fn notify_favicon_changed(&self, _webview: WebView) {}
951 fn notify_new_frame_ready(&self, _webview: WebView) {}
953 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
957 fn notify_traversal_complete(&self, _webview: WebView, _traversal_id: TraversalId) {}
959 fn notify_closed(&self, _webview: WebView) {}
963
964 fn notify_input_event_handled(
968 &self,
969 _webview: WebView,
970 _event_id: InputEventId,
971 _result: InputEventResult,
972 ) {
973 }
974 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
976 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
979 fn notify_fullscreen_state_changed(&self, _webview: WebView, _is_fullscreen: bool) {}
985
986 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
989 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
992 fn request_move_to(&self, _webview: WebView, _point: DeviceIntPoint) {}
994 fn request_protocol_handler(
1000 &self,
1001 _webview: WebView,
1002 _protocol_handler_registration: ProtocolHandlerRegistration,
1003 _allow_deny_request: AllowOrDenyRequest,
1004 ) {
1005 }
1006 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
1012 fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {}
1032 fn request_permission(&self, _webview: WebView, _request: PermissionRequest) {}
1036
1037 fn request_authentication(
1039 &self,
1040 _webview: WebView,
1041 _authentication_request: AuthenticationRequest,
1042 ) {
1043 }
1044
1045 fn show_bluetooth_device_dialog(
1047 &self,
1048 _webview: WebView,
1049 _request: BluetoothDeviceSelectionRequest,
1050 ) {
1051 }
1052
1053 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
1056
1057 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
1062
1063 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
1071
1072 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
1074
1075 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
1078
1079 fn notify_accessibility_tree_update(
1086 &self,
1087 _webview: WebView,
1088 _tree_update: accesskit::TreeUpdate,
1089 ) {
1090 }
1091}
1092
1093pub(crate) struct DefaultWebViewDelegate;
1094impl WebViewDelegate for DefaultWebViewDelegate {}
1095
1096#[cfg(test)]
1097mod test {
1098 use super::*;
1099
1100 #[test]
1101 fn test_allow_deny_request() {
1102 use servo_base::generic_channel;
1103
1104 use crate::responders::ServoErrorChannel;
1105
1106 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1107 let errors = ServoErrorChannel::default();
1109 let (sender, receiver) =
1110 generic_channel::channel().expect("Failed to create IPC channel");
1111 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1112 request.allow();
1113 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1114 assert_eq!(receiver.try_recv().ok(), None);
1115 assert!(errors.try_recv().is_none());
1116
1117 let errors = ServoErrorChannel::default();
1119 let (sender, receiver) =
1120 generic_channel::channel().expect("Failed to create IPC channel");
1121 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1122 request.deny();
1123 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1124 assert_eq!(receiver.try_recv().ok(), None);
1125 assert!(errors.try_recv().is_none());
1126
1127 let errors = ServoErrorChannel::default();
1129 let (sender, receiver) =
1130 generic_channel::channel().expect("Failed to create IPC channel");
1131 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1132 drop(request);
1133 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1134 assert_eq!(receiver.try_recv().ok(), None);
1135 assert!(errors.try_recv().is_none());
1136
1137 let errors = ServoErrorChannel::default();
1139 let (sender, receiver) =
1140 generic_channel::channel().expect("Failed to create IPC channel");
1141 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1142 drop(receiver);
1143 request.allow();
1144 assert!(errors.try_recv().is_some());
1145
1146 let errors = ServoErrorChannel::default();
1148 let (sender, receiver) =
1149 generic_channel::channel().expect("Failed to create IPC channel");
1150 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1151 drop(receiver);
1152 request.deny();
1153 assert!(errors.try_recv().is_some());
1154
1155 let errors = ServoErrorChannel::default();
1157 let (sender, receiver) =
1158 generic_channel::channel().expect("Failed to create IPC channel");
1159 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1160 drop(receiver);
1161 drop(request);
1162 assert!(errors.try_recv().is_none());
1163 }
1164 }
1165
1166 #[test]
1167 fn test_authentication_request() {
1168 use crate::responders::ServoErrorChannel;
1169
1170 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1171
1172 let errors = ServoErrorChannel::default();
1174 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1175 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1176 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1177 assert_eq!(
1178 receiver.try_recv().ok(),
1179 Some(Some(AuthenticationResponse {
1180 username: "diffie".to_owned(),
1181 password: "hunter2".to_owned(),
1182 }))
1183 );
1184 assert_eq!(receiver.try_recv().ok(), None);
1185 assert!(errors.try_recv().is_none());
1186
1187 let errors = ServoErrorChannel::default();
1189 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1190 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1191 drop(request);
1192 assert_eq!(receiver.try_recv().ok(), Some(None));
1193 assert_eq!(receiver.try_recv().ok(), None);
1194 assert!(errors.try_recv().is_none());
1195
1196 let errors = ServoErrorChannel::default();
1198 let (sender, receiver) = tokio::sync::oneshot::channel();
1199 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1200 drop(receiver);
1201 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1202 assert!(errors.try_recv().is_some());
1203
1204 let errors = ServoErrorChannel::default();
1206 let (sender, receiver) = tokio::sync::oneshot::channel();
1207 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1208 drop(receiver);
1209 drop(request);
1210 assert!(errors.try_recv().is_none());
1211 }
1212
1213 #[test]
1214 fn test_web_resource_load() {
1215 use http::{HeaderMap, Method, StatusCode};
1216
1217 use crate::responders::ServoErrorChannel;
1218
1219 let web_resource_request = || WebResourceRequest {
1220 method: Method::GET,
1221 headers: HeaderMap::default(),
1222 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1223 destination: content_security_policy::Destination::Document,
1224 referrer_url: None,
1225 is_for_main_frame: false,
1226 is_redirect: false,
1227 };
1228 let web_resource_response = || {
1229 WebResourceResponse::new(
1230 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1231 )
1232 .status_code(StatusCode::IM_A_TEAPOT)
1233 };
1234
1235 let errors = ServoErrorChannel::default();
1237 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1238 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1239 request.intercept(web_resource_response()).cancel();
1240 assert!(matches!(
1241 receiver.try_recv(),
1242 Ok(WebResourceResponseMsg::Start(_))
1243 ));
1244 assert!(matches!(
1245 receiver.try_recv(),
1246 Ok(WebResourceResponseMsg::CancelLoad)
1247 ));
1248 assert!(matches!(receiver.try_recv(), Err(_)));
1249 assert!(errors.try_recv().is_none());
1250
1251 let errors = ServoErrorChannel::default();
1253 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1254 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1255 drop(request.intercept(web_resource_response()));
1256 assert!(matches!(
1257 receiver.try_recv(),
1258 Ok(WebResourceResponseMsg::Start(_))
1259 ));
1260 assert!(matches!(
1261 receiver.try_recv(),
1262 Ok(WebResourceResponseMsg::FinishLoad)
1263 ));
1264 assert!(matches!(receiver.try_recv(), Err(_)));
1265 assert!(errors.try_recv().is_none());
1266
1267 let errors = ServoErrorChannel::default();
1269 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1270 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1271 drop(request);
1272 assert!(matches!(
1273 receiver.try_recv(),
1274 Ok(WebResourceResponseMsg::DoNotIntercept)
1275 ));
1276 assert!(matches!(receiver.try_recv(), Err(_)));
1277 assert!(errors.try_recv().is_none());
1278
1279 let errors = ServoErrorChannel::default();
1281 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1282 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1283 drop(receiver);
1284 request.intercept(web_resource_response()).cancel();
1285 assert!(errors.try_recv().is_some());
1286
1287 let errors = ServoErrorChannel::default();
1289 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1290 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1291 drop(receiver);
1292 drop(request.intercept(web_resource_response()));
1293 assert!(errors.try_recv().is_some());
1294
1295 let errors = ServoErrorChannel::default();
1297 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1298 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1299 drop(receiver);
1300 drop(request);
1301 assert!(errors.try_recv().is_none());
1302 }
1303}