OLD | NEW |
| (Empty) |
1 // Copyright 2016 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/html/shadow/MediaControlsOrientationLockDelegate.h" | |
6 | |
7 #include "core/dom/Document.h" | |
8 #include "core/dom/DocumentUserGestureToken.h" | |
9 #include "core/dom/Fullscreen.h" | |
10 #include "core/frame/ScreenOrientationController.h" | |
11 #include "core/html/HTMLAudioElement.h" | |
12 #include "core/html/HTMLVideoElement.h" | |
13 #include "core/html/shadow/MediaControls.h" | |
14 #include "core/loader/EmptyClients.h" | |
15 #include "core/testing/DummyPageHolder.h" | |
16 #include "platform/UserGestureIndicator.h" | |
17 #include "platform/testing/EmptyWebMediaPlayer.h" | |
18 #include "platform/testing/UnitTestHelpers.h" | |
19 #include "public/platform/WebSize.h" | |
20 #include "public/platform/modules/screen_orientation/WebLockOrientationCallback.
h" | |
21 #include "testing/gmock/include/gmock/gmock.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 using ::testing::_; | |
25 using ::testing::Return; | |
26 | |
27 namespace blink { | |
28 | |
29 namespace { | |
30 | |
31 // WebLockOrientationCallback implementation that will not react to a success | |
32 // nor a failure. | |
33 class DummyScreenOrientationCallback : public WebLockOrientationCallback { | |
34 public: | |
35 void onSuccess() override {} | |
36 void onError(WebLockOrientationError) override {} | |
37 }; | |
38 | |
39 class MockVideoWebMediaPlayer : public EmptyWebMediaPlayer { | |
40 public: | |
41 bool hasVideo() const override { return true; } | |
42 | |
43 MOCK_CONST_METHOD0(naturalSize, WebSize()); | |
44 }; | |
45 | |
46 class MockChromeClient : public EmptyChromeClient { | |
47 public: | |
48 MOCK_CONST_METHOD0(screenInfo, WebScreenInfo()); | |
49 }; | |
50 | |
51 class StubLocalFrameClient : public EmptyLocalFrameClient { | |
52 public: | |
53 static StubLocalFrameClient* create() { return new StubLocalFrameClient; } | |
54 | |
55 std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( | |
56 HTMLMediaElement&, | |
57 const WebMediaPlayerSource&, | |
58 WebMediaPlayerClient*) override { | |
59 return WTF::wrapUnique(new MockVideoWebMediaPlayer()); | |
60 } | |
61 }; | |
62 | |
63 class MockScreenOrientationController final | |
64 : public ScreenOrientationController { | |
65 WTF_MAKE_NONCOPYABLE(MockScreenOrientationController); | |
66 | |
67 public: | |
68 static MockScreenOrientationController* provideTo(LocalFrame& frame) { | |
69 MockScreenOrientationController* controller = | |
70 new MockScreenOrientationController(frame); | |
71 ScreenOrientationController::provideTo(frame, controller); | |
72 return controller; | |
73 } | |
74 | |
75 MOCK_METHOD1(lock, void(WebScreenOrientationLockType)); | |
76 MOCK_METHOD0(mockUnlock, void()); | |
77 | |
78 DEFINE_INLINE_VIRTUAL_TRACE() { ScreenOrientationController::trace(visitor); } | |
79 | |
80 private: | |
81 explicit MockScreenOrientationController(LocalFrame& frame) | |
82 : ScreenOrientationController(frame) {} | |
83 | |
84 void lock(WebScreenOrientationLockType type, | |
85 std::unique_ptr<WebLockOrientationCallback>) override { | |
86 m_locked = true; | |
87 lock(type); | |
88 } | |
89 | |
90 void unlock() override { | |
91 m_locked = false; | |
92 mockUnlock(); | |
93 } | |
94 | |
95 void notifyOrientationChanged() override {} | |
96 | |
97 bool maybeHasActiveLock() const override { return m_locked; } | |
98 | |
99 bool m_locked = false; | |
100 }; | |
101 | |
102 } // anonymous namespace | |
103 | |
104 class MediaControlsOrientationLockDelegateTest : public ::testing::Test { | |
105 protected: | |
106 void SetUp() override { | |
107 m_previousVideoFullscreenOrientationLockValue = | |
108 RuntimeEnabledFeatures::videoFullscreenOrientationLockEnabled(); | |
109 RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled(true); | |
110 | |
111 m_chromeClient = new MockChromeClient(); | |
112 | |
113 Page::PageClients clients; | |
114 fillWithEmptyClients(clients); | |
115 clients.chromeClient = m_chromeClient.get(); | |
116 | |
117 m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, | |
118 StubLocalFrameClient::create()); | |
119 | |
120 document().write("<body><video></body>"); | |
121 m_video = toHTMLVideoElement(*document().querySelector("video")); | |
122 | |
123 m_screenOrientationController = | |
124 MockScreenOrientationController::provideTo(m_pageHolder->frame()); | |
125 } | |
126 | |
127 void TearDown() override { | |
128 ::testing::Mock::VerifyAndClear(&screenOrientationController()); | |
129 | |
130 RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled( | |
131 m_previousVideoFullscreenOrientationLockValue); | |
132 } | |
133 | |
134 static bool hasDelegate(const MediaControls& mediaControls) { | |
135 return !!mediaControls.m_orientationLockDelegate; | |
136 } | |
137 | |
138 void simulateEnterFullscreen() { | |
139 UserGestureIndicator gesture(DocumentUserGestureToken::create(&document())); | |
140 | |
141 Fullscreen::requestFullscreen(video()); | |
142 Fullscreen::from(document()).didEnterFullscreen(); | |
143 testing::runPendingTasks(); | |
144 } | |
145 | |
146 void simulateExitFullscreen() { | |
147 Fullscreen::exitFullscreen(document()); | |
148 Fullscreen::from(document()).didExitFullscreen(); | |
149 testing::runPendingTasks(); | |
150 } | |
151 | |
152 void simulateOrientationLock() { | |
153 ScreenOrientationController* controller = | |
154 ScreenOrientationController::from(*document().frame()); | |
155 controller->lock(WebScreenOrientationLockLandscape, | |
156 WTF::wrapUnique(new DummyScreenOrientationCallback)); | |
157 EXPECT_TRUE(controller->maybeHasActiveLock()); | |
158 } | |
159 | |
160 void simulateVideoReadyState(HTMLMediaElement::ReadyState state) { | |
161 video().setReadyState(state); | |
162 } | |
163 | |
164 void simulateVideoNetworkState(HTMLMediaElement::NetworkState state) { | |
165 video().setNetworkState(state); | |
166 } | |
167 | |
168 void checkStatePendingFullscreen() const { | |
169 EXPECT_EQ(MediaControlsOrientationLockDelegate::State::PendingFullscreen, | |
170 m_video->mediaControls()->m_orientationLockDelegate->m_state); | |
171 } | |
172 | |
173 void checkStatePendingMetadata() const { | |
174 EXPECT_EQ(MediaControlsOrientationLockDelegate::State::PendingMetadata, | |
175 m_video->mediaControls()->m_orientationLockDelegate->m_state); | |
176 } | |
177 | |
178 void checkStateMaybeLockedFullscreen() const { | |
179 EXPECT_EQ( | |
180 MediaControlsOrientationLockDelegate::State::MaybeLockedFullscreen, | |
181 m_video->mediaControls()->m_orientationLockDelegate->m_state); | |
182 } | |
183 | |
184 bool delegateWillUnlockFullscreen() const { | |
185 return m_video->mediaControls() | |
186 ->m_orientationLockDelegate->m_shouldUnlockOrientation; | |
187 } | |
188 | |
189 WebScreenOrientationLockType computeOrientationLock() const { | |
190 return m_video->mediaControls() | |
191 ->m_orientationLockDelegate->computeOrientationLock(); | |
192 } | |
193 | |
194 MockChromeClient& chromeClient() const { return *m_chromeClient; } | |
195 | |
196 HTMLVideoElement& video() const { return *m_video; } | |
197 Document& document() const { return m_pageHolder->document(); } | |
198 MockScreenOrientationController& screenOrientationController() const { | |
199 return *m_screenOrientationController; | |
200 } | |
201 MockVideoWebMediaPlayer& mockWebMediaPlayer() const { | |
202 return *static_cast<MockVideoWebMediaPlayer*>(video().webMediaPlayer()); | |
203 } | |
204 | |
205 private: | |
206 bool m_previousVideoFullscreenOrientationLockValue; | |
207 std::unique_ptr<DummyPageHolder> m_pageHolder; | |
208 Persistent<HTMLVideoElement> m_video; | |
209 Persistent<MockScreenOrientationController> m_screenOrientationController; | |
210 Persistent<MockChromeClient> m_chromeClient; | |
211 }; | |
212 | |
213 TEST_F(MediaControlsOrientationLockDelegateTest, DelegateRequiresFlag) { | |
214 // Flag on by default. | |
215 EXPECT_TRUE(hasDelegate(*video().mediaControls())); | |
216 | |
217 // Same with flag off. | |
218 RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled(false); | |
219 HTMLVideoElement* video = HTMLVideoElement::create(document()); | |
220 document().body()->appendChild(video); | |
221 EXPECT_FALSE(hasDelegate(*video->mediaControls())); | |
222 } | |
223 | |
224 TEST_F(MediaControlsOrientationLockDelegateTest, DelegateRequiresVideo) { | |
225 HTMLAudioElement* audio = HTMLAudioElement::create(document()); | |
226 document().body()->appendChild(audio); | |
227 EXPECT_FALSE(hasDelegate(*audio->mediaControls())); | |
228 } | |
229 | |
230 TEST_F(MediaControlsOrientationLockDelegateTest, InitialState) { | |
231 checkStatePendingFullscreen(); | |
232 } | |
233 | |
234 TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenNoMetadata) { | |
235 EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); | |
236 | |
237 simulateEnterFullscreen(); | |
238 | |
239 checkStatePendingMetadata(); | |
240 } | |
241 | |
242 TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenNoMetadata) { | |
243 EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); | |
244 EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); | |
245 | |
246 simulateEnterFullscreen(); | |
247 // State set to PendingMetadata. | |
248 simulateExitFullscreen(); | |
249 | |
250 checkStatePendingFullscreen(); | |
251 } | |
252 | |
253 TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenWithMetadata) { | |
254 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
255 | |
256 EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); | |
257 EXPECT_FALSE(delegateWillUnlockFullscreen()); | |
258 | |
259 simulateEnterFullscreen(); | |
260 | |
261 EXPECT_TRUE(delegateWillUnlockFullscreen()); | |
262 checkStateMaybeLockedFullscreen(); | |
263 } | |
264 | |
265 TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenWithMetadata) { | |
266 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
267 | |
268 EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); | |
269 EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(1); | |
270 | |
271 simulateEnterFullscreen(); | |
272 // State set to MaybeLockedFullscreen. | |
273 simulateExitFullscreen(); | |
274 | |
275 EXPECT_FALSE(delegateWillUnlockFullscreen()); | |
276 checkStatePendingFullscreen(); | |
277 } | |
278 | |
279 TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenAfterPageLock) { | |
280 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
281 simulateOrientationLock(); | |
282 | |
283 EXPECT_FALSE(delegateWillUnlockFullscreen()); | |
284 EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); | |
285 | |
286 simulateEnterFullscreen(); | |
287 | |
288 EXPECT_FALSE(delegateWillUnlockFullscreen()); | |
289 checkStateMaybeLockedFullscreen(); | |
290 } | |
291 | |
292 TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenAfterPageLock) { | |
293 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
294 simulateOrientationLock(); | |
295 | |
296 EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); | |
297 EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); | |
298 | |
299 simulateEnterFullscreen(); | |
300 // State set to MaybeLockedFullscreen. | |
301 simulateExitFullscreen(); | |
302 | |
303 EXPECT_FALSE(delegateWillUnlockFullscreen()); | |
304 checkStatePendingFullscreen(); | |
305 } | |
306 | |
307 TEST_F(MediaControlsOrientationLockDelegateTest, | |
308 ReceivedMetadataAfterExitingFullscreen) { | |
309 EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); | |
310 | |
311 simulateEnterFullscreen(); | |
312 // State set to PendingMetadata. | |
313 | |
314 // Set up the WebMediaPlayer instance. | |
315 video().setSrc("http://example.com"); | |
316 testing::runPendingTasks(); | |
317 | |
318 simulateVideoNetworkState(HTMLMediaElement::kNetworkIdle); | |
319 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
320 testing::runPendingTasks(); | |
321 | |
322 checkStateMaybeLockedFullscreen(); | |
323 } | |
324 | |
325 TEST_F(MediaControlsOrientationLockDelegateTest, ReceivedMetadataLater) { | |
326 EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); | |
327 EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); | |
328 | |
329 simulateEnterFullscreen(); | |
330 // State set to PendingMetadata. | |
331 simulateExitFullscreen(); | |
332 | |
333 // Set up the WebMediaPlayer instance. | |
334 video().setSrc("http://example.com"); | |
335 testing::runPendingTasks(); | |
336 | |
337 simulateVideoNetworkState(HTMLMediaElement::kNetworkIdle); | |
338 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
339 testing::runPendingTasks(); | |
340 | |
341 checkStatePendingFullscreen(); | |
342 } | |
343 | |
344 TEST_F(MediaControlsOrientationLockDelegateTest, ComputeOrientationLock) { | |
345 // Set up the WebMediaPlayer instance. | |
346 video().setSrc("http://example.com"); | |
347 testing::runPendingTasks(); | |
348 | |
349 simulateVideoNetworkState(HTMLMediaElement::kNetworkIdle); | |
350 simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); | |
351 | |
352 EXPECT_CALL(mockWebMediaPlayer(), naturalSize()) | |
353 .Times(14) // Each `computeOrientationLock` calls the method twice. | |
354 .WillOnce(Return(WebSize(100, 50))) | |
355 .WillOnce(Return(WebSize(100, 50))) | |
356 .WillOnce(Return(WebSize(50, 100))) | |
357 .WillOnce(Return(WebSize(50, 100))) | |
358 .WillRepeatedly(Return(WebSize(100, 100))); | |
359 | |
360 // 100x50 | |
361 EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); | |
362 | |
363 // 50x100 | |
364 EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); | |
365 | |
366 // 100x100 has more subtilities, it depends on the current screen orientation. | |
367 WebScreenInfo screenInfo; | |
368 screenInfo.orientationType = WebScreenOrientationUndefined; | |
369 EXPECT_CALL(chromeClient(), screenInfo()) | |
370 .Times(1) | |
371 .WillOnce(Return(screenInfo)); | |
372 EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); | |
373 | |
374 screenInfo.orientationType = WebScreenOrientationPortraitPrimary; | |
375 EXPECT_CALL(chromeClient(), screenInfo()) | |
376 .Times(1) | |
377 .WillOnce(Return(screenInfo)); | |
378 EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); | |
379 | |
380 screenInfo.orientationType = WebScreenOrientationPortraitPrimary; | |
381 EXPECT_CALL(chromeClient(), screenInfo()) | |
382 .Times(1) | |
383 .WillOnce(Return(screenInfo)); | |
384 EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); | |
385 | |
386 screenInfo.orientationType = WebScreenOrientationLandscapePrimary; | |
387 EXPECT_CALL(chromeClient(), screenInfo()) | |
388 .Times(1) | |
389 .WillOnce(Return(screenInfo)); | |
390 EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); | |
391 | |
392 screenInfo.orientationType = WebScreenOrientationLandscapeSecondary; | |
393 EXPECT_CALL(chromeClient(), screenInfo()) | |
394 .Times(1) | |
395 .WillOnce(Return(screenInfo)); | |
396 EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); | |
397 } | |
398 | |
399 } // namespace blink | |
OLD | NEW |