script: Stubs for geolocation interfaces (#39584)

Needed for #39526; stubs out all the necessary interface from
https://www.w3.org/TR/geolocation/.

Testing: WPT

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
This commit is contained in:
Ashwin Naren 2025-10-01 21:17:36 -07:00 committed by GitHub
parent 9e380614ee
commit 65588cd5df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 494 additions and 5 deletions

View file

@ -114,6 +114,7 @@ pub struct Preferences {
pub dom_fontface_enabled: bool,
pub dom_fullscreen_test: bool,
pub dom_gamepad_enabled: bool,
pub dom_geolocation_enabled: bool,
pub dom_indexeddb_enabled: bool,
pub dom_intersection_observer_enabled: bool,
pub dom_microdata_testing_enabled: bool,
@ -294,6 +295,7 @@ impl Preferences {
dom_fontface_enabled: false,
dom_fullscreen_test: false,
dom_gamepad_enabled: true,
dom_geolocation_enabled: false,
dom_indexeddb_enabled: false,
dom_intersection_observer_enabled: false,
dom_microdata_testing_enabled: false,

View file

@ -0,0 +1,91 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use dom_struct::dom_struct;
use rustc_hash::FxHashSet;
use script_bindings::codegen::GenericBindings::GeolocationBinding::Geolocation_Binding::GeolocationMethods;
use script_bindings::codegen::GenericBindings::GeolocationBinding::{
PositionCallback, PositionOptions,
};
use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
use script_bindings::reflector::Reflector;
use script_bindings::root::DomRoot;
use script_bindings::script_runtime::CanGc;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
use crate::dom::globalscope::GlobalScope;
#[dom_struct]
pub struct Geolocation {
reflector_: Reflector,
/// <https://www.w3.org/TR/geolocation/#dfn-watchids>
watch_ids: RefCell<FxHashSet<u32>>,
next_watch_id: Cell<u32>,
}
impl Geolocation {
fn new_inherited() -> Self {
Geolocation {
reflector_: Reflector::new(),
watch_ids: RefCell::new(FxHashSet::default()),
next_watch_id: Cell::new(1),
}
}
pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited()), global, can_gc)
}
}
impl GeolocationMethods<DomTypeHolder> for Geolocation {
/// <https://www.w3.org/TR/geolocation/#dom-geolocation-getcurrentposition>
fn GetCurrentPosition(
&self,
_success_callback: Rc<PositionCallback<DomTypeHolder>>,
_options: &PositionOptions,
) {
// Step 1. If this's relevant global object's associated Document is not fully active:
// if !self.global().as_window().Document().is_active() {
// Step 1.1 Call back with error errorCallback and POSITION_UNAVAILABLE.
// Step 1.2 Terminate this algorithm.
// return;
// }
// Step 2. Request a position passing this, successCallback, errorCallback, and options.
// FIXME(arihant2math)
}
/// <https://www.w3.org/TR/geolocation/#watchposition-method>
fn WatchPosition(
&self,
_success_callback: Rc<PositionCallback<DomTypeHolder>>,
_options: &PositionOptions,
) -> i32 {
// Step 1. If this's relevant global object's associated Document is not fully active:
if !self.global().as_window().Document().is_active() {
// Step 1.1 Call back with error errorCallback and POSITION_UNAVAILABLE.
// Step 1.2 Return 0.
return 0;
}
// Step 2. Let watchId be an implementation-defined unsigned long that is greater than zero.
let watch_id = self.next_watch_id.get();
self.next_watch_id.set(watch_id + 1);
// Step 3. Append watchId to this's [[watchIDs]].
self.watch_ids.borrow_mut().insert(watch_id);
// Step 4. Request a position passing this, successCallback, errorCallback, options, and watchId.
// FIXME(arihant2math)
// Step 5. Return watchId.
watch_id as i32
}
/// <https://www.w3.org/TR/geolocation/#clearwatch-method>
fn ClearWatch(&self, watch_id: i32) {
let watch_id = u32::try_from(watch_id).ok();
if let Some(id) = watch_id {
self.watch_ids.borrow_mut().remove(&id);
}
}
}

View file

@ -0,0 +1,105 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use script_bindings::codegen::GenericBindings::GeolocationCoordinatesBinding::GeolocationCoordinatesMethods;
use script_bindings::num::Finite;
use script_bindings::reflector::Reflector;
use script_bindings::root::DomRoot;
use script_bindings::script_runtime::CanGc;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::globalscope::GlobalScope;
#[dom_struct]
pub struct GeolocationCoordinates {
reflector_: Reflector,
accuracy: Finite<f64>,
latitude: Finite<f64>,
longitude: Finite<f64>,
altitude: Option<Finite<f64>>,
altitude_accuracy: Option<Finite<f64>>,
heading: Option<Finite<f64>>,
speed: Option<Finite<f64>>,
}
impl GeolocationCoordinates {
fn new_inherited(
accuracy: Finite<f64>,
latitude: Finite<f64>,
longitude: Finite<f64>,
altitude: Option<Finite<f64>>,
altitude_accuracy: Option<Finite<f64>>,
heading: Option<Finite<f64>>,
speed: Option<Finite<f64>>,
) -> Self {
GeolocationCoordinates {
reflector_: Reflector::new(),
accuracy,
latitude,
longitude,
altitude,
altitude_accuracy,
heading,
speed,
}
}
#[expect(unused, clippy::too_many_arguments)]
pub(crate) fn new(
global: &GlobalScope,
accuracy: Finite<f64>,
latitude: Finite<f64>,
longitude: Finite<f64>,
altitude: Option<Finite<f64>>,
altitude_accuracy: Option<Finite<f64>>,
heading: Option<Finite<f64>>,
speed: Option<Finite<f64>>,
can_gc: CanGc,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(Self::new_inherited(
accuracy,
latitude,
longitude,
altitude,
altitude_accuracy,
heading,
speed,
)),
global,
can_gc,
)
}
}
impl GeolocationCoordinatesMethods<crate::DomTypeHolder> for GeolocationCoordinates {
fn Accuracy(&self) -> Finite<f64> {
self.accuracy
}
fn Latitude(&self) -> Finite<f64> {
self.latitude
}
fn Longitude(&self) -> Finite<f64> {
self.longitude
}
fn GetAltitude(&self) -> Option<Finite<f64>> {
self.altitude
}
fn GetAltitudeAccuracy(&self) -> Option<Finite<f64>> {
self.altitude_accuracy
}
fn GetHeading(&self) -> Option<Finite<f64>> {
self.heading
}
fn GetSpeed(&self) -> Option<Finite<f64>> {
self.speed
}
}

View file

@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use script_bindings::codegen::GenericBindings::GeolocationPositionBinding::GeolocationPositionMethods;
use script_bindings::reflector::Reflector;
use script_bindings::root::{Dom, DomRoot};
use script_bindings::script_runtime::CanGc;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::geolocationcoordinates::GeolocationCoordinates;
use crate::dom::globalscope::GlobalScope;
#[dom_struct]
pub struct GeolocationPosition {
reflector_: Reflector,
coords: Dom<GeolocationCoordinates>,
timestamp: u64,
}
impl GeolocationPosition {
fn new_inherited(coords: &GeolocationCoordinates, timestamp: u64) -> Self {
GeolocationPosition {
reflector_: Reflector::new(),
coords: Dom::from_ref(coords),
timestamp,
}
}
#[expect(unused)]
pub(crate) fn new(
global: &GlobalScope,
coords: &GeolocationCoordinates,
timestamp: u64,
can_gc: CanGc,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(Self::new_inherited(coords, timestamp)),
global,
can_gc,
)
}
}
impl GeolocationPositionMethods<DomTypeHolder> for GeolocationPosition {
fn Coords(&self) -> DomRoot<GeolocationCoordinates> {
DomRoot::from_ref(&*self.coords.clone())
}
fn Timestamp(&self) -> u64 {
self.timestamp
}
}

View file

@ -0,0 +1,51 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use dom_struct::dom_struct;
use script_bindings::codegen::GenericBindings::GeolocationPositionErrorBinding::GeolocationPositionErrorMethods;
use script_bindings::reflector::Reflector;
use script_bindings::root::DomRoot;
use script_bindings::script_runtime::CanGc;
use script_bindings::str::DOMString;
use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::globalscope::GlobalScope;
#[dom_struct]
pub struct GeolocationPositionError {
reflector_: Reflector,
code: u16,
message: DOMString,
}
impl GeolocationPositionError {
fn new_inherited(code: u16, message: DOMString) -> Self {
GeolocationPositionError {
reflector_: Reflector::new(),
code,
message,
}
}
#[expect(unused)]
pub(crate) fn new(
global: &GlobalScope,
code: u16,
message: DOMString,
can_gc: CanGc,
) -> DomRoot<Self> {
reflect_dom_object(Box::new(Self::new_inherited(code, message)), global, can_gc)
}
}
impl GeolocationPositionErrorMethods<DomTypeHolder> for GeolocationPositionError {
fn Code(&self) -> u16 {
self.code
}
fn Message(&self) -> DOMString {
self.message.clone()
}
}

View file

@ -0,0 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#[expect(clippy::module_inception, reason = "The interface name is Geolocation")]
pub(crate) mod geolocation;
pub(crate) use geolocation::Geolocation;
pub(crate) mod geolocationcoordinates;
pub(crate) mod geolocationposition;
pub(crate) mod geolocationpositionerror;

View file

@ -325,6 +325,8 @@ pub(crate) mod formdata;
pub(crate) mod formdataevent;
pub(crate) mod gamepad;
pub(crate) use self::gamepad::*;
pub(crate) mod geolocation;
pub(crate) use self::geolocation::*;
#[allow(dead_code)]
pub(crate) mod globalscope;
pub(crate) mod hashchangeevent;

View file

@ -38,6 +38,7 @@ use crate::dom::credentialmanagement::credentialscontainer::CredentialsContainer
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::gamepad::Gamepad;
use crate::dom::gamepad::gamepadevent::GamepadEventType;
use crate::dom::geolocation::Geolocation;
use crate::dom::globalscope::GlobalScope;
use crate::dom::mediadevices::MediaDevices;
use crate::dom::mediasession::MediaSession;
@ -238,6 +239,11 @@ impl NavigatorMethods<crate::DomTypeHolder> for Navigator {
.or_init(|| CredentialsContainer::new(&self.global(), CanGc::note()))
}
// https://www.w3.org/TR/geolocation/#navigator_interface
fn Geolocation(&self) -> DomRoot<Geolocation> {
Geolocation::new(&self.global(), CanGc::note())
}
// https://html.spec.whatwg.org/multipage/#navigatorlanguage
fn Language(&self) -> DOMString {
navigatorinfo::Language()

View file

@ -116,6 +116,7 @@ pub(crate) enum ScriptThreadEventCategory {
FileRead,
FontLoading,
FormPlannedNavigation,
GeolocationEvent,
HistoryEvent,
ImageCacheMsg,
InputEvent,
@ -157,6 +158,7 @@ impl From<ScriptThreadEventCategory> for ProfilerCategory {
ScriptThreadEventCategory::FormPlannedNavigation => {
ProfilerCategory::ScriptPlannedNavigation
},
ScriptThreadEventCategory::GeolocationEvent => ProfilerCategory::ScriptGeolocationEvent,
ScriptThreadEventCategory::HistoryEvent => ProfilerCategory::ScriptHistoryEvent,
ScriptThreadEventCategory::ImageCacheMsg => ProfilerCategory::ScriptImageCacheMsg,
ScriptThreadEventCategory::InputEvent => ProfilerCategory::ScriptInputEvent,
@ -203,6 +205,7 @@ impl From<ScriptThreadEventCategory> for ScriptHangAnnotation {
ScriptThreadEventCategory::FormPlannedNavigation => {
ScriptHangAnnotation::FormPlannedNavigation
},
ScriptThreadEventCategory::GeolocationEvent => ScriptHangAnnotation::GeolocationEvent,
ScriptThreadEventCategory::HistoryEvent => ScriptHangAnnotation::HistoryEvent,
ScriptThreadEventCategory::ImageCacheMsg => ScriptHangAnnotation::ImageCacheMsg,
ScriptThreadEventCategory::NetworkEvent => ScriptHangAnnotation::NetworkEvent,

View file

@ -1616,6 +1616,14 @@ impl ScriptThread {
profiler_chan,
f
),
ScriptThreadEventCategory::GeolocationEvent => {
time_profile!(
ProfilerCategory::ScriptGeolocationEvent,
None,
profiler_chan,
f
)
},
ScriptThreadEventCategory::HistoryEvent => {
time_profile!(ProfilerCategory::ScriptHistoryEvent, None, profiler_chan, f)
},

View file

@ -141,6 +141,8 @@ impl TaskManager {
task_source_functions!(self, file_reading_task_source, FileReading);
task_source_functions!(self, font_loading_task_source, FontLoading);
task_source_functions!(self, gamepad_task_source, Gamepad);
// FIXME(arihant2math): uncomment when geolocation is implemented.
// task_source_functions!(self, geolocation_task_source, Geolocation);
task_source_functions!(self, media_element_task_source, MediaElement);
task_source_functions!(self, networking_task_source, Networking);
task_source_functions!(self, performance_timeline_task_source, PerformanceTimeline);

View file

@ -46,6 +46,8 @@ pub(crate) enum TaskSourceName {
Timer,
/// <https://www.w3.org/TR/gamepad/#dfn-gamepad-task-source>
Gamepad,
/// <https://www.w3.org/TR/geolocation/#dfn-geolocation-task-source>
Geolocation,
/// <https://w3c.github.io/IntersectionObserver/#intersectionobserver-task-source>
IntersectionObserver,
/// <https://www.w3.org/TR/webgpu/#-webgpu-task-source>
@ -63,6 +65,7 @@ impl From<TaskSourceName> for ScriptThreadEventCategory {
TaskSourceName::DOMManipulation => ScriptThreadEventCategory::ScriptEvent,
TaskSourceName::FileReading => ScriptThreadEventCategory::FileRead,
TaskSourceName::FontLoading => ScriptThreadEventCategory::FontLoading,
TaskSourceName::Geolocation => ScriptThreadEventCategory::GeolocationEvent,
TaskSourceName::HistoryTraversal => ScriptThreadEventCategory::HistoryEvent,
TaskSourceName::Networking => ScriptThreadEventCategory::NetworkEvent,
TaskSourceName::PerformanceTimeline => {

View file

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://www.w3.org/TR/geolocation/#geolocation_interface
*/
partial interface Navigator {
[SameObject, Pref="dom_geolocation_enabled"] readonly attribute Geolocation geolocation;
};
// FIXME: The errorCallback parameters are currently commented out because they are not yet supported by the codegen,
// further debugging is needed.
// https://www.w3.org/TR/geolocation/#geolocation_interface
[Pref="dom_geolocation_enabled", Exposed=Window]
interface Geolocation {
undefined getCurrentPosition (
PositionCallback successCallback,
// optional PositionErrorCallback? errorCallback = null,
optional PositionOptions options = {}
);
long watchPosition (
PositionCallback successCallback,
// optional PositionErrorCallback? errorCallback = null,
optional PositionOptions options = {}
);
undefined clearWatch (long watchId);
};
callback PositionCallback = undefined (
GeolocationPosition position
);
callback PositionErrorCallback = undefined (
GeolocationPositionError positionError
);
// https://www.w3.org/TR/geolocation/#position_options_interface
dictionary PositionOptions {
boolean enableHighAccuracy = false;
[Clamp] unsigned long timeout = 0xFFFFFFFF;
[Clamp] unsigned long maximumAge = 0;
};

View file

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://www.w3.org/TR/geolocation/#coordinates_interface
*/
// https://www.w3.org/TR/geolocation/#coordinates_interface
[Pref="dom_geolocation_enabled", Exposed=Window, SecureContext]
interface GeolocationCoordinates {
readonly attribute double accuracy;
readonly attribute double latitude;
readonly attribute double longitude;
readonly attribute double? altitude;
readonly attribute double? altitudeAccuracy;
readonly attribute double? heading;
readonly attribute double? speed;
};

View file

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://www.w3.org/TR/geolocation/#position_interface
*/
// https://www.w3.org/TR/geolocation/#position_interface
[Pref="dom_geolocation_enabled", Exposed=Window, SecureContext]
interface GeolocationPosition {
readonly attribute GeolocationCoordinates coords;
readonly attribute EpochTimeStamp timestamp;
};

View file

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* The origin of this IDL file is
* https://www.w3.org/TR/geolocation/#position_error_interface
*/
// https://www.w3.org/TR/geolocation/#position_error_interface
[Pref="dom_geolocation_enabled", Exposed=Window]
interface GeolocationPositionError {
const unsigned short PERMISSION_DENIED = 1;
const unsigned short POSITION_UNAVAILABLE = 2;
const unsigned short TIMEOUT = 3;
readonly attribute unsigned short code;
readonly attribute DOMString message;
};

View file

@ -23,6 +23,7 @@ pub enum ScriptHangAnnotation {
FileRead,
FontLoading,
FormPlannedNavigation,
GeolocationEvent,
ImageCacheMsg,
InputEvent,
HistoryEvent,

View file

@ -105,12 +105,13 @@ pub enum ProfilerCategory {
ScriptEnterFullscreen = 0x79,
ScriptExitFullscreen = 0x7a,
ScriptWorkletEvent = 0x7b,
ScriptPerformanceEvent = 0x7c,
ScriptHistoryEvent = 0x7d,
ScriptPortMessage = 0x7e,
ScriptWebGPUMsg = 0x7f,
ScriptGeolocationEvent = 0x7c,
ScriptPerformanceEvent = 0x7d,
ScriptHistoryEvent = 0x7e,
ScriptPortMessage = 0x7f,
ScriptWebGPUMsg = 0x80,
ScriptDatabaseAccessEvent = 0x80,
ScriptDatabaseAccessEvent = 0x81,
/// Web performance metrics.
TimeToFirstPaint = 0x90,
@ -136,6 +137,7 @@ impl ProfilerCategory {
ProfilerCategory::ScriptEvent => "ScriptEvent",
ProfilerCategory::ScriptFileRead => "ScriptFileRead",
ProfilerCategory::ScriptFontLoading => "ScriptFontLoading",
ProfilerCategory::ScriptGeolocationEvent => "ScriptGeolocationEvent",
ProfilerCategory::ScriptImageCacheMsg => "ScriptImageCacheMsg",
ProfilerCategory::ScriptInputEvent => "ScriptInputEvent",
ProfilerCategory::ScriptNetworkEvent => "ScriptNetworkEvent",