WebCore/ChangeLog

 12009-08-19 Eric Carlson <eric.carlson@apple.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 HTML5 media elements must fire 'loadend' progress event
 6 https://bugs.webkit.org/show_bug.cgi?id=28419
 7
 8 * dom/EventNames.h:
 9 Define loadend.
 10
 11 * html/HTMLMediaElement.cpp:
 12 (WebCore::HTMLMediaElement::parseMappedAttribute):
 13 Deal with onloadend.
 14 (WebCore::HTMLMediaElement::loadInternal):
 15 Post 'loadend' immediately after 'abort'.
 16 (WebCore::HTMLMediaElement::noneSupported):
 17 Post 'loadend' immediately after 'error'.
 18 (WebCore::HTMLMediaElement::mediaEngineError):
 19 Ditto.
 20 (WebCore::HTMLMediaElement::setNetworkState):
 21 Post 'loadend' immediately after 'load'.
 22 (WebCore::HTMLMediaElement::userCancelledLoad):
 23 Post 'loadend' immediately after 'abort'.
 24
1252009-08-19 Anders Carlsson <andersca@apple.com>
226
327 Reviewed by Darin Adler.
47539

WebCore/dom/EventNames.h

@@namespace WebCore {
6161 macro(keypress) \
6262 macro(keyup) \
6363 macro(load) \
 64 macro(loadend) \
6465 macro(loadstart) \
6566 macro(message) \
6667 macro(mousedown) \
47525

WebCore/html/HTMLMediaElement.cpp

@@void HTMLMediaElement::parseMappedAttrib
179179 setAttributeEventListener(eventNames().loadeddataEvent, createAttributeEventListener(this, attr));
180180 else if (attrName == onloadedmetadataAttr)
181181 setAttributeEventListener(eventNames().loadedmetadataEvent, createAttributeEventListener(this, attr));
 182 else if (attrName == onloadendAttr)
 183 setAttributeEventListener(eventNames().loadendEvent, createAttributeEventListener(this, attr));
182184 else if (attrName == onloadstartAttr)
183185 setAttributeEventListener(eventNames().loadstartEvent, createAttributeEventListener(this, attr));
184186 else if (attrName == onpauseAttr)

@@void HTMLMediaElement::loadInternal()
432434 // one of the task queues, then remove those tasks.
433435 cancelPendingEventsAndCallbacks();
434436
435  // 4 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, set the
436  // error attribute to a new MediaError object whose code attribute is set to MEDIA_ERR_ABORTED,
437  // and fire a progress event called abort at the media element.
 437 // 4 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, set
 438 // the error attribute to a new MediaError object whose code attribute is set to
 439 // MEDIA_ERR_ABORTED, fire a progress event called abort at the media element, in the
 440 // context of the fetching process that is in progress for the element, and fire a progress
 441 // event called loadend at the media element, in the context of the same fetching process.
438442 if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) {
439443 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED);
440 
441  // fire synchronous 'abort'
 444
 445 // fire synchronous 'abort' and 'loadend'
442446 bool totalKnown = m_player && m_player->totalBytesKnown();
443447 unsigned loaded = m_player ? m_player->bytesLoaded() : 0;
444448 unsigned total = m_player ? m_player->totalBytes() : 0;
445449 dispatchProgressEvent(eventNames().abortEvent, totalKnown, loaded, total);
 450 dispatchProgressEvent(eventNames().loadendEvent, totalKnown, loaded, total);
446451 }
447 
448  // 5
 452
 453 // 5
449454 m_error = 0;
450455 m_autoplaying = true;
451456 m_playedTimeRanges = TimeRanges::create();

@@void HTMLMediaElement::loadInternal()
453458
454459 // 6
455460 setPlaybackRate(defaultPlaybackRate());
456 
 461
457462 // 7
458463 if (m_networkState != NETWORK_EMPTY) {
459464 m_networkState = NETWORK_EMPTY;

@@void HTMLMediaElement::loadInternal()
467472 }
468473 dispatchEvent(eventNames().emptiedEvent, false, true);
469474 }
470 
 475
471476 selectMediaResource();
472477 m_processingLoad = false;
473478}

@@void HTMLMediaElement::noneSupported()
592597 m_loadState = WaitingForSource;
593598 m_currentSourceNode = 0;
594599
595  // 3 - Reaching this step indicates that either the URL failed to resolve, or the media
596  // resource failed to load. Set the error attribute to a new MediaError object whose
 600 // 4 - Reaching this step indicates that either the URL failed to resolve, or the media
 601 // resource failed to load. Set the error attribute to a new MediaError object whose
597602 // code attribute is set to MEDIA_ERR_SRC_NOT_SUPPORTED.
598603 m_error = MediaError::create(MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
599604
600  // 4- Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
 605 // 5 - Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
601606 m_networkState = NETWORK_NO_SOURCE;
602607
603  // 5 - Queue a task to fire a progress event called error at the media element.
604  scheduleProgressEvent(eventNames().errorEvent);
 608 // 6 - Queue a task to fire a progress event called error at the media element, in
 609 // the context of the fetching process that was used to try to obtain the media
 610 // resource in the resource fetch algorithm.
 611 scheduleProgressEvent(eventNames().errorEvent);
 612
 613 // 7 - Queue a task to fire a progress event called loadend at the media element, in
 614 // the context of the fetching process that was used to try to obtain the media
 615 // resource in the resource fetch algorithm.
 616 scheduleProgressEvent(eventNames().loadendEvent);
605617
606  // 6 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
 618 // 8 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
607619 m_delayingTheLoadEvent = false;
608620
609  // Abort these steps. Until the load() method is invoked, the element won't attempt to load another resource.
610 
 621 // 9 -Abort these steps. Until the load() method is invoked, the element won't attempt to load another resource.
 622
611623 if (isVideo())
612624 static_cast<HTMLVideoElement*>(this)->updatePosterImage();
613625 if (renderer())

@@void HTMLMediaElement::mediaEngineError(
624636 // set to MEDIA_ERR_NETWORK/MEDIA_ERR_DECODE.
625637 m_error = err;
626638
627  // 3 - Queue a task to fire a progress event called error at the media element.
628  scheduleProgressEvent(eventNames().errorEvent);
 639 // 3 - Queue a task to fire a progress event called error at the media element, in
 640 // the context of the fetching process started by this instance of this algorithm.
 641 scheduleProgressEvent(eventNames().errorEvent);
 642
 643 // 4 - Queue a task to fire a progress event called loadend at the media element, in
 644 // the context of the fetching process started by this instance of this algorithm.
 645 scheduleProgressEvent(eventNames().loadendEvent);
629646
630  // 3 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
 647 // 5 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
631648 // task to fire a simple event called emptied at the element.
632649 m_networkState = NETWORK_EMPTY;
633650 scheduleEvent(eventNames().emptiedEvent);
634651
635  // 4 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
 652 // 6 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
636653 m_delayingTheLoadEvent = false;
637654
638  // 5 - Abort the overall resource selection algorithm.
 655 // 7 - Abort the overall resource selection algorithm.
639656 m_currentSourceNode = 0;
640 
641657}
642658
643659void HTMLMediaElement::cancelPendingEventsAndCallbacks()

@@void HTMLMediaElement::setNetworkState(M
722738 if (static_cast<ReadyState>(currentState) != m_readyState)
723739 setReadyState(currentState);
724740
725  scheduleProgressEvent(eventNames().loadEvent);
 741 scheduleProgressEvent(eventNames().loadEvent);
 742 scheduleProgressEvent(eventNames().loadendEvent);
726743 }
727744 }
728745}

@@void HTMLMediaElement::userCancelledLoad
15621579 // 2 - Set the error attribute to a new MediaError object whose code attribute is set to MEDIA_ERR_ABORT.
15631580 m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED);
15641581
1565  // 3 - Queue a task to fire a progress event called abort at the media element.
 1582 // 3 - Queue a task to fire a progress event called abort at the media element, in the context
 1583 // of the fetching process started by this instance of this algorithm.
15661584 scheduleProgressEvent(eventNames().abortEvent);
15671585
1568  // 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
1569  // element's networkState attribute to the NETWORK_EMPTY value and queue a task to fire a
1570  // simple event called emptied at the element. Otherwise, set set the element's networkState
 1586 // 4 - Queue a task to fire a progress event called loadend at the media element, in the context
 1587 // of the fetching process started by this instance of this algorithm.
 1588 scheduleProgressEvent(eventNames().loadendEvent);
 1589
 1590 // 5 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
 1591 // element's networkState attribute to the NETWORK_EMPTY value and queue a task to fire a
 1592 // simple event called emptied at the element. Otherwise, set set the element's networkState
15711593 // attribute to the NETWORK_IDLE value.
15721594 if (m_networkState >= NETWORK_LOADING) {
15731595 m_networkState = NETWORK_EMPTY;

@@void HTMLMediaElement::userCancelledLoad
15751597 scheduleEvent(eventNames().emptiedEvent);
15761598 }
15771599
1578  // 5 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
 1600 // 6 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
15791601 m_delayingTheLoadEvent = false;
 1602
 1603 // 7 - Abort the overall resource selection algorithm.
 1604 m_currentSourceNode = 0;
15801605 }
15811606}
15821607

@@void HTMLMediaElement::documentDidBecome
16081633 ExceptionCode ec;
16091634 load(ec);
16101635 }
1611 
 1636
16121637 if (renderer())
16131638 renderer()->updateFromElement();
16141639}
47525

LayoutTests/ChangeLog

 12009-08-19 Eric Carlson <eric.carlson@apple.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 HTML5 media elements must fire 'loadend' progress event
 6 https://bugs.webkit.org/show_bug.cgi?id=28419
 7
 8 Add 'loadend' to existing tests.
 9
 10 * media/event-attributes-expected.txt:
 11 * media/event-attributes.html:
 12 * media/media-load-event-expected.txt:
 13 * media/media-load-event.html:
 14 * media/progress-event-at-least-one-expected.txt:
 15 * media/progress-event-at-least-one.html:
 16
1172009-08-19 Ryosuke Niwa <rniwa@webkit.org>
218
319 Reviewed by Eric Seidel.
47539

LayoutTests/media/event-attributes-expected.txt

@@EVENT(loadeddata)
55EVENT(canplay)
66EVENT(canplaythrough)
77EVENT(load)
 8EVENT(loadend)
89
 10*** starting playback
911RUN(video.play())
1012EVENT(play)
1113EVENT(playing)
1214
 15*** changing playback rate
1316RUN(video.playbackRate = 2)
1417EVENT(ratechange)
1518
 19*** setting volume
1620RUN(video.volume = 0.5)
1721EVENT(volumechange)
1822
 23*** pausing playback
1924RUN(video.pause())
2025EVENT(pause)
2126
 27*** seeking
2228RUN(video.currentTime = 5.6)
2329EVENT(seeked)
2430
 31*** beginning playback
2532RUN(video.play())
2633EVENT(ratechange)
2734EVENT(play)
2835EVENT(playing)
2936EVENT(ended)
3037
 38*** played to end, setting 'src' to an invalid movie
3139RUN(video.src = 'content/garbage.mp4')
3240RUN(video.load())
3341EVENT(emptied)
47525

LayoutTests/media/event-attributes.html

1515 consoleWrite("EVENT(" + event.type + ")");
1616 switch (event.type)
1717 {
18  case "load":
19  consoleWrite("");
 18 case "loadend":
 19 consoleWrite("<br>*** starting playback");
2020 run("video.play()");
2121 break;
2222 case "playing":
2323 if (++playingCount == 1) {
24  consoleWrite("");
 24 consoleWrite("<br>*** changing playback rate");
2525 run("video.playbackRate = 2");
2626 }
2727 break;
2828 case "ratechange":
2929 if (++ratechangeCount == 1) {
30  consoleWrite("");
 30 consoleWrite("<br>*** setting volume");
3131 run("video.volume = 0.5");
3232 }
3333 break;
3434 case "volumechange":
35  consoleWrite("");
 35 consoleWrite("<br>*** pausing playback");
3636 run("video.pause()");
3737 break;
3838 case "pause":
39  consoleWrite("");
 39 consoleWrite("<br>*** seeking");
4040 run("video.currentTime = 5.6");
4141 break;
4242 case "seeked":
43  consoleWrite("");
 43 consoleWrite("<br>*** beginning playback");
4444 run("video.play()");
4545 break;
4646 case "ended":
47  consoleWrite("");
 47 consoleWrite("<br>*** played to end, setting 'src' to an invalid movie");
4848 run("video.src = 'content/garbage.mp4'");
4949 run("video.load()");
5050 break;

5858 default:
5959 break;
6060 }
61 
6261 }
6362
6463 function start()

8382 onloadeddata="eventHandler()"
8483 onloadedmetadata="eventHandler()"
8584 onloadstart="eventHandler()"
 85 onloadend="eventHandler()"
8686 onpause="eventHandler()"
8787 onplay="eventHandler()"
8888 onplaying="eventHandler()"
47525

LayoutTests/media/media-load-event-expected.txt

@@EVENT(loadstart)
88EVENT(durationchange)
99EVENT(loadeddata)
1010EVENT(load)
 11EVENT(loadend)
1112
1213RUN(document.getElementById('parent').appendChild(mediaElement))
1314RUN(mediaElement.play())
1415
1516EVENT(play)
1617EVENT(playing)
 18
1719END OF TEST
1820
47525

LayoutTests/media/media-load-event.html

44
55 <script>
66
7  function loaded()
 7 function playing()
88 {
9  consoleWrite("EVENT(load)");
 9 consoleWrite("EVENT(playing)<br>");
 10 endTest();
 11 }
 12
 13 function loadend()
 14 {
 15 consoleWrite("EVENT(loadend)");
1016 consoleWrite("");
1117 run("document.getElementById('parent').appendChild(mediaElement)");
1218 run("mediaElement.play()");
13  window.setTimeout(endTest, 250);
1419 consoleWrite("");
1520 }
1621

1823 {
1924 run("mediaElement = document.createElement('audio')");
2025
21  mediaElement.onload = loaded;
 26 mediaElement.setAttribute('onloadend', "loadend()");
 27 mediaElement.setAttribute('onplaying', "playing()");
2228
2329 waitForEvent("loadstart");
 30 waitForEvent("load");
2431 waitForEvent("waiting");
2532 waitForEvent("ratechange");
2633 waitForEvent("durationchange");
2734 waitForEvent("pause");
2835 waitForEvent("play");
29  waitForEvent("playing");
3036 waitForEvent('loadeddata');
3137
3238 run("mediaElement.src = 'content/test.wav'");
47525

LayoutTests/media/progress-event-at-least-one-expected.txt

@@EVENT(loadstart)
88EVENT(durationchange)
99EVENT(loadedmetadata)
1010EVENT(loadeddata)
11 EVENT(load)
 11EVENT(loadend)
1212EXPECTED (progressEventCount >= '1') OK
1313END OF TEST
1414
47525

LayoutTests/media/progress-event-at-least-one.html

1717 return;
1818 }
1919
20  function loaded()
 20 function loadend()
2121 {
22  consoleWrite("EVENT(load)");
 22 consoleWrite("EVENT(loadend)");
2323
2424 testExpected('progressEventCount', 1, '>=');
2525 endTest();

2929 {
3030 run("mediaElement = document.createElement('audio')");
3131
32  mediaElement.setAttribute('onload', "loaded()");
 32 mediaElement.setAttribute('onloadend', "loadend()");
3333 mediaElement.setAttribute('onprogress', "progress()");
3434
3535 waitForEvent("loadstart");
 36 waitForEvent("loadend");
 37 waitForEvent("loaded");
3638 waitForEvent("waiting");
3739 waitForEvent("ratechange");
3840 waitForEvent("durationchange");
47525