Skip to main content

script/dom/geolocation/
geolocationcoordinates.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
5use dom_struct::dom_struct;
6use embedder_traits::GeolocationPositionData;
7use js::context::JSContext;
8use script_bindings::codegen::GenericBindings::GeolocationCoordinatesBinding::GeolocationCoordinatesMethods;
9use script_bindings::num::Finite;
10use script_bindings::reflector::{Reflector, reflect_dom_object};
11use script_bindings::root::DomRoot;
12
13use crate::dom::globalscope::GlobalScope;
14
15#[dom_struct]
16pub struct GeolocationCoordinates {
17    reflector_: Reflector,
18    accuracy: Finite<f64>,
19    latitude: Finite<f64>,
20    longitude: Finite<f64>,
21    altitude: Option<Finite<f64>>,
22    altitude_accuracy: Option<Finite<f64>>,
23    heading: Option<Finite<f64>>,
24    speed: Option<Finite<f64>>,
25}
26
27/// The outer `Option` reports whether the value was representable while the inner one is the
28/// attribute's own nullability.
29fn optional_finite(value: Option<f64>) -> Option<Option<Finite<f64>>> {
30    match value {
31        None => Some(None),
32        Some(value) => Finite::new(value).map(Some),
33    }
34}
35
36impl GeolocationCoordinates {
37    fn new_inherited(
38        accuracy: Finite<f64>,
39        latitude: Finite<f64>,
40        longitude: Finite<f64>,
41        altitude: Option<Finite<f64>>,
42        altitude_accuracy: Option<Finite<f64>>,
43        heading: Option<Finite<f64>>,
44        speed: Option<Finite<f64>>,
45    ) -> Self {
46        GeolocationCoordinates {
47            reflector_: Reflector::new(),
48            accuracy,
49            latitude,
50            longitude,
51            altitude,
52            altitude_accuracy,
53            heading,
54            speed,
55        }
56    }
57
58    /// Step 1 and 2 of "constructing a `GeolocationPosition`"
59    /// Returns `None` if the platform reported a value that cannot be represented as an
60    /// unrestricted double, in which case the caller should report `POSITION_UNAVAILABLE`.
61    ///
62    /// [spec]: https://www.w3.org/TR/geolocation/#dfn-a-new-geolocationposition
63    pub(crate) fn from_position_data(
64        cx: &mut JSContext,
65        global: &GlobalScope,
66        data: &GeolocationPositionData,
67    ) -> Option<DomRoot<Self>> {
68        // > "heading": A double? that represents the heading in degrees, or null if not available
69        // > or the device is stationary.
70        let heading = if data.speed == Some(0.0) {
71            None
72        } else {
73            optional_finite(data.heading)?
74        };
75
76        Some(reflect_dom_object(
77            cx,
78            Box::new(Self::new_inherited(
79                Finite::new(data.accuracy)?,
80                Finite::new(data.latitude)?,
81                Finite::new(data.longitude)?,
82                optional_finite(data.altitude)?,
83                optional_finite(data.altitude_accuracy)?,
84                heading,
85                optional_finite(data.speed)?,
86            )),
87            global,
88        ))
89    }
90}
91
92impl GeolocationCoordinatesMethods<crate::DomTypeHolder> for GeolocationCoordinates {
93    fn Accuracy(&self) -> Finite<f64> {
94        self.accuracy
95    }
96
97    fn Latitude(&self) -> Finite<f64> {
98        self.latitude
99    }
100
101    fn Longitude(&self) -> Finite<f64> {
102        self.longitude
103    }
104
105    fn GetAltitude(&self) -> Option<Finite<f64>> {
106        self.altitude
107    }
108
109    fn GetAltitudeAccuracy(&self) -> Option<Finite<f64>> {
110        self.altitude_accuracy
111    }
112
113    fn GetHeading(&self) -> Option<Finite<f64>> {
114        self.heading
115    }
116
117    fn GetSpeed(&self) -> Option<Finite<f64>> {
118        self.speed
119    }
120}