| Index: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
|
| diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
|
| index 56ad755a6e9c9743151d0a62dc99d5335758bdd9..08b587563b24b65257c1af475046795e03d1f891 100644
|
| --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
|
| +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
|
| @@ -38,6 +38,7 @@
|
| #include "core/dom/ElementTraversal.h"
|
| #include "core/dom/ElementVisibilityObserver.h"
|
| #include "core/dom/Fullscreen.h"
|
| +#include "core/dom/IntersectionObserverEntry.h"
|
| #include "core/dom/TaskRunnerHelper.h"
|
| #include "core/dom/shadow/ShadowRoot.h"
|
| #include "core/events/Event.h"
|
| @@ -464,8 +465,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName,
|
| m_autoplayHelper(
|
| AutoplayExperimentHelper::create(m_autoplayHelperClient.get())),
|
| m_autoplayUmaHelper(AutoplayUmaHelper::create(this)),
|
| - m_remotePlaybackClient(nullptr),
|
| - m_autoplayVisibilityObserver(nullptr) {
|
| + m_remotePlaybackClient(nullptr) {
|
| ThreadState::current()->registerPreFinalizer(this);
|
|
|
| BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";
|
| @@ -482,6 +482,11 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName,
|
| addElementToDocumentMap(this, &document);
|
|
|
| UseCounter::count(document, UseCounter::HTMLMediaElement);
|
| +
|
| + m_viewportIntersectionObserver = new ViewportIntersectionObserver(
|
| + this, WTF::bind(&HTMLMediaElement::onVideoViewportIntersectionChanged,
|
| + wrapWeakPersistent(this)));
|
| + m_viewportIntersectionObserver->start();
|
| }
|
|
|
| HTMLMediaElement::~HTMLMediaElement() {
|
| @@ -497,6 +502,8 @@ HTMLMediaElement::~HTMLMediaElement() {
|
| void HTMLMediaElement::dispose() {
|
| closeMediaSource();
|
|
|
| + m_viewportIntersectionObserver->stop();
|
| +
|
| // Destroying the player may cause a resource load to be canceled,
|
| // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being
|
| // called via ResourceFetch::didLoadResource(), then
|
| @@ -1723,16 +1730,7 @@ void HTMLMediaElement::setReadyState(ReadyState state) {
|
| if (!isGestureNeededForPlayback()) {
|
| if (isHTMLVideoElement() && muted() &&
|
| RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
|
| - // We might end up in a situation where the previous
|
| - // observer didn't had time to fire yet. We can avoid
|
| - // creating a new one in this case.
|
| - if (!m_autoplayVisibilityObserver) {
|
| - m_autoplayVisibilityObserver = new ElementVisibilityObserver(
|
| - this,
|
| - WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
|
| - wrapWeakPersistent(this)));
|
| - m_autoplayVisibilityObserver->start();
|
| - }
|
| + m_shouldAutoplayWhenVisible = true;
|
| } else {
|
| m_paused = false;
|
| invalidateCachedTime();
|
| @@ -2355,7 +2353,7 @@ void HTMLMediaElement::setMuted(bool muted) {
|
|
|
| bool wasAutoplayingMuted =
|
| !paused() && m_muted && isLockedPendingUserGesture();
|
| - bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() &&
|
| + bool wasPendingAutoplayMuted = m_shouldAutoplayWhenVisible && paused() &&
|
| m_muted && isLockedPendingUserGesture();
|
|
|
| if (UserGestureIndicator::processingUserGesture())
|
| @@ -2382,11 +2380,9 @@ void HTMLMediaElement::setMuted(bool muted) {
|
| }
|
|
|
| // If an element was a candidate for autoplay muted but not visible, it will
|
| - // have a visibility observer ready to start its playback.
|
| - if (wasPendingAutoplayMuted) {
|
| - m_autoplayVisibilityObserver->stop();
|
| - m_autoplayVisibilityObserver = nullptr;
|
| - }
|
| + // start its playback once becomes visible.
|
| + if (wasPendingAutoplayMuted)
|
| + m_shouldAutoplayWhenVisible = false;
|
| }
|
|
|
| void HTMLMediaElement::updateVolume() {
|
| @@ -3742,7 +3738,7 @@ DEFINE_TRACE(HTMLMediaElement) {
|
| visitor->trace(m_autoplayHelper);
|
| visitor->trace(m_autoplayUmaHelper);
|
| visitor->trace(m_srcObject);
|
| - visitor->trace(m_autoplayVisibilityObserver);
|
| + visitor->trace(m_viewportIntersectionObserver);
|
| visitor->template registerWeakMembers<HTMLMediaElement,
|
| &HTMLMediaElement::clearWeakMembers>(
|
| this);
|
| @@ -3968,8 +3964,26 @@ EnumerationHistogram& HTMLMediaElement::showControlsHistogram() const {
|
| return histogram;
|
| }
|
|
|
| -void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) {
|
| - if (!isVisible)
|
| +void HTMLMediaElement::onVideoViewportIntersectionChanged(
|
| + IntersectionObserverEntry* entry) {
|
| + if (!entry || !entry->rootBounds() || !entry->intersectionRect())
|
| + return;
|
| +
|
| + WebMediaPlayer::ViewportIntersectionInfo info;
|
| + info.ratio = entry->intersectionRatio();
|
| + info.rootRect =
|
| + WebRect(entry->rootBounds()->top(), entry->rootBounds()->left(),
|
| + entry->rootBounds()->width(), entry->rootBounds()->height());
|
| + info.intersectRect = WebRect(
|
| + entry->intersectionRect()->top(), entry->intersectionRect()->left(),
|
| + entry->intersectionRect()->width(), entry->intersectionRect()->height());
|
| + if (m_webMediaPlayer)
|
| + m_webMediaPlayer->videoViewportIntersectionChanged(info);
|
| + m_viewportIntersectInfo = info;
|
| + bool isVisible = info.ratio > 0.f;
|
| + m_autoplayUmaHelper->visibilityMaybeChangedforMutedVideo(isVisible);
|
| +
|
| + if (!isVisible || !m_shouldAutoplayWhenVisible)
|
| return;
|
|
|
| if (shouldAutoplay()) {
|
| @@ -3981,13 +3995,7 @@ void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) {
|
|
|
| updatePlayState();
|
| }
|
| -
|
| - // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay()
|
| - // is never called. The leak comes from either ElementVisibilityObserver or
|
| - // IntersectionObserver. Should keep an eye on it. See
|
| - // https://crbug.com/627539
|
| - m_autoplayVisibilityObserver->stop();
|
| - m_autoplayVisibilityObserver = nullptr;
|
| + m_shouldAutoplayWhenVisible = false;
|
| }
|
|
|
| void HTMLMediaElement::clearWeakMembers(Visitor* visitor) {
|
|
|