| 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 "core/html/shadow/MediaControls.h" | 5 #include "core/html/shadow/MediaControls.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" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 164 |
| 165 // If scripts are not enabled, controls will always be shown. | 165 // If scripts are not enabled, controls will always be shown. |
| 166 m_pageHolder->frame().settings()->setScriptEnabled(true); | 166 m_pageHolder->frame().settings()->setScriptEnabled(true); |
| 167 } | 167 } |
| 168 | 168 |
| 169 void simulateRouteAvailabe() { | 169 void simulateRouteAvailabe() { |
| 170 m_mediaControls->mediaElement().remoteRouteAvailabilityChanged( | 170 m_mediaControls->mediaElement().remoteRouteAvailabilityChanged( |
| 171 WebRemotePlaybackAvailability::DeviceAvailable); | 171 WebRemotePlaybackAvailability::DeviceAvailable); |
| 172 } | 172 } |
| 173 | 173 |
| 174 void ensureLayout() { | 174 void ensureSizing() { |
| 175 // Force a relayout, so that the controls know the width. Otherwise, | 175 // Fire the size-change callback to ensure that the controls have |
| 176 // they don't know if, for example, the cast button will fit. | 176 // been properly notified of the video size. |
| 177 m_mediaControls->mediaElement().clientWidth(); | 177 m_mediaControls->notifyElementSizeChanged( |
| 178 m_mediaControls->mediaElement().getBoundingClientRect()); |
| 178 } | 179 } |
| 179 | 180 |
| 180 void simulateHideMediaControlsTimerFired() { | 181 void simulateHideMediaControlsTimerFired() { |
| 181 m_mediaControls->hideMediaControlsTimerFired(nullptr); | 182 m_mediaControls->hideMediaControlsTimerFired(nullptr); |
| 182 } | 183 } |
| 183 | 184 |
| 184 void simulateLoadedMetadata() { m_mediaControls->onLoadedMetadata(); } | 185 void simulateLoadedMetadata() { m_mediaControls->onLoadedMetadata(); } |
| 185 | 186 |
| 186 MediaControls& mediaControls() { return *m_mediaControls; } | 187 MediaControls& mediaControls() { return *m_mediaControls; } |
| 187 MockVideoWebMediaPlayer* webMediaPlayer() { | 188 MockVideoWebMediaPlayer* webMediaPlayer() { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 Document& document = this->document(); | 246 Document& document = this->document(); |
| 246 int oldElementCount = document.styleEngine().styleForElementCount(); | 247 int oldElementCount = document.styleEngine().styleForElementCount(); |
| 247 // Also assert that there are no layouts yet. | 248 // Also assert that there are no layouts yet. |
| 248 ASSERT_EQ(0, oldElementCount); | 249 ASSERT_EQ(0, oldElementCount); |
| 249 mediaControls().reset(); | 250 mediaControls().reset(); |
| 250 int newElementCount = document.styleEngine().styleForElementCount(); | 251 int newElementCount = document.styleEngine().styleForElementCount(); |
| 251 ASSERT_EQ(oldElementCount, newElementCount); | 252 ASSERT_EQ(oldElementCount, newElementCount); |
| 252 } | 253 } |
| 253 | 254 |
| 254 TEST_F(MediaControlsTest, CastButtonRequiresRoute) { | 255 TEST_F(MediaControlsTest, CastButtonRequiresRoute) { |
| 255 ensureLayout(); | 256 ensureSizing(); |
| 256 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, | 257 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, |
| 257 true); | 258 true); |
| 258 | 259 |
| 259 Element* castButton = getElementByShadowPseudoId( | 260 Element* castButton = getElementByShadowPseudoId( |
| 260 mediaControls(), "-internal-media-controls-cast-button"); | 261 mediaControls(), "-internal-media-controls-cast-button"); |
| 261 ASSERT_NE(nullptr, castButton); | 262 ASSERT_NE(nullptr, castButton); |
| 262 | 263 |
| 263 ASSERT_FALSE(isElementVisible(*castButton)); | 264 ASSERT_FALSE(isElementVisible(*castButton)); |
| 264 | 265 |
| 265 simulateRouteAvailabe(); | 266 simulateRouteAvailabe(); |
| 266 ASSERT_TRUE(isElementVisible(*castButton)); | 267 ASSERT_TRUE(isElementVisible(*castButton)); |
| 267 } | 268 } |
| 268 | 269 |
| 269 TEST_F(MediaControlsTest, CastButtonDisableRemotePlaybackAttr) { | 270 TEST_F(MediaControlsTest, CastButtonDisableRemotePlaybackAttr) { |
| 270 ensureLayout(); | 271 ensureSizing(); |
| 271 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, | 272 mediaControls().mediaElement().setBooleanAttribute(HTMLNames::controlsAttr, |
| 272 true); | 273 true); |
| 273 | 274 |
| 274 Element* castButton = getElementByShadowPseudoId( | 275 Element* castButton = getElementByShadowPseudoId( |
| 275 mediaControls(), "-internal-media-controls-cast-button"); | 276 mediaControls(), "-internal-media-controls-cast-button"); |
| 276 ASSERT_NE(nullptr, castButton); | 277 ASSERT_NE(nullptr, castButton); |
| 277 | 278 |
| 278 ASSERT_FALSE(isElementVisible(*castButton)); | 279 ASSERT_FALSE(isElementVisible(*castButton)); |
| 279 simulateRouteAvailabe(); | 280 simulateRouteAvailabe(); |
| 280 ASSERT_TRUE(isElementVisible(*castButton)); | 281 ASSERT_TRUE(isElementVisible(*castButton)); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 mediaControls().show(); | 348 mediaControls().show(); |
| 348 mediaControls().toggleOverflowMenu(); | 349 mediaControls().toggleOverflowMenu(); |
| 349 EXPECT_TRUE(isElementVisible(*overflowList)); | 350 EXPECT_TRUE(isElementVisible(*overflowList)); |
| 350 | 351 |
| 351 simulateHideMediaControlsTimerFired(); | 352 simulateHideMediaControlsTimerFired(); |
| 352 EXPECT_TRUE(isElementVisible(*overflowList)); | 353 EXPECT_TRUE(isElementVisible(*overflowList)); |
| 353 EXPECT_TRUE(isElementVisible(*panel)); | 354 EXPECT_TRUE(isElementVisible(*panel)); |
| 354 } | 355 } |
| 355 | 356 |
| 356 TEST_F(MediaControlsTest, DownloadButtonDisplayed) { | 357 TEST_F(MediaControlsTest, DownloadButtonDisplayed) { |
| 357 ensureLayout(); | 358 ensureSizing(); |
| 358 | 359 |
| 359 Element* downloadButton = getElementByShadowPseudoId( | 360 Element* downloadButton = getElementByShadowPseudoId( |
| 360 mediaControls(), "-internal-media-controls-download-button"); | 361 mediaControls(), "-internal-media-controls-download-button"); |
| 361 ASSERT_NE(nullptr, downloadButton); | 362 ASSERT_NE(nullptr, downloadButton); |
| 362 | 363 |
| 363 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 364 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 364 testing::runPendingTasks(); | 365 testing::runPendingTasks(); |
| 365 simulateLoadedMetadata(); | 366 simulateLoadedMetadata(); |
| 366 | 367 |
| 367 // Download button should normally be displayed. | 368 // Download button should normally be displayed. |
| 368 EXPECT_TRUE(isElementVisible(*downloadButton)); | 369 EXPECT_TRUE(isElementVisible(*downloadButton)); |
| 369 } | 370 } |
| 370 | 371 |
| 371 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedEmptyUrl) { | 372 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedEmptyUrl) { |
| 372 ensureLayout(); | 373 ensureSizing(); |
| 373 | 374 |
| 374 Element* downloadButton = getElementByShadowPseudoId( | 375 Element* downloadButton = getElementByShadowPseudoId( |
| 375 mediaControls(), "-internal-media-controls-download-button"); | 376 mediaControls(), "-internal-media-controls-download-button"); |
| 376 ASSERT_NE(nullptr, downloadButton); | 377 ASSERT_NE(nullptr, downloadButton); |
| 377 | 378 |
| 378 // Download button should not be displayed when URL is empty. | 379 // Download button should not be displayed when URL is empty. |
| 379 mediaControls().mediaElement().setSrc(""); | 380 mediaControls().mediaElement().setSrc(""); |
| 380 testing::runPendingTasks(); | 381 testing::runPendingTasks(); |
| 381 simulateLoadedMetadata(); | 382 simulateLoadedMetadata(); |
| 382 EXPECT_FALSE(isElementVisible(*downloadButton)); | 383 EXPECT_FALSE(isElementVisible(*downloadButton)); |
| 383 } | 384 } |
| 384 | 385 |
| 385 TEST_F(MediaControlsTest, DownloadButtonDisplayedHiddenAndDisplayed) { | 386 TEST_F(MediaControlsTest, DownloadButtonDisplayedHiddenAndDisplayed) { |
| 386 ensureLayout(); | 387 ensureSizing(); |
| 387 | 388 |
| 388 Element* downloadButton = getElementByShadowPseudoId( | 389 Element* downloadButton = getElementByShadowPseudoId( |
| 389 mediaControls(), "-internal-media-controls-download-button"); | 390 mediaControls(), "-internal-media-controls-download-button"); |
| 390 ASSERT_NE(nullptr, downloadButton); | 391 ASSERT_NE(nullptr, downloadButton); |
| 391 | 392 |
| 392 // Initially show button. | 393 // Initially show button. |
| 393 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 394 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 394 testing::runPendingTasks(); | 395 testing::runPendingTasks(); |
| 395 simulateLoadedMetadata(); | 396 simulateLoadedMetadata(); |
| 396 EXPECT_TRUE(isElementVisible(*downloadButton)); | 397 EXPECT_TRUE(isElementVisible(*downloadButton)); |
| 397 histogramTester().expectBucketCount("Media.Controls.Download", | 398 histogramTester().expectBucketCount("Media.Controls.Download", |
| 398 DownloadActionMetrics::Shown, 1); | 399 DownloadActionMetrics::Shown, 1); |
| 399 | 400 |
| 400 // Hide button. | 401 // Hide button. |
| 401 mediaControls().mediaElement().setSrc(""); | 402 mediaControls().mediaElement().setSrc(""); |
| 402 testing::runPendingTasks(); | 403 testing::runPendingTasks(); |
| 403 EXPECT_TRUE(isElementVisible(*downloadButton)); | 404 EXPECT_TRUE(isElementVisible(*downloadButton)); |
| 404 histogramTester().expectBucketCount("Media.Controls.Download", | 405 histogramTester().expectBucketCount("Media.Controls.Download", |
| 405 DownloadActionMetrics::Shown, 1); | 406 DownloadActionMetrics::Shown, 1); |
| 406 | 407 |
| 407 // Showing button again should not increment Shown count. | 408 // Showing button again should not increment Shown count. |
| 408 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 409 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 409 testing::runPendingTasks(); | 410 testing::runPendingTasks(); |
| 410 EXPECT_TRUE(isElementVisible(*downloadButton)); | 411 EXPECT_TRUE(isElementVisible(*downloadButton)); |
| 411 histogramTester().expectBucketCount("Media.Controls.Download", | 412 histogramTester().expectBucketCount("Media.Controls.Download", |
| 412 DownloadActionMetrics::Shown, 1); | 413 DownloadActionMetrics::Shown, 1); |
| 413 } | 414 } |
| 414 | 415 |
| 415 TEST_F(MediaControlsTest, DownloadButtonRecordsClickOnlyOnce) { | 416 TEST_F(MediaControlsTest, DownloadButtonRecordsClickOnlyOnce) { |
| 416 ensureLayout(); | 417 ensureSizing(); |
| 417 | 418 |
| 418 MediaControlDownloadButtonElement* downloadButton = | 419 MediaControlDownloadButtonElement* downloadButton = |
| 419 static_cast<MediaControlDownloadButtonElement*>( | 420 static_cast<MediaControlDownloadButtonElement*>( |
| 420 getElementByShadowPseudoId( | 421 getElementByShadowPseudoId( |
| 421 mediaControls(), "-internal-media-controls-download-button")); | 422 mediaControls(), "-internal-media-controls-download-button")); |
| 422 ASSERT_NE(nullptr, downloadButton); | 423 ASSERT_NE(nullptr, downloadButton); |
| 423 | 424 |
| 424 // Initially show button. | 425 // Initially show button. |
| 425 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 426 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 426 testing::runPendingTasks(); | 427 testing::runPendingTasks(); |
| 427 simulateLoadedMetadata(); | 428 simulateLoadedMetadata(); |
| 428 EXPECT_TRUE(isElementVisible(*downloadButton)); | 429 EXPECT_TRUE(isElementVisible(*downloadButton)); |
| 429 histogramTester().expectBucketCount("Media.Controls.Download", | 430 histogramTester().expectBucketCount("Media.Controls.Download", |
| 430 DownloadActionMetrics::Shown, 1); | 431 DownloadActionMetrics::Shown, 1); |
| 431 | 432 |
| 432 // Click button once. | 433 // Click button once. |
| 433 downloadButton->dispatchSimulatedClick( | 434 downloadButton->dispatchSimulatedClick( |
| 434 Event::createBubble(EventTypeNames::click), SendNoEvents); | 435 Event::createBubble(EventTypeNames::click), SendNoEvents); |
| 435 histogramTester().expectBucketCount("Media.Controls.Download", | 436 histogramTester().expectBucketCount("Media.Controls.Download", |
| 436 DownloadActionMetrics::Clicked, 1); | 437 DownloadActionMetrics::Clicked, 1); |
| 437 | 438 |
| 438 // Clicking button again should not increment Clicked count. | 439 // Clicking button again should not increment Clicked count. |
| 439 downloadButton->dispatchSimulatedClick( | 440 downloadButton->dispatchSimulatedClick( |
| 440 Event::createBubble(EventTypeNames::click), SendNoEvents); | 441 Event::createBubble(EventTypeNames::click), SendNoEvents); |
| 441 histogramTester().expectBucketCount("Media.Controls.Download", | 442 histogramTester().expectBucketCount("Media.Controls.Download", |
| 442 DownloadActionMetrics::Clicked, 1); | 443 DownloadActionMetrics::Clicked, 1); |
| 443 } | 444 } |
| 444 | 445 |
| 445 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedInfiniteDuration) { | 446 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedInfiniteDuration) { |
| 446 ensureLayout(); | 447 ensureSizing(); |
| 447 | 448 |
| 448 Element* downloadButton = getElementByShadowPseudoId( | 449 Element* downloadButton = getElementByShadowPseudoId( |
| 449 mediaControls(), "-internal-media-controls-download-button"); | 450 mediaControls(), "-internal-media-controls-download-button"); |
| 450 ASSERT_NE(nullptr, downloadButton); | 451 ASSERT_NE(nullptr, downloadButton); |
| 451 | 452 |
| 452 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 453 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 453 testing::runPendingTasks(); | 454 testing::runPendingTasks(); |
| 454 | 455 |
| 455 // Download button should not be displayed when duration is infinite. | 456 // Download button should not be displayed when duration is infinite. |
| 456 mediaControls().mediaElement().durationChanged( | 457 mediaControls().mediaElement().durationChanged( |
| 457 std::numeric_limits<double>::infinity(), false /* requestSeek */); | 458 std::numeric_limits<double>::infinity(), false /* requestSeek */); |
| 458 simulateLoadedMetadata(); | 459 simulateLoadedMetadata(); |
| 459 EXPECT_FALSE(isElementVisible(*downloadButton)); | 460 EXPECT_FALSE(isElementVisible(*downloadButton)); |
| 460 } | 461 } |
| 461 | 462 |
| 462 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedHLS) { | 463 TEST_F(MediaControlsTest, DownloadButtonNotDisplayedHLS) { |
| 463 ensureLayout(); | 464 ensureSizing(); |
| 464 | 465 |
| 465 Element* downloadButton = getElementByShadowPseudoId( | 466 Element* downloadButton = getElementByShadowPseudoId( |
| 466 mediaControls(), "-internal-media-controls-download-button"); | 467 mediaControls(), "-internal-media-controls-download-button"); |
| 467 ASSERT_NE(nullptr, downloadButton); | 468 ASSERT_NE(nullptr, downloadButton); |
| 468 | 469 |
| 469 // Download button should not be displayed for HLS streams. | 470 // Download button should not be displayed for HLS streams. |
| 470 mediaControls().mediaElement().setSrc("https://example.com/foo.m3u8"); | 471 mediaControls().mediaElement().setSrc("https://example.com/foo.m3u8"); |
| 471 testing::runPendingTasks(); | 472 testing::runPendingTasks(); |
| 472 simulateLoadedMetadata(); | 473 simulateLoadedMetadata(); |
| 473 EXPECT_FALSE(isElementVisible(*downloadButton)); | 474 EXPECT_FALSE(isElementVisible(*downloadButton)); |
| 474 } | 475 } |
| 475 | 476 |
| 476 TEST_F(MediaControlsTest, TimelineSeekToRoundedEnd) { | 477 TEST_F(MediaControlsTest, TimelineSeekToRoundedEnd) { |
| 477 ensureLayout(); | 478 ensureSizing(); |
| 478 | 479 |
| 479 MediaControlTimelineElement* timeline = | 480 MediaControlTimelineElement* timeline = |
| 480 static_cast<MediaControlTimelineElement*>(getElementByShadowPseudoId( | 481 static_cast<MediaControlTimelineElement*>(getElementByShadowPseudoId( |
| 481 mediaControls(), "-webkit-media-controls-timeline")); | 482 mediaControls(), "-webkit-media-controls-timeline")); |
| 482 ASSERT_NE(nullptr, timeline); | 483 ASSERT_NE(nullptr, timeline); |
| 483 | 484 |
| 484 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); | 485 mediaControls().mediaElement().setSrc("https://example.com/foo.mp4"); |
| 485 testing::runPendingTasks(); | 486 testing::runPendingTasks(); |
| 486 | 487 |
| 487 // Tests the case where the real length of the video, |exactDuration|, gets | 488 // Tests the case where the real length of the video, |exactDuration|, gets |
| (...skipping 12 matching lines...) Expand all Loading... |
| 500 // underlying <input type="range">. This would set the |value| to the |max| | 501 // underlying <input type="range">. This would set the |value| to the |max| |
| 501 // attribute, which can be slightly rounded relative to the duration. | 502 // attribute, which can be slightly rounded relative to the duration. |
| 502 timeline->setValueAsNumber(roundedUpDuration, ASSERT_NO_EXCEPTION); | 503 timeline->setValueAsNumber(roundedUpDuration, ASSERT_NO_EXCEPTION); |
| 503 ASSERT_EQ(roundedUpDuration, timeline->valueAsNumber()); | 504 ASSERT_EQ(roundedUpDuration, timeline->valueAsNumber()); |
| 504 EXPECT_EQ(0.0, mediaControls().mediaElement().currentTime()); | 505 EXPECT_EQ(0.0, mediaControls().mediaElement().currentTime()); |
| 505 timeline->dispatchInputEvent(); | 506 timeline->dispatchInputEvent(); |
| 506 EXPECT_EQ(exactDuration, mediaControls().mediaElement().currentTime()); | 507 EXPECT_EQ(exactDuration, mediaControls().mediaElement().currentTime()); |
| 507 } | 508 } |
| 508 | 509 |
| 509 } // namespace blink | 510 } // namespace blink |
| OLD | NEW |