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

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

Issue 1470153004: Autoplay experiment metric fixes and additions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased. Created 4 years, 11 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
(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 "core/dom/Document.h"
6 #include "core/html/AutoplayExperimentHelper.h"
7 #include "platform/UserGestureIndicator.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace blink {
12
13 using namespace testing;
14 using RecordMetricsBehavior = AutoplayExperimentHelper::Client::RecordMetricsBeh avior;
15
16 class MockAutoplayClient : public AutoplayExperimentHelper::Client {
17 public:
18 enum ElementType { VIDEO,
19 AUDIO };
philipj_slow 2016/01/12 15:12:18 Enum on a single line or each entry on a separate
liberato (no reviews please) 2016/01/29 08:25:24 Done.
20
21 MockAutoplayClient(const char* mode = "enabled-forvideo", ElementType type = VIDEO)
philipj_slow 2016/01/12 15:12:18 The default value of at least mode doesn't make th
liberato (no reviews please) 2016/01/29 08:25:24 Done.
22 : m_mode(mode)
23 , m_duration(100)
24 {
25 // Set up default behaviors that the helper is allowed to use or cache
26 // during construction.
27
28 EXPECT_CALL(*this, autoplayExperimentMode())
29 .WillRepeatedly(Return(m_mode));
30
31 // Use m_isVideo to answer these.
32 EXPECT_CALL(*this, isHTMLVideoElement())
33 .WillRepeatedly(Return(type == VIDEO));
34 EXPECT_CALL(*this, isHTMLAudioElement())
35 .WillRepeatedly(Return(type != VIDEO));
philipj_slow 2016/01/12 15:12:18 type == AUDIO?
liberato (no reviews please) 2016/01/29 08:25:24 Done.
36
37 // Now set up some useful defaults.
38 // Remember that this are only evaluated once.
39 EXPECT_CALL(*this, duration())
philipj_slow 2016/01/12 15:12:18 Reading http://stackoverflow.com/questions/1393347
liberato (no reviews please) 2016/01/29 08:25:24 Done, plus NiceMock to supress the warnings.
philipj_slow 2016/02/02 08:08:15 It worked, yay!
40 .WillRepeatedly(Return(m_duration));
41 EXPECT_CALL(*this, currentTime())
42 .WillRepeatedly(Return(0));
43
44 // Default to "not optimized for mobile" page.
45 EXPECT_CALL(*this, isLegacyViewportType())
46 .WillRepeatedly(Return(false));
47
48 // Other handy defaults.
49 EXPECT_CALL(*this, paused())
50 .WillRepeatedly(Return(true));
51 EXPECT_CALL(*this, pageVisibilityState())
52 .WillRepeatedly(Return(PageVisibilityStateVisible));
53 EXPECT_CALL(*this, absoluteBoundingBoxRect())
54 .WillRepeatedly(Return(
55 IntRect(10, 10, 100, 100)));
56
57 // Normally, the autoplay experiment should not modify lots of other
58 // state unless we explicitly expect it.
59 EXPECT_CALL(*this, setMuted(_))
60 .Times(0);
61 EXPECT_CALL(*this, removeUserGestureRequirement())
62 .Times(0);
63 EXPECT_CALL(*this, setRequestPositionUpdates(true))
64 .Times(0);
65 EXPECT_CALL(*this, recordAutoplayMetric(_))
66 .Times(0);
67 }
68
69 virtual ~MockAutoplayClient() {}
70
71 MOCK_CONST_METHOD0(currentTime, double());
72 MOCK_CONST_METHOD0(duration, double());
73 MOCK_CONST_METHOD0(paused, bool());
74 MOCK_CONST_METHOD0(muted, bool());
75 MOCK_METHOD1(setMuted, void(bool));
76 MOCK_METHOD0(playInternal, void());
77 MOCK_CONST_METHOD0(isUserGestureRequiredForPlay, bool());
78 MOCK_METHOD0(removeUserGestureRequirement, void());
79 MOCK_METHOD1(recordAutoplayMetric, void(AutoplayMetrics));
80 MOCK_METHOD1(shouldAutoplay, bool(RecordMetricsBehavior));
81 MOCK_CONST_METHOD0(isHTMLVideoElement, bool());
82 MOCK_CONST_METHOD0(isHTMLAudioElement, bool());
83 MOCK_METHOD0(isLegacyViewportType, bool());
84 MOCK_CONST_METHOD0(pageVisibilityState, PageVisibilityState());
85 MOCK_CONST_METHOD0(autoplayExperimentMode, String());
86 MOCK_METHOD1(setRequestPositionUpdates, void(bool));
87 MOCK_CONST_METHOD0(absoluteBoundingBoxRect, IntRect());
88
89 const char* m_mode;
90 // const since changes to it won't affect the mocked value.
91 const double m_duration;
92 };
93
94 class AutoplayExperimentTest : public ::testing::Test {
95 public:
96 AutoplayExperimentTest()
97 : client(nullptr)
98 , helper(nullptr)
99 {
100 }
101 ~AutoplayExperimentTest()
102 {
103 if (helper)
104 delete helper;
philipj_slow 2016/01/12 15:12:18 Looks like you really want an auto pointer, so Own
liberato (no reviews please) 2016/01/29 08:25:25 Done.
105
106 if (client)
107 delete client;
108 }
109
110 bool isEligible()
111 {
112 return helper->isEligible();
113 }
114
115 void setInterface(MockAutoplayClient* client)
116 {
117 this->client = client;
118
119 // Set some defaults.
120 setUserGestureRequiredForPlay(true);
121 setShouldAutoplay(true);
122 setIsMuted(false);
123
124 helper = new AutoplayExperimentHelper(*client);
125 }
126
127 MockAutoplayClient* client;
philipj_slow 2016/01/12 15:12:18 https://www.chromium.org/blink/coding-style#TOC-Na
liberato (no reviews please) 2016/01/29 08:25:24 don't know why i did that. thanks.
128 AutoplayExperimentHelper* helper;
129
130 // Mirror updatePlayState to transition to play.
131 void startPlayback()
132 {
133 EXPECT_CALL(*client, paused())
134 .WillRepeatedly(Return(false));
135 EXPECT_CALL(*client, recordAutoplayMetric(AnyPlaybackStarted))
136 .Times(1);
137 helper->playbackStarted();
138 }
139
140 void startPlaybackWithoutUserGesture()
141 {
142 EXPECT_FALSE(UserGestureIndicator::processingUserGesture());
143 startPlayback();
144 }
145
146 void startPlaybackWithUserGesture()
147 {
148 UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
149 EXPECT_TRUE(UserGestureIndicator::processingUserGesture());
150 startPlayback();
151 }
152
153 void setCurrentTimeToEnd()
154 {
155 EXPECT_CALL(*client, currentTime())
philipj_slow 2016/01/12 15:12:18 Is this how unit tests are normally written? I'm u
liberato (no reviews please) 2016/01/29 08:25:24 moved to ON_CALL, and make a NiceMock out of it to
156 .WillRepeatedly(Return(client->m_duration));
157 }
158
159 void setUserGestureRequiredForPlay(bool required)
160 {
161 EXPECT_CALL(*client, isUserGestureRequiredForPlay())
162 .WillRepeatedly(Return(required));
163 }
164
165 void setShouldAutoplay(bool should)
166 {
167 EXPECT_CALL(*client, shouldAutoplay(_))
168 .WillRepeatedly(Return(should));
169 }
170
171 void setIsMuted(bool isMuted)
172 {
173 EXPECT_CALL(*client, muted())
174 .WillRepeatedly(Return(isMuted));
175 }
176
177 void pausePlaybackExpectingBailout(bool expectingAutoplay)
178 {
179 EXPECT_CALL(*client, recordAutoplayMetric(AnyPlaybackPaused))
180 .Times(1);
181 EXPECT_CALL(*client, recordAutoplayMetric(AnyPlaybackBailout))
182 .Times(1);
183 if (expectingAutoplay) {
184 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayPaused))
185 .Times(1);
186 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayBailout))
187 .Times(1);
188 }
189 helper->pauseMethodCalled();
190 }
191
192 void pausePlaybackNotExpectingBailout(bool expectingAutoplay)
philipj_slow 2016/01/12 15:12:18 Doesn't this have to EXPECT_CALL *something* to fa
liberato (no reviews please) 2016/01/29 08:25:24 added Times(0) for both bailout cases.
193 {
194 EXPECT_CALL(*client, recordAutoplayMetric(AnyPlaybackPaused))
195 .Times(1);
196 if (expectingAutoplay)
197 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayPaused)).Times(1);
198 setCurrentTimeToEnd();
199 helper->pauseMethodCalled();
200 }
201
202 void endPlayback(bool expectingAutoplay)
203 {
204 EXPECT_CALL(*client, recordAutoplayMetric(AnyPlaybackComplete))
205 .Times(1);
206 if (expectingAutoplay)
207 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayComplete)).Times(1 );
208 helper->playbackEnded();
209 }
210
211 void moveIntoViewport()
212 {
213 helper->positionChanged(IntRect(0, 0, 200, 200));
214 helper->triggerAutoplayViewportCheckForTesting();
215 }
216 };
217
218 TEST_F(AutoplayExperimentTest, IsNotEligibleWithEmptyMode)
219 {
220 setInterface(new MockAutoplayClient(""));
221 EXPECT_FALSE(isEligible());
222 }
223
224 TEST_F(AutoplayExperimentTest, IsVideoEligibleForVideoMode)
225 {
226 // Video should be eligible in "forvideo" mode.
227 setInterface(new MockAutoplayClient());
228 EXPECT_TRUE(isEligible());
229 }
230
231 TEST_F(AutoplayExperimentTest, IsAudioNotEligibleForVideoMode)
232 {
233 // Audio should not be eligible for video mode.
234 setInterface(new MockAutoplayClient("enabled-forvideo", MockAutoplayClient:: AUDIO));
235 EXPECT_FALSE(isEligible());
236 }
237
238 TEST_F(AutoplayExperimentTest, IsEligibleRequiresUserGesture)
239 {
240 setInterface(new MockAutoplayClient());
241 // If a user gesture is not required, then we're not eligible.
242 EXPECT_CALL(*client, isUserGestureRequiredForPlay())
243 .WillRepeatedly(Return(false));
244 EXPECT_FALSE(isEligible());
245 }
246
247 TEST_F(AutoplayExperimentTest, IsEligibleRequiresShouldAutoplay)
248 {
249 setInterface(new MockAutoplayClient());
250 // If we shouldn't autoplay, then we're not eligible.
251 EXPECT_CALL(*client, shouldAutoplay(_))
252 .WillRepeatedly(Return(false));
253 EXPECT_FALSE(isEligible());
254 }
255
256 TEST_F(AutoplayExperimentTest, IsAudioEligibleForAudioMode)
257 {
258 setInterface(new MockAutoplayClient("enabled-foraudio", MockAutoplayClient:: AUDIO));
259 EXPECT_TRUE(isEligible());
260 }
261
262 TEST_F(AutoplayExperimentTest, EligibleIfOptimizedForMobile)
263 {
264 setInterface(new MockAutoplayClient("enabled-forvideo-ifmobile"));
265 // Should not be eligible with our default of "not mobile".
266 EXPECT_FALSE(isEligible());
267
268 EXPECT_CALL(*client, isLegacyViewportType())
269 .WillRepeatedly(Return(true));
270 EXPECT_TRUE(isEligible());
271 }
272
273 TEST_F(AutoplayExperimentTest, EligibleIfMuted)
274 {
275 setInterface(new MockAutoplayClient("enabled-forvideo-ifmuted"));
276 // Should not be eligible with our default of "not muted".
277 EXPECT_FALSE(isEligible());
278
279 EXPECT_CALL(*client, muted())
280 .WillRepeatedly(Return(true));
281 EXPECT_TRUE(isEligible());
282 }
283
284 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenBailout)
285 {
286 setInterface(new MockAutoplayClient());
287
288 EXPECT_CALL(*client, removeUserGestureRequirement())
289 .Times(1);
290 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
291 .Times(1);
292 helper->becameReadyToPlay();
293
294 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackStartedByAutopl ayFlagImmediately))
295 .Times(1);
296 startPlaybackWithoutUserGesture();
297
298 pausePlaybackExpectingBailout(true);
299 }
300
301 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenPause)
302 {
303 setInterface(new MockAutoplayClient());
304
305 EXPECT_CALL(*client, removeUserGestureRequirement())
306 .Times(1);
307 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
308 .Times(1);
309 helper->becameReadyToPlay();
310
311 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackStartedByAutopl ayFlagImmediately))
312 .Times(1);
313 startPlaybackWithoutUserGesture();
314
315 pausePlaybackNotExpectingBailout(true);
316 }
317
318 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenComplete)
319 {
320 setInterface(new MockAutoplayClient());
321
322 EXPECT_CALL(*client, removeUserGestureRequirement())
323 .Times(1);
324 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
325 .Times(1);
326 helper->becameReadyToPlay();
327
328 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackStartedByAutopl ayFlagImmediately))
329 .Times(1);
330 startPlaybackWithoutUserGesture();
331
332 // Now stop at the end.
333 endPlayback(true);
334 }
335
336 TEST_F(AutoplayExperimentTest, NoUserGestureNeededShouldNotOverride)
337 {
338 // Make sure that we don't override the user gesture if it isn't needed.
339 setInterface(new MockAutoplayClient());
340 setUserGestureRequiredForPlay(false);
341
342 // It is still autoplay media, though.
343 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
344 .Times(1);
345 helper->becameReadyToPlay();
346
347 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackUnknownReason))
348 .Times(1);
349 startPlaybackWithoutUserGesture();
350 }
351
352 TEST_F(AutoplayExperimentTest, NoAutoplayMetricsIfNoAutoplay)
353 {
354 // If playback is started while processing a user gesture, then nothing
355 // should be overridden or logged about autoplay.
356 setInterface(new MockAutoplayClient());
357 setUserGestureRequiredForPlay(false);
358 setShouldAutoplay(false);
359 startPlaybackWithUserGesture();
360
361 // Expect bailout, but not from autoplay.
362 pausePlaybackExpectingBailout(false);
363 }
364
365 TEST_F(AutoplayExperimentTest, PlayMethodThenBailout)
366 {
367 setInterface(new MockAutoplayClient());
368 setShouldAutoplay(false); // No autoplay attribute.
369
370 EXPECT_CALL(*client, removeUserGestureRequirement())
371 .Times(1);
372 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
373 .Times(1);
374 helper->playMethodCalled();
375
376 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackStartedByPlayMe thodImmediately))
377 .Times(1);
378 startPlaybackWithoutUserGesture();
379
380 pausePlaybackExpectingBailout(true);
381 }
382
383 TEST_F(AutoplayExperimentTest, DeferAutoplayUntilMuted)
384 {
385 setInterface(new MockAutoplayClient("enabled-forvideo-ifmuted"));
386
387 // Should not override the gesture requirement yet.
388 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
389 .Times(1);
390 helper->becameReadyToPlay();
391
392 // When we toggle the muted attribute, it should start.
393 EXPECT_CALL(*client, removeUserGestureRequirement())
394 .Times(1);
395 EXPECT_CALL(*client, playInternal())
396 .Times(1);
397 setIsMuted(true);
398 helper->mutedChanged();
399
400 // When playback starts (in response to playInternal()), it should also
401 // record why. 'After scroll' isn't the best name, but this isn't a common case.
402 EXPECT_CALL(*client, recordAutoplayMetric(GesturelessPlaybackStartedByAutopl ayFlagAfterScroll))
403 .Times(1);
404 startPlaybackWithoutUserGesture();
405 }
406
407 TEST_F(AutoplayExperimentTest, DeferPlaybackUntilInViewport)
408 {
409 setInterface(new MockAutoplayClient("enabled-forvideo-ifviewport"));
410
411 // Should not override the gesture requirement yet.
412 EXPECT_CALL(*client, recordAutoplayMetric(AutoplayMediaFound))
413 .Times(1);
414 EXPECT_CALL(*client, setRequestPositionUpdates(true))
415 .Times(1);
416 helper->becameReadyToPlay();
417
418 EXPECT_CALL(*client, removeUserGestureRequirement())
419 .Times(1);
420 EXPECT_CALL(*client, playInternal())
421 .Times(1);
422 EXPECT_CALL(*client, setRequestPositionUpdates(false))
423 .Times(1);
424 moveIntoViewport();
425 }
426 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698