From 920bb84fd7028f1e1173e992cfee8030b674490b Mon Sep 17 00:00:00 2001 From: Niccolo Antonelli-Dziri Date: Sat, 18 Apr 2026 16:29:18 +0200 Subject: [PATCH] LibWeb: Support Geolocation permission Add the 'requesting permission to use a powerful feature' algorithm to PermissionsAPI. In requesting geolocation, now checks for permission status. UI element to request permission to the user does not exist yet, and like previously, defaults to denied. A few tests pass because they use "geolocation" feature. --- Libraries/LibWeb/Geolocation/Geolocation.cpp | 22 +++++++--- .../LibWeb/PermissionsAPI/Permissions.cpp | 42 +++++++++++++++++- Libraries/LibWeb/PermissionsAPI/Permissions.h | 2 + .../Text/expected/all-window-properties.txt | 2 + .../permissions/all-permissions.txt | 25 +++++++++++ .../permissions/permissionsstatus-name.txt | 6 +++ .../permissions/all-permissions.html | 43 +++++++++++++++++++ .../permissions/permissionsstatus-name.html | 15 +++++++ 8 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/permissions/all-permissions.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/permissions/permissionsstatus-name.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/permissions/all-permissions.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/permissions/permissionsstatus-name.html diff --git a/Libraries/LibWeb/Geolocation/Geolocation.cpp b/Libraries/LibWeb/Geolocation/Geolocation.cpp index 4dcf2e541f..f0aa0a4aba 100644 --- a/Libraries/LibWeb/Geolocation/Geolocation.cpp +++ b/Libraries/LibWeb/Geolocation/Geolocation.cpp @@ -7,14 +7,17 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -324,15 +327,17 @@ void Geolocation::request_a_position(GC::Ref success_callb // 2. Continue to the next steps below. // AD-HOC: This is implemented by run_in_parallel_when_document_is_visible(). - // FIXME: 6. Let descriptor be a new PermissionDescriptor whose name is "geolocation". + // 6. Let descriptor be a new PermissionDescriptor whose name is "geolocation". + auto descriptor = Bindings::PermissionDescriptor { "geolocation"_string }; // 7. In parallel: // AD-HOC: run_in_parallel_when_document_is_visible() already runs this in parallel. { - // FIXME: 1. Set permission to request permission to use descriptor. + // 1. Set permission to request permission to use descriptor. + auto permission = Web::PermissionsAPI::request_permission(descriptor); - // FIXME: 2. If permission is "denied", then: - if (false) { + // 2. If permission is "denied", then: + if (permission == Bindings::PermissionState::Denied) { // 1. If watchId was passed, remove watchId from watchIDs. if (watch_id.has_value()) m_watch_ids.remove(watch_id.value()); @@ -371,7 +376,11 @@ void Geolocation::run_in_parallel_when_document_is_visible(DOM::Document& docume { // Run callback in parallel if the document is already visible. if (document.visibility_state_value() == HTML::VisibilityState::Visible) { - Platform::EventLoopPlugin::the().deferred_invoke(callback); + auto callback_with_context = GC::create_function(heap(), [this, callback] { + HTML::TemporaryExecutionContext execution_context { realm() }; + callback->function()(); + }); + Platform::EventLoopPlugin::the().deferred_invoke(callback_with_context); return; } @@ -389,9 +398,10 @@ void Geolocation::run_in_parallel_when_document_is_visible(DOM::Document& docume clear_observer_and_timer(); }); - document_observer->set_document_visibility_state_observer([clear_observer_and_timer, callback](HTML::VisibilityState state) { + document_observer->set_document_visibility_state_observer([this, clear_observer_and_timer, callback](HTML::VisibilityState state) { if (state == HTML::VisibilityState::Visible) { clear_observer_and_timer(); + HTML::TemporaryExecutionContext execution_context { realm() }; callback->function()(); } }); diff --git a/Libraries/LibWeb/PermissionsAPI/Permissions.cpp b/Libraries/LibWeb/PermissionsAPI/Permissions.cpp index 79564069dc..325114ac3d 100644 --- a/Libraries/LibWeb/PermissionsAPI/Permissions.cpp +++ b/Libraries/LibWeb/PermissionsAPI/Permissions.cpp @@ -20,12 +20,50 @@ namespace Web::PermissionsAPI { -bool is_permission_supported(String const&) +bool is_permission_supported(String const& name) { - // FIXME: Actually support permissions + if (name == "geolocation") { + return true; + } return false; } +// https://w3c.github.io/permissions/#dfn-request-permission-to-use +Bindings::PermissionState request_permission(Bindings::PermissionDescriptor const& descriptor) +{ + // 1. Let current state be the descriptor's permission state. + auto current_state = permission_state(descriptor); + + // 2. If current state is not "prompt", return current state and abort these steps. + if (current_state != Bindings::PermissionState::Prompt) + return current_state; + + // FIXME: 3. Ask the user for express permission for the calling algorithm to use the powerful feature described by descriptor. + + // 4. If the user gives express permission to use the powerful feature, set current state to "granted"; otherwise to "denied". + // The user's interaction may provide new information about the user's intent for the origin. + if (false) { + current_state = Bindings::PermissionState::Granted; + } else { + current_state = Bindings::PermissionState::Denied; + } + + // 5. Let settings be the current settings object. + auto& settings = HTML::current_settings_object(); + + // 6. Let key be the result of generating a permission key for descriptor with settings's top-level origin and settings's origin. + VERIFY(settings.top_level_origin.has_value()); + auto key = permission_key_generation_algorithm(settings.top_level_origin.value(), settings.origin()); + + // 7. Queue a task on the current settings object's responsible event loop to set a permission store entry with descriptor, key, and current state. + HTML::queue_global_task(HTML::Task::Source::Permissions, settings.global_object(), GC::create_function(settings.realm().heap(), [descriptor, key, current_state] { + PermissionStore::the().set_permission_store_entry(descriptor, key, current_state); + })); + + // 8. Return current state. + return current_state; +} + // https://w3c.github.io/permissions/#dfn-permission-state Bindings::PermissionState permission_state(Bindings::PermissionDescriptor descriptor, Optional settings) { diff --git a/Libraries/LibWeb/PermissionsAPI/Permissions.h b/Libraries/LibWeb/PermissionsAPI/Permissions.h index 1c28d3e9d9..7890efebe0 100644 --- a/Libraries/LibWeb/PermissionsAPI/Permissions.h +++ b/Libraries/LibWeb/PermissionsAPI/Permissions.h @@ -20,6 +20,8 @@ Bindings::PermissionState permission_state(Bindings::PermissionDescriptor descri Bindings::PermissionState get_current_permission_state(String const& name, Optional settings = {}); +Bindings::PermissionState request_permission(Bindings::PermissionDescriptor const& descriptor); + class WEB_API Permissions : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(Permissions, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(Permissions); diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 63ef842f98..5dd33f313c 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -353,6 +353,8 @@ PerformanceObserverEntryList PerformanceResourceTiming PerformanceTiming PeriodicWave +PermissionStatus +Permissions Plugin PluginArray PointerEvent diff --git a/Tests/LibWeb/Text/expected/wpt-import/permissions/all-permissions.txt b/Tests/LibWeb/Text/expected/wpt-import/permissions/all-permissions.txt new file mode 100644 index 0000000000..151a0b193c --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/permissions/all-permissions.txt @@ -0,0 +1,25 @@ +Harness status: OK + +Found 19 tests + +1 Pass +18 Fail +Fail Query "camera" permission +Pass Query "geolocation" permission +Fail Query "microphone" permission +Fail Query "notifications" permission +Fail Query "persistent-storage" permission +Fail Query "push" permission +Fail Query "accelerometer" permission +Fail Query "ambient-light-sensor" permission +Fail Query "background-fetch" permission +Fail Query "background-sync" permission +Fail Query "bluetooth" permission +Fail Query "gyroscope" permission +Fail Query "magnetometer" permission +Fail Query "midi" permission +Fail Query "nfc" permission +Fail Query "screen-wake-lock" permission +Fail Query "display-capture" permission +Fail Query "speaker-selection" permission +Fail Query "xr-spatial-tracking" permission \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/permissions/permissionsstatus-name.txt b/Tests/LibWeb/Text/expected/wpt-import/permissions/permissionsstatus-name.txt new file mode 100644 index 0000000000..5cdc172611 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/permissions/permissionsstatus-name.txt @@ -0,0 +1,6 @@ +Harness status: OK + +Found 1 tests + +1 Pass +Pass Test PermissionStatus's name attribute. \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/permissions/all-permissions.html b/Tests/LibWeb/Text/input/wpt-import/permissions/all-permissions.html new file mode 100644 index 0000000000..bde6c0d089 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/permissions/all-permissions.html @@ -0,0 +1,43 @@ + + +Test all known permissions support + + +
+ + diff --git a/Tests/LibWeb/Text/input/wpt-import/permissions/permissionsstatus-name.html b/Tests/LibWeb/Text/input/wpt-import/permissions/permissionsstatus-name.html new file mode 100644 index 0000000000..7499e884c8 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/permissions/permissionsstatus-name.html @@ -0,0 +1,15 @@ + + +Test PermissionStatus's name attribute. + + +
+ + \ No newline at end of file