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 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 m_displayMode = Unknown; | 784 m_displayMode = Unknown; |
785 | 785 |
786 // 1 - Abort any already-running instance of the resource selection algorith m for this element. | 786 // 1 - Abort any already-running instance of the resource selection algorith m for this element. |
787 m_loadState = WaitingForSource; | 787 m_loadState = WaitingForSource; |
788 m_currentSourceNode = nullptr; | 788 m_currentSourceNode = nullptr; |
789 | 789 |
790 // 2 - If there are any tasks from the media element's media element event t ask source in | 790 // 2 - If there are any tasks from the media element's media element event t ask source in |
791 // one of the task queues, then remove those tasks. | 791 // one of the task queues, then remove those tasks. |
792 cancelPendingEventsAndCallbacks(); | 792 cancelPendingEventsAndCallbacks(); |
793 | 793 |
794 for (auto& resolver : m_playPromiseResolvers) | |
795 m_playPromiseRejectList.append(resolver); | |
philipj_slow
2016/04/06 14:12:59
m_playPromiseRejectList.append(m_playPromiseResolv
mlamouri (slow - plz ping)
2016/04/12 14:36:20
Done. Here and other places.
| |
796 m_playPromiseResolvers.clear(); | |
794 rejectPlayPromises(AbortError, "The play() request was interrupted by a new load request."); | 797 rejectPlayPromises(AbortError, "The play() request was interrupted by a new load request."); |
795 | 798 |
796 // 3 - If the media element's networkState is set to NETWORK_LOADING or NETW ORK_IDLE, queue | 799 // 3 - If the media element's networkState is set to NETWORK_LOADING or NETW ORK_IDLE, queue |
797 // a task to fire a simple event named abort at the media element. | 800 // a task to fire a simple event named abort at the media element. |
798 if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) | 801 if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) |
799 scheduleEvent(EventTypeNames::abort); | 802 scheduleEvent(EventTypeNames::abort); |
800 | 803 |
801 resetMediaPlayerAndMediaSource(); | 804 resetMediaPlayerAndMediaSource(); |
802 | 805 |
803 // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps | 806 // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps |
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2004 | 2007 |
2005 WebMediaPlayer::Preload preload = preloadType(); | 2008 WebMediaPlayer::Preload preload = preloadType(); |
2006 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) | 2009 if (m_ignorePreloadNone && preload == WebMediaPlayer::PreloadNone) |
2007 return WebMediaPlayer::PreloadMetaData; | 2010 return WebMediaPlayer::PreloadMetaData; |
2008 | 2011 |
2009 return preload; | 2012 return preload; |
2010 } | 2013 } |
2011 | 2014 |
2012 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) | 2015 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* scriptState) |
2013 { | 2016 { |
2017 // We have to share the same logic for internal and external callers. The | |
2018 // internal callers do not want to receive a Promise back but when ::play() | |
2019 // is called, |m_playPromiseResolvers| needs to be populated. What this code do | |
philipj_slow
2016/04/06 14:12:59
s/do then/does/
mlamouri (slow - plz ping)
2016/04/12 14:36:20
Done.
| |
2020 // then is to populate |m_playPromiseResolvers| before calling ::play() and remove | |
2021 // the Promise if ::play() failed. | |
2022 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | |
2023 ScriptPromise promise = resolver->promise(); | |
2024 m_playPromiseResolvers.append(resolver); | |
philipj_slow
2016/04/06 14:12:59
I don't follow why this change was needed. Does it
mlamouri (slow - plz ping)
2016/04/12 14:36:20
Assume the media is already playing. It will resol
| |
2025 | |
2014 Nullable<ExceptionCode> code = play(); | 2026 Nullable<ExceptionCode> code = play(); |
2015 if (!code.isNull()) { | 2027 if (!code.isNull()) { |
2028 ASSERT(!m_playPromiseResolvers.isEmpty()); | |
2029 m_playPromiseResolvers.removeLast(); | |
2030 | |
2016 String message; | 2031 String message; |
2017 switch (code.get()) { | 2032 switch (code.get()) { |
2018 case NotAllowedError: | 2033 case NotAllowedError: |
2019 message = "play() can only be initiated by a user gesture."; | 2034 message = "play() can only be initiated by a user gesture."; |
2020 break; | 2035 break; |
2021 case NotSupportedError: | 2036 case NotSupportedError: |
2022 message = "The element has no supported sources."; | 2037 message = "The element has no supported sources."; |
2023 break; | 2038 break; |
2024 default: | 2039 default: |
2025 ASSERT_NOT_REACHED(); | 2040 ASSERT_NOT_REACHED(); |
2026 } | 2041 } |
2027 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(code.get(), message)); | 2042 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(code.get(), message)); |
2028 } | 2043 } |
2029 | 2044 |
2030 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | |
2031 ScriptPromise promise = resolver->promise(); | |
2032 | |
2033 m_playResolvers.append(resolver); | |
2034 return promise; | 2045 return promise; |
2035 } | 2046 } |
2036 | 2047 |
2037 Nullable<ExceptionCode> HTMLMediaElement::play() | 2048 Nullable<ExceptionCode> HTMLMediaElement::play() |
2038 { | 2049 { |
2039 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); | 2050 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); |
2040 | 2051 |
2041 m_autoplayHelper->playMethodCalled(); | 2052 m_autoplayHelper->playMethodCalled(); |
2042 | 2053 |
2043 if (!UserGestureIndicator::processingUserGesture()) { | 2054 if (!UserGestureIndicator::processingUserGesture()) { |
(...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3626 visitor->trace(m_asyncEventQueue); | 3637 visitor->trace(m_asyncEventQueue); |
3627 visitor->trace(m_error); | 3638 visitor->trace(m_error); |
3628 visitor->trace(m_currentSourceNode); | 3639 visitor->trace(m_currentSourceNode); |
3629 visitor->trace(m_nextChildNodeToConsider); | 3640 visitor->trace(m_nextChildNodeToConsider); |
3630 visitor->trace(m_mediaSource); | 3641 visitor->trace(m_mediaSource); |
3631 visitor->trace(m_audioTracks); | 3642 visitor->trace(m_audioTracks); |
3632 visitor->trace(m_videoTracks); | 3643 visitor->trace(m_videoTracks); |
3633 visitor->trace(m_cueTimeline); | 3644 visitor->trace(m_cueTimeline); |
3634 visitor->trace(m_textTracks); | 3645 visitor->trace(m_textTracks); |
3635 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3646 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
3636 visitor->trace(m_playResolvers); | 3647 visitor->trace(m_playPromiseResolvers); |
3648 visitor->trace(m_playPromiseResolveList); | |
3649 visitor->trace(m_playPromiseRejectList); | |
3637 visitor->trace(m_audioSourceProvider); | 3650 visitor->trace(m_audioSourceProvider); |
3638 visitor->trace(m_autoplayHelperClient); | 3651 visitor->trace(m_autoplayHelperClient); |
3639 visitor->trace(m_autoplayHelper); | 3652 visitor->trace(m_autoplayHelper); |
3640 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); | 3653 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); |
3641 Supplementable<HTMLMediaElement>::trace(visitor); | 3654 Supplementable<HTMLMediaElement>::trace(visitor); |
3642 HTMLElement::trace(visitor); | 3655 HTMLElement::trace(visitor); |
3643 ActiveDOMObject::trace(visitor); | 3656 ActiveDOMObject::trace(visitor); |
3644 } | 3657 } |
3645 | 3658 |
3646 void HTMLMediaElement::createPlaceholderTracksIfNecessary() | 3659 void HTMLMediaElement::createPlaceholderTracksIfNecessary() |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3708 // TODO(liberato): remove once autoplay gesture override experiment concludes. | 3721 // TODO(liberato): remove once autoplay gesture override experiment concludes. |
3709 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() | 3722 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() |
3710 { | 3723 { |
3711 if (FrameView* view = document().view()) | 3724 if (FrameView* view = document().view()) |
3712 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput eVisibleArea())); | 3725 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput eVisibleArea())); |
3713 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); | 3726 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); |
3714 } | 3727 } |
3715 | 3728 |
3716 void HTMLMediaElement::scheduleResolvePlayPromises() | 3729 void HTMLMediaElement::scheduleResolvePlayPromises() |
3717 { | 3730 { |
3718 // Per spec, if there are two tasks in the queue, the first task will remove | 3731 // TODO(mlamouri): per spec, we should create a new task but we can't create |
3719 // all the pending promises making the second task useless unless a promise | 3732 // a new cancellable task without cancelling the previous one. There are two |
3720 // can be added between the first and second task being run which is not | 3733 // approaches then: cancel the previous task and create a new one with the |
3721 // possible at the moment. | 3734 // appended promise list or append the new promise to the current list. The |
philipj_slow
2016/04/06 14:12:59
Hmm, so these are two decidedly not great options.
mlamouri (slow - plz ping)
2016/04/12 14:36:20
I believe I'm doing what you are suggesting here o
| |
3735 // former approach is prefered because it might be the less observable | |
3736 // change. | |
3737 ASSERT(m_playPromiseResolveList.isEmpty() || m_playPromiseResolveTask->isPen ding()); | |
3738 if (m_playPromiseResolvers.isEmpty()) | |
3739 return; | |
3740 | |
3741 for (auto& resolver : m_playPromiseResolvers) | |
3742 m_playPromiseResolveList.append(resolver); | |
3743 m_playPromiseResolvers.clear(); | |
3744 | |
3722 if (m_playPromiseResolveTask->isPending()) | 3745 if (m_playPromiseResolveTask->isPending()) |
3723 return; | 3746 return; |
3724 | 3747 |
3725 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO M_HERE, m_playPromiseResolveTask->cancelAndCreate()); | 3748 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO M_HERE, m_playPromiseResolveTask->cancelAndCreate()); |
3726 } | 3749 } |
3727 | 3750 |
3728 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) | 3751 void HTMLMediaElement::scheduleRejectPlayPromises(ExceptionCode code) |
3729 { | 3752 { |
3730 // Per spec, if there are two tasks in the queue, the first task will remove | 3753 // TODO(mlamouri): per spec, we should create a new task but we can't create |
3731 // all the pending promises making the second task useless unless a promise | 3754 // a new cancellable task without cancelling the previous one. There are two |
3732 // can be added between the first and second task being run which is not | 3755 // approaches then: cancel the previous task and create a new one with the |
3733 // possible at the moment. | 3756 // appended promise list or append the new promise to the current list. The |
3757 // former approach is prefered because it might be the less observable | |
3758 // change. | |
3759 ASSERT(m_playPromiseRejectList.isEmpty() || m_playPromiseRejectTask->isPendi ng()); | |
3760 if (m_playPromiseResolvers.isEmpty()) | |
3761 return; | |
3762 | |
3763 for (auto& resolver : m_playPromiseResolvers) | |
3764 m_playPromiseRejectList.append(resolver); | |
3765 m_playPromiseResolvers.clear(); | |
3766 | |
3734 if (m_playPromiseRejectTask->isPending()) | 3767 if (m_playPromiseRejectTask->isPending()) |
3735 return; | 3768 return; |
3736 | 3769 |
3737 // TODO(mlamouri): because cancellable tasks can't take parameters, the | 3770 // TODO(mlamouri): because cancellable tasks can't take parameters, the |
3738 // error code needs to be saved. | 3771 // error code needs to be saved. |
3739 m_playPromiseErrorCode = code; | 3772 m_playPromiseErrorCode = code; |
3740 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO M_HERE, m_playPromiseRejectTask->cancelAndCreate()); | 3773 Platform::current()->currentThread()->getWebTaskRunner()->postTask(BLINK_FRO M_HERE, m_playPromiseRejectTask->cancelAndCreate()); |
3741 } | 3774 } |
3742 | 3775 |
3743 void HTMLMediaElement::scheduleNotifyPlaying() | 3776 void HTMLMediaElement::scheduleNotifyPlaying() |
3744 { | 3777 { |
3745 scheduleEvent(EventTypeNames::playing); | 3778 scheduleEvent(EventTypeNames::playing); |
3746 scheduleResolvePlayPromises(); | 3779 scheduleResolvePlayPromises(); |
3747 } | 3780 } |
3748 | 3781 |
3749 void HTMLMediaElement::resolvePlayPromises() | 3782 void HTMLMediaElement::resolvePlayPromises() |
3750 { | 3783 { |
3751 for (auto& resolver: m_playResolvers) | 3784 for (auto& resolver: m_playPromiseResolveList) |
3752 resolver->resolve(); | 3785 resolver->resolve(); |
3753 | 3786 |
3754 m_playResolvers.clear(); | 3787 m_playPromiseResolveList.clear(); |
3755 } | 3788 } |
3756 | 3789 |
3757 void HTMLMediaElement::rejectPlayPromises() | 3790 void HTMLMediaElement::rejectPlayPromises() |
3758 { | 3791 { |
3759 // TODO(mlamouri): the message is generated based on the code because | 3792 // TODO(mlamouri): the message is generated based on the code because |
3760 // arguments can't be passed to a cancellable task. In order to save space | 3793 // arguments can't be passed to a cancellable task. In order to save space |
3761 // used by the object, the string isn't saved. | 3794 // used by the object, the string isn't saved. |
3762 ASSERT(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not SupportedError); | 3795 ASSERT(m_playPromiseErrorCode == AbortError || m_playPromiseErrorCode == Not SupportedError); |
3763 if (m_playPromiseErrorCode == AbortError) | 3796 if (m_playPromiseErrorCode == AbortError) |
3764 rejectPlayPromises(AbortError, "The play() request was interrupted by a call to pause()."); | 3797 rejectPlayPromises(AbortError, "The play() request was interrupted by a call to pause()."); |
3765 else | 3798 else |
3766 rejectPlayPromises(NotSupportedError, "Failed to load because no support ed source was found."); | 3799 rejectPlayPromises(NotSupportedError, "Failed to load because no support ed source was found."); |
3767 } | 3800 } |
3768 | 3801 |
3769 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess age) | 3802 void HTMLMediaElement::rejectPlayPromises(ExceptionCode code, const String& mess age) |
3770 { | 3803 { |
3771 ASSERT(code == AbortError || code == NotSupportedError); | 3804 ASSERT(code == AbortError || code == NotSupportedError); |
3772 | 3805 |
3773 for (auto& resolver: m_playResolvers) | 3806 for (auto& resolver: m_playPromiseRejectList) |
3774 resolver->reject(DOMException::create(code, message)); | 3807 resolver->reject(DOMException::create(code, message)); |
3775 | 3808 |
3776 m_playResolvers.clear(); | 3809 m_playPromiseRejectList.clear(); |
3777 } | 3810 } |
3778 | 3811 |
3779 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3812 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
3780 { | 3813 { |
3781 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) | 3814 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) |
3782 getAudioSourceProvider().setClient(nullptr); | 3815 getAudioSourceProvider().setClient(nullptr); |
3783 } | 3816 } |
3784 | 3817 |
3785 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) | 3818 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) |
3786 { | 3819 { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3882 } | 3915 } |
3883 | 3916 |
3884 #if !ENABLE(OILPAN) | 3917 #if !ENABLE(OILPAN) |
3885 WeakPtr<HTMLMediaElement> HTMLMediaElement::createWeakPtr() | 3918 WeakPtr<HTMLMediaElement> HTMLMediaElement::createWeakPtr() |
3886 { | 3919 { |
3887 return m_weakPtrFactory.createWeakPtr(); | 3920 return m_weakPtrFactory.createWeakPtr(); |
3888 } | 3921 } |
3889 #endif | 3922 #endif |
3890 | 3923 |
3891 } // namespace blink | 3924 } // namespace blink |
OLD | NEW |