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
--- 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