зеркало из https://github.com/mozilla/gecko-dev.git
Bug 462455. Initiate media load when appending <source> child elements to media elements. r=doublec,sr=roc
--HG-- extra : rebase_source : b9bca050ef528705c08988d3677bf9bd8c865f33
This commit is contained in:
Родитель
dc2eb3467f
Коммит
318f45146f
|
@ -154,8 +154,8 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument)
|
|||
|
||||
// IID for the nsINode interface
|
||||
#define NS_INODE_IID \
|
||||
{ 0x355cc896, 0x2ed0, 0x4237, \
|
||||
{ 0x85, 0xf7, 0x4d, 0xb0, 0xcf, 0x4d, 0xc4, 0x90 } }
|
||||
{ 0x075803c5, 0xb37f, 0x489f, \
|
||||
{ 0x9b, 0x17, 0x9a, 0x60, 0x44, 0x5d, 0x66, 0x1b } }
|
||||
|
||||
/**
|
||||
* An internal interface that abstracts some DOMNode-related parts that both
|
||||
|
@ -215,7 +215,9 @@ public:
|
|||
returns a non-null value for nsIContent::GetText() */
|
||||
eDATA_NODE = 1 << 12,
|
||||
/** nsMathMLElement */
|
||||
eMATHML = 1 << 13
|
||||
eMATHML = 1 << 13,
|
||||
/** nsHTMLMediaElement */
|
||||
eMEDIA = 1 << 14
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsMediaDecoder.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
// Define to output information on decoding and painting framerate
|
||||
/* #define DEBUG_FRAME_RATE 1 */
|
||||
|
@ -46,6 +47,17 @@
|
|||
typedef PRUint16 nsMediaNetworkState;
|
||||
typedef PRUint16 nsMediaReadyState;
|
||||
|
||||
// Object representing a single execution of the media load algorithm.
|
||||
// Used by implicit load events so that they can be cancelled when Load()
|
||||
// is executed.
|
||||
// Note: When bug 465458 lands, all events are expected to do this, not
|
||||
// just implicit load events.
|
||||
class nsMediaLoad : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS;
|
||||
};
|
||||
|
||||
class nsHTMLMediaElement : public nsGenericHTMLElement
|
||||
{
|
||||
public:
|
||||
|
@ -192,6 +204,29 @@ public:
|
|||
*/
|
||||
static void ShutdownMediaTypes();
|
||||
|
||||
/**
|
||||
* Called when a child source element is added to this media element. This
|
||||
* may queue a load() task if appropriate.
|
||||
*/
|
||||
void NotifyAddedSource();
|
||||
|
||||
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
|
||||
|
||||
/**
|
||||
* Queues an event to call Load().
|
||||
*/
|
||||
void QueueLoadTask();
|
||||
|
||||
/**
|
||||
* Returns the current nsMediaLoad object. Implicit load events store a
|
||||
* reference to the nsMediaLoad object that was current when they were
|
||||
* enqueued, and if it has changed when they come to fire, they consider
|
||||
* themselves cancelled, and don't fire.
|
||||
* Note: When bug 465458 lands, all events are expected to do this, not
|
||||
* just implicit load events.
|
||||
*/
|
||||
nsMediaLoad* GetCurrentMediaLoad() { return mCurrentLoad; }
|
||||
|
||||
protected:
|
||||
class nsMediaLoadListener;
|
||||
|
||||
|
@ -235,6 +270,9 @@ protected:
|
|||
// Error attribute
|
||||
nsCOMPtr<nsIDOMHTMLMediaError> mError;
|
||||
|
||||
// The current media load object.
|
||||
nsRefPtr<nsMediaLoad> mCurrentLoad;
|
||||
|
||||
// Media loading flags. See:
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#video)
|
||||
nsMediaNetworkState mNetworkState;
|
||||
|
@ -291,4 +329,7 @@ protected:
|
|||
// PR_TRUE if we've reported a "waiting" event since the last
|
||||
// readyState change to HAVE_CURRENT_DATA.
|
||||
PRPackedBool mWaitingFired;
|
||||
|
||||
// PR_TRUE if we're in BindToTree().
|
||||
PRPackedBool mIsBindingToTree;
|
||||
};
|
||||
|
|
|
@ -103,6 +103,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// Asynchronous runner which invokes Load() on the main thread.
|
||||
class nsMediaLoadEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsMediaLoadEvent(nsHTMLMediaElement *aMedia)
|
||||
: mMedia(aMedia), mCurrentLoad(mMedia->GetCurrentMediaLoad()) {}
|
||||
~nsMediaLoadEvent() {}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
// Only run the task if it's not been cancelled.
|
||||
if (mMedia && mMedia->GetCurrentMediaLoad() == mCurrentLoad)
|
||||
mMedia->Load();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsHTMLMediaElement> mMedia;
|
||||
nsRefPtr<nsMediaLoad> mCurrentLoad;
|
||||
};
|
||||
|
||||
class nsHTMLMediaElement::nsMediaLoadListener : public nsIStreamListener
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -169,6 +189,8 @@ NS_IMETHODIMP nsHTMLMediaElement::nsMediaLoadListener::OnDataAvailable(nsIReques
|
|||
return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS0(nsMediaLoad)
|
||||
|
||||
// nsIDOMHTMLMediaElement
|
||||
NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls)
|
||||
|
@ -257,9 +279,21 @@ void nsHTMLMediaElement::NoSupportedMediaError()
|
|||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::QueueLoadTask()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event = new nsMediaLoadEvent(this);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
/* void load (); */
|
||||
NS_IMETHODIMP nsHTMLMediaElement::Load()
|
||||
{
|
||||
// Set a new load object. This will cause implicit load events which were
|
||||
// enqueued before with a different load object to silently be cancelled.
|
||||
// Note: When bug 465458 lands, all events are expected to do this, not
|
||||
// just implicit load events.
|
||||
mCurrentLoad = new nsMediaLoad();
|
||||
|
||||
if (AbortExistingLoads())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -271,7 +305,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
nsresult rv = PickMediaElement(getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv)) {
|
||||
NoSupportedMediaError();
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mChannel) {
|
||||
|
@ -291,7 +325,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
nsContentUtils::GetSecurityManager());
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
NoSupportedMediaError();
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(mChannel),
|
||||
|
@ -302,7 +336,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
nsIRequest::LOAD_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NetworkError();
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
// The listener holds a strong reference to us. This creates a reference
|
||||
// cycle which is manually broken in the listener's OnStartRequest method
|
||||
|
@ -320,7 +354,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (NS_FAILED(rv)) {
|
||||
NoSupportedMediaError();
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
|
@ -329,7 +363,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
nsIScriptSecurityManager::STANDARD);
|
||||
if (NS_FAILED(rv)) {
|
||||
NoSupportedMediaError();
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
listener = loadListener;
|
||||
}
|
||||
|
@ -354,7 +388,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
|
|||
// be destroyed.
|
||||
mChannel = nsnull;
|
||||
NetworkError();
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -530,7 +564,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
|
|||
mMuted(PR_FALSE),
|
||||
mIsDoneAddingChildren(!aFromParser),
|
||||
mPlayingBeforeSeek(PR_FALSE),
|
||||
mWaitingFired(PR_FALSE)
|
||||
mWaitingFired(PR_FALSE),
|
||||
mIsBindingToTree(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -630,17 +665,19 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
|
|||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
mIsBindingToTree = PR_TRUE;
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
|
||||
aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mIsDoneAddingChildren &&
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
mIsDoneAddingChildren &&
|
||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
Load();
|
||||
QueueLoadTask();
|
||||
}
|
||||
|
||||
mIsBindingToTree = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1266,7 @@ nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified)
|
|||
mIsDoneAddingChildren = PR_TRUE;
|
||||
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
Load();
|
||||
QueueLoadTask();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,3 +1347,25 @@ void nsHTMLMediaElement::Thaw()
|
|||
mDecoder->Resume();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLMediaElement::IsNodeOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eCONTENT | eELEMENT | eHTML | eMEDIA));
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::NotifyAddedSource()
|
||||
{
|
||||
// Binding a source element to a media element could trigger a new load.
|
||||
// See HTML spec, '4.8.9 The source element' for conditions:
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
|
||||
// Note: we must not start a load if we're in nsHTMLMediaElement::BindToTree(),
|
||||
// that will trigger a load when it completes.
|
||||
PRBool shouldLoad = IsInDoc() &&
|
||||
!mIsBindingToTree &&
|
||||
mIsDoneAddingChildren &&
|
||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
||||
if (shouldLoad) {
|
||||
QueueLoadTask();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsHTMLMediaElement.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsHTMLSourceElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLSourceElement
|
||||
|
@ -71,6 +74,12 @@ public:
|
|||
const nsAString& aValue,
|
||||
nsAttrValue& aResult);
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
// Override BindToTree() so that we can trigger a load when we add a
|
||||
// child source element.
|
||||
virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
|
||||
nsIContent *aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
};
|
||||
|
||||
|
||||
|
@ -124,3 +133,24 @@ nsHTMLSourceElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSourceElement::BindToTree(nsIDocument *aDocument,
|
||||
nsIContent *aParent,
|
||||
nsIContent *aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
|
||||
aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aParent->IsNodeOfType(nsINode::eMEDIA))
|
||||
return NS_OK;
|
||||
|
||||
nsHTMLMediaElement* media = static_cast<nsHTMLMediaElement*>(aParent);
|
||||
media->NotifyAddedSource();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,13 @@ public:
|
|||
nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus();
|
||||
|
||||
private:
|
||||
|
||||
// Returns PR_TRUE if we're in shutdown state. Threadsafe.
|
||||
PRBool IsShutdown();
|
||||
|
||||
// Reads from the media stream. Returns PR_FALSE on failure or EOF.
|
||||
PRBool ReadAll(char* aBuf, PRUint32 aSize);
|
||||
|
||||
// Change the current state and wake the playback thread if it is waiting
|
||||
// on mMonitor. Used by public member functions called from both threads,
|
||||
// so must hold mMonitor. Threadsafe.
|
||||
|
@ -898,16 +905,25 @@ ReadUint16LE(const char** aBuffer)
|
|||
return result;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ReadAll(nsMediaStream* aStream, char* aBuf, PRUint32 aSize)
|
||||
PRBool
|
||||
nsWaveStateMachine::IsShutdown()
|
||||
{
|
||||
nsAutoMonitor monitor(mMonitor);
|
||||
return mState == STATE_SHUTDOWN;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsWaveStateMachine::ReadAll(char* aBuf, PRUint32 aSize)
|
||||
{
|
||||
PRUint32 got = 0;
|
||||
do {
|
||||
PRUint32 read = 0;
|
||||
if (NS_FAILED(aStream->Read(aBuf + got, aSize - got, &read))) {
|
||||
if (NS_FAILED(mStream->Read(aBuf + got, aSize - got, &read))) {
|
||||
NS_WARNING("Stream read failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (IsShutdown())
|
||||
return PR_FALSE;
|
||||
got += read;
|
||||
} while (got != aSize);
|
||||
return PR_TRUE;
|
||||
|
@ -922,7 +938,7 @@ nsWaveStateMachine::LoadRIFFChunk()
|
|||
NS_ABORT_IF_FALSE(mStream->Tell() == 0,
|
||||
"LoadRIFFChunk called when stream in invalid state");
|
||||
|
||||
if (!ReadAll(mStream, riffHeader, sizeof(riffHeader))) {
|
||||
if (!ReadAll(riffHeader, sizeof(riffHeader))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -953,7 +969,7 @@ nsWaveStateMachine::LoadFormatChunk()
|
|||
NS_ABORT_IF_FALSE(mStream->Tell() % 2 == 0,
|
||||
"LoadFormatChunk called with unaligned stream");
|
||||
|
||||
if (!ReadAll(mStream, waveFormat, sizeof(waveFormat))) {
|
||||
if (!ReadAll(waveFormat, sizeof(waveFormat))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -988,7 +1004,7 @@ nsWaveStateMachine::LoadFormatChunk()
|
|||
char extLength[2];
|
||||
const char* p = extLength;
|
||||
|
||||
if (!ReadAll(mStream, extLength, sizeof(extLength))) {
|
||||
if (!ReadAll(extLength, sizeof(extLength))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1001,7 +1017,7 @@ nsWaveStateMachine::LoadFormatChunk()
|
|||
|
||||
if (extra > 0) {
|
||||
nsAutoArrayPtr<char> chunkExtension(new char[extra]);
|
||||
if (!ReadAll(mStream, chunkExtension.get(), extra)) {
|
||||
if (!ReadAll(chunkExtension.get(), extra)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -1050,7 +1066,7 @@ nsWaveStateMachine::FindDataOffset()
|
|||
char chunkHeader[8];
|
||||
const char* p = chunkHeader;
|
||||
|
||||
if (!ReadAll(mStream, chunkHeader, sizeof(chunkHeader))) {
|
||||
if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1086,7 @@ nsWaveStateMachine::FindDataOffset()
|
|||
size += size % 2;
|
||||
|
||||
nsAutoArrayPtr<char> chunk(new char[size]);
|
||||
if (!ReadAll(mStream, chunk.get(), size)) {
|
||||
if (!ReadAll(chunk.get(), size)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,9 +76,12 @@ _TEST_FILES += \
|
|||
test_ended2.html \
|
||||
test_error_on_404.html \
|
||||
test_onloadedmetadata.html \
|
||||
test_load_coalescing.html \
|
||||
test_play.html \
|
||||
test_progress1.html \
|
||||
test_progress3.html \
|
||||
test_source.html \
|
||||
test_source_write.html \
|
||||
test_standalone.html \
|
||||
test_timeupdate1.html \
|
||||
test_timeupdate2.html \
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=462455
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 462455</title>
|
||||
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462455">Mozilla Bug 462455</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 462455 **/
|
||||
/** Tests case described in bug 462455 comment 22. **/
|
||||
|
||||
var gLoadStartsCount = 0;
|
||||
var gAbortCount = 0;
|
||||
var gVolumeChanged = 0;
|
||||
var gEmptiedCount = 0;
|
||||
|
||||
function errorHandler(e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function abortHandler() {
|
||||
gAbortCount++;
|
||||
}
|
||||
|
||||
function startHandler() {
|
||||
gLoadStartsCount++;
|
||||
}
|
||||
|
||||
function loadedHandler() {
|
||||
is(gLoadStartsCount, 2, "Should have received 2 loadstarts.");
|
||||
is(gAbortCount, 0, "Shouldn't have aborted any loads");
|
||||
is(gVolumeChanged, 1, "Should have received volume changed");
|
||||
is(gEmptiedCount, 1, "EmptiedCount should be 1");
|
||||
gLoadStartsCount = 0;
|
||||
gAbortCount = 0;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function emptiedHandler() {
|
||||
gEmptiedCount++;
|
||||
}
|
||||
|
||||
function volumeChangeHandler() {
|
||||
gVolumeChanged++;
|
||||
}
|
||||
|
||||
function testEventOrder() {
|
||||
var v = document.createElement('video');
|
||||
v.addEventListener('error', errorHandler, false);
|
||||
v.addEventListener('abort', abortHandler, false);
|
||||
v.addEventListener('loadeddata', loadedHandler, false);
|
||||
v.addEventListener('loadstart', startHandler, false);
|
||||
v.addEventListener('volumechange', volumeChangeHandler, false);
|
||||
v.addEventListener('emptied', emptiedHandler, false);
|
||||
document.body.appendChild(v); // Queues implicit load. This should be silently cancelled by the next explicit load.
|
||||
|
||||
var s = document.createElement("source");
|
||||
s.type = "bogus/type";
|
||||
s.src = "error-404.ogv";
|
||||
v.appendChild(s); // Will queue a load. This should be silently cancelled by the next explicit load.
|
||||
|
||||
v.load(); // Explicit load. Will cancel queued loads. Expect loadstart, emptied, error events.
|
||||
v.muted = true; // Will queue a volumechanged event.
|
||||
|
||||
// Load continues in background asynchronously.
|
||||
|
||||
v.addEventListener('error',
|
||||
function (event) {
|
||||
event.stopPropagation();
|
||||
var s2 = document.createElement("source");
|
||||
s2.type = "application/ogg";
|
||||
s2.src = "320x240.ogv";
|
||||
v.appendChild(s2); // Will queue a load. Expect loadstart, loadeddata etc.
|
||||
// Should coalesce with the previous load, so there should be 1 load, and volume changed should arrive first.
|
||||
}, false);
|
||||
|
||||
|
||||
// First two implicit loads will run and silently cancel themselves some time after this function returns. Expect no events.
|
||||
// Then the volumechange event should run.
|
||||
// Then the third implicit load (for s2) should run and succeed. Expect loadstart and loadeddata events.
|
||||
}
|
||||
|
||||
addLoadEvent(testEventOrder);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -14,33 +14,32 @@ SimpleTest.waitForExplicitFinish();
|
|||
function maketest(expect_load, attach_media, name, type, check_metadata) {
|
||||
return function (testNum) {
|
||||
var e = document.createElement('video');
|
||||
|
||||
e.addEventListener('error', function(e) { e.stopPropagation();}, false);
|
||||
|
||||
var errorRun = false;
|
||||
if (expect_load) {
|
||||
// this could be loadedmetadata, but needs bug 466410 fixed
|
||||
e.addEventListener('loadeddata', function () {
|
||||
e.addEventListener('loadedmetadata', function () {
|
||||
ok(e.readyState >= HTMLMediaElement.HAVE_METADATA,
|
||||
'test ' + testNum + ' networkState ' + e.networkState + ' expected >= ' + e.LOADED_METADATA);
|
||||
'test ' + testNum + ' readyState ' + e.readyState + ' expected >= ' + HTMLMediaElement.HAVE_METADATA);
|
||||
is(e.currentSrc.substring(e.currentSrc.length - name.length), name, 'test ' + testNum);
|
||||
ok(e.networkState >= HTMLMediaElement.NETWORK_LOADING,
|
||||
'test ' + testNum + ' networkState = ' + e.networkState + ' expected >= ' + HTMLMediaElement.NETWORK_LOADING);
|
||||
check_metadata(e);
|
||||
e.parentNode.removeChild(e);
|
||||
runNextTest();
|
||||
}, false);
|
||||
}
|
||||
|
||||
attach_media(e, name, type);
|
||||
|
||||
if (expect_load) {
|
||||
ok(e.networkState >= HTMLMediaElement.NETWORK_LOADING,
|
||||
'test ' + testNum + ' networkState ' + e.networkState + ' expected >= ' + e.LOADING);
|
||||
e.addEventListener('error', function(e) { e.stopPropagation();}, false);
|
||||
} else {
|
||||
ok(e.networkState == HTMLMediaElement.NETWORK_EMPTY,
|
||||
'test ' + testNum + ' networkState ' + e.networkState + ' expected ' + e.EMPTY);
|
||||
is(e.currentSrc, '', 'test ' + testNum);
|
||||
e.parentNode.removeChild(e);
|
||||
runNextTest();
|
||||
}
|
||||
e.addEventListener('error', function(event) {
|
||||
event.stopPropagation();
|
||||
is(expect_load, false, "Didn't load when we weren't expecting to.");
|
||||
is(errorRun, false, "error handler should run once only!");
|
||||
errorRun = true;
|
||||
is(e.readyState, HTMLMediaElement.HAVE_NOTHING,
|
||||
'test ' + testNum + ' readyState should be HAVE_NOTHING when load fails.');
|
||||
e.parentNode.removeChild(e);
|
||||
runNextTest();
|
||||
}, false);
|
||||
}
|
||||
attach_media(e, name, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,14 +118,14 @@ var subTests = [
|
|||
maketest(false, add_source, 'unknown.raw', 'bogus/type', null),
|
||||
|
||||
// should start loading, then fire error, needs bug 462455 fixed
|
||||
// maketest(true, add_source, 'unknown.raw', 'application/ogg', null),
|
||||
// maketest(true, add_source, 'unknown.raw', 'audio/x-wav', null),
|
||||
maketest(false, add_source, 'unknown.raw', 'application/ogg', null),
|
||||
maketest(false, add_source, 'unknown.raw', 'audio/x-wav', null),
|
||||
|
||||
// element doesn't notice source children attached later, needs bug 462455 fixed
|
||||
// maketest(true, late_add_sources_last, '320x240.ogv', null, 0.2, 0.4),
|
||||
// maketest(true, late_add_sources_first, '320x240.ogv', 'application/ogg', 0.2, 0.4),
|
||||
// maketest(true, late_add_sources_last, 'r11025_u8_c1.wav', null, 0.2, 0.4),
|
||||
// maketest(true, late_add_sources_first, 'r11025_u8_c1.wav', 'audio/x-wav', 0.2, 0.4),
|
||||
maketest(true, late_add_sources_last, '320x240.ogv', 'application/ogg', check_ogg),
|
||||
maketest(true, late_add_sources_first, '320x240.ogv', 'application/ogg', check_ogg),
|
||||
maketest(true, late_add_sources_last, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
|
||||
maketest(true, late_add_sources_first, 'r11025_u8_c1.wav', 'audio/x-wav', check_wav),
|
||||
|
||||
SimpleTest.finish
|
||||
];
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Media test: append source child</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<video id="v1" onerror="event.stopPropagation();"></video>
|
||||
<audio id="a1" onerror="event.stopPropagation();"></audio>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var v1 = document.getElementById("v1");
|
||||
var a1 = document.getElementById("a1");
|
||||
|
||||
is(v1.src, "", "src should be null");
|
||||
is(a1.src, "", "src should be null");
|
||||
is(v1.currentSrc, "", "currentSrc should be null");
|
||||
is(a1.currentSrc, "", "currentSrc should be null");
|
||||
is(v1.childNodes.length, 0, "should have no children");
|
||||
is(a1.childNodes.length, 0, "should have no children");
|
||||
|
||||
function newSource() {
|
||||
var e = document.createElement("source");
|
||||
e.type = "application/ogg";
|
||||
e.src = "320x240.ogv";
|
||||
return e;
|
||||
}
|
||||
|
||||
var audioLoaded = false;
|
||||
var videoLoaded = false;
|
||||
|
||||
function loaded(media) {
|
||||
ok(media.networkState > 0, "networkState should be > 0");
|
||||
is(media.childNodes.length, 1, "should have 1 child");
|
||||
var sourceFile = media.currentSrc.substring(media.currentSrc.lastIndexOf('/'));
|
||||
is(sourceFile, "/320x240.ogv", "loaded wrong resource");
|
||||
if (media == a1)
|
||||
audioLoaded = true;
|
||||
else if (media == v1)
|
||||
videoLoaded = true;
|
||||
if (audioLoaded && videoLoaded) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
v1.addEventListener('loadeddata', function() { loaded(v1); }, false);
|
||||
a1.addEventListener('loadeddata', function() { loaded(a1); }, false);
|
||||
|
||||
v1.appendChild(newSource());
|
||||
a1.appendChild(newSource());
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=462455
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 462455</title>
|
||||
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462455">Mozilla Bug 462455</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<video id="v">
|
||||
<source src="320x240.ogv" type="application/ogg"></source>
|
||||
<script>
|
||||
var loadStarted = false;
|
||||
document.write('Pause parsing!');
|
||||
var v = document.getElementById('v');
|
||||
if (v.networkState != HTMLMediaElement.NETWORK_EMPTY) {
|
||||
loadStarted = true;
|
||||
}
|
||||
is(loadStarted, false, "We shouldn't start a load until the video tag is closed.");
|
||||
</script>
|
||||
</video>
|
||||
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче