Index: Source/core/html/HTMLMediaElement.cpp |
diff --git a/Source/core/html/HTMLMediaElement.cpp b/Source/core/html/HTMLMediaElement.cpp |
index ef4a05ad0d62be0329b56a7988629cce0241fb62..b8773b06417d72ed30f4d3595197a1538a418b2b 100644 |
--- a/Source/core/html/HTMLMediaElement.cpp |
+++ b/Source/core/html/HTMLMediaElement.cpp |
@@ -247,25 +247,7 @@ static bool canLoadURL(const KURL& url, const ContentType& contentType, const St |
return false; |
} |
-// These values are used for a histogram. Do not reorder. |
-enum AutoplayMetrics { |
- // Media element with autoplay seen. |
- AutoplayMediaFound = 0, |
- // Autoplay enabled and user stopped media play at any point. |
- AutoplayStopped = 1, |
- // Autoplay enabled but user bailed out on media play early. |
- AutoplayBailout = 2, |
- // Autoplay disabled but user manually started media. |
- AutoplayManualStart = 3, |
- // Autoplay was (re)enabled through a user-gesture triggered load() |
- AutoplayEnabledThroughLoad = 4, |
- // Autoplay disabled by sandbox flags. |
- AutoplayDisabledBySandbox = 5, |
- // This enum value must be last. |
- NumberOfAutoplayMetrics, |
-}; |
- |
-static void recordAutoplayMetric(AutoplayMetrics metric) |
+void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) |
{ |
Platform::current()->histogramEnumeration("Blink.MediaElement.Autoplay", metric, NumberOfAutoplayMetrics); |
} |
@@ -355,7 +337,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum |
, m_remoteRoutesAvailable(false) |
, m_playingRemotely(false) |
, m_isFinalizing(false) |
- , m_initialPlayWithoutUserGestures(false) |
+ , m_initialPlayWithoutUserGesture(false) |
, m_autoplayMediaCounted(false) |
, m_inOverlayFullscreenVideo(false) |
, m_audioTracks(AudioTrackList::create(*this)) |
@@ -364,6 +346,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum |
#if ENABLE(WEB_AUDIO) |
, m_audioSourceNode(nullptr) |
#endif |
+ , m_autoplayHelper(*this) |
{ |
#if ENABLE(OILPAN) |
ThreadState::current()->registerPreFinalizer(this); |
@@ -382,6 +365,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum |
HTMLMediaElement::~HTMLMediaElement() |
{ |
WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); |
+ |
#if !ENABLE(OILPAN) |
// HTMLMediaElement and m_asyncEventQueue always become unreachable |
// together. So HTMLMediaElement and m_asyncEventQueue are destructed in |
@@ -691,12 +675,37 @@ String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySy |
return canPlay; |
} |
+void HTMLMediaElement::recordMetricsIfPausing() |
+{ |
+ // If not playing, then nothing to record. |
+ if (!m_playing) |
philipj_slow
2015/09/02 09:24:12
Use m_paused here unless there's a reason to use m
liberato (no reviews please)
2015/09/04 06:49:46
i think i used m_paused originally, but switched a
philipj_slow
2015/09/04 08:42:29
OK, whatever you find out please let me know, what
|
+ return; |
+ |
+ const bool bailout = isBailout(); |
+ |
+ // Record that play was paused. We don't care if it was autoplay, |
+ // play(), or the user manually started it. |
+ recordAutoplayMetric(AnyPlaybackPaused); |
+ if (bailout) |
+ recordAutoplayMetric(AnyPlaybackBailout); |
+ |
+ // If this was a gestureless play, then record that separately. |
+ // These cover attr and play() gestureless starts. |
+ if (m_initialPlayWithoutUserGesture) { |
+ m_initialPlayWithoutUserGesture = false; |
+ |
+ recordAutoplayMetric(AutoplayPaused); |
+ |
+ if (bailout) |
+ recordAutoplayMetric(AutoplayBailout); |
+ } |
+} |
+ |
void HTMLMediaElement::load() |
{ |
WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); |
- if (m_initialPlayWithoutUserGestures && m_playing) |
- gesturelessInitialPlayHalted(); |
+ recordMetricsIfPausing(); |
if (UserGestureIndicator::processingUserGesture() && m_userGestureRequiredForPlay) { |
recordAutoplayMetric(AutoplayEnabledThroughLoad); |
@@ -1555,11 +1564,17 @@ void HTMLMediaElement::setReadyState(ReadyState state) |
if (document().isSandboxed(SandboxAutomaticFeatures)) { |
recordAutoplayMetric(AutoplayDisabledBySandbox); |
- } else if (!m_userGestureRequiredForPlay) { |
- m_paused = false; |
- invalidateCachedTime(); |
- scheduleEvent(EventTypeNames::play); |
- scheduleEvent(EventTypeNames::playing); |
+ } else { |
+ // If the autoplay experiment says that it's okay to play now, |
+ // then don't require a user gesture. |
+ m_autoplayHelper.becameReadyToPlay(); |
+ |
+ if (!m_userGestureRequiredForPlay) { |
+ m_paused = false; |
+ invalidateCachedTime(); |
+ scheduleEvent(EventTypeNames::play); |
+ scheduleEvent(EventTypeNames::playing); |
+ } |
} |
} |
@@ -1692,7 +1707,7 @@ void HTMLMediaElement::seek(double time) |
// 11 - Set the current playback position to the given new playback position. |
webMediaPlayer()->seek(time); |
- m_initialPlayWithoutUserGestures = false; |
+ m_initialPlayWithoutUserGesture = false; |
// 14-17 are handled, if necessary, when the engine signals a readystate change or otherwise |
// satisfies seek completion and signals a time change. |
@@ -1942,9 +1957,13 @@ void HTMLMediaElement::play() |
{ |
WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); |
+ m_autoplayHelper.playMethodCalled(); |
+ |
if (!UserGestureIndicator::processingUserGesture()) { |
autoplayMediaEncountered(); |
+ |
if (m_userGestureRequiredForPlay) { |
+ recordAutoplayMetric(PlayMethodFailed); |
String message = ExceptionMessages::failedToExecute("play", "HTMLMediaElement", "API can only be initiated by a user gesture."); |
document().executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
return; |
@@ -1998,25 +2017,17 @@ void HTMLMediaElement::autoplayMediaEncountered() |
recordAutoplayMetric(AutoplayMediaFound); |
if (!m_userGestureRequiredForPlay) |
- m_initialPlayWithoutUserGestures = true; |
+ m_initialPlayWithoutUserGesture = true; |
} |
} |
-void HTMLMediaElement::gesturelessInitialPlayHalted() |
+bool HTMLMediaElement::isBailout() const |
{ |
- ASSERT(m_initialPlayWithoutUserGestures); |
- m_initialPlayWithoutUserGestures = false; |
- |
- recordAutoplayMetric(AutoplayStopped); |
- |
// We count the user as having bailed-out on the video if they watched |
// less than one minute and less than 50% of it. |
- double playedTime = currentTime(); |
- if (playedTime < 60) { |
- double progress = playedTime / duration(); |
- if (progress < 0.5) |
- recordAutoplayMetric(AutoplayBailout); |
- } |
+ const double playedTime = currentTime(); |
+ const double progress = playedTime / duration(); |
+ return (playedTime < 60) && (progress < 0.5); |
} |
void HTMLMediaElement::pause() |
@@ -2026,11 +2037,12 @@ void HTMLMediaElement::pause() |
if (m_networkState == NETWORK_EMPTY) |
scheduleDelayedAction(LoadMediaResource); |
+ m_autoplayHelper.pauseMethodCalled(); |
+ |
m_autoplaying = false; |
if (!m_paused) { |
- if (m_initialPlayWithoutUserGestures) |
- gesturelessInitialPlayHalted(); |
+ recordMetricsIfPausing(); |
m_paused = true; |
scheduleTimeupdateEvent(false); |
@@ -2123,6 +2135,8 @@ void HTMLMediaElement::setMuted(bool muted) |
m_muted = muted; |
+ m_autoplayHelper.mutedChanged(); |
+ |
updateVolume(); |
scheduleEvent(EventTypeNames::volumechange); |
@@ -2754,6 +2768,7 @@ void HTMLMediaElement::timeChanged() |
m_sentEndEvent = true; |
scheduleEvent(EventTypeNames::ended); |
} |
+ recordMetricsIfPausing(); |
// If the media element has a current media controller, then report the controller state |
// for the media element's current media controller. |
updateMediaController(); |
@@ -2974,6 +2989,7 @@ void HTMLMediaElement::updatePlayState() |
mediaControls()->playbackStarted(); |
startPlaybackProgressTimer(); |
m_playing = true; |
+ recordAutoplayMetric(AnyPlaybackStarted); |
} else { // Should not be playing right now |
if (isPlaying) |
@@ -3093,8 +3109,7 @@ void HTMLMediaElement::stop() |
{ |
WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); |
- if (m_playing && m_initialPlayWithoutUserGestures) |
- gesturelessInitialPlayHalted(); |
+ recordMetricsIfPausing(); |
// Close the async event queue so that no events are enqueued by userCancelledLoad. |
cancelPendingEventsAndCallbacks(); |
@@ -3708,6 +3723,31 @@ void HTMLMediaElement::selectInitialTracksIfNecessary() |
videoTracks().anonymousIndexedGetter(0)->setSelected(true); |
} |
+bool HTMLMediaElement::isUserGestureRequiredForPlay() const |
+{ |
+ return m_userGestureRequiredForPlay; |
+} |
+ |
+void HTMLMediaElement::removeUserGestureRequirement() |
+{ |
+ m_userGestureRequiredForPlay = false; |
+} |
+ |
+void HTMLMediaElement::setInitialPlayWithoutUserGestures(bool value) |
+{ |
+ m_initialPlayWithoutUserGesture = value; |
+} |
+ |
+void HTMLMediaElement::notifyPositionMayHaveChanged() |
+{ |
+ m_autoplayHelper.positionChanged(); |
+} |
+ |
+void HTMLMediaElement::triggerAutoplayViewportCheck() |
+{ |
+ m_autoplayHelper.triggerAutoplayViewportCheck(); |
+} |
+ |
#if ENABLE(WEB_AUDIO) |
void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
{ |