From f6e4caf197d76e40c8e1a9052ad8916236875b60 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 1 Aug 2023 15:26:56 +0100 Subject: [PATCH] LibWeb: Implement the `:buffering` and `:stalled` pseudo-classes Currently, HTMLMediaElement doesn't implement the stall timeout, so `:stalled` always returns false. --- Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 4 ++++ Userland/Libraries/LibWeb/CSS/Selector.cpp | 2 ++ Userland/Libraries/LibWeb/CSS/Selector.h | 6 ++++++ Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp | 12 ++++++++++++ Userland/Libraries/LibWeb/Dump.cpp | 6 ++++++ Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp | 11 ++++++++++- Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h | 3 ++- 7 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index b1733dc591..9b781fdf23 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -465,6 +465,8 @@ Parser::ParseErrorOr Parser::parse_pseudo_simple_selec if (pseudo_name.equals_ignoring_ascii_case("active"sv)) return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Active); + if (pseudo_name.equals_ignoring_ascii_case("buffering"sv)) + return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Buffering); if (pseudo_name.equals_ignoring_ascii_case("checked"sv)) return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Checked); if (pseudo_name.equals_ignoring_ascii_case("indeterminate"sv)) @@ -507,6 +509,8 @@ Parser::ParseErrorOr Parser::parse_pseudo_simple_selec return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Root); if (pseudo_name.equals_ignoring_ascii_case("seeking"sv)) return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Seeking); + if (pseudo_name.equals_ignoring_ascii_case("stalled"sv)) + return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Stalled); if (pseudo_name.equals_ignoring_ascii_case("host"sv)) return make_pseudo_class_selector(Selector::SimpleSelector::PseudoClass::Type::Host); if (pseudo_name.equals_ignoring_ascii_case("visited"sv)) diff --git a/Userland/Libraries/LibWeb/CSS/Selector.cpp b/Userland/Libraries/LibWeb/CSS/Selector.cpp index c581122db9..53234e3728 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.cpp +++ b/Userland/Libraries/LibWeb/CSS/Selector.cpp @@ -236,6 +236,8 @@ ErrorOr Selector::SimpleSelector::serialize() const case Selector::SimpleSelector::PseudoClass::Type::Seeking: case Selector::SimpleSelector::PseudoClass::Type::Muted: case Selector::SimpleSelector::PseudoClass::Type::VolumeLocked: + case Selector::SimpleSelector::PseudoClass::Type::Buffering: + case Selector::SimpleSelector::PseudoClass::Type::Stalled: // If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s. TRY(s.try_append(':')); TRY(s.try_append(pseudo_class_name(pseudo_class.type))); diff --git a/Userland/Libraries/LibWeb/CSS/Selector.h b/Userland/Libraries/LibWeb/CSS/Selector.h index 1e044e11cf..6b360074df 100644 --- a/Userland/Libraries/LibWeb/CSS/Selector.h +++ b/Userland/Libraries/LibWeb/CSS/Selector.h @@ -120,6 +120,8 @@ public: Seeking, Muted, VolumeLocked, + Buffering, + Stalled, }; Type type; @@ -319,6 +321,10 @@ constexpr StringView pseudo_class_name(Selector::SimpleSelector::PseudoClass::Ty return "muted"sv; case Selector::SimpleSelector::PseudoClass::Type::VolumeLocked: return "volume-locked"sv; + case Selector::SimpleSelector::PseudoClass::Type::Buffering: + return "buffering"sv; + case Selector::SimpleSelector::PseudoClass::Type::Stalled: + return "stalled"sv; } VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index a8f4540a2f..46e2f4360f 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -406,6 +406,18 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla // Once we do, implement this! return false; } + case CSS::Selector::SimpleSelector::PseudoClass::Type::Buffering: { + if (!is(element)) + return false; + auto const& media_element = static_cast(element); + return media_element.blocked(); + } + case CSS::Selector::SimpleSelector::PseudoClass::Type::Stalled: { + if (!is(element)) + return false; + auto const& media_element = static_cast(element); + return media_element.stalled(); + } } return false; diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index 72e6b05da6..4ebacdb343 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -557,6 +557,12 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector) case CSS::Selector::SimpleSelector::PseudoClass::Type::VolumeLocked: pseudo_class_description = "VolumeLocked"; break; + case CSS::Selector::SimpleSelector::PseudoClass::Type::Buffering: + pseudo_class_description = "Buffering"; + break; + case CSS::Selector::SimpleSelector::PseudoClass::Type::Stalled: + pseudo_class_description = "Stalled"; + break; } builder.appendff(" pseudo_class={}", pseudo_class_description); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp index 595835277e..b12f2e47f4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp @@ -1273,7 +1273,10 @@ void HTMLMediaElement::forget_media_resource_specific_tracks() // https://html.spec.whatwg.org/multipage/media.html#ready-states:media-element-3 void HTMLMediaElement::set_ready_state(ReadyState ready_state) { - ScopeGuard guard { [&] { m_ready_state = ready_state; } }; + ScopeGuard guard { [&] { + m_ready_state = ready_state; + set_needs_style_update(true); + } }; // When the ready state of a media element whose networkState is not NETWORK_EMPTY changes, the user agent must // follow the steps given below: @@ -1624,6 +1627,12 @@ bool HTMLMediaElement::blocked() const return false; } +bool HTMLMediaElement::stalled() const +{ + // FIXME: Implement stall timeout. https://html.spec.whatwg.org/multipage/media.html#stall-timeout + return false; +} + // https://html.spec.whatwg.org/multipage/media.html#potentially-playing bool HTMLMediaElement::potentially_playing() const { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h index 9ec120b502..eb4d08beea 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h @@ -68,6 +68,8 @@ public: HaveEnoughData, }; ReadyState ready_state() const { return m_ready_state; } + bool blocked() const; + bool stalled() const; bool seeking() const { return m_seeking; } void set_seeking(bool); @@ -172,7 +174,6 @@ private: void volume_or_muted_attribute_changed(); - bool blocked() const; bool is_eligible_for_autoplay() const; bool has_ended_playback() const; WebIDL::ExceptionOr reached_end_of_media_playback();