From 5f410f2fce0ec4931395feb2a92bee64a5264ebe Mon Sep 17 00:00:00 2001 From: Alastor Wu Date: Tue, 12 Mar 2019 00:32:21 +0000 Subject: [PATCH] Bug 1531863 - part2 : handle text track mode changed in MediaElement. r=jya In order to make the implementation more fitting with the spec, move the implementation of `pending-text-track-change-notification-flag` from text track list to media element. In addition, it also help us not to expose the internal flag `show-poster` (which will be implemented in patch3) of media element when doing the related algorithm. Differential Revision: https://phabricator.services.mozilla.com/D21810 --HG-- extra : moz-landing-system : lando --- dom/html/HTMLMediaElement.cpp | 16 ++++++++++++ dom/html/HTMLMediaElement.h | 10 ++++++++ dom/media/TextTrack.cpp | 47 ++++++++++++++++------------------- dom/media/TextTrackList.cpp | 38 +++++++++------------------- dom/media/TextTrackList.h | 2 -- 5 files changed, 59 insertions(+), 54 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 2741568549fe..f5394787ec59 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -7375,6 +7375,22 @@ already_AddRefed HTMLMediaElement::SetSinkId(const nsAString& aSinkId, return promise.forget(); } +void HTMLMediaElement::NotifyTextTrackModeChanged() { + if (mPendingTextTrackChanged) { + return; + } + mPendingTextTrackChanged = true; + mAbstractMainThread->Dispatch( + NS_NewRunnableFunction("HTMLMediaElement::NotifyTextTrackModeChanged", + [this, self = RefPtr(this)]() { + mPendingTextTrackChanged = false; + if (!mTextTrackManager) { + return; + } + GetTextTracks()->CreateAndDispatchChangeEvent(); + })); +} + } // namespace dom } // namespace mozilla diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index d613ae7804cd..82c1ac553c92 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -1674,6 +1674,16 @@ class HTMLMediaElement : public nsGenericHTMLElement, // bfcache. bool mHasEverBeenBlockedForAutoplay = false; + // True if we have dispatched a task for text track changed, will be unset + // when we starts processing text track changed. + // https://html.spec.whatwg.org/multipage/media.html#pending-text-track-change-notification-flag + bool mPendingTextTrackChanged = false; + + public: + // This function will be called whenever a text track that is in a media + // element's list of text tracks has its text track mode change value + void NotifyTextTrackModeChanged(); + public: // Helper class to measure times for playback telemetry stats class TimeDurationAccumulator { diff --git a/dom/media/TextTrack.cpp b/dom/media/TextTrack.cpp index 7817bb726233..1478b92b8c2d 100644 --- a/dom/media/TextTrack.cpp +++ b/dom/media/TextTrack.cpp @@ -73,33 +73,28 @@ JSObject* TextTrack::WrapObject(JSContext* aCx, } void TextTrack::SetMode(TextTrackMode aValue) { - if (mMode != aValue) { - mMode = aValue; - if (aValue == TextTrackMode::Disabled) { - // Remove all the cues in MediaElement. - HTMLMediaElement* mediaElement = GetMediaElement(); - if (mediaElement) { - for (size_t i = 0; i < mCueList->Length(); ++i) { - mediaElement->NotifyCueRemoved(*(*mCueList)[i]); - } - } - SetCuesInactive(); - } else { - // Add all the cues into MediaElement. - HTMLMediaElement* mediaElement = GetMediaElement(); - if (mediaElement) { - for (size_t i = 0; i < mCueList->Length(); ++i) { - mediaElement->NotifyCueAdded(*(*mCueList)[i]); - } - } - } - if (mTextTrackList) { - mTextTrackList->CreateAndDispatchChangeEvent(); - } - // Ensure the TimeMarchesOn is called in case that the mCueList - // is empty. - NotifyCueUpdated(nullptr); + if (mMode == aValue) { + return; } + mMode = aValue; + + HTMLMediaElement* mediaElement = GetMediaElement(); + if (aValue == TextTrackMode::Disabled) { + for (size_t i = 0; i < mCueList->Length() && mediaElement; ++i) { + mediaElement->NotifyCueRemoved(*(*mCueList)[i]); + } + SetCuesInactive(); + } else { + for (size_t i = 0; i < mCueList->Length() && mediaElement; ++i) { + mediaElement->NotifyCueAdded(*(*mCueList)[i]); + } + } + if (mediaElement) { + mediaElement->NotifyTextTrackModeChanged(); + } + // Ensure the TimeMarchesOn is called in case that the mCueList + // is empty. + NotifyCueUpdated(nullptr); } void TextTrack::GetId(nsAString& aId) const { diff --git a/dom/media/TextTrackList.cpp b/dom/media/TextTrackList.cpp index fc521522e571..bcf18e844e8f 100644 --- a/dom/media/TextTrackList.cpp +++ b/dom/media/TextTrackList.cpp @@ -118,39 +118,25 @@ class TrackEventRunner : public Runnable { RefPtr mEvent; }; -class ChangeEventRunner final : public TrackEventRunner { - public: - ChangeEventRunner(TextTrackList* aList, Event* aEvent) - : TrackEventRunner(aList, aEvent) {} - - NS_IMETHOD Run() override { - mList->mPendingTextTrackChange = false; - return TrackEventRunner::Run(); - } -}; - nsresult TextTrackList::DispatchTrackEvent(Event* aEvent) { return DispatchTrustedEvent(aEvent); } void TextTrackList::CreateAndDispatchChangeEvent() { MOZ_ASSERT(NS_IsMainThread()); - if (!mPendingTextTrackChange) { - nsPIDOMWindowInner* win = GetOwner(); - if (!win) { - return; - } - - mPendingTextTrackChange = true; - RefPtr event = NS_NewDOMEvent(this, nullptr, nullptr); - - event->InitEvent(NS_LITERAL_STRING("change"), false, false); - event->SetTrusted(true); - - nsCOMPtr eventRunner = new ChangeEventRunner(this, event); - nsGlobalWindowInner::Cast(win)->Dispatch(TaskCategory::Other, - eventRunner.forget()); + nsPIDOMWindowInner* win = GetOwner(); + if (!win) { + return; } + + RefPtr event = NS_NewDOMEvent(this, nullptr, nullptr); + + event->InitEvent(NS_LITERAL_STRING("change"), false, false); + event->SetTrusted(true); + + nsCOMPtr eventRunner = new TrackEventRunner(this, event); + nsGlobalWindowInner::Cast(win)->Dispatch(TaskCategory::Other, + eventRunner.forget()); } void TextTrackList::CreateAndDispatchTrackEventRunner( diff --git a/dom/media/TextTrackList.h b/dom/media/TextTrackList.h index 5f8d008717e3..42e24e64ec9a 100644 --- a/dom/media/TextTrackList.h +++ b/dom/media/TextTrackList.h @@ -65,8 +65,6 @@ class TextTrackList final : public DOMEventTargetHelper { IMPL_EVENT_HANDLER(addtrack) IMPL_EVENT_HANDLER(removetrack) - bool mPendingTextTrackChange = false; - private: ~TextTrackList();