| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/media_controls/MediaControlsImpl.h" | 5 #include "modules/media_controls/MediaControlsImpl.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include "core/HTMLNames.h" | 9 #include "core/HTMLNames.h" |
| 10 #include "core/css/StylePropertySet.h" | 10 #include "core/css/StylePropertySet.h" |
| 11 #include "core/dom/ClientRect.h" | 11 #include "core/dom/ClientRect.h" |
| 12 #include "core/dom/Document.h" | 12 #include "core/dom/Document.h" |
| 13 #include "core/dom/ElementTraversal.h" | 13 #include "core/dom/ElementTraversal.h" |
| 14 #include "core/dom/StyleEngine.h" | 14 #include "core/dom/StyleEngine.h" |
| 15 #include "core/events/Event.h" | 15 #include "core/events/Event.h" |
| 16 #include "core/frame/Settings.h" | 16 #include "core/frame/Settings.h" |
| 17 #include "core/html/HTMLElement.h" | 17 #include "core/html/HTMLElement.h" |
| 18 #include "core/html/HTMLVideoElement.h" | 18 #include "core/html/HTMLVideoElement.h" |
| 19 #include "core/html/shadow/MediaControlElementTypes.h" | 19 #include "core/html/shadow/MediaControlElementTypes.h" |
| 20 #include "core/input/EventHandler.h" | 20 #include "core/input/EventHandler.h" |
| 21 #include "core/layout/LayoutObject.h" | 21 #include "core/layout/LayoutObject.h" |
| 22 #include "core/loader/EmptyClients.h" | 22 #include "core/loader/EmptyClients.h" |
| 23 #include "core/testing/DummyPageHolder.h" | 23 #include "core/testing/DummyPageHolder.h" |
| 24 #include "platform/heap/Handle.h" | 24 #include "platform/heap/Handle.h" |
| 25 #include "platform/testing/EmptyWebMediaPlayer.h" | 25 #include "platform/testing/EmptyWebMediaPlayer.h" |
| 26 #include "platform/testing/HistogramTester.h" | 26 #include "platform/testing/HistogramTester.h" |
| 27 #include "platform/testing/TestingPlatformSupport.h" |
| 27 #include "platform/testing/UnitTestHelpers.h" | 28 #include "platform/testing/UnitTestHelpers.h" |
| 28 #include "public/platform/WebMouseEvent.h" | 29 #include "public/platform/WebMouseEvent.h" |
| 29 #include "public/platform/WebScreenInfo.h" | 30 #include "public/platform/WebScreenInfo.h" |
| 30 #include "public/platform/WebSize.h" | 31 #include "public/platform/WebSize.h" |
| 31 #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h
" | 32 #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h
" |
| 32 #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h" | 33 #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 34 #include "testing/gtest/include/gtest/gtest.h" |
| 34 | 35 |
| 35 namespace blink { | 36 namespace blink { |
| 36 | 37 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 enum DownloadActionMetrics { | 154 enum DownloadActionMetrics { |
| 154 Shown = 0, | 155 Shown = 0, |
| 155 Clicked, | 156 Clicked, |
| 156 Count // Keep last. | 157 Count // Keep last. |
| 157 }; | 158 }; |
| 158 | 159 |
| 159 } // namespace | 160 } // namespace |
| 160 | 161 |
| 161 class MediaControlsImplTest : public ::testing::Test { | 162 class MediaControlsImplTest : public ::testing::Test { |
| 162 protected: | 163 protected: |
| 163 virtual void SetUp() { | 164 virtual void SetUp() { initializePage(); } |
| 165 |
| 166 void initializePage() { |
| 164 Page::PageClients clients; | 167 Page::PageClients clients; |
| 165 fillWithEmptyClients(clients); | 168 fillWithEmptyClients(clients); |
| 166 clients.chromeClient = new MockChromeClient(); | 169 clients.chromeClient = new MockChromeClient(); |
| 167 m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, | 170 m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, |
| 168 StubLocalFrameClient::create()); | 171 StubLocalFrameClient::create()); |
| 169 | 172 |
| 170 document().write("<video>"); | 173 document().write("<video>"); |
| 171 HTMLVideoElement& video = | 174 HTMLVideoElement& video = |
| 172 toHTMLVideoElement(*document().querySelector("video")); | 175 toHTMLVideoElement(*document().querySelector("video")); |
| 173 m_mediaControls = static_cast<MediaControlsImpl*>(video.mediaControls()); | 176 m_mediaControls = static_cast<MediaControlsImpl*>(video.mediaControls()); |
| 174 | 177 |
| 175 // If scripts are not enabled, controls will always be shown. | 178 // If scripts are not enabled, controls will always be shown. |
| 176 m_pageHolder->frame().settings()->setScriptEnabled(true); | 179 m_pageHolder->frame().settings()->setScriptEnabled(true); |
| 177 } | 180 } |
| 178 | 181 |
| 179 void simulateRouteAvailabe() { | 182 void simulateRouteAvailable() { |
| 180 m_mediaControls->mediaElement().remoteRouteAvailabilityChanged( | 183 m_mediaControls->mediaElement().remoteRouteAvailabilityChanged( |
| 181 WebRemotePlaybackAvailability::DeviceAvailable); | 184 WebRemotePlaybackAvailability::DeviceAvailable); |
| 182 } | 185 } |
| 183 | 186 |
| 184 void ensureSizing() { | 187 void ensureSizing() { |
| 185 // Fire the size-change callback to ensure that the controls have | 188 // Fire the size-change callback to ensure that the controls have |
| 186 // been properly notified of the video size. | 189 // been properly notified of the video size. |
| 187 m_mediaControls->notifyElementSizeChanged( | 190 m_mediaControls->notifyElementSizeChanged( |
| 188 m_mediaControls->mediaElement().getBoundingClientRect()); | 191 m_mediaControls->mediaElement().getBoundingClientRect()); |
| 189 } | 192 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 ensureSizing(); | 317 ensureSizing(); |
| 315 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, | 318 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, |
| 316 true); | 319 true); |
| 317 | 320 |
| 318 Element* castButton = getElementByShadowPseudoId( | 321 Element* castButton = getElementByShadowPseudoId( |
| 319 mediaControls(), "-internal-media-controls-cast-button"); | 322 mediaControls(), "-internal-media-controls-cast-button"); |
| 320 ASSERT_NE(nullptr, castButton); | 323 ASSERT_NE(nullptr, castButton); |
| 321 | 324 |
| 322 ASSERT_FALSE(isElementVisible(*castButton)); | 325 ASSERT_FALSE(isElementVisible(*castButton)); |
| 323 | 326 |
| 324 simulateRouteAvailabe(); | 327 simulateRouteAvailable(); |
| 325 ASSERT_TRUE(isElementVisible(*castButton)); | 328 ASSERT_TRUE(isElementVisible(*castButton)); |
| 326 } | 329 } |
| 327 | 330 |
| 328 TEST_F(MediaControlsImplTest, CastButtonDisableRemotePlaybackAttr) { | 331 TEST_F(MediaControlsImplTest, CastButtonDisableRemotePlaybackAttr) { |
| 329 ensureSizing(); | 332 ensureSizing(); |
| 330 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, | 333 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, |
| 331 true); | 334 true); |
| 332 | 335 |
| 333 Element* castButton = getElementByShadowPseudoId( | 336 Element* castButton = getElementByShadowPseudoId( |
| 334 mediaControls(), "-internal-media-controls-cast-button"); | 337 mediaControls(), "-internal-media-controls-cast-button"); |
| 335 ASSERT_NE(nullptr, castButton); | 338 ASSERT_NE(nullptr, castButton); |
| 336 | 339 |
| 337 ASSERT_FALSE(isElementVisible(*castButton)); | 340 ASSERT_FALSE(isElementVisible(*castButton)); |
| 338 simulateRouteAvailabe(); | 341 simulateRouteAvailable(); |
| 339 ASSERT_TRUE(isElementVisible(*castButton)); | 342 ASSERT_TRUE(isElementVisible(*castButton)); |
| 340 | 343 |
| 341 mediaControls().mediaElement().setBooleanAttribute( | 344 mediaControls().mediaElement().setBooleanAttribute( |
| 342 HTMLNames::disableremoteplaybackAttr, true); | 345 HTMLNames::disableremoteplaybackAttr, true); |
| 343 ASSERT_FALSE(isElementVisible(*castButton)); | 346 ASSERT_FALSE(isElementVisible(*castButton)); |
| 344 | 347 |
| 345 mediaControls().mediaElement().setBooleanAttribute( | 348 mediaControls().mediaElement().setBooleanAttribute( |
| 346 HTMLNames::disableremoteplaybackAttr, false); | 349 HTMLNames::disableremoteplaybackAttr, false); |
| 347 ASSERT_TRUE(isElementVisible(*castButton)); | 350 ASSERT_TRUE(isElementVisible(*castButton)); |
| 348 } | 351 } |
| 349 | 352 |
| 350 TEST_F(MediaControlsImplTest, CastOverlayDefault) { | 353 TEST_F(MediaControlsImplTest, CastOverlayDefault) { |
| 351 Element* castOverlayButton = getElementByShadowPseudoId( | 354 Element* castOverlayButton = getElementByShadowPseudoId( |
| 352 mediaControls(), "-internal-media-controls-overlay-cast-button"); | 355 mediaControls(), "-internal-media-controls-overlay-cast-button"); |
| 353 ASSERT_NE(nullptr, castOverlayButton); | 356 ASSERT_NE(nullptr, castOverlayButton); |
| 354 | 357 |
| 355 simulateRouteAvailabe(); | 358 simulateRouteAvailable(); |
| 356 ASSERT_TRUE(isElementVisible(*castOverlayButton)); | 359 ASSERT_TRUE(isElementVisible(*castOverlayButton)); |
| 357 } | 360 } |
| 358 | 361 |
| 359 TEST_F(MediaControlsImplTest, CastOverlayDisableRemotePlaybackAttr) { | 362 TEST_F(MediaControlsImplTest, CastOverlayDisableRemotePlaybackAttr) { |
| 360 Element* castOverlayButton = getElementByShadowPseudoId( | 363 Element* castOverlayButton = getElementByShadowPseudoId( |
| 361 mediaControls(), "-internal-media-controls-overlay-cast-button"); | 364 mediaControls(), "-internal-media-controls-overlay-cast-button"); |
| 362 ASSERT_NE(nullptr, castOverlayButton); | 365 ASSERT_NE(nullptr, castOverlayButton); |
| 363 | 366 |
| 364 ASSERT_FALSE(isElementVisible(*castOverlayButton)); | 367 ASSERT_FALSE(isElementVisible(*castOverlayButton)); |
| 365 simulateRouteAvailabe(); | 368 simulateRouteAvailable(); |
| 366 ASSERT_TRUE(isElementVisible(*castOverlayButton)); | 369 ASSERT_TRUE(isElementVisible(*castOverlayButton)); |
| 367 | 370 |
| 368 mediaControls().mediaElement().setBooleanAttribute( | 371 mediaControls().mediaElement().setBooleanAttribute( |
| 369 HTMLNames::disableremoteplaybackAttr, true); | 372 HTMLNames::disableremoteplaybackAttr, true); |
| 370 ASSERT_FALSE(isElementVisible(*castOverlayButton)); | 373 ASSERT_FALSE(isElementVisible(*castOverlayButton)); |
| 371 | 374 |
| 372 mediaControls().mediaElement().setBooleanAttribute( | 375 mediaControls().mediaElement().setBooleanAttribute( |
| 373 HTMLNames::disableremoteplaybackAttr, false); | 376 HTMLNames::disableremoteplaybackAttr, false); |
| 374 ASSERT_TRUE(isElementVisible(*castOverlayButton)); | 377 ASSERT_TRUE(isElementVisible(*castOverlayButton)); |
| 375 } | 378 } |
| 376 | 379 |
| 377 TEST_F(MediaControlsImplTest, CastOverlayMediaControlsDisabled) { | 380 TEST_F(MediaControlsImplTest, CastOverlayMediaControlsDisabled) { |
| 378 Element* castOverlayButton = getElementByShadowPseudoId( | 381 Element* castOverlayButton = getElementByShadowPseudoId( |
| 379 mediaControls(), "-internal-media-controls-overlay-cast-button"); | 382 mediaControls(), "-internal-media-controls-overlay-cast-button"); |
| 380 ASSERT_NE(nullptr, castOverlayButton); | 383 ASSERT_NE(nullptr, castOverlayButton); |
| 381 | 384 |
| 382 EXPECT_FALSE(isElementVisible(*castOverlayButton)); | 385 EXPECT_FALSE(isElementVisible(*castOverlayButton)); |
| 383 simulateRouteAvailabe(); | 386 simulateRouteAvailable(); |
| 384 EXPECT_TRUE(isElementVisible(*castOverlayButton)); | 387 EXPECT_TRUE(isElementVisible(*castOverlayButton)); |
| 385 | 388 |
| 386 document().settings()->setMediaControlsEnabled(false); | 389 document().settings()->setMediaControlsEnabled(false); |
| 387 EXPECT_FALSE(isElementVisible(*castOverlayButton)); | 390 EXPECT_FALSE(isElementVisible(*castOverlayButton)); |
| 388 | 391 |
| 389 document().settings()->setMediaControlsEnabled(true); | 392 document().settings()->setMediaControlsEnabled(true); |
| 390 EXPECT_TRUE(isElementVisible(*castOverlayButton)); | 393 EXPECT_TRUE(isElementVisible(*castOverlayButton)); |
| 391 } | 394 } |
| 392 | 395 |
| 393 TEST_F(MediaControlsImplTest, KeepControlsVisibleIfOverflowListVisible) { | 396 TEST_F(MediaControlsImplTest, KeepControlsVisibleIfOverflowListVisible) { |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 histogramTester().expectTotalCount( | 789 histogramTester().expectTotalCount( |
| 787 "Media.Timeline.DragGestureDuration.128_255", 1); | 790 "Media.Timeline.DragGestureDuration.128_255", 1); |
| 788 histogramTester().expectUniqueSample("Media.Timeline.DragPercent.128_255", | 791 histogramTester().expectUniqueSample("Media.Timeline.DragPercent.128_255", |
| 789 8 /* (-35.0%, -30.0%] */, 1); | 792 8 /* (-35.0%, -30.0%] */, 1); |
| 790 histogramTester().expectUniqueSample( | 793 histogramTester().expectUniqueSample( |
| 791 "Media.Timeline.DragSumAbsTimeDelta.128_255", 17 /* [8m, 15m) */, 1); | 794 "Media.Timeline.DragSumAbsTimeDelta.128_255", 17 /* [8m, 15m) */, 1); |
| 792 histogramTester().expectUniqueSample("Media.Timeline.DragTimeDelta.128_255", | 795 histogramTester().expectUniqueSample("Media.Timeline.DragTimeDelta.128_255", |
| 793 9 /* (-4m, -2m] */, 1); | 796 9 /* (-4m, -2m] */, 1); |
| 794 } | 797 } |
| 795 | 798 |
| 799 TEST_F(MediaControlsImplTest, ControlsRemainVisibleDuringKeyboardInteraction) { |
| 800 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> |
| 801 m_platform; |
| 802 |
| 803 // DocumentParserTiming has DCHECKS to make sure time > 0.0. |
| 804 m_platform->advanceClockSeconds(1); |
| 805 |
| 806 // Need to reinitialize page since we changed the platform. |
| 807 initializePage(); |
| 808 ensureSizing(); |
| 809 |
| 810 Element* panel = mediaControls().panelElement(); |
| 811 |
| 812 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, |
| 813 true); |
| 814 mediaControls().mediaElement().setSrc("http://example.com"); |
| 815 mediaControls().mediaElement().play(); |
| 816 |
| 817 // Controls start out visible. |
| 818 EXPECT_TRUE(isElementVisible(*panel)); |
| 819 |
| 820 // Tabbing between controls prevents controls from hiding. |
| 821 m_platform->runForPeriodSeconds(2); |
| 822 mediaControls().dispatchEvent(Event::create("focusin")); |
| 823 m_platform->runForPeriodSeconds(2); |
| 824 EXPECT_TRUE(isElementVisible(*panel)); |
| 825 |
| 826 // Seeking on the timeline or volume bar prevents controls from hiding. |
| 827 mediaControls().dispatchEvent(Event::create("input")); |
| 828 m_platform->runForPeriodSeconds(2); |
| 829 EXPECT_TRUE(isElementVisible(*panel)); |
| 830 |
| 831 // Pressing a key prevents controls from hiding. |
| 832 mediaControls().panelElement()->dispatchEvent(Event::create("keypress")); |
| 833 m_platform->runForPeriodSeconds(2); |
| 834 EXPECT_TRUE(isElementVisible(*panel)); |
| 835 |
| 836 // Once user interaction stops, controls can hide. |
| 837 m_platform->runForPeriodSeconds(2); |
| 838 EXPECT_FALSE(isElementVisible(*panel)); |
| 839 } |
| 840 |
| 796 } // namespace blink | 841 } // namespace blink |
| OLD | NEW |