2010-07-12 Eric Carlson <eric.carlson@apple.com>

        Reviewed by Darin Adler.

        Update media element's handling of empty 'src' attribute
        https://bugs.webkit.org/show_bug.cgi?id=42001

        * html/HTMLMediaElement.cpp:
        (WebCore::HTMLMediaElement::src): Return getNonEmptyURLAttribute().
        (WebCore::HTMLMediaElement::selectMediaResource): Call noneSupported() for empty 'src'.
        (WebCore::HTMLMediaElement::selectNextSourceChild): Use getNonEmptyURLAttribute() to convert 
        'src' to URL instead of document()->completeURL(). Don't consider a <source> with an empty 'src'. 

        * html/HTMLMediaElement.idl: Add 'NonEmpty' option to 'src' attribute.

        * html/HTMLSourceElement.cpp:
        (WebCore::HTMLSourceElement::src): Return getNonEmptyURLAttribute().
        (WebCore::HTMLSourceElement::isURLAttribute): New, 'src' is a URL attribute.
        * html/HTMLSourceElement.h:

        * html/HTMLSourceElement.idl: Add 'NonEmpty' option to 'src' attribute.

        * html/HTMLVideoElement.cpp:
        (WebCore::HTMLVideoElement::parseMappedAttribute): Use getNonEmptyURLAttribute() to convert 
        'poster' to URL instead of document()->completeURL().

        * html/HTMLVideoElement.idl:  Add 'NonEmpty' option to 'poster' attribute.

2010-07-12  Eric Carlson  <eric.carlson@apple.com>

        Reviewed by NOBODY (OOPS!).

        Update media element's handling of empty 'src' attribute
        https://bugs.webkit.org/show_bug.cgi?id=42001

        * fast/dom/URL-attribute-reflection-expected.txt: Update results now that audio, video, and
        source return 'non-empty URL'.

        * media/video-poster-expected.txt:
        * media/video-poster.html: Test empty poster url.

        * media/video-source-error-no-candidate-expected.txt:
        * media/video-source-error-no-candidate.html: Empty 'src' should fires an error event.

        * media/video-source-expected.txt:
        * media/video-source.html: Test <source> element's 'src' attribute and property as well 
        as currentSrc.

        * media/video-src-empty-expected.txt: Removed.
        * media/video-src-empty.html: Removed, the test is no longer valid.

        * media/video-src-none-expected.txt:
        * media/video-src-none.html: Updated to test empty 'src'. Add tests to ensure that an error 
        is fired when load() is called and the 'src' is empty, but not when 'src' is missing.

        * media/video-src.html:
        * media/video-src-expected.txt: Test 'src' attribute and property as well as currentSrc.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@63119 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9bc4a243
2010-07-12 Eric Carlson <eric.carlson@apple.com>
Reviewed by Darin Adler.
Update media element's handling of empty 'src' attribute
https://bugs.webkit.org/show_bug.cgi?id=42001
* fast/dom/URL-attribute-reflection-expected.txt: Update results now that audio, video, and
source return 'non-empty URL'.
* media/video-poster-expected.txt:
* media/video-poster.html: Test empty poster url.
* media/video-source-error-no-candidate-expected.txt:
* media/video-source-error-no-candidate.html: Empty 'src' should fires an error event.
* media/video-source-expected.txt:
* media/video-source.html: Test <source> element's 'src' attribute and property as well
as currentSrc.
* media/video-src-empty-expected.txt: Removed.
* media/video-src-empty.html: Removed, the test is no longer valid.
* media/video-src-none-expected.txt:
* media/video-src-none.html: Updated to test empty 'src'. Add tests to ensure that an error
is fired when load() is called and the 'src' is empty, but not when 'src' is missing.
* media/video-src.html:
* media/video-src-expected.txt: Test 'src' attribute and property as well as currentSrc.
2010-07-12 Eric Seidel <eric@webkit.org>
Reviewed by Adam Barth.
......@@ -19,15 +19,15 @@ FAIL testURLReflection('href', 'link') should be non-empty URL. Was URL.
FAIL testURLReflection('href', 'base') should be URL. Was non-URL.
FAIL testURLReflection('icon', 'command') should be non-empty URL. Was none.
FAIL testURLReflection('manifest', 'html') should be non-empty URL. Was none.
FAIL testURLReflection('poster', 'video') should be non-empty URL. Was URL.
FAIL testURLReflection('src', 'audio') should be non-empty URL. Was URL.
PASS testURLReflection('poster', 'video') is 'non-empty URL'
PASS testURLReflection('src', 'audio') is 'non-empty URL'
FAIL testURLReflection('src', 'embed') should be non-empty URL. Was non-URL.
FAIL testURLReflection('src', 'iframe') should be non-empty URL. Was non-URL.
FAIL testURLReflection('src', 'img') should be non-empty URL. Was URL.
FAIL testURLReflection('src', 'input') should be non-empty URL. Was URL.
FAIL testURLReflection('src', 'script') should be non-empty URL. Was URL.
FAIL testURLReflection('src', 'source') should be non-empty URL. Was URL.
FAIL testURLReflection('src', 'video') should be non-empty URL. Was URL.
PASS testURLReflection('src', 'source') is 'non-empty URL'
PASS testURLReflection('src', 'video') is 'non-empty URL'
FAIL testURLReflection('longDesc', 'img') should be non-empty URL. Was URL.
FAIL testURLReflection('lowsrc', 'img') should be non-empty URL. Was URL.
PASS successfullyParsed is true
......
Set 'poster' to 'content/greenbox.png'.
EXPECTED (video.getAttribute('poster') == 'content/greenbox.png') OK
EXPECTED (relativeURL(video.poster) == 'content/greenbox.png') OK
Set 'poster' to ''.
EXPECTED (video.getAttribute('poster') == '') OK
EXPECTED (relativeURL(video.poster) == '') OK
Set 'poster' to 'content/abe.png'.
EXPECTED (video.getAttribute('poster') == 'content/abe.png') OK
EXPECTED (relativeURL(video.poster) == 'content/abe.png') OK
END OF TEST
<video poster="content/greenbox.png" controls></video>
<script src=video-test.js></script>
<script>
testExpected("video.getAttribute('poster')", "content/greenbox.png");
testExpected("relativeURL(video.poster)", "content/greenbox.png");
video.setAttribute('poster', 'content/abe.png');
testExpected("video.getAttribute('poster')", "content/abe.png");
testExpected("relativeURL(video.poster)", "content/abe.png");
endTest();
</script>
<html>
<head>
<script src=video-test.js></script>
<script>
function testPoster(url)
{
testExpected("video.getAttribute('poster')", url);
testExpected("relativeURL(video.poster)", url);
}
function test()
{
findMediaElement();
consoleWrite("<br><i>Set 'poster' to 'content/greenbox.png'.<" + "/i>");
testPoster('content/greenbox.png');
consoleWrite("<br><i>Set 'poster' to ''.<" + "/i>");
video.setAttribute('poster', '');
testPoster('');
consoleWrite("<br><i>Set 'poster' to 'content/abe.png'.<" + "/i>");
video.setAttribute('poster', 'content/abe.png');
testPoster('content/abe.png');
consoleWrite('');
endTest();
}
</script>
</head>
<body onload="setTimeout(test, 100)">
<video poster="content/greenbox.png" controls></video>
</body>
</html>
Test that 'error' events are fired when no urls are passed to the media engine.
Test that 'error' events are fired from <source> element when it can not be used.
EVENT(error) from <source id='missing-src' src=''> OK
EVENT(error) from <source id='missing-src' src=null> OK
EXPECTED (video.error == 'null') OK
EVENT(error) from <source id='bogus-type' src='content/test.mp4'> OK
......@@ -10,5 +10,8 @@ EXPECTED (video.error == 'null') OK
EVENT(error) from <source id='unsupported-media-query' src='content/test.mp4'> OK
EXPECTED (video.error == 'null') OK
EVENT(error) from <source id='empty-src' src=''> OK
EXPECTED (video.error == 'null') OK
END OF TEST
......@@ -8,6 +8,7 @@
var sources = [];
var errorCount = 0;
var expectedErrorCount = 4;
function errorEvent(evt)
{
......@@ -19,16 +20,17 @@
break;
}
var src = sources[ndx].getAttribute('src') == null ? "null" : "'" + relativeURL(evt.target.src) + "'";
if (sources[ndx] == evt.target)
logResult(true, "EVENT(error) from &lt;source id='<em>" + evt.target.id + "</em>' src='<em>" + relativeURL(evt.target.src) + "</em>'&gt;");
logResult(true, "EVENT(error) from &lt;source id='<em>" + evt.target.id + "</em>' src=<em>" + src + "</em>&gt;");
else
logResult(false, "EVENT(error) from " + evt.target);
testExpected("video.error", null);
if (++errorCount == 3) {
if (++errorCount == expectedErrorCount) {
consoleWrite("");
setTimeout(endTest, 1000);
setTimeout(endTest, 200);
}
}
......@@ -39,7 +41,6 @@
sources = document.getElementsByTagName('source');
findMediaElement();
waitForEvent("loadstart");
}
</script>
</head>
......@@ -50,9 +51,10 @@
<source id=missing-src type="video/blahblah">
<source id=bogus-type src=content/test.mp4 type="video/blahblah">
<source id=unsupported-media-query src=content/test.mp4 media=print>
<source id=empty-src src="" type="video/mp4">
</video>
<p>Test that 'error' events are fired when no urls are passed to the media engine.</p>
<p>Test that 'error' events are fired from &lt;source&gt; element when it can not be used.</p>
</body>
</html>
EVENT(loadstart)
EXPECTED (relativeURL(video.currentSrc) == 'content/test.mp4') OK
EXPECTED (source.getAttribute('src') == 'content/test.mp4') OK
EXPECTED (relativeURL(source.src) == 'content/test.mp4') OK
END OF TEST
<body>
<script src=media-file.js></script>
<script src=video-test.js></script>
<div id=panel></div>
<script>
var panel = document.getElementById("panel");
var mediaFile = findMediaFile("video", "content/test");
panel.innerHTML = "<video controls><source src='" + mediaFile + "'></video>";
</script>
<script>
video = mediaElement = document.getElementsByTagName('video')[0];
waitForEvent("loadstart", function () {
testExpected("relativeURL(video.currentSrc) ", mediaFile);
endTest();
});
</script>
<html>
<head>
<script src=media-file.js></script>
<script src=video-test.js></script>
<script>
function test()
{
var panel = document.getElementById("panel");
var mediaFile = findMediaFile("video", "content/test");
panel.innerHTML = "<video controls><source src='" + mediaFile + "'></video>";
video = mediaElement = document.getElementsByTagName('video')[0];
waitForEvent("loadstart", function () {
testExpected("relativeURL(video.currentSrc) ", mediaFile);
source = document.querySelector('source');
testExpected("source.getAttribute('src')", mediaFile);
testExpected("relativeURL(source.src) ", mediaFile);
endTest();
});
}
</script>
</head>
<body onload="setTimeout(test, 100)">
<div id=panel></div>
</body>
</html>
Empty src attribute defined. Invalid URL and video should error.
EXPECTED (video.error.code == '4') OK
EXPECTED (video.networkState == '4') OK
END OF TEST
<html>
<body>
<p>Empty src attribute defined. Invalid URL and video should error.</p>
<video src="" onerror="errorEvent()" controls></video>
<script src=video-test.js></script>
<script>
function errorEvent()
{
testExpected("video.error.code", MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
testExpected("video.networkState", HTMLMediaElement.NETWORK_NO_SOURCE);
endTest();
}
</script>
</body>
</html>
EVENT(loadstart)
EXPECTED (relativeURL(video.currentSrc) == 'content/test.mp4') OK
EXPECTED (relativeURL(video.src) == 'content/test.mp4') OK
EXPECTED (video.getAttribute('src') == 'content/test.mp4') OK
END OF TEST
No src attribute defined. Video should remain in NETWORK_EMPTY.
EXPECTED (video.error == 'null') OK
EXPECTED (video.networkState == '0') OK
Network state should remain in NETWORK_EMPTY with empty or missing 'src' attribute.
** <video> with no src attribute**
EXPECTED (videos[0].error == 'null') OK
EXPECTED (videos[0].networkState == '0') OK
EXPECTED (videos[0].src == '') OK
** <video> with empty src attribute **
EXPECTED (videos[1].error == 'null') OK
EXPECTED (videos[1].networkState == '0') OK
EXPECTED (videos[1].src == '') OK
Calling load() with empty 'src' should fire 'error' event, set network state to NETWORK_NO_SOURCE, and set error to MEDIA_ERR_SRC_NOT_SUPPORTED.
'error' event:
EXPECTED (state == 'load() with empty 'src'') OK
EXPECTED ([object HTMLVideoElement] == '[object HTMLVideoElement]') OK
EXPECTED (videos[1].error.code == '4') OK
EXPECTED (videos[1].networkState == '4') OK
Calling load() with no 'src' should NOT fire 'error' event, set network state to NETWORK_EMPTY.
EXPECTED (state == 'load() with no 'src''), OBSERVED 'load() with missing 'src'' FAIL
EXPECTED (videos[0].error == 'null') OK
EXPECTED (videos[0].networkState == '0') OK
EXPECTED (videos[0].src == '') OK
END OF TEST
<html>
<body onload="setTimeout(test, 250)">
<p>No src attribute defined. Video should remain in NETWORK_EMPTY.</p>
<video controls></video>
<head>
<script src=video-test.js></script>
<script>
function test()
var state;
function someTimeLater()
{
testExpected("video.error", null);
testExpected("video.networkState", HTMLMediaElement.NETWORK_EMPTY);
testExpected("state", "load() with no 'src'");
testExpected("videos[0].error", null);
testExpected("videos[0].networkState", HTMLMediaElement.NETWORK_EMPTY);
testExpected("videos[0].src", "");
endTest();
}
function errorEvent()
{
consoleWrite("'error' event:");
testExpected("state", "load() with empty 'src'");
testExpected(event.target, videos[1]);
testExpected("videos[1].error.code", MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
testExpected("videos[1].networkState", HTMLMediaElement.NETWORK_NO_SOURCE);
consoleWrite("<i>Calling load() with no 'src' should NOT fire 'error' event, set network state to NETWORK_EMPTY.<" + "/i>");
state = "load() with missing 'src'";
videos[0].load();
setTimeout(someTimeLater, 100) ;
}
function test()
{
videos = document.querySelectorAll('video');
consoleWrite("<br><i>Network state should remain in NETWORK_EMPTY with empty or missing 'src' attribute.<" + "/i>");
consoleWrite("** &lt;video&gt; with no src attribute**");
testExpected("videos[0].error", null);
testExpected("videos[0].networkState", HTMLMediaElement.NETWORK_EMPTY);
testExpected("videos[0].src", "");
consoleWrite("** &lt;video&gt; with empty src attribute **");
testExpected("videos[1].error", null);
testExpected("videos[1].networkState", HTMLMediaElement.NETWORK_EMPTY);
testExpected("videos[1].src", "");
consoleWrite("<br><" + "i>Calling load() with empty 'src' should fire 'error' event, set network state to NETWORK_NO_SOURCE, and set error to MEDIA_ERR_SRC_NOT_SUPPORTED.<" + "/i>");
state = "load() with empty 'src'";
videos[1].load();
}
</script>
</head>
<body onload="setTimeout(test, 100)">
<video width=320 height=60 controls onerror="errorEvent()"></video>
<br>
<video width=320 height=60 controls src="" onerror="errorEvent()"></video>
</body>
</html>
<body>
<script src=media-file.js></script>
<script src=video-test.js></script>
<video controls></video>
<html>
<head>
<script src=media-file.js></script>
<script src=video-test.js></script>
<script>
<script>
video = mediaElement = document.getElementsByTagName('video')[0];
var mediaFile = findMediaFile("video", "content/test");
function test()
{
video = mediaElement = document.getElementsByTagName('video')[0];
var mediaFile = findMediaFile("video", "content/test");
waitForEvent("loadstart", function () {
testExpected("relativeURL(video.currentSrc) ", mediaFile);
testExpected("relativeURL(video.src) ", mediaFile);
testExpected("video.getAttribute('src')", mediaFile);
endTest();
});
video.src = mediaFile;
}
</script>
</head>
waitForEvent("loadstart", function () {
testExpected("relativeURL(video.currentSrc) ", mediaFile);
endTest();
});
<body onload="setTimeout(test, 100)">
<video controls></video>
</body>
</html>
video.src = mediaFile;
</script>
2010-07-12 Eric Carlson <eric.carlson@apple.com>
Reviewed by Darin Adler.
Update media element's handling of empty 'src' attribute
https://bugs.webkit.org/show_bug.cgi?id=42001
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::src): Return getNonEmptyURLAttribute().
(WebCore::HTMLMediaElement::selectMediaResource): Call noneSupported() for empty 'src'.
(WebCore::HTMLMediaElement::selectNextSourceChild): Use getNonEmptyURLAttribute() to convert
'src' to URL instead of document()->completeURL(). Don't consider a <source> with an empty 'src'.
* html/HTMLMediaElement.idl: Add 'NonEmpty' option to 'src' attribute.
* html/HTMLSourceElement.cpp:
(WebCore::HTMLSourceElement::src): Return getNonEmptyURLAttribute().
(WebCore::HTMLSourceElement::isURLAttribute): New, 'src' is a URL attribute.
* html/HTMLSourceElement.h:
* html/HTMLSourceElement.idl: Add 'NonEmpty' option to 'src' attribute.
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::parseMappedAttribute): Use getNonEmptyURLAttribute() to convert
'poster' to URL instead of document()->completeURL().
* html/HTMLVideoElement.idl: Add 'NonEmpty' option to 'poster' attribute.
2010-07-12 Martin Robinson <mrobinson@igalia.com>
Reviewed by Xan Lopez.
......@@ -424,7 +424,7 @@ PassRefPtr<MediaError> HTMLMediaElement::error() const
KURL HTMLMediaElement::src() const
{
return document()->completeURL(getAttribute(srcAttr));
return getNonEmptyURLAttribute(srcAttr);
}
void HTMLMediaElement::setSrc(const String& url)
......@@ -545,14 +545,16 @@ void HTMLMediaElement::loadInternal()
void HTMLMediaElement::selectMediaResource()
{
enum Mode { attribute, children };
Mode mode = attribute;
// 1 - Set the networkState to NETWORK_NO_SOURCE
m_networkState = NETWORK_NO_SOURCE;
// 2 - Asynchronously await a stable state.
// 3 - ... the media element has neither a src attribute ...
String mediaSrc = getAttribute(srcAttr);
if (!mediaSrc) {
if (!hasAttribute(srcAttr)) {
// ... nor a source element child: ...
Node* node;
for (node = firstChild(); node; node = node->nextSibling()) {
......@@ -568,6 +570,8 @@ void HTMLMediaElement::selectMediaResource()
ASSERT(!m_delayingTheLoadEvent);
return;
}
mode = children;
}
// 4
......@@ -577,11 +581,17 @@ void HTMLMediaElement::selectMediaResource()
// 5
scheduleEvent(eventNames().loadstartEvent);
// 6 - If the media element has a src attribute, then run these substeps
ContentType contentType("");
if (!mediaSrc.isNull()) {
KURL mediaURL = document()->completeURL(mediaSrc);
// 6 - If mode is attribute, then run these substeps
if (mode == attribute) {
// 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();
return;
}
if (isSafeToLoadURL(mediaURL, Complain) && dispatchBeforeLoadEvent(mediaURL.string())) {
ContentType contentType("");
m_loadState = LoadingFromSrcAttr;
loadResource(mediaURL, contentType);
} else
......@@ -1468,9 +1478,12 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType *contentType, InvalidSo
}
HTMLSourceElement* source = static_cast<HTMLSourceElement*>(node);
if (!source->hasAttribute(srcAttr))
goto check_again;
// If candidate does not have a src attribute, or if its src attribute's value is the empty string ... jump down to the failed step below
mediaURL = source->getNonEmptyURLAttribute(srcAttr);
if (mediaURL.isEmpty())
goto check_again;
if (source->hasAttribute(mediaAttr)) {
MediaQueryEvaluator screenEval("screen", document()->frame(), renderer() ? renderer()->style() : 0);
RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(source->media());
......@@ -1484,7 +1497,6 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType *contentType, InvalidSo
}
// Is it safe to load this url?
mediaURL = source->src();
if (!isSafeToLoadURL(mediaURL, actionIfInvalid) || !dispatchBeforeLoadEvent(mediaURL.string()))
goto check_again;
......
......@@ -30,7 +30,7 @@ interface [Conditional=VIDEO] HTMLMediaElement : HTMLElement {
readonly attribute MediaError error;
// network state
attribute [Reflect,URL] DOMString src;
attribute [Reflect,NonEmpty,URL] DOMString src;
readonly attribute DOMString currentSrc;
const unsigned short NETWORK_EMPTY = 0;
......
......@@ -64,7 +64,7 @@ void HTMLSourceElement::insertedIntoDocument()
KURL HTMLSourceElement::src() const
{
return document()->completeURL(getAttribute(srcAttr));
return getNonEmptyURLAttribute(srcAttr);
}
void HTMLSourceElement::setSrc(const String& url)
......@@ -110,5 +110,11 @@ void HTMLSourceElement::errorEventTimerFired(Timer<HTMLSourceElement>*)
dispatchEvent(Event::create(eventNames().errorEvent, false, true));
}
bool HTMLSourceElement::isURLAttribute(Attribute* attribute) const
{
return attribute->name() == srcAttr;
}
}
#endif
......@@ -54,7 +54,8 @@ private:
virtual int tagPriority() const { return 0; }
virtual void insertedIntoDocument();
virtual bool isURLAttribute(Attribute*) const;
void errorEventTimerFired(Timer<HTMLSourceElement>*);
Timer<HTMLSourceElement> m_errorEventTimer;
......
......@@ -25,7 +25,7 @@
module html {
interface [Conditional=VIDEO] HTMLSourceElement : HTMLElement {
attribute DOMString src;
attribute [Reflect,NonEmpty,URL] DOMString src;
attribute DOMString type;
attribute DOMString media;
};
......
......@@ -101,7 +101,7 @@ void HTMLVideoElement::parseMappedAttribute(Attribute* attr)
const QualifiedName& attrName = attr->name();
if (attrName == posterAttr) {
m_posterURL = document()->completeURL(attr->value());
m_posterURL = getNonEmptyURLAttribute(posterAttr);
updatePosterImage();
if (m_shouldDisplayPosterImage) {
#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
......
......@@ -32,7 +32,7 @@ module html {
attribute [Reflect] unsigned long height;
readonly attribute unsigned long videoWidth;
readonly attribute unsigned long videoHeight;
attribute [Reflect,URL] DOMString poster;
attribute [Reflect,NonEmpty,URL] DOMString poster;
readonly attribute boolean webkitSupportsFullscreen;
readonly attribute boolean webkitDisplayingFullscreen;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment