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

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

Issue 1179223002: Implement autoplay gesture override experiment. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebased. Created 5 years, 3 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
« no previous file with comments | « Source/core/html/AutoplayExperimentHelper.h ('k') | Source/core/html/HTMLMediaElement.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/html/AutoplayExperimentHelper.h"
7
8 #include "core/dom/Document.h"
9 #include "core/frame/Settings.h"
10 #include "core/html/HTMLMediaElement.h"
11 #include "core/layout/LayoutBox.h"
12 #include "core/layout/LayoutObject.h"
13 #include "core/layout/LayoutVideo.h"
14 #include "core/layout/LayoutView.h"
15 #include "core/page/Page.h"
16 #include "platform/Logging.h"
17 #include "platform/UserGestureIndicator.h"
18 #include "platform/geometry/IntRect.h"
19
20 namespace blink {
21
22 using namespace HTMLNames;
23
24 AutoplayExperimentHelper::AutoplayExperimentHelper(HTMLMediaElement& element)
25 : m_element(element)
26 , m_mode(AutoplayExperimentConfig::Mode::Off)
27 , m_playPending(false)
28 {
29 if (document().settings()) {
30 m_mode = AutoplayExperimentConfig::fromString(document().settings()->aut oplayExperimentMode());
31
32 if (m_mode != AutoplayExperimentConfig::Mode::Off) {
33 WTF_LOG(Media, "HTMLMediaElement: autoplay experiment set to %d",
34 m_mode);
35 }
36 }
37 }
38
39 AutoplayExperimentHelper::~AutoplayExperimentHelper()
40 {
41 }
42
43 void AutoplayExperimentHelper::becameReadyToPlay()
44 {
45 // Assuming that we're eligible to override the user gesture requirement,
46 // then play.
47 if (isEligible()) {
48 prepareToPlay(GesturelessPlaybackStartedByAutoplayFlagImmediately);
49 }
50 }
51
52 void AutoplayExperimentHelper::playMethodCalled()
53 {
54 // Set the pending state, even if the play isn't going to be pending.
55 // Eligibility can change if, for example, the mute status changes.
56 // Having this set is okay.
57 m_playPending = true;
58
59 if (!UserGestureIndicator::processingUserGesture()) {
60
61 if (isEligible()) {
62 // Remember that userGestureRequiredForPlay is required for
63 // us to be eligible for the experiment.
64 // We are able to override the gesture requirement now, so
65 // do so.
66 prepareToPlay(GesturelessPlaybackStartedByPlayMethodImmediately);
67 }
68
69 }
70 }
71
72 void AutoplayExperimentHelper::pauseMethodCalled()
73 {
74 // Don't try to autoplay, if we would have.
75 m_playPending = false;
76 }
77
78 void AutoplayExperimentHelper::mutedChanged()
79 {
80 // In other words, start playing if we just needed 'mute' to autoplay.
81 maybeStartPlaying();
82 }
83
84 bool AutoplayExperimentHelper::maybeStartPlaying()
85 {
86 // See if we're allowed to autoplay now.
87 if (!isEligible()) {
88 return false;
89 }
90
91 // Start playing!
92 prepareToPlay(m_element.shouldAutoplay()
93 ? GesturelessPlaybackStartedByAutoplayFlagAfterScroll
94 : GesturelessPlaybackStartedByPlayMethodAfterScroll);
95 m_element.playInternal();
96
97 return true;
98 }
99
100 bool AutoplayExperimentHelper::isEligible() const
101 {
102 // If no user gesture is required, then the experiment doesn't apply.
103 // This is what prevents us from starting playback more than once.
104 // Since this flag is never set to true once it's cleared, it will block
105 // the autoplay experiment forever.
106 if (!m_element.isUserGestureRequiredForPlay())
107 return false;
108
109 if (m_mode == AutoplayExperimentConfig::Mode::Off)
110 return false;
111
112 // Make sure that this is an element of the right type.
113 if (!enabled(AutoplayExperimentConfig::Mode::ForVideo)
114 && isHTMLVideoElement(m_element))
115 return false;
116
117 if (!enabled(AutoplayExperimentConfig::Mode::ForAudio)
118 && isHTMLAudioElement(m_element))
119 return false;
120
121 // If nobody has requested playback, either by the autoplay attribute or
122 // a play() call, then do nothing.
123 if (!m_playPending && !m_element.shouldAutoplay())
124 return false;
125
126 // If the video is already playing, then do nothing. Note that there
127 // is not a path where a user gesture is required but the video is
128 // playing. However, we check for completeness.
129 if (!m_element.paused())
130 return false;
131
132 // Note that the viewport test always returns false on desktop, which is
133 // why video-autoplay-experiment.html doesn't check -ifmobile .
134 if (enabled(AutoplayExperimentConfig::Mode::IfMobile)
135 && !document().viewportDescription().isLegacyViewportType())
136 return false;
137
138 // If media is muted, then autoplay when it comes into view.
139 if (enabled(AutoplayExperimentConfig::Mode::IfMuted))
140 return m_element.muted();
141
142 // Autoplay when it comes into view (if needed), maybe muted.
143 return true;
144 }
145
146 void AutoplayExperimentHelper::muteIfNeeded()
147 {
148 if (enabled(AutoplayExperimentConfig::Mode::PlayMuted)) {
149 ASSERT(!isEligible());
150 // If we are actually changing the muted state, then this will call
151 // mutedChanged(). If isEligible(), then mutedChanged() will try
152 // to start playback, which we should not do here.
153 m_element.setMuted(true);
154 }
155 }
156
157 void AutoplayExperimentHelper::prepareToPlay(AutoplayMetrics metric)
158 {
159 m_element.recordAutoplayMetric(metric);
160
161 // This also causes !isEligible, so that we don't allow autoplay more than
162 // once. Be sure to do this before muteIfNeeded().
163 m_element.removeUserGestureRequirement();
164
165 muteIfNeeded();
166
167 // Record that this autoplayed without a user gesture. This is normally
168 // set when we discover an autoplay attribute, but we include all cases
169 // where playback started without a user gesture, e.g., play().
170 m_element.setInitialPlayWithoutUserGestures(true);
171
172 // Do not actually start playback here.
173 }
174
175 Document& AutoplayExperimentHelper::document() const
176 {
177 return m_element.document();
178 }
179
180 }
OLDNEW
« no previous file with comments | « Source/core/html/AutoplayExperimentHelper.h ('k') | Source/core/html/HTMLMediaElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698