embedder_traits/geolocation.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Types used to request geographic position data from the embedding layer.
6//!
7//! See <https://www.w3.org/TR/geolocation/>.
8
9use malloc_size_of_derive::MallocSizeOf;
10use serde::{Deserialize, Serialize};
11use servo_base::id::{PipelineId, WebViewId};
12
13/// Identifies a single ongoing watchPosition() subscription. A subscription lives as long as
14/// the Document that started it, so the identifier is scoped to a pipeline rather than being
15/// globally unique.
16#[derive(Clone, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
17pub struct GeolocationWatchId {
18 #[doc(hidden)]
19 pub webview_id: WebViewId,
20 #[doc(hidden)]
21 pub pipeline_id: PipelineId,
22 /// The `watchId` returned to script by `watchPosition()`.
23 #[doc(hidden)]
24 pub index: u32,
25}
26
27/// Hints about how a position should be acquired.
28#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
29pub struct GeolocationRequestOptions {
30 /// A hint that the application would like to receive the most accurate location data
31 /// available, at the cost of response time and power consumption.
32 ///
33 /// <https://www.w3.org/TR/geolocation/#dom-positionoptions-enablehighaccuracy>
34 pub high_accuracy: bool,
35}
36
37/// A position acquired from the underlying system.
38///
39/// This mirrors the spec's "positionData" map, which is used to construct a
40/// GeolocationCoordinates.
41///
42/// <https://www.w3.org/TR/geolocation/#dfn-acquire-a-position>
43#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
44pub struct GeolocationPositionData {
45 /// The accuracy, in meters, at the 95% confidence level. Must not be negative.
46 pub accuracy: f64,
47 /// Degrees north of the Equator.
48 pub latitude: f64,
49 /// Degrees east of the Prime Meridian.
50 pub longitude: f64,
51 /// Meters above the WGS84 ellipsoid, or `None` if not available.
52 pub altitude: Option<f64>,
53 /// Accuracy of [`Self::altitude`] in meters at the 95% confidence level, or `None` if not
54 /// available. Must not be negative.
55 pub altitude_accuracy: Option<f64>,
56 /// Direction of travel in degrees clockwise from true north, or `None` if not available.
57 /// Servo reports `None` to script whenever [`Self::speed`] is zero, so an embedder does not
58 /// need to special-case a stationary device.
59 pub heading: Option<f64>,
60 /// Ground speed in meters per second, or `None` if not available. Must not be negative.
61 pub speed: Option<f64>,
62}
63
64impl GeolocationPositionData {
65 /// Create position data for a device whose altitude, heading and speed are unknown.
66 pub fn new(latitude: f64, longitude: f64, accuracy: f64) -> Self {
67 Self {
68 accuracy,
69 latitude,
70 longitude,
71 altitude: None,
72 altitude_accuracy: None,
73 heading: None,
74 speed: None,
75 }
76 }
77}
78
79/// The reason a position could not be acquired. These map directly onto the constants of
80/// `GeolocationPositionError`.
81///
82/// <https://www.w3.org/TR/geolocation/#position_error_interface>
83#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
84pub enum GeolocationErrorKind {
85 /// The user or the operating system refused access to the location service. Note that this is
86 /// distinct from the user refusing Servo's own permission prompt, which never reaches the
87 /// embedder's geolocation backend.
88 PermissionDenied,
89 /// The location service failed, or is not available on this platform.
90 PositionUnavailable,
91 /// Acquiring a position took longer than the page allowed.
92 Timeout,
93}
94
95/// A failure to acquire a position, as reported by the embedding layer.
96#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
97pub struct GeolocationError {
98 /// Which of the `GeolocationPositionError` constants to report to script.
99 pub kind: GeolocationErrorKind,
100 /// A human-readable description. The spec does not constrain this value.
101 pub message: String,
102}
103
104impl GeolocationError {
105 /// A [`GeolocationErrorKind::PositionUnavailable`] error with the given message.
106 pub fn position_unavailable(message: impl Into<String>) -> Self {
107 Self {
108 kind: GeolocationErrorKind::PositionUnavailable,
109 message: message.into(),
110 }
111 }
112
113 /// A [`GeolocationErrorKind::PermissionDenied`] error with the given message.
114 pub fn permission_denied(message: impl Into<String>) -> Self {
115 Self {
116 kind: GeolocationErrorKind::PermissionDenied,
117 message: message.into(),
118 }
119 }
120
121 /// A [`GeolocationErrorKind::Timeout`] error with the given message.
122 pub fn timeout(message: impl Into<String>) -> Self {
123 Self {
124 kind: GeolocationErrorKind::Timeout,
125 message: message.into(),
126 }
127 }
128}
129
130/// The reply sent back to script for a one-shot position request, or for each update of an
131/// ongoing watch.
132pub type GeolocationResult = Result<GeolocationPositionData, GeolocationError>;