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

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

Issue 2654123002: Autoplay muted video when visible and pause when invisible (Closed)
Patch Set: improved tests Created 3 years, 10 months 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 m_displayMode(Unknown), 405 m_displayMode(Unknown),
406 m_officialPlaybackPosition(0), 406 m_officialPlaybackPosition(0),
407 m_officialPlaybackPositionNeedsUpdate(true), 407 m_officialPlaybackPositionNeedsUpdate(true),
408 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), 408 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()),
409 m_pendingActionFlags(0), 409 m_pendingActionFlags(0),
410 m_lockedPendingUserGesture(false), 410 m_lockedPendingUserGesture(false),
411 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled(true), 411 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled(true),
412 m_playing(false), 412 m_playing(false),
413 m_shouldDelayLoadEvent(false), 413 m_shouldDelayLoadEvent(false),
414 m_haveFiredLoadedData(false), 414 m_haveFiredLoadedData(false),
415 m_autoplaying(true), 415 m_canAutoplay(true),
416 m_muted(false), 416 m_muted(false),
417 m_paused(true), 417 m_paused(true),
418 m_seeking(false), 418 m_seeking(false),
419 m_sentStalledEvent(false), 419 m_sentStalledEvent(false),
420 m_ignorePreloadNone(false), 420 m_ignorePreloadNone(false),
421 m_textTracksVisible(false), 421 m_textTracksVisible(false),
422 m_shouldPerformAutomaticTrackSelection(true), 422 m_shouldPerformAutomaticTrackSelection(true),
423 m_tracksAreReady(true), 423 m_tracksAreReady(true),
424 m_processingPreferenceChange(false), 424 m_processingPreferenceChange(false),
425 m_playingRemotely(false), 425 m_playingRemotely(false),
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 // This is where that change would have an effect, and it is measured to 856 // This is where that change would have an effect, and it is measured to
857 // verify the assumption that it's a very rare situation. 857 // verify the assumption that it's a very rare situation.
858 UseCounter::count(document(), 858 UseCounter::count(document(),
859 UseCounter::HTMLMediaElementLoadNetworkEmptyNotPaused); 859 UseCounter::HTMLMediaElementLoadNetworkEmptyNotPaused);
860 } 860 }
861 861
862 // 7 - Set the playbackRate attribute to the value of the defaultPlaybackRate 862 // 7 - Set the playbackRate attribute to the value of the defaultPlaybackRate
863 // attribute. 863 // attribute.
864 setPlaybackRate(defaultPlaybackRate()); 864 setPlaybackRate(defaultPlaybackRate());
865 865
866 // 8 - Set the error attribute to null and the autoplaying flag to true. 866 // 8 - Set the error attribute to null and the can autoplay flag to true.
867 m_error = nullptr; 867 m_error = nullptr;
868 m_autoplaying = true; 868 m_canAutoplay = true;
869 869
870 // 9 - Invoke the media element's resource selection algorithm. 870 // 9 - Invoke the media element's resource selection algorithm.
871 invokeResourceSelectionAlgorithm(); 871 invokeResourceSelectionAlgorithm();
872 872
873 // 10 - Note: Playback of any previously playing media resource for this 873 // 10 - Note: Playback of any previously playing media resource for this
874 // element stops. 874 // element stops.
875 } 875 }
876 876
877 void HTMLMediaElement::invokeResourceSelectionAlgorithm() { 877 void HTMLMediaElement::invokeResourceSelectionAlgorithm() {
878 BLINK_MEDIA_LOG << "invokeResourceSelectionAlgorithm(" << (void*)this << ")"; 878 BLINK_MEDIA_LOG << "invokeResourceSelectionAlgorithm(" << (void*)this << ")";
(...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 m_autoplayVisibilityObserver = new ElementVisibilityObserver( 1744 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1745 this, 1745 this,
1746 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, 1746 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1747 wrapWeakPersistent(this))); 1747 wrapWeakPersistent(this)));
1748 m_autoplayVisibilityObserver->start(); 1748 m_autoplayVisibilityObserver->start();
1749 } 1749 }
1750 } else { 1750 } else {
1751 m_paused = false; 1751 m_paused = false;
1752 scheduleEvent(EventTypeNames::play); 1752 scheduleEvent(EventTypeNames::play);
1753 scheduleNotifyPlaying(); 1753 scheduleNotifyPlaying();
1754 m_autoplaying = false; 1754 m_canAutoplay = false;
1755 } 1755 }
1756 } else { 1756 } else {
1757 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( 1757 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
1758 CrossOriginAutoplayResult::AutoplayBlocked); 1758 CrossOriginAutoplayResult::AutoplayBlocked);
1759 } 1759 }
1760 } 1760 }
1761 1761
1762 scheduleEvent(EventTypeNames::canplaythrough); 1762 scheduleEvent(EventTypeNames::canplaythrough);
1763 1763
1764 shouldUpdateDisplayState = true; 1764 shouldUpdateDisplayState = true;
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2091 return endedPlayback() && getDirectionOfPlayback() == Forward; 2091 return endedPlayback() && getDirectionOfPlayback() == Forward;
2092 } 2092 }
2093 2093
2094 bool HTMLMediaElement::autoplay() const { 2094 bool HTMLMediaElement::autoplay() const {
2095 return fastHasAttribute(autoplayAttr); 2095 return fastHasAttribute(autoplayAttr);
2096 } 2096 }
2097 2097
2098 bool HTMLMediaElement::shouldAutoplay() { 2098 bool HTMLMediaElement::shouldAutoplay() {
2099 if (document().isSandboxed(SandboxAutomaticFeatures)) 2099 if (document().isSandboxed(SandboxAutomaticFeatures))
2100 return false; 2100 return false;
2101 return m_autoplaying && m_paused && autoplay(); 2101 return m_canAutoplay && m_paused && autoplay();
2102 } 2102 }
2103 2103
2104 String HTMLMediaElement::preload() const { 2104 String HTMLMediaElement::preload() const {
2105 return preloadTypeToString(preloadType()); 2105 return preloadTypeToString(preloadType());
2106 } 2106 }
2107 2107
2108 void HTMLMediaElement::setPreload(const AtomicString& preload) { 2108 void HTMLMediaElement::setPreload(const AtomicString& preload) {
2109 BLINK_MEDIA_LOG << "setPreload(" << (void*)this << ", " << preload << ")"; 2109 BLINK_MEDIA_LOG << "setPreload(" << (void*)this << ", " << preload << ")";
2110 setAttribute(preloadAttr, preload); 2110 setAttribute(preloadAttr, preload);
2111 } 2111 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 } else { 2240 } else {
2241 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( 2241 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
2242 CrossOriginAutoplayResult::PlayedWithGesture); 2242 CrossOriginAutoplayResult::PlayedWithGesture);
2243 UserGestureIndicator::utilizeUserGesture(); 2243 UserGestureIndicator::utilizeUserGesture();
2244 unlockUserGesture(); 2244 unlockUserGesture();
2245 } 2245 }
2246 2246
2247 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) 2247 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported)
2248 return NotSupportedError; 2248 return NotSupportedError;
2249 2249
2250 if (m_autoplayVisibilityObserver) {
2251 m_autoplayVisibilityObserver->stop();
2252 m_autoplayVisibilityObserver = nullptr;
2253 }
2254
2250 playInternal(); 2255 playInternal();
2251 2256
2252 return nullptr; 2257 return nullptr;
2253 } 2258 }
2254 2259
2255 void HTMLMediaElement::playInternal() { 2260 void HTMLMediaElement::playInternal() {
2256 BLINK_MEDIA_LOG << "playInternal(" << (void*)this << ")"; 2261 BLINK_MEDIA_LOG << "playInternal(" << (void*)this << ")";
2257 2262
2258 // Always return the buffering strategy to normal when not paused, 2263 // Always return the buffering strategy to normal when not paused,
2259 // regardless of the cause. (In contrast with aggressive buffering which is 2264 // regardless of the cause. (In contrast with aggressive buffering which is
(...skipping 17 matching lines...) Expand all
2277 scheduleEvent(EventTypeNames::play); 2282 scheduleEvent(EventTypeNames::play);
2278 2283
2279 if (m_readyState <= kHaveCurrentData) 2284 if (m_readyState <= kHaveCurrentData)
2280 scheduleEvent(EventTypeNames::waiting); 2285 scheduleEvent(EventTypeNames::waiting);
2281 else if (m_readyState >= kHaveFutureData) 2286 else if (m_readyState >= kHaveFutureData)
2282 scheduleNotifyPlaying(); 2287 scheduleNotifyPlaying();
2283 } else if (m_readyState >= kHaveFutureData) { 2288 } else if (m_readyState >= kHaveFutureData) {
2284 scheduleResolvePlayPromises(); 2289 scheduleResolvePlayPromises();
2285 } 2290 }
2286 2291
2287 m_autoplaying = false; 2292 m_canAutoplay = false;
2288 2293
2289 setIgnorePreloadNone(); 2294 setIgnorePreloadNone();
2290 updatePlayState(); 2295 updatePlayState();
2291 } 2296 }
2292 2297
2293 void HTMLMediaElement::pause() { 2298 void HTMLMediaElement::pause() {
2294 BLINK_MEDIA_LOG << "pause(" << (void*)this << ")"; 2299 BLINK_MEDIA_LOG << "pause(" << (void*)this << ")";
2295 2300
2296 // Only buffer aggressively on a user-initiated pause. Other types of pauses 2301 // Only buffer aggressively on a user-initiated pause. Other types of pauses
2297 // (which go directly to pauseInternal()) should not cause this behavior. 2302 // (which go directly to pauseInternal()) should not cause this behavior.
2298 if (webMediaPlayer() && UserGestureIndicator::utilizeUserGesture()) 2303 if (webMediaPlayer() && UserGestureIndicator::utilizeUserGesture())
2299 webMediaPlayer()->setBufferingStrategy( 2304 webMediaPlayer()->setBufferingStrategy(
2300 WebMediaPlayer::BufferingStrategy::Aggressive); 2305 WebMediaPlayer::BufferingStrategy::Aggressive);
2301 2306
2307 if (m_autoplayVisibilityObserver) {
2308 m_autoplayVisibilityObserver->stop();
2309 m_autoplayVisibilityObserver = nullptr;
2310 }
2311
2302 pauseInternal(); 2312 pauseInternal();
2303 } 2313 }
2304 2314
2305 void HTMLMediaElement::pauseInternal() { 2315 void HTMLMediaElement::pauseInternal() {
2306 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")"; 2316 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")";
2307 2317
2308 if (m_networkState == kNetworkEmpty) 2318 if (m_networkState == kNetworkEmpty)
2309 invokeResourceSelectionAlgorithm(); 2319 invokeResourceSelectionAlgorithm();
2310 2320
2311 m_autoplaying = false; 2321 m_canAutoplay = false;
2312 2322
2313 if (!m_paused) { 2323 if (!m_paused) {
2314 m_paused = true; 2324 m_paused = true;
2315 scheduleTimeupdateEvent(false); 2325 scheduleTimeupdateEvent(false);
2316 scheduleEvent(EventTypeNames::pause); 2326 scheduleEvent(EventTypeNames::pause);
2317 2327
2318 // Force an update to official playback position. Automatic updates from 2328 // Force an update to official playback position. Automatic updates from
2319 // currentPlaybackPosition() will be blocked while m_paused = true. This 2329 // currentPlaybackPosition() will be blocked while m_paused = true. This
2320 // blocking is desired while paused, but its good to update it one final 2330 // blocking is desired while paused, but its good to update it one final
2321 // time to accurately reflect movie time at the moment we paused. 2331 // time to accurately reflect movie time at the moment we paused.
(...skipping 1672 matching lines...) Expand 10 before | Expand all | Expand 10 after
3994 ("Media.Controls.Show.Video", MediaControlsShowMax)); 4004 ("Media.Controls.Show.Video", MediaControlsShowMax));
3995 return histogram; 4005 return histogram;
3996 } 4006 }
3997 4007
3998 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 4008 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
3999 ("Media.Controls.Show.Audio", MediaControlsShowMax)); 4009 ("Media.Controls.Show.Audio", MediaControlsShowMax));
4000 return histogram; 4010 return histogram;
4001 } 4011 }
4002 4012
4003 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) { 4013 void HTMLMediaElement::onVisibilityChangedForAutoplay(bool isVisible) {
4004 if (!isVisible) 4014 if (!isVisible) {
4015 if (m_canAutoplay && autoplay()) {
mlamouri (slow - plz ping) 2017/02/14 20:59:02 Would it make sense to add a DCHECK(isAutoplayMute
Zhiqiang Zhang (Slow) 2017/02/14 21:47:31 Hmm, it might hit this DCHECK when the page calls
4016 pauseInternal();
4017 m_canAutoplay = true;
4018 }
4005 return; 4019 return;
4020 }
4006 4021
4007 if (shouldAutoplay()) { 4022 if (shouldAutoplay()) {
4008 m_paused = false; 4023 m_paused = false;
4009 scheduleEvent(EventTypeNames::play); 4024 scheduleEvent(EventTypeNames::play);
4010 scheduleNotifyPlaying(); 4025 scheduleNotifyPlaying();
4011 m_autoplaying = false;
4012 4026
4013 updatePlayState(); 4027 updatePlayState();
4014 } 4028 }
4015
4016 // TODO(zqzhang): There's still flaky leak if onVisibilityChangedForAutoplay()
4017 // is never called. The leak comes from either ElementVisibilityObserver or
4018 // IntersectionObserver. Should keep an eye on it. See
4019 // https://crbug.com/627539
4020 m_autoplayVisibilityObserver->stop();
4021 m_autoplayVisibilityObserver = nullptr;
4022 } 4029 }
4023 4030
4024 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) { 4031 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) {
4025 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) { 4032 if (!ThreadHeap::isHeapObjectAlive(m_audioSourceNode)) {
4026 getAudioSourceProvider().setClient(nullptr); 4033 getAudioSourceProvider().setClient(nullptr);
4027 m_audioSourceNode = nullptr; 4034 m_audioSourceNode = nullptr;
4028 } 4035 }
4029 } 4036 }
4030 4037
4031 void HTMLMediaElement::AudioSourceProviderImpl::wrap( 4038 void HTMLMediaElement::AudioSourceProviderImpl::wrap(
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4126 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE); 4133 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE);
4127 } 4134 }
4128 4135
4129 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) { 4136 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) {
4130 m_mostlyFillingViewport = true; 4137 m_mostlyFillingViewport = true;
4131 if (m_webMediaPlayer) 4138 if (m_webMediaPlayer)
4132 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport); 4139 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport);
4133 } 4140 }
4134 4141
4135 } // namespace blink 4142 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698