OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 , m_textTracksVisible(false) | 427 , m_textTracksVisible(false) |
428 , m_shouldPerformAutomaticTrackSelection(true) | 428 , m_shouldPerformAutomaticTrackSelection(true) |
429 , m_tracksAreReady(true) | 429 , m_tracksAreReady(true) |
430 , m_processingPreferenceChange(false) | 430 , m_processingPreferenceChange(false) |
431 , m_remoteRoutesAvailable(false) | 431 , m_remoteRoutesAvailable(false) |
432 , m_playingRemotely(false) | 432 , m_playingRemotely(false) |
433 , m_inOverlayFullscreenVideo(false) | 433 , m_inOverlayFullscreenVideo(false) |
434 , m_audioTracks(AudioTrackList::create(*this)) | 434 , m_audioTracks(AudioTrackList::create(*this)) |
435 , m_videoTracks(VideoTrackList::create(*this)) | 435 , m_videoTracks(VideoTrackList::create(*this)) |
436 , m_textTracks(nullptr) | 436 , m_textTracks(nullptr) |
437 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolvePlayPromises)) | 437 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolveScheduledPlayPromises)) |
438 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectPlayPromises)) | 438 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectScheduledPlayPromises)) |
439 , m_audioSourceNode(nullptr) | 439 , m_audioSourceNode(nullptr) |
440 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) | 440 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) |
441 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) | 441 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) |
442 , m_remotePlaybackClient(nullptr) | 442 , m_remotePlaybackClient(nullptr) |
443 { | 443 { |
444 ThreadState::current()->registerPreFinalizer(this); | 444 ThreadState::current()->registerPreFinalizer(this); |
445 | 445 |
446 DVLOG(MEDIA_LOG_LEVEL) << "HTMLMediaElement(" << (void*)this << ")"; | 446 DVLOG(MEDIA_LOG_LEVEL) << "HTMLMediaElement(" << (void*)this << ")"; |
447 | 447 |
448 // If any experiment is enabled, then we want to enable a user gesture by | 448 // If any experiment is enabled, then we want to enable a user gesture by |
(...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 | 1387 |
1388 void HTMLMediaElement::cancelPendingEventsAndCallbacks() | 1388 void HTMLMediaElement::cancelPendingEventsAndCallbacks() |
1389 { | 1389 { |
1390 DVLOG(MEDIA_LOG_LEVEL) << "cancelPendingEventsAndCallbacks(" << (void*)this
<< ")"; | 1390 DVLOG(MEDIA_LOG_LEVEL) << "cancelPendingEventsAndCallbacks(" << (void*)this
<< ")"; |
1391 m_asyncEventQueue->cancelAllEvents(); | 1391 m_asyncEventQueue->cancelAllEvents(); |
1392 | 1392 |
1393 for (HTMLSourceElement* source = Traversal<HTMLSourceElement>::firstChild(*t
his); source; source = Traversal<HTMLSourceElement>::nextSibling(*source)) | 1393 for (HTMLSourceElement* source = Traversal<HTMLSourceElement>::firstChild(*t
his); source; source = Traversal<HTMLSourceElement>::nextSibling(*source)) |
1394 source->cancelPendingErrorEvent(); | 1394 source->cancelPendingErrorEvent(); |
1395 | 1395 |
1396 m_playPromiseResolveTask->cancel(); | 1396 m_playPromiseResolveTask->cancel(); |
| 1397 m_playPromiseResolveList.clear(); |
1397 m_playPromiseRejectTask->cancel(); | 1398 m_playPromiseRejectTask->cancel(); |
| 1399 m_playPromiseRejectList.clear(); |
1398 } | 1400 } |
1399 | 1401 |
1400 void HTMLMediaElement::networkStateChanged() | 1402 void HTMLMediaElement::networkStateChanged() |
1401 { | 1403 { |
1402 setNetworkState(webMediaPlayer()->getNetworkState()); | 1404 setNetworkState(webMediaPlayer()->getNetworkState()); |
1403 } | 1405 } |
1404 | 1406 |
1405 void HTMLMediaElement::mediaLoadingFailed(WebMediaPlayer::NetworkState error) | 1407 void HTMLMediaElement::mediaLoadingFailed(WebMediaPlayer::NetworkState error) |
1406 { | 1408 { |
1407 stopPeriodicTimers(); | 1409 stopPeriodicTimers(); |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2014 | 2016 |
2015 WebMediaPlayer::Preload preload = preloadType(); | 2017 WebMediaPlayer::Preload preload = preloadType(); |
2016 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) | 2018 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) |
2017 return WebMediaPlayer::PreloadMetaData; | 2019 return WebMediaPlayer::PreloadMetaData; |
2018 | 2020 |
2019 return preload; | 2021 return preload; |
2020 } | 2022 } |
2021 | 2023 |
2022 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) | 2024 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) |
2023 { | 2025 { |
| 2026 // We have to share the same logic for internal and external callers. The |
| 2027 // internal callers do not want to receive a Promise back but when ::play() |
| 2028 // is called, |m_playPromiseResolvers| needs to be populated. What this code |
| 2029 // does is to populate |m_playPromiseResolvers| before calling ::play() and |
| 2030 // remove the Promise if ::play() failed. |
| 2031 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 2032 ScriptPromise promise = resolver->promise(); |
| 2033 m_playPromiseResolvers.append(resolver); |
| 2034 |
2024 Nullable<ExceptionCode> code = play(); | 2035 Nullable<ExceptionCode> code = play(); |
2025 if (!code.isNull()) { | 2036 if (!code.isNull()) { |
| 2037 DCHECK(!m_playPromiseResolvers.isEmpty()); |
| 2038 m_playPromiseResolvers.removeLast(); |
| 2039 |
2026 String message; | 2040 String message; |
2027 switch (code.get()) { | 2041 switch (code.get()) { |
2028 case NotAllowedError: | 2042 case NotAllowedError: |
2029 message = "play() can only be initiated by a user gesture."; | 2043 message = "play() can only be initiated by a user gesture."; |
2030 break; | 2044 break; |
2031 case NotSupportedError: | 2045 case NotSupportedError: |
2032 message = "The element has no supported sources."; | 2046 message = "The element has no supported sources."; |
2033 break; | 2047 break; |
2034 default: | 2048 default: |
2035 NOTREACHED(); | 2049 NOTREACHED(); |
2036 } | 2050 } |
2037 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(code.get(), message)); | 2051 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(code.get(), message)); |
2038 } | 2052 } |
2039 | 2053 |
2040 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | |
2041 ScriptPromise promise = resolver->promise(); | |
2042 | |
2043 m_playResolvers.append(resolver); | |
2044 return promise; | 2054 return promise; |
2045 } | 2055 } |
2046 | 2056 |
2047 Nullable<ExceptionCode> HTMLMediaElement::play() | 2057 Nullable<ExceptionCode> HTMLMediaElement::play() |
2048 { | 2058 { |
2049 DVLOG(MEDIA_LOG_LEVEL) << "play(" << (void*)this << ")"; | 2059 DVLOG(MEDIA_LOG_LEVEL) << "play(" << (void*)this << ")"; |
2050 | 2060 |
2051 m_autoplayHelper->playMethodCalled(); | 2061 m_autoplayHelper->playMethodCalled(); |
2052 | 2062 |
2053 if (!UserGestureIndicator::processingUserGesture()) { | 2063 if (!UserGestureIndicator::processingUserGesture()) { |
(...skipping 1541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3595 visitor->trace(m_asyncEventQueue); | 3605 visitor->trace(m_asyncEventQueue); |
3596 visitor->trace(m_error); | 3606 visitor->trace(m_error); |
3597 visitor->trace(m_currentSourceNode); | 3607 visitor->trace(m_currentSourceNode); |
3598 visitor->trace(m_nextChildNodeToConsider); | 3608 visitor->trace(m_nextChildNodeToConsider); |
3599 visitor->trace(m_mediaSource); | 3609 visitor->trace(m_mediaSource); |
3600 visitor->trace(m_audioTracks); | 3610 visitor->trace(m_audioTracks); |
3601 visitor->trace(m_videoTracks); | 3611 visitor->trace(m_videoTracks); |
3602 visitor->trace(m_cueTimeline); | 3612 visitor->trace(m_cueTimeline); |
3603 visitor->trace(m_textTracks); | 3613 visitor->trace(m_textTracks); |
3604 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3614 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
3605 visitor->trace(m_playResolvers); | 3615 visitor->trace(m_playPromiseResolvers); |
| 3616 visitor->trace(m_playPromiseResolveList); |
| 3617 visitor->trace(m_playPromiseRejectList); |
3606 visitor->trace(m_audioSourceProvider); | 3618 visitor->trace(m_audioSourceProvider); |
3607 visitor->trace(m_autoplayHelperClient); | 3619 visitor->trace(m_autoplayHelperClient); |
3608 visitor->trace(m_autoplayHelper); | 3620 visitor->trace(m_autoplayHelper); |
3609 visitor->trace(m_srcObject); | 3621 visitor->trace(m_srcObject); |
3610 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); | 3622 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); |
3611 Supplementable<HTMLMediaElement>::trace(visitor); | 3623 Supplementable<HTMLMediaElement>::trace(visitor); |
3612 HTMLElement::trace(visitor); | 3624 HTMLElement::trace(visitor); |
3613 ActiveDOMObject::trace(visitor); | 3625 ActiveDOMObject::trace(visitor); |
3614 } | 3626 } |
3615 | 3627 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3692 // TODO(liberato): remove once autoplay gesture override experiment concludes. | 3704 // TODO(liberato): remove once autoplay gesture override experiment concludes. |
3693 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() | 3705 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() |
3694 { | 3706 { |
3695 if (FrameView* view = document().view()) | 3707 if (FrameView* view = document().view()) |
3696 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput
eVisibleArea())); | 3708 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput
eVisibleArea())); |
3697 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); | 3709 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); |
3698 } | 3710 } |
3699 | 3711 |
3700 void HTMLMediaElement::scheduleResolvePlayPromises() | 3712 void HTMLMediaElement::scheduleResolvePlayPromises() |
3701 { | 3713 { |
3702 // Per spec, if there are two tasks in the queue, the first task will remove | 3714 // TODO(mlamouri): per spec, we should create a new task but we can't create |
3703 // all the pending promises making the second task useless unless a promise | 3715 // a new cancellable task without cancelling the previous one. There are two |
3704 // can be added between the first and second task being run which is not | 3716 // approaches then: cancel the previous task and create a new one with the |
3705 // possible at the moment. | 3717 // appended promise list or append the new promise to the current list. The |
| 3718 // latter approach is preferred because it might be the less observable |
| 3719 // change. |
| 3720 DCHECK(m_playPromiseResolveList.isEmpty() || m_playPromiseResolveTask->isPen
ding()); |
| 3721 if (m_playPromiseResolvers.isEmpty()) |
| 3722 return; |
| 3723 |
| 3724 m_playPromiseResolveList.appendVector(m_playPromiseResolvers); |
| 3725 m_playPromiseResolvers.clear(); |
| 3726 |
3706 if (m_playPromiseResolveTask->isPending()) | 3727 if (m_playPromiseResolveTask->isPending()) |
3707 return; | 3728 return; |
3708 | 3729 |
3709 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseResolveTask->cancelAndCreate()); | 3730 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseResolveTask->cancelAndCreate()); |
3710 } | 3731 } |
3711 | 3732 |
3712 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) | 3733 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) |
3713 { | 3734 { |
3714 // Per spec, if there are two tasks in the queue, the first task will remove | 3735 // TODO(mlamouri): per spec, we should create a new task but we can't create |
3715 // all the pending promises making the second task useless unless a promise | 3736 // a new cancellable task without cancelling the previous one. There are two |
3716 // can be added between the first and second task being run which is not | 3737 // approaches then: cancel the previous task and create a new one with the |
3717 // possible at the moment. | 3738 // appended promise list or append the new promise to the current list. The |
| 3739 // latter approach is preferred because it might be the less observable |
| 3740 // change. |
| 3741 DCHECK(m_playPromiseRejectList.isEmpty() || m_playPromiseRejectTask->isPendi
ng()); |
| 3742 if (m_playPromiseResolvers.isEmpty()) |
| 3743 return; |
| 3744 |
| 3745 m_playPromiseRejectList.appendVector(m_playPromiseResolvers); |
| 3746 m_playPromiseResolvers.clear(); |
| 3747 |
3718 if (m_playPromiseRejectTask->isPending()) | 3748 if (m_playPromiseRejectTask->isPending()) |
3719 return; | 3749 return; |
3720 | 3750 |
3721 // TODO(mlamouri): because cancellable tasks can't take parameters, the | 3751 // TODO(mlamouri): because cancellable tasks can't take parameters, the |
3722 // error code needs to be saved. | 3752 // error code needs to be saved. |
3723 m_playPromiseErrorCode = code; | 3753 m_playPromiseErrorCode = code; |
3724 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseRejectTask->cancelAndCreate()); | 3754 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseRejectTask->cancelAndCreate()); |
3725 } | 3755 } |
3726 | 3756 |
3727 void HTMLMediaElement::scheduleNotifyPlaying() | 3757 void HTMLMediaElement::scheduleNotifyPlaying() |
3728 { | 3758 { |
3729 scheduleEvent(EventTypeNames::playing); | 3759 scheduleEvent(EventTypeNames::playing); |
3730 scheduleResolvePlayPromises(); | 3760 scheduleResolvePlayPromises(); |
3731 } | 3761 } |
3732 | 3762 |
3733 void HTMLMediaElement::resolvePlayPromises() | 3763 void HTMLMediaElement::resolveScheduledPlayPromises() |
3734 { | 3764 { |
3735 for (auto& resolver: m_playResolvers) | 3765 for (auto& resolver: m_playPromiseResolveList) |
3736 resolver->resolve(); | 3766 resolver->resolve(); |
3737 | 3767 |
3738 m_playResolvers.clear(); | 3768 m_playPromiseResolveList.clear(); |
3739 } | 3769 } |
3740 | 3770 |
3741 void HTMLMediaElement::rejectPlayPromises() | 3771 void HTMLMediaElement::rejectScheduledPlayPromises() |
3742 { | 3772 { |
3743 // TODO(mlamouri): the message is generated based on the code because | 3773 // TODO(mlamouri): the message is generated based on the code because |
3744 // arguments can't be passed to a cancellable task. In order to save space | 3774 // arguments can't be passed to a cancellable task. In order to save space |
3745 // used by the object, the string isn't saved. | 3775 // used by the object, the string isn't saved. |
3746 DCHECK(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not
SupportedError); | 3776 DCHECK(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not
SupportedError); |
3747 if (m_playPromiseErrorCode == AbortError) | 3777 if (m_playPromiseErrorCode == AbortError) |
3748 rejectPlayPromises(AbortError, "The play() request was interrupted by a
call to pause()."); | 3778 rejectPlayPromisesInternal(AbortError, "The play() request was interrupt
ed by a call to pause()."); |
3749 else | 3779 else |
3750 rejectPlayPromises(NotSupportedError, "Failed to load because no support
ed source was found."); | 3780 rejectPlayPromisesInternal(NotSupportedError, "Failed to load because no
supported source was found."); |
3751 } | 3781 } |
3752 | 3782 |
3753 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess
age) | 3783 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess
age) |
3754 { | 3784 { |
| 3785 m_playPromiseRejectList.appendVector(m_playPromiseResolvers); |
| 3786 m_playPromiseResolvers.clear(); |
| 3787 rejectPlayPromisesInternal(code, message); |
| 3788 } |
| 3789 |
| 3790 void HTMLMediaElement::rejectPlayPromisesInternal(ExceptionCode code, const Stri
ng& message) |
| 3791 { |
3755 DCHECK(code == AbortError || code == NotSupportedError); | 3792 DCHECK(code == AbortError || code == NotSupportedError); |
3756 | 3793 |
3757 for (auto& resolver: m_playResolvers) | 3794 for (auto& resolver: m_playPromiseRejectList) |
3758 resolver->reject(DOMException::create(code, message)); | 3795 resolver->reject(DOMException::create(code, message)); |
3759 | 3796 |
3760 m_playResolvers.clear(); | 3797 m_playPromiseRejectList.clear(); |
3761 } | 3798 } |
3762 | 3799 |
3763 EnumerationHistogram& HTMLMediaElement::showControlsHistogram() const | 3800 EnumerationHistogram& HTMLMediaElement::showControlsHistogram() const |
3764 { | 3801 { |
3765 if (isHTMLVideoElement()) { | 3802 if (isHTMLVideoElement()) { |
3766 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); | 3803 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); |
3767 return histogram; | 3804 return histogram; |
3768 } | 3805 } |
3769 | 3806 |
3770 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); | 3807 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3881 | 3918 |
3882 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst | 3919 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst |
3883 { | 3920 { |
3884 IntRect result; | 3921 IntRect result; |
3885 if (LayoutObject* object = m_element->layoutObject()) | 3922 if (LayoutObject* object = m_element->layoutObject()) |
3886 result = object->absoluteBoundingBoxRect(); | 3923 result = object->absoluteBoundingBoxRect(); |
3887 return result; | 3924 return result; |
3888 } | 3925 } |
3889 | 3926 |
3890 } // namespace blink | 3927 } // namespace blink |
OLD | NEW |