| 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 26 matching lines...) Expand all Loading... |
| 37 #include "core/dom/ElementTraversal.h" | 37 #include "core/dom/ElementTraversal.h" |
| 38 #include "core/dom/ElementVisibilityObserver.h" | 38 #include "core/dom/ElementVisibilityObserver.h" |
| 39 #include "core/dom/Fullscreen.h" | 39 #include "core/dom/Fullscreen.h" |
| 40 #include "core/dom/shadow/ShadowRoot.h" | 40 #include "core/dom/shadow/ShadowRoot.h" |
| 41 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
| 42 #include "core/frame/FrameView.h" | 42 #include "core/frame/FrameView.h" |
| 43 #include "core/frame/LocalFrame.h" | 43 #include "core/frame/LocalFrame.h" |
| 44 #include "core/frame/Settings.h" | 44 #include "core/frame/Settings.h" |
| 45 #include "core/frame/UseCounter.h" | 45 #include "core/frame/UseCounter.h" |
| 46 #include "core/frame/csp/ContentSecurityPolicy.h" | 46 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 47 #include "core/html/AutoplayUmaHelper.h" |
| 47 #include "core/html/HTMLMediaSource.h" | 48 #include "core/html/HTMLMediaSource.h" |
| 48 #include "core/html/HTMLSourceElement.h" | 49 #include "core/html/HTMLSourceElement.h" |
| 49 #include "core/html/HTMLTrackElement.h" | 50 #include "core/html/HTMLTrackElement.h" |
| 50 #include "core/html/MediaError.h" | 51 #include "core/html/MediaError.h" |
| 51 #include "core/html/MediaFragmentURIParser.h" | 52 #include "core/html/MediaFragmentURIParser.h" |
| 52 #include "core/html/TimeRanges.h" | 53 #include "core/html/TimeRanges.h" |
| 53 #include "core/html/shadow/MediaControls.h" | 54 #include "core/html/shadow/MediaControls.h" |
| 54 #include "core/html/track/AudioTrack.h" | 55 #include "core/html/track/AudioTrack.h" |
| 55 #include "core/html/track/AudioTrackList.h" | 56 #include "core/html/track/AudioTrackList.h" |
| 56 #include "core/html/track/AutomaticTrackSelection.h" | 57 #include "core/html/track/AutomaticTrackSelection.h" |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 case WebMediaPlayer::PreloadMetaData: | 275 case WebMediaPlayer::PreloadMetaData: |
| 275 return "metadata"; | 276 return "metadata"; |
| 276 case WebMediaPlayer::PreloadAuto: | 277 case WebMediaPlayer::PreloadAuto: |
| 277 return "auto"; | 278 return "auto"; |
| 278 } | 279 } |
| 279 | 280 |
| 280 NOTREACHED(); | 281 NOTREACHED(); |
| 281 return String(); | 282 return String(); |
| 282 } | 283 } |
| 283 | 284 |
| 284 // These values are used for histograms. Do not reorder. | |
| 285 enum AutoplaySource { | |
| 286 // Autoplay comes from HTMLMediaElement `autoplay` attribute. | |
| 287 AutoplaySourceAttribute = 0, | |
| 288 // Autoplay comes from `play()` method. | |
| 289 AutoplaySourceMethod = 1, | |
| 290 // This enum value must be last. | |
| 291 NumberOfAutoplaySources = 2, | |
| 292 }; | |
| 293 | |
| 294 } // anonymous namespace | 285 } // anonymous namespace |
| 295 | 286 |
| 296 class HTMLMediaElement::AutoplayHelperClientImpl : | 287 class HTMLMediaElement::AutoplayHelperClientImpl : |
| 297 public AutoplayExperimentHelper::Client { | 288 public AutoplayExperimentHelper::Client { |
| 298 | 289 |
| 299 public: | 290 public: |
| 300 static AutoplayHelperClientImpl* create(HTMLMediaElement* element) | 291 static AutoplayHelperClientImpl* create(HTMLMediaElement* element) |
| 301 { | 292 { |
| 302 return new AutoplayHelperClientImpl(element); | 293 return new AutoplayHelperClientImpl(element); |
| 303 } | 294 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 , m_playingRemotely(false) | 432 , m_playingRemotely(false) |
| 442 , m_inOverlayFullscreenVideo(false) | 433 , m_inOverlayFullscreenVideo(false) |
| 443 , m_audioTracks(AudioTrackList::create(*this)) | 434 , m_audioTracks(AudioTrackList::create(*this)) |
| 444 , m_videoTracks(VideoTrackList::create(*this)) | 435 , m_videoTracks(VideoTrackList::create(*this)) |
| 445 , m_textTracks(nullptr) | 436 , m_textTracks(nullptr) |
| 446 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolveScheduledPlayPromises)) | 437 , m_playPromiseResolveTask(CancellableTaskFactory::create(this, &HTMLMediaEl
ement::resolveScheduledPlayPromises)) |
| 447 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectScheduledPlayPromises)) | 438 , m_playPromiseRejectTask(CancellableTaskFactory::create(this, &HTMLMediaEle
ment::rejectScheduledPlayPromises)) |
| 448 , m_audioSourceNode(nullptr) | 439 , m_audioSourceNode(nullptr) |
| 449 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) | 440 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) |
| 450 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) | 441 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient.g
et())) |
| 442 , m_autoplayUmaHelper(AutoplayUmaHelper::create(this)) |
| 451 , m_remotePlaybackClient(nullptr) | 443 , m_remotePlaybackClient(nullptr) |
| 452 , m_autoplayVisibilityObserver(nullptr) | 444 , m_autoplayVisibilityObserver(nullptr) |
| 453 { | 445 { |
| 454 ThreadState::current()->registerPreFinalizer(this); | 446 ThreadState::current()->registerPreFinalizer(this); |
| 455 | 447 |
| 456 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; | 448 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; |
| 457 | 449 |
| 458 // If any experiment is enabled, then we want to enable a user gesture by | 450 // If any experiment is enabled, then we want to enable a user gesture by |
| 459 // default, otherwise the experiment does nothing. | 451 // default, otherwise the experiment does nothing. |
| 460 if ((document.settings() && document.settings()->mediaPlaybackRequiresUserGe
sture()) | 452 if ((document.settings() && document.settings()->mediaPlaybackRequiresUserGe
sture()) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 490 // doesn't get dispatched during the object destruction. | 482 // doesn't get dispatched during the object destruction. |
| 491 // See Document::isDelayingLoadEvent(). | 483 // See Document::isDelayingLoadEvent(). |
| 492 // Also see http://crbug.com/275223 for more details. | 484 // Also see http://crbug.com/275223 for more details. |
| 493 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | 485 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); |
| 494 } | 486 } |
| 495 | 487 |
| 496 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) | 488 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) |
| 497 { | 489 { |
| 498 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; | 490 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; |
| 499 | 491 |
| 492 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); |
| 500 // If any experiment is enabled, then we want to enable a user gesture by | 493 // If any experiment is enabled, then we want to enable a user gesture by |
| 501 // default, otherwise the experiment does nothing. | 494 // default, otherwise the experiment does nothing. |
| 502 bool oldDocumentRequiresUserGesture = (oldDocument.settings() && oldDocument
.settings()->mediaPlaybackRequiresUserGesture()) | 495 bool oldDocumentRequiresUserGesture = (oldDocument.settings() && oldDocument
.settings()->mediaPlaybackRequiresUserGesture()) |
| 503 || m_autoplayHelper->isExperimentEnabled(); | 496 || m_autoplayHelper->isExperimentEnabled(); |
| 504 bool newDocumentRequiresUserGesture = (document().settings() && document().s
ettings()->mediaPlaybackRequiresUserGesture()) | 497 bool newDocumentRequiresUserGesture = (document().settings() && document().s
ettings()->mediaPlaybackRequiresUserGesture()) |
| 505 || m_autoplayHelper->isExperimentEnabled(); | 498 || m_autoplayHelper->isExperimentEnabled(); |
| 506 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { | 499 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { |
| 507 m_lockedPendingUserGesture = true; | 500 m_lockedPendingUserGesture = true; |
| 508 } | 501 } |
| 509 | 502 |
| (...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 | 1633 |
| 1641 if (m_readyState == kHaveEnoughData && oldState < kHaveEnoughData && tracksA
reReady) { | 1634 if (m_readyState == kHaveEnoughData && oldState < kHaveEnoughData && tracksA
reReady) { |
| 1642 if (oldState <= kHaveCurrentData) { | 1635 if (oldState <= kHaveCurrentData) { |
| 1643 scheduleEvent(EventTypeNames::canplay); | 1636 scheduleEvent(EventTypeNames::canplay); |
| 1644 if (isPotentiallyPlaying) | 1637 if (isPotentiallyPlaying) |
| 1645 scheduleNotifyPlaying(); | 1638 scheduleNotifyPlaying(); |
| 1646 } | 1639 } |
| 1647 | 1640 |
| 1648 // Check for autoplay, and record metrics about it if needed. | 1641 // Check for autoplay, and record metrics about it if needed. |
| 1649 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { | 1642 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { |
| 1650 recordAutoplaySourceMetric(AutoplaySourceAttribute); | 1643 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); |
| 1651 | 1644 |
| 1652 // If the autoplay experiment says that it's okay to play now, | 1645 // If the autoplay experiment says that it's okay to play now, |
| 1653 // then don't require a user gesture. | 1646 // then don't require a user gesture. |
| 1654 m_autoplayHelper->becameReadyToPlay(); | 1647 m_autoplayHelper->becameReadyToPlay(); |
| 1655 | 1648 |
| 1656 if (!isGestureNeededForPlayback()) { | 1649 if (!isGestureNeededForPlayback()) { |
| 1657 if (isHTMLVideoElement() && muted() && RuntimeEnabledFeatures::a
utoplayMutedVideosEnabled()) { | 1650 if (isHTMLVideoElement() && muted() && RuntimeEnabledFeatures::a
utoplayMutedVideosEnabled()) { |
| 1658 // We might end up in a situation where the previous | 1651 // We might end up in a situation where the previous |
| 1659 // observer didn't had time to fire yet. We can avoid | 1652 // observer didn't had time to fire yet. We can avoid |
| 1660 // creating a new one in this case. | 1653 // creating a new one in this case. |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 return promise; | 2086 return promise; |
| 2094 } | 2087 } |
| 2095 | 2088 |
| 2096 Nullable<ExceptionCode> HTMLMediaElement::play() | 2089 Nullable<ExceptionCode> HTMLMediaElement::play() |
| 2097 { | 2090 { |
| 2098 BLINK_MEDIA_LOG << "play(" << (void*)this << ")"; | 2091 BLINK_MEDIA_LOG << "play(" << (void*)this << ")"; |
| 2099 | 2092 |
| 2100 m_autoplayHelper->playMethodCalled(); | 2093 m_autoplayHelper->playMethodCalled(); |
| 2101 | 2094 |
| 2102 if (!UserGestureIndicator::processingUserGesture()) { | 2095 if (!UserGestureIndicator::processingUserGesture()) { |
| 2103 recordAutoplaySourceMetric(AutoplaySourceMethod); | 2096 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); |
| 2104 if (isGestureNeededForPlayback()) { | 2097 if (isGestureNeededForPlayback()) { |
| 2105 // If playback is deferred, then don't start playback but don't | 2098 // If playback is deferred, then don't start playback but don't |
| 2106 // fail yet either. | 2099 // fail yet either. |
| 2107 if (m_autoplayHelper->isPlaybackDeferred()) | 2100 if (m_autoplayHelper->isPlaybackDeferred()) |
| 2108 return nullptr; | 2101 return nullptr; |
| 2109 | 2102 |
| 2110 // If we're already playing, then this play would do nothing anyway. | 2103 // If we're already playing, then this play would do nothing anyway. |
| 2111 // Call playInternal to handle scheduling the promise resolution. | 2104 // Call playInternal to handle scheduling the promise resolution. |
| 2112 if (!m_paused) { | 2105 if (!m_paused) { |
| 2113 playInternal(); | 2106 playInternal(); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 | 2301 |
| 2309 updateVolume(); | 2302 updateVolume(); |
| 2310 | 2303 |
| 2311 scheduleEvent(EventTypeNames::volumechange); | 2304 scheduleEvent(EventTypeNames::volumechange); |
| 2312 | 2305 |
| 2313 // If an element autoplayed while muted, it needs to be unlocked to unmute, | 2306 // If an element autoplayed while muted, it needs to be unlocked to unmute, |
| 2314 // otherwise, it will be paused. | 2307 // otherwise, it will be paused. |
| 2315 if (wasAutoplayingMuted) { | 2308 if (wasAutoplayingMuted) { |
| 2316 if (isGestureNeededForPlayback()) { | 2309 if (isGestureNeededForPlayback()) { |
| 2317 pause(); | 2310 pause(); |
| 2318 recordAutoplayUnmuteStatus(AutoplayUnmuteActionFailure); | 2311 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteAction
Status::Failure); |
| 2319 } else { | 2312 } else { |
| 2320 recordAutoplayUnmuteStatus(AutoplayUnmuteActionSuccess); | 2313 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(AutoplayUnmuteAction
Status::Success); |
| 2321 } | 2314 } |
| 2322 } | 2315 } |
| 2323 } | 2316 } |
| 2324 | 2317 |
| 2325 void HTMLMediaElement::updateVolume() | 2318 void HTMLMediaElement::updateVolume() |
| 2326 { | 2319 { |
| 2327 if (webMediaPlayer()) | 2320 if (webMediaPlayer()) |
| 2328 webMediaPlayer()->setVolume(effectiveMediaVolume()); | 2321 webMediaPlayer()->setVolume(effectiveMediaVolume()); |
| 2329 | 2322 |
| 2330 if (mediaControls()) | 2323 if (mediaControls()) |
| (...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3664 visitor->trace(m_videoTracks); | 3657 visitor->trace(m_videoTracks); |
| 3665 visitor->trace(m_cueTimeline); | 3658 visitor->trace(m_cueTimeline); |
| 3666 visitor->trace(m_textTracks); | 3659 visitor->trace(m_textTracks); |
| 3667 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3660 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
| 3668 visitor->trace(m_playPromiseResolvers); | 3661 visitor->trace(m_playPromiseResolvers); |
| 3669 visitor->trace(m_playPromiseResolveList); | 3662 visitor->trace(m_playPromiseResolveList); |
| 3670 visitor->trace(m_playPromiseRejectList); | 3663 visitor->trace(m_playPromiseRejectList); |
| 3671 visitor->trace(m_audioSourceProvider); | 3664 visitor->trace(m_audioSourceProvider); |
| 3672 visitor->trace(m_autoplayHelperClient); | 3665 visitor->trace(m_autoplayHelperClient); |
| 3673 visitor->trace(m_autoplayHelper); | 3666 visitor->trace(m_autoplayHelper); |
| 3667 visitor->trace(m_autoplayUmaHelper); |
| 3674 visitor->trace(m_srcObject); | 3668 visitor->trace(m_srcObject); |
| 3675 visitor->trace(m_autoplayVisibilityObserver); | 3669 visitor->trace(m_autoplayVisibilityObserver); |
| 3676 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); | 3670 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); |
| 3677 Supplementable<HTMLMediaElement>::trace(visitor); | 3671 Supplementable<HTMLMediaElement>::trace(visitor); |
| 3678 HTMLElement::trace(visitor); | 3672 HTMLElement::trace(visitor); |
| 3679 ActiveDOMObject::trace(visitor); | 3673 ActiveDOMObject::trace(visitor); |
| 3680 } | 3674 } |
| 3681 | 3675 |
| 3682 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) | 3676 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) |
| 3683 { | 3677 { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 { | 3878 { |
| 3885 if (isHTMLVideoElement()) { | 3879 if (isHTMLVideoElement()) { |
| 3886 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); | 3880 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Sh
ow.Video", MediaControlsShowMax)); |
| 3887 return histogram; | 3881 return histogram; |
| 3888 } | 3882 } |
| 3889 | 3883 |
| 3890 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); | 3884 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, ("Media.Controls.Show.A
udio", MediaControlsShowMax)); |
| 3891 return histogram; | 3885 return histogram; |
| 3892 } | 3886 } |
| 3893 | 3887 |
| 3894 void HTMLMediaElement::recordAutoplaySourceMetric(int source) | |
| 3895 { | |
| 3896 DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Auto
play", NumberOfAutoplaySources)); | |
| 3897 DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video
.Autoplay.Muted", NumberOfAutoplaySources)); | |
| 3898 DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Auto
play", NumberOfAutoplaySources)); | |
| 3899 | |
| 3900 if (isHTMLVideoElement()) { | |
| 3901 videoHistogram.count(source); | |
| 3902 if (muted()) | |
| 3903 mutedVideoHistogram.count(source); | |
| 3904 } else { | |
| 3905 audioHistogram.count(source); | |
| 3906 } | |
| 3907 } | |
| 3908 | |
| 3909 void HTMLMediaElement::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus sta
tus) | |
| 3910 { | |
| 3911 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.V
ideo.Autoplay.Muted.UnmuteAction", AutoplayUnmuteActionMax)); | |
| 3912 | |
| 3913 autoplayUnmuteHistogram.count(status); | |
| 3914 } | |
| 3915 | |
| 3916 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) | 3888 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) |
| 3917 { | 3889 { |
| 3918 if (!isVisible) | 3890 if (!isVisible) |
| 3919 return; | 3891 return; |
| 3920 | 3892 |
| 3921 if (shouldAutoplay()) { | 3893 if (shouldAutoplay()) { |
| 3922 m_paused = false; | 3894 m_paused = false; |
| 3923 invalidateCachedTime(); | 3895 invalidateCachedTime(); |
| 3924 scheduleEvent(EventTypeNames::play); | 3896 scheduleEvent(EventTypeNames::play); |
| 3925 scheduleNotifyPlaying(); | 3897 scheduleNotifyPlaying(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4041 | 4013 |
| 4042 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst | 4014 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst |
| 4043 { | 4015 { |
| 4044 IntRect result; | 4016 IntRect result; |
| 4045 if (LayoutObject* object = m_element->layoutObject()) | 4017 if (LayoutObject* object = m_element->layoutObject()) |
| 4046 result = object->absoluteBoundingBoxRect(); | 4018 result = object->absoluteBoundingBoxRect(); |
| 4047 return result; | 4019 return result; |
| 4048 } | 4020 } |
| 4049 | 4021 |
| 4050 } // namespace blink | 4022 } // namespace blink |
| OLD | NEW |