Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp

Issue 2475643004: Monitor the intersection of video and viewport. (Closed)
Patch Set: Consolidate two ElementVisibilityObserver in AUtoplayUmaHelper. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 ElementVisibilityObserver(
486 this, WTF::bind(&HTMLMediaElement::onVideoViewportRatioChanged,
487 wrapWeakPersistent(this)));
488 m_videoViewportRatioObserver->start(
489 Vector<float>({std::numeric_limits<float>::min(), 0.85}));
miu 2016/11/05 02:47:47 1. Where does 0.85 come from, and how do we change
xjz 2016/11/09 02:24:28 Done. Now is able to monitor every changes on vide
485 } 490 }
486 491
487 HTMLMediaElement::~HTMLMediaElement() { 492 HTMLMediaElement::~HTMLMediaElement() {
488 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")"; 493 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")";
489 494
490 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). 495 // m_audioSourceNode is explicitly cleared by AudioNode::dispose().
491 // Since AudioNode::dispose() is guaranteed to be always called before 496 // Since AudioNode::dispose() is guaranteed to be always called before
492 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared 497 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared
493 // even if the AudioNode and the HTMLMediaElement die together. 498 // even if the AudioNode and the HTMLMediaElement die together.
494 DCHECK(!m_audioSourceNode); 499 DCHECK(!m_audioSourceNode);
495 } 500 }
496 501
497 void HTMLMediaElement::dispose() { 502 void HTMLMediaElement::dispose() {
498 closeMediaSource(); 503 closeMediaSource();
499 504
505 m_videoViewportRatioObserver->stop();
506
500 // Destroying the player may cause a resource load to be canceled, 507 // Destroying the player may cause a resource load to be canceled,
501 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being 508 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being
502 // called via ResourceFetch::didLoadResource(), then 509 // called via ResourceFetch::didLoadResource(), then
503 // FrameLoader::checkCompleted(). But it's guaranteed that the load event 510 // FrameLoader::checkCompleted(). But it's guaranteed that the load event
504 // doesn't get dispatched during the object destruction. 511 // doesn't get dispatched during the object destruction.
505 // See Document::isDelayingLoadEvent(). 512 // See Document::isDelayingLoadEvent().
506 // Also see http://crbug.com/275223 for more details. 513 // Also see http://crbug.com/275223 for more details.
507 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); 514 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking();
508 } 515 }
509 516
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { 1723 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
1717 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); 1724 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute);
1718 1725
1719 // If the autoplay experiment says that it's okay to play now, 1726 // If the autoplay experiment says that it's okay to play now,
1720 // then don't require a user gesture. 1727 // then don't require a user gesture.
1721 m_autoplayHelper->becameReadyToPlay(); 1728 m_autoplayHelper->becameReadyToPlay();
1722 1729
1723 if (!isGestureNeededForPlayback()) { 1730 if (!isGestureNeededForPlayback()) {
1724 if (isHTMLVideoElement() && muted() && 1731 if (isHTMLVideoElement() && muted() &&
1725 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { 1732 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
1726 // We might end up in a situation where the previous 1733 m_autoplayWhenVisible = 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 { 1734 } else {
1737 m_paused = false; 1735 m_paused = false;
1738 invalidateCachedTime(); 1736 invalidateCachedTime();
1739 scheduleEvent(EventTypeNames::play); 1737 scheduleEvent(EventTypeNames::play);
1740 scheduleNotifyPlaying(); 1738 scheduleNotifyPlaying();
1741 m_autoplaying = false; 1739 m_autoplaying = false;
1742 } 1740 }
1743 } 1741 }
1744 } 1742 }
1745 1743
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 2346
2349 void HTMLMediaElement::setMuted(bool muted) { 2347 void HTMLMediaElement::setMuted(bool muted) {
2350 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted) 2348 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted)
2351 << ")"; 2349 << ")";
2352 2350
2353 if (m_muted == muted) 2351 if (m_muted == muted)
2354 return; 2352 return;
2355 2353
2356 bool wasAutoplayingMuted = 2354 bool wasAutoplayingMuted =
2357 !paused() && m_muted && isLockedPendingUserGesture(); 2355 !paused() && m_muted && isLockedPendingUserGesture();
2358 bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() && 2356 bool wasPendingAutoplayMuted = m_autoplayWhenVisible && paused() && m_muted &&
miu 2016/11/05 02:47:47 Is the m_autoplayWhenVisible boolean necessary? Wh
xjz 2016/11/09 02:24:28 As replied to the comment in .h file, I keeps the
2359 m_muted && isLockedPendingUserGesture(); 2357 isLockedPendingUserGesture();
2360 2358
2361 if (UserGestureIndicator::processingUserGesture()) 2359 if (UserGestureIndicator::processingUserGesture())
2362 unlockUserGesture(); 2360 unlockUserGesture();
2363 2361
2364 m_muted = muted; 2362 m_muted = muted;
2365 m_autoplayHelper->mutedChanged(); 2363 m_autoplayHelper->mutedChanged();
2366 2364
2367 updateVolume(); 2365 updateVolume();
2368 2366
2369 scheduleEvent(EventTypeNames::volumechange); 2367 scheduleEvent(EventTypeNames::volumechange);
2370 2368
2371 // If an element autoplayed while muted, it needs to be unlocked to unmute, 2369 // If an element autoplayed while muted, it needs to be unlocked to unmute,
2372 // otherwise, it will be paused. 2370 // otherwise, it will be paused.
2373 if (wasAutoplayingMuted) { 2371 if (wasAutoplayingMuted) {
2374 if (isGestureNeededForPlayback()) { 2372 if (isGestureNeededForPlayback()) {
2375 pause(); 2373 pause();
2376 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( 2374 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(
2377 AutoplayUnmuteActionStatus::Failure); 2375 AutoplayUnmuteActionStatus::Failure);
2378 } else { 2376 } else {
2379 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( 2377 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(
2380 AutoplayUnmuteActionStatus::Success); 2378 AutoplayUnmuteActionStatus::Success);
2381 } 2379 }
2382 } 2380 }
2383 2381
2384 // If an element was a candidate for autoplay muted but not visible, it will 2382 // If an element was a candidate for autoplay muted but not visible, it will
2385 // have a visibility observer ready to start its playback. 2383 // have a visibility observer ready to start its playback.
miu 2016/11/05 02:47:46 Please adjust comment.
xjz 2016/11/09 02:24:28 Done.
2386 if (wasPendingAutoplayMuted) { 2384 if (wasPendingAutoplayMuted) {
2387 m_autoplayVisibilityObserver->stop(); 2385 m_autoplayWhenVisible = false;
2388 m_autoplayVisibilityObserver = nullptr;
2389 } 2386 }
2390 } 2387 }
2391 2388
2392 void HTMLMediaElement::updateVolume() { 2389 void HTMLMediaElement::updateVolume() {
2393 if (webMediaPlayer()) 2390 if (webMediaPlayer())
2394 webMediaPlayer()->setVolume(effectiveMediaVolume()); 2391 webMediaPlayer()->setVolume(effectiveMediaVolume());
2395 2392
2396 if (mediaControls()) 2393 if (mediaControls())
2397 mediaControls()->updateVolume(); 2394 mediaControls()->updateVolume();
2398 } 2395 }
(...skipping 1336 matching lines...) Expand 10 before | Expand all | Expand 10 after
3735 visitor->trace(m_textTracks); 3732 visitor->trace(m_textTracks);
3736 visitor->trace(m_textTracksWhenResourceSelectionBegan); 3733 visitor->trace(m_textTracksWhenResourceSelectionBegan);
3737 visitor->trace(m_playPromiseResolvers); 3734 visitor->trace(m_playPromiseResolvers);
3738 visitor->trace(m_playPromiseResolveList); 3735 visitor->trace(m_playPromiseResolveList);
3739 visitor->trace(m_playPromiseRejectList); 3736 visitor->trace(m_playPromiseRejectList);
3740 visitor->trace(m_audioSourceProvider); 3737 visitor->trace(m_audioSourceProvider);
3741 visitor->trace(m_autoplayHelperClient); 3738 visitor->trace(m_autoplayHelperClient);
3742 visitor->trace(m_autoplayHelper); 3739 visitor->trace(m_autoplayHelper);
3743 visitor->trace(m_autoplayUmaHelper); 3740 visitor->trace(m_autoplayUmaHelper);
3744 visitor->trace(m_srcObject); 3741 visitor->trace(m_srcObject);
3745 visitor->trace(m_autoplayVisibilityObserver); 3742 visitor->trace(m_videoViewportRatioObserver);
3746 visitor->template registerWeakMembers<HTMLMediaElement, 3743 visitor->template registerWeakMembers<HTMLMediaElement,
3747 &HTMLMediaElement::clearWeakMembers>( 3744 &HTMLMediaElement::clearWeakMembers>(
3748 this); 3745 this);
3749 Supplementable<HTMLMediaElement>::trace(visitor); 3746 Supplementable<HTMLMediaElement>::trace(visitor);
3750 HTMLElement::trace(visitor); 3747 HTMLElement::trace(visitor);
3751 ActiveDOMObject::trace(visitor); 3748 ActiveDOMObject::trace(visitor);
3752 } 3749 }
3753 3750
3754 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) { 3751 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) {
3755 visitor->traceWrappers(m_videoTracks); 3752 visitor->traceWrappers(m_videoTracks);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
3961 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 3958 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
3962 ("Media.Controls.Show.Video", MediaControlsShowMax)); 3959 ("Media.Controls.Show.Video", MediaControlsShowMax));
3963 return histogram; 3960 return histogram;
3964 } 3961 }
3965 3962
3966 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 3963 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
3967 ("Media.Controls.Show.Audio", MediaControlsShowMax)); 3964 ("Media.Controls.Show.Audio", MediaControlsShowMax));
3968 return histogram; 3965 return histogram;
3969 } 3966 }
3970 3967
3971 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { 3968 void HTMLMediaElement::onVideoViewportRatioChanged(bool isVisible) {
3969 m_autoplayUmaHelper->onVisibilityChangedForMutedVideo(isVisible);
3972 if (!isVisible) 3970 if (!isVisible)
3973 return; 3971 return;
3974 3972
3975 if (shouldAutoplay()) { 3973 if (shouldAutoplay() && m_autoplayWhenVisible) {
3976 m_paused = false; 3974 m_paused = false;
3977 invalidateCachedTime(); 3975 invalidateCachedTime();
3978 scheduleEvent(EventTypeNames::play); 3976 scheduleEvent(EventTypeNames::play);
3979 scheduleNotifyPlaying(); 3977 scheduleNotifyPlaying();
3980 m_autoplaying = false; 3978 m_autoplaying = false;
3981 3979
3982 updatePlayState(); 3980 updatePlayState();
3983 } 3981 }
3982 m_autoplayWhenVisible = false;
3984 3983
3985 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay() 3984 if (m_webMediaPlayer) {
3986 // is never called. The leak comes from either ElementVisibilityObserver or 3985 m_webMediaPlayer->videoViewportRatioChanged(
3987 // IntersectionObserver. Should keep an eye on it. See 3986 m_videoViewportRatioObserver->ratio());
3988 // https://crbug.com/627539 3987 }
3989 m_autoplayVisibilityObserver->stop();
3990 m_autoplayVisibilityObserver = nullptr;
3991 } 3988 }
3992 3989
3993 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) { 3990 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) {
3994 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) { 3991 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) {
3995 getAudioSourceProvider().setClient(nullptr); 3992 getAudioSourceProvider().setClient(nullptr);
3996 m_audioSourceNode = nullptr; 3993 m_audioSourceNode = nullptr;
3997 } 3994 }
3998 } 3995 }
3999 3996
4000 void HTMLMediaElement::AudioSourceProviderImpl::wrap( 3997 void HTMLMediaElement::AudioSourceProviderImpl::wrap(
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4092 4089
4093 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() 4090 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect()
4094 const { 4091 const {
4095 IntRect result; 4092 IntRect result;
4096 if (LayoutObject* object = m_element->layoutObject()) 4093 if (LayoutObject* object = m_element->layoutObject())
4097 result = object->absoluteBoundingBoxRect(); 4094 result = object->absoluteBoundingBoxRect();
4098 return result; 4095 return result;
4099 } 4096 }
4100 4097
4101 } // namespace blink 4098 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698