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

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

Issue 2475643004: Monitor the intersection of video and viewport. (Closed)
Patch Set: Fix trybots failure. 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 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 this, 456 this,
457 &HTMLMediaElement::resolveScheduledPlayPromises)), 457 &HTMLMediaElement::resolveScheduledPlayPromises)),
458 m_playPromiseRejectTask(CancellableTaskFactory::create( 458 m_playPromiseRejectTask(CancellableTaskFactory::create(
459 this, 459 this,
460 &HTMLMediaElement::rejectScheduledPlayPromises)), 460 &HTMLMediaElement::rejectScheduledPlayPromises)),
461 m_audioSourceNode(nullptr), 461 m_audioSourceNode(nullptr),
462 m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)), 462 m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)),
463 m_autoplayHelper( 463 m_autoplayHelper(
464 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())), 464 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())),
465 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), 465 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)),
466 m_remotePlaybackClient(nullptr), 466 m_remotePlaybackClient(nullptr) {
467 m_autoplayVisibilityObserver(nullptr) {
468 ThreadState::current()->registerPreFinalizer(this); 467 ThreadState::current()->registerPreFinalizer(this);
469 468
470 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; 469 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";
471 470
472 // If any experiment is enabled, then we want to enable a user gesture by 471 // If any experiment is enabled, then we want to enable a user gesture by
473 // default, otherwise the experiment does nothing. 472 // default, otherwise the experiment does nothing.
474 if ((document.settings() && 473 if ((document.settings() &&
475 document.settings()->mediaPlaybackRequiresUserGesture()) || 474 document.settings()->mediaPlaybackRequiresUserGesture()) ||
476 m_autoplayHelper->isExperimentEnabled()) { 475 m_autoplayHelper->isExperimentEnabled()) {
477 m_lockedPendingUserGesture = true; 476 m_lockedPendingUserGesture = true;
478 } 477 }
479 478
480 LocalFrame* frame = document.frame(); 479 LocalFrame* frame = document.frame();
481 if (frame) { 480 if (frame) {
482 m_remotePlaybackClient = 481 m_remotePlaybackClient =
483 frame->loader().client()->createWebRemotePlaybackClient(*this); 482 frame->loader().client()->createWebRemotePlaybackClient(*this);
484 } 483 }
485 484
486 setHasCustomStyleCallbacks(); 485 setHasCustomStyleCallbacks();
487 addElementToDocumentMap(this, &document); 486 addElementToDocumentMap(this, &document);
488 487
489 UseCounter::count(document, UseCounter::HTMLMediaElement); 488 UseCounter::count(document, UseCounter::HTMLMediaElement);
489
490 m_viewportIntersectionObserver = new ElementViewportIntersectionObserver(
491 this, WTF::bind(&HTMLMediaElement::onVideoViewportIntersectionChanged,
492 wrapWeakPersistent(this)));
493 m_viewportIntersectionObserver->start();
490 } 494 }
491 495
492 HTMLMediaElement::~HTMLMediaElement() { 496 HTMLMediaElement::~HTMLMediaElement() {
493 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")"; 497 BLINK_MEDIA_LOG << "~HTMLMediaElement(" << (void*)this << ")";
494 498
495 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). 499 // m_audioSourceNode is explicitly cleared by AudioNode::dispose().
496 // Since AudioNode::dispose() is guaranteed to be always called before 500 // Since AudioNode::dispose() is guaranteed to be always called before
497 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared 501 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared
498 // even if the AudioNode and the HTMLMediaElement die together. 502 // even if the AudioNode and the HTMLMediaElement die together.
499 DCHECK(!m_audioSourceNode); 503 DCHECK(!m_audioSourceNode);
500 } 504 }
501 505
502 void HTMLMediaElement::dispose() { 506 void HTMLMediaElement::dispose() {
503 closeMediaSource(); 507 closeMediaSource();
504 508
509 m_viewportIntersectionObserver->stop();
510
505 // Destroying the player may cause a resource load to be canceled, 511 // Destroying the player may cause a resource load to be canceled,
506 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being 512 // which could result in LocalDOMWindow::dispatchWindowLoadEvent() being
507 // called via ResourceFetch::didLoadResource(), then 513 // called via ResourceFetch::didLoadResource(), then
508 // FrameLoader::checkCompleted(). But it's guaranteed that the load event 514 // FrameLoader::checkCompleted(). But it's guaranteed that the load event
509 // doesn't get dispatched during the object destruction. 515 // doesn't get dispatched during the object destruction.
510 // See Document::isDelayingLoadEvent(). 516 // See Document::isDelayingLoadEvent().
511 // Also see http://crbug.com/275223 for more details. 517 // Also see http://crbug.com/275223 for more details.
512 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking(); 518 clearMediaPlayerAndAudioSourceProviderClientWithoutLocking();
513 } 519 }
514 520
(...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { 1741 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
1736 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); 1742 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute);
1737 1743
1738 // If the autoplay experiment says that it's okay to play now, 1744 // If the autoplay experiment says that it's okay to play now,
1739 // then don't require a user gesture. 1745 // then don't require a user gesture.
1740 m_autoplayHelper->becameReadyToPlay(); 1746 m_autoplayHelper->becameReadyToPlay();
1741 1747
1742 if (!isGestureNeededForPlayback()) { 1748 if (!isGestureNeededForPlayback()) {
1743 if (isHTMLVideoElement() && muted() && 1749 if (isHTMLVideoElement() && muted() &&
1744 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { 1750 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
1745 // We might end up in a situation where the previous 1751 m_shouldAutoplayWhenVisible = true;
1746 // observer didn't had time to fire yet. We can avoid
1747 // creating a new one in this case.
1748 if (!m_autoplayVisibilityObserver) {
1749 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1750 this,
1751 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1752 wrapWeakPersistent(this)));
1753 m_autoplayVisibilityObserver->start();
1754 }
1755 } else { 1752 } else {
1756 m_paused = false; 1753 m_paused = false;
1757 scheduleEvent(EventTypeNames::play); 1754 scheduleEvent(EventTypeNames::play);
1758 scheduleNotifyPlaying(); 1755 scheduleNotifyPlaying();
1759 m_autoplaying = false; 1756 m_autoplaying = false;
1760 } 1757 }
1761 } 1758 }
1762 } 1759 }
1763 1760
1764 scheduleEvent(EventTypeNames::canplaythrough); 1761 scheduleEvent(EventTypeNames::canplaythrough);
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
2439 } 2436 }
2440 2437
2441 void HTMLMediaElement::setMuted(bool muted) { 2438 void HTMLMediaElement::setMuted(bool muted) {
2442 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted) 2439 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << boolString(muted)
2443 << ")"; 2440 << ")";
2444 2441
2445 if (m_muted == muted) 2442 if (m_muted == muted)
2446 return; 2443 return;
2447 2444
2448 bool wasAutoplayingMuted = isAutoplayingMuted(); 2445 bool wasAutoplayingMuted = isAutoplayingMuted();
2449 bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() && 2446 bool wasPendingAutoplayMuted = m_shouldAutoplayWhenVisible && paused() &&
2450 m_muted && isLockedPendingUserGesture(); 2447 m_muted && isLockedPendingUserGesture();
2451 2448
2452 if (UserGestureIndicator::processingUserGesture()) 2449 if (UserGestureIndicator::processingUserGesture())
2453 unlockUserGesture(); 2450 unlockUserGesture();
2454 2451
2455 m_muted = muted; 2452 m_muted = muted;
2456 m_autoplayHelper->mutedChanged(); 2453 m_autoplayHelper->mutedChanged();
2457 2454
2458 scheduleEvent(EventTypeNames::volumechange); 2455 scheduleEvent(EventTypeNames::volumechange);
2459 2456
2460 // If an element autoplayed while muted, it needs to be unlocked to unmute, 2457 // If an element autoplayed while muted, it needs to be unlocked to unmute,
2461 // otherwise, it will be paused. 2458 // otherwise, it will be paused.
2462 if (wasAutoplayingMuted) { 2459 if (wasAutoplayingMuted) {
2463 if (isGestureNeededForPlayback()) { 2460 if (isGestureNeededForPlayback()) {
2464 pause(); 2461 pause();
2465 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( 2462 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(
2466 AutoplayUnmuteActionStatus::Failure); 2463 AutoplayUnmuteActionStatus::Failure);
2467 } else { 2464 } else {
2468 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( 2465 m_autoplayUmaHelper->recordAutoplayUnmuteStatus(
2469 AutoplayUnmuteActionStatus::Success); 2466 AutoplayUnmuteActionStatus::Success);
2470 } 2467 }
2471 } 2468 }
2472 2469
2473 // This is called after the volumechange event to make sure isAutoplayingMuted 2470 // This is called after the volumechange event to make sure isAutoplayingMuted
2474 // returns the right value when webMediaPlayer receives the volume update. 2471 // returns the right value when webMediaPlayer receives the volume update.
2475 if (webMediaPlayer()) 2472 if (webMediaPlayer())
2476 webMediaPlayer()->setVolume(effectiveMediaVolume()); 2473 webMediaPlayer()->setVolume(effectiveMediaVolume());
2477 2474
2478 // If an element was a candidate for autoplay muted but not visible, it will 2475 // If an element was a candidate for autoplay muted but not visible, it will
2479 // have a visibility observer ready to start its playback. 2476 // start its playback once becomes visible.
2480 if (wasPendingAutoplayMuted) { 2477 if (wasPendingAutoplayMuted)
2481 m_autoplayVisibilityObserver->stop(); 2478 m_shouldAutoplayWhenVisible = false;
2482 m_autoplayVisibilityObserver = nullptr;
2483 }
2484 } 2479 }
2485 2480
2486 double HTMLMediaElement::effectiveMediaVolume() const { 2481 double HTMLMediaElement::effectiveMediaVolume() const {
2487 if (m_muted) 2482 if (m_muted)
2488 return 0; 2483 return 0;
2489 2484
2490 return m_volume; 2485 return m_volume;
2491 } 2486 }
2492 2487
2493 // The spec says to fire periodic timeupdate events (those sent while playing) 2488 // The spec says to fire periodic timeupdate events (those sent while playing)
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after
3833 visitor->trace(m_textTracks); 3828 visitor->trace(m_textTracks);
3834 visitor->trace(m_textTracksWhenResourceSelectionBegan); 3829 visitor->trace(m_textTracksWhenResourceSelectionBegan);
3835 visitor->trace(m_playPromiseResolvers); 3830 visitor->trace(m_playPromiseResolvers);
3836 visitor->trace(m_playPromiseResolveList); 3831 visitor->trace(m_playPromiseResolveList);
3837 visitor->trace(m_playPromiseRejectList); 3832 visitor->trace(m_playPromiseRejectList);
3838 visitor->trace(m_audioSourceProvider); 3833 visitor->trace(m_audioSourceProvider);
3839 visitor->trace(m_autoplayHelperClient); 3834 visitor->trace(m_autoplayHelperClient);
3840 visitor->trace(m_autoplayHelper); 3835 visitor->trace(m_autoplayHelper);
3841 visitor->trace(m_autoplayUmaHelper); 3836 visitor->trace(m_autoplayUmaHelper);
3842 visitor->trace(m_srcObject); 3837 visitor->trace(m_srcObject);
3843 visitor->trace(m_autoplayVisibilityObserver); 3838 visitor->trace(m_viewportIntersectionObserver);
3844 visitor->template registerWeakMembers<HTMLMediaElement, 3839 visitor->template registerWeakMembers<HTMLMediaElement,
3845 &HTMLMediaElement::clearWeakMembers>( 3840 &HTMLMediaElement::clearWeakMembers>(
3846 this); 3841 this);
3847 Supplementable<HTMLMediaElement>::trace(visitor); 3842 Supplementable<HTMLMediaElement>::trace(visitor);
3848 HTMLElement::trace(visitor); 3843 HTMLElement::trace(visitor);
3849 ActiveDOMObject::trace(visitor); 3844 ActiveDOMObject::trace(visitor);
3850 } 3845 }
3851 3846
3852 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) { 3847 DEFINE_TRACE_WRAPPERS(HTMLMediaElement) {
3853 visitor->traceWrappers(m_videoTracks); 3848 visitor->traceWrappers(m_videoTracks);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
4057 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 4052 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
4058 ("Media.Controls.Show.Video", MediaControlsShowMax)); 4053 ("Media.Controls.Show.Video", MediaControlsShowMax));
4059 return histogram; 4054 return histogram;
4060 } 4055 }
4061 4056
4062 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 4057 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
4063 ("Media.Controls.Show.Audio", MediaControlsShowMax)); 4058 ("Media.Controls.Show.Audio", MediaControlsShowMax));
4064 return histogram; 4059 return histogram;
4065 } 4060 }
4066 4061
4067 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { 4062 void HTMLMediaElement::onVideoViewportIntersectionChanged(
4068 if (!isVisible) 4063 const WebRect& rootRect,
4064 const WebRect& intersectRect) {
4065 WebMediaPlayer::ViewportIntersectionInfo info;
4066 info.rootRect = rootRect;
4067 info.intersectRect = intersectRect;
4068 if (m_webMediaPlayer)
4069 m_webMediaPlayer->videoViewportIntersectionChanged(info);
4070 m_currentViewportIntersection = info;
4071
4072 bool isVisible = !intersectRect.isEmpty();
4073 m_autoplayUmaHelper->visibilityMaybeChangedforMutedVideo(isVisible);
4074
4075 if (!isVisible || !m_shouldAutoplayWhenVisible)
4069 return; 4076 return;
4070 4077
4071 if (shouldAutoplay()) { 4078 if (shouldAutoplay()) {
4072 m_paused = false; 4079 m_paused = false;
4073 scheduleEvent(EventTypeNames::play); 4080 scheduleEvent(EventTypeNames::play);
4074 scheduleNotifyPlaying(); 4081 scheduleNotifyPlaying();
4075 m_autoplaying = false; 4082 m_autoplaying = false;
4076 4083
4077 updatePlayState(); 4084 updatePlayState();
4078 } 4085 }
4079 4086 m_shouldAutoplayWhenVisible = false;
4080 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay()
4081 // is never called. The leak comes from either ElementVisibilityObserver or
4082 // IntersectionObserver. Should keep an eye on it. See
4083 // https://crbug.com/627539
4084 m_autoplayVisibilityObserver->stop();
4085 m_autoplayVisibilityObserver = nullptr;
4086 } 4087 }
4087 4088
4088 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) { 4089 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) {
4089 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) { 4090 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) {
4090 getAudioSourceProvider().setClient(nullptr); 4091 getAudioSourceProvider().setClient(nullptr);
4091 m_audioSourceNode = nullptr; 4092 m_audioSourceNode = nullptr;
4092 } 4093 }
4093 } 4094 }
4094 4095
4095 void HTMLMediaElement::AudioSourceProviderImpl::wrap( 4096 void HTMLMediaElement::AudioSourceProviderImpl::wrap(
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4187 4188
4188 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() 4189 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect()
4189 const { 4190 const {
4190 IntRect result; 4191 IntRect result;
4191 if (LayoutObject* object = m_element->layoutObject()) 4192 if (LayoutObject* object = m_element->layoutObject())
4192 result = object->absoluteBoundingBoxRect(); 4193 result = object->absoluteBoundingBoxRect();
4193 return result; 4194 return result;
4194 } 4195 }
4195 4196
4196 } // namespace blink 4197 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLMediaElement.h ('k') | third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698