Bug 1531863 - part2 : handle text track mode changed in MediaElement. r=jya
authorAlastor Wu <alwu@mozilla.com>
Tue, 12 Mar 2019 00:32:21 +0000
changeset 521462 6dbda553b478
parent 521461 5b9bb0da7cd6
child 521463 442e99192e46
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1531863
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/TextTrack.cpp
dom/media/TextTrackList.cpp
dom/media/TextTrackList.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -7370,13 +7370,29 @@ already_AddRefed<Promise> HTMLMediaEleme
               }
             }
           });
 
   aRv = NS_OK;
   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 mozilla
 
 #undef LOG
 #undef LOG_EVENT
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1669,16 +1669,26 @@ class HTMLMediaElement : public nsGeneri
   // audio.
   MozPromiseHolder<GenericNonExclusivePromise> mAllowedToPlayPromise;
 
   // True if media has ever been blocked for autoplay, it's used to notify front
   // end to show the correct blocking icon when the document goes back from
   // 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 {
    public:
     TimeDurationAccumulator() : mCount(0) {}
     void Start() {
       if (IsStarted()) {
         return;
--- a/dom/media/TextTrack.cpp
+++ b/dom/media/TextTrack.cpp
@@ -68,43 +68,38 @@ void TextTrack::SetDefaultSettings() {
 }
 
 JSObject* TextTrack::WrapObject(JSContext* aCx,
                                 JS::Handle<JSObject*> aGivenProto) {
   return TextTrack_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 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 (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]);
     }
-    if (mTextTrackList) {
-      mTextTrackList->CreateAndDispatchChangeEvent();
+    SetCuesInactive();
+  } else {
+    for (size_t i = 0; i < mCueList->Length() && mediaElement; ++i) {
+      mediaElement->NotifyCueAdded(*(*mCueList)[i]);
     }
-    // Ensure the TimeMarchesOn is called in case that the mCueList
-    // is empty.
-    NotifyCueUpdated(nullptr);
+  }
+  if (mediaElement) {
+    mediaElement->NotifyTextTrackModeChanged();
   }
+  // Ensure the TimeMarchesOn is called in case that the mCueList
+  // is empty.
+  NotifyCueUpdated(nullptr);
 }
 
 void TextTrack::GetId(nsAString& aId) const {
   // If the track has a track element then its id should be the same as the
   // track element's id.
   if (mTrackElement) {
     mTrackElement->GetAttribute(NS_LITERAL_STRING("id"), aId);
   }
--- a/dom/media/TextTrackList.cpp
+++ b/dom/media/TextTrackList.cpp
@@ -113,49 +113,35 @@ class TrackEventRunner : public Runnable
   NS_IMETHOD Run() override { return mList->DispatchTrackEvent(mEvent); }
 
   RefPtr<TextTrackList> mList;
 
  private:
   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) {
   return DispatchTrustedEvent(aEvent);
 }
 
 void TextTrackList::CreateAndDispatchChangeEvent() {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!mPendingTextTrackChange) {
-    nsPIDOMWindowInner* win = GetOwner();
-    if (!win) {
-      return;
-    }
+  nsPIDOMWindowInner* win = GetOwner();
+  if (!win) {
+    return;
+  }
+
+  RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
 
-    mPendingTextTrackChange = true;
-    RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
+  event->InitEvent(NS_LITERAL_STRING("change"), false, false);
+  event->SetTrusted(true);
 
-    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());
-  }
+  nsCOMPtr<nsIRunnable> eventRunner = new TrackEventRunner(this, event);
+  nsGlobalWindowInner::Cast(win)->Dispatch(TaskCategory::Other,
+                                           eventRunner.forget());
 }
 
 void TextTrackList::CreateAndDispatchTrackEventRunner(
     TextTrack* aTrack, const nsAString& aEventName) {
   DebugOnly<nsresult> rv;
   nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
   if (!target) {
     // If we are not able to get the main-thread object we are shutting down.
--- a/dom/media/TextTrackList.h
+++ b/dom/media/TextTrackList.h
@@ -60,18 +60,16 @@ class TextTrackList final : public DOMEv
 
   bool AreTextTracksLoaded();
   nsTArray<RefPtr<TextTrack>>& GetTextTrackArray();
 
   IMPL_EVENT_HANDLER(change)
   IMPL_EVENT_HANDLER(addtrack)
   IMPL_EVENT_HANDLER(removetrack)
 
-  bool mPendingTextTrackChange = false;
-
  private:
   ~TextTrackList();
 
   nsTArray<RefPtr<TextTrack>> mTextTracks;
   RefPtr<TextTrackManager> mTextTrackManager;
 
   void CreateAndDispatchTrackEventRunner(TextTrack* aTrack,
                                          const nsAString& aEventName);