fission_shell_winit/
geolocation.rs1use fission_core::{
2 GeolocationError, GeolocationPermission, GeolocationPermissionRequest, GeolocationPosition,
3 GeolocationPositionRequest, GET_CURRENT_POSITION, GET_GEOLOCATION_PERMISSION,
4 REQUEST_GEOLOCATION_PERMISSION,
5};
6use fission_shell::async_host::AsyncRegistry;
7use std::sync::Arc;
8
9pub trait GeolocationHost: Send + Sync + 'static {
11 fn permission(&self) -> Result<GeolocationPermission, GeolocationError>;
13 fn request_permission(
15 &self,
16 request: GeolocationPermissionRequest,
17 ) -> Result<GeolocationPermission, GeolocationError>;
18 fn current_position(
20 &self,
21 request: GeolocationPositionRequest,
22 ) -> Result<GeolocationPosition, GeolocationError>;
23}
24
25#[derive(Debug, Default)]
26pub struct UnsupportedGeolocationHost;
27
28impl GeolocationHost for UnsupportedGeolocationHost {
29 fn permission(&self) -> Result<GeolocationPermission, GeolocationError> {
30 Ok(GeolocationPermission::Unsupported)
31 }
32
33 fn request_permission(
34 &self,
35 _request: GeolocationPermissionRequest,
36 ) -> Result<GeolocationPermission, GeolocationError> {
37 Ok(GeolocationPermission::Unsupported)
38 }
39
40 fn current_position(
41 &self,
42 _request: GeolocationPositionRequest,
43 ) -> Result<GeolocationPosition, GeolocationError> {
44 Err(GeolocationError::unsupported("current_position"))
45 }
46}
47
48#[derive(Debug, Clone)]
49pub struct MemoryGeolocationHost {
50 position: GeolocationPosition,
51}
52
53impl MemoryGeolocationHost {
54 pub fn new(position: GeolocationPosition) -> Self {
55 Self { position }
56 }
57}
58
59impl Default for MemoryGeolocationHost {
60 fn default() -> Self {
61 Self {
62 position: GeolocationPosition {
63 latitude: 51.5074,
64 longitude: -0.1278,
65 altitude_meters: None,
66 accuracy_meters: 10.0,
67 altitude_accuracy_meters: None,
68 heading_degrees: None,
69 speed_mps: None,
70 timestamp_unix_ms: 1_774_000_000_000,
71 },
72 }
73 }
74}
75
76impl GeolocationHost for MemoryGeolocationHost {
77 fn permission(&self) -> Result<GeolocationPermission, GeolocationError> {
78 Ok(GeolocationPermission::Granted)
79 }
80
81 fn request_permission(
82 &self,
83 _request: GeolocationPermissionRequest,
84 ) -> Result<GeolocationPermission, GeolocationError> {
85 Ok(GeolocationPermission::Granted)
86 }
87
88 fn current_position(
89 &self,
90 _request: GeolocationPositionRequest,
91 ) -> Result<GeolocationPosition, GeolocationError> {
92 Ok(self.position.clone())
93 }
94}
95
96pub(crate) fn register_geolocation_capabilities(
97 async_registry: &mut AsyncRegistry,
98 host: Arc<dyn GeolocationHost>,
99) {
100 let permission_host = host.clone();
101 async_registry.register_operation_capability(GET_GEOLOCATION_PERMISSION, move |(), _| {
102 let host = permission_host.clone();
103 async move { host.permission() }
104 });
105
106 let request_host = host.clone();
107 async_registry.register_operation_capability(
108 REQUEST_GEOLOCATION_PERMISSION,
109 move |request, _| {
110 let host = request_host.clone();
111 async move { host.request_permission(request) }
112 },
113 );
114
115 async_registry.register_operation_capability(GET_CURRENT_POSITION, move |request, _| {
116 let host = host.clone();
117 async move { host.current_position(request) }
118 });
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn unsupported_host_reports_unsupported() {
127 let host = UnsupportedGeolocationHost;
128 assert_eq!(
129 host.permission().unwrap(),
130 GeolocationPermission::Unsupported
131 );
132 assert!(host
133 .current_position(GeolocationPositionRequest::default())
134 .is_err());
135 }
136
137 #[test]
138 fn memory_host_returns_position() {
139 let host = MemoryGeolocationHost::default();
140 assert_eq!(host.permission().unwrap(), GeolocationPermission::Granted);
141 assert_eq!(
142 host.current_position(GeolocationPositionRequest::default())
143 .unwrap()
144 .latitude,
145 51.5074
146 );
147 }
148}