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

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

Issue 1179223002: Implement autoplay gesture override experiment. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: removed WebRuntimeFeatures.h whitespace-only change. Created 5 years, 5 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 reserved. 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows 242 // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows
243 // it cannot render. 243 // it cannot render.
244 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp ty()) { 244 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp ty()) {
245 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs, keySystem.lower ()); 245 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs, keySystem.lower ());
246 return supported > WebMimeRegistry::IsNotSupported; 246 return supported > WebMimeRegistry::IsNotSupported;
247 } 247 }
248 248
249 return false; 249 return false;
250 } 250 }
251 251
252 // These values are used for a histogram. Do not reorder. 252 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric)
253 enum AutoplayMetrics {
254 // Media element with autoplay seen.
255 AutoplayMediaFound = 0,
256 // Autoplay enabled and user stopped media play at any point.
257 AutoplayStopped = 1,
258 // Autoplay enabled but user bailed out on media play early.
259 AutoplayBailout = 2,
260 // Autoplay disabled but user manually started media.
261 AutoplayManualStart = 3,
262 // Autoplay was (re)enabled through a user-gesture triggered load()
263 AutoplayEnabledThroughLoad = 4,
264 // Autoplay disabled by sandbox flags.
265 AutoplayDisabledBySandbox = 5,
266 // This enum value must be last.
267 NumberOfAutoplayMetrics,
268 };
269
270 static void recordAutoplayMetric(AutoplayMetrics metric)
271 { 253 {
272 Platform::current()->histogramEnumeration("Blink.MediaElement.Autoplay", met ric, NumberOfAutoplayMetrics); 254 Platform::current()->histogramEnumeration("Blink.MediaElement.Autoplay", met ric, NumberOfAutoplayMetrics);
273 } 255 }
274 256
275 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType, const String& keySystem) 257 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType, const String& keySystem)
276 { 258 {
277 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); 259 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
278 260
279 if (!RuntimeEnabledFeatures::mediaEnabled()) 261 if (!RuntimeEnabledFeatures::mediaEnabled())
280 return WebMimeRegistry::IsNotSupported; 262 return WebMimeRegistry::IsNotSupported;
(...skipping 10 matching lines...) Expand all
291 // 4.8.10.3 MIME types - The canPlayType(type) method must return the empty string if type is a type that the 273 // 4.8.10.3 MIME types - The canPlayType(type) method must return the empty string if type is a type that the
292 // user agent knows it cannot render or is the type "application/octet-strea m" 274 // user agent knows it cannot render or is the type "application/octet-strea m"
293 if (type == "application/octet-stream") 275 if (type == "application/octet-stream")
294 return WebMimeRegistry::IsNotSupported; 276 return WebMimeRegistry::IsNotSupported;
295 277
296 return Platform::current()->mimeRegistry()->supportsMediaMIMEType(type, type Codecs, system); 278 return Platform::current()->mimeRegistry()->supportsMediaMIMEType(type, type Codecs, system);
297 } 279 }
298 280
299 URLRegistry* HTMLMediaElement::s_mediaStreamRegistry = 0; 281 URLRegistry* HTMLMediaElement::s_mediaStreamRegistry = 0;
300 282
283 class HTMLMediaElement::AutoplayExperimentScrollListener : public EventListener {
284 public:
285 AutoplayExperimentScrollListener(HTMLMediaElement* element) : EventListe ner(CPPEventListenerType), m_element(element) { }
286 virtual bool operator==(const EventListener& them)
287 {
288 return &them == this;
289 }
290
291 void handleEvent(ExecutionContext*, Event*) override
292 {
293 if (m_element)
294 m_element->autoplayExperimentMaybeStartPlaying();
295 }
296
297 private:
298 HTMLMediaElement* m_element;
299 };
300
301 void HTMLMediaElement::setMediaStreamRegistry(URLRegistry* registry) 301 void HTMLMediaElement::setMediaStreamRegistry(URLRegistry* registry)
302 { 302 {
303 ASSERT(!s_mediaStreamRegistry); 303 ASSERT(!s_mediaStreamRegistry);
304 s_mediaStreamRegistry = registry; 304 s_mediaStreamRegistry = registry;
305 } 305 }
306 306
307 bool HTMLMediaElement::isMediaStreamURL(const String& url) 307 bool HTMLMediaElement::isMediaStreamURL(const String& url)
308 { 308 {
309 return s_mediaStreamRegistry ? s_mediaStreamRegistry->contains(url) : false; 309 return s_mediaStreamRegistry ? s_mediaStreamRegistry->contains(url) : false;
310 } 310 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 , m_completelyLoaded(false) 352 , m_completelyLoaded(false)
353 , m_havePreparedToPlay(false) 353 , m_havePreparedToPlay(false)
354 , m_tracksAreReady(true) 354 , m_tracksAreReady(true)
355 , m_haveVisibleTextTrack(false) 355 , m_haveVisibleTextTrack(false)
356 , m_processingPreferenceChange(false) 356 , m_processingPreferenceChange(false)
357 , m_remoteRoutesAvailable(false) 357 , m_remoteRoutesAvailable(false)
358 , m_playingRemotely(false) 358 , m_playingRemotely(false)
359 , m_isFinalizing(false) 359 , m_isFinalizing(false)
360 , m_initialPlayWithoutUserGestures(false) 360 , m_initialPlayWithoutUserGestures(false)
361 , m_autoplayMediaCounted(false) 361 , m_autoplayMediaCounted(false)
362 , m_autoplayExperimentPlayPending(false)
363 , m_autoplayExperimentStartedByExperiment(false)
364 , m_autoplayExperimentMode(ExperimentOff)
362 , m_audioTracks(AudioTrackList::create(*this)) 365 , m_audioTracks(AudioTrackList::create(*this))
363 , m_videoTracks(VideoTrackList::create(*this)) 366 , m_videoTracks(VideoTrackList::create(*this))
364 , m_textTracks(nullptr) 367 , m_textTracks(nullptr)
365 #if ENABLE(WEB_AUDIO) 368 #if ENABLE(WEB_AUDIO)
366 , m_audioSourceNode(nullptr) 369 , m_audioSourceNode(nullptr)
367 #endif 370 #endif
368 { 371 {
369 #if ENABLE(OILPAN) 372 #if ENABLE(OILPAN)
370 ThreadState::current()->registerPreFinalizer(this); 373 ThreadState::current()->registerPreFinalizer(this);
371 #endif 374 #endif
372 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); 375 ASSERT(RuntimeEnabledFeatures::mediaEnabled());
373 376
374 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); 377 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this);
375 378
376 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) 379 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture())
377 m_userGestureRequiredForPlay = true; 380 m_userGestureRequiredForPlay = true;
378 381
382 if (document.settings()) {
383 const String& autoplayMode = document.settings()->autoplayExperimentMode ();
384 if (autoplayMode == "always") {
385 m_autoplayExperimentMode = ExperimentAlways;
386 } else if (autoplayMode == "if-muted") {
387 m_autoplayExperimentMode = ExperimentIfMuted;
388 } else if (autoplayMode == "play-muted") {
389 m_autoplayExperimentMode = ExperimentPlayMuted;
390 }
391
392 if (m_autoplayExperimentMode != ExperimentOff) {
393 WTF_LOG(Media, "HTMLMediaElement: autoplay experiment set to '%s'",
394 autoplayMode.ascii().data());
395 }
396 }
397
379 setHasCustomStyleCallbacks(); 398 setHasCustomStyleCallbacks();
380 addElementToDocumentMap(this, &document); 399 addElementToDocumentMap(this, &document);
381 } 400 }
382 401
383 HTMLMediaElement::~HTMLMediaElement() 402 HTMLMediaElement::~HTMLMediaElement()
384 { 403 {
385 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); 404 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this);
405
406 autoplayExperimentClearScrollListenerIfNeeded();
407
386 #if !ENABLE(OILPAN) 408 #if !ENABLE(OILPAN)
387 // HTMLMediaElement and m_asyncEventQueue always become unreachable 409 // HTMLMediaElement and m_asyncEventQueue always become unreachable
388 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in 410 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in
389 // the same GC. We don't need to close it explicitly in Oilpan. 411 // the same GC. We don't need to close it explicitly in Oilpan.
390 m_asyncEventQueue->close(); 412 m_asyncEventQueue->close();
391 413
392 setShouldDelayLoadEvent(false); 414 setShouldDelayLoadEvent(false);
393 415
394 if (m_textTracks) 416 if (m_textTracks)
395 m_textTracks->clearOwner(); 417 m_textTracks->clearOwner();
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 scheduleEvent(EventTypeNames::canplay); 1538 scheduleEvent(EventTypeNames::canplay);
1517 if (isPotentiallyPlaying) 1539 if (isPotentiallyPlaying)
1518 scheduleEvent(EventTypeNames::playing); 1540 scheduleEvent(EventTypeNames::playing);
1519 } 1541 }
1520 1542
1521 if (m_autoplaying && m_paused && autoplay()) { 1543 if (m_autoplaying && m_paused && autoplay()) {
1522 autoplayMediaEncountered(); 1544 autoplayMediaEncountered();
1523 1545
1524 if (document().isSandboxed(SandboxAutomaticFeatures)) { 1546 if (document().isSandboxed(SandboxAutomaticFeatures)) {
1525 recordAutoplayMetric(AutoplayDisabledBySandbox); 1547 recordAutoplayMetric(AutoplayDisabledBySandbox);
1526 } else if (!m_userGestureRequiredForPlay) { 1548 } else {
1527 m_paused = false; 1549 // If the autoplay experiment says that it's okay to play now,
1528 invalidateCachedTime(); 1550 // then don't require a user gesture.
1529 scheduleEvent(EventTypeNames::play); 1551 if (autoplayExperimentIsEligible()) {
1530 scheduleEvent(EventTypeNames::playing); 1552 if (autoplayExperimentIsVisible()) {
1553 autoplayExperimentPrepareToPlay(AutoplayExperimentStarte dByLoad);
1554 // Will play below.
1555 } else {
1556 // Wait for visibility checks to pass.
1557 autoplayExperimentInstallScrollListenerIfNeeded();
1558 }
1559 }
1560
1561 if (!m_userGestureRequiredForPlay) {
1562 m_paused = false;
1563 invalidateCachedTime();
1564 scheduleEvent(EventTypeNames::play);
1565 scheduleEvent(EventTypeNames::playing);
1566 }
1531 } 1567 }
1532 } 1568 }
1533 1569
1534 scheduleEvent(EventTypeNames::canplaythrough); 1570 scheduleEvent(EventTypeNames::canplaythrough);
1535 1571
1536 shouldUpdateDisplayState = true; 1572 shouldUpdateDisplayState = true;
1537 } 1573 }
1538 1574
1539 if (shouldUpdateDisplayState) { 1575 if (shouldUpdateDisplayState) {
1540 updateDisplayState(); 1576 updateDisplayState();
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 1955
1920 MediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const 1956 MediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const
1921 { 1957 {
1922 return autoplay() ? MediaPlayer::Auto : preloadType(); 1958 return autoplay() ? MediaPlayer::Auto : preloadType();
1923 } 1959 }
1924 1960
1925 void HTMLMediaElement::play() 1961 void HTMLMediaElement::play()
1926 { 1962 {
1927 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); 1963 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this);
1928 1964
1965 // Set the pending state, even if the play isn't going to be pending.
1966 // Eligibility can change if, for example, the mute status changes.
1967 // Having this set is okay.
1968 m_autoplayExperimentPlayPending = true;
1969
1929 if (!UserGestureIndicator::processingUserGesture()) { 1970 if (!UserGestureIndicator::processingUserGesture()) {
1930 autoplayMediaEncountered(); 1971 autoplayMediaEncountered();
1972
1973 if (autoplayExperimentIsEligible()) {
1974 // Remember that m_userGestureRequiredForPlay is required for
1975 // us to be eligible for the experiment.
1976 // If we are able to override the gesture requirement now, then
1977 // do so. Otherwise, install a scroll listener if we need one.
1978 if (autoplayExperimentIsVisible()) {
1979 // Override the gesture and play.
1980 autoplayExperimentPrepareToPlay(AutoplayExperimentStartedByPlay) ;
1981 } else {
1982 // Wait for visibility.
1983 autoplayExperimentInstallScrollListenerIfNeeded();
1984 }
1985 }
1986
1931 if (m_userGestureRequiredForPlay) { 1987 if (m_userGestureRequiredForPlay) {
1932 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture."); 1988 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture.");
1933 document().executionContext()->addConsoleMessage(ConsoleMessage::cre ate(JSMessageSource, WarningMessageLevel, message)); 1989 document().executionContext()->addConsoleMessage(ConsoleMessage::cre ate(JSMessageSource, WarningMessageLevel, message));
1934 return; 1990 return;
1935 } 1991 }
1936 } else if (m_userGestureRequiredForPlay) { 1992 } else if (m_userGestureRequiredForPlay) {
1937 if (m_autoplayMediaCounted) 1993 if (m_autoplayMediaCounted)
1938 recordAutoplayMetric(AutoplayManualStart); 1994 recordAutoplayMetric(AutoplayManualStart);
1939 m_userGestureRequiredForPlay = false; 1995 m_userGestureRequiredForPlay = false;
1996 autoplayExperimentClearScrollListenerIfNeeded();
1940 } 1997 }
1941 1998
1942 playInternal(); 1999 playInternal();
1943 } 2000 }
1944 2001
1945 void HTMLMediaElement::playInternal() 2002 void HTMLMediaElement::playInternal()
1946 { 2003 {
1947 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); 2004 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this);
1948 2005
1949 // 4.8.10.9. Playing the media resource 2006 // 4.8.10.9. Playing the media resource
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1986 } 2043 }
1987 } 2044 }
1988 2045
1989 void HTMLMediaElement::gesturelessInitialPlayHalted() 2046 void HTMLMediaElement::gesturelessInitialPlayHalted()
1990 { 2047 {
1991 ASSERT(m_initialPlayWithoutUserGestures); 2048 ASSERT(m_initialPlayWithoutUserGestures);
1992 m_initialPlayWithoutUserGestures = false; 2049 m_initialPlayWithoutUserGestures = false;
1993 2050
1994 recordAutoplayMetric(AutoplayStopped); 2051 recordAutoplayMetric(AutoplayStopped);
1995 2052
2053 if (m_autoplayExperimentStartedByExperiment)
2054 recordAutoplayMetric(AutoplayExperimentStopped);
2055
1996 // We count the user as having bailed-out on the video if they watched 2056 // We count the user as having bailed-out on the video if they watched
1997 // less than one minute and less than 50% of it. 2057 // less than one minute and less than 50% of it.
1998 double playedTime = currentTime(); 2058 double playedTime = currentTime();
1999 if (playedTime < 60) { 2059 if (playedTime < 60) {
2000 double progress = playedTime / duration(); 2060 double progress = playedTime / duration();
2001 if (progress < 0.5) 2061 if (progress < 0.5) {
2002 recordAutoplayMetric(AutoplayBailout); 2062 recordAutoplayMetric(AutoplayBailout);
2063 // If this autoplay was started by the experiment, then record
2064 // that separately.
2065 if (m_autoplayExperimentStartedByExperiment)
2066 recordAutoplayMetric(AutoplayExperimentBailout);
2067 }
2003 } 2068 }
2004 } 2069 }
2005 2070
2006 void HTMLMediaElement::pause() 2071 void HTMLMediaElement::pause()
2007 { 2072 {
2008 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); 2073 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this);
2009 2074
2010 if (!m_player || m_networkState == NETWORK_EMPTY) 2075 if (!m_player || m_networkState == NETWORK_EMPTY)
2011 scheduleDelayedAction(LoadMediaResource); 2076 scheduleDelayedAction(LoadMediaResource);
2012 2077
2078 // Don't try to autoplay, if we would have.
2079 m_autoplayExperimentPlayPending = false;
2080 autoplayExperimentClearScrollListenerIfNeeded();
2081
2013 m_autoplaying = false; 2082 m_autoplaying = false;
2014 2083
2015 if (!m_paused) { 2084 if (!m_paused) {
2016 if (m_initialPlayWithoutUserGestures) 2085 if (m_initialPlayWithoutUserGestures)
2017 gesturelessInitialPlayHalted(); 2086 gesturelessInitialPlayHalted();
2018 2087
2019 m_paused = true; 2088 m_paused = true;
2020 scheduleTimeupdateEvent(false); 2089 scheduleTimeupdateEvent(false);
2021 scheduleEvent(EventTypeNames::pause); 2090 scheduleEvent(EventTypeNames::pause);
2022 } 2091 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2100 2169
2101 void HTMLMediaElement::setMuted(bool muted) 2170 void HTMLMediaElement::setMuted(bool muted)
2102 { 2171 {
2103 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) ); 2172 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) );
2104 2173
2105 if (m_muted == muted) 2174 if (m_muted == muted)
2106 return; 2175 return;
2107 2176
2108 m_muted = muted; 2177 m_muted = muted;
2109 2178
2179 // If we are no longer eligible for the autoplay experiment, then also
2180 // quit listening to scroll events. If we are eligible, and if we should
2181 // be playing, then start playing. In other words, start playing if
2182 // we just needed 'mute' to autoplay.
2183 if (!autoplayExperimentIsEligible()) {
2184 autoplayExperimentClearScrollListenerIfNeeded();
2185 } else {
2186 // Try to play. If we can't, then install a visibility listener.
2187 if (!autoplayExperimentMaybeStartPlaying())
2188 autoplayExperimentInstallScrollListenerIfNeeded();
2189 }
2190
2110 updateVolume(); 2191 updateVolume();
2111 2192
2112 scheduleEvent(EventTypeNames::volumechange); 2193 scheduleEvent(EventTypeNames::volumechange);
2113 } 2194 }
2114 2195
2115 void HTMLMediaElement::updateVolume() 2196 void HTMLMediaElement::updateVolume()
2116 { 2197 {
2117 if (webMediaPlayer()) 2198 if (webMediaPlayer())
2118 webMediaPlayer()->setVolume(effectiveMediaVolume()); 2199 webMediaPlayer()->setVolume(effectiveMediaVolume());
2119 2200
(...skipping 1584 matching lines...) Expand 10 before | Expand all | Expand 10 after
3704 } 3785 }
3705 3786
3706 #if ENABLE(WEB_AUDIO) 3787 #if ENABLE(WEB_AUDIO)
3707 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) 3788 void HTMLMediaElement::clearWeakMembers(Visitor* visitor)
3708 { 3789 {
3709 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider()) 3790 if (!Heap::isHeapObjectAlive(m_audioSourceNode) && audioSourceProvider())
3710 audioSourceProvider()->setClient(nullptr); 3791 audioSourceProvider()->setClient(nullptr);
3711 } 3792 }
3712 #endif 3793 #endif
3713 3794
3795 void HTMLMediaElement::autoplayExperimentInstallScrollListenerIfNeeded()
3796 {
3797 if (document().domWindow() && !m_autoplayExperimentScrollListener) {
3798 m_autoplayExperimentScrollListener = adoptRef(new AutoplayExperimentScro llListener(this));
3799 document().domWindow()->addEventListener("scroll", m_autoplayExperimentS crollListener, false);
philipj_slow 2015/07/21 12:51:29 I take it this will prevent smooth scrolling while
liberato (no reviews please) 2015/07/27 06:03:09 good point. we really only care if it ends up in
Rick Byers 2015/08/05 14:27:59 Listening to scroll events doesn't "prevent smooth
philipj_slow 2015/08/05 14:40:12 Oh... http://rbyers.github.io/EventListenerOptions
3800 }
3714 } 3801 }
3802
3803 void HTMLMediaElement::autoplayExperimentClearScrollListenerIfNeeded()
3804 {
3805 if (m_autoplayExperimentScrollListener) {
3806 LocalDOMWindow* domWindow = document().domWindow();
3807 if (domWindow) {
3808 domWindow->removeEventListener("scroll", m_autoplayExperimentScrollL istener, false);
3809 }
3810 // Either way, clear our ref.
3811 m_autoplayExperimentScrollListener.clear();
3812 }
3813 }
3814
3815 bool HTMLMediaElement::autoplayExperimentIsVisible()
3816 {
3817 // We could check for eligibility here, but we skip it. Some of our
3818 // callers need to do it separately, and we don't want to check more
3819 // than we need to.
3820
3821 // Autoplay is requested, and we're willing to override if the visibility
3822 // requirements are met.
3823
3824 // Check visibility.
3825 const LocalDOMWindow* domWindow = document().domWindow();
3826 if (!domWindow)
3827 return false;
3828
3829 FloatRect us(offsetLeft(), offsetTop(), clientWidth(), clientHeight());
3830 FloatRect screen(domWindow->scrollX(), domWindow->scrollY(), domWindow->inne rWidth(), domWindow->innerHeight());
3831
3832 return screen.contains(us);
3833 }
3834
3835 bool HTMLMediaElement::autoplayExperimentMaybeStartPlaying()
3836 {
3837 // Make sure that we're eligible and visible.
3838 if (!autoplayExperimentIsEligible() || !autoplayExperimentIsVisible()) {
3839 return false;
3840 }
3841
3842 // Start playing!
3843 autoplayExperimentPrepareToPlay(AutoplayExperimentStartedByScroll);
3844 // Why are we always preparing? Just go!
3845 playInternal();
3846
3847 return true;
3848 }
3849
3850 bool HTMLMediaElement::autoplayExperimentIsEligible() const
3851 {
3852 // If no user gesture is required, then the experiment doesn't apply.
3853 // This is what prevents us from starting playback more than once.
3854 // Since this flag is never set to true once it's cleared, it will block
3855 // the autoplay experiment forever.
3856 if (!m_userGestureRequiredForPlay)
3857 return false;
3858
3859 if (m_autoplayExperimentMode == ExperimentOff)
3860 return false;
3861
3862 // If nobody has requested playback, either by the autoplay attribute or
3863 // a play() call, then do nothing.
3864 if (!m_autoplayExperimentPlayPending && !autoplay())
3865 return false;
3866
3867 // If the video is already playing, then do nothing. Note that there
3868 // is not a path where a user gesture is required but the video is
3869 // playing. However, we check for completeness.
3870 if (!m_paused)
3871 return false;
3872
3873 // Note that the viewport test always returns false on desktop. For
3874 // tests, we allow an override.
3875 const bool optimizedForMobile = document().viewportDescription().isLegacyVie wportType()
3876 || (document().settings() && document().settings()->overrideOptimizedFor MobileCheck());
3877
3878 if (!optimizedForMobile)
3879 return false;
3880
3881 if (m_autoplayExperimentMode == ExperimentIfMuted) {
3882 // If media is muted, then autoplay when it comes into view.
3883 return fastHasAttribute(mutedAttr) || m_muted;
3884 }
3885
3886 // Autoplay when it comes into view, maybe muted.
3887 return true;
3888 }
3889
3890 void HTMLMediaElement::autoplayExperimentMuteIfNeeded()
3891 {
3892 if (m_autoplayExperimentMode == ExperimentPlayMuted) {
3893 m_muted = true;
3894 updateVolume();
3895 }
3896 }
3897
3898 void HTMLMediaElement::autoplayExperimentPrepareToPlay(AutoplayMetrics metric)
3899 {
3900 recordAutoplayMetric(metric);
3901
3902 // This also causes !autoplayExperimentIsEligible, so that we don't
3903 // allow autoplay more than once.
3904 m_userGestureRequiredForPlay = false;
3905
3906 m_autoplayExperimentStartedByExperiment = true;
3907 autoplayExperimentClearScrollListenerIfNeeded();
3908 autoplayExperimentMuteIfNeeded();
3909
3910 // Record that this autoplayed without a user gesture. This is normally
3911 // set when we discover an autoplay attribute, but we include all cases
3912 // where playback started without a user gesture, e.g., play().
3913 m_initialPlayWithoutUserGestures = true;
3914 }
3915
3916 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698