LibWeb: Implement nagivator.serviceWorker.getRegistration()

This commit is contained in:
Feng Yu 2025-01-02 17:18:49 -08:00 committed by Andrew Kaster
parent 8e410f959c
commit 37e1d6ece1
Notes: github-actions[bot] 2025-01-30 22:19:44 +00:00
12 changed files with 280 additions and 36 deletions

View file

@ -21,6 +21,8 @@
#include <LibWeb/HTML/WorkerGlobalScope.h>
#include <LibWeb/Page/Page.h>
#include <LibWeb/SecureContexts/AbstractOperations.h>
#include <LibWeb/ServiceWorker/ServiceWorker.h>
#include <LibWeb/ServiceWorker/ServiceWorkerRegistration.h>
#include <LibWeb/StorageAPI/StorageManager.h>
namespace Web::HTML {
@ -61,6 +63,8 @@ void EnvironmentSettingsObject::visit_edges(Cell::Visitor& visitor)
m_realm_execution_context->visit_edges(visitor);
visitor.visit(m_fetch_group);
visitor.visit(m_storage_manager);
visitor.visit(m_service_worker_registration_object_map);
visitor.visit(m_service_worker_object_map);
}
JS::ExecutionContext& EnvironmentSettingsObject::realm_execution_context()
@ -574,4 +578,63 @@ GC::Ref<StorageAPI::StorageManager> EnvironmentSettingsObject::storage_manager()
return *m_storage_manager;
}
// https://w3c.github.io/ServiceWorker/#get-the-service-worker-registration-object
GC::Ref<ServiceWorker::ServiceWorkerRegistration> EnvironmentSettingsObject::get_service_worker_registration_object(ServiceWorker::Registration const& registration)
{
// 1. Let objectMap be environments service worker registration object map.
auto& object_map = this->m_service_worker_registration_object_map;
// FIXME: File spec issue asking if this should be keyed on the registration's scope url only or on the url and the storage key
auto const key = ServiceWorker::RegistrationKey { registration.storage_key(), registration.scope_url().serialize(URL::ExcludeFragment::Yes).to_byte_string() };
// 2. If objectMap[registration] does not exist, then:
if (!object_map.contains(key)) {
// 1. Let registrationObject be a new ServiceWorkerRegistration in environments Realm.
// 2. Set registrationObjects service worker registration to registration.
// 3. Set registrationObjects installing attribute to null.
// 4. Set registrationObjects waiting attribute to null.
// 5. Set registrationObjects active attribute to null.
auto registration_object = ServiceWorker::ServiceWorkerRegistration::create(realm(), registration);
// 6. If registrations installing worker is not null, then set registrationObjects installing attribute to the result of getting the service worker object that represents registrations installing worker in environment.
if (registration.installing_worker())
registration_object->set_installing(get_service_worker_object(registration.installing_worker()));
// 7. If registrations waiting worker is not null, then set registrationObjects waiting attribute to the result of getting the service worker object that represents registrations waiting worker in environment.
if (registration.waiting_worker())
registration_object->set_waiting(get_service_worker_object(registration.waiting_worker()));
// 8. If registrations active worker is not null, then set registrationObjects active attribute to the result of getting the service worker object that represents registrations active worker in environment.
if (registration.active_worker())
registration_object->set_active(get_service_worker_object(registration.active_worker()));
// 9. Set objectMap[registration] to registrationObject.
object_map.set(key, registration_object);
}
// 3. Return objectMap[registration].
return *object_map.get(key);
}
GC::Ref<ServiceWorker::ServiceWorker> EnvironmentSettingsObject::get_service_worker_object(ServiceWorker::ServiceWorkerRecord* service_worker)
{
// 1. Let objectMap be environments service worker object map.
auto& object_map = this->m_service_worker_object_map;
// 2. If objectMap[serviceWorker] does not exist, then:
if (!object_map.contains(service_worker)) {
// 1. Let serviceWorkerObj be a new ServiceWorker in environments Realm, and associate it with serviceWorker.
auto service_worker_obj = ServiceWorker::ServiceWorker::create(realm(), service_worker);
// 2. Set serviceWorkerObjs state to serviceWorkers state.
service_worker_obj->set_service_worker_state(service_worker->state);
// 3. Set objectMap[serviceWorker] to serviceWorkerObj.
object_map.set(service_worker, service_worker_obj);
}
// 3. Return objectMap[serviceWorker].
return *object_map.get(service_worker);
}
}