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.
This commit is contained in:
parent
9f4a712e57
commit
920bb84fd7
8 changed files with 149 additions and 8 deletions
|
|
@ -7,14 +7,17 @@
|
|||
#include <AK/Time.h>
|
||||
#include <LibWeb/Bindings/Geolocation.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/Permissions.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/DocumentObserver.h>
|
||||
#include <LibWeb/Geolocation/Geolocation.h>
|
||||
#include <LibWeb/Geolocation/GeolocationPosition.h>
|
||||
#include <LibWeb/HTML/EventLoop/Task.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/HTML/TraversableNavigable.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/PermissionsAPI/Permissions.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/Platform/Timer.h>
|
||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||
|
|
@ -324,15 +327,17 @@ void Geolocation::request_a_position(GC::Ref<WebIDL::CallbackType> 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()();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<HTML::EnvironmentSettingsObject&> settings)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ Bindings::PermissionState permission_state(Bindings::PermissionDescriptor descri
|
|||
|
||||
Bindings::PermissionState get_current_permission_state(String const& name, Optional<HTML::EnvironmentSettingsObject&> 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);
|
||||
|
|
|
|||
|
|
@ -353,6 +353,8 @@ PerformanceObserverEntryList
|
|||
PerformanceResourceTiming
|
||||
PerformanceTiming
|
||||
PeriodicWave
|
||||
PermissionStatus
|
||||
Permissions
|
||||
Plugin
|
||||
PluginArray
|
||||
PointerEvent
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass Test PermissionStatus's name attribute.
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test all known permissions support</title>
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
<div id="log"></div>
|
||||
|
||||
<script>
|
||||
// These are marked "at risk" in the spec...
|
||||
const atRisk = [
|
||||
"accelerometer",
|
||||
"ambient-light-sensor",
|
||||
"background-fetch",
|
||||
"background-sync",
|
||||
"bluetooth",
|
||||
"gyroscope",
|
||||
"magnetometer",
|
||||
"midi",
|
||||
"nfc",
|
||||
"screen-wake-lock",
|
||||
"display-capture",
|
||||
"speaker-selection",
|
||||
"xr-spatial-tracking",
|
||||
];
|
||||
|
||||
// These are known to be supported by multiple engines...
|
||||
const permissions = [
|
||||
"camera",
|
||||
"geolocation",
|
||||
"microphone",
|
||||
"notifications",
|
||||
"persistent-storage",
|
||||
"push",
|
||||
];
|
||||
|
||||
for (const name of [...permissions, ...atRisk]) {
|
||||
promise_test(async (test) => {
|
||||
const status = await navigator.permissions.query({ name });
|
||||
assert_true(status instanceof PermissionStatus);
|
||||
//assert_equals(status.name, name, `permission's name should be "${name}"`);
|
||||
}, `Query "${name}" permission`);
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test PermissionStatus's name attribute.</title>
|
||||
<script src=../resources/testharness.js></script>
|
||||
<script src=../resources/testharnessreport.js></script>
|
||||
<div id="log"></div>
|
||||
|
||||
<script>
|
||||
promise_test(async () => {
|
||||
const result = await navigator.permissions.query({
|
||||
name: "geolocation",
|
||||
});
|
||||
assert_equals(result.name, "geolocation", "Name was geolocation");
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in a new issue