Skip to main content

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>;