1use std::path::PathBuf;
6
7use base::generic_channel::{GenericSender, SendResult};
8use base::id::PipelineId;
9use constellation_traits::EmbedderToConstellationMessage;
10use embedder_traits::{
11 AllowOrDeny, AuthenticationResponse, ContextMenuResult, Cursor, FilterPattern,
12 GamepadHapticEffectType, InputMethodType, KeyboardEvent, LoadStatus, MediaSessionEvent,
13 Notification, PermissionFeature, RgbColor, ScreenGeometry, SelectElementOptionOrOptgroup,
14 SimpleDialog, TraversalId, WebResourceRequest, WebResourceResponse, WebResourceResponseMsg,
15};
16use ipc_channel::ipc::IpcSender;
17use serde::Serialize;
18use url::Url;
19use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
20
21use crate::responders::ServoErrorSender;
22use crate::{ConstellationProxy, WebView};
23
24pub struct NavigationRequest {
27 pub url: Url,
28 pub(crate) pipeline_id: PipelineId,
29 pub(crate) constellation_proxy: ConstellationProxy,
30 pub(crate) response_sent: bool,
31}
32
33impl NavigationRequest {
34 pub fn allow(mut self) {
35 self.constellation_proxy
36 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
37 self.pipeline_id,
38 true,
39 ));
40 self.response_sent = true;
41 }
42
43 pub fn deny(mut self) {
44 self.constellation_proxy
45 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
46 self.pipeline_id,
47 false,
48 ));
49 self.response_sent = true;
50 }
51}
52
53impl Drop for NavigationRequest {
54 fn drop(&mut self) {
55 if !self.response_sent {
56 self.constellation_proxy
57 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
58 self.pipeline_id,
59 true,
60 ));
61 }
62 }
63}
64
65pub(crate) struct IpcResponder<T: Serialize> {
67 response_sender: GenericSender<T>,
68 response_sent: bool,
69 default_response: Option<T>,
71}
72
73impl<T: Serialize> IpcResponder<T> {
74 pub(crate) fn new(response_sender: GenericSender<T>, default_response: T) -> Self {
75 Self {
76 response_sender,
77 response_sent: false,
78 default_response: Some(default_response),
79 }
80 }
81
82 pub(crate) fn send(&mut self, response: T) -> SendResult {
83 let result = self.response_sender.send(response);
84 self.response_sent = true;
85 result
86 }
87
88 pub(crate) fn into_inner(self) -> GenericSender<T> {
89 self.response_sender.clone()
90 }
91}
92
93impl<T: Serialize> Drop for IpcResponder<T> {
94 fn drop(&mut self) {
95 if !self.response_sent {
96 let response = self
97 .default_response
98 .take()
99 .expect("Guaranteed by inherent impl");
100 let _ = self.response_sender.send(response);
103 }
104 }
105}
106
107pub struct PermissionRequest {
111 pub(crate) requested_feature: PermissionFeature,
112 pub(crate) allow_deny_request: AllowOrDenyRequest,
113}
114
115impl PermissionRequest {
116 pub fn feature(&self) -> PermissionFeature {
117 self.requested_feature
118 }
119
120 pub fn allow(self) {
121 self.allow_deny_request.allow();
122 }
123
124 pub fn deny(self) {
125 self.allow_deny_request.deny();
126 }
127}
128
129pub struct AllowOrDenyRequest(IpcResponder<AllowOrDeny>, ServoErrorSender);
130
131impl AllowOrDenyRequest {
132 pub(crate) fn new(
133 response_sender: GenericSender<AllowOrDeny>,
134 default_response: AllowOrDeny,
135 error_sender: ServoErrorSender,
136 ) -> Self {
137 Self(
138 IpcResponder::new(response_sender, default_response),
139 error_sender,
140 )
141 }
142
143 pub fn allow(mut self) {
144 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
145 self.1.raise_response_send_error(error);
146 }
147 }
148
149 pub fn deny(mut self) {
150 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
151 self.1.raise_response_send_error(error);
152 }
153 }
154}
155
156pub struct AuthenticationRequest {
160 pub(crate) url: Url,
161 pub(crate) for_proxy: bool,
162 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
163 pub(crate) error_sender: ServoErrorSender,
164}
165
166impl AuthenticationRequest {
167 pub(crate) fn new(
168 url: Url,
169 for_proxy: bool,
170 response_sender: GenericSender<Option<AuthenticationResponse>>,
171 error_sender: ServoErrorSender,
172 ) -> Self {
173 Self {
174 url,
175 for_proxy,
176 responder: IpcResponder::new(response_sender, None),
177 error_sender,
178 }
179 }
180
181 pub fn url(&self) -> &Url {
183 &self.url
184 }
185 pub fn for_proxy(&self) -> bool {
187 self.for_proxy
188 }
189 pub fn authenticate(mut self, username: String, password: String) {
191 if let Err(error) = self
192 .responder
193 .send(Some(AuthenticationResponse { username, password }))
194 {
195 self.error_sender.raise_response_send_error(error);
196 }
197 }
198}
199
200pub struct WebResourceLoad {
204 pub request: WebResourceRequest,
205 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
206 pub(crate) error_sender: ServoErrorSender,
207}
208
209impl WebResourceLoad {
210 pub(crate) fn new(
211 web_resource_request: WebResourceRequest,
212 response_sender: GenericSender<WebResourceResponseMsg>,
213 error_sender: ServoErrorSender,
214 ) -> Self {
215 Self {
216 request: web_resource_request,
217 responder: IpcResponder::new(response_sender, WebResourceResponseMsg::DoNotIntercept),
218 error_sender,
219 }
220 }
221
222 pub fn request(&self) -> &WebResourceRequest {
224 &self.request
225 }
226 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
229 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
230 self.error_sender.raise_response_send_error(error);
231 }
232 InterceptedWebResourceLoad {
233 request: self.request.clone(),
234 response_sender: self.responder.into_inner(),
235 finished: false,
236 error_sender: self.error_sender,
237 }
238 }
239}
240
241pub struct InterceptedWebResourceLoad {
247 pub request: WebResourceRequest,
248 pub(crate) response_sender: GenericSender<WebResourceResponseMsg>,
249 pub(crate) finished: bool,
250 pub(crate) error_sender: ServoErrorSender,
251}
252
253impl InterceptedWebResourceLoad {
254 pub fn send_body_data(&self, data: Vec<u8>) {
257 if let Err(error) = self
258 .response_sender
259 .send(WebResourceResponseMsg::SendBodyData(data))
260 {
261 self.error_sender.raise_response_send_error(error);
262 }
263 }
264 pub fn finish(mut self) {
266 if let Err(error) = self
267 .response_sender
268 .send(WebResourceResponseMsg::FinishLoad)
269 {
270 self.error_sender.raise_response_send_error(error);
271 }
272 self.finished = true;
273 }
274 pub fn cancel(mut self) {
276 if let Err(error) = self
277 .response_sender
278 .send(WebResourceResponseMsg::CancelLoad)
279 {
280 self.error_sender.raise_response_send_error(error);
281 }
282 self.finished = true;
283 }
284}
285
286impl Drop for InterceptedWebResourceLoad {
287 fn drop(&mut self) {
288 if !self.finished {
289 if let Err(error) = self
290 .response_sender
291 .send(WebResourceResponseMsg::FinishLoad)
292 {
293 self.error_sender.raise_response_send_error(error);
294 }
295 }
296 }
297}
298
299pub enum FormControl {
301 SelectElement(SelectElement),
303 ColorPicker(ColorPicker),
305}
306
307pub struct SelectElement {
309 pub(crate) options: Vec<SelectElementOptionOrOptgroup>,
310 pub(crate) selected_option: Option<usize>,
311 pub(crate) position: DeviceIntRect,
312 pub(crate) responder: IpcResponder<Option<usize>>,
313}
314
315impl SelectElement {
316 pub(crate) fn new(
317 options: Vec<SelectElementOptionOrOptgroup>,
318 selected_option: Option<usize>,
319 position: DeviceIntRect,
320 ipc_sender: GenericSender<Option<usize>>,
321 ) -> Self {
322 Self {
323 options,
324 selected_option,
325 position,
326 responder: IpcResponder::new(ipc_sender, None),
327 }
328 }
329
330 pub fn position(&self) -> DeviceIntRect {
334 self.position
335 }
336
337 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
340 &self.options
341 }
342
343 pub fn select(&mut self, id: Option<usize>) {
348 self.selected_option = id;
349 }
350
351 pub fn selected_option(&self) -> Option<usize> {
352 self.selected_option
353 }
354
355 pub fn submit(mut self) {
357 let _ = self.responder.send(self.selected_option);
358 }
359}
360
361pub struct ColorPicker {
363 pub(crate) current_color: RgbColor,
364 pub(crate) position: DeviceIntRect,
365 pub(crate) responder: IpcResponder<Option<RgbColor>>,
366 pub(crate) error_sender: ServoErrorSender,
367}
368
369impl ColorPicker {
370 pub(crate) fn new(
371 current_color: RgbColor,
372 position: DeviceIntRect,
373 ipc_sender: GenericSender<Option<RgbColor>>,
374 error_sender: ServoErrorSender,
375 ) -> Self {
376 Self {
377 current_color,
378 position,
379 responder: IpcResponder::new(ipc_sender, None),
380 error_sender,
381 }
382 }
383
384 pub fn position(&self) -> DeviceIntRect {
388 self.position
389 }
390
391 pub fn current_color(&self) -> RgbColor {
393 self.current_color
394 }
395
396 pub fn select(&mut self, color: Option<RgbColor>) {
397 if let Err(error) = self.responder.send(color) {
398 self.error_sender.raise_response_send_error(error);
399 }
400 }
401}
402
403pub trait WebViewDelegate {
404 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
408 None
409 }
410 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
413 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
416 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
419 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
422 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
427 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
430 fn notify_cursor_changed(&self, _webview: WebView, _: Cursor) {}
433 fn notify_favicon_changed(&self, _webview: WebView) {}
436 fn notify_new_frame_ready(&self, _webview: WebView) {}
438 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
442 fn notify_traversal_complete(&self, _webview: WebView, _: TraversalId) {}
444 fn notify_closed(&self, _webview: WebView) {}
448
449 fn notify_keyboard_event(&self, _webview: WebView, _: KeyboardEvent) {}
454 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
456 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
459 fn notify_fullscreen_state_changed(&self, _webview: WebView, _: bool) {}
465
466 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
469 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
472 fn request_move_to(&self, _webview: WebView, _: DeviceIntPoint) {}
474 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
480 fn request_open_auxiliary_webview(&self, _parent_webview: WebView) -> Option<WebView> {
483 None
484 }
485
486 fn request_permission(&self, _webview: WebView, _: PermissionRequest) {}
490
491 fn request_authentication(
492 &self,
493 _webview: WebView,
494 _authentication_request: AuthenticationRequest,
495 ) {
496 }
497
498 fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog) {
503 let _ = match dialog {
505 SimpleDialog::Alert {
506 response_sender, ..
507 } => response_sender.send(Default::default()),
508 SimpleDialog::Confirm {
509 response_sender, ..
510 } => response_sender.send(Default::default()),
511 SimpleDialog::Prompt {
512 response_sender, ..
513 } => response_sender.send(Default::default()),
514 };
515 }
516
517 fn show_context_menu(
519 &self,
520 _webview: WebView,
521 result_sender: GenericSender<ContextMenuResult>,
522 _: Option<String>,
523 _: Vec<String>,
524 ) {
525 let _ = result_sender.send(ContextMenuResult::Ignored);
526 }
527
528 fn show_bluetooth_device_dialog(
531 &self,
532 _webview: WebView,
533 _: Vec<String>,
534 response_sender: GenericSender<Option<String>>,
535 ) {
536 let _ = response_sender.send(None);
537 }
538
539 fn show_file_selection_dialog(
541 &self,
542 _webview: WebView,
543 _filter_pattern: Vec<FilterPattern>,
544 _allow_select_mutiple: bool,
545 response_sender: GenericSender<Option<Vec<PathBuf>>>,
546 ) {
547 let _ = response_sender.send(None);
548 }
549
550 fn show_ime(
555 &self,
556 _webview: WebView,
557 _type: InputMethodType,
558 _text: Option<(String, i32)>,
559 _multiline: bool,
560 _position: DeviceIntRect,
561 ) {
562 }
563
564 fn hide_ime(&self, _webview: WebView) {}
566
567 fn show_form_control(&self, _webview: WebView, _form_control: FormControl) {}
570
571 fn play_gamepad_haptic_effect(
573 &self,
574 _webview: WebView,
575 _: usize,
576 _: GamepadHapticEffectType,
577 _: IpcSender<bool>,
578 ) {
579 }
580 fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: IpcSender<bool>) {}
582
583 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
591
592 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
594}
595
596pub(crate) struct DefaultWebViewDelegate;
597impl WebViewDelegate for DefaultWebViewDelegate {}
598
599#[test]
600fn test_allow_deny_request() {
601 use base::generic_channel;
602
603 use crate::ServoErrorChannel;
604
605 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
606 let errors = ServoErrorChannel::default();
608 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
609 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
610 request.allow();
611 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
612 assert_eq!(receiver.try_recv().ok(), None);
613 assert!(errors.try_recv().is_none());
614
615 let errors = ServoErrorChannel::default();
617 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
618 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
619 request.deny();
620 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
621 assert_eq!(receiver.try_recv().ok(), None);
622 assert!(errors.try_recv().is_none());
623
624 let errors = ServoErrorChannel::default();
626 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
627 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
628 drop(request);
629 assert_eq!(receiver.try_recv().ok(), Some(default_response));
630 assert_eq!(receiver.try_recv().ok(), None);
631 assert!(errors.try_recv().is_none());
632
633 let errors = ServoErrorChannel::default();
635 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
636 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
637 drop(receiver);
638 request.allow();
639 assert!(errors.try_recv().is_some());
640
641 let errors = ServoErrorChannel::default();
643 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
644 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
645 drop(receiver);
646 request.deny();
647 assert!(errors.try_recv().is_some());
648
649 let errors = ServoErrorChannel::default();
651 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
652 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
653 drop(receiver);
654 drop(request);
655 assert!(errors.try_recv().is_none());
656 }
657}
658
659#[test]
660fn test_authentication_request() {
661 use base::generic_channel;
662
663 use crate::ServoErrorChannel;
664
665 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
666
667 let errors = ServoErrorChannel::default();
669 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
670 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
671 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
672 assert_eq!(
673 receiver.try_recv().ok(),
674 Some(Some(AuthenticationResponse {
675 username: "diffie".to_owned(),
676 password: "hunter2".to_owned(),
677 }))
678 );
679 assert_eq!(receiver.try_recv().ok(), None);
680 assert!(errors.try_recv().is_none());
681
682 let errors = ServoErrorChannel::default();
684 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
685 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
686 drop(request);
687 assert_eq!(receiver.try_recv().ok(), Some(None));
688 assert_eq!(receiver.try_recv().ok(), None);
689 assert!(errors.try_recv().is_none());
690
691 let errors = ServoErrorChannel::default();
693 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
694 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
695 drop(receiver);
696 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
697 assert!(errors.try_recv().is_some());
698
699 let errors = ServoErrorChannel::default();
701 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
702 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
703 drop(receiver);
704 drop(request);
705 assert!(errors.try_recv().is_none());
706}
707
708#[test]
709fn test_web_resource_load() {
710 use base::generic_channel;
711 use http::{HeaderMap, Method, StatusCode};
712
713 use crate::ServoErrorChannel;
714
715 let web_resource_request = || WebResourceRequest {
716 method: Method::GET,
717 headers: HeaderMap::default(),
718 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
719 is_for_main_frame: false,
720 is_redirect: false,
721 };
722 let web_resource_response = || {
723 WebResourceResponse::new(Url::parse("https://diffie.test").expect("Guaranteed by argument"))
724 .status_code(StatusCode::IM_A_TEAPOT)
725 };
726
727 let errors = ServoErrorChannel::default();
729 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
730 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
731 request.intercept(web_resource_response()).cancel();
732 assert!(matches!(
733 receiver.try_recv(),
734 Ok(WebResourceResponseMsg::Start(_))
735 ));
736 assert!(matches!(
737 receiver.try_recv(),
738 Ok(WebResourceResponseMsg::CancelLoad)
739 ));
740 assert!(matches!(receiver.try_recv(), Err(_)));
741 assert!(errors.try_recv().is_none());
742
743 let errors = ServoErrorChannel::default();
745 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
746 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
747 drop(request.intercept(web_resource_response()));
748 assert!(matches!(
749 receiver.try_recv(),
750 Ok(WebResourceResponseMsg::Start(_))
751 ));
752 assert!(matches!(
753 receiver.try_recv(),
754 Ok(WebResourceResponseMsg::FinishLoad)
755 ));
756 assert!(matches!(receiver.try_recv(), Err(_)));
757 assert!(errors.try_recv().is_none());
758
759 let errors = ServoErrorChannel::default();
761 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
762 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
763 drop(request);
764 assert!(matches!(
765 receiver.try_recv(),
766 Ok(WebResourceResponseMsg::DoNotIntercept)
767 ));
768 assert!(matches!(receiver.try_recv(), Err(_)));
769 assert!(errors.try_recv().is_none());
770
771 let errors = ServoErrorChannel::default();
773 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
774 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
775 drop(receiver);
776 request.intercept(web_resource_response()).cancel();
777 assert!(errors.try_recv().is_some());
778
779 let errors = ServoErrorChannel::default();
781 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
782 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
783 drop(receiver);
784 drop(request.intercept(web_resource_response()));
785 assert!(errors.try_recv().is_some());
786
787 let errors = ServoErrorChannel::default();
789 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
790 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
791 drop(receiver);
792 drop(request);
793 assert!(errors.try_recv().is_none());
794}