From 324b1a63c1cd1e95db66484f921bd94af30c138a Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Thu, 27 Jun 2013 21:05:03 -0400 Subject: [PATCH] Bug 880094 - Provide a stable state for HTMLTrackElement asynchronous functions. r=cpearce - Removed HTMLMediaElement::AsyncAwaitStableState and exposed a new method, HTMLMediaElement::RunInStableState, that allows any nsIRunnable to run on the app shell and take advantage of IsCancelled() code in an nsMediaEvent. - HTMLTrackElement now uses this to call HTMLTrackElement::LoadResource. - Changed test_texttrackcue.html to listen for MediaElement's "loadedmetadata" to ensure that we wait until the cues are loaded before testing and set preload=auto to get it to pass on Android. --- .../html/content/public/HTMLMediaElement.h | 7 ++++++ content/html/content/src/HTMLMediaElement.cpp | 22 +++++++++---------- content/html/content/src/HTMLTrackElement.cpp | 2 +- content/media/test/test_texttrackcue.html | 6 ++--- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/content/html/content/public/HTMLMediaElement.h b/content/html/content/public/HTMLMediaElement.h index 221a7b0c18b..347675d8359 100644 --- a/content/html/content/public/HTMLMediaElement.h +++ b/content/html/content/public/HTMLMediaElement.h @@ -321,6 +321,13 @@ public: */ void SetRequestHeaders(nsIHttpChannel* aChannel); + /** + * Asynchronously awaits a stable state, whereupon aRunnable runs on the main + * thread. This adds an event which run aRunnable to the appshell's list of + * sections synchronous the next time control returns to the event loop. + */ + void RunInStableState(nsIRunnable* aRunnable); + /** * Fires a timeupdate event. If aPeriodic is true, the event will only * be fired if we've not fired a timeupdate event (for any reason) in the diff --git a/content/html/content/src/HTMLMediaElement.cpp b/content/html/content/src/HTMLMediaElement.cpp index 15239c46623..f22904f1ade 100644 --- a/content/html/content/src/HTMLMediaElement.cpp +++ b/content/html/content/src/HTMLMediaElement.cpp @@ -667,12 +667,12 @@ typedef void (HTMLMediaElement::*SyncSectionFn)(); class nsSyncSection : public nsMediaEvent { private: - SyncSectionFn mClosure; + nsCOMPtr mRunnable; public: nsSyncSection(HTMLMediaElement* aElement, - SyncSectionFn aClosure) : + nsIRunnable* aRunnable) : nsMediaEvent(aElement), - mClosure(aClosure) + mRunnable(aRunnable) { } @@ -680,20 +680,16 @@ public: // Silently cancel if our load has been cancelled. if (IsCancelled()) return NS_OK; - (mElement.get()->*mClosure)(); + mRunnable->Run(); return NS_OK; } }; static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); -// Asynchronously awaits a stable state, whereupon aClosure runs on the main -// thread. This adds an event which run aClosure to the appshell's list of -// sections synchronous the next time control returns to the event loop. -void AsyncAwaitStableState(HTMLMediaElement* aElement, - SyncSectionFn aClosure) +void HTMLMediaElement::RunInStableState(nsIRunnable* aRunnable) { - nsCOMPtr event = new nsSyncSection(aElement, aClosure); + nsCOMPtr event = new nsSyncSection(this, aRunnable); nsCOMPtr appShell = do_GetService(kAppShellCID); appShell->RunInStableState(event); } @@ -702,7 +698,8 @@ void HTMLMediaElement::QueueLoadFromSourceTask() { ChangeDelayLoadStatus(true); mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; - AsyncAwaitStableState(this, &HTMLMediaElement::LoadFromSourceChildren); + RunInStableState( + NS_NewRunnableMethod(this, &HTMLMediaElement::LoadFromSourceChildren)); } void HTMLMediaElement::QueueSelectResourceTask() @@ -712,7 +709,8 @@ void HTMLMediaElement::QueueSelectResourceTask() return; mHaveQueuedSelectResource = true; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE; - AsyncAwaitStableState(this, &HTMLMediaElement::SelectResourceWrapper); + RunInStableState( + NS_NewRunnableMethod(this, &HTMLMediaElement::SelectResourceWrapper)); } /* void load (); */ diff --git a/content/html/content/src/HTMLTrackElement.cpp b/content/html/content/src/HTMLTrackElement.cpp index e86cae15d36..7c77e583bc7 100644 --- a/content/html/content/src/HTMLTrackElement.cpp +++ b/content/html/content/src/HTMLTrackElement.cpp @@ -304,7 +304,7 @@ HTMLTrackElement::BindToTree(nsIDocument* aDocument, media->NotifyAddedSource(); LOG(PR_LOG_DEBUG, ("Track element sent notification to parent.")); - nsContentUtils::AddScriptRunner( + mMediaParent->RunInStableState( NS_NewRunnableMethod(this, &HTMLTrackElement::LoadResource)); } diff --git a/content/media/test/test_texttrackcue.html b/content/media/test/test_texttrackcue.html index a8a4a2d9314..5adcdbd124f 100644 --- a/content/media/test/test_texttrackcue.html +++ b/content/media/test/test_texttrackcue.html @@ -21,13 +21,13 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]}, function() { var video = document.createElement("video"); video.src = "seek.webm"; + video.preload = "auto"; var trackElement = document.createElement("track"); trackElement.src = "basic.vtt"; trackElement.kind = "subtitles"; document.getElementById("content").appendChild(video); video.appendChild(trackElement); - run_tests(); - function run_tests() { + video.addEventListener("loadedmetadata", function run_tests() { // Re-que run_tests() at the end of the event loop until the track // element has loaded its data. if (trackElement.readyState == 1) { @@ -116,7 +116,7 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]}, todo_is(cueList.length, 4, "Cue list length should be 4."); SimpleTest.finish(); - } + }); } );