Bug 1531863 - part2 : handle text track mode changed in MediaElement. r=jya
☠☠ backed out by b653c9d4de17 ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Thu, 07 Mar 2019 15:26:20 +0000
changeset 520916 21bafd01b4389ff72d26f78f28079a6585708b4c
parent 520915 c9628b2b89b23bbbf49d9854f9c1569c614558e2
child 520917 5be609c166652d5861cc5a8bac0265c3bf98d242
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [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
@@ -119,49 +119,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
@@ -61,18 +61,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);