Skip to content

Commit 0673156

Browse files
committed
LibWeb: Implement the Badging API
Add support for the Badging API (https://w3c.github.io/badging/), which allows web applications to set application badges. This fixes the WPT test badging/non-fully-active.https.html.
1 parent df1b89b commit 0673156

File tree

8 files changed

+120
-0
lines changed

8 files changed

+120
-0
lines changed

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ set(SOURCES
592592
HTML/NavigationParams.cpp
593593
HTML/NavigationTransition.cpp
594594
HTML/Navigator.cpp
595+
HTML/NavigatorBadge.cpp
595596
HTML/NavigatorBeacon.cpp
596597
HTML/NavigatorConcurrentHardware.cpp
597598
HTML/NavigatorDeviceMemory.cpp

Libraries/LibWeb/HTML/Navigator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ Navigator::Navigator(JS::Realm& realm)
3737

3838
Navigator::~Navigator() = default;
3939

40+
HTML::Window& Navigator::window()
41+
{
42+
return as<HTML::Window>(HTML::current_principal_global_object());
43+
}
44+
4045
void Navigator::initialize(JS::Realm& realm)
4146
{
4247
WEB_SET_PROTOTYPE_FOR_INTERFACE(Navigator);

Libraries/LibWeb/HTML/Navigator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <LibWeb/GPC/GlobalPrivacyControl.h>
1212
#include <LibWeb/Gamepad/NavigatorGamepad.h>
1313
#include <LibWeb/HTML/MimeTypeArray.h>
14+
#include <LibWeb/HTML/NavigatorBadge.h>
1415
#include <LibWeb/HTML/NavigatorBeacon.h>
1516
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
1617
#include <LibWeb/HTML/NavigatorDeviceMemory.h>
@@ -27,6 +28,7 @@ namespace Web::HTML {
2728

2829
class Navigator
2930
: public Bindings::PlatformObject
31+
, public NavigatorBadgeMixin
3032
, public NavigatorBeaconPartial
3133
, public NavigatorConcurrentHardwareMixin
3234
, public NavigatorDeviceMemoryMixin
@@ -78,6 +80,9 @@ class Navigator
7880
protected:
7981
virtual void visit_edges(Cell::Visitor&) override;
8082

83+
// ^NavigatorBadgeMixin
84+
virtual HTML::Window& window() override;
85+
8186
private:
8287
explicit Navigator(JS::Realm&);
8388

Libraries/LibWeb/HTML/Navigator.idl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#import <Geolocation/Geolocation.idl>
66
#import <GPC/GlobalPrivacyControl.idl>
77
#import <HTML/MimeTypeArray.idl>
8+
#import <HTML/NavigatorBadge.idl>
89
#import <HTML/NavigatorBeacon.idl>
910
#import <HTML/NavigatorConcurrentHardware.idl>
1011
#import <HTML/NavigatorDeviceMemory.idl>
@@ -89,3 +90,4 @@ Navigator includes NavigatorConcurrentHardware;
8990
Navigator includes NavigatorAutomationInformation;
9091
Navigator includes NavigatorStorage;
9192
Navigator includes NavigatorDeviceMemory;
93+
Navigator includes NavigatorBadge;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2025, Estefania Sanchez <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include <LibWeb/Bindings/Intrinsics.h>
8+
#include <LibWeb/DOM/Document.h>
9+
#include <LibWeb/HTML/Navigator.h>
10+
#include <LibWeb/HTML/NavigatorBadge.h>
11+
#include <LibWeb/HTML/Scripting/Environments.h>
12+
#include <LibWeb/HTML/Window.h>
13+
#include <LibWeb/WebIDL/DOMException.h>
14+
#include <LibWeb/WebIDL/Promise.h>
15+
16+
namespace Web::HTML {
17+
18+
// https://w3c.github.io/badging/#setting-the-application-badge
19+
GC::Ref<WebIDL::Promise> NavigatorBadgeMixin::set_app_badge(Optional<u64> contents)
20+
{
21+
// 1. Let global be context's relevant global object.
22+
auto& window_object = window();
23+
auto& realm = window_object.realm();
24+
25+
// 2. If global is a Window object, then:
26+
// 2-1. Let document be global's associated Document.
27+
auto& document = window_object.associated_document();
28+
29+
// 2-2. If document is not fully active, return a promise rejected with a "InvalidStateError" DOMException.
30+
if (!document.is_fully_active()) {
31+
auto exception = WebIDL::InvalidStateError::create(realm, "Document is not fully active"_utf16);
32+
return WebIDL::create_rejected_promise(realm, exception);
33+
}
34+
35+
// 2-3. If document's relevant settings object's origin is not same origin-domain with this's relevant settings
36+
// object's top-level origin, return a promise rejected with a "SecurityError" DOMException.
37+
auto const document_origin = document.relevant_settings_object().origin();
38+
auto navigator = window_object.navigator();
39+
auto& this_settings = HTML::relevant_settings_object(*navigator);
40+
if (this_settings.top_level_origin.has_value() && !document_origin.is_same_origin_domain(this_settings.top_level_origin.value())) {
41+
auto exception = WebIDL::SecurityError::create(realm, "Document's origin is not same origin-domain with top-level origin"_utf16);
42+
return WebIDL::create_rejected_promise(realm, exception);
43+
}
44+
45+
// 3. Let promise be a new promise.
46+
auto promise = WebIDL::create_promise(realm);
47+
48+
// FIXME: 4. In parallel:
49+
// FIXME: 4-1. If the user agent requires express permission to set the application badge, then:
50+
// FIXME: 4-1-1. Let permissionState be the result of getting the current permission state with "notifications".
51+
// FIXME: 4-1-2. If permissionState is not "granted", queue a global task on the user interaction task source given
52+
// global to reject promise with a NotAllowedError and terminate this algorithm.
53+
54+
// FIXME: 4-2. Switching on contents, if it happens to be the case that:
55+
// contents was not passed: Set badge to "flag".
56+
// contents is 0: Set badge to "nothing".
57+
// contents: Set badge to contents.
58+
(void)contents;
59+
60+
// FIXME: 4-3. Queue a global task on the DOM manipulation task source given global to resolve promise with undefined.
61+
WebIDL::resolve_promise(realm, promise, JS::js_undefined());
62+
63+
// 5. Return promise.
64+
return promise;
65+
}
66+
67+
// https://w3c.github.io/badging/#clearappbadge-method
68+
GC::Ref<WebIDL::Promise> NavigatorBadgeMixin::clear_app_badge()
69+
{
70+
// When the clearAppBadge() method is called, the user agent MUST set the application badge of this to 0.
71+
return set_app_badge(0);
72+
}
73+
74+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2025, Estefania Sanchez <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <AK/Optional.h>
10+
#include <LibGC/Ptr.h>
11+
#include <LibWeb/Forward.h>
12+
13+
namespace Web::HTML {
14+
15+
class NavigatorBadgeMixin {
16+
public:
17+
virtual ~NavigatorBadgeMixin() = default;
18+
19+
GC::Ref<WebIDL::Promise> set_app_badge(Optional<u64> contents);
20+
GC::Ref<WebIDL::Promise> clear_app_badge();
21+
22+
protected:
23+
virtual HTML::Window& window() = 0;
24+
};
25+
26+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// https://w3c.github.io/badging
2+
[SecureContext]
3+
interface mixin NavigatorBadge {
4+
Promise<undefined> setAppBadge(optional [EnforceRange] unsigned long long contents);
5+
Promise<undefined> clearAppBadge();
6+
};

Libraries/LibWeb/HTML/WorkerNavigator.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ WorkerNavigator includes NavigatorOnLine;
2828
WorkerNavigator includes NavigatorConcurrentHardware;
2929
WorkerNavigator includes NavigatorStorage;
3030
WorkerNavigator includes NavigatorDeviceMemory;
31+
// FIXME: WorkerNavigator includes NavigatorBadge; https://w3c.github.io/badging/

0 commit comments

Comments
 (0)