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
This commit is contained in:
Alastor Wu 2019-03-07 15:26:20 +00:00
parent 01fa5895a1
commit 64ab84e0bc
5 changed files with 59 additions and 54 deletions

View File

@ -7375,6 +7375,22 @@ already_AddRefed<Promise> HTMLMediaElement::SetSinkId(const nsAString& aSinkId,
return promise.forget(); return promise.forget();
} }
void HTMLMediaElement::NotifyTextTrackModeChanged() {
if (mPendingTextTrackChanged) {
return;
}
mPendingTextTrackChanged = true;
mAbstractMainThread->Dispatch(
NS_NewRunnableFunction("HTMLMediaElement::NotifyTextTrackModeChanged",
[this, self = RefPtr<HTMLMediaElement>(this)]() {
mPendingTextTrackChanged = false;
if (!mTextTrackManager) {
return;
}
GetTextTracks()->CreateAndDispatchChangeEvent();
}));
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -1674,6 +1674,16 @@ class HTMLMediaElement : public nsGenericHTMLElement,
// bfcache. // bfcache.
bool mHasEverBeenBlockedForAutoplay = false; 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: public:
// Helper class to measure times for playback telemetry stats // Helper class to measure times for playback telemetry stats
class TimeDurationAccumulator { class TimeDurationAccumulator {

View File

@ -73,33 +73,28 @@ JSObject* TextTrack::WrapObject(JSContext* aCx,
} }
void TextTrack::SetMode(TextTrackMode aValue) { void TextTrack::SetMode(TextTrackMode aValue) {
if (mMode != aValue) { if (mMode == aValue) {
mMode = aValue; return;
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);
} }
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 { void TextTrack::GetId(nsAString& aId) const {

View File

@ -124,39 +124,25 @@ class TrackEventRunner : public Runnable {
RefPtr<Event> mEvent; RefPtr<Event> 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) { nsresult TextTrackList::DispatchTrackEvent(Event* aEvent) {
return DispatchTrustedEvent(aEvent); return DispatchTrustedEvent(aEvent);
} }
void TextTrackList::CreateAndDispatchChangeEvent() { void TextTrackList::CreateAndDispatchChangeEvent() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!mPendingTextTrackChange) { nsPIDOMWindowInner* win = GetOwner();
nsPIDOMWindowInner* win = GetOwner(); if (!win) {
if (!win) { return;
return;
}
mPendingTextTrackChange = true;
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
event->InitEvent(NS_LITERAL_STRING("change"), false, false);
event->SetTrusted(true);
nsCOMPtr<nsIRunnable> eventRunner = new ChangeEventRunner(this, event);
nsGlobalWindowInner::Cast(win)->Dispatch(TaskCategory::Other,
eventRunner.forget());
} }
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
event->InitEvent(NS_LITERAL_STRING("change"), false, false);
event->SetTrusted(true);
nsCOMPtr<nsIRunnable> eventRunner = new TrackEventRunner(this, event);
nsGlobalWindowInner::Cast(win)->Dispatch(TaskCategory::Other,
eventRunner.forget());
} }
void TextTrackList::CreateAndDispatchTrackEventRunner( void TextTrackList::CreateAndDispatchTrackEventRunner(

View File

@ -66,8 +66,6 @@ class TextTrackList final : public DOMEventTargetHelper {
IMPL_EVENT_HANDLER(addtrack) IMPL_EVENT_HANDLER(addtrack)
IMPL_EVENT_HANDLER(removetrack) IMPL_EVENT_HANDLER(removetrack)
bool mPendingTextTrackChange = false;
private: private:
~TextTrackList(); ~TextTrackList();