From 01de168e482820e3e98079b24f805fac74d23666 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Mon, 9 Feb 2009 14:04:10 +1300 Subject: [PATCH] Bug 476731 - Media element should fire error event when src is a 404 - r=doublec sr=roc --- .../html/content/public/nsHTMLMediaElement.h | 6 ++ .../html/content/src/nsHTMLMediaElement.cpp | 56 +++++++++---- content/media/video/test/Makefile.in | 1 + .../video/test/file_access_controls.html | 20 ++--- content/media/video/test/test_autoplay.html | 4 +- content/media/video/test/test_bug463162.xhtml | 8 +- .../media/video/test/test_can_play_type.html | 2 +- .../video/test/test_can_play_type_no_ogg.html | 2 +- .../test/test_can_play_type_no_wave.html | 2 +- .../video/test/test_can_play_type_ogg.html | 2 +- .../video/test/test_can_play_type_wave.html | 2 +- content/media/video/test/test_constants.html | 2 +- content/media/video/test/test_controls.html | 4 +- .../media/video/test/test_currentTime.html | 2 +- .../video/test/test_decoder_disable.html | 48 +++++++---- .../media/video/test/test_error_on_404.html | 80 +++++++++++++++++++ .../video/test/test_media_selection.html | 2 + .../media/video/test/test_networkState.html | 2 +- content/media/video/test/test_paused.html | 2 +- content/media/video/test/test_readyState.html | 2 +- content/media/video/test/test_seek2.html | 2 +- content/media/video/test/test_volume.html | 2 +- dom/public/idl/html/nsIDOMHTMLMediaError.idl | 5 +- 23 files changed, 194 insertions(+), 64 deletions(-) create mode 100644 content/media/video/test/test_error_on_404.html diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 5dd129979ead..68dacabcf754 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -213,6 +213,12 @@ protected: */ nsresult NewURIFromString(const nsAutoString& aURISpec, nsIURI** aURI); + /** + * Does step 12 of the media load() algorithm, sends error/emptied events to + * to the media element, and reset network/begun state. + */ + void NoSupportedMediaError(); + nsRefPtr mDecoder; nsCOMPtr mChannel; diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index bb5b8c38da90..1e00fc844f00 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -138,6 +138,8 @@ NS_IMETHODIMP nsHTMLMediaElement::nsMediaLoadListener::OnStartRequest(nsIRequest // the connection since we aren't interested in keeping the channel // alive ourselves. rv = NS_BINDING_ABORTED; + if (mElement) + mElement->NetworkError(); } // The element is only needed until we've had a chance to call @@ -243,16 +245,31 @@ PRBool nsHTMLMediaElement::AbortExistingLoads() return PR_FALSE; } +void nsHTMLMediaElement::NoSupportedMediaError() +{ + mError = new nsHTMLMediaError(nsIDOMHTMLMediaError::MEDIA_ERR_NONE_SUPPORTED); + mBegun = PR_FALSE; + DispatchAsyncProgressEvent(NS_LITERAL_STRING("error")); + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied")); +} + /* void load (); */ NS_IMETHODIMP nsHTMLMediaElement::Load() { if (AbortExistingLoads()) return NS_OK; + mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; + mBegun = PR_TRUE; + DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); + nsCOMPtr uri; nsresult rv = PickMediaElement(getter_AddRefs(uri)); - if (NS_FAILED(rv)) + if (NS_FAILED(rv)) { + NoSupportedMediaError(); return rv; + } if (mChannel) { mChannel->Cancel(NS_BINDING_ABORTED); @@ -270,6 +287,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { + NoSupportedMediaError(); return NS_ERROR_CONTENT_BLOCKED; } @@ -279,8 +297,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() nsnull, nsnull, nsIRequest::LOAD_NORMAL); - NS_ENSURE_SUCCESS(rv, rv); - + if (NS_FAILED(rv)) { + NetworkError(); + return rv; + } // The listener holds a strong reference to us. This creates a reference // cycle which is manually broken in the listener's OnStartRequest method // after it is finished with the element. @@ -295,14 +315,19 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() PR_FALSE, &rv); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + NoSupportedMediaError(); + return rv; + } } else { rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(NodePrincipal(), uri, nsIScriptSecurityManager::STANDARD); - NS_ENSURE_SUCCESS(rv, rv); - + if (NS_FAILED(rv)) { + NoSupportedMediaError(); + return rv; + } listener = loadListener; } @@ -325,14 +350,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() // and is useless now anyway, so drop our reference to it to allow it to // be destroyed. mChannel = nsnull; + NetworkError(); return rv; } - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; - - mBegun = PR_TRUE; - - DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); return NS_OK; } @@ -1163,9 +1184,6 @@ nsresult nsHTMLMediaElement::DispatchAsyncProgressEvent(const nsAString& aName) nsresult nsHTMLMediaElement::DispatchProgressEvent(const nsAString& aName) { - if (!mDecoder) - return NS_OK; - nsCOMPtr docEvent(do_QueryInterface(GetOwnerDoc())); nsCOMPtr target(do_QueryInterface(static_cast(this))); NS_ENSURE_TRUE(docEvent && target, NS_ERROR_INVALID_ARG); @@ -1177,9 +1195,15 @@ nsresult nsHTMLMediaElement::DispatchProgressEvent(const nsAString& aName) nsCOMPtr progressEvent(do_QueryInterface(event)); NS_ENSURE_TRUE(progressEvent, NS_ERROR_FAILURE); - nsMediaDecoder::Statistics stats = mDecoder->GetStatistics(); + PRInt64 totalBytes = 0; + PRUint64 downloadPosition = 0; + if (mDecoder) { + nsMediaDecoder::Statistics stats = mDecoder->GetStatistics(); + totalBytes = stats.mTotalBytes; + downloadPosition = stats.mDownloadPosition; + } rv = progressEvent->InitProgressEvent(aName, PR_TRUE, PR_TRUE, - stats.mTotalBytes >= 0, stats.mDownloadPosition, stats.mTotalBytes); + totalBytes >= 0, downloadPosition, totalBytes); NS_ENSURE_SUCCESS(rv, rv); PRBool dummy; diff --git a/content/media/video/test/Makefile.in b/content/media/video/test/Makefile.in index 256137aad02c..00c925164290 100644 --- a/content/media/video/test/Makefile.in +++ b/content/media/video/test/Makefile.in @@ -74,6 +74,7 @@ _TEST_FILES += \ test_duration1.html \ test_ended1.html \ test_ended2.html \ + test_error_on_404.html \ test_onloadedmetadata.html \ test_progress1.html \ test_progress3.html \ diff --git a/content/media/video/test/file_access_controls.html b/content/media/video/test/file_access_controls.html index cc9f5b562775..ebd719c19842 100644 --- a/content/media/video/test/file_access_controls.html +++ b/content/media/video/test/file_access_controls.html @@ -1,5 +1,7 @@ + + - - - - - - - diff --git a/content/media/video/test/test_autoplay.html b/content/media/video/test/test_autoplay.html index 60de46abc2cd..0b733e18e887 100644 --- a/content/media/video/test/test_autoplay.html +++ b/content/media/video/test/test_autoplay.html @@ -7,8 +7,8 @@ - - + +
 
diff --git a/content/media/video/test/test_can_play_type_no_wave.html b/content/media/video/test/test_can_play_type_no_wave.html
index 5d9ddff2c179..9d791ae098ac 100644
--- a/content/media/video/test/test_can_play_type_no_wave.html
+++ b/content/media/video/test/test_can_play_type_no_wave.html
@@ -16,7 +16,7 @@ a Bug 469247
 
 
-
+
 
 
 
diff --git a/content/media/video/test/test_can_play_type_ogg.html b/content/media/video/test/test_can_play_type_ogg.html
index 32e8eb7105e4..95bf175e0b81 100644
--- a/content/media/video/test/test_can_play_type_ogg.html
+++ b/content/media/video/test/test_can_play_type_ogg.html
@@ -16,7 +16,7 @@ a Bug 469247
 
 
-
+
 
 
 
diff --git a/content/media/video/test/test_can_play_type_wave.html b/content/media/video/test/test_can_play_type_wave.html
index e64ad15ad48d..84a7a64df6bc 100644
--- a/content/media/video/test/test_can_play_type_wave.html
+++ b/content/media/video/test/test_can_play_type_wave.html
@@ -16,7 +16,7 @@ a Bug 469247
 
 
-
+
 
 
 
diff --git a/content/media/video/test/test_constants.html b/content/media/video/test/test_constants.html
index 61b0e4c5acf7..bf947d50e4cc 100644
--- a/content/media/video/test/test_constants.html
+++ b/content/media/video/test/test_constants.html
@@ -11,7 +11,7 @@
   
 
 
-
+
 
 
+var gLoadError = new Object();
 
-
+gLoadError['video1'] = 0; 
+gLoadError['video2'] = 0;
+gLoadError['video3'] = 0;
 
-
-
-
-
+
+
+
+
+
+
 
+ diff --git a/content/media/video/test/test_error_on_404.html b/content/media/video/test/test_error_on_404.html new file mode 100644 index 000000000000..610e0d735a1d --- /dev/null +++ b/content/media/video/test/test_error_on_404.html @@ -0,0 +1,80 @@ + + + + + Test for Bug 476731 + + + + + +Mozilla Bug +

+ +
+
+
+
+
+
+ + + + + + + + diff --git a/content/media/video/test/test_media_selection.html b/content/media/video/test/test_media_selection.html index cb48a2110e89..23a24e088951 100644 --- a/content/media/video/test/test_media_selection.html +++ b/content/media/video/test/test_media_selection.html @@ -15,6 +15,8 @@ function maketest(expect_load, attach_media, name, type, check_metadata) { return function (testNum) { var e = document.createElement('video'); + e.addEventListener('error', function(e) { e.stopPropagation();}, false); + if (expect_load) { // this could be loadedmetadata, but needs bug 466410 fixed e.addEventListener('loadeddata', function () { diff --git a/content/media/video/test/test_networkState.html b/content/media/video/test/test_networkState.html index 6788f5cfa491..d5828ee32ef0 100644 --- a/content/media/video/test/test_networkState.html +++ b/content/media/video/test/test_networkState.html @@ -7,7 +7,7 @@ - +