mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 703379. Keep a table of media elements indexed by URI and when loading, try to find an existing element with the same URI and clone its decoder. r=doublec
This commit is contained in:
parent
fc5886fa9f
commit
58e9a065d6
@ -370,21 +370,38 @@ protected:
|
||||
/**
|
||||
* Initialize a decoder as a clone of an existing decoder in another
|
||||
* element.
|
||||
* mLoadingSrc must already be set.
|
||||
*/
|
||||
nsresult InitializeDecoderAsClone(nsMediaDecoder* aOriginal);
|
||||
|
||||
/**
|
||||
* Initialize a decoder to load the given channel. The decoder's stream
|
||||
* listener is returned via aListener.
|
||||
* mLoadingSrc must already be set.
|
||||
*/
|
||||
nsresult InitializeDecoderForChannel(nsIChannel *aChannel,
|
||||
nsIStreamListener **aListener);
|
||||
|
||||
/**
|
||||
* Finish setting up the decoder after Load() has been called on it.
|
||||
* Called by InitializeDecoderForChannel/InitializeDecoderAsClone.
|
||||
*/
|
||||
nsresult FinishDecoderSetup(nsMediaDecoder* aDecoder);
|
||||
|
||||
/**
|
||||
* Call this after setting up mLoadingSrc and mDecoder.
|
||||
*/
|
||||
void AddMediaElementToURITable();
|
||||
/**
|
||||
* Call this before clearing mLoadingSrc.
|
||||
*/
|
||||
void RemoveMediaElementFromURITable();
|
||||
/**
|
||||
* Call this to find a media element with the same NodePrincipal and mLoadingSrc
|
||||
* set to aURI, and with a decoder on which Load() has been called.
|
||||
*/
|
||||
nsHTMLMediaElement* LookupMediaElementURITable(nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Execute the initial steps of the load algorithm that ensure existing
|
||||
* loads are aborted, the element is emptied, and a new load ID is
|
||||
@ -431,7 +448,7 @@ protected:
|
||||
/**
|
||||
* The resource-fetch algorithm step of the load algorithm.
|
||||
*/
|
||||
nsresult LoadResource(nsIURI* aURI);
|
||||
nsresult LoadResource();
|
||||
|
||||
/**
|
||||
* Selects the next <source> child from which to load a resource. Called
|
||||
@ -492,11 +509,11 @@ protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* Suspends the load of resource at aURI, so that it can be resumed later
|
||||
* Suspends the load of mLoadingSrc, so that it can be resumed later
|
||||
* by ResumeLoad(). This is called when we have a media with a 'preload'
|
||||
* attribute value of 'none', during the resource selection algorithm.
|
||||
*/
|
||||
void SuspendLoad(nsIURI* aURI);
|
||||
void SuspendLoad();
|
||||
|
||||
/**
|
||||
* Resumes a previously suspended load (suspended by SuspendLoad(uri)).
|
||||
@ -535,6 +552,7 @@ protected:
|
||||
*/
|
||||
void ProcessMediaFragmentURI();
|
||||
|
||||
// The current decoder. Load() has been called on this decoder.
|
||||
nsRefPtr<nsMediaDecoder> mDecoder;
|
||||
|
||||
// A reference to the ImageContainer which contains the current frame
|
||||
@ -597,11 +615,11 @@ protected:
|
||||
// Current audio sample rate.
|
||||
PRUint32 mRate;
|
||||
|
||||
// URI of the resource we're attempting to load. When the decoder is
|
||||
// successfully initialized, we rely on it to record the URI we're playing,
|
||||
// and clear mLoadingSrc. This stores the value we return in the currentSrc
|
||||
// attribute until the decoder is initialized. Use GetCurrentSrc() to access
|
||||
// the currentSrc attribute.
|
||||
// URI of the resource we're attempting to load. This stores the value we
|
||||
// return in the currentSrc attribute. Use GetCurrentSrc() to access the
|
||||
// currentSrc attribute.
|
||||
// This is always the original URL we're trying to load --- before
|
||||
// redirects etc.
|
||||
nsCOMPtr<nsIURI> mLoadingSrc;
|
||||
|
||||
// Stores the current preload action for this element. Initially set to
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIDOMNotifyAudioAvailableEvent.h"
|
||||
#include "nsMediaFragmentURIParser.h"
|
||||
#include "nsURIHashKey.h"
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
#include "nsOggDecoder.h"
|
||||
@ -479,11 +480,14 @@ void nsHTMLMediaElement::AbortExistingLoads()
|
||||
mCurrentLoadID++;
|
||||
|
||||
bool fireTimeUpdate = false;
|
||||
|
||||
if (mDecoder) {
|
||||
RemoveMediaElementFromURITable();
|
||||
fireTimeUpdate = mDecoder->GetCurrentTime() != 0.0;
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nsnull;
|
||||
}
|
||||
mLoadingSrc = nsnull;
|
||||
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING ||
|
||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE)
|
||||
@ -497,6 +501,7 @@ void nsHTMLMediaElement::AbortExistingLoads()
|
||||
mIsLoadingFromSourceChildren = false;
|
||||
mSuspendedAfterFirstFrame = false;
|
||||
mAllowSuspendAfterFirstFrame = true;
|
||||
mLoadIsSuspended = false;
|
||||
mSourcePointer = nsnull;
|
||||
|
||||
// TODO: The playback rate must be set to the default playback rate.
|
||||
@ -648,12 +653,12 @@ void nsHTMLMediaElement::SelectResource()
|
||||
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
||||
// preload:none media, suspend the load here before we make any
|
||||
// network requests.
|
||||
SuspendLoad(uri);
|
||||
SuspendLoad();
|
||||
mIsRunningSelectResource = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rv = LoadResource(uri);
|
||||
rv = LoadResource();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mIsRunningSelectResource = false;
|
||||
return;
|
||||
@ -750,11 +755,11 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
||||
// preload:none media, suspend the load here before we make any
|
||||
// network requests.
|
||||
SuspendLoad(uri);
|
||||
SuspendLoad();
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(LoadResource(uri))) {
|
||||
if (NS_SUCCEEDED(LoadResource())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -764,7 +769,7 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||
NS_NOTREACHED("Execution should not reach here!");
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
|
||||
void nsHTMLMediaElement::SuspendLoad()
|
||||
{
|
||||
mLoadIsSuspended = true;
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
@ -775,20 +780,19 @@ void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
|
||||
void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction)
|
||||
{
|
||||
NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one");
|
||||
nsCOMPtr<nsIURI> uri = mLoadingSrc;
|
||||
mLoadIsSuspended = false;
|
||||
mPreloadAction = aAction;
|
||||
ChangeDelayLoadStatus(true);
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
if (!mIsLoadingFromSourceChildren) {
|
||||
// We were loading from the element's src attribute.
|
||||
if (NS_FAILED(LoadResource(uri))) {
|
||||
if (NS_FAILED(LoadResource())) {
|
||||
NoSupportedMediaSourceError();
|
||||
}
|
||||
} else {
|
||||
// We were loading from a child <source> element. Try to resume the
|
||||
// load of that child, and if that fails, try the next child.
|
||||
if (NS_FAILED(LoadResource(uri))) {
|
||||
if (NS_FAILED(LoadResource())) {
|
||||
LoadFromSourceChildren();
|
||||
}
|
||||
}
|
||||
@ -873,7 +877,7 @@ void nsHTMLMediaElement::UpdatePreloadAction()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
||||
nsresult nsHTMLMediaElement::LoadResource()
|
||||
{
|
||||
NS_ASSERTION(mDelayingLoadEvent,
|
||||
"Should delay load event (if in document) during load");
|
||||
@ -890,9 +894,17 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
||||
mChannel = nsnull;
|
||||
}
|
||||
|
||||
nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
|
||||
if (other) {
|
||||
// Clone it.
|
||||
nsresult rv = InitializeDecoderAsClone(other->mDecoder);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA,
|
||||
aURI,
|
||||
mLoadingSrc,
|
||||
NodePrincipal(),
|
||||
static_cast<nsGenericElement*>(this),
|
||||
EmptyCString(), // mime type
|
||||
@ -920,7 +932,7 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
aURI,
|
||||
mLoadingSrc,
|
||||
nsnull,
|
||||
loadGroup,
|
||||
nsnull,
|
||||
@ -949,7 +961,7 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
|
||||
} else {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(NodePrincipal(),
|
||||
aURI,
|
||||
mLoadingSrc,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
listener = loadListener;
|
||||
}
|
||||
@ -991,9 +1003,11 @@ nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
|
||||
|
||||
AbortExistingLoads();
|
||||
|
||||
ChangeDelayLoadStatus(true);
|
||||
nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(mLoadingSrc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsresult rv = InitializeDecoderForChannel(aChannel, aListener);
|
||||
ChangeDelayLoadStatus(true);
|
||||
rv = InitializeDecoderForChannel(aChannel, aListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
ChangeDelayLoadStatus(false);
|
||||
return rv;
|
||||
@ -1017,6 +1031,7 @@ NS_IMETHODIMP nsHTMLMediaElement::MozLoadFrom(nsIDOMHTMLMediaElement* aOther)
|
||||
|
||||
ChangeDelayLoadStatus(true);
|
||||
|
||||
mLoadingSrc = other->mLoadingSrc;
|
||||
nsresult rv = InitializeDecoderAsClone(other->mDecoder);
|
||||
if (NS_FAILED(rv)) {
|
||||
ChangeDelayLoadStatus(false);
|
||||
@ -1241,6 +1256,76 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMuted(bool aMuted)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class MediaElementSetForURI : public nsURIHashKey {
|
||||
public:
|
||||
MediaElementSetForURI(const nsIURI* aKey) : nsURIHashKey(aKey) {}
|
||||
MediaElementSetForURI(const MediaElementSetForURI& toCopy)
|
||||
: nsURIHashKey(toCopy), mElements(toCopy.mElements) {}
|
||||
nsTArray<nsHTMLMediaElement*> mElements;
|
||||
};
|
||||
|
||||
typedef nsTHashtable<MediaElementSetForURI> MediaElementURITable;
|
||||
// Elements in this table must have non-null mDecoder and mLoadingSrc, and those
|
||||
// can't change while the element is in the table. The table is keyed by
|
||||
// the element's mLoadingSrc. Each entry has a list of all elements with the
|
||||
// same mLoadingSrc.
|
||||
static MediaElementURITable* gElementTable;
|
||||
|
||||
void
|
||||
nsHTMLMediaElement::AddMediaElementToURITable()
|
||||
{
|
||||
NS_ASSERTION(mDecoder && mDecoder->GetStream(), "Call this only with decoder Load called");
|
||||
if (!gElementTable) {
|
||||
gElementTable = new MediaElementURITable();
|
||||
gElementTable->Init();
|
||||
}
|
||||
MediaElementSetForURI* entry = gElementTable->PutEntry(mLoadingSrc);
|
||||
entry->mElements.AppendElement(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLMediaElement::RemoveMediaElementFromURITable()
|
||||
{
|
||||
NS_ASSERTION(mDecoder, "Don't call this without decoder!");
|
||||
NS_ASSERTION(mLoadingSrc, "Can't have decoder without source!");
|
||||
if (!gElementTable)
|
||||
return;
|
||||
MediaElementSetForURI* entry = gElementTable->GetEntry(mLoadingSrc);
|
||||
if (!entry)
|
||||
return;
|
||||
entry->mElements.RemoveElement(this);
|
||||
if (entry->mElements.IsEmpty()) {
|
||||
gElementTable->RemoveEntry(mLoadingSrc);
|
||||
if (gElementTable->Count() == 0) {
|
||||
delete gElementTable;
|
||||
gElementTable = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsHTMLMediaElement*
|
||||
nsHTMLMediaElement::LookupMediaElementURITable(nsIURI* aURI)
|
||||
{
|
||||
if (!gElementTable)
|
||||
return nsnull;
|
||||
MediaElementSetForURI* entry = gElementTable->GetEntry(aURI);
|
||||
if (!entry)
|
||||
return nsnull;
|
||||
for (PRUint32 i = 0; i < entry->mElements.Length(); ++i) {
|
||||
nsHTMLMediaElement* elem = entry->mElements[i];
|
||||
bool equal;
|
||||
// Look for elements that have the same principal.
|
||||
// XXX when we implement crossorigin for video, we'll also need to check
|
||||
// for the same crossorigin mode here. Ditto for anything else that could
|
||||
// cause us to send different headers.
|
||||
if (NS_SUCCEEDED(elem->NodePrincipal()->Equals(NodePrincipal(), &equal)) && equal) {
|
||||
NS_ASSERTION(elem->mDecoder && elem->mDecoder->GetStream(), "Decoder gone");
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mCurrentLoadID(0),
|
||||
@ -1297,16 +1382,14 @@ nsHTMLMediaElement::~nsHTMLMediaElement()
|
||||
|
||||
UnregisterFreezableElement();
|
||||
if (mDecoder) {
|
||||
RemoveMediaElementFromURITable();
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nsnull;
|
||||
}
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
mChannel = nsnull;
|
||||
}
|
||||
if (mAudioStream) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1347,9 +1430,13 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
nsresult rv = Load();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else if (mLoadIsSuspended) {
|
||||
}
|
||||
if (mLoadIsSuspended) {
|
||||
ResumeLoad(PRELOAD_ENOUGH);
|
||||
} else if (mDecoder) {
|
||||
}
|
||||
// Even if we just did Load() or ResumeLoad(), we could already have a decoder
|
||||
// here if we managed to clone an existing decoder.
|
||||
if (mDecoder) {
|
||||
if (mDecoder->IsEnded()) {
|
||||
SetCurrentTime(0);
|
||||
}
|
||||
@ -1811,6 +1898,8 @@ nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
|
||||
|
||||
nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
{
|
||||
NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
|
||||
|
||||
nsMediaStream* originalStream = aOriginal->GetStream();
|
||||
if (!originalStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1848,6 +1937,8 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
||||
nsIStreamListener **aListener)
|
||||
{
|
||||
NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
|
||||
|
||||
nsCAutoString mimeType;
|
||||
aChannel->GetContentType(mimeType);
|
||||
|
||||
@ -1878,10 +1969,10 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
||||
|
||||
nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
|
||||
{
|
||||
mDecoder = aDecoder;
|
||||
NS_ASSERTION(mLoadingSrc, "mLoadingSrc set up");
|
||||
|
||||
// Decoder has assumed ownership responsibility for remembering the URI.
|
||||
mLoadingSrc = nsnull;
|
||||
mDecoder = aDecoder;
|
||||
AddMediaElementToURITable();
|
||||
|
||||
// Force a same-origin check before allowing events for this media resource.
|
||||
mMediaSecurityVerified = false;
|
||||
@ -2019,9 +2110,11 @@ void nsHTMLMediaElement::NetworkError()
|
||||
void nsHTMLMediaElement::DecodeError()
|
||||
{
|
||||
if (mDecoder) {
|
||||
RemoveMediaElementFromURITable();
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nsnull;
|
||||
}
|
||||
mLoadingSrc = nsnull;
|
||||
if (mIsLoadingFromSourceChildren) {
|
||||
mError = nsnull;
|
||||
if (mSourceLoadCandidate) {
|
||||
@ -2669,13 +2762,10 @@ void nsHTMLMediaElement::FireTimeUpdate(bool aPeriodic)
|
||||
|
||||
void nsHTMLMediaElement::GetCurrentSpec(nsCString& aString)
|
||||
{
|
||||
if (mDecoder) {
|
||||
nsMediaStream* stream = mDecoder->GetStream();
|
||||
if (stream) {
|
||||
stream->URI()->GetSpec(aString);
|
||||
}
|
||||
} else if (mLoadingSrc) {
|
||||
if (mLoadingSrc) {
|
||||
mLoadingSrc->GetSpec(aString);
|
||||
} else {
|
||||
aString.Truncate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,7 @@ _TEST_FILES = \
|
||||
can_play_type_webm.js \
|
||||
cancellable_request.sjs \
|
||||
dynamic_redirect.sjs \
|
||||
dynamic_resource.sjs \
|
||||
file_access_controls.html \
|
||||
fragment_play.js \
|
||||
fragment_noplay.js \
|
||||
@ -120,6 +121,7 @@ _TEST_FILES = \
|
||||
test_info_leak.html \
|
||||
test_load.html \
|
||||
test_load_candidates.html \
|
||||
test_load_same_resource.html \
|
||||
test_load_source.html \
|
||||
test_loop.html \
|
||||
test_media_selection.html \
|
||||
|
34
content/media/test/dynamic_resource.sjs
Normal file
34
content/media/test/dynamic_resource.sjs
Normal file
@ -0,0 +1,34 @@
|
||||
// Return resource1 file content for the first request with a given key.
|
||||
// All subsequent requests return resource2. Both must be video/ogg.
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var key = (request.queryString.match(/^key=([^&]*)&/))[1];
|
||||
var resource1 = (request.queryString.match(/res1=([^&]*)/))[1];
|
||||
var resource2 = (request.queryString.match(/res2=([^&]*)/))[1];
|
||||
|
||||
var resource = getState(key) == "2" ? resource2 : resource1;
|
||||
setState(key, "2");
|
||||
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties).
|
||||
get("CurWorkD", Components.interfaces.nsILocalFile);
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
|
||||
createInstance(Components.interfaces.nsIBinaryInputStream);
|
||||
var paths = "tests/content/media/test/" + resource;
|
||||
var split = paths.split("/");
|
||||
for(var i = 0; i < split.length; ++i) {
|
||||
file.append(split[i]);
|
||||
}
|
||||
fis.init(file, -1, -1, false);
|
||||
dump("file=" + file + "\n");
|
||||
bis.setInputStream(fis);
|
||||
var bytes = bis.readBytes(bis.available());
|
||||
response.setStatusLine(request.httpVersion, 206, "Partial Content");
|
||||
response.setHeader("Content-Range", "bytes 0-" + (bytes.length - 1) + "/" + bytes.length);
|
||||
response.setHeader("Content-Length", ""+bytes.length, false);
|
||||
response.setHeader("Content-Type", "video/ogg", false);
|
||||
response.write(bytes, bytes.length);
|
||||
bis.close();
|
||||
}
|
@ -25,9 +25,13 @@ var gProgressTests = [
|
||||
|
||||
// Used by test_mozLoadFrom. Need one test file per decoder backend, plus
|
||||
// anything for testing clone-specific bugs.
|
||||
var cloneKey = Math.floor(Math.random()*100000000);
|
||||
var gCloneTests = gSmallTests.concat([
|
||||
// Actual duration is ~200ms, we have Content-Duration lie about it.
|
||||
{ name:"bug520908.ogv", type:"video/ogg", duration:9000 },
|
||||
// short-video is more like 1s, so if you load this twice you'll get an unexpected duration
|
||||
{ name:"dynamic_resource.sjs?key=" + cloneKey + "&res1=320x240.ogv&res2=short-video.ogv",
|
||||
type:"video/ogg", duration:0.233 },
|
||||
]);
|
||||
|
||||
// Used by test_play_twice. Need one test file per decoder backend, plus
|
||||
|
70
content/media/test/test_load_same_resource.html
Normal file
70
content/media/test/test_load_same_resource.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test loading of the same resource in multiple elements</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function cloneLoaded(event) {
|
||||
ok(true, "Clone loaded OK");
|
||||
var e = event.target;
|
||||
|
||||
if (e._expectedDuration) {
|
||||
ok(Math.abs(e.duration - e._expectedDuration) < 0.1,
|
||||
"Clone " + e.currentSrc + " duration: " + e.duration + " expected: " + e._expectedDuration);
|
||||
}
|
||||
|
||||
manager.finished(e.token);
|
||||
}
|
||||
|
||||
function tryClone(event) {
|
||||
var e = event.target;
|
||||
var clone = e.cloneNode(false);
|
||||
clone.token = e.token;
|
||||
|
||||
if (e._expectedDuration) {
|
||||
ok(Math.abs(e.duration - e._expectedDuration) < 0.1,
|
||||
e.currentSrc + " duration: " + e.duration + " expected: " + e._expectedDuration);
|
||||
clone._expectedDuration = e._expectedDuration;
|
||||
}
|
||||
|
||||
clone.addEventListener("loadeddata", cloneLoaded, false);
|
||||
}
|
||||
|
||||
// This test checks that loading the same URI twice in different elements at the same time
|
||||
// uses the same resource without doing another network fetch. One of the gCloneTests
|
||||
// uses dynamic_resource.sjs to return one resource on the first fetch and a different resource
|
||||
// on the second fetch. These resources have different lengths, so if the cloned element
|
||||
// does a network fetch it will get a resource with the wrong length and we get a test
|
||||
// failure.
|
||||
|
||||
function initTest(test, token) {
|
||||
var elemType = /^audio/.test(test.type) ? "audio" : "video";
|
||||
var e = document.createElement(elemType);
|
||||
if (e.canPlayType(test.type)) {
|
||||
e.src = test.name;
|
||||
if (test.duration) {
|
||||
e._expectedDuration = test.duration;
|
||||
}
|
||||
ok(true, "Trying to load " + test.name);
|
||||
e.addEventListener("loadeddata", tryClone, false);
|
||||
e.load();
|
||||
e.token = token;
|
||||
manager.started(token);
|
||||
}
|
||||
}
|
||||
|
||||
manager.runTests(gCloneTests, initTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -30,6 +30,7 @@ manager.onFinished = function() {
|
||||
};
|
||||
|
||||
var test = getPlayableVideo(gSeekTests);
|
||||
var baseName = test.name;
|
||||
var gTest = test;
|
||||
var bogusSrc = "bogus.duh";
|
||||
var bogusType = "video/bogus";
|
||||
@ -144,8 +145,9 @@ var tests = [
|
||||
suspend:
|
||||
function(e) {
|
||||
var v = e.target;
|
||||
if (v._gotSuspend)
|
||||
if (v._gotSuspend) {
|
||||
return; // We can receive multiple suspend events, like the one after download completes.
|
||||
}
|
||||
v._gotSuspend = true;
|
||||
is(v._gotLoadStart, true, "(4) Must get loadstart.");
|
||||
is(v._gotLoadedMetaData, false, "(4) Must not get loadedmetadata.");
|
||||
@ -557,14 +559,23 @@ var tests = [
|
||||
}
|
||||
];
|
||||
|
||||
var iterationCount = 0;
|
||||
function startTest(test, token) {
|
||||
if (test == tests[0]) {
|
||||
++iterationCount;
|
||||
}
|
||||
if (iterationCount == 2) {
|
||||
// Do this series of tests on logically different resources
|
||||
test.name = baseName + "?" + Math.floor(Math.random()*100000);
|
||||
}
|
||||
var v = document.createElement("video");
|
||||
v.token = token;
|
||||
test.setup(v);
|
||||
manager.started(token);
|
||||
}
|
||||
|
||||
manager.runTests(tests, startTest);
|
||||
var twiceTests = tests.concat(tests);
|
||||
manager.runTests(twiceTests, startTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
Loading…
Reference in New Issue
Block a user