From 848078aedd71f9b031c20443be0c6284255f949d Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 22 Apr 2023 15:11:07 -0400 Subject: [PATCH] LibWeb: Propagate LibVideo decoder errors to the HTMLMediaElement --- .../LibWeb/HTML/HTMLMediaElement.cpp | 35 ++++++++++++++++++- .../Libraries/LibWeb/HTML/HTMLMediaElement.h | 1 + Userland/Libraries/LibWeb/HTML/VideoTrack.cpp | 10 +++--- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp index df6b5666ab..b567b151c9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.cpp @@ -105,6 +105,40 @@ void HTMLMediaElement::did_remove_attribute(DeprecatedFlyString const& name) m_crossorigin = cors_setting_attribute_from_keyword({}); } +// https://html.spec.whatwg.org/multipage/media.html#fatal-decode-error +WebIDL::ExceptionOr HTMLMediaElement::set_decoder_error(String error_message) +{ + auto& realm = this->realm(); + auto& vm = realm.vm(); + + // -> If the media data is corrupted + // Fatal errors in decoding the media data that occur after the user agent has established whether the current media + // resource is usable (i.e. once the media element's readyState attribute is no longer HAVE_NOTHING) must cause the + // user agent to execute the following steps: + if (m_ready_state == ReadyState::HaveNothing) + return {}; + + // 1. The user agent should cancel the fetching process. + if (m_fetch_controller) + m_fetch_controller->stop_fetch(); + + // 2. Set the error attribute to the result of creating a MediaError with MEDIA_ERR_DECODE. + m_error = TRY(vm.heap().allocate(realm, realm, MediaError::Code::Decode, move(error_message))); + + // 3. Set the element's networkState attribute to the NETWORK_IDLE value. + m_network_state = NetworkState::Idle; + + // 4. Set the element's delaying-the-load-event flag to false. This stops delaying the load event. + m_delaying_the_load_event.clear(); + + // 5. Fire an event named error at the media element. + dispatch_event(TRY(DOM::Event::create(realm, HTML::EventNames::error))); + + // FIXME: 6. Abort the overall resource selection algorithm. + + return {}; +} + // https://html.spec.whatwg.org/multipage/media.html#dom-media-buffered WebIDL::ExceptionOr> HTMLMediaElement::buffered() const { @@ -865,7 +899,6 @@ WebIDL::ExceptionOr HTMLMediaElement::process_media_data(Function If the connection is interrupted after some media data has been received, causing the user agent to give up trying to fetch the resource - // FIXME: -> If the media data is corrupted // FIXME: -> If the media data fetching process is aborted by the user // FIXME: -> If the media data can be fetched but has non-fatal errors or uses, in part, codecs that are unsupported, preventing the user agent from // rendering the content completely correctly but not preventing playback altogether diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h index 53b5694451..66017a8f9f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMediaElement.h @@ -35,6 +35,7 @@ public: void queue_a_media_element_task(JS::SafeFunction steps); JS::GCPtr error() const { return m_error; } + WebIDL::ExceptionOr set_decoder_error(String error_message); String const& current_src() const { return m_current_src; } diff --git a/Userland/Libraries/LibWeb/HTML/VideoTrack.cpp b/Userland/Libraries/LibWeb/HTML/VideoTrack.cpp index a1eda89da0..d8198d7b9f 100644 --- a/Userland/Libraries/LibWeb/HTML/VideoTrack.cpp +++ b/Userland/Libraries/LibWeb/HTML/VideoTrack.cpp @@ -51,12 +51,14 @@ VideoTrack::VideoTrack(JS::Realm& realm, JS::NonnullGCPtr medi } }; - m_playback_manager->on_decoder_error = [](auto) { - // FIXME: Propagate this error to HTMLMediaElement's error attribute. + m_playback_manager->on_decoder_error = [this](auto error) { + auto error_message = String::from_utf8(error.description()).release_value_but_fixme_should_propagate_errors(); + m_media_element->set_decoder_error(move(error_message)).release_value_but_fixme_should_propagate_errors(); }; - m_playback_manager->on_fatal_playback_error = [](auto) { - // FIXME: Propagate this error to HTMLMediaElement's error attribute. + m_playback_manager->on_fatal_playback_error = [this](auto error) { + auto error_message = String::from_utf8(error.string_literal()).release_value_but_fixme_should_propagate_errors(); + m_media_element->set_decoder_error(move(error_message)).release_value_but_fixme_should_propagate_errors(); }; }