ladybird/Libraries/LibWeb/ServiceWorker/ServiceWorkerContainer.h
Andreas Kling 1835d739f5 LibWeb: Implement ServiceWorkerContainer getRegistrations
Expose ServiceWorkerContainer.getRegistrations() and implement the
Service Workers algorithm for collecting registrations matching the
current client's storage key. Resolve the promise with a frozen array
of ServiceWorkerRegistration objects, matching the Web-exposed return
type.

Use OrderedHashMap for the temporary LibWeb registration map, since the
Service Workers spec defines the registration map as ordered and
getRegistrations() exposes that iteration order.

Add text coverage for the no-registration case used by TradingView's
startup path. Without this method, the page threw while calling
navigator.serviceWorker.getRegistrations() and aborted before rendering
its chart.
2026-05-23 19:11:01 +02:00

59 lines
2.1 KiB
C++

/*
* Copyright (c) 2024, Tim Ledbetter <tim.ledbetter@ladybird.org>
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/ServiceWorkerRegistration.h>
#include <LibWeb/Bindings/Worker.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/TrustedTypes/TrustedScript.h>
#include <LibWeb/TrustedTypes/TrustedScriptURL.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
#include <LibWeb/WebIDL/Promise.h>
#define ENUMERATE_SERVICE_WORKER_CONTAINER_EVENT_HANDLERS(E) \
E(oncontrollerchange, HTML::EventNames::controllerchange) \
E(onmessage, HTML::EventNames::message) \
E(onmessageerror, HTML::EventNames::messageerror)
namespace Web::ServiceWorker {
class ServiceWorkerContainer : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(ServiceWorkerContainer, DOM::EventTarget);
GC_DECLARE_ALLOCATOR(ServiceWorkerContainer);
public:
[[nodiscard]] static GC::Ref<ServiceWorkerContainer> create(JS::Realm& realm);
virtual ~ServiceWorkerContainer() override;
GC::Ref<WebIDL::Promise> register_(TrustedTypes::TrustedScriptURLOrString script_url, Bindings::RegistrationOptions const&);
GC::Ref<WebIDL::Promise> get_registration(String const& client_url);
GC::Ref<WebIDL::Promise> get_registrations();
GC::Ref<WebIDL::Promise> ready();
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void set_##attribute_name(WebIDL::CallbackType*); \
WebIDL::CallbackType* attribute_name();
ENUMERATE_SERVICE_WORKER_CONTAINER_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE
private:
explicit ServiceWorkerContainer(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
void start_register(Optional<URL::URL> scope_url, Optional<URL::URL> script_url, GC::Ref<WebIDL::Promise>, HTML::EnvironmentSettingsObject&, URL::URL referrer, Bindings::WorkerType, Bindings::ServiceWorkerUpdateViaCache);
GC::Ref<HTML::EnvironmentSettingsObject> m_service_worker_client;
GC::Ptr<WebIDL::Promise> m_ready_promise;
};
}