script/dom/geolocation/
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/. */
4use std::cell::{Cell, RefCell};
5use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use rustc_hash::FxHashSet;
9use script_bindings::codegen::GenericBindings::GeolocationBinding::Geolocation_Binding::GeolocationMethods;
10use script_bindings::codegen::GenericBindings::GeolocationBinding::{
11    PositionCallback, PositionOptions,
12};
13use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
14use script_bindings::reflector::Reflector;
15use script_bindings::root::DomRoot;
16use script_bindings::script_runtime::CanGc;
17
18use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
19use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
20use crate::dom::globalscope::GlobalScope;
21
22#[dom_struct]
23pub struct Geolocation {
24    reflector_: Reflector,
25    /// <https://www.w3.org/TR/geolocation/#dfn-watchids>
26    watch_ids: RefCell<FxHashSet<u32>>,
27    next_watch_id: Cell<u32>,
28}
29
30impl Geolocation {
31    fn new_inherited() -> Self {
32        Geolocation {
33            reflector_: Reflector::new(),
34            watch_ids: RefCell::new(FxHashSet::default()),
35            next_watch_id: Cell::new(1),
36        }
37    }
38
39    pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Self> {
40        reflect_dom_object(Box::new(Self::new_inherited()), global, can_gc)
41    }
42}
43
44impl GeolocationMethods<DomTypeHolder> for Geolocation {
45    /// <https://www.w3.org/TR/geolocation/#dom-geolocation-getcurrentposition>
46    fn GetCurrentPosition(
47        &self,
48        _success_callback: Rc<PositionCallback<DomTypeHolder>>,
49        _options: &PositionOptions,
50    ) {
51        // Step 1. If this's relevant global object's associated Document is not fully active:
52        // if !self.global().as_window().Document().is_active() {
53        // Step 1.1 Call back with error errorCallback and POSITION_UNAVAILABLE.
54        // Step 1.2 Terminate this algorithm.
55        // return;
56        // }
57        // Step 2. Request a position passing this, successCallback, errorCallback, and options.
58        // FIXME(arihant2math)
59    }
60
61    /// <https://www.w3.org/TR/geolocation/#watchposition-method>
62    fn WatchPosition(
63        &self,
64        _success_callback: Rc<PositionCallback<DomTypeHolder>>,
65        _options: &PositionOptions,
66    ) -> i32 {
67        // Step 1. If this's relevant global object's associated Document is not fully active:
68        if !self.global().as_window().Document().is_active() {
69            // Step 1.1 Call back with error errorCallback and POSITION_UNAVAILABLE.
70            // Step 1.2 Return 0.
71            return 0;
72        }
73        // Step 2. Let watchId be an implementation-defined unsigned long that is greater than zero.
74        let watch_id = self.next_watch_id.get();
75        self.next_watch_id.set(watch_id + 1);
76        // Step 3. Append watchId to this's [[watchIDs]].
77        self.watch_ids.borrow_mut().insert(watch_id);
78        // Step 4. Request a position passing this, successCallback, errorCallback, options, and watchId.
79        // FIXME(arihant2math)
80        // Step 5. Return watchId.
81        watch_id as i32
82    }
83
84    /// <https://www.w3.org/TR/geolocation/#clearwatch-method>
85    fn ClearWatch(&self, watch_id: i32) {
86        let watch_id = u32::try_from(watch_id).ok();
87        if let Some(id) = watch_id {
88            self.watch_ids.borrow_mut().remove(&id);
89        }
90    }
91}