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

Unified Diff: third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp

Issue 2779273003: [Media Controls] Add UMA for timeline scrubber (Closed)
Patch Set: Appease MSVC Created 3 years, 8 months 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 side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp ('k') | third_party/WebKit/Source/platform/Histogram.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698