ladybird/Libraries/LibWeb/NotificationsAPI/Notification.h
Niccolo Antonelli Dziri bd76078f97 LibWeb: Add constructor for Notification and getter methods
The full constructor for NotificationsAPI::Notification is implemented
along with the getter methods.
It is now possible to call the elements of Notification in JS without
getting undefined but the default values (or the ones passed in
options).

The method `current_wall_time` is added in EnvironmentSettingsObject.

This passes a least a few more tests because of the getter methods
that are created.

https://wpt.live/notifications/constructor-basic.https.html

https://wpt.live/notifications/idlharness.https.any.html
2026-02-13 16:47:42 +00:00

139 lines
5.4 KiB
C++

/*
* Copyright (c) 2025, Niccolo Antonelli-Dziri <niccolo.antonelli-dziri@protonmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibJS/Runtime/Realm.h>
#include <LibJS/Runtime/Value.h>
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/HighResolutionTime/EpochTimeStamp.h>
namespace Web::NotificationsAPI {
struct NotificationAction {
String action;
String title;
Optional<String> navigate;
Optional<String> icon;
};
struct NotificationOptions {
Bindings::NotificationDirection dir = Bindings::NotificationDirection::Auto;
String lang = ""_string;
String body = ""_string;
Optional<String> navigate;
String tag = ""_string;
Optional<String> image;
Optional<String> icon;
Optional<String> badge;
// VibratePattern vibrate; // FIXME: properly implement vibrate pattern
Optional<HighResolutionTime::EpochTimeStamp> timestamp;
bool renotify = false;
Optional<bool> silent;
bool require_interaction = false;
JS::Value data;
Vector<NotificationAction> actions;
};
// https://notifications.spec.whatwg.org/#concept-notification
// This is the notification described as "notification" in the spec. Do not confuse it with "notification" as in the IDL which is just the JS wrapper.
// "A notification is an abstract representation of something that happened, such as the delivery of a message."
struct ConceptNotification {
// FIXME: A notification has an associated service worker registration (null or a service worker registration). It is initially null.
String title;
Bindings::NotificationDirection direction;
String language;
String body;
Optional<URL::URL> navigation_url;
String tag;
HTML::SerializationRecord data;
HighResolutionTime::EpochTimeStamp timestamp;
URL::Origin origin = URL::Origin({}); // FIXME: Is this a hack ? There is no default constructor to URL::Origin and the value for `origin` is set in `create-a-notification-with-a-settings-object`
bool renotify_preference;
Optional<bool> silent_preference;
bool require_interaction_preference;
Optional<URL::URL> image_url;
Optional<URL::URL> icon_url;
Optional<URL::URL> badge_url;
// FIXME: add the resources from m_image_url, m_icon_url and m_badge_url
// FIXME: A notification has an associated vibration pattern (a list). It is initially « ».
// https://notifications.spec.whatwg.org/#action
struct Action {
String name;
String title;
Optional<URL::URL> navigation_url;
Optional<URL::URL> icon_url;
// FIXME: icon resource
};
Vector<Action> actions;
};
// https://notifications.spec.whatwg.org/#notifications
class WEB_API Notification final : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(Notification, DOM::EventTarget);
GC_DECLARE_ALLOCATOR(Notification);
public:
[[nodiscard]] static WebIDL::ExceptionOr<GC::Ref<Notification>> construct_impl(
JS::Realm& realm,
String const& title,
NotificationOptions const& options);
// https://notifications.spec.whatwg.org/#create-a-notification-with-a-settings-object
static WebIDL::ExceptionOr<ConceptNotification> create_a_notification_with_a_settings_object(
JS::Realm& realm,
String const& title,
NotificationOptions const& options,
GC::Ref<HTML::EnvironmentSettingsObject> settings);
// https://notifications.spec.whatwg.org/#create-a-notification
static WebIDL::ExceptionOr<ConceptNotification> create_a_notification(
JS::Realm& realm,
String const& title,
NotificationOptions const& options,
URL::Origin origin,
URL::URL base_url,
HighResolutionTime::EpochTimeStamp fallback_timestamp);
static unsigned long max_actions(JS::VM&)
{
// FIXME: Change the number of max_actions supported when actions will actually be supported
// It seems like Chrome is 2, Firefox is undefined, Safari is undefined
return 0;
}
String const& title() const { return m_notification.title; }
Bindings::NotificationDirection dir() const { return m_notification.direction; }
String const& lang() const { return m_notification.language; }
String const& body() const { return m_notification.body; }
String navigate() const { return m_notification.navigation_url.has_value() ? m_notification.navigation_url->serialize() : ""_string; }
String const& tag() const { return m_notification.tag; }
String image() const { return m_notification.image_url.has_value() ? m_notification.image_url->serialize() : ""_string; }
String icon() const { return m_notification.icon_url.has_value() ? m_notification.icon_url->serialize() : ""_string; }
String badge() const { return m_notification.badge_url.has_value() ? m_notification.badge_url->serialize() : ""_string; }
HighResolutionTime::EpochTimeStamp timestamp() const { return m_notification.timestamp; }
bool renotify() const { return m_notification.renotify_preference; }
Optional<bool> silent() const { return m_notification.silent_preference; }
bool require_interaction() const { return m_notification.require_interaction_preference; }
Vector<NotificationAction> actions() const;
JS::Value data() const;
private:
Notification(JS::Realm&);
virtual void initialize(JS::Realm&) override;
ConceptNotification m_notification;
};
}