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

Unified Diff: third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp

Issue 1949633002: Don't remove the gesture requirement in the autoplay experiment. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed test expectations. Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp
diff --git a/third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp
index 9b3db335c44c20a1fd7e9a999e8d10b32ee895b7..0b20c3e8027064c73d0a5487981e672858494f62 100644
--- a/third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp
+++ b/third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp
@@ -31,7 +31,7 @@ AutoplayExperimentHelper::AutoplayExperimentHelper(Client* client)
, m_wasInViewport(false)
, m_autoplayMediaEncountered(false)
, m_playbackStartedMetricRecorded(false)
- , m_waitingForAutoplayPlaybackEnd(false)
+ , m_waitingForAutoplayPlaybackStop(false)
, m_recordedElement(false)
, m_lastLocationUpdateTime(-std::numeric_limits<double>::infinity())
, m_viewportTimer(this, &AutoplayExperimentHelper::viewportTimerFired)
@@ -73,28 +73,35 @@ void AutoplayExperimentHelper::becameReadyToPlay()
void AutoplayExperimentHelper::playMethodCalled()
{
- // Set the pending state, even if the play isn't going to be pending.
- // Eligibility can change if, for example, the mute status changes.
- // Having this set is okay.
- m_playPending = true;
+ // If a play is already pending, then do nothing. We're already trying
+ // to play. Similarly, do nothing if we're already playing.
+ if (m_playPending || !m_client->paused())
+ return;
if (!UserGestureIndicator::utilizeUserGesture()) {
autoplayMediaEncountered();
- if (isEligible()) {
- // Remember that userGestureRequiredForPlay is required for
- // us to be eligible for the experiment.
+ // Check for eligibility, but don't worry if playback is currently
+ // pending. If we're still not eligible, then this play() will fail.
+ if (isEligible(IgnorePendingPlayback)) {
+ m_playPending = true;
+
// If we are able to override the gesture requirement now, then
// do so. Otherwise, install an event listener if we need one.
+ // We do not actually start playback; play() will do that.
if (meetsVisibilityRequirements()) {
// Override the gesture and assume that play() will succeed.
prepareToAutoplay(GesturelessPlaybackStartedByPlayMethodImmediately);
} else {
// Wait for viewport visibility.
+ // TODO(liberato): if the autoplay is allowed soon enough, then
+ // it should still record *Immediately. Otherwise, we end up
+ // here before the first layout sometimes, when the item is
+ // visible but we just don't know that yet.
registerForPositionUpdatesIfNeeded();
}
}
- } else if (isUserGestureRequiredForPlay()) {
+ } else if (isLockedPendingUserGesture()) {
// If this media tried to autoplay, and we haven't played it yet, then
// record that the user provided the gesture to start it the first time.
if (m_autoplayMediaEncountered && !m_playbackStartedMetricRecorded)
@@ -102,6 +109,7 @@ void AutoplayExperimentHelper::playMethodCalled()
// Don't let future gestureless playbacks affect metrics.
m_autoplayMediaEncountered = true;
m_playbackStartedMetricRecorded = true;
+ m_playPending = false;
unregisterForPositionUpdatesIfNeeded();
}
@@ -116,31 +124,9 @@ void AutoplayExperimentHelper::pauseMethodCalled()
void AutoplayExperimentHelper::loadMethodCalled()
{
- if (isUserGestureRequiredForPlay() && UserGestureIndicator::utilizeUserGesture()) {
+ if (isLockedPendingUserGesture() && UserGestureIndicator::utilizeUserGesture()) {
recordAutoplayMetric(AutoplayEnabledThroughLoad);
- removeUserGestureRequirement(GesturelessPlaybackEnabledByLoad);
- }
-}
-
-void AutoplayExperimentHelper::mutedChanged()
-{
- // If we are no longer eligible for the autoplay experiment, then also
- // quit listening for events. If we are eligible, and if we should be
- // playing, then start playing. In other words, start playing if
- // we just needed 'mute' to autoplay.
-
- // Make sure that autoplay was actually deferred. If, for example, the
- // autoplay attribute is set after the media is ready to play, then it
- // would normally have no effect. We don't want to start playing.
- if (!m_autoplayMediaEncountered)
- return;
-
- if (!isEligible()) {
- unregisterForPositionUpdatesIfNeeded();
- } else {
- // Try to play. If we can't, then install a listener.
- if (!maybeStartPlaying())
- registerForPositionUpdatesIfNeeded();
+ unlockUserGesture(GesturelessPlaybackEnabledByLoad);
}
}
@@ -275,9 +261,8 @@ bool AutoplayExperimentHelper::meetsVisibilityRequirements() const
bool AutoplayExperimentHelper::maybeStartPlaying()
{
// See if we're allowed to autoplay now.
- if (!isEligible() || !meetsVisibilityRequirements()) {
+ if (!isGestureRequirementOverridden())
return false;
- }
// Start playing!
prepareToAutoplay(client().shouldAutoplay()
@@ -296,7 +281,17 @@ bool AutoplayExperimentHelper::maybeStartPlaying()
return true;
}
-bool AutoplayExperimentHelper::isEligible() const
+bool AutoplayExperimentHelper::isGestureRequirementOverridden() const
+{
+ return isEligible() && meetsVisibilityRequirements();
+}
+
+bool AutoplayExperimentHelper::isPlaybackDeferred() const
+{
+ return m_playPending;
+}
+
+bool AutoplayExperimentHelper::isEligible(EligibilityMode mode) const
{
if (m_mode == Mode::ExperimentOff)
return false;
@@ -309,7 +304,7 @@ bool AutoplayExperimentHelper::isEligible() const
// This is what prevents us from starting playback more than once.
// Since this flag is never set to true once it's cleared, it will block
// the autoplay experiment forever.
- if (!isUserGestureRequiredForPlay())
+ if (!isLockedPendingUserGesture())
return false;
// Make sure that this is an element of the right type.
@@ -322,7 +317,7 @@ bool AutoplayExperimentHelper::isEligible() const
// If nobody has requested playback, either by the autoplay attribute or
// a play() call, then do nothing.
- if (!m_playPending && !client().shouldAutoplay())
+ if (mode != IgnorePendingPlayback && !m_playPending && !client().shouldAutoplay())
return false;
// Note that the viewport test always returns false on desktop, which is
@@ -345,21 +340,29 @@ bool AutoplayExperimentHelper::isEligible() const
void AutoplayExperimentHelper::muteIfNeeded()
{
- if (enabled(PlayMuted)) {
- ASSERT(!isEligible());
- // If we are actually changing the muted state, then this will call
- // mutedChanged(). If isEligible(), then mutedChanged() will try
- // to start playback, which we should not do here.
+ if (enabled(PlayMuted))
client().setMuted(true);
- }
}
-void AutoplayExperimentHelper::removeUserGestureRequirement(AutoplayMetrics metric)
+void AutoplayExperimentHelper::unlockUserGesture(AutoplayMetrics metric)
{
- if (client().isUserGestureRequiredForPlay()) {
- m_autoplayDeferredMetric = metric;
- client().removeUserGestureRequirement();
- }
+ // Note that this could be moved back into HTMLMediaElement fairly easily.
+ // It's only here so that we can record the reason, and we can hide the
+ // ordering between unlocking and recording from the element this way.
+ if (!client().isLockedPendingUserGesture())
+ return;
+
+ setDeferredOverrideReason(metric);
+ client().unlockUserGesture();
+}
+
+void AutoplayExperimentHelper::setDeferredOverrideReason(AutoplayMetrics metric)
+{
+ // If the player is unlocked, then we don't care about any later reason.
+ if (!client().isLockedPendingUserGesture())
+ return;
+
+ m_autoplayDeferredMetric = metric;
}
void AutoplayExperimentHelper::prepareToAutoplay(AutoplayMetrics metric)
@@ -369,7 +372,7 @@ void AutoplayExperimentHelper::prepareToAutoplay(AutoplayMetrics metric)
// Also note that, at this point, we know that we're goint to start
// playback. However, we still don't record the metric here. Instead,
// we let playbackStarted() do that later.
- removeUserGestureRequirement(metric);
+ setDeferredOverrideReason(metric);
// Don't bother to call autoplayMediaEncountered, since whoever initiates
// playback has do it anyway, in case we don't allow autoplay.
@@ -418,23 +421,34 @@ void AutoplayExperimentHelper::autoplayMediaEncountered()
}
}
-bool AutoplayExperimentHelper::isUserGestureRequiredForPlay() const
+bool AutoplayExperimentHelper::isLockedPendingUserGesture() const
{
- return client().isUserGestureRequiredForPlay();
+ return client().isLockedPendingUserGesture();
}
void AutoplayExperimentHelper::playbackStarted()
{
recordAutoplayMetric(AnyPlaybackStarted);
+ // Forget about our most recent visibility check. If another override is
+ // requested, then we'll have to refresh it. That way, we don't need to
+ // keep it up to date in the interim.
+ m_lastVisibleRect = IntRect();
+ m_wasInViewport = false;
+
+ // Any pending play is now playing.
+ m_playPending = false;
+
if (m_playbackStartedMetricRecorded)
return;
+ // Whether we record anything or not, we only want to record metrics for
+ // the initial playback.
m_playbackStartedMetricRecorded = true;
- // If this is a gestureless start, record why it was allowed.
- if (!UserGestureIndicator::processingUserGesture()) {
- m_waitingForAutoplayPlaybackEnd = true;
+ // If this is a gestureless start, then record why it was allowed.
+ if (m_autoplayMediaEncountered) {
+ m_waitingForAutoplayPlaybackStop = true;
recordAutoplayMetric(m_autoplayDeferredMetric);
}
}
@@ -452,8 +466,8 @@ void AutoplayExperimentHelper::playbackStopped()
// If this was a gestureless play, then record that separately.
// These cover attr and play() gestureless starts.
- if (m_waitingForAutoplayPlaybackEnd) {
- m_waitingForAutoplayPlaybackEnd = false;
+ if (m_waitingForAutoplayPlaybackStop) {
+ m_waitingForAutoplayPlaybackStop = false;
recordAutoplayMetric(ended ? AutoplayComplete : AutoplayPaused);

Powered by Google App Engine
This is Rietveld 408576698