| 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 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 , m_textTracksVisible(false) | 437 , m_textTracksVisible(false) |
| 438 , m_shouldPerformAutomaticTrackSelection(true) | 438 , m_shouldPerformAutomaticTrackSelection(true) |
| 439 , m_tracksAreReady(true) | 439 , m_tracksAreReady(true) |
| 440 , m_processingPreferenceChange(false) | 440 , m_processingPreferenceChange(false) |
| 441 , m_remoteRoutesAvailable(false) | 441 , m_remoteRoutesAvailable(false) |
| 442 , m_playingRemotely(false) | 442 , m_playingRemotely(false) |
| 443 , m_inOverlayFullscreenVideo(false) | 443 , m_inOverlayFullscreenVideo(false) |
| 444 , m_audioTracks(AudioTrackList::create(*this)) | 444 , m_audioTracks(AudioTrackList::create(*this)) |
| 445 , m_videoTracks(VideoTrackList::create(*this)) | 445 , m_videoTracks(VideoTrackList::create(*this)) |
| 446 , m_textTracks(nullptr) | 446 , m_textTracks(nullptr) |
| 447 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolvePlayPromises)) | 447 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolveScheduledPlayPromises)) |
| 448 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectPlayPromises)) | 448 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectScheduledPlayPromises)) |
| 449 , m_audioSourceNode(nullptr) | 449 , m_audioSourceNode(nullptr) |
| 450 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) | 450 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) |
| 451 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) | 451 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) |
| 452 , m_remotePlaybackClient(nullptr) | 452 , m_remotePlaybackClient(nullptr) |
| 453 { | 453 { |
| 454 ThreadState::current()->registerPreFinalizer(this); | 454 ThreadState::current()->registerPreFinalizer(this); |
| 455 | 455 |
| 456 DVLOG(MEDIA_LOG_LEVEL) << "HTMLMediaElement(" << (void*)this << ")"; | 456 DVLOG(MEDIA_LOG_LEVEL) << "HTMLMediaElement(" << (void*)this << ")"; |
| 457 | 457 |
| 458 // If any experiment is enabled, then we want to enable a user gesture by | 458 // 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... |
| 1397 | 1397 |
| 1398 void HTMLMediaElement::cancelPendingEventsAndCallbacks() | 1398 void HTMLMediaElement::cancelPendingEventsAndCallbacks() |
| 1399 { | 1399 { |
| 1400 DVLOG(MEDIA_LOG_LEVEL) << "cancelPendingEventsAndCallbacks(" << (void*)this
<< ")"; | 1400 DVLOG(MEDIA_LOG_LEVEL) << "cancelPendingEventsAndCallbacks(" << (void*)this
<< ")"; |
| 1401 m_asyncEventQueue->cancelAllEvents(); | 1401 m_asyncEventQueue->cancelAllEvents(); |
| 1402 | 1402 |
| 1403 for (HTMLSourceElement* source = Traversal<HTMLSourceElement>::firstChild(*t
his); source; source = Traversal<HTMLSourceElement>::nextSibling(*source)) | 1403 for (HTMLSourceElement* source = Traversal<HTMLSourceElement>::firstChild(*t
his); source; source = Traversal<HTMLSourceElement>::nextSibling(*source)) |
| 1404 source->cancelPendingErrorEvent(); | 1404 source->cancelPendingErrorEvent(); |
| 1405 | 1405 |
| 1406 m_playPromiseResolveTask->cancel(); | 1406 m_playPromiseResolveTask->cancel(); |
| 1407 m_playPromiseResolveList.clear(); |
| 1407 m_playPromiseRejectTask->cancel(); | 1408 m_playPromiseRejectTask->cancel(); |
| 1409 m_playPromiseRejectList.clear(); |
| 1408 } | 1410 } |
| 1409 | 1411 |
| 1410 void HTMLMediaElement::networkStateChanged() | 1412 void HTMLMediaElement::networkStateChanged() |
| 1411 { | 1413 { |
| 1412 setNetworkState(webMediaPlayer()->getNetworkState()); | 1414 setNetworkState(webMediaPlayer()->getNetworkState()); |
| 1413 } | 1415 } |
| 1414 | 1416 |
| 1415 void HTMLMediaElement::mediaLoadingFailed(WebMediaPlayer::NetworkState error) | 1417 void HTMLMediaElement::mediaLoadingFailed(WebMediaPlayer::NetworkState error) |
| 1416 { | 1418 { |
| 1417 stopPeriodicTimers(); | 1419 stopPeriodicTimers(); |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 | 2024 |
| 2023 WebMediaPlayer::Preload preload = preloadType(); | 2025 WebMediaPlayer::Preload preload = preloadType(); |
| 2024 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) | 2026 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) |
| 2025 return WebMediaPlayer::PreloadMetaData; | 2027 return WebMediaPlayer::PreloadMetaData; |
| 2026 | 2028 |
| 2027 return preload; | 2029 return preload; |
| 2028 } | 2030 } |
| 2029 | 2031 |
| 2030 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) | 2032 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) |
| 2031 { | 2033 { |
| 2034 // We have to share the same logic for internal and external callers. The |
| 2035 // internal callers do not want to receive a Promise back but when ::play() |
| 2036 // is called, |m_playPromiseResolvers| needs to be populated. What this code |
| 2037 // does is to populate |m_playPromiseResolvers| before calling ::play() and |
| 2038 // remove the Promise if ::play() failed. |
| 2039 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 2040 ScriptPromise promise = resolver->promise(); |
| 2041 m_playPromiseResolvers.append(resolver); |
| 2042 |
| 2032 Nullable<ExceptionCode> code = play(); | 2043 Nullable<ExceptionCode> code = play(); |
| 2033 if (!code.isNull()) { | 2044 if (!code.isNull()) { |
| 2045 DCHECK(!m_playPromiseResolvers.isEmpty()); |
| 2046 m_playPromiseResolvers.removeLast(); |
| 2047 |
| 2034 String message; | 2048 String message; |
| 2035 switch (code.get()) { | 2049 switch (code.get()) { |
| 2036 case NotAllowedError: | 2050 case NotAllowedError: |
| 2037 message = "play() can only be initiated by a user gesture."; | 2051 message = "play() can only be initiated by a user gesture."; |
| 2038 break; | 2052 break; |
| 2039 case NotSupportedError: | 2053 case NotSupportedError: |
| 2040 message = "The element has no supported sources."; | 2054 message = "The element has no supported sources."; |
| 2041 break; | 2055 break; |
| 2042 default: | 2056 default: |
| 2043 ASSERT_NOT_REACHED(); | 2057 ASSERT_NOT_REACHED(); |
| 2044 } | 2058 } |
| 2045 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(code.get(), message)); | 2059 resolver->reject(DOMException::create(code.get(), message)); |
| 2060 return promise; |
| 2046 } | 2061 } |
| 2047 | 2062 |
| 2048 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | |
| 2049 ScriptPromise promise = resolver->promise(); | |
| 2050 | |
| 2051 m_playResolvers.append(resolver); | |
| 2052 return promise; | 2063 return promise; |
| 2053 } | 2064 } |
| 2054 | 2065 |
| 2055 Nullable<ExceptionCode> HTMLMediaElement::play() | 2066 Nullable<ExceptionCode> HTMLMediaElement::play() |
| 2056 { | 2067 { |
| 2057 DVLOG(MEDIA_LOG_LEVEL) << "play(" << (void*)this << ")"; | 2068 DVLOG(MEDIA_LOG_LEVEL) << "play(" << (void*)this << ")"; |
| 2058 | 2069 |
| 2059 m_autoplayHelper->playMethodCalled(); | 2070 m_autoplayHelper->playMethodCalled(); |
| 2060 | 2071 |
| 2061 if (!UserGestureIndicator::processingUserGesture()) { | 2072 if (!UserGestureIndicator::processingUserGesture()) { |
| (...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3604 visitor->trace(m_asyncEventQueue); | 3615 visitor->trace(m_asyncEventQueue); |
| 3605 visitor->trace(m_error); | 3616 visitor->trace(m_error); |
| 3606 visitor->trace(m_currentSourceNode); | 3617 visitor->trace(m_currentSourceNode); |
| 3607 visitor->trace(m_nextChildNodeToConsider); | 3618 visitor->trace(m_nextChildNodeToConsider); |
| 3608 visitor->trace(m_mediaSource); | 3619 visitor->trace(m_mediaSource); |
| 3609 visitor->trace(m_audioTracks); | 3620 visitor->trace(m_audioTracks); |
| 3610 visitor->trace(m_videoTracks); | 3621 visitor->trace(m_videoTracks); |
| 3611 visitor->trace(m_cueTimeline); | 3622 visitor->trace(m_cueTimeline); |
| 3612 visitor->trace(m_textTracks); | 3623 visitor->trace(m_textTracks); |
| 3613 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3624 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
| 3614 visitor->trace(m_playResolvers); | 3625 visitor->trace(m_playPromiseResolvers); |
| 3626 visitor->trace(m_playPromiseResolveList); |
| 3627 visitor->trace(m_playPromiseRejectList); |
| 3615 visitor->trace(m_audioSourceProvider); | 3628 visitor->trace(m_audioSourceProvider); |
| 3616 visitor->trace(m_autoplayHelperClient); | 3629 visitor->trace(m_autoplayHelperClient); |
| 3617 visitor->trace(m_autoplayHelper); | 3630 visitor->trace(m_autoplayHelper); |
| 3618 visitor->trace(m_srcObject); | 3631 visitor->trace(m_srcObject); |
| 3619 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); | 3632 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); |
| 3620 Supplementable<HTMLMediaElement>::trace(visitor); | 3633 Supplementable<HTMLMediaElement>::trace(visitor); |
| 3621 HTMLElement::trace(visitor); | 3634 HTMLElement::trace(visitor); |
| 3622 ActiveDOMObject::trace(visitor); | 3635 ActiveDOMObject::trace(visitor); |
| 3623 } | 3636 } |
| 3624 | 3637 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3701 // TODO(liberato): remove once autoplay gesture override experiment concludes. | 3714 // TODO(liberato): remove once autoplay gesture override experiment concludes. |
| 3702 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() | 3715 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() |
| 3703 { | 3716 { |
| 3704 if (FrameView* view = document().view()) | 3717 if (FrameView* view = document().view()) |
| 3705 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput
eVisibleArea())); | 3718 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput
eVisibleArea())); |
| 3706 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); | 3719 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); |
| 3707 } | 3720 } |
| 3708 | 3721 |
| 3709 void HTMLMediaElement::scheduleResolvePlayPromises() | 3722 void HTMLMediaElement::scheduleResolvePlayPromises() |
| 3710 { | 3723 { |
| 3711 // Per spec, if there are two tasks in the queue, the first task will remove | 3724 // TODO(mlamouri): per spec, we should create a new task but we can't create |
| 3712 // all the pending promises making the second task useless unless a promise | 3725 // a new cancellable task without cancelling the previous one. There are two |
| 3713 // can be added between the first and second task being run which is not | 3726 // approaches then: cancel the previous task and create a new one with the |
| 3714 // possible at the moment. | 3727 // appended promise list or append the new promise to the current list. The |
| 3728 // latter approach is preferred because it might be the less observable |
| 3729 // change. |
| 3730 DCHECK(m_playPromiseResolveList.isEmpty() || m_playPromiseResolveTask->isPen
ding()); |
| 3731 if (m_playPromiseResolvers.isEmpty()) |
| 3732 return; |
| 3733 |
| 3734 m_playPromiseResolveList.appendVector(m_playPromiseResolvers); |
| 3735 m_playPromiseResolvers.clear(); |
| 3736 |
| 3715 if (m_playPromiseResolveTask->isPending()) | 3737 if (m_playPromiseResolveTask->isPending()) |
| 3716 return; | 3738 return; |
| 3717 | 3739 |
| 3718 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseResolveTask->cancelAndCreate()); | 3740 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseResolveTask->cancelAndCreate()); |
| 3719 } | 3741 } |
| 3720 | 3742 |
| 3721 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) | 3743 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) |
| 3722 { | 3744 { |
| 3723 // Per spec, if there are two tasks in the queue, the first task will remove | 3745 // TODO(mlamouri): per spec, we should create a new task but we can't create |
| 3724 // all the pending promises making the second task useless unless a promise | 3746 // a new cancellable task without cancelling the previous one. There are two |
| 3725 // can be added between the first and second task being run which is not | 3747 // approaches then: cancel the previous task and create a new one with the |
| 3726 // possible at the moment. | 3748 // appended promise list or append the new promise to the current list. The |
| 3749 // latter approach is preferred because it might be the less observable |
| 3750 // change. |
| 3751 DCHECK(m_playPromiseRejectList.isEmpty() || m_playPromiseRejectTask->isPendi
ng()); |
| 3752 if (m_playPromiseResolvers.isEmpty()) |
| 3753 return; |
| 3754 |
| 3755 m_playPromiseRejectList.appendVector(m_playPromiseResolvers); |
| 3756 m_playPromiseResolvers.clear(); |
| 3757 |
| 3727 if (m_playPromiseRejectTask->isPending()) | 3758 if (m_playPromiseRejectTask->isPending()) |
| 3728 return; | 3759 return; |
| 3729 | 3760 |
| 3730 // TODO(mlamouri): because cancellable tasks can't take parameters, the | 3761 // TODO(mlamouri): because cancellable tasks can't take parameters, the |
| 3731 // error code needs to be saved. | 3762 // error code needs to be saved. |
| 3732 m_playPromiseErrorCode = code; | 3763 m_playPromiseErrorCode = code; |
| 3733 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseRejectTask->cancelAndCreate()); | 3764 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO
M_HERE, m_playPromiseRejectTask->cancelAndCreate()); |
| 3734 } | 3765 } |
| 3735 | 3766 |
| 3736 void HTMLMediaElement::scheduleNotifyPlaying() | 3767 void HTMLMediaElement::scheduleNotifyPlaying() |
| 3737 { | 3768 { |
| 3738 scheduleEvent(EventTypeNames::playing); | 3769 scheduleEvent(EventTypeNames::playing); |
| 3739 scheduleResolvePlayPromises(); | 3770 scheduleResolvePlayPromises(); |
| 3740 } | 3771 } |
| 3741 | 3772 |
| 3742 void HTMLMediaElement::resolvePlayPromises() | 3773 void HTMLMediaElement::resolveScheduledPlayPromises() |
| 3743 { | 3774 { |
| 3744 for (auto& resolver: m_playResolvers) | 3775 for (auto& resolver: m_playPromiseResolveList) |
| 3745 resolver->resolve(); | 3776 resolver->resolve(); |
| 3746 | 3777 |
| 3747 m_playResolvers.clear(); | 3778 m_playPromiseResolveList.clear(); |
| 3748 } | 3779 } |
| 3749 | 3780 |
| 3750 void HTMLMediaElement::rejectPlayPromises() | 3781 void HTMLMediaElement::rejectScheduledPlayPromises() |
| 3751 { | 3782 { |
| 3752 // TODO(mlamouri): the message is generated based on the code because | 3783 // TODO(mlamouri): the message is generated based on the code because |
| 3753 // arguments can't be passed to a cancellable task. In order to save space | 3784 // arguments can't be passed to a cancellable task. In order to save space |
| 3754 // used by the object, the string isn't saved. | 3785 // used by the object, the string isn't saved. |
| 3755 ASSERT(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not
SupportedError); | 3786 DCHECK(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not
SupportedError); |
| 3756 if (m_playPromiseErrorCode == AbortError) | 3787 if (m_playPromiseErrorCode == AbortError) |
| 3757 rejectPlayPromises(AbortError, "The play() request was interrupted by a
call to pause()."); | 3788 rejectPlayPromisesInternal(AbortError, "The play() request was interrupt
ed by a call to pause()."); |
| 3758 else | 3789 else |
| 3759 rejectPlayPromises(NotSupportedError, "Failed to load because no support
ed source was found."); | 3790 rejectPlayPromisesInternal(NotSupportedError, "Failed to load because no
supported source was found."); |
| 3760 } | 3791 } |
| 3761 | 3792 |
| 3762 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess
age) | 3793 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess
age) |
| 3763 { | 3794 { |
| 3764 ASSERT(code == AbortError || code == NotSupportedError); | 3795 m_playPromiseRejectList.appendVector(m_playPromiseResolvers); |
| 3796 m_playPromiseResolvers.clear(); |
| 3797 rejectPlayPromisesInternal(code, message); |
| 3798 } |
| 3765 | 3799 |
| 3766 for (auto& resolver: m_playResolvers) | 3800 void HTMLMediaElement::rejectPlayPromisesInternal(ExceptionCode code, const Stri
ng& message) |
| 3801 { |
| 3802 DCHECK(code == AbortError || code == NotSupportedError); |
| 3803 |
| 3804 for (auto& resolver: m_playPromiseRejectList) |
| 3767 resolver->reject(DOMException::create(code, message)); | 3805 resolver->reject(DOMException::create(code, message)); |
| 3768 | 3806 |
| 3769 m_playResolvers.clear(); | 3807 m_playPromiseRejectList.clear(); |
| 3770 } | 3808 } |
| 3771 | 3809 |
| 3772 EnumerationHistogram& HTMLMediaElement::showControlsHistogram() const | 3810 EnumerationHistogram& HTMLMediaElement::showControlsHistogram() const |
| 3773 { | 3811 { |
| 3774 if (isHTMLVideoElement()) { | 3812 if (isHTMLVideoElement()) { |
| 3775 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); | 3813 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); |
| 3776 return histogram; | 3814 return histogram; |
| 3777 } | 3815 } |
| 3778 | 3816 |
| 3779 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); | 3817 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3905 | 3943 |
| 3906 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst | 3944 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst |
| 3907 { | 3945 { |
| 3908 IntRect result; | 3946 IntRect result; |
| 3909 if (LayoutObject* object = m_element->layoutObject()) | 3947 if (LayoutObject* object = m_element->layoutObject()) |
| 3910 result = object->absoluteBoundingBoxRect(); | 3948 result = object->absoluteBoundingBoxRect(); |
| 3911 return result; | 3949 return result; |
| 3912 } | 3950 } |
| 3913 | 3951 |
| 3914 } // namespace blink | 3952 } // namespace blink |
| OLD | NEW |