diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn index 7ae2f3248b6..97ae5c19333 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/HTML/BUILD.gn @@ -163,6 +163,7 @@ source_set("HTML") { "SubmitEvent.cpp", "TagNames.cpp", "TextMetrics.cpp", + "TextTrack.cpp", "TimeRanges.cpp", "Timer.cpp", "ToggleEvent.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index 3863d42d2ea..e20c73f0a0d 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -224,6 +224,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/HTML/Storage.idl", "//Userland/Libraries/LibWeb/HTML/SubmitEvent.idl", "//Userland/Libraries/LibWeb/HTML/TextMetrics.idl", + "//Userland/Libraries/LibWeb/HTML/TextTrack.idl", "//Userland/Libraries/LibWeb/HTML/TimeRanges.idl", "//Userland/Libraries/LibWeb/HTML/ToggleEvent.idl", "//Userland/Libraries/LibWeb/HTML/TrackEvent.idl", diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index 7674cc7efbf..ba370e465da 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -322,6 +322,7 @@ Text TextDecoder TextEncoder TextMetrics +TextTrack TimeRanges ToggleEvent TrackEvent diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 2749007a965..5b22c4ac91e 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -431,6 +431,7 @@ set(SOURCES HTML/SyntaxHighlighter/SyntaxHighlighter.cpp HTML/TagNames.cpp HTML/TextMetrics.cpp + HTML/TextTrack.cpp HTML/Timer.cpp HTML/TimeRanges.cpp HTML/ToggleEvent.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index e77caee2ee3..8c8c00b24c5 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -69,6 +69,7 @@ enum class RequestPriority; enum class RequestRedirect; enum class ResizeObserverBoxOptions; enum class ResponseType; +enum class TextTrackKind; enum class XMLHttpRequestResponseType; } @@ -468,6 +469,7 @@ class SharedImageRequest; class Storage; class SubmitEvent; class TextMetrics; +class TextTrack; class Timer; class TimeRanges; class ToggleEvent; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp index e9242f9794f..76a539550e0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.cpp @@ -1,12 +1,15 @@ /* * Copyright (c) 2020, the SerenityOS developers. + * Copyright (c) 2024, Jamie Mansfield * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include #include +#include namespace Web::HTML { @@ -15,6 +18,7 @@ JS_DEFINE_ALLOCATOR(HTMLTrackElement); HTMLTrackElement::HTMLTrackElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { + m_track = TextTrack::create(document.realm()); } HTMLTrackElement::~HTMLTrackElement() = default; @@ -25,4 +29,19 @@ void HTMLTrackElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTrackElement); } +void HTMLTrackElement::attribute_changed(FlyString const& name, Optional const& value) +{ + HTMLElement::attribute_changed(name, value); + + // https://html.spec.whatwg.org/multipage/media.html#sourcing-out-of-band-text-tracks + // As the kind, label, and srclang attributes are set, changed, or removed, the text track must update accordingly, as per the definitions above. + if (name.equals_ignoring_ascii_case("kind"sv)) { + m_track->set_kind(text_track_kind_from_string(value.value_or({}))); + } else if (name.equals_ignoring_ascii_case("label"sv)) { + m_track->set_label(value.value_or({})); + } else if (name.equals_ignoring_ascii_case("srclang"sv)) { + m_track->set_language(value.value_or({})); + } +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h index de203d1a131..9d75a8e124a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, the SerenityOS developers. + * Copyright (c) 2024, Jamie Mansfield * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,6 +8,7 @@ #pragma once #include +#include namespace Web::HTML { @@ -17,10 +19,17 @@ class HTMLTrackElement final : public HTMLElement { public: virtual ~HTMLTrackElement() override; + JS::Handle track() { return m_track; } + private: HTMLTrackElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; + + // ^DOM::Element + virtual void attribute_changed(FlyString const& name, Optional const& value) override; + + JS::GCPtr m_track; }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.idl index b9e1155d610..8b28966f1ff 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLTrackElement.idl @@ -28,6 +28,6 @@ interface HTMLTrackElement : HTMLElement { // FIXME: [const unsigned short ERROR = 3; [FIXME] readonly attribute unsigned short readyState; - [FIXME] readonly attribute TextTrack track; + readonly attribute TextTrack track; }; diff --git a/Userland/Libraries/LibWeb/HTML/TextTrack.cpp b/Userland/Libraries/LibWeb/HTML/TextTrack.cpp new file mode 100644 index 00000000000..b0a060b97be --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/TextTrack.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024, Jamie Mansfield + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(TextTrack); + +JS::NonnullGCPtr TextTrack::create(JS::Realm& realm) +{ + return realm.heap().allocate(realm, realm); +} + +TextTrack::TextTrack(JS::Realm& realm) + : DOM::EventTarget(realm) +{ +} + +TextTrack::~TextTrack() = default; + +void TextTrack::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(TextTrack); +} + +// https://html.spec.whatwg.org/multipage/media.html#dom-texttrack-kind +Bindings::TextTrackKind TextTrack::kind() +{ + return m_kind; +} + +void TextTrack::set_kind(Bindings::TextTrackKind kind) +{ + m_kind = kind; +} + +// https://html.spec.whatwg.org/multipage/media.html#dom-texttrack-label +String TextTrack::label() +{ + return m_label; +} + +void TextTrack::set_label(String label) +{ + m_label = label; +} + +// https://html.spec.whatwg.org/multipage/media.html#dom-texttrack-language +String TextTrack::language() +{ + return m_language; +} + +void TextTrack::set_language(String language) +{ + m_language = language; +} + +// https://html.spec.whatwg.org/multipage/media.html#handler-texttrack-oncuechange +void TextTrack::set_oncuechange(WebIDL::CallbackType* event_handler) +{ + set_event_handler_attribute(HTML::EventNames::cuechange, event_handler); +} + +// https://html.spec.whatwg.org/multipage/media.html#handler-texttrack-oncuechange +WebIDL::CallbackType* TextTrack::oncuechange() +{ + return event_handler_attribute(HTML::EventNames::cuechange); +} + +Bindings::TextTrackKind text_track_kind_from_string(String value) +{ + // https://html.spec.whatwg.org/multipage/media.html#attr-track-kind + + if (value.is_empty() || value.equals_ignoring_ascii_case("subtitles"sv)) { + return Bindings::TextTrackKind::Subtitles; + } + if (value.equals_ignoring_ascii_case("captions"sv)) { + return Bindings::TextTrackKind::Captions; + } + if (value.equals_ignoring_ascii_case("descriptions"sv)) { + return Bindings::TextTrackKind::Descriptions; + } + if (value.equals_ignoring_ascii_case("chapters"sv)) { + return Bindings::TextTrackKind::Chapters; + } + if (value.equals_ignoring_ascii_case("metadata"sv)) { + return Bindings::TextTrackKind::Metadata; + } + + return Bindings::TextTrackKind::Metadata; +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/TextTrack.h b/Userland/Libraries/LibWeb/HTML/TextTrack.h new file mode 100644 index 00000000000..ecd54ce00f6 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/TextTrack.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024, Jamie Mansfield + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace Web::HTML { + +class TextTrack final : public DOM::EventTarget { + WEB_PLATFORM_OBJECT(TextTrack, DOM::EventTarget); + JS_DECLARE_ALLOCATOR(TextTrack); + +public: + static JS::NonnullGCPtr create(JS::Realm&); + virtual ~TextTrack() override; + + Bindings::TextTrackKind kind(); + void set_kind(Bindings::TextTrackKind); + + String label(); + void set_label(String); + + String language(); + void set_language(String); + + void set_oncuechange(WebIDL::CallbackType*); + WebIDL::CallbackType* oncuechange(); + +private: + TextTrack(JS::Realm&); + + virtual void initialize(JS::Realm&) override; + + Bindings::TextTrackKind m_kind { Bindings::TextTrackKind::Subtitles }; + String m_label {}; + String m_language {}; +}; + +Bindings::TextTrackKind text_track_kind_from_string(String); + +} diff --git a/Userland/Libraries/LibWeb/HTML/TextTrack.idl b/Userland/Libraries/LibWeb/HTML/TextTrack.idl new file mode 100644 index 00000000000..0b372f2a5c8 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/TextTrack.idl @@ -0,0 +1,28 @@ +#import + +// https://html.spec.whatwg.org/multipage/media.html#texttrackmode +enum TextTrackMode { "disabled", "hidden", "showing" }; + +// https://html.spec.whatwg.org/multipage/media.html#texttrackkind +enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" }; + +// https://html.spec.whatwg.org/multipage/media.html#texttrack +[Exposed=Window] +interface TextTrack : EventTarget { + readonly attribute TextTrackKind kind; + readonly attribute DOMString label; + readonly attribute DOMString language; + + [FIXME] readonly attribute DOMString id; + [FIXME] readonly attribute DOMString inBandMetadataTrackDispatchType; + + [FIXME] attribute TextTrackMode mode; + + [FIXME] readonly attribute TextTrackCueList? cues; + [FIXME] readonly attribute TextTrackCueList? activeCues; + + [FIXME] undefined addCue(TextTrackCue cue); + [FIXME] undefined removeCue(TextTrackCue cue); + + attribute EventHandler oncuechange; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 28248608780..3827757a1ee 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -208,6 +208,7 @@ libweb_js_bindings(HTML/PromiseRejectionEvent) libweb_js_bindings(HTML/Storage) libweb_js_bindings(HTML/SubmitEvent) libweb_js_bindings(HTML/TextMetrics) +libweb_js_bindings(HTML/TextTrack) libweb_js_bindings(HTML/TimeRanges) libweb_js_bindings(HTML/ToggleEvent) libweb_js_bindings(HTML/TrackEvent)