servo/
geolocation_delegate.rs1use embedder_traits::{
6 GeolocationError, GeolocationPositionData, GeolocationRequestOptions, GeolocationResult,
7 GeolocationWatchId,
8};
9use servo_base::generic_channel::GenericCallback;
10use servo_config::pref;
11
12use crate::WebView;
13
14pub struct PositionRequest {
17 result_sender: GenericCallback<GeolocationResult>,
18 options: GeolocationRequestOptions,
19 response_sent: bool,
20}
21
22impl PositionRequest {
23 pub(crate) fn new(
24 result_sender: GenericCallback<GeolocationResult>,
25 options: GeolocationRequestOptions,
26 ) -> Self {
27 Self {
28 result_sender,
29 options,
30 response_sent: false,
31 }
32 }
33
34 pub fn options(&self) -> &GeolocationRequestOptions {
36 &self.options
37 }
38
39 pub fn success(mut self, position: GeolocationPositionData) {
41 let _ = self.result_sender.send(Ok(position));
42 self.response_sent = true;
43 }
44
45 pub fn failure(mut self, error: GeolocationError) {
47 let _ = self.result_sender.send(Err(error));
48 self.response_sent = true;
49 }
50}
51
52impl Drop for PositionRequest {
53 fn drop(&mut self) {
54 if !self.response_sent {
55 let _ = self
56 .result_sender
57 .send(Err(GeolocationError::position_unavailable(
58 "No response sent for request.",
59 )));
60 }
61 }
62}
63
64pub struct PositionWatch {
67 id: GeolocationWatchId,
68 result_sender: GenericCallback<GeolocationResult>,
69 options: GeolocationRequestOptions,
70}
71
72impl PositionWatch {
73 pub(crate) fn new(
74 id: GeolocationWatchId,
75 result_sender: GenericCallback<GeolocationResult>,
76 options: GeolocationRequestOptions,
77 ) -> Self {
78 Self {
79 id,
80 result_sender,
81 options,
82 }
83 }
84
85 pub fn id(&self) -> GeolocationWatchId {
87 self.id.clone()
88 }
89
90 pub fn options(&self) -> &GeolocationRequestOptions {
92 &self.options
93 }
94
95 pub fn update(&self, position: GeolocationPositionData) {
97 let _ = self.result_sender.send(Ok(position));
98 }
99
100 pub fn error(&self, error: GeolocationError) {
103 let _ = self.result_sender.send(Err(error));
104 }
105}
106
107pub trait GeolocationDelegate {
109 fn request_position(&self, _webview: WebView, request: PositionRequest) {
111 match default_position_response() {
112 Ok(position) => request.success(position),
113 Err(error) => request.failure(error),
114 }
115 }
116
117 fn start_watch(&self, _webview: WebView, watch: PositionWatch) {
119 match default_position_response() {
120 Ok(position) => watch.update(position),
121 Err(error) => watch.error(error),
122 }
123 }
124
125 fn stop_watch(&self, _webview: WebView, _id: &GeolocationWatchId) {}
128}
129
130fn default_position_response() -> GeolocationResult {
133 if !pref!(dom_geolocation_test_position_enabled) {
134 return Err(GeolocationError::position_unavailable(
135 "No geolocation backend is available.",
136 ));
137 }
138
139 Ok(GeolocationPositionData {
140 accuracy: pref!(dom_geolocation_test_accuracy),
141 latitude: pref!(dom_geolocation_test_latitude),
142 longitude: pref!(dom_geolocation_test_longitude),
143 altitude: None,
144 altitude_accuracy: None,
145 heading: Some(pref!(dom_geolocation_test_heading)),
146 speed: Some(pref!(dom_geolocation_test_speed)),
147 })
148}
149
150pub(crate) struct DefaultGeolocationDelegate;
151
152impl GeolocationDelegate for DefaultGeolocationDelegate {}