Chromium Code Reviews| Index: third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp |
| diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4b55204f5937f2aa7fce11af8edf98eaad7bc9a4 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp |
| @@ -0,0 +1,416 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
|
DaleCurtis
2016/12/12 23:25:13
Nice tests!
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "core/html/shadow/MediaControlsOrientationLockDelegate.h" |
| + |
| +#include "core/dom/Document.h" |
| +#include "core/dom/DocumentUserGestureToken.h" |
| +#include "core/dom/Fullscreen.h" |
| +#include "core/frame/ScreenOrientationController.h" |
| +#include "core/html/HTMLAudioElement.h" |
| +#include "core/html/HTMLVideoElement.h" |
| +#include "core/loader/EmptyClients.h" |
| +#include "core/testing/DummyPageHolder.h" |
| +#include "platform/UserGestureIndicator.h" |
| +#include "platform/testing/UnitTestHelpers.h" |
| +#include "public/platform/WebMediaPlayer.h" |
| +#include "public/platform/WebSize.h" |
| +#include "public/platform/modules/screen_orientation/WebLockOrientationCallback.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::_; |
| +using ::testing::Return; |
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +// WebLockOrientationCallback implementation that will not react to a success |
| +// nor a failure. |
| +class DummyScreenOrientationCallback : public WebLockOrientationCallback { |
| + public: |
| + void onSuccess() override {} |
| + void onError(WebLockOrientationError) override {} |
| +}; |
| + |
| +class MockVideoWebMediaPlayer : public WebMediaPlayer { |
| + public: |
| + void load(LoadType, const WebMediaPlayerSource&, CORSMode) override{}; |
| + void play() override{}; |
| + void pause() override{}; |
| + bool supportsSave() const override { return false; }; |
| + void seek(double seconds) override{}; |
| + void setRate(double) override{}; |
| + void setVolume(double) override{}; |
| + WebTimeRanges buffered() const override { return WebTimeRanges(); }; |
| + WebTimeRanges seekable() const override { return WebTimeRanges(); }; |
| + void setSinkId(const WebString& sinkId, |
| + const WebSecurityOrigin&, |
| + WebSetSinkIdCallbacks*) override{}; |
| + bool hasVideo() const override { return true; }; |
| + bool hasAudio() const override { return false; }; |
| + bool paused() const override { return false; }; |
| + bool seeking() const override { return false; }; |
| + double duration() const override { return 0.0; }; |
| + double currentTime() const override { return 0.0; }; |
| + NetworkState getNetworkState() const override { return NetworkStateEmpty; }; |
| + ReadyState getReadyState() const override { return ReadyStateHaveNothing; }; |
| + WebString getErrorMessage() override { return WebString(); }; |
| + bool didLoadingProgress() override { return false; }; |
| + bool hasSingleSecurityOrigin() const override { return true; }; |
| + bool didPassCORSAccessCheck() const override { return true; }; |
| + double mediaTimeForTimeValue(double timeValue) const override { |
| + return timeValue; |
| + }; |
| + unsigned decodedFrameCount() const override { return 0; }; |
| + unsigned droppedFrameCount() const override { return 0; }; |
| + size_t audioDecodedByteCount() const override { return 0; }; |
| + size_t videoDecodedByteCount() const override { return 0; }; |
| + void paint(WebCanvas*, const WebRect&, SkPaint&) override{}; |
| + |
| + MOCK_CONST_METHOD0(naturalSize, WebSize()); |
| +}; |
| + |
| +class MockChromeClient : public EmptyChromeClient { |
| + public: |
| + MOCK_CONST_METHOD0(screenInfo, WebScreenInfo()); |
| +}; |
| + |
| +class StubFrameLoaderClient : public EmptyFrameLoaderClient { |
| + public: |
| + static StubFrameLoaderClient* create() { return new StubFrameLoaderClient; } |
| + |
| + std::unique_ptr<WebMediaPlayer> createWebMediaPlayer( |
| + HTMLMediaElement&, |
| + const WebMediaPlayerSource&, |
| + WebMediaPlayerClient*) override { |
| + return WTF::wrapUnique(new MockVideoWebMediaPlayer()); |
| + } |
| +}; |
| + |
| +class MockScreenOrientationController final |
| + : public GarbageCollectedFinalized<MockScreenOrientationController>, |
| + public ScreenOrientationController { |
| + USING_GARBAGE_COLLECTED_MIXIN(MockScreenOrientationController); |
| + WTF_MAKE_NONCOPYABLE(MockScreenOrientationController); |
| + |
| + public: |
| + static MockScreenOrientationController* provideTo(LocalFrame& frame) { |
| + MockScreenOrientationController* controller = |
| + new MockScreenOrientationController(); |
| + ScreenOrientationController::provideTo(frame, controller); |
| + return controller; |
| + } |
| + |
| + MOCK_METHOD1(lock, void(WebScreenOrientationLockType)); |
| + MOCK_METHOD0(mockUnlock, void()); |
| + |
| + DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<LocalFrame>::trace(visitor); } |
| + |
| + private: |
| + MockScreenOrientationController() = default; |
| + |
| + void lock(WebScreenOrientationLockType type, |
| + 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/
|
| + m_locked = true; |
| + lock(type); |
| + } |
| + void unlock() override { |
| + m_locked = false; |
| + mockUnlock(); |
| + } |
| + bool maybeHasActiveLock() const override { return m_locked; } |
| + |
| + bool m_locked = false; |
| +}; |
| + |
| +} // anonymous namespace |
| + |
| +class MediaControlsOrientationLockDelegateTest : public ::testing::Test { |
| + protected: |
| + void SetUp() override { |
| + m_previousVideoFullscreenOrientationLockValue = |
| + RuntimeEnabledFeatures::videoFullscreenOrientationLockEnabled(); |
| + RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled(true); |
| + |
| + m_chromeClient = new MockChromeClient(); |
| + |
| + Page::PageClients clients; |
| + fillWithEmptyClients(clients); |
| + clients.chromeClient = m_chromeClient.get(); |
| + |
| + m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, |
| + StubFrameLoaderClient::create()); |
| + |
| + document().write("<body><video></body>"); |
| + m_video = toHTMLVideoElement(*document().querySelector("video")); |
| + |
| + m_screenOrientationController = |
| + MockScreenOrientationController::provideTo(m_pageHolder->frame()); |
| + } |
| + |
| + void TearDown() override { |
| + RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled( |
| + m_previousVideoFullscreenOrientationLockValue); |
| + } |
| + |
| + static bool hasDelegate(const MediaControls& mediaControls) { |
| + return !!mediaControls.m_orientationLockDelegate; |
| + } |
| + |
| + void simulateEnterFullscreen() { |
| + UserGestureIndicator gesture(DocumentUserGestureToken::create(&document())); |
| + |
| + 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/
|
| + Fullscreen::from(document()).didEnterFullscreen(); |
| + testing::runPendingTasks(); |
| + } |
| + |
| + void simulateExitFullscreen() { |
| + Fullscreen::exitFullscreen(document()); |
| + Fullscreen::from(document()).didExitFullscreen(); |
| + testing::runPendingTasks(); |
| + } |
| + |
| + void simulateOrientationLock() { |
| + ScreenOrientationController* controller = |
| + ScreenOrientationController::from(*document().frame()); |
| + controller->lock(WebScreenOrientationLockLandscape, |
| + WTF::wrapUnique(new DummyScreenOrientationCallback)); |
| + EXPECT_TRUE(controller->maybeHasActiveLock()); |
| + } |
| + |
| + void simulateVideoReadyState(HTMLMediaElement::ReadyState state) { |
| + video().setReadyState(state); |
| + } |
| + |
| + void simulateVideoNetworkState(HTMLMediaElement::NetworkState state) { |
| + video().setNetworkState(state); |
| + } |
| + |
| + void checkStatePendingFullscreen() const { |
| + EXPECT_EQ(MediaControlsOrientationLockDelegate::State::PendingFullscreen, |
| + m_video->mediaControls()->m_orientationLockDelegate->m_state); |
| + } |
| + |
| + void checkStatePendingMetadata() const { |
| + EXPECT_EQ(MediaControlsOrientationLockDelegate::State::PendingMetadata, |
| + m_video->mediaControls()->m_orientationLockDelegate->m_state); |
| + } |
| + |
| + void checkStateMaybeLockedFullscreen() const { |
| + EXPECT_EQ( |
| + MediaControlsOrientationLockDelegate::State::MaybeLockedFullscreen, |
| + m_video->mediaControls()->m_orientationLockDelegate->m_state); |
| + } |
| + |
| + bool delegateWillUnlockFullscreen() const { |
| + return m_video->mediaControls() |
| + ->m_orientationLockDelegate->m_shouldUnlockOrientation; |
| + } |
| + |
| + WebScreenOrientationLockType computeOrientationLock() const { |
| + return m_video->mediaControls() |
| + ->m_orientationLockDelegate->computeOrientationLock(); |
| + } |
| + |
| + MockChromeClient& chromeClient() const { return *m_chromeClient; } |
| + |
| + HTMLVideoElement& video() const { return *m_video; } |
| + Document& document() const { return m_pageHolder->document(); } |
| + MockScreenOrientationController& screenOrientationController() const { |
| + return *m_screenOrientationController; |
| + } |
| + MockVideoWebMediaPlayer& mockWebMediaPlayer() const { |
| + return *static_cast<MockVideoWebMediaPlayer*>(video().webMediaPlayer()); |
| + } |
| + |
| + private: |
| + bool m_previousVideoFullscreenOrientationLockValue; |
| + std::unique_ptr<DummyPageHolder> m_pageHolder; |
| + Persistent<HTMLVideoElement> m_video; |
| + Persistent<MockScreenOrientationController> m_screenOrientationController; |
| + Persistent<MockChromeClient> m_chromeClient; |
| +}; |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, DelegateRequiresFlag) { |
| + // Flag on by default. |
| + EXPECT_TRUE(hasDelegate(*video().mediaControls())); |
| + |
| + { |
|
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.
|
| + RuntimeEnabledFeatures::setVideoFullscreenOrientationLockEnabled(false); |
| + |
| + HTMLVideoElement* video = HTMLVideoElement::create(document()); |
| + document().body()->appendChild(video); |
| + EXPECT_FALSE(hasDelegate(*video->mediaControls())); |
| + |
| + 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.
|
| + } |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, DelegateRequiresVideo) { |
| + HTMLAudioElement* audio = HTMLAudioElement::create(document()); |
| + document().body()->appendChild(audio); |
| + EXPECT_FALSE(hasDelegate(*audio->mediaControls())); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, InitialState) { |
| + checkStatePendingFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenNoMetadata) { |
| + 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
|
| + |
| + simulateEnterFullscreen(); |
| + |
| + checkStatePendingMetadata(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenNoMetadata) { |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); |
| + EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); |
| + |
| + simulateEnterFullscreen(); |
| + // State set to PendingMetadata. |
| + simulateExitFullscreen(); |
| + |
| + checkStatePendingFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenWithMetadata) { |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); |
| + EXPECT_FALSE(delegateWillUnlockFullscreen()); |
| + |
| + simulateEnterFullscreen(); |
| + |
| + EXPECT_TRUE(delegateWillUnlockFullscreen()); |
| + checkStateMaybeLockedFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenWithMetadata) { |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); |
| + EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(1); |
| + |
| + simulateEnterFullscreen(); |
| + // State set to MaybeLockedFullscreen. |
| + simulateExitFullscreen(); |
| + |
| + EXPECT_FALSE(delegateWillUnlockFullscreen()); |
| + checkStatePendingFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, EnterFullscreenAfterPageLock) { |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + simulateOrientationLock(); |
| + |
| + EXPECT_FALSE(delegateWillUnlockFullscreen()); |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); |
| + |
| + simulateEnterFullscreen(); |
| + |
| + EXPECT_FALSE(delegateWillUnlockFullscreen()); |
| + checkStateMaybeLockedFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, LeaveFullscreenAfterPageLock) { |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + simulateOrientationLock(); |
| + |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); |
| + EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); |
| + |
| + simulateEnterFullscreen(); |
| + // State set to MaybeLockedFullscreen. |
| + simulateExitFullscreen(); |
| + |
| + EXPECT_FALSE(delegateWillUnlockFullscreen()); |
| + checkStatePendingFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, ReceivedMetadataWhilePending) { |
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(1); |
| + |
| + simulateEnterFullscreen(); |
| + // State set to PendingMetadata. |
| + |
| + simulateVideoNetworkState(HTMLMediaElement::kNetworkIdle); |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + testing::runPendingTasks(); |
| + |
| + checkStateMaybeLockedFullscreen(); |
| +} |
| + |
| +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
|
| + EXPECT_CALL(screenOrientationController(), lock(_)).Times(0); |
| + EXPECT_CALL(screenOrientationController(), mockUnlock()).Times(0); |
| + |
| + simulateEnterFullscreen(); |
| + // State set to PendingMetadata. |
| + simulateExitFullscreen(); |
| + |
| + simulateVideoNetworkState(HTMLMediaElement::kNetworkIdle); |
| + simulateVideoReadyState(HTMLMediaElement::kHaveMetadata); |
| + testing::runPendingTasks(); |
| + |
| + checkStatePendingFullscreen(); |
| +} |
| + |
| +TEST_F(MediaControlsOrientationLockDelegateTest, ComputeOrientationLock) { |
| + // Set up the WebMediaPlayer instance. |
| + video().setSrc("http://example.com"); |
| + testing::runPendingTasks(); |
| + |
| + EXPECT_CALL(mockWebMediaPlayer(), naturalSize()) |
| + .Times(14) // Each `computeOrientationLock` calls the method twice. |
| + .WillOnce(Return(WebSize(100, 50))) |
| + .WillOnce(Return(WebSize(100, 50))) |
| + .WillOnce(Return(WebSize(50, 100))) |
| + .WillOnce(Return(WebSize(50, 100))) |
| + .WillRepeatedly(Return(WebSize(100, 100))); |
| + |
| + // 100x50 |
| + EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); |
| + |
| + // 50x100 |
| + EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); |
| + |
| + // 100x100 has more subtilities, it depends on the current screen orientation. |
| + WebScreenInfo screenInfo; |
| + screenInfo.orientationType = WebScreenOrientationUndefined; |
| + EXPECT_CALL(chromeClient(), screenInfo()) |
| + .Times(1) |
| + .WillOnce(Return(screenInfo)); |
| + EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); |
| + |
| + screenInfo.orientationType = WebScreenOrientationPortraitPrimary; |
| + EXPECT_CALL(chromeClient(), screenInfo()) |
| + .Times(1) |
| + .WillOnce(Return(screenInfo)); |
| + EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); |
| + |
| + screenInfo.orientationType = WebScreenOrientationPortraitPrimary; |
| + EXPECT_CALL(chromeClient(), screenInfo()) |
| + .Times(1) |
| + .WillOnce(Return(screenInfo)); |
| + EXPECT_EQ(WebScreenOrientationLockPortrait, computeOrientationLock()); |
| + |
| + screenInfo.orientationType = WebScreenOrientationLandscapePrimary; |
| + EXPECT_CALL(chromeClient(), screenInfo()) |
| + .Times(1) |
| + .WillOnce(Return(screenInfo)); |
| + EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); |
| + |
| + screenInfo.orientationType = WebScreenOrientationLandscapeSecondary; |
| + EXPECT_CALL(chromeClient(), screenInfo()) |
| + .Times(1) |
| + .WillOnce(Return(screenInfo)); |
| + EXPECT_EQ(WebScreenOrientationLockLandscape, computeOrientationLock()); |
| +} |
| + |
| +} // namespace blink |