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

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

Issue 2510353004: Deprecating AutoplayExperimentHelper (Closed)
Patch Set: rebased Created 4 years 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/dom/DocumentUserGestureToken.h"
7 #include "core/html/AutoplayExperimentHelper.h"
8 #include "platform/UserGestureIndicator.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 // msvc refuses to compile if we use all of ::testing, due to a conflict with
13 // WTF::NotNull. So, we just use what we need.
14 using ::testing::Return;
15 using ::testing::NiceMock;
16 using ::testing::_;
17
18 namespace blink {
19
20 class MockAutoplayClient : public AutoplayExperimentHelper::Client {
21 public:
22 enum ElementType { Video, Audio };
23
24 MockAutoplayClient(const char* mode, ElementType type)
25 : m_mode(mode), m_duration(100) {
26 // Set up default behaviors that the helper is allowed to use or cache
27 // during construction.
28
29 ON_CALL(*this, autoplayExperimentMode()).WillByDefault(Return(m_mode));
30
31 // Use m_isVideo to answer these.
32 ON_CALL(*this, isHTMLVideoElement()).WillByDefault(Return(type == Video));
33 ON_CALL(*this, isHTMLAudioElement()).WillByDefault(Return(type == Audio));
34
35 // Now set up some useful defaults.
36 // Remember that this are only evaluated once.
37 ON_CALL(*this, duration()).WillByDefault(Return(m_duration));
38 ON_CALL(*this, currentTime()).WillByDefault(Return(0));
39
40 // Default to "not optimized for mobile" page.
41 ON_CALL(*this, isLegacyViewportType()).WillByDefault(Return(false));
42
43 // Other handy defaults.
44 ON_CALL(*this, paused()).WillByDefault(Return(true));
45 ON_CALL(*this, ended()).WillByDefault(Return(false));
46 ON_CALL(*this, pageVisibilityState())
47 .WillByDefault(Return(PageVisibilityStateVisible));
48 ON_CALL(*this, isCrossOrigin()).WillByDefault(Return(false));
49 ON_CALL(*this, isAutoplayAllowedPerSettings()).WillByDefault(Return(true));
50 ON_CALL(*this, absoluteBoundingBoxRect())
51 .WillByDefault(Return(IntRect(10, 10, 100, 100)));
52
53 // Normally, the autoplay experiment should not modify lots of other
54 // state unless we explicitly expect it.
55 EXPECT_CALL(*this, setMuted(_)).Times(0);
56 EXPECT_CALL(*this, unlockUserGesture()).Times(0);
57 EXPECT_CALL(*this, setRequestPositionUpdates(true)).Times(0);
58 EXPECT_CALL(*this, recordAutoplayMetric(_)).Times(0);
59 }
60
61 virtual ~MockAutoplayClient() {}
62
63 MOCK_CONST_METHOD0(currentTime, double());
64 MOCK_CONST_METHOD0(duration, double());
65 MOCK_CONST_METHOD0(paused, bool());
66 MOCK_CONST_METHOD0(ended, bool());
67 MOCK_CONST_METHOD0(muted, bool());
68 MOCK_METHOD1(setMuted, void(bool));
69 MOCK_METHOD0(playInternal, void());
70 MOCK_METHOD0(pauseInternal, void());
71 MOCK_CONST_METHOD0(isLockedPendingUserGesture, bool());
72 MOCK_METHOD0(unlockUserGesture, void());
73 MOCK_METHOD1(recordAutoplayMetric, void(AutoplayMetrics));
74 MOCK_METHOD0(shouldAutoplay, bool());
75 MOCK_CONST_METHOD0(isHTMLVideoElement, bool());
76 MOCK_CONST_METHOD0(isHTMLAudioElement, bool());
77 MOCK_METHOD0(isLegacyViewportType, bool());
78 MOCK_CONST_METHOD0(pageVisibilityState, PageVisibilityState());
79 MOCK_CONST_METHOD0(autoplayExperimentMode, String());
80 MOCK_CONST_METHOD0(isCrossOrigin, bool());
81 MOCK_CONST_METHOD0(isAutoplayAllowedPerSettings, bool());
82 MOCK_METHOD1(setRequestPositionUpdates, void(bool));
83 MOCK_CONST_METHOD0(absoluteBoundingBoxRect, IntRect());
84
85 const char* m_mode;
86 // const since changes to it won't affect the mocked value.
87 const double m_duration;
88 };
89
90 class AutoplayExperimentTest : public ::testing::Test {
91 public:
92 AutoplayExperimentTest() {}
93
94 ~AutoplayExperimentTest() {}
95
96 bool isEligible() { return m_helper->isEligible(); }
97
98 bool meetsVisibilityRequirements() {
99 return m_helper->meetsVisibilityRequirements();
100 }
101
102 void setInterface(MockAutoplayClient* client) {
103 m_client = client;
104
105 // Set some defaults.
106 setUserGestureRequiredForPlay(true);
107 setShouldAutoplay(true);
108 setIsMuted(false);
109
110 m_helper = AutoplayExperimentHelper::create(m_client.get());
111 }
112
113 void TearDown() {
114 // Be sure that the mock is destructed before the test, so that any
115 // missing expectations are noticed. Otherwise, the test will pass
116 // and then missing expectations will show up in the log, without
117 // causing a test failure.
118 m_helper.clear();
119 m_client.clear();
120 ThreadState::current()->collectAllGarbage();
121 }
122
123 Persistent<MockAutoplayClient> m_client;
124 Persistent<AutoplayExperimentHelper> m_helper;
125
126 // Mirror updatePlayState to transition to play.
127 void startPlayback() {
128 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackStarted)).Times(1);
129 m_helper->playbackStarted();
130 }
131
132 void startPlaybackWithoutUserGesture() {
133 EXPECT_FALSE(UserGestureIndicator::processingUserGesture());
134 startPlayback();
135 }
136
137 void startPlaybackWithUserGesture() {
138 UserGestureIndicator indicator(DocumentUserGestureToken::create(nullptr));
139 EXPECT_TRUE(UserGestureIndicator::processingUserGesture());
140 startPlayback();
141 }
142
143 void setUserGestureRequiredForPlay(bool required) {
144 ON_CALL(*m_client, isLockedPendingUserGesture())
145 .WillByDefault(Return(required));
146 }
147
148 void setShouldAutoplay(bool should) {
149 ON_CALL(*m_client, shouldAutoplay()).WillByDefault(Return(should));
150 }
151
152 void setIsMuted(bool isMuted) {
153 ON_CALL(*m_client, muted()).WillByDefault(Return(isMuted));
154 }
155
156 void pausePlaybackExpectingBailout(bool expectingAutoplay) {
157 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackPaused)).Times(1);
158 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackBailout)).Times(1);
159 if (expectingAutoplay) {
160 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayPaused)).Times(1);
161 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayBailout)).Times(1);
162 }
163 m_helper->pauseMethodCalled();
164 m_helper->playbackStopped();
165 }
166
167 void pausePlaybackNotExpectingBailout(bool expectingAutoplay) {
168 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackPaused)).Times(1);
169 if (expectingAutoplay)
170 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayPaused)).Times(1);
171 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackBailout)).Times(0);
172 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayBailout)).Times(0);
173
174 // Move past the bailout point, but not to the end. That way, we don't
175 // have to set ended().
176 ON_CALL(*m_client, currentTime())
177 .WillByDefault(Return(m_client->m_duration - 1));
178
179 m_helper->pauseMethodCalled();
180 m_helper->playbackStopped();
181 }
182
183 void endPlayback(bool expectingAutoplay) {
184 EXPECT_CALL(*m_client, recordAutoplayMetric(AnyPlaybackComplete)).Times(1);
185 if (expectingAutoplay)
186 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayComplete)).Times(1);
187 ON_CALL(*m_client, currentTime())
188 .WillByDefault(Return(m_client->m_duration));
189 ON_CALL(*m_client, ended()).WillByDefault(Return(true));
190 m_helper->playbackStopped();
191 }
192
193 void moveIntoViewport() {
194 m_helper->positionChanged(IntRect(0, 0, 200, 200));
195 m_helper->triggerAutoplayViewportCheckForTesting();
196 }
197 };
198
199 TEST_F(AutoplayExperimentTest, IsNotEligibleWithEmptyMode) {
200 setInterface(new NiceMock<MockAutoplayClient>("", MockAutoplayClient::Video));
201 EXPECT_FALSE(isEligible());
202 }
203
204 TEST_F(AutoplayExperimentTest, IsVideoEligibleForVideoMode) {
205 // Video should be eligible in "forvideo" mode.
206 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
207 MockAutoplayClient::Video));
208 EXPECT_TRUE(isEligible());
209 }
210
211 TEST_F(AutoplayExperimentTest, IsAudioNotEligibleForVideoMode) {
212 // Audio should not be eligible for video mode.
213 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
214 MockAutoplayClient::Audio));
215 EXPECT_FALSE(isEligible());
216 }
217
218 TEST_F(AutoplayExperimentTest, IsEligibleRequiresUserGesture) {
219 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
220 MockAutoplayClient::Video));
221 // If a user gesture is not required, then we're not eligible.
222 ON_CALL(*m_client, isLockedPendingUserGesture()).WillByDefault(Return(false));
223 EXPECT_FALSE(isEligible());
224 }
225
226 TEST_F(AutoplayExperimentTest, IsEligibleRequiresShouldAutoplay) {
227 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
228 MockAutoplayClient::Video));
229 // If we shouldn't autoplay, then we're not eligible.
230 ON_CALL(*m_client, shouldAutoplay()).WillByDefault(Return(false));
231 EXPECT_FALSE(isEligible());
232 }
233
234 TEST_F(AutoplayExperimentTest, IsAudioEligibleForAudioMode) {
235 setInterface(new NiceMock<MockAutoplayClient>("enabled-foraudio",
236 MockAutoplayClient::Audio));
237 EXPECT_TRUE(isEligible());
238 }
239
240 TEST_F(AutoplayExperimentTest, EligibleIfOptimizedForMobile) {
241 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo-ifmobile",
242 MockAutoplayClient::Video));
243 // Should not be eligible with our default of "not mobile".
244 EXPECT_FALSE(isEligible());
245
246 ON_CALL(*m_client, isLegacyViewportType()).WillByDefault(Return(true));
247 EXPECT_TRUE(isEligible());
248 }
249
250 TEST_F(AutoplayExperimentTest, EligibleIfMuted) {
251 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo-ifmuted",
252 MockAutoplayClient::Video));
253 // Should not be eligible with our default of "not muted".
254 EXPECT_FALSE(isEligible());
255
256 ON_CALL(*m_client, muted()).WillByDefault(Return(true));
257 EXPECT_TRUE(isEligible());
258 }
259
260 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenBailout) {
261 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
262 MockAutoplayClient::Video));
263
264 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
265 m_helper->becameReadyToPlay();
266 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
267
268 EXPECT_CALL(
269 *m_client,
270 recordAutoplayMetric(GesturelessPlaybackStartedByAutoplayFlagImmediately))
271 .Times(1);
272 startPlaybackWithoutUserGesture();
273
274 pausePlaybackExpectingBailout(true);
275 }
276
277 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenPause) {
278 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
279 MockAutoplayClient::Video));
280
281 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
282 m_helper->becameReadyToPlay();
283 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
284
285 EXPECT_CALL(
286 *m_client,
287 recordAutoplayMetric(GesturelessPlaybackStartedByAutoplayFlagImmediately))
288 .Times(1);
289 startPlaybackWithoutUserGesture();
290
291 pausePlaybackNotExpectingBailout(true);
292 }
293
294 TEST_F(AutoplayExperimentTest, BecameReadyAutoplayThenComplete) {
295 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
296 MockAutoplayClient::Video));
297
298 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
299 m_helper->becameReadyToPlay();
300 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
301
302 EXPECT_CALL(
303 *m_client,
304 recordAutoplayMetric(GesturelessPlaybackStartedByAutoplayFlagImmediately))
305 .Times(1);
306 startPlaybackWithoutUserGesture();
307
308 // Now stop at the end.
309 endPlayback(true);
310 }
311
312 TEST_F(AutoplayExperimentTest, NoUserGestureNeededShouldNotOverride) {
313 // Make sure that we don't override the user gesture if it isn't needed.
314 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
315 MockAutoplayClient::Video));
316 setUserGestureRequiredForPlay(false);
317
318 // It is still autoplay media, though.
319 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
320 m_helper->becameReadyToPlay();
321
322 EXPECT_CALL(*m_client, recordAutoplayMetric(GesturelessPlaybackNotOverridden))
323 .Times(1);
324 startPlaybackWithoutUserGesture();
325 }
326
327 TEST_F(AutoplayExperimentTest, NoAutoplayMetricsIfNoAutoplay) {
328 // If playback is started while processing a user gesture, then nothing
329 // should be overridden or logged about autoplay.
330 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
331 MockAutoplayClient::Video));
332 setUserGestureRequiredForPlay(false);
333 setShouldAutoplay(false);
334 startPlaybackWithUserGesture();
335
336 // Expect bailout, but not from autoplay.
337 pausePlaybackExpectingBailout(false);
338 }
339
340 TEST_F(AutoplayExperimentTest, PlayMethodThenBailout) {
341 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
342 MockAutoplayClient::Video));
343 setShouldAutoplay(false); // No autoplay attribute.
344
345 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
346 m_helper->playMethodCalled();
347 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
348
349 EXPECT_CALL(*m_client, recordAutoplayMetric(
350 GesturelessPlaybackStartedByPlayMethodImmediately))
351 .Times(1);
352 startPlaybackWithoutUserGesture();
353
354 pausePlaybackExpectingBailout(true);
355 }
356
357 TEST_F(AutoplayExperimentTest, DeferAutoplayUntilMuted) {
358 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo-ifmuted",
359 MockAutoplayClient::Video));
360
361 // Should not override the gesture requirement yet.
362 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
363 m_helper->becameReadyToPlay();
364
365 // When we toggle the muted attribute, it should become eligible to start.
366 EXPECT_FALSE(m_helper->isGestureRequirementOverridden());
367 setIsMuted(true);
368 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
369 }
370
371 TEST_F(AutoplayExperimentTest, DeferPlaybackUntilInViewport) {
372 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo-ifviewport",
373 MockAutoplayClient::Video));
374
375 // Should not override the gesture requirement yet.
376 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
377 EXPECT_CALL(*m_client, setRequestPositionUpdates(true)).Times(1);
378 m_helper->becameReadyToPlay();
379
380 EXPECT_CALL(*m_client, playInternal()).Times(1);
381 EXPECT_CALL(*m_client, setRequestPositionUpdates(false)).Times(1);
382 moveIntoViewport();
383 EXPECT_TRUE(m_helper->isGestureRequirementOverridden());
384 }
385
386 TEST_F(AutoplayExperimentTest, WithSameOriginTests) {
387 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo-ifsameorigin",
388 MockAutoplayClient::Video));
389 ON_CALL(*m_client, isCrossOrigin()).WillByDefault(Return(false));
390 EXPECT_TRUE(isEligible());
391 ON_CALL(*m_client, isCrossOrigin()).WillByDefault(Return(true));
392 EXPECT_FALSE(isEligible());
393 }
394
395 TEST_F(AutoplayExperimentTest, WithoutSameOriginTests) {
396 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
397 MockAutoplayClient::Video));
398 ON_CALL(*m_client, isCrossOrigin()).WillByDefault(Return(false));
399 EXPECT_TRUE(isEligible());
400 ON_CALL(*m_client, isCrossOrigin()).WillByDefault(Return(true));
401 EXPECT_TRUE(isEligible());
402 }
403
404 TEST_F(AutoplayExperimentTest, AudioPageVisibility) {
405 setInterface(new NiceMock<MockAutoplayClient>(
406 "enabled-foraudio-ifpagevisible", MockAutoplayClient::Audio));
407 ON_CALL(*m_client, pageVisibilityState())
408 .WillByDefault(Return(PageVisibilityStateVisible));
409 EXPECT_TRUE(isEligible());
410 EXPECT_TRUE(meetsVisibilityRequirements());
411
412 ON_CALL(*m_client, pageVisibilityState())
413 .WillByDefault(Return(PageVisibilityStateHidden));
414 EXPECT_TRUE(isEligible());
415 EXPECT_FALSE(meetsVisibilityRequirements());
416 }
417
418 TEST_F(AutoplayExperimentTest, PlayTwiceIsIgnored) {
419 setInterface(new NiceMock<MockAutoplayClient>("enabled-forvideo",
420 MockAutoplayClient::Video));
421 setShouldAutoplay(false); // No autoplay attribute.
422
423 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
424 m_helper->playMethodCalled();
425 ON_CALL(*m_client, paused()).WillByDefault(Return(false));
426 m_helper->playMethodCalled();
427 }
428
429 TEST_F(AutoplayExperimentTest, CrossOriginMutedTests) {
430 setInterface(new NiceMock<MockAutoplayClient>(
431 "enabled-forvideo-ifsameorigin-ormuted", MockAutoplayClient::Video));
432 ON_CALL(*m_client, isCrossOrigin()).WillByDefault(Return(true));
433
434 // Cross-orgin unmuted content should be eligible.
435 setIsMuted(true);
436 EXPECT_TRUE(isEligible());
437
438 // Cross-origin muted content should not be eligible.
439 setIsMuted(false);
440 EXPECT_FALSE(isEligible());
441
442 // Start playback.
443 EXPECT_CALL(*m_client, recordAutoplayMetric(AutoplayMediaFound)).Times(1);
444 m_helper->becameReadyToPlay();
445 ON_CALL(*m_client, paused()).WillByDefault(Return(false));
446 setIsMuted(true);
447 m_helper->mutedChanged();
448
449 // Verify that unmuting pauses playback.
450 setIsMuted(false);
451 EXPECT_CALL(*m_client, pauseInternal()).Times(1);
452 m_helper->mutedChanged();
453 }
454 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/AutoplayExperimentHelper.cpp ('k') | third_party/WebKit/Source/core/html/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698