diff options
author | amogh.bihani@samsung.com <amogh.bihani@samsung.com> | 2014-09-10 14:49:06 +0000 |
---|---|---|
committer | amogh.bihani@samsung.com <amogh.bihani@samsung.com> | 2014-09-10 14:49:06 +0000 |
commit | ffd973612f29572c00ea4a1a7530685486cc9c55 (patch) | |
tree | 17b29806bdc3d9ff556aba199f3138fc6b96a110 | |
parent | 031776d9b2b34b468a78304c88f26a24866d4f66 (diff) | |
download | chromium_src-ffd973612f29572c00ea4a1a7530685486cc9c55.zip chromium_src-ffd973612f29572c00ea4a1a7530685486cc9c55.tar.gz chromium_src-ffd973612f29572c00ea4a1a7530685486cc9c55.tar.bz2 |
Allow HTMLMediaElement.currentTime to be set before the transition to HAVE_METADATA
Spec now allows currentTime to be set when the readyState is still HAVE_NOTHING.
This patch modifies the behaviour in accordance to the spec. The default playback
start position is set to the new currentTime and the resource plays from that point
once it is loaded.
http://www.whatwg.org/specs/web-apps/current-work/#dom-media-currenttime
BUG=399314
Review URL: https://codereview.chromium.org/517593003
git-svn-id: svn://svn.chromium.org/blink/trunk@181736 bbb929c8-8fbe-4397-9dbb-9b2b20218538
-rw-r--r-- | third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata-expected.txt | 10 | ||||
-rw-r--r-- | third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata.html | 32 | ||||
-rw-r--r-- | third_party/WebKit/LayoutTests/media/video-seek-no-src-exception-expected.txt | 7 | ||||
-rw-r--r-- | third_party/WebKit/LayoutTests/media/video-seek-no-src-expected.txt | 7 | ||||
-rw-r--r-- | third_party/WebKit/LayoutTests/media/video-seek-no-src.html (renamed from third_party/WebKit/LayoutTests/media/video-seek-no-src-exception.html) | 11 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/HTMLMediaElement.cpp | 67 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/HTMLMediaElement.h | 5 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/MediaController.cpp | 6 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/MediaController.h | 2 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/MediaController.idl | 2 | ||||
-rw-r--r-- | third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp | 2 |
11 files changed, 105 insertions, 46 deletions
diff --git a/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata-expected.txt b/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata-expected.txt new file mode 100644 index 0000000..32ee4e3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata-expected.txt @@ -0,0 +1,10 @@ +Test currentTime values when setting while HAVE_NOTHING. + + +EXPECTED (video.currentTime == '0') OK +EXPECTED (video.currentTime == '1') OK +EVENT(loadedmetadata) +EXPECTED (video.currentTime == '1') OK +EVENT(seeked) +END OF TEST + diff --git a/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata.html b/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata.html new file mode 100644 index 0000000..3e675ce --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-currentTime-before-have-metadata.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + <head> + <script src=media-file.js></script> + <script src=video-test.js></script> + <script> + function onWindowLoad(e) + { + video = document.getElementById('video'); + + video.src = findMediaFile("video", "content/test"); + testExpected("video.currentTime", 0); + video.currentTime = 1; + testExpected("video.currentTime", 1); + + waitForEvent('loadedmetadata', function() + { + testExpected("video.currentTime", 1); + }); + + waitForEventAndEnd('seeked'); + } + + window.addEventListener('load', onWindowLoad, false); + </script> + </head> + <body> + <video controls id="video"></video> + <p>Test currentTime values when setting while HAVE_NOTHING.</p> + <br/> + </body> +</html> diff --git a/third_party/WebKit/LayoutTests/media/video-seek-no-src-exception-expected.txt b/third_party/WebKit/LayoutTests/media/video-seek-no-src-exception-expected.txt deleted file mode 100644 index 2f1a553..0000000 --- a/third_party/WebKit/LayoutTests/media/video-seek-no-src-exception-expected.txt +++ /dev/null @@ -1,7 +0,0 @@ -Test that seeking video with no 'src' attribute throws an INVALID_STATE_ERR exception. - -EXPECTED (video.networkState == '0') OK -EXPECTED (video.readyState == '0') OK -TEST(video.currentTime = 1.1) THROWS(DOMException.INVALID_STATE_ERR: Failed to set the 'currentTime' property on 'HTMLMediaElement': The element's readyState is HAVE_NOTHING.) OK -END OF TEST - diff --git a/third_party/WebKit/LayoutTests/media/video-seek-no-src-expected.txt b/third_party/WebKit/LayoutTests/media/video-seek-no-src-expected.txt new file mode 100644 index 0000000..9dc392b --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/video-seek-no-src-expected.txt @@ -0,0 +1,7 @@ +Test that seeking video with no 'src' attribute sets default playback start position to that time. + +EXPECTED (video.networkState == '0') OK +EXPECTED (video.readyState == '0') OK +EXPECTED (video.currentTime == '1.1') OK +END OF TEST + diff --git a/third_party/WebKit/LayoutTests/media/video-seek-no-src-exception.html b/third_party/WebKit/LayoutTests/media/video-seek-no-src.html index 4eccf91..c70a8c8 100644 --- a/third_party/WebKit/LayoutTests/media/video-seek-no-src-exception.html +++ b/third_party/WebKit/LayoutTests/media/video-seek-no-src.html @@ -2,16 +2,17 @@ <body> <video loop controls></video> - - <p>Test that seeking video with no 'src' attribute throws an INVALID_STATE_ERR exception.</p> + + <p>Test that seeking video with no 'src' attribute sets default playback start position to that time.</p> <script src=video-test.js></script> <script> testExpected("video.networkState", HTMLMediaElement.NETWORK_EMPTY); testExpected("video.readyState", HTMLMediaElement.HAVE_NOTHING); - testDOMException("video.currentTime = 1.1", "DOMException.INVALID_STATE_ERR"); - setTimeout(endTest, 200) + video.currentTime = 1.1; + testExpected("video.currentTime", 1.1); + endTest(); </script> - + </body> </html> diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index 2a8bc6b..297200a 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp @@ -324,6 +324,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum , m_duration(std::numeric_limits<double>::quiet_NaN()) , m_lastTimeUpdateEventWallTime(0) , m_lastTimeUpdateEventMovieTime(std::numeric_limits<double>::max()) + , m_defaultPlaybackStartPosition(0) , m_loadState(WaitingForSource) , m_deferredLoadState(NotDeferred) , m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired) @@ -1817,6 +1818,11 @@ void HTMLMediaElement::setReadyState(ReadyState state) if (isHTMLVideoElement()) scheduleEvent(EventTypeNames::resize); scheduleEvent(EventTypeNames::loadedmetadata); + + if (m_defaultPlaybackStartPosition > 0) + seek(m_defaultPlaybackStartPosition); + + m_defaultPlaybackStartPosition = 0; if (hasMediaControls()) mediaControls()->reset(); if (renderer()) @@ -1917,17 +1923,13 @@ void HTMLMediaElement::prepareToPlay() startDeferredLoad(); } -void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) +void HTMLMediaElement::seek(double time) { WTF_LOG(Media, "HTMLMediaElement::seek(%p, %f)", this, time); - // 4.8.10.9 Seeking - - // 1 - If the media element's readyState is HAVE_NOTHING, then raise an InvalidStateError exception. - if (m_readyState == HAVE_NOTHING) { - exceptionState.throwDOMException(InvalidStateError, "The element's readyState is HAVE_NOTHING."); + // 2 - If the media element's readyState is HAVE_NOTHING, abort these steps. + if (m_readyState == HAVE_NOTHING) return; - } // If the media engine has been told to postpone loading data, let it go ahead now. if (m_preload < MediaPlayer::Auto && m_readyState < HAVE_FUTURE_DATA) @@ -1935,23 +1937,24 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) // Get the current time before setting m_seeking, m_lastSeekTime is returned once it is set. refreshCachedTime(); - double now = currentTime(); + // This is needed to avoid getting default playback start position from currentTime(). + double now = m_cachedTime; - // 2 - If the element's seeking IDL attribute is true, then another instance of this algorithm is + // 3 - If the element's seeking IDL attribute is true, then another instance of this algorithm is // already running. Abort that other instance of the algorithm without waiting for the step that // it is running to complete. // Nothing specific to be done here. - // 3 - Set the seeking IDL attribute to true. + // 4 - Set the seeking IDL attribute to true. // The flag will be cleared when the engine tells us the time has actually changed. bool previousSeekStillPending = m_seeking; m_seeking = true; - // 5 - If the new playback position is later than the end of the media resource, then let it be the end + // 6 - If the new playback position is later than the end of the media resource, then let it be the end // of the media resource instead. time = std::min(time, duration()); - // 6 - If the new playback position is less than the earliest possible position, let it be that position instead. + // 7 - If the new playback position is less than the earliest possible position, let it be that position instead. time = std::max(time, 0.0); // Ask the media engine for the time value in the movie's time scale before comparing with current time. This @@ -1965,7 +1968,7 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) time = mediaTime; } - // 7 - If the (possibly now changed) new playback position is not in one of the ranges given in the + // 8 - If the (possibly now changed) new playback position is not in one of the ranges given in the // seekable attribute, then let it be the position in one of the ranges given in the seekable attribute // that is the nearest to the new playback position. ... If there are no ranges given in the seekable // attribute then set the seeking IDL attribute to false and abort these steps. @@ -1998,13 +2001,13 @@ void HTMLMediaElement::seek(double time, ExceptionState& exceptionState) m_lastSeekTime = time; m_sentEndEvent = false; - // 8 - Queue a task to fire a simple event named seeking at the element. + // 10 - Queue a task to fire a simple event named seeking at the element. scheduleEvent(EventTypeNames::seeking); - // 9 - Set the current playback position to the given new playback position + // 11 - Set the current playback position to the given new playback position. webMediaPlayer()->seek(time); - // 10-14 are handled, if necessary, when the engine signals a readystate change or otherwise + // 14-17 are handled, if necessary, when the engine signals a readystate change or otherwise // satisfies seek completion and signals a time change. } @@ -2012,14 +2015,13 @@ void HTMLMediaElement::finishSeek() { WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); - // 4.8.10.9 Seeking completion - // 12 - Set the seeking IDL attribute to false. + // 14 - Set the seeking IDL attribute to false. m_seeking = false; - // 13 - Queue a task to fire a simple event named timeupdate at the element. + // 16 - Queue a task to fire a simple event named timeupdate at the element. scheduleTimeupdateEvent(false); - // 14 - Queue a task to fire a simple event named seeked at the element. + // 17 - Queue a task to fire a simple event named seeked at the element. scheduleEvent(EventTypeNames::seeked); setDisplayMode(Video); @@ -2057,6 +2059,9 @@ void HTMLMediaElement::invalidateCachedTime() // playback state double HTMLMediaElement::currentTime() const { + if (m_defaultPlaybackStartPosition) + return m_defaultPlaybackStartPosition; + if (m_readyState == HAVE_NOTHING) return 0; @@ -2086,7 +2091,15 @@ void HTMLMediaElement::setCurrentTime(double time, ExceptionState& exceptionStat exceptionState.throwDOMException(InvalidStateError, "The element is slaved to a MediaController."); return; } - seek(time, exceptionState); + + // If the media element's readyState is HAVE_NOTHING, then set the default + // playback start position to that time. + if (m_readyState == HAVE_NOTHING) { + m_defaultPlaybackStartPosition = time; + return; + } + + seek(time); } double HTMLMediaElement::duration() const @@ -2225,7 +2238,7 @@ void HTMLMediaElement::playInternal() scheduleDelayedAction(LoadMediaResource); if (endedPlayback()) - seek(0, IGNORE_EXCEPTION); + seek(0); if (m_mediaController) m_mediaController->bringElementUpToSpeed(this); @@ -3083,7 +3096,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged() if (loop() && !m_mediaController) { m_sentEndEvent = false; // then seek to the earliest possible position of the media resource and abort these steps. - seek(0, IGNORE_EXCEPTION); + seek(0); } else { // If the media element does not have a current media controller, and the media element // has still ended playback, and the direction of playback is still forwards, and paused @@ -3137,7 +3150,7 @@ void HTMLMediaElement::durationChanged(double duration, bool requestSeek) renderer()->updateFromElement(); if (requestSeek) - seek(duration, IGNORE_EXCEPTION); + seek(duration); } void HTMLMediaElement::mediaPlayerPlaybackStateChanged() @@ -3168,10 +3181,10 @@ void HTMLMediaElement::mediaPlayerRequestSeek(double time) { // The player is the source of this seek request. if (m_mediaController) { - m_mediaController->setCurrentTime(time, IGNORE_EXCEPTION); + m_mediaController->setCurrentTime(time); return; } - setCurrentTime(time, IGNORE_EXCEPTION); + setCurrentTime(time, ASSERT_NO_EXCEPTION); } // MediaPlayerPresentation methods @@ -3870,7 +3883,7 @@ void HTMLMediaElement::applyMediaFragmentURI() if (m_fragmentStartTime != MediaPlayer::invalidTime()) { m_sentEndEvent = false; UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragmentStart); - seek(m_fragmentStartTime, IGNORE_EXCEPTION); + seek(m_fragmentStartTime); } } diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h index 7c0acbc..91f5f63 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h @@ -376,7 +376,7 @@ private: void startProgressEventTimer(); void stopPeriodicTimers(); - void seek(double time, ExceptionState&); + void seek(double time); void finishSeek(); void checkIfSeekNeeded(); void addPlayedRange(double start, double end); @@ -509,6 +509,9 @@ private: // The last time a timeupdate event was sent in movie time. double m_lastTimeUpdateEventMovieTime; + // The default playback start position. + double m_defaultPlaybackStartPosition; + // Loading state. enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement }; LoadState m_loadState; diff --git a/third_party/WebKit/Source/core/html/MediaController.cpp b/third_party/WebKit/Source/core/html/MediaController.cpp index 38b7405..f86a22a 100644 --- a/third_party/WebKit/Source/core/html/MediaController.cpp +++ b/third_party/WebKit/Source/core/html/MediaController.cpp @@ -157,7 +157,7 @@ double MediaController::currentTime() const return m_position; } -void MediaController::setCurrentTime(double time, ExceptionState& exceptionState) +void MediaController::setCurrentTime(double time) { // When the user agent is to seek the media controller to a particular new playback position, // it must follow these steps: @@ -174,7 +174,7 @@ void MediaController::setCurrentTime(double time, ExceptionState& exceptionState // Seek each slaved media element to the new playback position relative to the media element timeline. for (MediaElementSequence::const_iterator it = m_mediaElements.begin(); it != m_mediaElements.end(); ++it) - (*it)->seek(time, exceptionState); + (*it)->seek(time); scheduleTimeupdateEvent(); } @@ -483,7 +483,7 @@ void MediaController::bringElementUpToSpeed(HTMLMediaElement* element) // When the user agent is to bring a media element up to speed with its new media controller, // it must seek that media element to the MediaController's media controller position relative // to the media element's timeline. - element->seek(currentTime(), IGNORE_EXCEPTION); + element->seek(currentTime()); // Update volume to take controller volume and mute into account. element->updateVolume(); diff --git a/third_party/WebKit/Source/core/html/MediaController.h b/third_party/WebKit/Source/core/html/MediaController.h index 30aab98..ca92367 100644 --- a/third_party/WebKit/Source/core/html/MediaController.h +++ b/third_party/WebKit/Source/core/html/MediaController.h @@ -56,7 +56,7 @@ public: double duration() const; double currentTime() const; - void setCurrentTime(double, ExceptionState&); + void setCurrentTime(double); bool paused() const { return m_paused; } void play(); diff --git a/third_party/WebKit/Source/core/html/MediaController.idl b/third_party/WebKit/Source/core/html/MediaController.idl index 8e70a8b..0a61cb6 100644 --- a/third_party/WebKit/Source/core/html/MediaController.idl +++ b/third_party/WebKit/Source/core/html/MediaController.idl @@ -35,7 +35,7 @@ readonly attribute TimeRanges seekable; readonly attribute unrestricted double duration; - [RaisesException=Setter] attribute double currentTime; + attribute double currentTime; readonly attribute boolean paused; readonly attribute TimeRanges played; diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp index 170b04b..9a184f8 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp @@ -407,7 +407,7 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event) // FIXME: This will need to take the timeline offset into consideration // once that concept is supported, see https://crbug.com/312699 if (mediaElement().controller()) - mediaElement().controller()->setCurrentTime(time, IGNORE_EXCEPTION); + mediaElement().controller()->setCurrentTime(time); else mediaElement().setCurrentTime(time, IGNORE_EXCEPTION); } |