Diff
Modified: trunk/LayoutTests/ChangeLog (90038 => 90039)
--- trunk/LayoutTests/ChangeLog 2011-06-29 20:46:33 UTC (rev 90038)
+++ trunk/LayoutTests/ChangeLog 2011-06-29 20:52:35 UTC (rev 90039)
@@ -1,3 +1,15 @@
+2011-06-29 Eric Carlson <[email protected]>
+
+ Reviewed by Darin Adler.
+
+ Media element loads blocked by a resource load delegate do not generate an error event
+ https://bugs.webkit.org/show_bug.cgi?id=63558
+
+ * media/media-blocked-by-beforeload-expected.txt: Added.
+ * media/media-blocked-by-beforeload.html: Added.
+ * media/media-blocked-by-willsendrequest-expected.txt: Added.
+ * media/media-blocked-by-willsendrequest.html: Added.
+
2011-06-29 Darin Adler <[email protected]>
Reviewed by Anders Carlsson.
Added: trunk/LayoutTests/media/media-blocked-by-beforeload-expected.txt (0 => 90039)
--- trunk/LayoutTests/media/media-blocked-by-beforeload-expected.txt (rev 0)
+++ trunk/LayoutTests/media/media-blocked-by-beforeload-expected.txt 2011-06-29 20:52:35 UTC (rev 90039)
@@ -0,0 +1,40 @@
+Test to ensure that a media file blocked by a beforeload handler generates an error and does not block the document's 'load' event.
+
+*** Test initial state ***
+EXPECTED (video.networkState == '0') OK
+EXPECTED (video.error == 'null') OK
+
+*** Test blocking the 'src' attribute ***
+
+EVENT('beforeload')
+EXPECTED (event.target.tagName == 'VIDEO') OK
+blocking load of 'src'
+
+EVENT('loadstart')
+
+EVENT('error')
+EXPECTED (event.target.tagName == 'VIDEO') OK
+EXPECTED (video.error != 'null') OK
+EXPECTED (video.error.code == '4') OK
+EXPECTED (video.networkState == '3') OK
+
+*** Test using the <source> element ***
+
+EVENT('beforeload')
+EXPECTED (event.target.tagName == 'VIDEO') OK
+blocking load of first <source> element
+
+EVENT('beforeload')
+EXPECTED (event.target.tagName == 'VIDEO') OK
+allowing load of second <source> element
+
+EVENT('loadstart')
+
+EVENT('error')
+EXPECTED (event.target.tagName == 'SOURCE') OK
+EXPECTED (video.error == 'null') OK
+
+EVENT('loadedmetadata')
+
+END OF TEST
+
Added: trunk/LayoutTests/media/media-blocked-by-beforeload.html (0 => 90039)
--- trunk/LayoutTests/media/media-blocked-by-beforeload.html (rev 0)
+++ trunk/LayoutTests/media/media-blocked-by-beforeload.html 2011-06-29 20:52:35 UTC (rev 90039)
@@ -0,0 +1,132 @@
+<!doctype html>
+<html>
+<head>
+ <style>
+ video { background-color: yellow; width: 320px; height: 240px;}
+ </style>
+ <script src=""
+ <script src=""
+</head>
+<body>
+ <video controls ></video>
+ <p>Test to ensure that a media file blocked by a beforeload handler generates an error
+ and does not block the document's 'load' event.</p>
+
+ <script>
+ if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+
+ var blockedURL;
+ var allowedURL;
+ var test;
+
+ function logEvent(evt)
+ {
+ consoleWrite("<br>EVENT('" + evt.type + "')");
+ }
+
+ function loadedmetadata(evt)
+ {
+ logEvent(evt);
+ consoleWrite("");
+ endTest();
+ }
+
+ function setupSourceTest()
+ {
+ consoleWrite("<br>*** Test using the <source> element ***");
+ blockedURL = relativeURL(video.src);
+ allowedURL = findMediaFile("audio", "content/test");
+
+ // Remove 'src' attribute so <source> will be used when we force a reload
+ video.removeAttribute('src');
+
+ var blockedSource = document.createElement('source');
+ blockedSource.src = ""
+ blockedSource.type = mimeTypeForExtension(blockedSource.src.split('.')[1]);
+ video.appendChild(blockedSource);
+
+ var allowedSource = document.createElement('source');
+ allowedSource.src = ""
+ allowedSource.type = mimeTypeForExtension(allowedSource.src.split('.')[1]);
+ video.appendChild(allowedSource);
+
+ test = 2;
+ video.load();
+ };
+
+ function error(evt)
+ {
+ logEvent(evt);
+ switch (test)
+ {
+ case 1:
+ testExpected("event.target.tagName", "VIDEO");
+ testExpected("video.error", null, "!=");
+ testExpected("video.error.code", MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ testExpected("video.networkState", HTMLMediaElement.NETWORK_NO_SOURCE);
+
+ setupSourceTest();
+ break;
+ case 2:
+ // The error should have been fired at the <source> and the media element should
+ // not be in an error state.
+ testExpected("event.target.tagName", "SOURCE");
+ testExpected("video.error", null);
+ break;
+ case 3:
+ failTest("Unexpected 'error' event fired!");
+ break;
+ }
+ }
+
+ function beforeload(evt)
+ {
+ logEvent(evt);
+ testExpected("event.target.tagName", "VIDEO");
+ switch (test)
+ {
+ case 1:
+ consoleWrite("blocking load of 'src'");
+ evt.preventDefault();
+ break;
+
+ case 2:
+ if (relativeURL(evt.url) == blockedURL) {
+ consoleWrite("blocking load of first <source> element");
+ evt.preventDefault();
+ } else {
+ consoleWrite("allowing load of second <source> element");
+ }
+ break;
+ }
+ }
+
+ function loaded(evt)
+ {
+ logEvent(evt);
+ testExpected("video.error", null, "!=");
+ testExpected("video.error.code", MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ testExpected("video.networkState", HTMLMediaElement.NETWORK_NO_SOURCE);
+ };
+
+ findMediaElement();
+
+ video.addEventListener('loadstart', logEvent, true);
+ video.addEventListener('loadedmetadata', loadedmetadata, true);
+ video.addEventListener('beforeload', beforeload, true);
+ video.addEventListener('error', error, true);
+ window.addEventListener('load', loaded, true);
+
+ consoleWrite("*** Test initial state ***");
+ testExpected("video.networkState", HTMLMediaElement.NETWORK_EMPTY);
+ testExpected("video.error", null);
+
+ consoleWrite("<br>*** Test blocking the 'src' attribute ***");
+ test = 1;
+ var mediaFile = findMediaFile("video", "content/test");
+ video.src = ""
+ </script>
+
+</body>
+</html>
Added: trunk/LayoutTests/media/media-blocked-by-willsendrequest-expected.txt (0 => 90039)
--- trunk/LayoutTests/media/media-blocked-by-willsendrequest-expected.txt (rev 0)
+++ trunk/LayoutTests/media/media-blocked-by-willsendrequest-expected.txt 2011-06-29 20:52:35 UTC (rev 90039)
@@ -0,0 +1,12 @@
+Test to ensure that a media file blocked by the resource load delegate generates an error and does not block the document's 'load' event.
+
+EXPECTED (video.networkState == '0') OK
+
+EVENT(loadstart)
+EVENT(error)
+EXPECTED (video.error != 'null') OK
+EXPECTED (video.error.code == '4') OK
+EXPECTED (video.networkState == '3') OK
+
+END OF TEST
+
Added: trunk/LayoutTests/media/media-blocked-by-willsendrequest.html (0 => 90039)
--- trunk/LayoutTests/media/media-blocked-by-willsendrequest.html (rev 0)
+++ trunk/LayoutTests/media/media-blocked-by-willsendrequest.html 2011-06-29 20:52:35 UTC (rev 90039)
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+<head>
+ <script src=""
+ <script src=""
+</head>
+<body>
+ <video controls></video>
+ <p>Test to ensure that a media file blocked by the resource load delegate generates an error
+ and does not block the document's 'load' event.</p>
+
+ <script>
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.setWillSendRequestReturnsNull(true);
+ } else
+ consoleWrite("This test can only be run in DumpRenderTree!<br><br>");
+
+ function loaded()
+ {
+ testExpected("video.error", null, "!=");
+ testExpected("video.error.code", MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ testExpected("video.networkState", HTMLMediaElement.NETWORK_NO_SOURCE);
+ consoleWrite("");
+ endTest();
+ };
+
+ window._onload_ = loaded;
+
+ findMediaElement();
+ waitForEvent("loadstart");
+ waitForEvent("error");
+
+ testExpected("video.networkState", HTMLMediaElement.NETWORK_EMPTY);
+ consoleWrite("");
+ var mediaFile = findMediaFile("video", "content/test");
+ video.src = ""
+ </script>
+
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (90038 => 90039)
--- trunk/Source/WebCore/ChangeLog 2011-06-29 20:46:33 UTC (rev 90038)
+++ trunk/Source/WebCore/ChangeLog 2011-06-29 20:52:35 UTC (rev 90039)
@@ -1,3 +1,29 @@
+2011-06-29 Eric Carlson <[email protected]>
+
+ Reviewed by Darin Adler.
+
+ Media element loads blocked by a resource load delegate do not generate an error event
+ https://bugs.webkit.org/show_bug.cgi?id=63558
+
+ Tests: media/media-blocked-by-beforeload.html
+ media/media-blocked-by-willsendrequest.html
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::selectMediaResource): Call mediaLoadingFailed instead of noneSupported
+ so all failures follow the same code path.
+ (WebCore::HTMLMediaElement::loadResource): Call mediaLoadingFailed when there is no frame, when
+ the loader delegate rejects the url, or when MediaPlayer doesn't find a media engine that
+ supports the type.
+ (WebCore::HTMLMediaElement::selectNextSourceChild): Fix incorrect logging.
+ (WebCore::HTMLMediaElement::mediaLoadingFailed): Change name of parameter from "state" to
+ "error" to make its purpose obvious.
+
+ * platform/graphics/MediaPlayer.cpp:
+ (WebCore::MediaPlayer::load): Return a bool indicating whether or not the url was given to
+ a media engine.
+ (WebCore::MediaPlayer::loadWithNextMediaEngine): Add some logging.
+ * platform/graphics/MediaPlayer.h:
+
2011-06-29 Darin Adler <[email protected]>
Reviewed by Anders Carlsson.
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (90038 => 90039)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2011-06-29 20:46:33 UTC (rev 90038)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2011-06-29 20:52:35 UTC (rev 90039)
@@ -641,22 +641,26 @@
// 6 - If mode is attribute, then run these substeps
if (mode == attribute) {
+ m_loadState = LoadingFromSrcAttr;
+
// If the src attribute's value is the empty string ... jump down to the failed step below
KURL mediaURL = getNonEmptyURLAttribute(srcAttr);
if (mediaURL.isEmpty()) {
- noneSupported();
+ mediaLoadingFailed(MediaPlayer::FormatError);
LOG(Media, "HTMLMediaElement::selectMediaResource, empty 'src'");
return;
}
- if (isSafeToLoadURL(mediaURL, Complain) && dispatchBeforeLoadEvent(mediaURL.string())) {
- ContentType contentType("");
- m_loadState = LoadingFromSrcAttr;
- loadResource(mediaURL, contentType);
- } else
- noneSupported();
+ if (!isSafeToLoadURL(mediaURL, Complain) || !dispatchBeforeLoadEvent(mediaURL.string())) {
+ mediaLoadingFailed(MediaPlayer::FormatError);
+ return;
+ }
- LOG(Media, "HTMLMediaElement::selectMediaResource, 'src' not used");
+ // No type information is available when the url comes from the 'src' attribute so MediaPlayer
+ // will have to pick a media engine based on the file extension.
+ ContentType contentType("");
+ loadResource(mediaURL, contentType);
+ LOG(Media, "HTMLMediaElement::selectMediaResource, using 'src' attribute url");
return;
}
@@ -712,12 +716,16 @@
LOG(Media, "HTMLMediaElement::loadResource(%s, %s)", urlForLogging(initialURL).utf8().data(), contentType.raw().utf8().data());
Frame* frame = document()->frame();
- if (!frame)
+ if (!frame) {
+ mediaLoadingFailed(MediaPlayer::FormatError);
return;
+ }
KURL url = ""
- if (!frame->loader()->willLoadMediaElementURL(url))
+ if (!frame->loader()->willLoadMediaElementURL(url)) {
+ mediaLoadingFailed(MediaPlayer::FormatError);
return;
+ }
// The resource fetch algorithm
m_networkState = NETWORK_LOADING;
@@ -765,7 +773,8 @@
m_player->setPreservesPitch(m_webkitPreservesPitch);
updateVolume();
- m_player->load(url.string(), contentType);
+ if (!m_player->load(url.string(), contentType))
+ mediaLoadingFailed(MediaPlayer::FormatError);
// If there is no poster to display, allow the media engine to render video frames as soon as
// they are available.
@@ -926,7 +935,7 @@
endProcessingMediaPlayerCallback();
}
-void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState state)
+void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error)
{
stopPeriodicTimers();
@@ -950,11 +959,11 @@
return;
}
- if (state == MediaPlayer::NetworkError && m_readyState >= HAVE_METADATA)
+ if (error == MediaPlayer::NetworkError && m_readyState >= HAVE_METADATA)
mediaEngineError(MediaError::create(MediaError::MEDIA_ERR_NETWORK));
- else if (state == MediaPlayer::DecodeError)
+ else if (error == MediaPlayer::DecodeError)
mediaEngineError(MediaError::create(MediaError::MEDIA_ERR_DECODE));
- else if ((state == MediaPlayer::FormatError || state == MediaPlayer::NetworkError) && m_loadState == LoadingFromSrcAttr)
+ else if ((error == MediaPlayer::FormatError || error == MediaPlayer::NetworkError) && m_loadState == LoadingFromSrcAttr)
noneSupported();
updateDisplayState();
@@ -1162,6 +1171,7 @@
void HTMLMediaElement::prepareToPlay()
{
+ LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this);
if (m_havePreparedToPlay)
return;
m_havePreparedToPlay = true;
@@ -1773,7 +1783,7 @@
// Don't log if this was just called to find out if there are any valid <source> elements.
bool shouldLog = actionIfInvalid != DoNothing;
if (shouldLog)
- LOG(Media, "HTMLMediaElement::selectNextSourceChild(contentType : \"%s\")", contentType ? contentType->raw().utf8().data() : "");
+ LOG(Media, "HTMLMediaElement::selectNextSourceChild");
#endif
if (m_nextChildNodeToConsider == sourceChildEndOfListValue()) {
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (90038 => 90039)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2011-06-29 20:46:33 UTC (rev 90038)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2011-06-29 20:52:35 UTC (rev 90039)
@@ -33,6 +33,7 @@
#include "Frame.h"
#include "FrameView.h"
#include "IntRect.h"
+#include "Logging.h"
#include "MIMETypeRegistry.h"
#include "MediaPlayerPrivate.h"
#include "Settings.h"
@@ -316,7 +317,7 @@
m_mediaPlayerClient = 0;
}
-void MediaPlayer::load(const String& url, const ContentType& contentType)
+bool MediaPlayer::load(const String& url, const ContentType& contentType)
{
String type = contentType.type().lower();
String typeCodecs = contentType.parameter(codecs());
@@ -340,6 +341,7 @@
m_contentMIMEType = type;
m_contentTypeCodecs = typeCodecs;
loadWithNextMediaEngine(0);
+ return m_currentMediaEngine;
}
void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
@@ -354,6 +356,7 @@
// Don't delete and recreate the player unless it comes from a different engine.
if (!engine) {
+ LOG(Media, "MediaPlayer::loadWithNextMediaEngine - no media engine found for type \"%s\"", m_contentMIMEType.utf8().data());
m_currentMediaEngine = engine;
m_private = nullptr;
} else if (m_currentMediaEngine != engine) {
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (90038 => 90039)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2011-06-29 20:46:33 UTC (rev 90038)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2011-06-29 20:52:35 UTC (rev 90039)
@@ -197,7 +197,7 @@
IntSize size() const { return m_size; }
void setSize(const IntSize& size);
- void load(const String& url, const ContentType&);
+ bool load(const String& url, const ContentType&);
void cancelLoad();
bool visible() const;