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 if 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}
320
321pub enum EmbedderControl {
323 SelectElement(SelectElement),
325 ColorPicker(ColorPicker),
327 FilePicker(FilePicker),
329 InputMethod(InputMethodControl),
332 SimpleDialog(SimpleDialog),
337 ContextMenu(ContextMenu),
341}
342
343impl EmbedderControl {
344 pub fn id(&self) -> EmbedderControlId {
345 match self {
346 EmbedderControl::SelectElement(select_element) => select_element.id,
347 EmbedderControl::ColorPicker(color_picker) => color_picker.id,
348 EmbedderControl::FilePicker(file_picker) => file_picker.id,
349 EmbedderControl::InputMethod(input_method) => input_method.id,
350 EmbedderControl::SimpleDialog(simple_dialog) => simple_dialog.id(),
351 EmbedderControl::ContextMenu(context_menu) => context_menu.id,
352 }
353 }
354}
355
356pub struct ContextMenu {
358 pub(crate) id: EmbedderControlId,
359 pub(crate) position: DeviceIntRect,
360 pub(crate) items: Vec<ContextMenuItem>,
361 pub(crate) element_info: ContextMenuElementInformation,
362 pub(crate) response_sent: bool,
363 pub(crate) constellation_proxy: ConstellationProxy,
364}
365
366impl ContextMenu {
367 pub fn id(&self) -> EmbedderControlId {
369 self.id
370 }
371
372 pub fn position(&self) -> DeviceIntRect {
376 self.position
377 }
378
379 pub fn element_info(&self) -> &ContextMenuElementInformation {
382 &self.element_info
383 }
384
385 pub fn items(&self) -> &[ContextMenuItem] {
387 &self.items
388 }
389
390 pub fn select(mut self, action: ContextMenuAction) {
392 self.constellation_proxy
393 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
394 self.id,
395 EmbedderControlResponse::ContextMenu(Some(action)),
396 ));
397 self.response_sent = true;
398 }
399
400 pub fn dismiss(mut self) {
402 self.constellation_proxy
403 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
404 self.id,
405 EmbedderControlResponse::ContextMenu(None),
406 ));
407 self.response_sent = true;
408 }
409}
410
411impl Drop for ContextMenu {
412 fn drop(&mut self) {
413 if !self.response_sent {
414 self.constellation_proxy
415 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
416 self.id,
417 EmbedderControlResponse::ContextMenu(None),
418 ));
419 }
420 }
421}
422
423pub struct SelectElement {
425 pub(crate) id: EmbedderControlId,
426 pub(crate) position: DeviceIntRect,
427 pub(crate) constellation_proxy: ConstellationProxy,
428 pub(crate) select_element_request: SelectElementRequest,
429 pub(crate) response_sent: bool,
430}
431
432impl SelectElement {
433 pub fn id(&self) -> EmbedderControlId {
435 self.id
436 }
437
438 pub fn position(&self) -> DeviceIntRect {
442 self.position
443 }
444
445 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
448 &self.select_element_request.options
449 }
450
451 pub fn select(&mut self, selected_options: Vec<usize>) {
456 self.select_element_request.selected_options = selected_options
457 }
458
459 pub fn selected_options(&self) -> Vec<usize> {
460 self.select_element_request.selected_options.clone()
461 }
462
463 pub fn allow_select_multiple(&self) -> bool {
464 self.select_element_request.allow_select_multiple
465 }
466
467 pub fn submit(mut self) {
469 self.response_sent = true;
470 self.constellation_proxy
471 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
472 self.id,
473 EmbedderControlResponse::SelectElement(self.selected_options()),
474 ));
475 }
476}
477
478impl Drop for SelectElement {
479 fn drop(&mut self) {
480 if !self.response_sent {
481 self.constellation_proxy
482 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
483 self.id,
484 EmbedderControlResponse::SelectElement(self.selected_options()),
485 ));
486 }
487 }
488}
489
490pub struct ColorPicker {
492 pub(crate) id: EmbedderControlId,
493 pub(crate) current_color: Option<RgbColor>,
494 pub(crate) position: DeviceIntRect,
495 pub(crate) constellation_proxy: ConstellationProxy,
496 pub(crate) response_sent: bool,
497}
498
499impl ColorPicker {
500 pub fn id(&self) -> EmbedderControlId {
502 self.id
503 }
504
505 pub fn position(&self) -> DeviceIntRect {
509 self.position
510 }
511
512 pub fn current_color(&self) -> Option<RgbColor> {
515 self.current_color
516 }
517
518 pub fn select(&mut self, color: Option<RgbColor>) {
519 self.current_color = color;
520 }
521
522 pub fn submit(mut self) {
524 self.response_sent = true;
525 self.constellation_proxy
526 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
527 self.id,
528 EmbedderControlResponse::ColorPicker(self.current_color),
529 ));
530 }
531}
532
533impl Drop for ColorPicker {
534 fn drop(&mut self) {
535 if !self.response_sent {
536 self.constellation_proxy
537 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
538 self.id,
539 EmbedderControlResponse::ColorPicker(self.current_color),
540 ));
541 }
542 }
543}
544
545pub struct FilePicker {
547 pub(crate) id: EmbedderControlId,
548 pub(crate) file_picker_request: FilePickerRequest,
549 pub(crate) response_sender: Option<Sender<Option<Vec<PathBuf>>>>,
550}
551
552impl FilePicker {
553 pub fn id(&self) -> EmbedderControlId {
555 self.id
556 }
557
558 pub fn filter_patterns(&self) -> &[FilterPattern] {
559 &self.file_picker_request.filter_patterns
560 }
561
562 pub fn allow_select_multiple(&self) -> bool {
563 self.file_picker_request.allow_select_multiple
564 }
565
566 pub fn current_paths(&self) -> &[PathBuf] {
569 &self.file_picker_request.current_paths
570 }
571
572 pub fn select(&mut self, paths: &[PathBuf]) {
573 self.file_picker_request.current_paths = paths.to_owned();
574 }
575
576 pub fn submit(mut self) {
578 if let Some(sender) = self.response_sender.take() {
579 let _ = sender.send(Some(std::mem::take(
580 &mut self.file_picker_request.current_paths,
581 )));
582 }
583 }
584
585 pub fn dismiss(mut self) {
587 if let Some(sender) = self.response_sender.take() {
588 let _ = sender.send(None);
589 }
590 }
591}
592
593impl Drop for FilePicker {
594 fn drop(&mut self) {
595 if let Some(sender) = self.response_sender.take() {
596 let _ = sender.send(None);
597 }
598 }
599}
600
601pub struct InputMethodControl {
603 pub(crate) id: EmbedderControlId,
604 pub(crate) input_method_type: InputMethodType,
605 pub(crate) text: String,
606 pub(crate) insertion_point: Option<u32>,
607 pub(crate) position: DeviceIntRect,
608 pub(crate) multiline: bool,
609 pub(crate) allow_virtual_keyboard: bool,
610}
611
612impl InputMethodControl {
613 pub fn id(&self) -> EmbedderControlId {
615 self.id
616 }
617
618 pub fn input_method_type(&self) -> InputMethodType {
620 self.input_method_type
621 }
622
623 pub fn text(&self) -> String {
625 self.text.clone()
626 }
627
628 pub fn insertion_point(&self) -> Option<u32> {
631 self.insertion_point
632 }
633
634 pub fn position(&self) -> DeviceIntRect {
639 self.position
640 }
641
642 pub fn multiline(&self) -> bool {
644 self.multiline
645 }
646
647 pub fn allow_virtual_keyboard(&self) -> bool {
651 self.allow_virtual_keyboard
652 }
653}
654
655pub enum SimpleDialog {
659 Alert(AlertDialog),
660 Confirm(ConfirmDialog),
661 Prompt(PromptDialog),
662}
663
664impl SimpleDialog {
665 pub fn message(&self) -> &str {
666 match self {
667 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
668 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
669 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
670 }
671 }
672
673 pub fn confirm(self) {
674 match self {
675 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
676 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
677 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
678 }
679 }
680
681 pub fn dismiss(self) {
682 match self {
683 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
684 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
685 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
686 }
687 }
688}
689
690impl SimpleDialog {
691 fn id(&self) -> EmbedderControlId {
692 match self {
693 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
694 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
695 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
696 }
697 }
698}
699
700impl From<SimpleDialogRequest> for SimpleDialog {
701 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
702 match simple_dialog_request {
703 SimpleDialogRequest::Alert {
704 id,
705 message,
706 response_sender,
707 } => Self::Alert(AlertDialog {
708 id,
709 message,
710 response_sender,
711 response_sent: false,
712 }),
713 SimpleDialogRequest::Confirm {
714 id,
715 message,
716 response_sender,
717 } => Self::Confirm(ConfirmDialog {
718 id,
719 message,
720 response_sender,
721 response_sent: false,
722 }),
723 SimpleDialogRequest::Prompt {
724 id,
725 message,
726 default,
727 response_sender,
728 } => Self::Prompt(PromptDialog {
729 id,
730 message,
731 current_value: default,
732 response_sender,
733 response_sent: false,
734 }),
735 }
736 }
737}
738
739pub struct AlertDialog {
744 id: EmbedderControlId,
745 message: String,
746 response_sender: GenericSender<AlertResponse>,
747 response_sent: bool,
748}
749
750impl Drop for AlertDialog {
751 fn drop(&mut self) {
752 if !self.response_sent {
753 let _ = self.response_sender.send(AlertResponse::Ok);
754 }
755 }
756}
757
758impl AlertDialog {
759 pub fn message(&self) -> &str {
760 &self.message
761 }
762
763 pub fn confirm(self) {
765 }
767}
768
769pub struct ConfirmDialog {
775 id: EmbedderControlId,
776 message: String,
777 response_sender: GenericSender<ConfirmResponse>,
778 response_sent: bool,
779}
780
781impl ConfirmDialog {
782 pub fn message(&self) -> &str {
783 &self.message
784 }
785
786 pub fn dismiss(mut self) {
788 let _ = self.response_sender.send(ConfirmResponse::Cancel);
789 self.response_sent = true;
790 }
791
792 pub fn confirm(mut self) {
794 let _ = self.response_sender.send(ConfirmResponse::Ok);
795 self.response_sent = true;
796 }
797}
798
799impl Drop for ConfirmDialog {
800 fn drop(&mut self) {
801 if !self.response_sent {
802 let _ = self.response_sender.send(ConfirmResponse::Cancel);
803 }
804 }
805}
806
807pub struct PromptDialog {
816 id: EmbedderControlId,
817 message: String,
818 current_value: String,
819 response_sender: GenericSender<PromptResponse>,
820 response_sent: bool,
821}
822
823impl Drop for PromptDialog {
824 fn drop(&mut self) {
825 if !self.response_sent {
826 let _ = self.response_sender.send(PromptResponse::Cancel);
827 }
828 }
829}
830
831impl PromptDialog {
832 pub fn message(&self) -> &str {
833 &self.message
834 }
835
836 pub fn current_value(&self) -> &str {
837 &self.current_value
838 }
839
840 pub fn set_current_value(&mut self, new_value: &str) {
841 self.current_value = new_value.to_owned()
842 }
843
844 pub fn dismiss(mut self) {
846 let _ = self.response_sender.send(PromptResponse::Cancel);
847 self.response_sent = true;
848 }
849
850 pub fn confirm(mut self) {
853 let _ = self
854 .response_sender
855 .send(PromptResponse::Ok(self.current_value.clone()));
856 self.response_sent = true;
857 }
858}
859
860pub struct CreateNewWebViewRequest {
861 pub(crate) servo: Servo,
862 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
863}
864
865impl CreateNewWebViewRequest {
866 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
867 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
868 }
869}
870
871pub trait WebViewDelegate {
872 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
876 None
877 }
878 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
881 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
884 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
887 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
890 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
895 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
898 fn notify_cursor_changed(&self, _webview: WebView, _cursor: Cursor) {}
901 fn notify_favicon_changed(&self, _webview: WebView) {}
904 fn notify_new_frame_ready(&self, _webview: WebView) {}
906 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
910 fn notify_traversal_complete(&self, _webview: WebView, _traversal_id: TraversalId) {}
912 fn notify_closed(&self, _webview: WebView) {}
916
917 fn notify_input_event_handled(
921 &self,
922 _webview: WebView,
923 _event_id: InputEventId,
924 _result: InputEventResult,
925 ) {
926 }
927 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
929 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
932 fn notify_fullscreen_state_changed(&self, _webview: WebView, _is_fullscreen: bool) {}
938
939 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
942 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
945 fn request_move_to(&self, _webview: WebView, _point: DeviceIntPoint) {}
947 fn request_protocol_handler(
953 &self,
954 _webview: WebView,
955 _protocol_handler_registration: ProtocolHandlerRegistration,
956 _allow_deny_request: AllowOrDenyRequest,
957 ) {
958 }
959 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
965 fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {}
985 fn request_permission(&self, _webview: WebView, _request: PermissionRequest) {}
989
990 fn request_authentication(
991 &self,
992 _webview: WebView,
993 _authentication_request: AuthenticationRequest,
994 ) {
995 }
996
997 fn show_bluetooth_device_dialog(
999 &self,
1000 _webview: WebView,
1001 _request: BluetoothDeviceSelectionRequest,
1002 ) {
1003 }
1004
1005 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
1008
1009 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
1014
1015 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
1023
1024 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
1026
1027 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
1030
1031 fn notify_accessibility_tree_update(
1038 &self,
1039 _webview: WebView,
1040 _tree_update: accesskit::TreeUpdate,
1041 ) {
1042 }
1043}
1044
1045pub(crate) struct DefaultWebViewDelegate;
1046impl WebViewDelegate for DefaultWebViewDelegate {}
1047
1048#[cfg(test)]
1049mod test {
1050 use super::*;
1051
1052 #[test]
1053 fn test_allow_deny_request() {
1054 use servo_base::generic_channel;
1055
1056 use crate::responders::ServoErrorChannel;
1057
1058 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1059 let errors = ServoErrorChannel::default();
1061 let (sender, receiver) =
1062 generic_channel::channel().expect("Failed to create IPC channel");
1063 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1064 request.allow();
1065 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1066 assert_eq!(receiver.try_recv().ok(), None);
1067 assert!(errors.try_recv().is_none());
1068
1069 let errors = ServoErrorChannel::default();
1071 let (sender, receiver) =
1072 generic_channel::channel().expect("Failed to create IPC channel");
1073 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1074 request.deny();
1075 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1076 assert_eq!(receiver.try_recv().ok(), None);
1077 assert!(errors.try_recv().is_none());
1078
1079 let errors = ServoErrorChannel::default();
1081 let (sender, receiver) =
1082 generic_channel::channel().expect("Failed to create IPC channel");
1083 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1084 drop(request);
1085 assert_eq!(receiver.try_recv().ok(), Some(default_response));
1086 assert_eq!(receiver.try_recv().ok(), None);
1087 assert!(errors.try_recv().is_none());
1088
1089 let errors = ServoErrorChannel::default();
1091 let (sender, receiver) =
1092 generic_channel::channel().expect("Failed to create IPC channel");
1093 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1094 drop(receiver);
1095 request.allow();
1096 assert!(errors.try_recv().is_some());
1097
1098 let errors = ServoErrorChannel::default();
1100 let (sender, receiver) =
1101 generic_channel::channel().expect("Failed to create IPC channel");
1102 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1103 drop(receiver);
1104 request.deny();
1105 assert!(errors.try_recv().is_some());
1106
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 drop(receiver);
1113 drop(request);
1114 assert!(errors.try_recv().is_none());
1115 }
1116 }
1117
1118 #[test]
1119 fn test_authentication_request() {
1120 use crate::responders::ServoErrorChannel;
1121
1122 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1123
1124 let errors = ServoErrorChannel::default();
1126 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1127 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1128 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1129 assert_eq!(
1130 receiver.try_recv().ok(),
1131 Some(Some(AuthenticationResponse {
1132 username: "diffie".to_owned(),
1133 password: "hunter2".to_owned(),
1134 }))
1135 );
1136 assert_eq!(receiver.try_recv().ok(), None);
1137 assert!(errors.try_recv().is_none());
1138
1139 let errors = ServoErrorChannel::default();
1141 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1142 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1143 drop(request);
1144 assert_eq!(receiver.try_recv().ok(), Some(None));
1145 assert_eq!(receiver.try_recv().ok(), None);
1146 assert!(errors.try_recv().is_none());
1147
1148 let errors = ServoErrorChannel::default();
1150 let (sender, receiver) = tokio::sync::oneshot::channel();
1151 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1152 drop(receiver);
1153 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1154 assert!(errors.try_recv().is_some());
1155
1156 let errors = ServoErrorChannel::default();
1158 let (sender, receiver) = tokio::sync::oneshot::channel();
1159 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1160 drop(receiver);
1161 drop(request);
1162 assert!(errors.try_recv().is_none());
1163 }
1164
1165 #[test]
1166 fn test_web_resource_load() {
1167 use http::{HeaderMap, Method, StatusCode};
1168
1169 use crate::responders::ServoErrorChannel;
1170
1171 let web_resource_request = || WebResourceRequest {
1172 method: Method::GET,
1173 headers: HeaderMap::default(),
1174 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1175 is_for_main_frame: false,
1176 is_redirect: false,
1177 };
1178 let web_resource_response = || {
1179 WebResourceResponse::new(
1180 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1181 )
1182 .status_code(StatusCode::IM_A_TEAPOT)
1183 };
1184
1185 let errors = ServoErrorChannel::default();
1187 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1188 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1189 request.intercept(web_resource_response()).cancel();
1190 assert!(matches!(
1191 receiver.try_recv(),
1192 Ok(WebResourceResponseMsg::Start(_))
1193 ));
1194 assert!(matches!(
1195 receiver.try_recv(),
1196 Ok(WebResourceResponseMsg::CancelLoad)
1197 ));
1198 assert!(matches!(receiver.try_recv(), Err(_)));
1199 assert!(errors.try_recv().is_none());
1200
1201 let errors = ServoErrorChannel::default();
1203 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1204 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1205 drop(request.intercept(web_resource_response()));
1206 assert!(matches!(
1207 receiver.try_recv(),
1208 Ok(WebResourceResponseMsg::Start(_))
1209 ));
1210 assert!(matches!(
1211 receiver.try_recv(),
1212 Ok(WebResourceResponseMsg::FinishLoad)
1213 ));
1214 assert!(matches!(receiver.try_recv(), Err(_)));
1215 assert!(errors.try_recv().is_none());
1216
1217 let errors = ServoErrorChannel::default();
1219 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1220 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1221 drop(request);
1222 assert!(matches!(
1223 receiver.try_recv(),
1224 Ok(WebResourceResponseMsg::DoNotIntercept)
1225 ));
1226 assert!(matches!(receiver.try_recv(), Err(_)));
1227 assert!(errors.try_recv().is_none());
1228
1229 let errors = ServoErrorChannel::default();
1231 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1232 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1233 drop(receiver);
1234 request.intercept(web_resource_response()).cancel();
1235 assert!(errors.try_recv().is_some());
1236
1237 let errors = ServoErrorChannel::default();
1239 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1240 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1241 drop(receiver);
1242 drop(request.intercept(web_resource_response()));
1243 assert!(errors.try_recv().is_some());
1244
1245 let errors = ServoErrorChannel::default();
1247 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1248 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1249 drop(receiver);
1250 drop(request);
1251 assert!(errors.try_recv().is_none());
1252 }
1253}