| Index: third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
|
| diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
|
| index ab4cb7734dc4da433e3ff0e44e69270509392b1c..04cb43bdb82d131f027fdfc32d32529494cb6cf5 100644
|
| --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
|
| +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
|
| @@ -8,6 +8,7 @@
|
| #include <memory>
|
| #include "core/HTMLNames.h"
|
| #include "core/css/StylePropertySet.h"
|
| +#include "core/dom/ClientRect.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/ElementTraversal.h"
|
| #include "core/dom/StyleEngine.h"
|
| @@ -16,6 +17,7 @@
|
| #include "core/html/HTMLElement.h"
|
| #include "core/html/HTMLVideoElement.h"
|
| #include "core/html/shadow/MediaControlElementTypes.h"
|
| +#include "core/input/EventHandler.h"
|
| #include "core/layout/LayoutObject.h"
|
| #include "core/loader/EmptyClients.h"
|
| #include "core/testing/DummyPageHolder.h"
|
| @@ -23,6 +25,8 @@
|
| #include "platform/testing/EmptyWebMediaPlayer.h"
|
| #include "platform/testing/HistogramTester.h"
|
| #include "platform/testing/UnitTestHelpers.h"
|
| +#include "public/platform/WebMouseEvent.h"
|
| +#include "public/platform/WebScreenInfo.h"
|
| #include "public/platform/WebSize.h"
|
| #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h"
|
| #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h"
|
| @@ -32,6 +36,16 @@ namespace blink {
|
|
|
| namespace {
|
|
|
| +class MockChromeClient : public EmptyChromeClient {
|
| + public:
|
| + // EmptyChromeClient overrides:
|
| + WebScreenInfo screenInfo() const override {
|
| + WebScreenInfo screenInfo;
|
| + screenInfo.orientationType = WebScreenOrientationLandscapePrimary;
|
| + return screenInfo;
|
| + }
|
| +};
|
| +
|
| class MockVideoWebMediaPlayer : public EmptyWebMediaPlayer {
|
| public:
|
| // WebMediaPlayer overrides:
|
| @@ -147,13 +161,15 @@ enum DownloadActionMetrics {
|
| class MediaControlsImplTest : public ::testing::Test {
|
| protected:
|
| virtual void SetUp() {
|
| - m_pageHolder = DummyPageHolder::create(IntSize(800, 600), nullptr,
|
| + Page::PageClients clients;
|
| + fillWithEmptyClients(clients);
|
| + clients.chromeClient = new MockChromeClient();
|
| + m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients,
|
| StubLocalFrameClient::create());
|
| - Document& document = this->document();
|
|
|
| - document.write("<video>");
|
| + document().write("<video>");
|
| HTMLVideoElement& video =
|
| - toHTMLVideoElement(*document.querySelector("video"));
|
| + toHTMLVideoElement(*document().querySelector("video"));
|
| m_mediaControls = static_cast<MediaControlsImpl*>(video.mediaControls());
|
|
|
| // If scripts are not enabled, controls will always be shown.
|
| @@ -197,12 +213,50 @@ class MediaControlsImplTest : public ::testing::Test {
|
| simulateLoadedMetadata();
|
| }
|
|
|
| + void setReady() {
|
| + mediaControls().mediaElement().setReadyState(
|
| + HTMLMediaElement::kHaveEnoughData);
|
| + }
|
| +
|
| + void mouseDownAt(WebFloatPoint pos);
|
| + void mouseMoveTo(WebFloatPoint pos);
|
| + void mouseUpAt(WebFloatPoint pos);
|
| +
|
| private:
|
| std::unique_ptr<DummyPageHolder> m_pageHolder;
|
| Persistent<MediaControlsImpl> m_mediaControls;
|
| HistogramTester m_histogramTester;
|
| };
|
|
|
| +void MediaControlsImplTest::mouseDownAt(WebFloatPoint pos) {
|
| + WebMouseEvent mouseDownEvent(WebInputEvent::MouseDown, pos /* client pos */,
|
| + pos /* screen pos */,
|
| + WebPointerProperties::Button::Left, 1,
|
| + WebInputEvent::Modifiers::LeftButtonDown,
|
| + WebInputEvent::TimeStampForTesting);
|
| + mouseDownEvent.setFrameScale(1);
|
| + document().frame()->eventHandler().handleMousePressEvent(mouseDownEvent);
|
| +}
|
| +
|
| +void MediaControlsImplTest::mouseMoveTo(WebFloatPoint pos) {
|
| + WebMouseEvent mouseMoveEvent(WebInputEvent::MouseMove, pos /* client pos */,
|
| + pos /* screen pos */,
|
| + WebPointerProperties::Button::Left, 1,
|
| + WebInputEvent::Modifiers::LeftButtonDown,
|
| + WebInputEvent::TimeStampForTesting);
|
| + mouseMoveEvent.setFrameScale(1);
|
| + document().frame()->eventHandler().handleMouseMoveEvent(mouseMoveEvent, {});
|
| +}
|
| +
|
| +void MediaControlsImplTest::mouseUpAt(WebFloatPoint pos) {
|
| + WebMouseEvent mouseUpEvent(
|
| + WebMouseEvent::MouseUp, pos /* client pos */, pos /* screen pos */,
|
| + WebPointerProperties::Button::Left, 1, WebInputEvent::NoModifiers,
|
| + WebInputEvent::TimeStampForTesting);
|
| + mouseUpEvent.setFrameScale(1);
|
| + document().frame()->eventHandler().handleMouseReleaseEvent(mouseUpEvent);
|
| +}
|
| +
|
| TEST_F(MediaControlsImplTest, HideAndShow) {
|
| mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr,
|
| true);
|
| @@ -481,11 +535,6 @@ TEST_F(MediaControlsImplTest, DownloadButtonNotDisplayedHLS) {
|
| TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) {
|
| ensureSizing();
|
|
|
| - MediaControlTimelineElement* timeline =
|
| - static_cast<MediaControlTimelineElement*>(getElementByShadowPseudoId(
|
| - mediaControls(), "-webkit-media-controls-timeline"));
|
| - ASSERT_NE(nullptr, timeline);
|
| -
|
| // Tests the case where the real length of the video, |exactDuration|, gets
|
| // rounded up slightly to |roundedUpDuration| when setting the timeline's
|
| // |max| attribute (crbug.com/695065).
|
| @@ -496,6 +545,7 @@ TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) {
|
| // Simulate a click slightly past the end of the track of the timeline's
|
| // underlying <input type="range">. This would set the |value| to the |max|
|
| // attribute, which can be slightly rounded relative to the duration.
|
| + MediaControlTimelineElement* timeline = mediaControls().timelineElement();
|
| timeline->setValueAsNumber(roundedUpDuration, ASSERT_NO_EXCEPTION);
|
| ASSERT_EQ(roundedUpDuration, timeline->valueAsNumber());
|
| EXPECT_EQ(0.0, mediaControls().mediaElement().currentTime());
|
| @@ -506,53 +556,213 @@ TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) {
|
| TEST_F(MediaControlsImplTest, TimelineImmediatelyUpdatesCurrentTime) {
|
| ensureSizing();
|
|
|
| - MediaControlTimelineElement* timeline =
|
| - static_cast<MediaControlTimelineElement*>(getElementByShadowPseudoId(
|
| - mediaControls(), "-webkit-media-controls-timeline"));
|
| - ASSERT_NE(nullptr, timeline);
|
| MediaControlCurrentTimeDisplayElement* currentTimeDisplay =
|
| static_cast<MediaControlCurrentTimeDisplayElement*>(
|
| getElementByShadowPseudoId(
|
| mediaControls(), "-webkit-media-controls-current-time-display"));
|
| - ASSERT_NE(nullptr, currentTimeDisplay);
|
|
|
| double duration = 600;
|
| loadMediaWithDuration(duration);
|
|
|
| // Simulate seeking the underlying range to 50%. Current time display should
|
| // update synchronously (rather than waiting for media to finish seeking).
|
| - timeline->setValueAsNumber(duration / 2, ASSERT_NO_EXCEPTION);
|
| - timeline->dispatchInputEvent();
|
| + mediaControls().timelineElement()->setValueAsNumber(duration / 2,
|
| + ASSERT_NO_EXCEPTION);
|
| + mediaControls().timelineElement()->dispatchInputEvent();
|
| EXPECT_EQ(duration / 2, currentTimeDisplay->currentValue());
|
| }
|
|
|
| TEST_F(MediaControlsImplTest, VolumeSliderPaintInvalidationOnInput) {
|
| ensureSizing();
|
|
|
| - MediaControlVolumeSliderElement* volumeSlider =
|
| - static_cast<MediaControlVolumeSliderElement*>(getElementByShadowPseudoId(
|
| - mediaControls(), "-webkit-media-controls-volume-slider"));
|
| - ASSERT_NE(nullptr, volumeSlider);
|
| -
|
| - HTMLElement* element = volumeSlider;
|
| + Element* volumeSlider = mediaControls().volumeSliderElement();
|
|
|
| MockLayoutObject layoutObject;
|
| LayoutObject* prevLayoutObject = volumeSlider->layoutObject();
|
| volumeSlider->setLayoutObject(&layoutObject);
|
|
|
| Event* event = Event::create(EventTypeNames::input);
|
| - element->defaultEventHandler(event);
|
| + volumeSlider->defaultEventHandler(event);
|
| EXPECT_EQ(1, layoutObject.fullPaintInvalidationCallCount());
|
|
|
| event = Event::create(EventTypeNames::input);
|
| - element->defaultEventHandler(event);
|
| + volumeSlider->defaultEventHandler(event);
|
| EXPECT_EQ(2, layoutObject.fullPaintInvalidationCallCount());
|
|
|
| event = Event::create(EventTypeNames::input);
|
| - element->defaultEventHandler(event);
|
| + volumeSlider->defaultEventHandler(event);
|
| EXPECT_EQ(3, layoutObject.fullPaintInvalidationCallCount());
|
|
|
| volumeSlider->setLayoutObject(prevLayoutObject);
|
| }
|
|
|
| +TEST_F(MediaControlsImplTest, TimelineMetricsWidth) {
|
| + mediaControls().mediaElement().setSrc("https://example.com/foo.mp4");
|
| + testing::runPendingTasks();
|
| + setReady();
|
| + ensureSizing();
|
| + testing::runPendingTasks();
|
| +
|
| + MediaControlTimelineElement* timeline = mediaControls().timelineElement();
|
| + ASSERT_TRUE(isElementVisible(*timeline));
|
| + ASSERT_LT(0, timeline->getBoundingClientRect()->width());
|
| +
|
| + mediaControls().mediaElement().play();
|
| + testing::runPendingTasks();
|
| +
|
| + histogramTester().expectUniqueSample(
|
| + "Media.Timeline.Width.InlineLandscape",
|
| + timeline->getBoundingClientRect()->width(), 1);
|
| + histogramTester().expectTotalCount("Media.Timeline.Width.InlinePortrait", 0);
|
| + histogramTester().expectTotalCount("Media.Timeline.Width.FullscreenLandscape",
|
| + 0);
|
| + histogramTester().expectTotalCount("Media.Timeline.Width.FullscreenPortrait",
|
| + 0);
|
| +}
|
| +
|
| +TEST_F(MediaControlsImplTest, TimelineMetricsClick) {
|
| + double duration = 540; // 9 minutes
|
| + loadMediaWithDuration(duration);
|
| + ensureSizing();
|
| + testing::runPendingTasks();
|
| +
|
| + ASSERT_TRUE(isElementVisible(*mediaControls().timelineElement()));
|
| + ClientRect* timelineRect =
|
| + mediaControls().timelineElement()->getBoundingClientRect();
|
| + ASSERT_LT(0, timelineRect->width());
|
| +
|
| + EXPECT_EQ(0, mediaControls().mediaElement().currentTime());
|
| +
|
| + WebFloatPoint trackCenter(timelineRect->left() + timelineRect->width() / 2,
|
| + timelineRect->top() + timelineRect->height() / 2);
|
| + mouseDownAt(trackCenter);
|
| + mouseUpAt(trackCenter);
|
| + testing::runPendingTasks();
|
| +
|
| + EXPECT_LE(0.49 * duration, mediaControls().mediaElement().currentTime());
|
| + EXPECT_GE(0.51 * duration, mediaControls().mediaElement().currentTime());
|
| +
|
| + histogramTester().expectUniqueSample("Media.Timeline.SeekType.128_255",
|
| + 0 /* SeekType::kClick */, 1);
|
| + histogramTester().expectTotalCount(
|
| + "Media.Timeline.DragGestureDuration.128_255", 0);
|
| + histogramTester().expectTotalCount("Media.Timeline.DragPercent.128_255", 0);
|
| + histogramTester().expectTotalCount(
|
| + "Media.Timeline.DragSumAbsTimeDelta.128_255", 0);
|
| + histogramTester().expectTotalCount("Media.Timeline.DragTimeDelta.128_255", 0);
|
| +}
|
| +
|
| +TEST_F(MediaControlsImplTest, TimelineMetricsDragFromCurrentPosition) {
|
| + double duration = 540; // 9 minutes
|
| + loadMediaWithDuration(duration);
|
| + ensureSizing();
|
| + testing::runPendingTasks();
|
| +
|
| + ASSERT_TRUE(isElementVisible(*mediaControls().timelineElement()));
|
| + ClientRect* timelineRect =
|
| + mediaControls().timelineElement()->getBoundingClientRect();
|
| + ASSERT_LT(0, timelineRect->width());
|
| +
|
| + EXPECT_EQ(0, mediaControls().mediaElement().currentTime());
|
| +
|
| + float y = timelineRect->top() + timelineRect->height() / 2;
|
| + WebFloatPoint thumb(timelineRect->left(), y);
|
| + WebFloatPoint trackTwoThirds(
|
| + timelineRect->left() + timelineRect->width() * 2 / 3, y);
|
| + mouseDownAt(thumb);
|
| + mouseMoveTo(trackTwoThirds);
|
| + mouseUpAt(trackTwoThirds);
|
| +
|
| + EXPECT_LE(0.66 * duration, mediaControls().mediaElement().currentTime());
|
| + EXPECT_GE(0.68 * duration, mediaControls().mediaElement().currentTime());
|
| +
|
| + histogramTester().expectUniqueSample(
|
| + "Media.Timeline.SeekType.128_255",
|
| + 1 /* SeekType::kDragFromCurrentPosition */, 1);
|
| + histogramTester().expectTotalCount(
|
| + "Media.Timeline.DragGestureDuration.128_255", 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragPercent.128_255",
|
| + 47 /* [60.0%, 70.0%) */, 1);
|
| + histogramTester().expectUniqueSample(
|
| + "Media.Timeline.DragSumAbsTimeDelta.128_255", 16 /* [4m, 8m) */, 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragTimeDelta.128_255",
|
| + 40 /* [4m, 8m) */, 1);
|
| +}
|
| +
|
| +TEST_F(MediaControlsImplTest, TimelineMetricsDragFromElsewhere) {
|
| + double duration = 540; // 9 minutes
|
| + loadMediaWithDuration(duration);
|
| + ensureSizing();
|
| + testing::runPendingTasks();
|
| +
|
| + ASSERT_TRUE(isElementVisible(*mediaControls().timelineElement()));
|
| + ClientRect* timelineRect =
|
| + mediaControls().timelineElement()->getBoundingClientRect();
|
| + ASSERT_LT(0, timelineRect->width());
|
| +
|
| + EXPECT_EQ(0, mediaControls().mediaElement().currentTime());
|
| +
|
| + float y = timelineRect->top() + timelineRect->height() / 2;
|
| + WebFloatPoint trackOneThird(
|
| + timelineRect->left() + timelineRect->width() * 1 / 3, y);
|
| + WebFloatPoint trackTwoThirds(
|
| + timelineRect->left() + timelineRect->width() * 2 / 3, y);
|
| + mouseDownAt(trackOneThird);
|
| + mouseMoveTo(trackTwoThirds);
|
| + mouseUpAt(trackTwoThirds);
|
| +
|
| + EXPECT_LE(0.66 * duration, mediaControls().mediaElement().currentTime());
|
| + EXPECT_GE(0.68 * duration, mediaControls().mediaElement().currentTime());
|
| +
|
| + histogramTester().expectUniqueSample("Media.Timeline.SeekType.128_255",
|
| + 2 /* SeekType::kDragFromElsewhere */, 1);
|
| + histogramTester().expectTotalCount(
|
| + "Media.Timeline.DragGestureDuration.128_255", 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragPercent.128_255",
|
| + 42 /* [30.0%, 35.0%) */, 1);
|
| + histogramTester().expectUniqueSample(
|
| + "Media.Timeline.DragSumAbsTimeDelta.128_255", 15 /* [2m, 4m) */, 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragTimeDelta.128_255",
|
| + 39 /* [2m, 4m) */, 1);
|
| +}
|
| +
|
| +TEST_F(MediaControlsImplTest, TimelineMetricsDragBackAndForth) {
|
| + double duration = 540; // 9 minutes
|
| + loadMediaWithDuration(duration);
|
| + ensureSizing();
|
| + testing::runPendingTasks();
|
| +
|
| + ASSERT_TRUE(isElementVisible(*mediaControls().timelineElement()));
|
| + ClientRect* timelineRect =
|
| + mediaControls().timelineElement()->getBoundingClientRect();
|
| + ASSERT_LT(0, timelineRect->width());
|
| +
|
| + EXPECT_EQ(0, mediaControls().mediaElement().currentTime());
|
| +
|
| + float y = timelineRect->top() + timelineRect->height() / 2;
|
| + WebFloatPoint trackTwoThirds(
|
| + timelineRect->left() + timelineRect->width() * 2 / 3, y);
|
| + WebFloatPoint trackEnd(timelineRect->left() + timelineRect->width(), y);
|
| + WebFloatPoint trackOneThird(
|
| + timelineRect->left() + timelineRect->width() * 1 / 3, y);
|
| + mouseDownAt(trackTwoThirds);
|
| + mouseMoveTo(trackEnd);
|
| + mouseMoveTo(trackOneThird);
|
| + mouseUpAt(trackOneThird);
|
| +
|
| + EXPECT_LE(0.32 * duration, mediaControls().mediaElement().currentTime());
|
| + EXPECT_GE(0.34 * duration, mediaControls().mediaElement().currentTime());
|
| +
|
| + histogramTester().expectUniqueSample("Media.Timeline.SeekType.128_255",
|
| + 2 /* SeekType::kDragFromElsewhere */, 1);
|
| + histogramTester().expectTotalCount(
|
| + "Media.Timeline.DragGestureDuration.128_255", 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragPercent.128_255",
|
| + 8 /* (-35.0%, -30.0%] */, 1);
|
| + histogramTester().expectUniqueSample(
|
| + "Media.Timeline.DragSumAbsTimeDelta.128_255", 17 /* [8m, 15m) */, 1);
|
| + histogramTester().expectUniqueSample("Media.Timeline.DragTimeDelta.128_255",
|
| + 9 /* (-4m, -2m] */, 1);
|
| +}
|
| +
|
| } // namespace blink
|
|
|