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 | 9 |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
11 #include "core/HTMLNames.h" | 11 #include "core/HTMLNames.h" |
12 #include "core/css/StylePropertySet.h" | 12 #include "core/css/StylePropertySet.h" |
13 #include "core/dom/Document.h" | 13 #include "core/dom/Document.h" |
14 #include "core/dom/ElementTraversal.h" | 14 #include "core/dom/ElementTraversal.h" |
15 #include "core/dom/StyleEngine.h" | 15 #include "core/dom/StyleEngine.h" |
16 #include "core/events/Event.h" | 16 #include "core/events/Event.h" |
17 #include "core/frame/Settings.h" | 17 #include "core/frame/Settings.h" |
18 #include "core/geometry/DOMRect.h" | 18 #include "core/geometry/DOMRect.h" |
19 #include "core/html/HTMLElement.h" | 19 #include "core/html/HTMLElement.h" |
20 #include "core/html/HTMLVideoElement.h" | 20 #include "core/html/HTMLVideoElement.h" |
21 #include "core/input/EventHandler.h" | 21 #include "core/input/EventHandler.h" |
22 #include "core/layout/LayoutObject.h" | 22 #include "core/layout/LayoutObject.h" |
23 #include "core/loader/EmptyClients.h" | 23 #include "core/loader/EmptyClients.h" |
24 #include "core/testing/DummyPageHolder.h" | 24 #include "core/testing/DummyPageHolder.h" |
| 25 #include "modules/media_controls/MediaDownloadInProductHelpManager.h" |
25 #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.
h" | 26 #include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.
h" |
26 #include "modules/media_controls/elements/MediaControlDownloadButtonElement.h" | 27 #include "modules/media_controls/elements/MediaControlDownloadButtonElement.h" |
27 #include "modules/media_controls/elements/MediaControlTimelineElement.h" | 28 #include "modules/media_controls/elements/MediaControlTimelineElement.h" |
28 #include "modules/media_controls/elements/MediaControlVolumeSliderElement.h" | 29 #include "modules/media_controls/elements/MediaControlVolumeSliderElement.h" |
29 #include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h" | 30 #include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h" |
30 #include "modules/remoteplayback/RemotePlayback.h" | 31 #include "modules/remoteplayback/RemotePlayback.h" |
31 #include "platform/RuntimeEnabledFeatures.h" | 32 #include "platform/RuntimeEnabledFeatures.h" |
32 #include "platform/heap/Handle.h" | 33 #include "platform/heap/Handle.h" |
33 #include "platform/testing/EmptyWebMediaPlayer.h" | 34 #include "platform/testing/EmptyWebMediaPlayer.h" |
34 #include "platform/testing/HistogramTester.h" | 35 #include "platform/testing/HistogramTester.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 WebTimeRanges Seekable() const override { return seekable_; } | 70 WebTimeRanges Seekable() const override { return seekable_; } |
70 bool HasVideo() const override { return true; } | 71 bool HasVideo() const override { return true; } |
71 | 72 |
72 WebTimeRanges seekable_; | 73 WebTimeRanges seekable_; |
73 }; | 74 }; |
74 | 75 |
75 class MockLayoutObject : public LayoutObject { | 76 class MockLayoutObject : public LayoutObject { |
76 public: | 77 public: |
77 MockLayoutObject(Node* node) : LayoutObject(node) {} | 78 MockLayoutObject(Node* node) : LayoutObject(node) {} |
78 | 79 |
| 80 void SetVisible(bool visible) { visible_ = visible; } |
| 81 |
79 const char* GetName() const override { return "MockLayoutObject"; } | 82 const char* GetName() const override { return "MockLayoutObject"; } |
80 void UpdateLayout() override {} | 83 void UpdateLayout() override {} |
81 FloatRect LocalBoundingBoxRectForAccessibility() const override { | 84 FloatRect LocalBoundingBoxRectForAccessibility() const override { |
82 return FloatRect(); | 85 return FloatRect(); |
83 } | 86 } |
| 87 void AbsoluteQuads(Vector<FloatQuad>& quads, |
| 88 MapCoordinatesFlags mode) const override { |
| 89 if (!visible_) |
| 90 return; |
| 91 quads.push_back(FloatQuad(FloatRect(0.f, 0.f, 10.f, 10.f))); |
| 92 } |
| 93 |
| 94 private: |
| 95 bool visible_ = false; |
84 }; | 96 }; |
85 | 97 |
86 class StubLocalFrameClientForImpl : public EmptyLocalFrameClient { | 98 class StubLocalFrameClientForImpl : public EmptyLocalFrameClient { |
87 public: | 99 public: |
88 static StubLocalFrameClientForImpl* Create() { | 100 static StubLocalFrameClientForImpl* Create() { |
89 return new StubLocalFrameClientForImpl; | 101 return new StubLocalFrameClientForImpl; |
90 } | 102 } |
91 | 103 |
92 std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer( | 104 std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer( |
93 HTMLMediaElement&, | 105 HTMLMediaElement&, |
(...skipping 10 matching lines...) Expand all Loading... |
104 | 116 |
105 Element* GetElementByShadowPseudoId(Node& root_node, | 117 Element* GetElementByShadowPseudoId(Node& root_node, |
106 const char* shadow_pseudo_id) { | 118 const char* shadow_pseudo_id) { |
107 for (Element& element : ElementTraversal::DescendantsOf(root_node)) { | 119 for (Element& element : ElementTraversal::DescendantsOf(root_node)) { |
108 if (element.ShadowPseudoId() == shadow_pseudo_id) | 120 if (element.ShadowPseudoId() == shadow_pseudo_id) |
109 return &element; | 121 return &element; |
110 } | 122 } |
111 return nullptr; | 123 return nullptr; |
112 } | 124 } |
113 | 125 |
| 126 MediaControlDownloadButtonElement& GetDownloadButton( |
| 127 MediaControlsImpl& controls) { |
| 128 Element* element = GetElementByShadowPseudoId( |
| 129 controls, "-internal-media-controls-download-button"); |
| 130 return static_cast<MediaControlDownloadButtonElement&>(*element); |
| 131 } |
| 132 |
114 bool IsElementVisible(Element& element) { | 133 bool IsElementVisible(Element& element) { |
115 const StylePropertySet* inline_style = element.InlineStyle(); | 134 const StylePropertySet* inline_style = element.InlineStyle(); |
116 | 135 |
117 if (!inline_style) | 136 if (!inline_style) |
118 return true; | 137 return true; |
119 | 138 |
120 if (inline_style->GetPropertyValue(CSSPropertyDisplay) == "none") | 139 if (inline_style->GetPropertyValue(CSSPropertyDisplay) == "none") |
121 return false; | 140 return false; |
122 | 141 |
123 if (inline_style->HasProperty(CSSPropertyOpacity) && | 142 if (inline_style->HasProperty(CSSPropertyOpacity) && |
(...skipping 27 matching lines...) Expand all Loading... |
151 | 170 |
152 InitializePage(); | 171 InitializePage(); |
153 } | 172 } |
154 | 173 |
155 void InitializePage() { | 174 void InitializePage() { |
156 Page::PageClients clients; | 175 Page::PageClients clients; |
157 FillWithEmptyClients(clients); | 176 FillWithEmptyClients(clients); |
158 clients.chrome_client = new MockChromeClientForImpl(); | 177 clients.chrome_client = new MockChromeClientForImpl(); |
159 page_holder_ = DummyPageHolder::Create( | 178 page_holder_ = DummyPageHolder::Create( |
160 IntSize(800, 600), &clients, StubLocalFrameClientForImpl::Create()); | 179 IntSize(800, 600), &clients, StubLocalFrameClientForImpl::Create()); |
| 180 GetDocument().GetSettings()->SetMediaDownloadInProductHelpEnabled( |
| 181 EnableDownloadInProductHelp()); |
161 | 182 |
162 GetDocument().write("<video>"); | 183 GetDocument().write("<video>"); |
163 HTMLVideoElement& video = | 184 HTMLVideoElement& video = |
164 toHTMLVideoElement(*GetDocument().QuerySelector("video")); | 185 toHTMLVideoElement(*GetDocument().QuerySelector("video")); |
165 media_controls_ = static_cast<MediaControlsImpl*>(video.GetMediaControls()); | 186 media_controls_ = static_cast<MediaControlsImpl*>(video.GetMediaControls()); |
166 | 187 |
167 // If scripts are not enabled, controls will always be shown. | 188 // If scripts are not enabled, controls will always be shown. |
168 page_holder_->GetFrame().GetSettings()->SetScriptEnabled(true); | 189 page_holder_->GetFrame().GetSettings()->SetScriptEnabled(true); |
169 } | 190 } |
170 | 191 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 241 } |
221 | 242 |
222 void MouseDownAt(WebFloatPoint pos); | 243 void MouseDownAt(WebFloatPoint pos); |
223 void MouseMoveTo(WebFloatPoint pos); | 244 void MouseMoveTo(WebFloatPoint pos); |
224 void MouseUpAt(WebFloatPoint pos); | 245 void MouseUpAt(WebFloatPoint pos); |
225 | 246 |
226 bool HasAvailabilityCallbacks(RemotePlayback* remote_playback) { | 247 bool HasAvailabilityCallbacks(RemotePlayback* remote_playback) { |
227 return !remote_playback->availability_callbacks_.IsEmpty(); | 248 return !remote_playback->availability_callbacks_.IsEmpty(); |
228 } | 249 } |
229 | 250 |
| 251 virtual bool EnableDownloadInProductHelp() { return false; } |
| 252 |
230 private: | 253 private: |
231 std::unique_ptr<DummyPageHolder> page_holder_; | 254 std::unique_ptr<DummyPageHolder> page_holder_; |
232 Persistent<MediaControlsImpl> media_controls_; | 255 Persistent<MediaControlsImpl> media_controls_; |
233 HistogramTester histogram_tester_; | 256 HistogramTester histogram_tester_; |
234 }; | 257 }; |
235 | 258 |
236 void MediaControlsImplTest::MouseDownAt(WebFloatPoint pos) { | 259 void MediaControlsImplTest::MouseDownAt(WebFloatPoint pos) { |
237 WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown, | 260 WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown, |
238 pos /* client pos */, pos /* screen pos */, | 261 pos /* client pos */, pos /* screen pos */, |
239 WebPointerProperties::Button::kLeft, 1, | 262 WebPointerProperties::Button::kLeft, 1, |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 MediaControls(), "-internal-media-controls-download-button"); | 529 MediaControls(), "-internal-media-controls-download-button"); |
507 ASSERT_NE(nullptr, download_button); | 530 ASSERT_NE(nullptr, download_button); |
508 | 531 |
509 // Download button should not be displayed for HLS streams. | 532 // Download button should not be displayed for HLS streams. |
510 MediaControls().MediaElement().SetSrc("https://example.com/foo.m3u8"); | 533 MediaControls().MediaElement().SetSrc("https://example.com/foo.m3u8"); |
511 testing::RunPendingTasks(); | 534 testing::RunPendingTasks(); |
512 SimulateLoadedMetadata(); | 535 SimulateLoadedMetadata(); |
513 EXPECT_FALSE(IsElementVisible(*download_button)); | 536 EXPECT_FALSE(IsElementVisible(*download_button)); |
514 } | 537 } |
515 | 538 |
| 539 TEST_F(MediaControlsImplTest, DownloadButtonInProductHelpDisabled) { |
| 540 EXPECT_FALSE(MediaControls().DownloadInProductHelp()); |
| 541 } |
| 542 |
| 543 class MediaControlsImplInProductHelpTest : public MediaControlsImplTest { |
| 544 public: |
| 545 void SetUp() override { |
| 546 MediaControlsImplTest::SetUp(); |
| 547 ASSERT_TRUE(MediaControls().DownloadInProductHelp()); |
| 548 } |
| 549 |
| 550 MediaDownloadInProductHelpManager& Manager() { |
| 551 return *MediaControls().DownloadInProductHelp(); |
| 552 } |
| 553 |
| 554 void Play() { MediaControls().OnPlay(); } |
| 555 |
| 556 bool EnableDownloadInProductHelp() override { return true; } |
| 557 }; |
| 558 |
| 559 TEST_F(MediaControlsImplInProductHelpTest, DownloadButtonInProductHelp_Button) { |
| 560 EnsureSizing(); |
| 561 |
| 562 // Inject the LayoutObject for the button to override the rect returned in |
| 563 // visual viewport. |
| 564 MediaControlDownloadButtonElement& button = |
| 565 GetDownloadButton(MediaControls()); |
| 566 MockLayoutObject layout_object(&button); |
| 567 layout_object.SetVisible(true); |
| 568 button.SetLayoutObject(&layout_object); |
| 569 |
| 570 MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4"); |
| 571 testing::RunPendingTasks(); |
| 572 SimulateLoadedMetadata(); |
| 573 Play(); |
| 574 |
| 575 // Load above should have made the button wanted, which should trigger showing |
| 576 // in-product help. |
| 577 EXPECT_TRUE(Manager().IsShowingInProductHelp()); |
| 578 |
| 579 // Disable the download button, which dismisses the in-product-help. |
| 580 button.SetIsWanted(false); |
| 581 EXPECT_FALSE(Manager().IsShowingInProductHelp()); |
| 582 |
| 583 // Toggle again. In-product help is shown only once. |
| 584 button.SetIsWanted(true); |
| 585 EXPECT_FALSE(Manager().IsShowingInProductHelp()); |
| 586 |
| 587 button.SetLayoutObject(nullptr); |
| 588 } |
| 589 |
| 590 TEST_F(MediaControlsImplInProductHelpTest, |
| 591 DownloadButtonInProductHelp_ControlsVisibility) { |
| 592 EnsureSizing(); |
| 593 |
| 594 // Inject the LayoutObject for the button to override the rect returned in |
| 595 // visual viewport. |
| 596 MediaControlDownloadButtonElement& button = |
| 597 GetDownloadButton(MediaControls()); |
| 598 MockLayoutObject layout_object(&button); |
| 599 layout_object.SetVisible(true); |
| 600 button.SetLayoutObject(&layout_object); |
| 601 |
| 602 // The in-product-help should not be shown while the controls are hidden. |
| 603 MediaControls().Hide(); |
| 604 MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4"); |
| 605 testing::RunPendingTasks(); |
| 606 SimulateLoadedMetadata(); |
| 607 Play(); |
| 608 |
| 609 ASSERT_TRUE(button.IsWanted()); |
| 610 EXPECT_FALSE(Manager().IsShowingInProductHelp()); |
| 611 |
| 612 // Showing the controls initiates showing in-product-help. |
| 613 MediaControls().MaybeShow(); |
| 614 EXPECT_TRUE(Manager().IsShowingInProductHelp()); |
| 615 |
| 616 // Hiding the controls dismissed in-product-help. |
| 617 MediaControls().Hide(); |
| 618 EXPECT_FALSE(Manager().IsShowingInProductHelp()); |
| 619 |
| 620 button.SetLayoutObject(nullptr); |
| 621 } |
| 622 |
| 623 TEST_F(MediaControlsImplInProductHelpTest, |
| 624 DownloadButtonInProductHelp_ButtonVisibility) { |
| 625 EnsureSizing(); |
| 626 |
| 627 // Inject the LayoutObject for the button to override the rect returned in |
| 628 // visual viewport. |
| 629 MediaControlDownloadButtonElement& button = |
| 630 GetDownloadButton(MediaControls()); |
| 631 MockLayoutObject layout_object(&button); |
| 632 button.SetLayoutObject(&layout_object); |
| 633 |
| 634 // The in-product-help should not be shown while the button is hidden. |
| 635 layout_object.SetVisible(false); |
| 636 MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4"); |
| 637 testing::RunPendingTasks(); |
| 638 SimulateLoadedMetadata(); |
| 639 Play(); |
| 640 |
| 641 ASSERT_TRUE(button.IsWanted()); |
| 642 EXPECT_FALSE(Manager().IsShowingInProductHelp()); |
| 643 |
| 644 // Make the button visible to show in-product-help. |
| 645 layout_object.SetVisible(true); |
| 646 button.SetIsWanted(false); |
| 647 button.SetIsWanted(true); |
| 648 EXPECT_TRUE(Manager().IsShowingInProductHelp()); |
| 649 |
| 650 button.SetLayoutObject(nullptr); |
| 651 } |
| 652 |
516 TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) { | 653 TEST_F(MediaControlsImplTest, TimelineSeekToRoundedEnd) { |
517 EnsureSizing(); | 654 EnsureSizing(); |
518 | 655 |
519 // Tests the case where the real length of the video, |exact_duration|, gets | 656 // Tests the case where the real length of the video, |exact_duration|, gets |
520 // rounded up slightly to |rounded_up_duration| when setting the timeline's | 657 // rounded up slightly to |rounded_up_duration| when setting the timeline's |
521 // |max| attribute (crbug.com/695065). | 658 // |max| attribute (crbug.com/695065). |
522 double exact_duration = 596.586667; | 659 double exact_duration = 596.586667; |
523 double rounded_up_duration = 596.587; | 660 double rounded_up_duration = 596.587; |
524 LoadMediaWithDuration(exact_duration); | 661 LoadMediaWithDuration(exact_duration); |
525 | 662 |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 { | 989 { |
853 Persistent<HTMLMediaElement> video_holder = element; | 990 Persistent<HTMLMediaElement> video_holder = element; |
854 page_holder->GetDocument().body()->RemoveChild(element); | 991 page_holder->GetDocument().body()->RemoveChild(element); |
855 page_holder->GetDocument().body()->AppendChild(video_holder.Get()); | 992 page_holder->GetDocument().body()->AppendChild(video_holder.Get()); |
856 EXPECT_TRUE(remote_playback->HasEventListeners()); | 993 EXPECT_TRUE(remote_playback->HasEventListeners()); |
857 EXPECT_TRUE(HasAvailabilityCallbacks(remote_playback)); | 994 EXPECT_TRUE(HasAvailabilityCallbacks(remote_playback)); |
858 } | 995 } |
859 } | 996 } |
860 | 997 |
861 } // namespace blink | 998 } // namespace blink |
OLD | NEW |