зеркало из https://github.com/mozilla/pjs.git
Bug 485288 - Update media load algorithm. r=roc a=blocking2.0
This commit is contained in:
Родитель
da9888206a
Коммит
4b32f2905e
|
@ -117,9 +117,6 @@ public:
|
||||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||||
PRBool aNullParent = PR_TRUE);
|
PRBool aNullParent = PR_TRUE);
|
||||||
|
|
||||||
virtual PRBool IsDoneAddingChildren();
|
|
||||||
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to reevaluate whether we should start/stop due to our owner
|
* Call this to reevaluate whether we should start/stop due to our owner
|
||||||
* document being active or inactive.
|
* document being active or inactive.
|
||||||
|
@ -149,6 +146,10 @@ public:
|
||||||
// resource has a decode error during metadata loading or decoding.
|
// resource has a decode error during metadata loading or decoding.
|
||||||
void DecodeError();
|
void DecodeError();
|
||||||
|
|
||||||
|
// Called by the video decoder object, on the main thread, when the
|
||||||
|
// resource load has been cancelled.
|
||||||
|
void LoadAborted();
|
||||||
|
|
||||||
// Called by the video decoder object, on the main thread,
|
// Called by the video decoder object, on the main thread,
|
||||||
// when the video playback has ended.
|
// when the video playback has ended.
|
||||||
void PlaybackEnded();
|
void PlaybackEnded();
|
||||||
|
@ -280,7 +281,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a child source element is added to this media element. This
|
* Called when a child source element is added to this media element. This
|
||||||
* may queue a load() task if appropriate.
|
* may queue a task to run the select resource algorithm if appropriate.
|
||||||
*/
|
*/
|
||||||
void NotifyAddedSource();
|
void NotifyAddedSource();
|
||||||
|
|
||||||
|
@ -333,8 +334,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class MediaLoadListener;
|
class MediaLoadListener;
|
||||||
class LoadNextSourceEvent;
|
|
||||||
class SelectResourceEvent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
|
* Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
|
||||||
|
@ -388,23 +387,25 @@ protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to load resources from the <source> children. This is a
|
* Attempts to load resources from the <source> children. This is a
|
||||||
* substep of the media selection algorith. Do not call this directly,
|
* substep of the resource selection algorithm. Do not call this directly,
|
||||||
* call QueueLoadFromSourceTask() instead.
|
* call QueueLoadFromSourceTask() instead.
|
||||||
*/
|
*/
|
||||||
void LoadFromSourceChildren();
|
void LoadFromSourceChildren();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an async event to call LoadFromSourceChildren().
|
* Asynchronously awaits a stable state, and then causes
|
||||||
|
* LoadFromSourceChildren() to be called on the main threads' event loop.
|
||||||
*/
|
*/
|
||||||
void QueueLoadFromSourceTask();
|
void QueueLoadFromSourceTask();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Media selection algorithm.
|
* Runs the media resource selection algorithm.
|
||||||
*/
|
*/
|
||||||
void SelectResource();
|
void SelectResource();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an async event to call SelectResource().
|
* Asynchronously awaits a stable state, and then causes SelectResource()
|
||||||
|
* to be run on the main thread's event loop.
|
||||||
*/
|
*/
|
||||||
void QueueSelectResourceTask();
|
void QueueSelectResourceTask();
|
||||||
|
|
||||||
|
@ -415,9 +416,10 @@ protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the next <source> child from which to load a resource. Called
|
* Selects the next <source> child from which to load a resource. Called
|
||||||
* during the media selection algorithm.
|
* during the resource selection algorithm. Stores the return value in
|
||||||
|
* mSourceLoadCandidate before returning.
|
||||||
*/
|
*/
|
||||||
already_AddRefed<nsIURI> GetNextSource();
|
nsIContent* GetNextSource();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes mDelayingLoadEvent, and will call BlockOnLoad()/UnblockOnLoad()
|
* Changes mDelayingLoadEvent, and will call BlockOnLoad()/UnblockOnLoad()
|
||||||
|
@ -493,6 +495,17 @@ protected:
|
||||||
*/
|
*/
|
||||||
void UpdatePreloadAction();
|
void UpdatePreloadAction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches an error event to a child source element.
|
||||||
|
*/
|
||||||
|
void DispatchAsyncSourceError(nsIContent* aSourceElement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the media element for an error condition as per aErrorCode.
|
||||||
|
* aErrorCode must be one of nsIDOMHTMLMediaError codes.
|
||||||
|
*/
|
||||||
|
void Error(PRUint16 aErrorCode);
|
||||||
|
|
||||||
nsRefPtr<nsMediaDecoder> mDecoder;
|
nsRefPtr<nsMediaDecoder> mDecoder;
|
||||||
|
|
||||||
// A reference to the ImageContainer which contains the current frame
|
// A reference to the ImageContainer which contains the current frame
|
||||||
|
@ -527,18 +540,19 @@ protected:
|
||||||
nsMediaReadyState mReadyState;
|
nsMediaReadyState mReadyState;
|
||||||
|
|
||||||
enum LoadAlgorithmState {
|
enum LoadAlgorithmState {
|
||||||
// Not waiting for any src/<source>.
|
// No load algorithm instance is waiting for a source to be added to the
|
||||||
|
// media in order to continue loading.
|
||||||
NOT_WAITING,
|
NOT_WAITING,
|
||||||
// No src or <source> children, load is waiting at load algorithm step 1.
|
// We've run the load algorithm, and we tried all source children of the
|
||||||
WAITING_FOR_SRC_OR_SOURCE,
|
// media element, and failed to load any successfully. We're waiting for
|
||||||
// No src at load time, and all <source> children don't resolve or
|
// another source element to be added to the media element, and will try
|
||||||
// give network errors during fetch, waiting for more <source> children
|
// to load any such element when its added.
|
||||||
// to be added.
|
|
||||||
WAITING_FOR_SOURCE
|
WAITING_FOR_SOURCE
|
||||||
};
|
};
|
||||||
|
|
||||||
// When the load algorithm is waiting for more src/<source>, this denotes
|
// Denotes the waiting state of a load algorithm instance. When the load
|
||||||
// what type of waiting we're doing.
|
// algorithm is waiting for a source element child to be added, this is set
|
||||||
|
// to WAITING_FOR_SOURCE, otherwise it's NOT_WAITING.
|
||||||
LoadAlgorithmState mLoadWaitStatus;
|
LoadAlgorithmState mLoadWaitStatus;
|
||||||
|
|
||||||
// Current audio volume
|
// Current audio volume
|
||||||
|
@ -550,11 +564,12 @@ protected:
|
||||||
// Current audio sample rate.
|
// Current audio sample rate.
|
||||||
PRUint32 mRate;
|
PRUint32 mRate;
|
||||||
|
|
||||||
// If we're loading a preload:none media, we'll record the URI we're
|
// URI of the resource we're attempting to load. When the decoder is
|
||||||
// attempting to load in mPreloadURI, and delay loading the resource until
|
// successfully initialized, we rely on it to record the URI we're playing,
|
||||||
// the user initiates a load by either playing the resource, or explicitly
|
// and clear mLoadingSrc. This stores the value we return in the currentSrc
|
||||||
// loading it.
|
// attribute until the decoder is initialized. Use GetCurrentSrc() to access
|
||||||
nsCOMPtr<nsIURI> mPreloadURI;
|
// the currentSrc attribute.
|
||||||
|
nsCOMPtr<nsIURI> mLoadingSrc;
|
||||||
|
|
||||||
// Stores the current preload action for this element. Initially set to
|
// Stores the current preload action for this element. Initially set to
|
||||||
// PRELOAD_UNDEFINED, its value is changed by calling
|
// PRELOAD_UNDEFINED, its value is changed by calling
|
||||||
|
@ -562,11 +577,15 @@ protected:
|
||||||
PreloadAction mPreloadAction;
|
PreloadAction mPreloadAction;
|
||||||
|
|
||||||
// Size of the media. Updated by the decoder on the main thread if
|
// Size of the media. Updated by the decoder on the main thread if
|
||||||
// it changes. Defaults to a width and height of -1 if not set.
|
// it changes. Defaults to a width and height of -1 inot set.
|
||||||
nsIntSize mMediaSize;
|
nsIntSize mMediaSize;
|
||||||
|
|
||||||
nsRefPtr<gfxASurface> mPrintSurface;
|
nsRefPtr<gfxASurface> mPrintSurface;
|
||||||
|
|
||||||
|
// Reference to the source element last returned by GetNextSource().
|
||||||
|
// This is the child source element which we're trying to load from.
|
||||||
|
nsCOMPtr<nsIContent> mSourceLoadCandidate;
|
||||||
|
|
||||||
// An audio stream for writing audio directly from JS.
|
// An audio stream for writing audio directly from JS.
|
||||||
nsAutoPtr<nsAudioStream> mAudioStream;
|
nsAutoPtr<nsAudioStream> mAudioStream;
|
||||||
|
|
||||||
|
@ -604,10 +623,6 @@ protected:
|
||||||
// True if the sound is muted
|
// True if the sound is muted
|
||||||
PRPackedBool mMuted;
|
PRPackedBool mMuted;
|
||||||
|
|
||||||
// Flag to indicate if the child elements (eg. <source/>) have been
|
|
||||||
// parsed.
|
|
||||||
PRPackedBool mIsDoneAddingChildren;
|
|
||||||
|
|
||||||
// If TRUE then the media element was actively playing before the currently
|
// If TRUE then the media element was actively playing before the currently
|
||||||
// in progress seeking. If FALSE then the media element is either not seeking
|
// in progress seeking. If FALSE then the media element is either not seeking
|
||||||
// or was not actively playing before the current seek. Used to decide whether
|
// or was not actively playing before the current seek. Used to decide whether
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "nsXPCOMStrings.h"
|
#include "nsXPCOMStrings.h"
|
||||||
#include "prlock.h"
|
#include "prlock.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsIThreadInternal.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsFrameManager.h"
|
#include "nsFrameManager.h"
|
||||||
|
|
||||||
|
@ -88,6 +89,8 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include "nsIDocShellTreeItem.h"
|
#include "nsIDocShellTreeItem.h"
|
||||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||||
|
#include "nsIAppShell.h"
|
||||||
|
#include "nsWidgetsCID.h"
|
||||||
|
|
||||||
#include "nsIPrivateDOMEvent.h"
|
#include "nsIPrivateDOMEvent.h"
|
||||||
#include "nsIDOMNotifyAudioAvailableEvent.h"
|
#include "nsIDOMNotifyAudioAvailableEvent.h"
|
||||||
|
@ -209,50 +212,31 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsHTMLMediaElement::LoadNextSourceEvent : public nsMediaEvent {
|
class nsSourceErrorEventRunner : public nsMediaEvent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsIContent> mSource;
|
||||||
public:
|
public:
|
||||||
LoadNextSourceEvent(nsHTMLMediaElement *aElement)
|
nsSourceErrorEventRunner(nsHTMLMediaElement* aElement,
|
||||||
: nsMediaEvent(aElement) {}
|
nsIContent* aSource)
|
||||||
|
: nsMediaEvent(aElement),
|
||||||
|
mSource(aSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHOD Run() {
|
NS_IMETHOD Run() {
|
||||||
if (!IsCancelled())
|
// Silently cancel if our load has been cancelled.
|
||||||
mElement->LoadFromSourceChildren();
|
if (IsCancelled())
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event source error", mElement.get()));
|
||||||
|
return nsContentUtils::DispatchTrustedEvent(mElement->GetOwnerDoc(),
|
||||||
|
mSource,
|
||||||
|
NS_LITERAL_STRING("error"),
|
||||||
|
PR_TRUE,
|
||||||
|
PR_TRUE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsHTMLMediaElement::SelectResourceEvent : public nsMediaEvent {
|
|
||||||
public:
|
|
||||||
SelectResourceEvent(nsHTMLMediaElement *aElement)
|
|
||||||
: nsMediaEvent(aElement) {}
|
|
||||||
NS_IMETHOD Run() {
|
|
||||||
if (!IsCancelled()) {
|
|
||||||
NS_ASSERTION(mElement->mIsRunningSelectResource,
|
|
||||||
"Should have flagged that we're running SelectResource()");
|
|
||||||
mElement->SelectResource();
|
|
||||||
mElement->mIsRunningSelectResource = PR_FALSE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void nsHTMLMediaElement::QueueSelectResourceTask()
|
|
||||||
{
|
|
||||||
// Don't allow multiple async select resource calls to be queued.
|
|
||||||
if (mIsRunningSelectResource)
|
|
||||||
return;
|
|
||||||
mIsRunningSelectResource = PR_TRUE;
|
|
||||||
ChangeDelayLoadStatus(PR_TRUE);
|
|
||||||
nsCOMPtr<nsIRunnable> event = new SelectResourceEvent(this);
|
|
||||||
NS_DispatchToMainThread(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsHTMLMediaElement::QueueLoadFromSourceTask()
|
|
||||||
{
|
|
||||||
ChangeDelayLoadStatus(PR_TRUE);
|
|
||||||
nsCOMPtr<nsIRunnable> event = new LoadNextSourceEvent(this);
|
|
||||||
NS_DispatchToMainThread(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There is a reference cycle involving this class: MediaLoadListener
|
* There is a reference cycle involving this class: MediaLoadListener
|
||||||
* holds a reference to the nsHTMLMediaElement, which holds a reference
|
* holds a reference to the nsHTMLMediaElement, which holds a reference
|
||||||
|
@ -441,6 +425,8 @@ NS_IMETHODIMP nsHTMLMediaElement::GetCurrentSrc(nsAString & aCurrentSrc)
|
||||||
if (stream) {
|
if (stream) {
|
||||||
stream->URI()->GetSpec(src);
|
stream->URI()->GetSpec(src);
|
||||||
}
|
}
|
||||||
|
} else if (mLoadingSrc) {
|
||||||
|
mLoadingSrc->GetSpec(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
aCurrentSrc = NS_ConvertUTF8toUTF16(src);
|
aCurrentSrc = NS_ConvertUTF8toUTF16(src);
|
||||||
|
@ -504,7 +490,6 @@ void nsHTMLMediaElement::AbortExistingLoads()
|
||||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING ||
|
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING ||
|
||||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE)
|
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE)
|
||||||
{
|
{
|
||||||
mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_ABORTED);
|
|
||||||
DispatchProgressEvent(NS_LITERAL_STRING("abort"));
|
DispatchProgressEvent(NS_LITERAL_STRING("abort"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +536,62 @@ void nsHTMLMediaElement::NoSupportedMediaSourceError()
|
||||||
ChangeDelayLoadStatus(PR_FALSE);
|
ChangeDelayLoadStatus(PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (nsHTMLMediaElement::*SyncSectionFn)();
|
||||||
|
|
||||||
|
// Runs a "synchronous section", a function that must run once the event loop
|
||||||
|
// has reached a "stable state". See:
|
||||||
|
// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
|
||||||
|
class nsSyncSection : public nsMediaEvent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SyncSectionFn mClosure;
|
||||||
|
public:
|
||||||
|
nsSyncSection(nsHTMLMediaElement* aElement,
|
||||||
|
SyncSectionFn aClosure) :
|
||||||
|
nsMediaEvent(aElement),
|
||||||
|
mClosure(aClosure)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
// Silently cancel if our load has been cancelled.
|
||||||
|
if (IsCancelled())
|
||||||
|
return NS_OK;
|
||||||
|
(mElement.get()->*mClosure)();
|
||||||
|
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(nsHTMLMediaElement* aElement,
|
||||||
|
SyncSectionFn aClosure)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIRunnable> event = new nsSyncSection(aElement, aClosure);
|
||||||
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
||||||
|
appShell->RunInStableState(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHTMLMediaElement::QueueLoadFromSourceTask()
|
||||||
|
{
|
||||||
|
ChangeDelayLoadStatus(PR_TRUE);
|
||||||
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||||
|
AsyncAwaitStableState(this, &nsHTMLMediaElement::LoadFromSourceChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHTMLMediaElement::QueueSelectResourceTask()
|
||||||
|
{
|
||||||
|
// Don't allow multiple async select resource calls to be queued.
|
||||||
|
if (mIsRunningSelectResource)
|
||||||
|
return;
|
||||||
|
mIsRunningSelectResource = PR_TRUE;
|
||||||
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
|
||||||
|
AsyncAwaitStableState(this, &nsHTMLMediaElement::SelectResource);
|
||||||
|
}
|
||||||
|
|
||||||
/* void load (); */
|
/* void load (); */
|
||||||
NS_IMETHODIMP nsHTMLMediaElement::Load()
|
NS_IMETHODIMP nsHTMLMediaElement::Load()
|
||||||
{
|
{
|
||||||
|
@ -591,18 +632,20 @@ static PRBool HasPotentialResource(nsIContent *aElement)
|
||||||
|
|
||||||
void nsHTMLMediaElement::SelectResource()
|
void nsHTMLMediaElement::SelectResource()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mDelayingLoadEvent, "Load event not delayed during resource selection?");
|
NS_ASSERTION(!mDelayingLoadEvent,
|
||||||
|
"Load event should not be delayed at start of resource selection.");
|
||||||
if (!HasPotentialResource(this)) {
|
if (!HasPotentialResource(this)) {
|
||||||
// While the media element has neither a src attribute nor any source
|
// The media element has neither a src attribute nor any source
|
||||||
// element children, wait. (This steps might wait forever.)
|
// element children, abort the load.
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
||||||
mLoadWaitStatus = WAITING_FOR_SRC_OR_SOURCE;
|
|
||||||
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
|
// This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called
|
||||||
ChangeDelayLoadStatus(PR_FALSE);
|
ChangeDelayLoadStatus(PR_FALSE);
|
||||||
|
mIsRunningSelectResource = PR_FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChangeDelayLoadStatus(PR_TRUE);
|
||||||
|
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||||
// Load event was delayed, and still is, so no need to call
|
// Load event was delayed, and still is, so no need to call
|
||||||
// AddRemoveSelfReference, since it must still be held
|
// AddRemoveSelfReference, since it must still be held
|
||||||
|
@ -617,29 +660,37 @@ void nsHTMLMediaElement::SelectResource()
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
|
LOG(PR_LOG_DEBUG, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
|
||||||
mIsLoadingFromSrcAttribute = PR_TRUE;
|
mIsLoadingFromSrcAttribute = PR_TRUE;
|
||||||
|
mLoadingSrc = uri;
|
||||||
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
||||||
// preload:none media, suspend the load here before we make any
|
// preload:none media, suspend the load here before we make any
|
||||||
// network requests.
|
// network requests.
|
||||||
SuspendLoad(uri);
|
SuspendLoad(uri);
|
||||||
|
mIsRunningSelectResource = PR_FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = LoadResource(uri);
|
rv = LoadResource(uri);
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mIsRunningSelectResource = PR_FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
NoSupportedMediaSourceError();
|
NoSupportedMediaSourceError();
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, the source elements will be used.
|
// Otherwise, the source elements will be used.
|
||||||
LoadFromSourceChildren();
|
LoadFromSourceChildren();
|
||||||
}
|
}
|
||||||
|
mIsRunningSelectResource = PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHTMLMediaElement::NotifyLoadError()
|
void nsHTMLMediaElement::NotifyLoadError()
|
||||||
{
|
{
|
||||||
if (mIsLoadingFromSrcAttribute) {
|
if (mIsLoadingFromSrcAttribute) {
|
||||||
|
LOG(PR_LOG_DEBUG, ("NotifyLoadError(), no supported media error"));
|
||||||
NoSupportedMediaSourceError();
|
NoSupportedMediaSourceError();
|
||||||
} else {
|
} else {
|
||||||
|
NS_ASSERTION(mSourceLoadCandidate, "Must know the source we were loading from!");
|
||||||
|
DispatchAsyncSourceError(mSourceLoadCandidate);
|
||||||
QueueLoadFromSourceTask();
|
QueueLoadFromSourceTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,18 +733,47 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mDelayingLoadEvent,
|
NS_ASSERTION(mDelayingLoadEvent,
|
||||||
"Should delay load event (if in document) during load");
|
"Should delay load event (if in document) during load");
|
||||||
|
NS_ASSERTION(!mIsLoadingFromSrcAttribute,
|
||||||
|
"Must remember we're loading from source children");
|
||||||
while (PR_TRUE) {
|
while (PR_TRUE) {
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIURI> uri = GetNextSource();
|
nsIContent* child = GetNextSource();
|
||||||
if (!uri) {
|
if (!child) {
|
||||||
// Exhausted candidates, wait for more candidates to be appended to
|
// Exhausted candidates, wait for more candidates to be appended to
|
||||||
// the media element.
|
// the media element.
|
||||||
mLoadWaitStatus = WAITING_FOR_SOURCE;
|
mLoadWaitStatus = WAITING_FOR_SOURCE;
|
||||||
NoSupportedMediaSourceError();
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
|
||||||
|
ChangeDelayLoadStatus(PR_FALSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
nsAutoString src,type;
|
||||||
|
|
||||||
|
// Must have src attribute.
|
||||||
|
if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
|
||||||
|
DispatchAsyncSourceError(child);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a type attribute, it must be a supported type.
|
||||||
|
if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
|
||||||
|
GetCanPlay(type) == CANPLAY_NO)
|
||||||
|
{
|
||||||
|
DispatchAsyncSourceError(child);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
|
||||||
|
NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
|
||||||
|
NewURIFromString(src, getter_AddRefs(uri));
|
||||||
|
if (!uri) {
|
||||||
|
DispatchAsyncSourceError(child);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLoadingSrc = uri;
|
||||||
|
NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
|
||||||
|
"Network state should be loading");
|
||||||
|
|
||||||
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
|
||||||
// preload:none media, suspend the load here before we make any
|
// preload:none media, suspend the load here before we make any
|
||||||
|
@ -707,6 +787,7 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If we fail to load, loop back and try loading the next resource.
|
// If we fail to load, loop back and try loading the next resource.
|
||||||
|
DispatchAsyncSourceError(child);
|
||||||
}
|
}
|
||||||
NS_NOTREACHED("Execution should not reach here!");
|
NS_NOTREACHED("Execution should not reach here!");
|
||||||
}
|
}
|
||||||
|
@ -714,7 +795,6 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||||
void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
|
void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
|
||||||
{
|
{
|
||||||
mLoadIsSuspended = PR_TRUE;
|
mLoadIsSuspended = PR_TRUE;
|
||||||
mPreloadURI = aURI;
|
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend"));
|
DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend"));
|
||||||
ChangeDelayLoadStatus(PR_FALSE);
|
ChangeDelayLoadStatus(PR_FALSE);
|
||||||
|
@ -723,9 +803,8 @@ void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI)
|
||||||
void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction)
|
void nsHTMLMediaElement::ResumeLoad(PreloadAction aAction)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one");
|
NS_ASSERTION(mLoadIsSuspended, "Can only resume preload if halted for one");
|
||||||
nsCOMPtr<nsIURI> uri = mPreloadURI;
|
nsCOMPtr<nsIURI> uri = mLoadingSrc;
|
||||||
mLoadIsSuspended = PR_FALSE;
|
mLoadIsSuspended = PR_FALSE;
|
||||||
mPreloadURI = nsnull;
|
|
||||||
mPreloadAction = aAction;
|
mPreloadAction = aAction;
|
||||||
ChangeDelayLoadStatus(PR_TRUE);
|
ChangeDelayLoadStatus(PR_TRUE);
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||||
|
@ -1063,6 +1142,7 @@ NS_IMETHODIMP nsHTMLMediaElement::GetPaused(PRBool *aPaused)
|
||||||
NS_IMETHODIMP nsHTMLMediaElement::Pause()
|
NS_IMETHODIMP nsHTMLMediaElement::Pause()
|
||||||
{
|
{
|
||||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||||
|
LOG(PR_LOG_DEBUG, ("Loading due to Pause()"));
|
||||||
nsresult rv = Load();
|
nsresult rv = Load();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
} else if (mDecoder) {
|
} else if (mDecoder) {
|
||||||
|
@ -1200,7 +1280,6 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||||
mAutoplayEnabled(PR_TRUE),
|
mAutoplayEnabled(PR_TRUE),
|
||||||
mPaused(PR_TRUE),
|
mPaused(PR_TRUE),
|
||||||
mMuted(PR_FALSE),
|
mMuted(PR_FALSE),
|
||||||
mIsDoneAddingChildren(!aFromParser),
|
|
||||||
mPlayingBeforeSeek(PR_FALSE),
|
mPlayingBeforeSeek(PR_FALSE),
|
||||||
mPausedForInactiveDocument(PR_FALSE),
|
mPausedForInactiveDocument(PR_FALSE),
|
||||||
mWaitingFired(PR_FALSE),
|
mWaitingFired(PR_FALSE),
|
||||||
|
@ -1369,16 +1448,11 @@ nsresult nsHTMLMediaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
aNotify);
|
aNotify);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
|
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
|
||||||
if (aName == nsGkAtoms::src) {
|
Load();
|
||||||
if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) {
|
|
||||||
// A previous load algorithm instance is waiting on a src
|
|
||||||
// addition, resume the load. It is waiting at "step 1 of the load
|
|
||||||
// algorithm".
|
|
||||||
mLoadWaitStatus = NOT_WAITING;
|
|
||||||
QueueSelectResourceTask();
|
|
||||||
}
|
}
|
||||||
} else if (aName == nsGkAtoms::autoplay) {
|
if (aNotify && aNameSpaceID == kNameSpaceID_None) {
|
||||||
|
if (aName == nsGkAtoms::autoplay) {
|
||||||
StopSuspendingAfterFirstFrame();
|
StopSuspendingAfterFirstFrame();
|
||||||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) {
|
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) {
|
||||||
NotifyAutoplayDataReady();
|
NotifyAutoplayDataReady();
|
||||||
|
@ -1429,15 +1503,6 @@ nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aPar
|
||||||
aParent,
|
aParent,
|
||||||
aBindingParent,
|
aBindingParent,
|
||||||
aCompileEventHandlers);
|
aCompileEventHandlers);
|
||||||
if (aDocument) {
|
|
||||||
if (NS_SUCCEEDED(rv) &&
|
|
||||||
mIsDoneAddingChildren &&
|
|
||||||
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY)
|
|
||||||
{
|
|
||||||
QueueSelectResourceTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsBindingToTree = PR_FALSE;
|
mIsBindingToTree = PR_FALSE;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1813,6 +1878,9 @@ nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
|
||||||
{
|
{
|
||||||
mDecoder = aDecoder;
|
mDecoder = aDecoder;
|
||||||
|
|
||||||
|
// Decoder has assumed ownership responsibility for remembering the URI.
|
||||||
|
mLoadingSrc = nsnull;
|
||||||
|
|
||||||
// Force a same-origin check before allowing events for this media resource.
|
// Force a same-origin check before allowing events for this media resource.
|
||||||
mMediaSecurityVerified = PR_FALSE;
|
mMediaSecurityVerified = PR_FALSE;
|
||||||
|
|
||||||
|
@ -1902,29 +1970,43 @@ void nsHTMLMediaElement::ResourceLoaded()
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||||
AddRemoveSelfReference();
|
AddRemoveSelfReference();
|
||||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||||
// The download has stopped
|
// Ensure a progress event is dispatched at the end of download.
|
||||||
|
DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress"));
|
||||||
|
// The download has stopped.
|
||||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend"));
|
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHTMLMediaElement::NetworkError()
|
void nsHTMLMediaElement::NetworkError()
|
||||||
{
|
{
|
||||||
mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_NETWORK);
|
Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
|
||||||
mBegun = PR_FALSE;
|
|
||||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
|
||||||
AddRemoveSelfReference();
|
|
||||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
|
||||||
ChangeDelayLoadStatus(PR_FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHTMLMediaElement::DecodeError()
|
void nsHTMLMediaElement::DecodeError()
|
||||||
{
|
{
|
||||||
mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_DECODE);
|
Error(nsIDOMMediaError::MEDIA_ERR_DECODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHTMLMediaElement::LoadAborted()
|
||||||
|
{
|
||||||
|
Error(nsIDOMMediaError::MEDIA_ERR_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHTMLMediaElement::Error(PRUint16 aErrorCode)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aErrorCode == nsIDOMMediaError::MEDIA_ERR_DECODE ||
|
||||||
|
aErrorCode == nsIDOMMediaError::MEDIA_ERR_NETWORK ||
|
||||||
|
aErrorCode == nsIDOMMediaError::MEDIA_ERR_ABORTED,
|
||||||
|
"Only use nsIDOMMediaError codes!");
|
||||||
|
mError = new nsMediaError(aErrorCode);
|
||||||
mBegun = PR_FALSE;
|
mBegun = PR_FALSE;
|
||||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
DispatchAsyncProgressEvent(NS_LITERAL_STRING("error"));
|
||||||
|
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY;
|
||||||
AddRemoveSelfReference();
|
|
||||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied"));
|
||||||
|
} else {
|
||||||
|
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||||
|
}
|
||||||
|
AddRemoveSelfReference();
|
||||||
ChangeDelayLoadStatus(PR_FALSE);
|
ChangeDelayLoadStatus(PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2211,25 +2293,6 @@ nsresult nsHTMLMediaElement::DispatchProgressEvent(const nsAString& aName)
|
||||||
return target->DispatchEvent(event, &dummy);
|
return target->DispatchEvent(event, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsHTMLMediaElement::DoneAddingChildren(PRBool aHaveNotified)
|
|
||||||
{
|
|
||||||
if (!mIsDoneAddingChildren) {
|
|
||||||
mIsDoneAddingChildren = PR_TRUE;
|
|
||||||
|
|
||||||
UpdatePreloadAction();
|
|
||||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
|
||||||
QueueSelectResourceTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool nsHTMLMediaElement::IsDoneAddingChildren()
|
|
||||||
{
|
|
||||||
return mIsDoneAddingChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const
|
PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -2349,21 +2412,41 @@ nsHTMLMediaElement::IsNodeOfType(PRUint32 aFlags) const
|
||||||
return !(aFlags & ~(eCONTENT | eMEDIA));
|
return !(aFlags & ~(eCONTENT | eMEDIA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsHTMLMediaElement::DispatchAsyncSourceError(nsIContent* aSourceElement)
|
||||||
|
{
|
||||||
|
LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing simple source error event", this));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRunnable> event = new nsSourceErrorEventRunner(this, aSourceElement);
|
||||||
|
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
void nsHTMLMediaElement::NotifyAddedSource()
|
void nsHTMLMediaElement::NotifyAddedSource()
|
||||||
{
|
{
|
||||||
if (mLoadWaitStatus == WAITING_FOR_SRC_OR_SOURCE) {
|
// If a source element is inserted as a child of a media element
|
||||||
|
// that has no src attribute and whose networkState has the value
|
||||||
|
// NETWORK_EMPTY, the user agent must invoke the media element's
|
||||||
|
// resource selection algorithm.
|
||||||
|
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
|
||||||
|
mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY)
|
||||||
|
{
|
||||||
QueueSelectResourceTask();
|
QueueSelectResourceTask();
|
||||||
} else if (mLoadWaitStatus == WAITING_FOR_SOURCE) {
|
}
|
||||||
|
|
||||||
|
// A load was paused in the resource selection algorithm, waiting for
|
||||||
|
// a new source child to be added, resume the resource selction algorithm.
|
||||||
|
if (mLoadWaitStatus == WAITING_FOR_SOURCE) {
|
||||||
QueueLoadFromSourceTask();
|
QueueLoadFromSourceTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIURI> nsHTMLMediaElement::GetNextSource()
|
nsIContent* nsHTMLMediaElement::GetNextSource()
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
nsCOMPtr<nsIDOMNode> thisDomNode =
|
nsCOMPtr<nsIDOMNode> thisDomNode =
|
||||||
do_QueryInterface(static_cast<nsGenericElement*>(this));
|
do_QueryInterface(static_cast<nsGenericElement*>(this));
|
||||||
|
|
||||||
|
mSourceLoadCandidate = nsnull;
|
||||||
|
|
||||||
if (!mSourcePointer) {
|
if (!mSourcePointer) {
|
||||||
// First time this has been run, create a selection to cover children.
|
// First time this has been run, create a selection to cover children.
|
||||||
mSourcePointer = do_CreateInstance("@mozilla.org/content/range;1");
|
mSourcePointer = do_CreateInstance("@mozilla.org/content/range;1");
|
||||||
|
@ -2397,27 +2480,13 @@ already_AddRefed<nsIURI> nsHTMLMediaElement::GetNextSource()
|
||||||
|
|
||||||
nsIContent* child = GetChildAt(startOffset);
|
nsIContent* child = GetChildAt(startOffset);
|
||||||
|
|
||||||
// If child is a <source> element, it may be the next candidate.
|
// If child is a <source> element, it is the next candidate.
|
||||||
if (child &&
|
if (child &&
|
||||||
child->Tag() == nsGkAtoms::source &&
|
child->Tag() == nsGkAtoms::source &&
|
||||||
child->IsHTML())
|
child->IsHTML())
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> uri;
|
mSourceLoadCandidate = child;
|
||||||
nsAutoString src,type;
|
return child;
|
||||||
|
|
||||||
// Must have src attribute.
|
|
||||||
if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If we have a type attribute, it must be a supported type.
|
|
||||||
if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
|
|
||||||
GetCanPlay(type) == CANPLAY_NO)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
|
|
||||||
NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
|
|
||||||
NewURIFromString(src, getter_AddRefs(uri));
|
|
||||||
return uri.forget();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_NOTREACHED("Execution should not reach here!");
|
NS_NOTREACHED("Execution should not reach here!");
|
||||||
|
|
|
@ -411,7 +411,6 @@ void nsBuiltinDecoder::ResourceLoaded()
|
||||||
|
|
||||||
// Ensure the final progress event gets fired
|
// Ensure the final progress event gets fired
|
||||||
if (mElement) {
|
if (mElement) {
|
||||||
mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress"));
|
|
||||||
mElement->ResourceLoaded();
|
mElement->ResourceLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,8 +565,11 @@ void nsBuiltinDecoder::NotifyDownloadEnded(nsresult aStatus)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
|
|
||||||
if (aStatus == NS_BINDING_ABORTED)
|
if (aStatus == NS_BINDING_ABORTED) {
|
||||||
|
// Download has been cancelled by user.
|
||||||
|
mElement->LoadAborted();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
MonitorAutoEnter mon(mMonitor);
|
MonitorAutoEnter mon(mMonitor);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
is(HTMLElement.NETWORK_EMPTY, undefined);
|
is(HTMLElement.NETWORK_EMPTY, undefined);
|
||||||
is(HTMLElement.NETWORK_IDLE, undefined);
|
is(HTMLElement.NETWORK_IDLE, undefined);
|
||||||
is(HTMLElement.NETWORK_LOADING, undefined);
|
is(HTMLElement.NETWORK_LOADING, undefined);
|
||||||
is(HTMLElement.NETWORK_LOADED, undefined);
|
|
||||||
is(HTMLElement.NETWORK_NO_SOURCE, undefined);
|
is(HTMLElement.NETWORK_NO_SOURCE, undefined);
|
||||||
is(HTMLElement.HAVE_NOTHING, undefined);
|
is(HTMLElement.HAVE_NOTHING, undefined);
|
||||||
is(HTMLElement.HAVE_METADATA, undefined);
|
is(HTMLElement.HAVE_METADATA, undefined);
|
||||||
|
@ -31,8 +30,7 @@ is(HTMLElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(HTMLMediaElement.NETWORK_EMPTY, 0);
|
is(HTMLMediaElement.NETWORK_EMPTY, 0);
|
||||||
is(HTMLMediaElement.NETWORK_IDLE, 1);
|
is(HTMLMediaElement.NETWORK_IDLE, 1);
|
||||||
is(HTMLMediaElement.NETWORK_LOADING, 2);
|
is(HTMLMediaElement.NETWORK_LOADING, 2);
|
||||||
todo_is(HTMLMediaElement.NETWORK_LOADED, undefined);
|
is(HTMLMediaElement.NETWORK_NO_SOURCE, 3);
|
||||||
is(HTMLMediaElement.NETWORK_NO_SOURCE, 4);
|
|
||||||
is(HTMLMediaElement.HAVE_NOTHING, 0);
|
is(HTMLMediaElement.HAVE_NOTHING, 0);
|
||||||
is(HTMLMediaElement.HAVE_METADATA, 1);
|
is(HTMLMediaElement.HAVE_METADATA, 1);
|
||||||
is(HTMLMediaElement.HAVE_CURRENT_DATA, 2);
|
is(HTMLMediaElement.HAVE_CURRENT_DATA, 2);
|
||||||
|
@ -58,7 +56,6 @@ is(HTMLVideoElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(HTMLAudioElement.NETWORK_EMPTY, undefined);
|
is(HTMLAudioElement.NETWORK_EMPTY, undefined);
|
||||||
is(HTMLAudioElement.NETWORK_IDLE, undefined);
|
is(HTMLAudioElement.NETWORK_IDLE, undefined);
|
||||||
is(HTMLAudioElement.NETWORK_LOADING, undefined);
|
is(HTMLAudioElement.NETWORK_LOADING, undefined);
|
||||||
is(HTMLAudioElement.NETWORK_LOADED, undefined);
|
|
||||||
is(HTMLAudioElement.NETWORK_NO_SOURCE, undefined);
|
is(HTMLAudioElement.NETWORK_NO_SOURCE, undefined);
|
||||||
is(HTMLAudioElement.HAVE_NOTHING, undefined);
|
is(HTMLAudioElement.HAVE_NOTHING, undefined);
|
||||||
is(HTMLAudioElement.HAVE_METADATA, undefined);
|
is(HTMLAudioElement.HAVE_METADATA, undefined);
|
||||||
|
@ -72,7 +69,6 @@ is(HTMLAudioElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(HTMLSourceElement.NETWORK_EMPTY, undefined);
|
is(HTMLSourceElement.NETWORK_EMPTY, undefined);
|
||||||
is(HTMLSourceElement.NETWORK_IDLE, undefined);
|
is(HTMLSourceElement.NETWORK_IDLE, undefined);
|
||||||
is(HTMLSourceElement.NETWORK_LOADING, undefined);
|
is(HTMLSourceElement.NETWORK_LOADING, undefined);
|
||||||
is(HTMLSourceElement.NETWORK_LOADED, undefined);
|
|
||||||
is(HTMLSourceElement.NETWORK_NO_SOURCE, undefined);
|
is(HTMLSourceElement.NETWORK_NO_SOURCE, undefined);
|
||||||
is(HTMLSourceElement.HAVE_NOTHING, undefined);
|
is(HTMLSourceElement.HAVE_NOTHING, undefined);
|
||||||
is(HTMLSourceElement.HAVE_METADATA, undefined);
|
is(HTMLSourceElement.HAVE_METADATA, undefined);
|
||||||
|
@ -86,7 +82,6 @@ is(HTMLSourceElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(MediaError.NETWORK_EMPTY, undefined);
|
is(MediaError.NETWORK_EMPTY, undefined);
|
||||||
is(MediaError.NETWORK_IDLE, undefined);
|
is(MediaError.NETWORK_IDLE, undefined);
|
||||||
is(MediaError.NETWORK_LOADING, undefined);
|
is(MediaError.NETWORK_LOADING, undefined);
|
||||||
is(MediaError.NETWORK_LOADED, undefined);
|
|
||||||
is(MediaError.NETWORK_NO_SOURCE, undefined);
|
is(MediaError.NETWORK_NO_SOURCE, undefined);
|
||||||
is(MediaError.HAVE_NOTHING, undefined);
|
is(MediaError.HAVE_NOTHING, undefined);
|
||||||
is(MediaError.HAVE_METADATA, undefined);
|
is(MediaError.HAVE_METADATA, undefined);
|
||||||
|
@ -100,7 +95,6 @@ is(MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, 4);
|
||||||
is(document.body.NETWORK_EMPTY, undefined);
|
is(document.body.NETWORK_EMPTY, undefined);
|
||||||
is(document.body.NETWORK_IDLE, undefined);
|
is(document.body.NETWORK_IDLE, undefined);
|
||||||
is(document.body.NETWORK_LOADING, undefined);
|
is(document.body.NETWORK_LOADING, undefined);
|
||||||
is(document.body.NETWORK_LOADED, undefined);
|
|
||||||
is(document.body.NETWORK_NO_SOURCE, undefined);
|
is(document.body.NETWORK_NO_SOURCE, undefined);
|
||||||
is(document.body.HAVE_NOTHING, undefined);
|
is(document.body.HAVE_NOTHING, undefined);
|
||||||
is(document.body.HAVE_METADATA, undefined);
|
is(document.body.HAVE_METADATA, undefined);
|
||||||
|
@ -114,8 +108,7 @@ is(document.body.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(document.getElementsByTagName("video")[0].NETWORK_EMPTY, 0);
|
is(document.getElementsByTagName("video")[0].NETWORK_EMPTY, 0);
|
||||||
is(document.getElementsByTagName("video")[0].NETWORK_IDLE, 1);
|
is(document.getElementsByTagName("video")[0].NETWORK_IDLE, 1);
|
||||||
is(document.getElementsByTagName("video")[0].NETWORK_LOADING, 2);
|
is(document.getElementsByTagName("video")[0].NETWORK_LOADING, 2);
|
||||||
is(document.getElementsByTagName("video")[0].NETWORK_LOADED, 3);
|
is(document.getElementsByTagName("video")[0].NETWORK_NO_SOURCE, 3);
|
||||||
is(document.getElementsByTagName("video")[0].NETWORK_NO_SOURCE, 4);
|
|
||||||
is(document.getElementsByTagName("video")[0].HAVE_NOTHING, 0);
|
is(document.getElementsByTagName("video")[0].HAVE_NOTHING, 0);
|
||||||
is(document.getElementsByTagName("video")[0].HAVE_METADATA, 1);
|
is(document.getElementsByTagName("video")[0].HAVE_METADATA, 1);
|
||||||
is(document.getElementsByTagName("video")[0].HAVE_CURRENT_DATA, 2);
|
is(document.getElementsByTagName("video")[0].HAVE_CURRENT_DATA, 2);
|
||||||
|
@ -128,8 +121,7 @@ is(document.getElementsByTagName("video")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undefi
|
||||||
is(document.getElementsByTagName("audio")[0].NETWORK_EMPTY, 0);
|
is(document.getElementsByTagName("audio")[0].NETWORK_EMPTY, 0);
|
||||||
is(document.getElementsByTagName("audio")[0].NETWORK_IDLE, 1);
|
is(document.getElementsByTagName("audio")[0].NETWORK_IDLE, 1);
|
||||||
is(document.getElementsByTagName("audio")[0].NETWORK_LOADING, 2);
|
is(document.getElementsByTagName("audio")[0].NETWORK_LOADING, 2);
|
||||||
is(document.getElementsByTagName("audio")[0].NETWORK_LOADED, 3);
|
is(document.getElementsByTagName("audio")[0].NETWORK_NO_SOURCE, 3);
|
||||||
is(document.getElementsByTagName("audio")[0].NETWORK_NO_SOURCE, 4);
|
|
||||||
is(document.getElementsByTagName("audio")[0].HAVE_NOTHING, 0);
|
is(document.getElementsByTagName("audio")[0].HAVE_NOTHING, 0);
|
||||||
is(document.getElementsByTagName("audio")[0].HAVE_METADATA, 1);
|
is(document.getElementsByTagName("audio")[0].HAVE_METADATA, 1);
|
||||||
is(document.getElementsByTagName("audio")[0].HAVE_CURRENT_DATA, 2);
|
is(document.getElementsByTagName("audio")[0].HAVE_CURRENT_DATA, 2);
|
||||||
|
@ -142,7 +134,6 @@ is(document.getElementsByTagName("audio")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undefi
|
||||||
is(document.getElementsByTagName("source")[0].NETWORK_EMPTY, undefined);
|
is(document.getElementsByTagName("source")[0].NETWORK_EMPTY, undefined);
|
||||||
is(document.getElementsByTagName("source")[0].NETWORK_IDLE, undefined);
|
is(document.getElementsByTagName("source")[0].NETWORK_IDLE, undefined);
|
||||||
is(document.getElementsByTagName("source")[0].NETWORK_LOADING, undefined);
|
is(document.getElementsByTagName("source")[0].NETWORK_LOADING, undefined);
|
||||||
is(document.getElementsByTagName("source")[0].NETWORK_LOADED, undefined);
|
|
||||||
is(document.getElementsByTagName("source")[0].NETWORK_NO_SOURCE, undefined);
|
is(document.getElementsByTagName("source")[0].NETWORK_NO_SOURCE, undefined);
|
||||||
is(document.getElementsByTagName("source")[0].HAVE_NOTHING, undefined);
|
is(document.getElementsByTagName("source")[0].HAVE_NOTHING, undefined);
|
||||||
is(document.getElementsByTagName("source")[0].HAVE_METADATA, undefined);
|
is(document.getElementsByTagName("source")[0].HAVE_METADATA, undefined);
|
||||||
|
@ -156,7 +147,6 @@ is(document.getElementsByTagName("source")[0].MEDIA_ERR_SRC_NOT_SUPPORTED, undef
|
||||||
is(HTMLElement.prototype.NETWORK_EMPTY, undefined);
|
is(HTMLElement.prototype.NETWORK_EMPTY, undefined);
|
||||||
is(HTMLElement.prototype.NETWORK_IDLE, undefined);
|
is(HTMLElement.prototype.NETWORK_IDLE, undefined);
|
||||||
is(HTMLElement.prototype.NETWORK_LOADING, undefined);
|
is(HTMLElement.prototype.NETWORK_LOADING, undefined);
|
||||||
is(HTMLElement.prototype.NETWORK_LOADED, undefined);
|
|
||||||
is(HTMLElement.prototype.NETWORK_NO_SOURCE, undefined);
|
is(HTMLElement.prototype.NETWORK_NO_SOURCE, undefined);
|
||||||
is(HTMLElement.prototype.HAVE_NOTHING, undefined);
|
is(HTMLElement.prototype.HAVE_NOTHING, undefined);
|
||||||
is(HTMLElement.prototype.HAVE_METADATA, undefined);
|
is(HTMLElement.prototype.HAVE_METADATA, undefined);
|
||||||
|
@ -170,8 +160,7 @@ is(HTMLElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
todo_is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY");
|
todo_is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY");
|
||||||
todo_is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE");
|
todo_is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE");
|
||||||
todo_is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING");
|
todo_is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING");
|
||||||
todo_is(HTMLMediaElement.prototype.NETWORK_LOADED, 3, "HTMLMediaElement.prototype.NETWORK_LOADED");
|
todo_is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 3, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE");
|
||||||
todo_is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 4, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE");
|
|
||||||
todo_is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING");
|
todo_is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING");
|
||||||
todo_is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA");
|
todo_is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA");
|
||||||
todo_is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA");
|
todo_is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA");
|
||||||
|
@ -184,8 +173,7 @@ is(HTMLMediaElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined, "HTMLMedia
|
||||||
is(HTMLVideoElement.prototype.NETWORK_EMPTY, 0);
|
is(HTMLVideoElement.prototype.NETWORK_EMPTY, 0);
|
||||||
is(HTMLVideoElement.prototype.NETWORK_IDLE, 1);
|
is(HTMLVideoElement.prototype.NETWORK_IDLE, 1);
|
||||||
is(HTMLVideoElement.prototype.NETWORK_LOADING, 2);
|
is(HTMLVideoElement.prototype.NETWORK_LOADING, 2);
|
||||||
is(HTMLVideoElement.prototype.NETWORK_LOADED, 3);
|
is(HTMLVideoElement.prototype.NETWORK_NO_SOURCE, 3);
|
||||||
is(HTMLVideoElement.prototype.NETWORK_NO_SOURCE, 4);
|
|
||||||
is(HTMLVideoElement.prototype.HAVE_NOTHING, 0);
|
is(HTMLVideoElement.prototype.HAVE_NOTHING, 0);
|
||||||
is(HTMLVideoElement.prototype.HAVE_METADATA, 1);
|
is(HTMLVideoElement.prototype.HAVE_METADATA, 1);
|
||||||
is(HTMLVideoElement.prototype.HAVE_CURRENT_DATA, 2);
|
is(HTMLVideoElement.prototype.HAVE_CURRENT_DATA, 2);
|
||||||
|
@ -198,8 +186,7 @@ is(HTMLVideoElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(HTMLAudioElement.prototype.NETWORK_EMPTY, 0);
|
is(HTMLAudioElement.prototype.NETWORK_EMPTY, 0);
|
||||||
is(HTMLAudioElement.prototype.NETWORK_IDLE, 1);
|
is(HTMLAudioElement.prototype.NETWORK_IDLE, 1);
|
||||||
is(HTMLAudioElement.prototype.NETWORK_LOADING, 2);
|
is(HTMLAudioElement.prototype.NETWORK_LOADING, 2);
|
||||||
is(HTMLAudioElement.prototype.NETWORK_LOADED, 3);
|
is(HTMLAudioElement.prototype.NETWORK_NO_SOURCE, 3);
|
||||||
is(HTMLAudioElement.prototype.NETWORK_NO_SOURCE, 4);
|
|
||||||
is(HTMLAudioElement.prototype.HAVE_NOTHING, 0);
|
is(HTMLAudioElement.prototype.HAVE_NOTHING, 0);
|
||||||
is(HTMLAudioElement.prototype.HAVE_METADATA, 1);
|
is(HTMLAudioElement.prototype.HAVE_METADATA, 1);
|
||||||
is(HTMLAudioElement.prototype.HAVE_CURRENT_DATA, 2);
|
is(HTMLAudioElement.prototype.HAVE_CURRENT_DATA, 2);
|
||||||
|
@ -212,7 +199,6 @@ is(HTMLAudioElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(HTMLSourceElement.prototype.NETWORK_EMPTY, undefined);
|
is(HTMLSourceElement.prototype.NETWORK_EMPTY, undefined);
|
||||||
is(HTMLSourceElement.prototype.NETWORK_IDLE, undefined);
|
is(HTMLSourceElement.prototype.NETWORK_IDLE, undefined);
|
||||||
is(HTMLSourceElement.prototype.NETWORK_LOADING, undefined);
|
is(HTMLSourceElement.prototype.NETWORK_LOADING, undefined);
|
||||||
is(HTMLSourceElement.prototype.NETWORK_LOADED, undefined);
|
|
||||||
is(HTMLSourceElement.prototype.NETWORK_NO_SOURCE, undefined);
|
is(HTMLSourceElement.prototype.NETWORK_NO_SOURCE, undefined);
|
||||||
is(HTMLSourceElement.prototype.HAVE_NOTHING, undefined);
|
is(HTMLSourceElement.prototype.HAVE_NOTHING, undefined);
|
||||||
is(HTMLSourceElement.prototype.HAVE_METADATA, undefined);
|
is(HTMLSourceElement.prototype.HAVE_METADATA, undefined);
|
||||||
|
@ -226,7 +212,6 @@ is(HTMLSourceElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||||
is(MediaError.prototype.NETWORK_EMPTY, undefined);
|
is(MediaError.prototype.NETWORK_EMPTY, undefined);
|
||||||
is(MediaError.prototype.NETWORK_IDLE, undefined);
|
is(MediaError.prototype.NETWORK_IDLE, undefined);
|
||||||
is(MediaError.prototype.NETWORK_LOADING, undefined);
|
is(MediaError.prototype.NETWORK_LOADING, undefined);
|
||||||
is(MediaError.prototype.NETWORK_LOADED, undefined);
|
|
||||||
is(MediaError.prototype.NETWORK_NO_SOURCE, undefined);
|
is(MediaError.prototype.NETWORK_NO_SOURCE, undefined);
|
||||||
is(MediaError.prototype.HAVE_NOTHING, undefined);
|
is(MediaError.prototype.HAVE_NOTHING, undefined);
|
||||||
is(MediaError.prototype.HAVE_METADATA, undefined);
|
is(MediaError.prototype.HAVE_METADATA, undefined);
|
||||||
|
|
|
@ -43,8 +43,7 @@ function startTest(test, token) {
|
||||||
ok(false, "Unexpected ended event");
|
ok(false, "Unexpected ended event");
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
v.src = test.name;
|
v.src = test.name; // implicitly starts a load.
|
||||||
v.load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.runTests(gDecodeErrorTests, startTest);
|
manager.runTests(gDecodeErrorTests, startTest);
|
||||||
|
|
|
@ -18,6 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448600
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function filename(uri) {
|
||||||
|
return uri.substr(uri.lastIndexOf("/")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function e(id) {
|
||||||
|
return document.getElementById(id);
|
||||||
|
}
|
||||||
|
|
||||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||||
.getService(Components.interfaces.nsIPrefService);
|
.getService(Components.interfaces.nsIPrefService);
|
||||||
|
@ -39,13 +47,19 @@ var gErrorCount = 0;
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
function finishTest() {
|
function finishTest() {
|
||||||
is(document.getElementById('video1').currentSrc, "", 'video1.currentSrc==""');
|
is(e('video1').currentSrc,
|
||||||
is(document.getElementById('video2').currentSrc, "", 'video2.currentSrc==""');
|
"",
|
||||||
is(document.getElementById('video3').currentSrc, "", 'video3.currentSrc==""');
|
'video1 currentSrc should be empty when there\'s no playable typed source children');
|
||||||
|
is(filename(e('video2').currentSrc),
|
||||||
|
filename(e('video2').src),
|
||||||
|
'video2 currentSrc should match src');
|
||||||
|
is(filename(e('video3').currentSrc),
|
||||||
|
filename(e('video3').src),
|
||||||
|
'video3 currentSrc should match src');
|
||||||
|
|
||||||
is(gLoadError['video1'], 1, "Load error on video1");
|
is(gLoadError['video1'], 2, "Expect one error per invalid source child on video1");
|
||||||
is(gLoadError['video2'], 1, "Load error on video2");
|
is(gLoadError['video2'], 1, "Expect one error on video2");
|
||||||
is(gLoadError['video3'], 1, "Load error on video3");
|
is(gLoadError['video3'], 1, "Expect one error on video3");
|
||||||
|
|
||||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
|
||||||
|
@ -59,7 +73,7 @@ function videoError(event, id) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
gLoadError[id]++;
|
gLoadError[id]++;
|
||||||
gErrorCount++;
|
gErrorCount++;
|
||||||
if (gErrorCount == 3) {
|
if (gErrorCount >= 4) {
|
||||||
finishTest();
|
finishTest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +82,7 @@ function videoError(event, id) {
|
||||||
|
|
||||||
<video id="video1" onerror="videoError(event, 'video1');">
|
<video id="video1" onerror="videoError(event, 'video1');">
|
||||||
<source type="video/ogg" src="320x240.ogv"/>
|
<source type="video/ogg" src="320x240.ogv"/>
|
||||||
<source type="audio/wave" src="r11025_u8_c1.wav"/>
|
<source type="audio/wave" src="r11025_u8_c1.wav" id='s2'/>
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<video id="video2" src="320x240.ogv" onerror="videoError(event, 'video2');"></video>
|
<video id="video2" src="320x240.ogv" onerror="videoError(event, 'video2');"></video>
|
||||||
|
|
|
@ -89,6 +89,7 @@ function createMedia(type, src) {
|
||||||
gMedia.addEventListener(gEventTypes[i], listener, false);
|
gMedia.addEventListener(gEventTypes[i], listener, false);
|
||||||
}
|
}
|
||||||
gMedia.src = src;
|
gMedia.src = src;
|
||||||
|
gMedia._name = src;
|
||||||
document.body.appendChild(gMedia);
|
document.body.appendChild(gMedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +109,10 @@ function test_is(a, b, msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filename(uri) {
|
||||||
|
return uri.substr(uri.lastIndexOf("/")+1);
|
||||||
|
}
|
||||||
|
|
||||||
function checkState() {
|
function checkState() {
|
||||||
if (gMedia != null) {
|
if (gMedia != null) {
|
||||||
test_ok(gMedia.networkState <= HTMLMediaElement.NETWORK_LOADING ||
|
test_ok(gMedia.networkState <= HTMLMediaElement.NETWORK_LOADING ||
|
||||||
|
@ -126,7 +131,9 @@ function checkState() {
|
||||||
test_ok(gMedia.error==null || gMedia.error.code==MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,
|
test_ok(gMedia.error==null || gMedia.error.code==MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,
|
||||||
"Error code should not exist or be SRC_NOT_SUPPORTED. gMedia.error=" +
|
"Error code should not exist or be SRC_NOT_SUPPORTED. gMedia.error=" +
|
||||||
(gMedia.error ? gMedia.error.code : "null"));
|
(gMedia.error ? gMedia.error.code : "null"));
|
||||||
test_is(gMedia.currentSrc, "", "Leaked currentSrc");
|
test_ok(filename(gMedia.currentSrc) == filename(gMedia._name) ||
|
||||||
|
gMedia.networkState == HTMLMediaElement.NETWORK_NO_SOURCE,
|
||||||
|
"currentSrc should match candidate uri, if we've got a valid source");
|
||||||
}
|
}
|
||||||
if (!gFinished) {
|
if (!gFinished) {
|
||||||
setTimeout(checkState, 1);
|
setTimeout(checkState, 1);
|
||||||
|
|
|
@ -89,8 +89,9 @@ var gTests = [
|
||||||
addSource(src, type);
|
addSource(src, type);
|
||||||
},
|
},
|
||||||
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata']
|
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata']
|
||||||
}, {
|
},{
|
||||||
// Test 2: video with multiple source, the first of which are bad, we should load the last.
|
// Test 2: video with multiple source, the first of which are bad, we should load the last,
|
||||||
|
// and receive error events for failed loads on the source children.
|
||||||
create:
|
create:
|
||||||
function(src, type) {
|
function(src, type) {
|
||||||
document.body.appendChild(gMedia);
|
document.body.appendChild(gMedia);
|
||||||
|
@ -98,7 +99,7 @@ var gTests = [
|
||||||
addSource("404b", type);
|
addSource("404b", type);
|
||||||
addSource(src, type);
|
addSource(src, type);
|
||||||
},
|
},
|
||||||
expectedEvents: ['loadstart', 'durationchange', 'loadedmetadata', 'loadeddata']
|
expectedEvents: ['loadstart', 'error', 'error', 'durationchange', 'loadedmetadata', 'loadeddata']
|
||||||
}, {
|
}, {
|
||||||
// Test 3: video with bad src, good <source>, ensure that <source> aren't used.
|
// Test 3: video with bad src, good <source>, ensure that <source> aren't used.
|
||||||
create:
|
create:
|
||||||
|
@ -123,7 +124,7 @@ var gTests = [
|
||||||
false);
|
false);
|
||||||
document.body.appendChild(gMedia);
|
document.body.appendChild(gMedia);
|
||||||
},
|
},
|
||||||
expectedEvents: ['loadstart', 'error', 'durationchange', 'loadedmetadata', 'loadeddata']
|
expectedEvents: ['loadstart', 'error', 'error', 'durationchange', 'loadedmetadata', 'loadeddata']
|
||||||
}, {
|
}, {
|
||||||
// Test 5: video with only 1 bad source, let it fail to load, then prepend
|
// Test 5: video with only 1 bad source, let it fail to load, then prepend
|
||||||
// a good <source> to the video, it shouldn't be selected, because the
|
// a good <source> to the video, it shouldn't be selected, because the
|
||||||
|
|
|
@ -25,7 +25,7 @@ var manager = new MediaTestManager;
|
||||||
|
|
||||||
function finish(evt) {
|
function finish(evt) {
|
||||||
var v = evt.target;
|
var v = evt.target;
|
||||||
is(v._error, false, "Shouldn't have thrown an error - " + v._name);
|
ok(v._error, "Should have received an error event before loaded");
|
||||||
v._finished = true;
|
v._finished = true;
|
||||||
v.parentNode.removeChild(v);
|
v.parentNode.removeChild(v);
|
||||||
manager.finished(v.token);
|
manager.finished(v.token);
|
||||||
|
@ -33,8 +33,7 @@ function finish(evt) {
|
||||||
|
|
||||||
function errorHandler(evt) {
|
function errorHandler(evt) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
evt.target._error = true;
|
evt.target.parentNode._error = true;
|
||||||
finish(evt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var extenstion = {
|
var extenstion = {
|
||||||
|
@ -56,6 +55,7 @@ function startTest(test, token) {
|
||||||
var s1 = document.createElement("source");
|
var s1 = document.createElement("source");
|
||||||
s1.type = test.type;
|
s1.type = test.type;
|
||||||
s1.src = "404." + extenstion[test.type];
|
s1.src = "404." + extenstion[test.type];
|
||||||
|
s1.addEventListener("error", errorHandler, false);
|
||||||
v.appendChild(s1);
|
v.appendChild(s1);
|
||||||
|
|
||||||
var s2 = document.createElement("source");
|
var s2 = document.createElement("source");
|
||||||
|
@ -63,9 +63,7 @@ function startTest(test, token) {
|
||||||
s2.src = test.name;
|
s2.src = test.name;
|
||||||
v.appendChild(s2);
|
v.appendChild(s2);
|
||||||
|
|
||||||
v.addEventListener("error", errorHandler, false);
|
|
||||||
v.addEventListener("loadeddata", finish, false);
|
v.addEventListener("loadeddata", finish, false);
|
||||||
|
|
||||||
document.body.appendChild(v);
|
document.body.appendChild(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -253,6 +253,7 @@ var tests = [
|
||||||
ok(true, "(7) Got playback ended");
|
ok(true, "(7) Got playback ended");
|
||||||
var v = e.target;
|
var v = e.target;
|
||||||
v._finished = true;
|
v._finished = true;
|
||||||
|
is(v._gotErrorEvent, true, "(7) Should get error event from first source load failure");
|
||||||
maybeFinish(v, 7);
|
maybeFinish(v, 7);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -262,10 +263,12 @@ var tests = [
|
||||||
v._gotLoadedMetaData = false;
|
v._gotLoadedMetaData = false;
|
||||||
v._finished = false;
|
v._finished = false;
|
||||||
v.preload = "none";
|
v.preload = "none";
|
||||||
|
v._gotErrorEvent = false;
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||||
v.addEventListener("suspend", this.suspend, false);
|
v.addEventListener("suspend", this.suspend, false);
|
||||||
v.addEventListener("ended", this.ended, false);
|
v.addEventListener("ended", this.ended, false);
|
||||||
|
v.addEventListener("error", function(e){v._gotErrorEvent = true; e.stopPropagation();}, false);
|
||||||
var s1 = document.createElement("source");
|
var s1 = document.createElement("source");
|
||||||
s1.src = "not-a-real-file.404"
|
s1.src = "not-a-real-file.404"
|
||||||
s1.type = test.type;
|
s1.type = test.type;
|
||||||
|
@ -297,8 +300,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("loadeddata", this.loadeddata, false);
|
v.addEventListener("loadeddata", this.loadeddata, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/*{
|
/*{
|
||||||
|
@ -326,8 +329,8 @@ var tests = [
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("loadeddata", function(){v.preload = "auto"}, false);
|
v.addEventListener("loadeddata", function(){v.preload = "auto"}, false);
|
||||||
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},*/
|
},*/
|
||||||
{
|
{
|
||||||
|
@ -348,8 +351,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v.preload = "auto";}, false);
|
v.addEventListener("loadstart", function(e){v.preload = "auto";}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -372,8 +375,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("loadeddata", this.loadeddata, false);
|
v.addEventListener("loadeddata", this.loadeddata, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -397,8 +400,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
v.addEventListener("canplaythrough", this.canplaythrough, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
v.preload = "metadata";
|
v.preload = "metadata";
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -426,8 +429,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("loadeddata", this.loadeddata, false);
|
v.addEventListener("loadeddata", this.loadeddata, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
v.preload = "none";
|
v.preload = "none";
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -486,8 +489,8 @@ var tests = [
|
||||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||||
v.addEventListener("ended", this.ended, false);
|
v.addEventListener("ended", this.ended, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -506,8 +509,8 @@ var tests = [
|
||||||
v.preload = "metadata";
|
v.preload = "metadata";
|
||||||
v.autoplay = true;
|
v.autoplay = true;
|
||||||
v.addEventListener("ended", this.ended, false);
|
v.addEventListener("ended", this.ended, false);
|
||||||
v.src = test.name;
|
v.src = test.name; // Causes implicit load.
|
||||||
document.body.appendChild(v); // Causes implicit load.
|
document.body.appendChild(v);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,8 +33,8 @@ if (resource != null) {
|
||||||
v.appendChild(s);
|
v.appendChild(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ok(v.networkState == HTMLMediaElement.NETWORK_EMPTY,
|
ok(v.networkState == HTMLMediaElement.NETWORK_NO_SOURCE,
|
||||||
"We shouldn't start a load until the video tag is closed.");
|
"We shouldn't start network load until the current task returns.");
|
||||||
</script>
|
</script>
|
||||||
</video>
|
</video>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1466,7 +1466,6 @@ nsWaveDecoder::ResourceLoaded()
|
||||||
|
|
||||||
if (mElement) {
|
if (mElement) {
|
||||||
// Ensure the final progress event gets fired
|
// Ensure the final progress event gets fired
|
||||||
mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress"));
|
|
||||||
mElement->ResourceLoaded();
|
mElement->ResourceLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,8 +1532,10 @@ nsWaveDecoder::NotifyDownloadEnded(nsresult aStatus)
|
||||||
{
|
{
|
||||||
if (NS_SUCCEEDED(aStatus)) {
|
if (NS_SUCCEEDED(aStatus)) {
|
||||||
ResourceLoaded();
|
ResourceLoaded();
|
||||||
} else if (aStatus != NS_BASE_STREAM_CLOSED &&
|
} else if (aStatus == NS_BINDING_ABORTED) {
|
||||||
aStatus != NS_BINDING_ABORTED) {
|
// Download has been cancelled by user.
|
||||||
|
mElement->LoadAborted();
|
||||||
|
} else if (aStatus != NS_BASE_STREAM_CLOSED) {
|
||||||
NetworkError();
|
NetworkError();
|
||||||
}
|
}
|
||||||
UpdateReadyStateForData();
|
UpdateReadyStateForData();
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#endif
|
#endif
|
||||||
%}
|
%}
|
||||||
|
|
||||||
[scriptable, uuid(4355cfdb-0d70-4e5b-bb48-3ae8111ee72b)]
|
[scriptable, uuid(c8b1423f-1321-4324-b6b7-8548d2fdc3da)]
|
||||||
interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
|
interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
|
||||||
{
|
{
|
||||||
// error state
|
// error state
|
||||||
|
@ -69,8 +69,7 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
|
||||||
const unsigned short NETWORK_EMPTY = 0;
|
const unsigned short NETWORK_EMPTY = 0;
|
||||||
const unsigned short NETWORK_IDLE = 1;
|
const unsigned short NETWORK_IDLE = 1;
|
||||||
const unsigned short NETWORK_LOADING = 2;
|
const unsigned short NETWORK_LOADING = 2;
|
||||||
const unsigned short NETWORK_LOADED = 3;
|
const unsigned short NETWORK_NO_SOURCE = 3;
|
||||||
const unsigned short NETWORK_NO_SOURCE = 4;
|
|
||||||
readonly attribute unsigned short networkState;
|
readonly attribute unsigned short networkState;
|
||||||
attribute DOMString preload;
|
attribute DOMString preload;
|
||||||
readonly attribute nsIDOMTimeRanges buffered;
|
readonly attribute nsIDOMTimeRanges buffered;
|
||||||
|
|
|
@ -515,9 +515,7 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent
|
||||||
// Some HTML nodes need DoneAddingChildren() called to initialize
|
// Some HTML nodes need DoneAddingChildren() called to initialize
|
||||||
// properly (e.g. form state restoration).
|
// properly (e.g. form state restoration).
|
||||||
// XXX expose ElementName group here and do switch
|
// XXX expose ElementName group here and do switch
|
||||||
if (aName == nsHtml5Atoms::video ||
|
if (aName == nsHtml5Atoms::object ||
|
||||||
aName == nsHtml5Atoms::audio ||
|
|
||||||
aName == nsHtml5Atoms::object ||
|
|
||||||
aName == nsHtml5Atoms::applet) {
|
aName == nsHtml5Atoms::applet) {
|
||||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||||
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
NS_ASSERTION(treeOp, "Tree op allocation failed.");
|
||||||
|
|
|
@ -38,12 +38,13 @@
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
|
#include "nsIRunnable.idl"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for the native event system layer. This interface is designed
|
* Interface for the native event system layer. This interface is designed
|
||||||
* to be used on the main application thread only.
|
* to be used on the main application thread only.
|
||||||
*/
|
*/
|
||||||
[uuid(501403e9-a091-4780-ba55-cfd1e21287a1)]
|
[uuid(40bc6280-ad83-471e-b197-80ab90e2065e)]
|
||||||
interface nsIAppShell : nsISupports
|
interface nsIAppShell : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -101,4 +102,15 @@ interface nsIAppShell : nsISupports
|
||||||
* The current event loop nesting level.
|
* The current event loop nesting level.
|
||||||
*/
|
*/
|
||||||
readonly attribute unsigned long eventloopNestingLevel;
|
readonly attribute unsigned long eventloopNestingLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows running of a "synchronous section", in the form of an nsIRunnable
|
||||||
|
* once the event loop has reached a "stable state". We've reached a stable
|
||||||
|
* state when the currently executing task/event has finished, see:
|
||||||
|
* http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
|
||||||
|
* In practice this runs aRunnable once the currently executing event
|
||||||
|
* finishes. If called multiple times per task/event, all the runnables will
|
||||||
|
* be executed, in the order in which runInStableState() was called.
|
||||||
|
*/
|
||||||
|
void runInStableState(in nsIRunnable aRunnable);
|
||||||
};
|
};
|
||||||
|
|
|
@ -324,14 +324,36 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, PRBool mayWait,
|
||||||
thr->Dispatch(mDummyEvent, NS_DISPATCH_NORMAL);
|
thr->Dispatch(mDummyEvent, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We're about to run an event, so we're in a stable state.
|
||||||
|
RunSyncSections();
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBaseAppShell::RunSyncSections()
|
||||||
|
{
|
||||||
|
if (mSyncSections.Count() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We've got synchronous sections awaiting a stable state. Run
|
||||||
|
// all the synchronous sections. Note that a synchronous section could
|
||||||
|
// add another synchronous section, so we don't remove elements from
|
||||||
|
// mSyncSections until all sections have been run, else we'll screw up
|
||||||
|
// our iteration.
|
||||||
|
for (PRUint32 i=0; i<mSyncSections.Count(); i++) {
|
||||||
|
mSyncSections[i]->Run();
|
||||||
|
}
|
||||||
|
mSyncSections.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Called from the main thread
|
// Called from the main thread
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsBaseAppShell::AfterProcessNextEvent(nsIThreadInternal *thr,
|
nsBaseAppShell::AfterProcessNextEvent(nsIThreadInternal *thr,
|
||||||
PRUint32 recursionDepth)
|
PRUint32 recursionDepth)
|
||||||
{
|
{
|
||||||
|
// We've just finished running an event, so we're in a stable state.
|
||||||
|
RunSyncSections();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,3 +365,18 @@ nsBaseAppShell::Observe(nsISupports *subject, const char *topic,
|
||||||
Exit();
|
Exit();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsBaseAppShell::RunInStableState(nsIRunnable* aRunnable)
|
||||||
|
{
|
||||||
|
if (!mRunning) {
|
||||||
|
// We're not running a "task"/event, so we're already in a "stable state",
|
||||||
|
// so we can run the synchronous section immediately.
|
||||||
|
aRunnable->Run();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// Else we're running a "task"/event, record the synchronous section, and
|
||||||
|
// run it with any others once we reach a stable state.
|
||||||
|
mSyncSections.AppendObject(aRunnable);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "nsIThreadInternal.h"
|
#include "nsIThreadInternal.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
|
#include "nsCOMArray.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "prinrval.h"
|
#include "prinrval.h"
|
||||||
|
|
||||||
|
@ -99,6 +100,11 @@ protected:
|
||||||
private:
|
private:
|
||||||
PRBool DoProcessNextNativeEvent(PRBool mayWait);
|
PRBool DoProcessNextNativeEvent(PRBool mayWait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs all synchronous sections which are queued up in mSyncSections.
|
||||||
|
*/
|
||||||
|
void RunSyncSections();
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> mDummyEvent;
|
nsCOMPtr<nsIRunnable> mDummyEvent;
|
||||||
/**
|
/**
|
||||||
* mBlockedWait points back to a slot that controls the wait loop in
|
* mBlockedWait points back to a slot that controls the wait loop in
|
||||||
|
@ -119,6 +125,7 @@ private:
|
||||||
eEventloopOther // innermost native event loop is a native library/plugin etc
|
eEventloopOther // innermost native event loop is a native library/plugin etc
|
||||||
};
|
};
|
||||||
EventloopNestingState mEventloopNestingState;
|
EventloopNestingState mEventloopNestingState;
|
||||||
|
nsCOMArray<nsIRunnable> mSyncSections;
|
||||||
PRPackedBool mRunning;
|
PRPackedBool mRunning;
|
||||||
PRPackedBool mExiting;
|
PRPackedBool mExiting;
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче