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);
98
99impl AllowOrDenyRequest {
100 pub(crate) fn new(
101 response_sender: GenericSender<AllowOrDeny>,
102 default_response: AllowOrDeny,
103 error_sender: ServoErrorSender,
104 ) -> Self {
105 Self(
106 IpcResponder::new(response_sender, default_response),
107 error_sender,
108 )
109 }
110
111 pub(crate) fn new_from_callback(
112 callback: GenericCallback<AllowOrDeny>,
113 default_response: AllowOrDeny,
114 error_sender: ServoErrorSender,
115 ) -> Self {
116 Self(
117 IpcResponder::new_same_process(Box::new(callback), default_response),
118 error_sender,
119 )
120 }
121
122 pub fn allow(mut self) {
124 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
125 self.1.raise_response_send_error(error);
126 }
127 }
128
129 pub fn deny(mut self) {
131 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
132 self.1.raise_response_send_error(error);
133 }
134 }
135}
136
137#[derive(Clone, Debug, Eq, PartialEq)]
140pub struct ProtocolHandlerRegistration {
141 pub scheme: String,
143 pub url: Url,
147 pub register_or_unregister: RegisterOrUnregister,
150}
151
152pub struct BluetoothDeviceSelectionRequest {
154 devices: Vec<BluetoothDeviceDescription>,
155 responder: IpcResponder<Option<String>>,
156}
157
158impl BluetoothDeviceSelectionRequest {
159 pub(crate) fn new(
160 devices: Vec<BluetoothDeviceDescription>,
161 responder: GenericSender<Option<String>>,
162 ) -> Self {
163 Self {
164 devices,
165 responder: IpcResponder::new(responder, None),
166 }
167 }
168
169 pub fn pick_device(mut self, device: &BluetoothDeviceDescription) -> Result<(), SendError> {
171 self.responder.send(Some(device.address.clone()))
172 }
173
174 pub fn cancel(mut self) -> Result<(), SendError> {
176 self.responder.send(None)
177 }
178
179 pub fn devices(&self) -> &Vec<BluetoothDeviceDescription> {
181 &self.devices
182 }
183}
184
185pub struct AuthenticationRequest {
189 pub(crate) url: Url,
190 pub(crate) for_proxy: bool,
191 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
192 pub(crate) error_sender: ServoErrorSender,
193}
194
195impl AuthenticationRequest {
196 pub(crate) fn new(
197 url: Url,
198 for_proxy: bool,
199 response_sender: Sender<Option<AuthenticationResponse>>,
200 error_sender: ServoErrorSender,
201 ) -> Self {
202 Self {
203 url,
204 for_proxy,
205 responder: IpcResponder::new_same_process(
206 Box::new(OneshotSender::from(response_sender)),
207 None,
208 ),
209 error_sender,
210 }
211 }
212
213 pub fn url(&self) -> &Url {
215 &self.url
216 }
217 pub fn for_proxy(&self) -> bool {
219 self.for_proxy
220 }
221 pub fn authenticate(mut self, username: String, password: String) {
223 if let Err(error) = self
224 .responder
225 .send(Some(AuthenticationResponse { username, password }))
226 {
227 self.error_sender.raise_response_send_error(error);
228 }
229 }
230}
231
232pub struct WebResourceLoad {
236 pub request: WebResourceRequest,
237 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
238 pub(crate) error_sender: ServoErrorSender,
239}
240
241impl WebResourceLoad {
242 pub(crate) fn new(
243 web_resource_request: WebResourceRequest,
244 response_sender: TokioSender<WebResourceResponseMsg>,
245 error_sender: ServoErrorSender,
246 ) -> Self {
247 Self {
248 request: web_resource_request,
249 responder: IpcResponder::new_same_process(
250 Box::new(response_sender),
251 WebResourceResponseMsg::DoNotIntercept,
252 ),
253 error_sender,
254 }
255 }
256
257 pub fn request(&self) -> &WebResourceRequest {
259 &self.request
260 }
261
262 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
265 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
266 self.error_sender.raise_response_send_error(error);
267 }
268 InterceptedWebResourceLoad {
269 request: self.request.clone(),
270 response_sender: self.responder,
271 finished: false,
272 error_sender: self.error_sender,
273 }
274 }
275}
276
277pub struct InterceptedWebResourceLoad {
283 pub request: WebResourceRequest,
284 pub(crate) response_sender: IpcResponder<WebResourceResponseMsg>,
285 pub(crate) finished: bool,
286 pub(crate) error_sender: ServoErrorSender,
287}
288
289impl InterceptedWebResourceLoad {
290 pub fn send_body_data(&mut self, data: Vec<u8>) {
293 if let Err(error) = self
294 .response_sender
295 .send(WebResourceResponseMsg::SendBodyData(data))
296 {
297 self.error_sender.raise_response_send_error(error);
298 }
299 }
300 pub fn finish(mut self) {
302 if let Err(error) = self
303 .response_sender
304 .send(WebResourceResponseMsg::FinishLoad)
305 {
306 self.error_sender.raise_response_send_error(error);
307 }
308 self.finished = true;
309 }
310 pub fn cancel(mut self) {
312 if let Err(error) = self
313 .response_sender
314 .send(WebResourceResponseMsg::CancelLoad)
315 {
316 self.error_sender.raise_response_send_error(error);
317 }
318 self.finished = true;
319 }
320}
321
322impl Drop for InterceptedWebResourceLoad {
323 fn drop(&mut self) {
324 if !self.finished &&
325 let Err(error) = self
326 .response_sender
327 .send(WebResourceResponseMsg::FinishLoad)
328 {
329 self.error_sender.raise_response_send_error(error);
330 }
331 }
332}
333
334pub enum EmbedderControl {
336 SelectElement(SelectElement),
338 ColorPicker(ColorPicker),
340 FilePicker(FilePicker),
342 InputMethod(InputMethodControl),
345 SimpleDialog(SimpleDialog),
350 ContextMenu(ContextMenu),
354}
355
356impl EmbedderControl {
357 pub fn id(&self) -> EmbedderControlId {
358 match self {
359 EmbedderControl::SelectElement(select_element) => select_element.id,
360 EmbedderControl::ColorPicker(color_picker) => color_picker.id,
361 EmbedderControl::FilePicker(file_picker) => file_picker.id,
362 EmbedderControl::InputMethod(input_method) => input_method.id,
363 EmbedderControl::SimpleDialog(simple_dialog) => simple_dialog.id(),
364 EmbedderControl::ContextMenu(context_menu) => context_menu.id,
365 }
366 }
367}
368
369pub struct ContextMenu {
371 pub(crate) id: EmbedderControlId,
372 pub(crate) position: DeviceIntRect,
373 pub(crate) items: Vec<ContextMenuItem>,
374 pub(crate) element_info: ContextMenuElementInformation,
375 pub(crate) response_sent: bool,
376 pub(crate) constellation_proxy: ConstellationProxy,
377}
378
379impl ContextMenu {
380 pub fn id(&self) -> EmbedderControlId {
382 self.id
383 }
384
385 pub fn position(&self) -> DeviceIntRect {
389 self.position
390 }
391
392 pub fn element_info(&self) -> &ContextMenuElementInformation {
395 &self.element_info
396 }
397
398 pub fn items(&self) -> &[ContextMenuItem] {
400 &self.items
401 }
402
403 pub fn select(mut self, action: ContextMenuAction) {
405 self.constellation_proxy
406 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
407 self.id,
408 EmbedderControlResponse::ContextMenu(Some(action)),
409 ));
410 self.response_sent = true;
411 }
412
413 pub fn dismiss(mut self) {
415 self.constellation_proxy
416 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
417 self.id,
418 EmbedderControlResponse::ContextMenu(None),
419 ));
420 self.response_sent = true;
421 }
422}
423
424impl Drop for ContextMenu {
425 fn drop(&mut self) {
426 if !self.response_sent {
427 self.constellation_proxy
428 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
429 self.id,
430 EmbedderControlResponse::ContextMenu(None),
431 ));
432 }
433 }
434}
435
436pub struct SelectElement {
438 pub(crate) id: EmbedderControlId,
439 pub(crate) position: DeviceIntRect,
440 pub(crate) constellation_proxy: ConstellationProxy,
441 pub(crate) select_element_request: SelectElementRequest,
442 pub(crate) response_sent: bool,
443}
444
445impl SelectElement {
446 pub fn id(&self) -> EmbedderControlId {
448 self.id
449 }
450
451 pub fn position(&self) -> DeviceIntRect {
455 self.position
456 }
457
458 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
461 &self.select_element_request.options
462 }
463
464 pub fn select(&mut self, selected_options: Vec<usize>) {
471 self.select_element_request.selected_options = selected_options
472 }
473
474 pub fn selected_options(&self) -> Vec<usize> {
477 self.select_element_request.selected_options.clone()
478 }
479
480 pub fn allow_select_multiple(&self) -> bool {
482 self.select_element_request.allow_select_multiple
483 }
484
485 pub fn submit(mut self) {
487 self.response_sent = true;
488 self.constellation_proxy
489 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
490 self.id,
491 EmbedderControlResponse::SelectElement(self.selected_options()),
492 ));
493 }
494}
495
496impl Drop for SelectElement {
497 fn drop(&mut self) {
498 if !self.response_sent {
499 self.constellation_proxy
500 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
501 self.id,
502 EmbedderControlResponse::SelectElement(self.selected_options()),
503 ));
504 }
505 }
506}
507
508pub struct ColorPicker {
510 pub(crate) id: EmbedderControlId,
511 pub(crate) current_color: Option<RgbColor>,
512 pub(crate) position: DeviceIntRect,
513 pub(crate) constellation_proxy: ConstellationProxy,
514 pub(crate) response_sent: bool,
515}
516
517impl ColorPicker {
518 pub fn id(&self) -> EmbedderControlId {
520 self.id
521 }
522
523 pub fn position(&self) -> DeviceIntRect {
527 self.position
528 }
529
530 pub fn current_color(&self) -> Option<RgbColor> {
533 self.current_color
534 }
535
536 pub fn select(&mut self, color: Option<RgbColor>) {
537 self.current_color = color;
538 }
539
540 pub fn submit(mut self) {
542 self.response_sent = true;
543 self.constellation_proxy
544 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
545 self.id,
546 EmbedderControlResponse::ColorPicker(self.current_color),
547 ));
548 }
549}
550
551impl Drop for ColorPicker {
552 fn drop(&mut self) {
553 if !self.response_sent {
554 self.constellation_proxy
555 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
556 self.id,
557 EmbedderControlResponse::ColorPicker(self.current_color),
558 ));
559 }
560 }
561}
562
563pub struct FilePicker {
565 pub(crate) id: EmbedderControlId,
566 pub(crate) file_picker_request: FilePickerRequest,
567 pub(crate) response_sender: Option<Sender<Option<Vec<PathBuf>>>>,
568}
569
570impl FilePicker {
571 pub fn id(&self) -> EmbedderControlId {
573 self.id
574 }
575
576 pub fn filter_patterns(&self) -> &[FilterPattern] {
577 &self.file_picker_request.filter_patterns
578 }
579
580 pub fn allow_select_multiple(&self) -> bool {
581 self.file_picker_request.allow_select_multiple
582 }
583
584 pub fn current_paths(&self) -> &[PathBuf] {
587 &self.file_picker_request.current_paths
588 }
589
590 pub fn select(&mut self, paths: &[PathBuf]) {
591 self.file_picker_request.current_paths = paths.to_owned();
592 }
593
594 pub fn submit(mut self) {
596 if let Some(sender) = self.response_sender.take() {
597 let _ = sender.send(Some(std::mem::take(
598 &mut self.file_picker_request.current_paths,
599 )));
600 }
601 }
602
603 pub fn dismiss(mut self) {
605 if let Some(sender) = self.response_sender.take() {
606 let _ = sender.send(None);
607 }
608 }
609}
610
611impl Drop for FilePicker {
612 fn drop(&mut self) {
613 if let Some(sender) = self.response_sender.take() {
614 let _ = sender.send(None);
615 }
616 }
617}
618
619pub struct InputMethodControl {
621 pub(crate) id: EmbedderControlId,
622 pub(crate) input_method_type: InputMethodType,
623 pub(crate) text: String,
624 pub(crate) insertion_point: Option<u32>,
625 pub(crate) position: DeviceIntRect,
626 pub(crate) multiline: bool,
627 pub(crate) allow_virtual_keyboard: bool,
628}
629
630impl InputMethodControl {
631 pub fn id(&self) -> EmbedderControlId {
633 self.id
634 }
635
636 pub fn input_method_type(&self) -> InputMethodType {
638 self.input_method_type
639 }
640
641 pub fn text(&self) -> String {
643 self.text.clone()
644 }
645
646 pub fn insertion_point(&self) -> Option<u32> {
649 self.insertion_point
650 }
651
652 pub fn position(&self) -> DeviceIntRect {
657 self.position
658 }
659
660 pub fn multiline(&self) -> bool {
662 self.multiline
663 }
664
665 pub fn allow_virtual_keyboard(&self) -> bool {
669 self.allow_virtual_keyboard
670 }
671}
672
673pub enum SimpleDialog {
677 Alert(AlertDialog),
678 Confirm(ConfirmDialog),
679 Prompt(PromptDialog),
680}
681
682impl SimpleDialog {
683 pub fn message(&self) -> &str {
684 match self {
685 SimpleDialog::Alert(alert_dialog) => alert_dialog.message(),
686 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.message(),
687 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.message(),
688 }
689 }
690
691 pub fn confirm(self) {
692 match self {
693 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
694 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.confirm(),
695 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.confirm(),
696 }
697 }
698
699 pub fn dismiss(self) {
700 match self {
701 SimpleDialog::Alert(alert_dialog) => alert_dialog.confirm(),
702 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.dismiss(),
703 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.dismiss(),
704 }
705 }
706}
707
708impl SimpleDialog {
709 fn id(&self) -> EmbedderControlId {
710 match self {
711 SimpleDialog::Alert(alert_dialog) => alert_dialog.id,
712 SimpleDialog::Confirm(confirm_dialog) => confirm_dialog.id,
713 SimpleDialog::Prompt(prompt_dialog) => prompt_dialog.id,
714 }
715 }
716}
717
718impl From<SimpleDialogRequest> for SimpleDialog {
719 fn from(simple_dialog_request: SimpleDialogRequest) -> Self {
720 match simple_dialog_request {
721 SimpleDialogRequest::Alert {
722 id,
723 message,
724 response_sender,
725 } => Self::Alert(AlertDialog {
726 id,
727 message,
728 response_sender,
729 response_sent: false,
730 }),
731 SimpleDialogRequest::Confirm {
732 id,
733 message,
734 response_sender,
735 } => Self::Confirm(ConfirmDialog {
736 id,
737 message,
738 response_sender,
739 response_sent: false,
740 }),
741 SimpleDialogRequest::Prompt {
742 id,
743 message,
744 default,
745 response_sender,
746 } => Self::Prompt(PromptDialog {
747 id,
748 message,
749 current_value: default,
750 response_sender,
751 response_sent: false,
752 }),
753 }
754 }
755}
756
757pub struct AlertDialog {
762 id: EmbedderControlId,
763 message: String,
764 response_sender: GenericSender<AlertResponse>,
765 response_sent: bool,
766}
767
768impl Drop for AlertDialog {
769 fn drop(&mut self) {
770 if !self.response_sent {
771 let _ = self.response_sender.send(AlertResponse::Ok);
772 }
773 }
774}
775
776impl AlertDialog {
777 pub fn message(&self) -> &str {
778 &self.message
779 }
780
781 pub fn confirm(self) {
783 }
785}
786
787pub struct ConfirmDialog {
793 id: EmbedderControlId,
794 message: String,
795 response_sender: GenericSender<ConfirmResponse>,
796 response_sent: bool,
797}
798
799impl ConfirmDialog {
800 pub fn message(&self) -> &str {
801 &self.message
802 }
803
804 pub fn dismiss(mut self) {
806 let _ = self.response_sender.send(ConfirmResponse::Cancel);
807 self.response_sent = true;
808 }
809
810 pub fn confirm(mut self) {
812 let _ = self.response_sender.send(ConfirmResponse::Ok);
813 self.response_sent = true;
814 }
815}
816
817impl Drop for ConfirmDialog {
818 fn drop(&mut self) {
819 if !self.response_sent {
820 let _ = self.response_sender.send(ConfirmResponse::Cancel);
821 }
822 }
823}
824
825pub struct PromptDialog {
834 id: EmbedderControlId,
835 message: String,
836 current_value: String,
837 response_sender: GenericSender<PromptResponse>,
838 response_sent: bool,
839}
840
841impl Drop for PromptDialog {
842 fn drop(&mut self) {
843 if !self.response_sent {
844 let _ = self.response_sender.send(PromptResponse::Cancel);
845 }
846 }
847}
848
849impl PromptDialog {
850 pub fn message(&self) -> &str {
851 &self.message
852 }
853
854 pub fn current_value(&self) -> &str {
855 &self.current_value
856 }
857
858 pub fn set_current_value(&mut self, new_value: &str) {
859 self.current_value = new_value.to_owned()
860 }
861
862 pub fn dismiss(mut self) {
864 let _ = self.response_sender.send(PromptResponse::Cancel);
865 self.response_sent = true;
866 }
867
868 pub fn confirm(mut self) {
871 let _ = self
872 .response_sender
873 .send(PromptResponse::Ok(self.current_value.clone()));
874 self.response_sent = true;
875 }
876}
877
878pub struct CreateNewWebViewRequest {
883 pub(crate) servo: Servo,
884 pub(crate) responder: IpcResponder<Option<NewWebViewDetails>>,
885}
886
887impl CreateNewWebViewRequest {
888 pub fn builder(self, rendering_context: Rc<dyn RenderingContext>) -> WebViewBuilder {
890 WebViewBuilder::new_for_create_request(&self.servo, rendering_context, self.responder)
891 }
892}
893
894pub trait WebViewDelegate {
895 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
899 None
900 }
901 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
904 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
907 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
910 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
913 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
918 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
921 fn notify_cursor_changed(&self, _webview: WebView, _cursor: Cursor) {}
924 fn notify_favicon_changed(&self, _webview: WebView) {}
927 fn notify_new_frame_ready(&self, _webview: WebView) {}
929 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
933 fn notify_traversal_complete(&self, _webview: WebView, _traversal_id: TraversalId) {}
935 fn notify_closed(&self, _webview: WebView) {}
939
940 fn notify_input_event_handled(
944 &self,
945 _webview: WebView,
946 _event_id: InputEventId,
947 _result: InputEventResult,
948 ) {
949 }
950 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
952 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
955 fn notify_fullscreen_state_changed(&self, _webview: WebView, _is_fullscreen: bool) {}
961
962 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
965 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
968 fn request_move_to(&self, _webview: WebView, _point: DeviceIntPoint) {}
970 fn request_protocol_handler(
976 &self,
977 _webview: WebView,
978 _protocol_handler_registration: ProtocolHandlerRegistration,
979 _allow_deny_request: AllowOrDenyRequest,
980 ) {
981 }
982 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
988 fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {}
1008 fn request_permission(&self, _webview: WebView, _request: PermissionRequest) {}
1012
1013 fn request_authentication(
1015 &self,
1016 _webview: WebView,
1017 _authentication_request: AuthenticationRequest,
1018 ) {
1019 }
1020
1021 fn show_bluetooth_device_dialog(
1023 &self,
1024 _webview: WebView,
1025 _request: BluetoothDeviceSelectionRequest,
1026 ) {
1027 }
1028
1029 fn show_embedder_control(&self, _webview: WebView, _embedder_control: EmbedderControl) {}
1032
1033 fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {}
1038
1039 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
1047
1048 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
1050
1051 fn show_console_message(&self, _webview: WebView, _level: ConsoleLogLevel, _message: String) {}
1054
1055 fn notify_accessibility_tree_update(
1062 &self,
1063 _webview: WebView,
1064 _tree_update: accesskit::TreeUpdate,
1065 ) {
1066 }
1067}
1068
1069pub(crate) struct DefaultWebViewDelegate;
1070impl WebViewDelegate for DefaultWebViewDelegate {}
1071
1072#[cfg(test)]
1073mod test {
1074 use super::*;
1075
1076 #[test]
1077 fn test_allow_deny_request() {
1078 use servo_base::generic_channel;
1079
1080 use crate::responders::ServoErrorChannel;
1081
1082 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
1083 let errors = ServoErrorChannel::default();
1085 let (sender, receiver) =
1086 generic_channel::channel().expect("Failed to create IPC channel");
1087 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1088 request.allow();
1089 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
1090 assert_eq!(receiver.try_recv().ok(), None);
1091 assert!(errors.try_recv().is_none());
1092
1093 let errors = ServoErrorChannel::default();
1095 let (sender, receiver) =
1096 generic_channel::channel().expect("Failed to create IPC channel");
1097 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1098 request.deny();
1099 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
1100 assert_eq!(receiver.try_recv().ok(), None);
1101 assert!(errors.try_recv().is_none());
1102
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 drop(request);
1109 assert_eq!(receiver.try_recv().ok(), Some(default_response));
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 drop(receiver);
1119 request.allow();
1120 assert!(errors.try_recv().is_some());
1121
1122 let errors = ServoErrorChannel::default();
1124 let (sender, receiver) =
1125 generic_channel::channel().expect("Failed to create IPC channel");
1126 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1127 drop(receiver);
1128 request.deny();
1129 assert!(errors.try_recv().is_some());
1130
1131 let errors = ServoErrorChannel::default();
1133 let (sender, receiver) =
1134 generic_channel::channel().expect("Failed to create IPC channel");
1135 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
1136 drop(receiver);
1137 drop(request);
1138 assert!(errors.try_recv().is_none());
1139 }
1140 }
1141
1142 #[test]
1143 fn test_authentication_request() {
1144 use crate::responders::ServoErrorChannel;
1145
1146 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
1147
1148 let errors = ServoErrorChannel::default();
1150 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1151 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1152 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1153 assert_eq!(
1154 receiver.try_recv().ok(),
1155 Some(Some(AuthenticationResponse {
1156 username: "diffie".to_owned(),
1157 password: "hunter2".to_owned(),
1158 }))
1159 );
1160 assert_eq!(receiver.try_recv().ok(), None);
1161 assert!(errors.try_recv().is_none());
1162
1163 let errors = ServoErrorChannel::default();
1165 let (sender, mut receiver) = tokio::sync::oneshot::channel();
1166 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1167 drop(request);
1168 assert_eq!(receiver.try_recv().ok(), Some(None));
1169 assert_eq!(receiver.try_recv().ok(), None);
1170 assert!(errors.try_recv().is_none());
1171
1172 let errors = ServoErrorChannel::default();
1174 let (sender, receiver) = tokio::sync::oneshot::channel();
1175 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1176 drop(receiver);
1177 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
1178 assert!(errors.try_recv().is_some());
1179
1180 let errors = ServoErrorChannel::default();
1182 let (sender, receiver) = tokio::sync::oneshot::channel();
1183 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
1184 drop(receiver);
1185 drop(request);
1186 assert!(errors.try_recv().is_none());
1187 }
1188
1189 #[test]
1190 fn test_web_resource_load() {
1191 use http::{HeaderMap, Method, StatusCode};
1192
1193 use crate::responders::ServoErrorChannel;
1194
1195 let web_resource_request = || WebResourceRequest {
1196 method: Method::GET,
1197 headers: HeaderMap::default(),
1198 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
1199 destination: content_security_policy::Destination::Document,
1200 referrer_url: None,
1201 is_for_main_frame: false,
1202 is_redirect: false,
1203 };
1204 let web_resource_response = || {
1205 WebResourceResponse::new(
1206 Url::parse("https://diffie.test").expect("Guaranteed by argument"),
1207 )
1208 .status_code(StatusCode::IM_A_TEAPOT)
1209 };
1210
1211 let errors = ServoErrorChannel::default();
1213 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1214 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1215 request.intercept(web_resource_response()).cancel();
1216 assert!(matches!(
1217 receiver.try_recv(),
1218 Ok(WebResourceResponseMsg::Start(_))
1219 ));
1220 assert!(matches!(
1221 receiver.try_recv(),
1222 Ok(WebResourceResponseMsg::CancelLoad)
1223 ));
1224 assert!(matches!(receiver.try_recv(), Err(_)));
1225 assert!(errors.try_recv().is_none());
1226
1227 let errors = ServoErrorChannel::default();
1229 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1230 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1231 drop(request.intercept(web_resource_response()));
1232 assert!(matches!(
1233 receiver.try_recv(),
1234 Ok(WebResourceResponseMsg::Start(_))
1235 ));
1236 assert!(matches!(
1237 receiver.try_recv(),
1238 Ok(WebResourceResponseMsg::FinishLoad)
1239 ));
1240 assert!(matches!(receiver.try_recv(), Err(_)));
1241 assert!(errors.try_recv().is_none());
1242
1243 let errors = ServoErrorChannel::default();
1245 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
1246 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1247 drop(request);
1248 assert!(matches!(
1249 receiver.try_recv(),
1250 Ok(WebResourceResponseMsg::DoNotIntercept)
1251 ));
1252 assert!(matches!(receiver.try_recv(), Err(_)));
1253 assert!(errors.try_recv().is_none());
1254
1255 let errors = ServoErrorChannel::default();
1257 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1258 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1259 drop(receiver);
1260 request.intercept(web_resource_response()).cancel();
1261 assert!(errors.try_recv().is_some());
1262
1263 let errors = ServoErrorChannel::default();
1265 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1266 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1267 drop(receiver);
1268 drop(request.intercept(web_resource_response()));
1269 assert!(errors.try_recv().is_some());
1270
1271 let errors = ServoErrorChannel::default();
1273 let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
1274 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
1275 drop(receiver);
1276 drop(request);
1277 assert!(errors.try_recv().is_none());
1278 }
1279}