Bug 1222980 - Dispatch |QueueLoadFromSourceTask| to main thread. And end the synchronous section and asynchronously await a stable state when the src is not set. r?jwwang. draft
authorctai <ctai@mozilla.com>
Tue, 13 Dec 2016 15:45:59 +0800
changeset 451841 6a167a8af202519b5a22e736c4910a167404e2cc
parent 451264 567894f026558e6dada617a3998f29aed06ac7d8
child 451842 4650ac2f3d836a9a44446e0464932c41e2872ee7
push id39309
push userbmo:ctai@mozilla.com
push dateWed, 21 Dec 2016 02:48:35 +0000
reviewersjwwang
bugs1222980
milestone53.0a1
Bug 1222980 - Dispatch |QueueLoadFromSourceTask| to main thread. And end the synchronous section and asynchronously await a stable state when the src is not set. r?jwwang. Dispatch |QueueLoadFromSourceTask| to main thread to make sure the task will be executed later than loadstart event. And when the src get errors, we need to end the synchronous section. MozReview-Commit-ID: EQ0jVIMnqoZ
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1721,22 +1721,30 @@ public:
       return NS_OK;
     mRunnable->Run();
     return NS_OK;
   }
 };
 
 void HTMLMediaElement::RunInStableState(nsIRunnable* aRunnable)
 {
+  if (mShuttingDown) {
+    return;
+  }
+
   nsCOMPtr<nsIRunnable> event = new nsSyncSection(this, aRunnable);
   nsContentUtils::RunInStableState(event.forget());
 }
 
 void HTMLMediaElement::QueueLoadFromSourceTask()
 {
+  if (!mIsLoadingFromSourceChildren || mShuttingDown) {
+    return;
+  }
+
   ChangeDelayLoadStatus(true);
   ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_LOADING);
   RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLMediaElement::LoadFromSourceChildren);
   RunInStableState(r);
 }
 
 void HTMLMediaElement::QueueSelectResourceTask()
 {
@@ -2063,16 +2071,28 @@ void HTMLMediaElement::NotifyMediaStream
     // We are a video element and HasVideo() changed so update the screen
     // wakelock
     NotifyOwnerDocumentActivityChanged();
   }
 
   mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal);
 }
 
+void HTMLMediaElement::DealWithFailedElement(nsIContent* aSourceElement)
+{
+  if (mShuttingDown) {
+    return;
+  }
+
+  DispatchAsyncSourceError(aSourceElement);
+  nsCOMPtr<nsIRunnable> event =
+    NewRunnableMethod(this, &HTMLMediaElement::QueueLoadFromSourceTask);
+  NS_DispatchToMainThread(event);
+}
+
 void
 HTMLMediaElement::NotifyOutputTrackStopped(DOMMediaStream* aOwningStream,
                                            TrackID aDestinationTrackID)
 {
   for (OutputMediaStream& ms : mOutputStreams) {
     if (!ms.mCapturingMediaStream) {
       continue;
     }
@@ -2120,54 +2140,54 @@ void HTMLMediaElement::LoadFromSourceChi
       ReportLoadError("MediaLoadExhaustedCandidates");
       return;
     }
 
     // Must have src attribute.
     nsAutoString src;
     if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
       ReportLoadError("MediaLoadSourceMissingSrc");
-      DispatchAsyncSourceError(child);
-      continue;
+      DealWithFailedElement(child);
+      return;
     }
 
     // If we have a type attribute, it must be a supported type.
     nsAutoString type;
     if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
       DecoderDoctorDiagnostics diagnostics;
       CanPlayStatus canPlay = GetCanPlay(type, &diagnostics);
       diagnostics.StoreFormatDiagnostics(
         OwnerDoc(), type, canPlay != CANPLAY_NO, __func__);
       if (canPlay == CANPLAY_NO) {
-        DispatchAsyncSourceError(child);
         const char16_t* params[] = { type.get(), src.get() };
         ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
-        continue;
+        DealWithFailedElement(child);
+        return;
       }
     }
     nsAutoString media;
     HTMLSourceElement *childSrc = HTMLSourceElement::FromContent(child);
     MOZ_ASSERT(childSrc, "Expect child to be HTMLSourceElement");
     if (childSrc && !childSrc->MatchesCurrentMedia()) {
-      DispatchAsyncSourceError(child);
       const char16_t* params[] = { media.get(), src.get() };
       ReportLoadError("MediaLoadSourceMediaNotMatched", params, ArrayLength(params));
-      continue;
+      DealWithFailedElement(child);
+      return;
     }
     LOG(LogLevel::Debug, ("%p Trying load from <source>=%s type=%s media=%s", this,
       NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get(),
       NS_ConvertUTF16toUTF8(media).get()));
 
     nsCOMPtr<nsIURI> uri;
     NewURIFromString(src, getter_AddRefs(uri));
     if (!uri) {
-      DispatchAsyncSourceError(child);
       const char16_t* params[] = { src.get() };
       ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
-      continue;
+      DealWithFailedElement(child);
+      return;
     }
 
     RemoveMediaElementFromURITable();
     mLoadingSrc = uri;
     mMediaSource = childSrc->GetSrcMediaSource();
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -960,16 +960,24 @@ protected:
    * This is the dedicated media source failure steps.
    * Called when all potential resources are exhausted. Changes network
    * state to NETWORK_NO_SOURCE, and sends error event with code
    * MEDIA_ERR_SRC_NOT_SUPPORTED.
    */
   void NoSupportedMediaSourceError(const nsACString& aErrorDetails = nsCString());
 
   /**
+   * Per spec, Failed with elements: Queue a task, using the DOM manipulation
+   * task source, to fire a simple event named error at the candidate element.
+   * So dispatch |QueueLoadFromSourceTask| to main thread to make sure the task
+   * will be executed later than loadstart event.
+   */
+  void DealWithFailedElement(nsIContent* aSourceElement);
+
+  /**
    * Attempts to load resources from the <source> children. This is a
    * substep of the resource selection algorithm. Do not call this directly,
    * call QueueLoadFromSourceTask() instead.
    */
   void LoadFromSourceChildren();
 
   /**
    * Asynchronously awaits a stable state, and then causes