Parcourir la source

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

Currently, HTMLMediaElement doesn't implement the stall timeout, so
`:stalled` always returns false.
Sam Atkins il y a 2 ans
Parent
commit
f6e4caf197

+ 4 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

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

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Selector.cpp

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

+ 6 - 0
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();
 }

+ 12 - 0
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<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;

+ 6 - 0
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);

+ 10 - 1
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
 {

+ 2 - 1
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<void> reached_end_of_media_playback();