Bug 882718 - 1. Fix testcase crash/failed . 2. The cuechange event should be fired in TimeMarchesOn. r=rillian draft
authorbechen <bechen@mozilla.com>
Wed, 01 Jun 2016 15:13:43 +0800
changeset 373771 47f9d6d574bab28e3acb5f3b887cacb3661b0fb7
parent 373768 426a405c60c614139e0d29e659f169b8b2859ee9
child 373772 75d748f68cb92af1b394bfa1e47ccd609fafa618
child 373860 d9345c6789d75df732edc8ecd9c53e3f5bc57899
push id19839
push userbechen@mozilla.com
push dateWed, 01 Jun 2016 07:14:12 +0000
reviewersrillian
bugs882718
milestone49.0a1
Bug 882718 - 1. Fix testcase crash/failed . 2. The cuechange event should be fired in TimeMarchesOn. r=rillian MozReview-Commit-ID: EYi9iZ1mfjg
dom/html/HTMLMediaElement.cpp
dom/html/TextTrackManager.cpp
dom/media/TextTrack.cpp
dom/media/TextTrackCueList.cpp
dom/media/TextTrackCueList.h
dom/media/test/test_texttrackcue.html
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3743,23 +3743,23 @@ void HTMLMediaElement::SeekStarted()
 {
   DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
 }
 
 void HTMLMediaElement::SeekCompleted()
 {
   mPlayingBeforeSeek = false;
   SetPlayedOrSeeked(true);
+  if (mTextTrackManager) {
+    mTextTrackManager->DidSeek();
+  }
   FireTimeUpdate(false);
   DispatchAsyncEvent(NS_LITERAL_STRING("seeked"));
   // We changed whether we're seeking so we need to AddRemoveSelfReference
   AddRemoveSelfReference();
-  if (mTextTrackManager) {
-    mTextTrackManager->DidSeek();
-  }
   if (mCurrentPlayRangeStart == -1.0) {
     mCurrentPlayRangeStart = CurrentTime();
   }
   // Unset the variable on seekend
   mPlayingThroughTheAudioChannelBeforeSeek = false;
 }
 
 void HTMLMediaElement::NotifySuspendedByCache(bool aIsSuspended)
--- a/dom/html/TextTrackManager.cpp
+++ b/dom/html/TextTrackManager.cpp
@@ -188,29 +188,31 @@ TextTrackManager::RemoveTextTrack(TextTr
     return;
   }
 
   mTextTracks->RemoveTextTrack(aTextTrack);
   // Remove the cues in mNewCues belong to aTextTrack.
   TextTrackCueList* removeCueList = aTextTrack->GetCues();
   if (removeCueList) {
     for (uint32_t i = 0; i < removeCueList->Length(); ++i) {
-      ErrorResult dummyRv;
-      mNewCues->RemoveCue(*((*removeCueList)[i]), dummyRv);
+      mNewCues->RemoveCue(*((*removeCueList)[i]));
     }
     DispatchTimeMarchesOn();
   }
 }
 
 void
 TextTrackManager::DidSeek()
 {
   if (mTextTracks) {
     mTextTracks->DidSeek();
   }
+  if (mMediaElement) {
+    mLastTimeMarchesOnCalled = mMediaElement->CurrentTime();
+  }
   mHasSeeked = true;
 }
 
 void
 TextTrackManager::UpdateCueDisplay()
 {
   if (!mMediaElement || !mTextTracks) {
     return;
@@ -259,18 +261,17 @@ TextTrackManager::AddCue(TextTrackCue& a
   }
   DispatchTimeMarchesOn();
 }
 
 void
 TextTrackManager::NotifyCueRemoved(TextTrackCue& aCue)
 {
   if (mNewCues) {
-    ErrorResult dummyRv;
-    mNewCues->RemoveCue(aCue, dummyRv);
+    mNewCues->RemoveCue(aCue);
   }
   DispatchTimeMarchesOn();
 }
 
 void
 TextTrackManager::PopulatePendingList()
 {
   if (!mTextTracks || !mPendingTextTracks || !mMediaElement) {
@@ -527,17 +528,18 @@ TextTrackManager::TimeMarchesOn()
 
   nsISupports* parentObject =
     mMediaElement->OwnerDoc()->GetParentObject();
   if (NS_WARN_IF(!parentObject)) {
     return;
   }
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(parentObject);
 
-  if (mMediaElement && !(mMediaElement->GetPlayedOrSeeked())) {
+  if (mMediaElement &&
+      (!(mMediaElement->GetPlayedOrSeeked())|| mMediaElement->Seeking())) {
     return;
   }
 
   // Step 3.
   double currentPlaybackTime = mMediaElement->CurrentTime();
   bool hasNormalPlayback = !mHasSeeked;
   mHasSeeked = false;
 
@@ -565,18 +567,17 @@ TextTrackManager::TimeMarchesOn()
                                      currentPlaybackTime);
     otherCues = mNewCues->GetCueListByTimeInterval(interval);;
   } else {
     // Seek case. Put the mLastActiveCues into otherCues.
     otherCues = mLastActiveCues;
   }
   for (uint32_t i = 0; i < currentCues->Length(); ++i) {
     TextTrackCue* cue = (*currentCues)[i];
-    ErrorResult dummy;
-    otherCues->RemoveCue(*cue, dummy);
+    otherCues->RemoveCue(*cue);
   }
 
   // Step 4.
   RefPtr<TextTrackCueList> missedCues = new TextTrackCueList(window);
   if (hasNormalPlayback) {
     for (uint32_t i = 0; i < otherCues->Length(); ++i) {
       TextTrackCue* cue = (*otherCues)[i];
       if (cue->StartTime() >= mLastTimeMarchesOnCalled &&
@@ -691,16 +692,20 @@ TextTrackManager::TimeMarchesOn()
     NS_DispatchToMainThread(eventList[i].forget());
   }
 
   // Step 16.
   for (uint32_t i = 0; i < affectedTracks.Length(); ++i) {
     TextTrack* ttrack = affectedTracks[i];
     if (ttrack) {
       ttrack->DispatchTrustedEvent(NS_LITERAL_STRING("cuechange"));
+      HTMLTrackElement* trackElement = ttrack->GetTrackElement();
+      if (trackElement) {
+        trackElement->DispatchTrackRunnable(NS_LITERAL_STRING("cuechange"));
+      }
     }
   }
 
   mLastTimeMarchesOnCalled = currentPlaybackTime;
   mLastActiveCues = currentCues;
 }
 
 } // namespace dom
--- a/dom/media/TextTrack.cpp
+++ b/dom/media/TextTrack.cpp
@@ -124,23 +124,24 @@ TextTrack::AddCue(TextTrackCue& aCue)
     }
   }
   SetDirty();
 }
 
 void
 TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
 {
-  //TODO: Apply the rules for text track cue rendering Bug 865407
   aCue.SetActive(false);
 
   mCueList->RemoveCue(aCue, aRv);
-  HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
-  if (mediaElement) {
-    mediaElement->NotifyCueRemoved(aCue);
+  if (mTextTrackList) {
+    HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
+    if (mediaElement) {
+      mediaElement->NotifyCueRemoved(aCue);
+    }
   }
   SetDirty();
 }
 
 void
 TextTrack::SetCuesDirty()
 {
   for (uint32_t i = 0; i < mCueList->Length(); i++) {
@@ -155,56 +156,41 @@ TextTrack::UpdateActiveCueList()
     return;
   }
 
   HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
   if (!mediaElement) {
     return;
   }
 
-  // Flag that indicates whether or not this call of UpdateActiveCueList has
-  // changed the activeCueList.
-  bool hasChanged = false;
-
   // If we are dirty, i.e. an event happened that may cause the sorted mCueList
   // to have changed like a seek or an insert for a cue, than we need to rebuild
   // the active cue list from scratch.
   if (mDirty) {
     mCuePos = 0;
     mDirty = false;
     mActiveCueList->RemoveAll();
   }
 
   double playbackTime = mediaElement->CurrentTime();
   // Remove all the cues from the active cue list whose end times now occur
   // earlier then the current playback time.
   for (uint32_t i = mActiveCueList->Length(); i > 0; i--) {
     if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) {
       mActiveCueList->RemoveCueAt(i - 1);
-      hasChanged = true;
     }
   }
   // Add all the cues, starting from the position of the last cue that was
   // added, that have valid start and end times for the current playback time.
   // We can stop iterating safely once we encounter a cue that does not have
   // a valid start time as the cue list is sorted.
   for (; mCuePos < mCueList->Length() &&
          (*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) {
     if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) {
       mActiveCueList->AddCue(*(*mCueList)[mCuePos]);
-      hasChanged = true;
-      }
-    }
-
-    if (hasChanged) {
-      RefPtr<AsyncEventDispatcher> asyncDispatcher =
-        new AsyncEventDispatcher(this, NS_LITERAL_STRING("cuechange"), false);
-      asyncDispatcher->PostDOMEvent();
-      if (mTrackElement) {
-        mTrackElement->DispatchTrackRunnable(NS_LITERAL_STRING("cuechange"));
     }
   }
 }
 
 TextTrackCueList*
 TextTrack::GetActiveCues() {
   if (mMode != TextTrackMode::Disabled) {
     UpdateActiveCueList();
--- a/dom/media/TextTrackCueList.cpp
+++ b/dom/media/TextTrackCueList.cpp
@@ -99,16 +99,22 @@ TextTrackCueList::RemoveCue(TextTrackCue
   if (!mList.Contains(&aCue)) {
     aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return;
   }
   mList.RemoveElement(&aCue);
 }
 
 void
+TextTrackCueList::RemoveCue(TextTrackCue& aCue)
+{
+  mList.RemoveElement(&aCue);
+}
+
+void
 TextTrackCueList::RemoveCueAt(uint32_t aIndex)
 {
   if (aIndex < mList.Length()) {
     mList.RemoveElementAt(aIndex);
   }
 }
 
 void
--- a/dom/media/TextTrackCueList.h
+++ b/dom/media/TextTrackCueList.h
@@ -45,16 +45,17 @@ public:
   TextTrackCue* operator[](uint32_t aIndex);
   TextTrackCue* GetCueById(const nsAString& aId);
   TextTrackCueList& operator=(const TextTrackCueList& aOther);
   // Adds a cue to mList by performing an insertion sort on mList.
   // We expect most files to already be sorted, so an insertion sort starting
   // from the end of the current array should be more efficient than a general
   // sort step after all cues are loaded.
   void AddCue(TextTrackCue& aCue);
+  void RemoveCue(TextTrackCue& aCue);
   void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
   void RemoveCueAt(uint32_t aIndex);
   void RemoveAll();
   void GetArray(nsTArray<RefPtr<TextTrackCue> >& aCues);
 
   void SetCuesInactive();
 
   already_AddRefed<TextTrackCueList>
--- a/dom/media/test/test_texttrackcue.html
+++ b/dom/media/test/test_texttrackcue.html
@@ -78,16 +78,20 @@ SpecialPowers.pushPrefEnv({"set": [["med
       cue.id = "Cue 01";
       is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
       cue.startTime = 0.51;
       is(cue.startTime, 0.51, "Cue's start time should be 0.51.");
       cue.endTime = 0.71;
       is(cue.endTime, 0.71, "Cue's end time should be 0.71.");
       cue.pauseOnExit = true;
       is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
+      video.addEventListener("pause", function pauseOnExit() {
+        video.removeEventListener("pause", pauseOnExit, false);
+        video.play();
+      });
 
       var exceptionHappened;
       function checkPercentageValue(prop) {
         ok(prop in cue, prop + " should be a property on VTTCue.");
         cue[prop] = 20;
         is(cue[prop], 20, "Cue's " + prop + " should now be 20.");
         [ 101, -1 ].forEach(function(val) {
           exceptionHappened = false;