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, EmbedderControlId,
12 FilterPattern, FormControlResponse, GamepadHapticEffectType, InputEventId, InputEventResult,
13 InputMethodType, LoadStatus, MediaSessionEvent, Notification, PermissionFeature, RgbColor,
14 ScreenGeometry, SelectElementOptionOrOptgroup, SimpleDialog, TraversalId, WebResourceRequest,
15 WebResourceResponse, WebResourceResponseMsg,
16};
17use ipc_channel::ipc::IpcSender;
18use serde::Serialize;
19use url::Url;
20use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
21
22use crate::responders::ServoErrorSender;
23use crate::{ConstellationProxy, WebView};
24
25pub struct NavigationRequest {
28 pub url: Url,
29 pub(crate) pipeline_id: PipelineId,
30 pub(crate) constellation_proxy: ConstellationProxy,
31 pub(crate) response_sent: bool,
32}
33
34impl NavigationRequest {
35 pub fn allow(mut self) {
36 self.constellation_proxy
37 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
38 self.pipeline_id,
39 true,
40 ));
41 self.response_sent = true;
42 }
43
44 pub fn deny(mut self) {
45 self.constellation_proxy
46 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
47 self.pipeline_id,
48 false,
49 ));
50 self.response_sent = true;
51 }
52}
53
54impl Drop for NavigationRequest {
55 fn drop(&mut self) {
56 if !self.response_sent {
57 self.constellation_proxy
58 .send(EmbedderToConstellationMessage::AllowNavigationResponse(
59 self.pipeline_id,
60 true,
61 ));
62 }
63 }
64}
65
66pub(crate) struct IpcResponder<T: Serialize> {
68 response_sender: GenericSender<T>,
69 response_sent: bool,
70 default_response: Option<T>,
72}
73
74impl<T: Serialize> IpcResponder<T> {
75 pub(crate) fn new(response_sender: GenericSender<T>, default_response: T) -> Self {
76 Self {
77 response_sender,
78 response_sent: false,
79 default_response: Some(default_response),
80 }
81 }
82
83 pub(crate) fn send(&mut self, response: T) -> SendResult {
84 let result = self.response_sender.send(response);
85 self.response_sent = true;
86 result
87 }
88
89 pub(crate) fn into_inner(self) -> GenericSender<T> {
90 self.response_sender.clone()
91 }
92}
93
94impl<T: Serialize> Drop for IpcResponder<T> {
95 fn drop(&mut self) {
96 if !self.response_sent {
97 let response = self
98 .default_response
99 .take()
100 .expect("Guaranteed by inherent impl");
101 let _ = self.response_sender.send(response);
104 }
105 }
106}
107
108pub struct PermissionRequest {
112 pub(crate) requested_feature: PermissionFeature,
113 pub(crate) allow_deny_request: AllowOrDenyRequest,
114}
115
116impl PermissionRequest {
117 pub fn feature(&self) -> PermissionFeature {
118 self.requested_feature
119 }
120
121 pub fn allow(self) {
122 self.allow_deny_request.allow();
123 }
124
125 pub fn deny(self) {
126 self.allow_deny_request.deny();
127 }
128}
129
130pub struct AllowOrDenyRequest(IpcResponder<AllowOrDeny>, ServoErrorSender);
131
132impl AllowOrDenyRequest {
133 pub(crate) fn new(
134 response_sender: GenericSender<AllowOrDeny>,
135 default_response: AllowOrDeny,
136 error_sender: ServoErrorSender,
137 ) -> Self {
138 Self(
139 IpcResponder::new(response_sender, default_response),
140 error_sender,
141 )
142 }
143
144 pub fn allow(mut self) {
145 if let Err(error) = self.0.send(AllowOrDeny::Allow) {
146 self.1.raise_response_send_error(error);
147 }
148 }
149
150 pub fn deny(mut self) {
151 if let Err(error) = self.0.send(AllowOrDeny::Deny) {
152 self.1.raise_response_send_error(error);
153 }
154 }
155}
156
157pub struct AuthenticationRequest {
161 pub(crate) url: Url,
162 pub(crate) for_proxy: bool,
163 pub(crate) responder: IpcResponder<Option<AuthenticationResponse>>,
164 pub(crate) error_sender: ServoErrorSender,
165}
166
167impl AuthenticationRequest {
168 pub(crate) fn new(
169 url: Url,
170 for_proxy: bool,
171 response_sender: GenericSender<Option<AuthenticationResponse>>,
172 error_sender: ServoErrorSender,
173 ) -> Self {
174 Self {
175 url,
176 for_proxy,
177 responder: IpcResponder::new(response_sender, None),
178 error_sender,
179 }
180 }
181
182 pub fn url(&self) -> &Url {
184 &self.url
185 }
186 pub fn for_proxy(&self) -> bool {
188 self.for_proxy
189 }
190 pub fn authenticate(mut self, username: String, password: String) {
192 if let Err(error) = self
193 .responder
194 .send(Some(AuthenticationResponse { username, password }))
195 {
196 self.error_sender.raise_response_send_error(error);
197 }
198 }
199}
200
201pub struct WebResourceLoad {
205 pub request: WebResourceRequest,
206 pub(crate) responder: IpcResponder<WebResourceResponseMsg>,
207 pub(crate) error_sender: ServoErrorSender,
208}
209
210impl WebResourceLoad {
211 pub(crate) fn new(
212 web_resource_request: WebResourceRequest,
213 response_sender: GenericSender<WebResourceResponseMsg>,
214 error_sender: ServoErrorSender,
215 ) -> Self {
216 Self {
217 request: web_resource_request,
218 responder: IpcResponder::new(response_sender, WebResourceResponseMsg::DoNotIntercept),
219 error_sender,
220 }
221 }
222
223 pub fn request(&self) -> &WebResourceRequest {
225 &self.request
226 }
227 pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad {
230 if let Err(error) = self.responder.send(WebResourceResponseMsg::Start(response)) {
231 self.error_sender.raise_response_send_error(error);
232 }
233 InterceptedWebResourceLoad {
234 request: self.request.clone(),
235 response_sender: self.responder.into_inner(),
236 finished: false,
237 error_sender: self.error_sender,
238 }
239 }
240}
241
242pub struct InterceptedWebResourceLoad {
248 pub request: WebResourceRequest,
249 pub(crate) response_sender: GenericSender<WebResourceResponseMsg>,
250 pub(crate) finished: bool,
251 pub(crate) error_sender: ServoErrorSender,
252}
253
254impl InterceptedWebResourceLoad {
255 pub fn send_body_data(&self, data: Vec<u8>) {
258 if let Err(error) = self
259 .response_sender
260 .send(WebResourceResponseMsg::SendBodyData(data))
261 {
262 self.error_sender.raise_response_send_error(error);
263 }
264 }
265 pub fn finish(mut self) {
267 if let Err(error) = self
268 .response_sender
269 .send(WebResourceResponseMsg::FinishLoad)
270 {
271 self.error_sender.raise_response_send_error(error);
272 }
273 self.finished = true;
274 }
275 pub fn cancel(mut self) {
277 if let Err(error) = self
278 .response_sender
279 .send(WebResourceResponseMsg::CancelLoad)
280 {
281 self.error_sender.raise_response_send_error(error);
282 }
283 self.finished = true;
284 }
285}
286
287impl Drop for InterceptedWebResourceLoad {
288 fn drop(&mut self) {
289 if !self.finished {
290 if let Err(error) = self
291 .response_sender
292 .send(WebResourceResponseMsg::FinishLoad)
293 {
294 self.error_sender.raise_response_send_error(error);
295 }
296 }
297 }
298}
299
300pub enum FormControl {
302 SelectElement(SelectElement),
304 ColorPicker(ColorPicker),
306}
307
308impl FormControl {
309 pub fn id(&self) -> EmbedderControlId {
310 match self {
311 FormControl::SelectElement(select_element) => select_element.id,
312 FormControl::ColorPicker(color_picker) => color_picker.id,
313 }
314 }
315}
316
317pub struct SelectElement {
319 pub(crate) id: EmbedderControlId,
320 pub(crate) options: Vec<SelectElementOptionOrOptgroup>,
321 pub(crate) selected_option: Option<usize>,
322 pub(crate) position: DeviceIntRect,
323 pub(crate) constellation_proxy: ConstellationProxy,
324 pub(crate) response_sent: bool,
325}
326
327impl SelectElement {
328 pub fn position(&self) -> DeviceIntRect {
332 self.position
333 }
334
335 pub fn options(&self) -> &[SelectElementOptionOrOptgroup] {
338 &self.options
339 }
340
341 pub fn select(&mut self, id: Option<usize>) {
346 self.selected_option = id;
347 }
348
349 pub fn selected_option(&self) -> Option<usize> {
350 self.selected_option
351 }
352
353 pub fn submit(mut self) {
355 self.response_sent = true;
356 self.constellation_proxy
357 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
358 self.id,
359 FormControlResponse::SelectElement(self.selected_option()),
360 ));
361 }
362}
363
364impl Drop for SelectElement {
365 fn drop(&mut self) {
366 if !self.response_sent {
367 self.constellation_proxy
368 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
369 self.id,
370 FormControlResponse::SelectElement(self.selected_option()),
371 ));
372 }
373 }
374}
375
376pub struct ColorPicker {
378 pub(crate) id: EmbedderControlId,
379 pub(crate) current_color: Option<RgbColor>,
380 pub(crate) position: DeviceIntRect,
381 pub(crate) constellation_proxy: ConstellationProxy,
382 pub(crate) response_sent: bool,
383}
384
385impl ColorPicker {
386 pub fn position(&self) -> DeviceIntRect {
390 self.position
391 }
392
393 pub fn current_color(&self) -> Option<RgbColor> {
396 self.current_color
397 }
398
399 pub fn select(&mut self, color: Option<RgbColor>) {
400 self.current_color = color;
401 }
402
403 pub fn submit(mut self) {
405 self.response_sent = true;
406 self.constellation_proxy
407 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
408 self.id,
409 FormControlResponse::ColorPicker(self.current_color),
410 ));
411 }
412}
413
414impl Drop for ColorPicker {
415 fn drop(&mut self) {
416 if !self.response_sent {
417 self.constellation_proxy
418 .send(EmbedderToConstellationMessage::EmbedderControlResponse(
419 self.id,
420 FormControlResponse::ColorPicker(self.current_color),
421 ));
422 }
423 }
424}
425
426pub trait WebViewDelegate {
427 fn screen_geometry(&self, _webview: WebView) -> Option<ScreenGeometry> {
431 None
432 }
433 fn notify_url_changed(&self, _webview: WebView, _url: Url) {}
436 fn notify_page_title_changed(&self, _webview: WebView, _title: Option<String>) {}
439 fn notify_status_text_changed(&self, _webview: WebView, _status: Option<String>) {}
442 fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {}
445 fn notify_animating_changed(&self, _webview: WebView, _animating: bool) {}
450 fn notify_load_status_changed(&self, _webview: WebView, _status: LoadStatus) {}
453 fn notify_cursor_changed(&self, _webview: WebView, _: Cursor) {}
456 fn notify_favicon_changed(&self, _webview: WebView) {}
459 fn notify_new_frame_ready(&self, _webview: WebView) {}
461 fn notify_history_changed(&self, _webview: WebView, _entries: Vec<Url>, _current: usize) {}
465 fn notify_traversal_complete(&self, _webview: WebView, _: TraversalId) {}
467 fn notify_closed(&self, _webview: WebView) {}
471
472 fn notify_input_event_handled(&self, _webview: WebView, _: InputEventId, _: InputEventResult) {}
476 fn notify_crashed(&self, _webview: WebView, _reason: String, _backtrace: Option<String>) {}
478 fn notify_media_session_event(&self, _webview: WebView, _event: MediaSessionEvent) {}
481 fn notify_fullscreen_state_changed(&self, _webview: WebView, _: bool) {}
487
488 fn request_navigation(&self, _webview: WebView, _navigation_request: NavigationRequest) {}
491 fn request_unload(&self, _webview: WebView, _unload_request: AllowOrDenyRequest) {}
494 fn request_move_to(&self, _webview: WebView, _: DeviceIntPoint) {}
496 fn request_resize_to(&self, _webview: WebView, _requested_outer_size: DeviceIntSize) {}
502 fn request_open_auxiliary_webview(&self, _parent_webview: WebView) -> Option<WebView> {
505 None
506 }
507
508 fn request_permission(&self, _webview: WebView, _: PermissionRequest) {}
512
513 fn request_authentication(
514 &self,
515 _webview: WebView,
516 _authentication_request: AuthenticationRequest,
517 ) {
518 }
519
520 fn show_simple_dialog(&self, _webview: WebView, dialog: SimpleDialog) {
525 let _ = match dialog {
527 SimpleDialog::Alert {
528 response_sender, ..
529 } => response_sender.send(Default::default()),
530 SimpleDialog::Confirm {
531 response_sender, ..
532 } => response_sender.send(Default::default()),
533 SimpleDialog::Prompt {
534 response_sender, ..
535 } => response_sender.send(Default::default()),
536 };
537 }
538
539 fn show_context_menu(
541 &self,
542 _webview: WebView,
543 result_sender: GenericSender<ContextMenuResult>,
544 _: Option<String>,
545 _: Vec<String>,
546 ) {
547 let _ = result_sender.send(ContextMenuResult::Ignored);
548 }
549
550 fn show_bluetooth_device_dialog(
553 &self,
554 _webview: WebView,
555 _: Vec<String>,
556 response_sender: GenericSender<Option<String>>,
557 ) {
558 let _ = response_sender.send(None);
559 }
560
561 fn show_file_selection_dialog(
563 &self,
564 _webview: WebView,
565 _filter_pattern: Vec<FilterPattern>,
566 _allow_select_mutiple: bool,
567 response_sender: GenericSender<Option<Vec<PathBuf>>>,
568 ) {
569 let _ = response_sender.send(None);
570 }
571
572 fn show_ime(
577 &self,
578 _webview: WebView,
579 _type: InputMethodType,
580 _text: Option<(String, i32)>,
581 _multiline: bool,
582 _position: DeviceIntRect,
583 ) {
584 }
585
586 fn hide_ime(&self, _webview: WebView) {}
588
589 fn show_form_control(&self, _webview: WebView, _form_control: FormControl) {}
592
593 fn play_gamepad_haptic_effect(
595 &self,
596 _webview: WebView,
597 _: usize,
598 _: GamepadHapticEffectType,
599 _: IpcSender<bool>,
600 ) {
601 }
602 fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: IpcSender<bool>) {}
604
605 fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {}
613
614 fn show_notification(&self, _webview: WebView, _notification: Notification) {}
616}
617
618pub(crate) struct DefaultWebViewDelegate;
619impl WebViewDelegate for DefaultWebViewDelegate {}
620
621#[test]
622fn test_allow_deny_request() {
623 use base::generic_channel;
624
625 use crate::ServoErrorChannel;
626
627 for default_response in [AllowOrDeny::Allow, AllowOrDeny::Deny] {
628 let errors = ServoErrorChannel::default();
630 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
631 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
632 request.allow();
633 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Allow));
634 assert_eq!(receiver.try_recv().ok(), None);
635 assert!(errors.try_recv().is_none());
636
637 let errors = ServoErrorChannel::default();
639 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
640 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
641 request.deny();
642 assert_eq!(receiver.try_recv().ok(), Some(AllowOrDeny::Deny));
643 assert_eq!(receiver.try_recv().ok(), None);
644 assert!(errors.try_recv().is_none());
645
646 let errors = ServoErrorChannel::default();
648 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
649 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
650 drop(request);
651 assert_eq!(receiver.try_recv().ok(), Some(default_response));
652 assert_eq!(receiver.try_recv().ok(), None);
653 assert!(errors.try_recv().is_none());
654
655 let errors = ServoErrorChannel::default();
657 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
658 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
659 drop(receiver);
660 request.allow();
661 assert!(errors.try_recv().is_some());
662
663 let errors = ServoErrorChannel::default();
665 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
666 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
667 drop(receiver);
668 request.deny();
669 assert!(errors.try_recv().is_some());
670
671 let errors = ServoErrorChannel::default();
673 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
674 let request = AllowOrDenyRequest::new(sender, default_response, errors.sender());
675 drop(receiver);
676 drop(request);
677 assert!(errors.try_recv().is_none());
678 }
679}
680
681#[test]
682fn test_authentication_request() {
683 use base::generic_channel;
684
685 use crate::ServoErrorChannel;
686
687 let url = Url::parse("https://example.com").expect("Guaranteed by argument");
688
689 let errors = ServoErrorChannel::default();
691 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
692 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
693 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
694 assert_eq!(
695 receiver.try_recv().ok(),
696 Some(Some(AuthenticationResponse {
697 username: "diffie".to_owned(),
698 password: "hunter2".to_owned(),
699 }))
700 );
701 assert_eq!(receiver.try_recv().ok(), None);
702 assert!(errors.try_recv().is_none());
703
704 let errors = ServoErrorChannel::default();
706 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
707 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
708 drop(request);
709 assert_eq!(receiver.try_recv().ok(), Some(None));
710 assert_eq!(receiver.try_recv().ok(), None);
711 assert!(errors.try_recv().is_none());
712
713 let errors = ServoErrorChannel::default();
715 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
716 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
717 drop(receiver);
718 request.authenticate("diffie".to_owned(), "hunter2".to_owned());
719 assert!(errors.try_recv().is_some());
720
721 let errors = ServoErrorChannel::default();
723 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
724 let request = AuthenticationRequest::new(url.clone(), false, sender, errors.sender());
725 drop(receiver);
726 drop(request);
727 assert!(errors.try_recv().is_none());
728}
729
730#[test]
731fn test_web_resource_load() {
732 use base::generic_channel;
733 use http::{HeaderMap, Method, StatusCode};
734
735 use crate::ServoErrorChannel;
736
737 let web_resource_request = || WebResourceRequest {
738 method: Method::GET,
739 headers: HeaderMap::default(),
740 url: Url::parse("https://example.com").expect("Guaranteed by argument"),
741 is_for_main_frame: false,
742 is_redirect: false,
743 };
744 let web_resource_response = || {
745 WebResourceResponse::new(Url::parse("https://diffie.test").expect("Guaranteed by argument"))
746 .status_code(StatusCode::IM_A_TEAPOT)
747 };
748
749 let errors = ServoErrorChannel::default();
751 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
752 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
753 request.intercept(web_resource_response()).cancel();
754 assert!(matches!(
755 receiver.try_recv(),
756 Ok(WebResourceResponseMsg::Start(_))
757 ));
758 assert!(matches!(
759 receiver.try_recv(),
760 Ok(WebResourceResponseMsg::CancelLoad)
761 ));
762 assert!(matches!(receiver.try_recv(), Err(_)));
763 assert!(errors.try_recv().is_none());
764
765 let errors = ServoErrorChannel::default();
767 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
768 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
769 drop(request.intercept(web_resource_response()));
770 assert!(matches!(
771 receiver.try_recv(),
772 Ok(WebResourceResponseMsg::Start(_))
773 ));
774 assert!(matches!(
775 receiver.try_recv(),
776 Ok(WebResourceResponseMsg::FinishLoad)
777 ));
778 assert!(matches!(receiver.try_recv(), Err(_)));
779 assert!(errors.try_recv().is_none());
780
781 let errors = ServoErrorChannel::default();
783 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
784 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
785 drop(request);
786 assert!(matches!(
787 receiver.try_recv(),
788 Ok(WebResourceResponseMsg::DoNotIntercept)
789 ));
790 assert!(matches!(receiver.try_recv(), Err(_)));
791 assert!(errors.try_recv().is_none());
792
793 let errors = ServoErrorChannel::default();
795 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
796 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
797 drop(receiver);
798 request.intercept(web_resource_response()).cancel();
799 assert!(errors.try_recv().is_some());
800
801 let errors = ServoErrorChannel::default();
803 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
804 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
805 drop(receiver);
806 drop(request.intercept(web_resource_response()));
807 assert!(errors.try_recv().is_some());
808
809 let errors = ServoErrorChannel::default();
811 let (sender, receiver) = generic_channel::channel().expect("Failed to create IPC channel");
812 let request = WebResourceLoad::new(web_resource_request(), sender, errors.sender());
813 drop(receiver);
814 drop(request);
815 assert!(errors.try_recv().is_none());
816}