Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights |
| 3 * reserved. | 3 * reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 #include "bindings/core/v8/ExceptionState.h" | 29 #include "bindings/core/v8/ExceptionState.h" |
| 30 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 30 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| 31 #include "bindings/core/v8/ScriptController.h" | 31 #include "bindings/core/v8/ScriptController.h" |
| 32 #include "bindings/core/v8/ScriptEventListener.h" | 32 #include "bindings/core/v8/ScriptEventListener.h" |
| 33 #include "bindings/core/v8/ScriptPromiseResolver.h" | 33 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 34 #include "core/HTMLNames.h" | 34 #include "core/HTMLNames.h" |
| 35 #include "core/css/MediaList.h" | 35 #include "core/css/MediaList.h" |
| 36 #include "core/dom/Attribute.h" | 36 #include "core/dom/Attribute.h" |
| 37 #include "core/dom/DOMException.h" | 37 #include "core/dom/DOMException.h" |
| 38 #include "core/dom/ElementTraversal.h" | 38 #include "core/dom/ElementTraversal.h" |
| 39 #include "core/dom/ElementVisibilityObserver.h" | 39 #include "core/dom/ElementVisibilityObserver.h" |
|
Zhiqiang Zhang (Slow)
2016/11/15 11:29:27
nit: remove this unused include
xjz
2016/11/15 23:03:39
This header file is needed.
| |
| 40 #include "core/dom/Fullscreen.h" | 40 #include "core/dom/Fullscreen.h" |
| 41 #include "core/dom/TaskRunnerHelper.h" | 41 #include "core/dom/TaskRunnerHelper.h" |
| 42 #include "core/dom/shadow/ShadowRoot.h" | 42 #include "core/dom/shadow/ShadowRoot.h" |
| 43 #include "core/events/Event.h" | 43 #include "core/events/Event.h" |
| 44 #include "core/frame/FrameView.h" | 44 #include "core/frame/FrameView.h" |
| 45 #include "core/frame/LocalFrame.h" | 45 #include "core/frame/LocalFrame.h" |
| 46 #include "core/frame/Settings.h" | 46 #include "core/frame/Settings.h" |
| 47 #include "core/frame/UseCounter.h" | 47 #include "core/frame/UseCounter.h" |
| 48 #include "core/frame/csp/ContentSecurityPolicy.h" | 48 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 49 #include "core/html/AutoplayUmaHelper.h" | 49 #include "core/html/AutoplayUmaHelper.h" |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 this, | 457 this, |
| 458 &HTMLMediaElement::resolveScheduledPlayPromises)), | 458 &HTMLMediaElement::resolveScheduledPlayPromises)), |
| 459 m_playPromiseRejectTask(CancellableTaskFactory::create( | 459 m_playPromiseRejectTask(CancellableTaskFactory::create( |
| 460 this, | 460 this, |
| 461 &HTMLMediaElement::rejectScheduledPlayPromises)), | 461 &HTMLMediaElement::rejectScheduledPlayPromises)), |
| 462 m_audioSourceNode(nullptr), | 462 m_audioSourceNode(nullptr), |
| 463 m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)), | 463 m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)), |
| 464 m_autoplayHelper( | 464 m_autoplayHelper( |
| 465 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())), | 465 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())), |
| 466 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), | 466 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), |
| 467 m_remotePlaybackClient(nullptr), | 467 m_remotePlaybackClient(nullptr) { |
| 468 m_autoplayVisibilityObserver(nullptr) { | |
| 469 ThreadState::current()->registerPreFinalizer(this); | 468 ThreadState::current()->registerPreFinalizer(this); |
| 470 | 469 |
| 471 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; | 470 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; |
| 472 | 471 |
| 473 // If any experiment is enabled, then we want to enable a user gesture by | 472 // If any experiment is enabled, then we want to enable a user gesture by |
| 474 // default, otherwise the experiment does nothing. | 473 // default, otherwise the experiment does nothing. |
| 475 if ((document.settings() && | 474 if ((document.settings() && |
| 476 document.settings()->mediaPlaybackRequiresUserGesture()) || | 475 document.settings()->mediaPlaybackRequiresUserGesture()) || |
| 477 m_autoplayHelper->isExperimentEnabled()) { | 476 m_autoplayHelper->isExperimentEnabled()) { |
| 478 m_lockedPendingUserGesture = true; | 477 m_lockedPendingUserGesture = true; |
| 479 } | 478 } |
| 480 | 479 |
| 481 setHasCustomStyleCallbacks(); | 480 setHasCustomStyleCallbacks(); |
| 482 addElementToDocumentMap(this, &document); | 481 addElementToDocumentMap(this, &document); |
| 483 | 482 |
| 484 UseCounter::count(document, UseCounter::HTMLMediaElement); | 483 UseCounter::count(document, UseCounter::HTMLMediaElement); |
| 484 | |
| 485 m_videoViewportRatioObserver = new ElementViewportRatioObserver( | |
| 486 this, WTF::bind(&HTMLMediaElement::onVideoViewportRatioChanged, | |
| 487 wrapWeakPersistent(this))); | |
| 488 m_videoViewportRatioObserver->start(); | |
| 485 } | 489 } |
| 486 | 490 |
| 487 HTMLMediaElement::~HTMLMediaElement() { | 491 HTMLMediaElement::~HTMLMediaElement() { |
| 488 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")"; | 492 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")"; |
| 489 | 493 |
| 490 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). | 494 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). |
| 491 // Since AudioNode::dispose() is guaranteed to be always called before | 495 // Since AudioNode::dispose() is guaranteed to be always called before |
| 492 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared | 496 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared |
| 493 // even if the AudioNode and the HTMLMediaElement die together. | 497 // even if the AudioNode and the HTMLMediaElement die together. |
| 494 DCHECK(!m_audioSourceNode); | 498 DCHECK(!m_audioSourceNode); |
| 495 } | 499 } |
| 496 | 500 |
| 497 void HTMLMediaElement::dispose() { | 501 void HTMLMediaElement::dispose() { |
| 498 closeMediaSource(); | 502 closeMediaSource(); |
| 499 | 503 |
| 504 m_videoViewportRatioObserver->stop(); | |
| 505 | |
| 500 // Destroying the player may cause a resource load to be canceled, | 506 // Destroying the player may cause a resource load to be canceled, |
| 501 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being | 507 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being |
| 502 // called via ResourceFetch::didLoadResource(), then | 508 // called via ResourceFetch::didLoadResource(), then |
| 503 // FrameLoader::checkCompleted(). But it's guaranteed that the load event | 509 // FrameLoader::checkCompleted(). But it's guaranteed that the load event |
| 504 // doesn't get dispatched during the object destruction. | 510 // doesn't get dispatched during the object destruction. |
| 505 // See Document::isDelayingLoadEvent(). | 511 // See Document::isDelayingLoadEvent(). |
| 506 // Also see http://crbug.com/275223 for more details. | 512 // Also see http://crbug.com/275223 for more details. |
| 507 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); | 513 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); |
| 508 } | 514 } |
| 509 | 515 |
| (...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1716 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { | 1722 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { |
| 1717 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); | 1723 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); |
| 1718 | 1724 |
| 1719 // If the autoplay experiment says that it's okay to play now, | 1725 // If the autoplay experiment says that it's okay to play now, |
| 1720 // then don't require a user gesture. | 1726 // then don't require a user gesture. |
| 1721 m_autoplayHelper->becameReadyToPlay(); | 1727 m_autoplayHelper->becameReadyToPlay(); |
| 1722 | 1728 |
| 1723 if (!isGestureNeededForPlayback()) { | 1729 if (!isGestureNeededForPlayback()) { |
| 1724 if (isHTMLVideoElement() && muted() && | 1730 if (isHTMLVideoElement() && muted() && |
| 1725 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { | 1731 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { |
| 1726 // We might end up in a situation where the previous | 1732 m_shouldAutoplayWhenVisible = true; |
| 1727 // observer didn't had time to fire yet. We can avoid | |
| 1728 // creating a new one in this case. | |
| 1729 if (!m_autoplayVisibilityObserver) { | |
| 1730 m_autoplayVisibilityObserver = new ElementVisibilityObserver( | |
| 1731 this, | |
| 1732 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, | |
| 1733 wrapWeakPersistent(this))); | |
| 1734 m_autoplayVisibilityObserver->start(); | |
| 1735 } | |
| 1736 } else { | 1733 } else { |
| 1737 m_paused = false; | 1734 m_paused = false; |
| 1738 invalidateCachedTime(); | 1735 invalidateCachedTime(); |
| 1739 scheduleEvent(EventTypeNames::play); | 1736 scheduleEvent(EventTypeNames::play); |
| 1740 scheduleNotifyPlaying(); | 1737 scheduleNotifyPlaying(); |
| 1741 m_autoplaying = false; | 1738 m_autoplaying = false; |
| 1742 } | 1739 } |
| 1743 } | 1740 } |
| 1744 } | 1741 } |
| 1745 | 1742 |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2348 | 2345 |
| 2349 void HTMLMediaElement::setMuted(bool muted) { | 2346 void HTMLMediaElement::setMuted(bool muted) { |
| 2350 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted) | 2347 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted) |
| 2351 << ")"; | 2348 << ")"; |
| 2352 | 2349 |
| 2353 if (m_muted == muted) | 2350 if (m_muted == muted) |
| 2354 return; | 2351 return; |
| 2355 | 2352 |
| 2356 bool wasAutoplayingMuted = | 2353 bool wasAutoplayingMuted = |
| 2357 !paused() && m_muted && isLockedPendingUserGesture(); | 2354 !paused() && m_muted && isLockedPendingUserGesture(); |
| 2358 bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() && | 2355 bool wasPendingAutoplayMuted = m_shouldAutoplayWhenVisible && paused() && |
| 2359 m_muted && isLockedPendingUserGesture(); | 2356 m_muted && isLockedPendingUserGesture(); |
| 2360 | 2357 |
| 2361 if (UserGestureIndicator::processingUserGesture()) | 2358 if (UserGestureIndicator::processingUserGesture()) |
| 2362 unlockUserGesture(); | 2359 unlockUserGesture(); |
| 2363 | 2360 |
| 2364 m_muted = muted; | 2361 m_muted = muted; |
| 2365 m_autoplayHelper->mutedChanged(); | 2362 m_autoplayHelper->mutedChanged(); |
| 2366 | 2363 |
| 2367 updateVolume(); | 2364 updateVolume(); |
| 2368 | 2365 |
| 2369 scheduleEvent(EventTypeNames::volumechange); | 2366 scheduleEvent(EventTypeNames::volumechange); |
| 2370 | 2367 |
| 2371 // If an element autoplayed while muted, it needs to be unlocked to unmute, | 2368 // If an element autoplayed while muted, it needs to be unlocked to unmute, |
| 2372 // otherwise, it will be paused. | 2369 // otherwise, it will be paused. |
| 2373 if (wasAutoplayingMuted) { | 2370 if (wasAutoplayingMuted) { |
| 2374 if (isGestureNeededForPlayback()) { | 2371 if (isGestureNeededForPlayback()) { |
| 2375 pause(); | 2372 pause(); |
| 2376 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( | 2373 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( |
| 2377 AutoplayUnmuteActionStatus::Failure); | 2374 AutoplayUnmuteActionStatus::Failure); |
| 2378 } else { | 2375 } else { |
| 2379 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( | 2376 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( |
| 2380 AutoplayUnmuteActionStatus::Success); | 2377 AutoplayUnmuteActionStatus::Success); |
| 2381 } | 2378 } |
| 2382 } | 2379 } |
| 2383 | 2380 |
| 2384 // If an element was a candidate for autoplay muted but not visible, it will | 2381 // If an element was a candidate for autoplay muted but not visible, it will |
| 2385 // have a visibility observer ready to start its playback. | 2382 // start its playback once becomes visible. |
| 2386 if (wasPendingAutoplayMuted) { | 2383 if (wasPendingAutoplayMuted) |
| 2387 m_autoplayVisibilityObserver->stop(); | 2384 m_shouldAutoplayWhenVisible = false; |
| 2388 m_autoplayVisibilityObserver = nullptr; | |
| 2389 } | |
| 2390 } | 2385 } |
| 2391 | 2386 |
| 2392 void HTMLMediaElement::updateVolume() { | 2387 void HTMLMediaElement::updateVolume() { |
| 2393 if (webMediaPlayer()) | 2388 if (webMediaPlayer()) |
| 2394 webMediaPlayer()->setVolume(effectiveMediaVolume()); | 2389 webMediaPlayer()->setVolume(effectiveMediaVolume()); |
| 2395 | 2390 |
| 2396 if (mediaControls()) | 2391 if (mediaControls()) |
| 2397 mediaControls()->updateVolume(); | 2392 mediaControls()->updateVolume(); |
| 2398 } | 2393 } |
| 2399 | 2394 |
| (...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3735 visitor->trace(m_textTracks); | 3730 visitor->trace(m_textTracks); |
| 3736 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3731 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
| 3737 visitor->trace(m_playPromiseResolvers); | 3732 visitor->trace(m_playPromiseResolvers); |
| 3738 visitor->trace(m_playPromiseResolveList); | 3733 visitor->trace(m_playPromiseResolveList); |
| 3739 visitor->trace(m_playPromiseRejectList); | 3734 visitor->trace(m_playPromiseRejectList); |
| 3740 visitor->trace(m_audioSourceProvider); | 3735 visitor->trace(m_audioSourceProvider); |
| 3741 visitor->trace(m_autoplayHelperClient); | 3736 visitor->trace(m_autoplayHelperClient); |
| 3742 visitor->trace(m_autoplayHelper); | 3737 visitor->trace(m_autoplayHelper); |
| 3743 visitor->trace(m_autoplayUmaHelper); | 3738 visitor->trace(m_autoplayUmaHelper); |
| 3744 visitor->trace(m_srcObject); | 3739 visitor->trace(m_srcObject); |
| 3745 visitor->trace(m_autoplayVisibilityObserver); | 3740 visitor->trace(m_videoViewportRatioObserver); |
| 3746 visitor->template registerWeakMembers<HTMLMediaElement, | 3741 visitor->template registerWeakMembers<HTMLMediaElement, |
| 3747 &HTMLMediaElement::clearWeakMembers>( | 3742 &HTMLMediaElement::clearWeakMembers>( |
| 3748 this); | 3743 this); |
| 3749 Supplementable<HTMLMediaElement>::trace(visitor); | 3744 Supplementable<HTMLMediaElement>::trace(visitor); |
| 3750 HTMLElement::trace(visitor); | 3745 HTMLElement::trace(visitor); |
| 3751 ActiveDOMObject::trace(visitor); | 3746 ActiveDOMObject::trace(visitor); |
| 3752 } | 3747 } |
| 3753 | 3748 |
| 3754 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) { | 3749 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) { |
| 3755 visitor->traceWrappers(m_videoTracks); | 3750 visitor->traceWrappers(m_videoTracks); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3961 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, | 3956 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, |
| 3962 ("Media.Controls.Show.Video", MediaControlsShowMax)); | 3957 ("Media.Controls.Show.Video", MediaControlsShowMax)); |
| 3963 return histogram; | 3958 return histogram; |
| 3964 } | 3959 } |
| 3965 | 3960 |
| 3966 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, | 3961 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, |
| 3967 ("Media.Controls.Show.Audio", MediaControlsShowMax)); | 3962 ("Media.Controls.Show.Audio", MediaControlsShowMax)); |
| 3968 return histogram; | 3963 return histogram; |
| 3969 } | 3964 } |
| 3970 | 3965 |
| 3971 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { | 3966 void HTMLMediaElement::onVideoViewportRatioChanged(float ratio) { |
| 3972 if (!isVisible) | 3967 if (m_webMediaPlayer) { |
| 3968 m_webMediaPlayer->videoViewportRatioChanged(ratio); | |
| 3969 } | |
| 3970 m_viewportRatio = ratio; | |
| 3971 bool isVisible = ratio > 0.f; | |
| 3972 m_autoplayUmaHelper->visibilityMaybeChangedforMutedVideo(isVisible); | |
| 3973 | |
| 3974 if (!isVisible || !m_shouldAutoplayWhenVisible) | |
| 3973 return; | 3975 return; |
| 3974 | 3976 |
| 3975 if (shouldAutoplay()) { | 3977 if (shouldAutoplay()) { |
| 3976 m_paused = false; | 3978 m_paused = false; |
| 3977 invalidateCachedTime(); | 3979 invalidateCachedTime(); |
| 3978 scheduleEvent(EventTypeNames::play); | 3980 scheduleEvent(EventTypeNames::play); |
| 3979 scheduleNotifyPlaying(); | 3981 scheduleNotifyPlaying(); |
| 3980 m_autoplaying = false; | 3982 m_autoplaying = false; |
| 3981 | 3983 |
| 3982 updatePlayState(); | 3984 updatePlayState(); |
| 3983 } | 3985 } |
| 3984 | 3986 m_shouldAutoplayWhenVisible = false; |
| 3985 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay() | |
| 3986 // is never called. The leak comes from either ElementVisibilityObserver or | |
| 3987 // IntersectionObserver. Should keep an eye on it. See | |
| 3988 // https://crbug.com/627539 | |
| 3989 m_autoplayVisibilityObserver->stop(); | |
| 3990 m_autoplayVisibilityObserver = nullptr; | |
| 3991 } | 3987 } |
| 3992 | 3988 |
| 3993 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) { | 3989 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) { |
| 3994 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) { | 3990 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) { |
| 3995 getAudioSourceProvider().setClient(nullptr); | 3991 getAudioSourceProvider().setClient(nullptr); |
| 3996 m_audioSourceNode = nullptr; | 3992 m_audioSourceNode = nullptr; |
| 3997 } | 3993 } |
| 3998 } | 3994 } |
| 3999 | 3995 |
| 4000 void HTMLMediaElement::AudioSourceProviderImpl::wrap( | 3996 void HTMLMediaElement::AudioSourceProviderImpl::wrap( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4092 | 4088 |
| 4093 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() | 4089 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() |
| 4094 const { | 4090 const { |
| 4095 IntRect result; | 4091 IntRect result; |
| 4096 if (LayoutObject* object = m_element->layoutObject()) | 4092 if (LayoutObject* object = m_element->layoutObject()) |
| 4097 result = object->absoluteBoundingBoxRect(); | 4093 result = object->absoluteBoundingBoxRect(); |
| 4098 return result; | 4094 return result; |
| 4099 } | 4095 } |
| 4100 | 4096 |
| 4101 } // namespace blink | 4097 } // namespace blink |
| OLD | NEW |