1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:18:11 +00:00

LibWeb: Implement the :buffering and :stalled pseudo-classes

Currently, HTMLMediaElement doesn't implement the stall timeout, so
`:stalled` always returns false.
This commit is contained in:
Sam Atkins 2023-08-01 15:26:56 +01:00 committed by Tim Flynn
parent eb7cda1172
commit f6e4caf197
7 changed files with 42 additions and 2 deletions

View file

@ -465,6 +465,8 @@ Parser::ParseErrorOr<Selector::SimpleSelector> 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<Selector::SimpleSelector> 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))

View file

@ -236,6 +236,8 @@ ErrorOr<String> 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)));

View file

@ -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();
}

View file

@ -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<HTML::HTMLMediaElement>(element))
return false;
auto const& media_element = static_cast<HTML::HTMLMediaElement const&>(element);
return media_element.blocked();
}
case CSS::Selector::SimpleSelector::PseudoClass::Type::Stalled: {
if (!is<HTML::HTMLMediaElement>(element))
return false;
auto const& media_element = static_cast<HTML::HTMLMediaElement const&>(element);
return media_element.stalled();
}
}
return false;

View file

@ -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);

View file

@ -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
{

View file

@ -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<void> reached_end_of_media_playback();