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 |