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