OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/elements/MediaControlCastButtonElement.h" | 5 #include "modules/media_controls/elements/MediaControlCastButtonElement.h" |
6 | 6 |
| 7 #include "bindings/core/v8/ScriptState.h" |
| 8 #include "bindings/core/v8/ToV8.h" |
7 #include "core/InputTypeNames.h" | 9 #include "core/InputTypeNames.h" |
8 #include "core/dom/ClientRect.h" | 10 #include "core/dom/ClientRect.h" |
9 #include "core/events/Event.h" | 11 #include "core/events/Event.h" |
| 12 #include "core/frame/Settings.h" |
10 #include "core/html/HTMLMediaElement.h" | 13 #include "core/html/HTMLMediaElement.h" |
| 14 #include "core/html/media/HTMLMediaElementControlsList.h" |
11 #include "modules/media_controls/MediaControlsImpl.h" | 15 #include "modules/media_controls/MediaControlsImpl.h" |
12 #include "modules/media_controls/elements/MediaControlElementsHelper.h" | 16 #include "modules/media_controls/elements/MediaControlElementsHelper.h" |
| 17 #include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h" |
| 18 #include "modules/remoteplayback/RemotePlayback.h" |
13 #include "platform/Histogram.h" | 19 #include "platform/Histogram.h" |
| 20 #include "platform/wtf/Functional.h" |
14 #include "public/platform/Platform.h" | 21 #include "public/platform/Platform.h" |
15 | 22 |
16 namespace blink { | 23 namespace blink { |
17 | 24 |
18 namespace { | |
19 | |
20 Element* ElementFromCenter(Element& element) { | |
21 ClientRect* client_rect = element.getBoundingClientRect(); | |
22 int center_x = | |
23 static_cast<int>((client_rect->left() + client_rect->right()) / 2); | |
24 int center_y = | |
25 static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); | |
26 | |
27 return element.GetDocument().ElementFromPoint(center_x, center_y); | |
28 } | |
29 | |
30 } // anonymous namespace | |
31 | |
32 MediaControlCastButtonElement::MediaControlCastButtonElement( | 25 MediaControlCastButtonElement::MediaControlCastButtonElement( |
33 MediaControlsImpl& media_controls, | 26 MediaControlsImpl& media_controls, |
34 bool is_overlay_button) | 27 bool is_overlay_button) |
35 : MediaControlInputElement(media_controls, kMediaCastOnButton), | 28 : MediaControlInputElement(media_controls, kMediaCastOnButton), |
36 is_overlay_button_(is_overlay_button) { | 29 is_overlay_button_(is_overlay_button), |
| 30 remote_playback_(HTMLMediaElementRemotePlayback::remote( |
| 31 media_controls.MediaElement())) { |
37 EnsureUserAgentShadowRoot(); | 32 EnsureUserAgentShadowRoot(); |
38 SetShadowPseudoId(is_overlay_button | 33 SetShadowPseudoId(is_overlay_button |
39 ? "-internal-media-controls-overlay-cast-button" | 34 ? "-internal-media-controls-overlay-cast-button" |
40 : "-internal-media-controls-cast-button"); | 35 : "-internal-media-controls-cast-button"); |
41 setType(InputTypeNames::button); | 36 setType(InputTypeNames::button); |
42 | 37 |
43 if (is_overlay_button_) | 38 if (is_overlay_button_) |
44 RecordMetrics(CastOverlayMetrics::kCreated); | 39 RecordMetrics(CastOverlayMetrics::kCreated); |
45 SetIsPlayingRemotely(false); | |
46 } | |
47 | 40 |
48 void MediaControlCastButtonElement::TryShowOverlay() { | 41 UpdateDisplayType(); |
49 DCHECK(is_overlay_button_); | |
50 | |
51 SetIsWanted(true); | |
52 if (ElementFromCenter(*this) != &MediaElement()) { | |
53 SetIsWanted(false); | |
54 return; | |
55 } | |
56 | |
57 DCHECK(IsWanted()); | |
58 if (!show_use_counted_) { | |
59 show_use_counted_ = true; | |
60 RecordMetrics(CastOverlayMetrics::kShown); | |
61 } | |
62 } | |
63 | |
64 void MediaControlCastButtonElement::SetIsPlayingRemotely( | |
65 bool is_playing_remotely) { | |
66 if (is_playing_remotely) { | |
67 if (is_overlay_button_) { | |
68 SetDisplayType(kMediaOverlayCastOnButton); | |
69 } else { | |
70 SetDisplayType(kMediaCastOnButton); | |
71 } | |
72 } else { | |
73 if (is_overlay_button_) { | |
74 SetDisplayType(kMediaOverlayCastOffButton); | |
75 } else { | |
76 SetDisplayType(kMediaCastOffButton); | |
77 } | |
78 } | |
79 UpdateOverflowString(); | |
80 } | 42 } |
81 | 43 |
82 bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { | 44 bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { |
83 return true; | 45 return true; |
84 } | 46 } |
85 | 47 |
86 WebLocalizedString::Name | 48 WebLocalizedString::Name |
87 MediaControlCastButtonElement::GetOverflowStringName() { | 49 MediaControlCastButtonElement::GetOverflowStringName() { |
88 if (MediaElement().IsPlayingRemotely()) | 50 if (IsPlayingRemotely()) |
89 return WebLocalizedString::kOverflowMenuStopCast; | 51 return WebLocalizedString::kOverflowMenuStopCast; |
90 return WebLocalizedString::kOverflowMenuCast; | 52 return WebLocalizedString::kOverflowMenuCast; |
91 } | 53 } |
92 | 54 |
93 bool MediaControlCastButtonElement::HasOverflowButton() { | 55 bool MediaControlCastButtonElement::HasOverflowButton() { |
94 return true; | 56 return true; |
95 } | 57 } |
96 | 58 |
97 void MediaControlCastButtonElement::DefaultEventHandler(Event* event) { | 59 void MediaControlCastButtonElement::DefaultEventHandler(Event* event) { |
98 if (event->type() == EventTypeNames::click) { | 60 if (event->type() == EventTypeNames::click) { |
99 if (is_overlay_button_) { | 61 if (is_overlay_button_) { |
100 Platform::Current()->RecordAction( | 62 Platform::Current()->RecordAction( |
101 UserMetricsAction("Media.Controls.CastOverlay")); | 63 UserMetricsAction("Media.Controls.CastOverlay")); |
| 64 |
| 65 if (!click_use_counted_) { |
| 66 click_use_counted_ = true; |
| 67 RecordMetrics(CastOverlayMetrics::kClicked); |
| 68 } |
102 } else { | 69 } else { |
103 Platform::Current()->RecordAction( | 70 Platform::Current()->RecordAction( |
104 UserMetricsAction("Media.Controls.Cast")); | 71 UserMetricsAction("Media.Controls.Cast")); |
105 } | 72 } |
106 | 73 |
107 if (is_overlay_button_ && !click_use_counted_) { | 74 remote_playback_->PromptInternal(); |
108 click_use_counted_ = true; | |
109 RecordMetrics(CastOverlayMetrics::kClicked); | |
110 } | |
111 if (MediaElement().IsPlayingRemotely()) { | |
112 MediaElement().RequestRemotePlaybackControl(); | |
113 } else { | |
114 MediaElement().RequestRemotePlayback(); | |
115 } | |
116 } | 75 } |
117 MediaControlInputElement::DefaultEventHandler(event); | 76 MediaControlInputElement::DefaultEventHandler(event); |
118 } | 77 } |
119 | 78 |
| 79 void MediaControlCastButtonElement::UpdateDisplayType() { |
| 80 if (IsPlayingRemotely()) { |
| 81 if (is_overlay_button_) |
| 82 SetDisplayType(kMediaOverlayCastOnButton); |
| 83 else |
| 84 SetDisplayType(kMediaCastOnButton); |
| 85 } else { |
| 86 if (is_overlay_button_) |
| 87 SetDisplayType(kMediaOverlayCastOffButton); |
| 88 else |
| 89 SetDisplayType(kMediaCastOffButton); |
| 90 } |
| 91 UpdateOverflowString(); |
| 92 } |
| 93 |
| 94 void MediaControlCastButtonElement::SetIsWanted(bool wanted) { |
| 95 if (wanted == IsWanted()) |
| 96 return; |
| 97 |
| 98 MediaControlElement::SetIsWanted(wanted); |
| 99 if (IsWanted() && is_overlay_button_ && !show_use_counted_) { |
| 100 show_use_counted_ = true; |
| 101 RecordMetrics(CastOverlayMetrics::kShown); |
| 102 } |
| 103 } |
| 104 |
| 105 bool MediaControlCastButtonElement::ShouldShow() { |
| 106 if (MediaElement().FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) |
| 107 return false; |
| 108 |
| 109 // Explicitly do not show cast button when the MediaControlsEnabled setting is |
| 110 // false to make sure the overlay does not appear. |
| 111 Document& document = MediaElement().GetDocument(); |
| 112 if (document.GetSettings() && |
| 113 !document.GetSettings()->GetMediaControlsEnabled()) { |
| 114 return false; |
| 115 } |
| 116 |
| 117 // The page disabled the button via the attribute. |
| 118 if (MediaElement().ControlsListInternal()->ShouldHideRemotePlayback()) { |
| 119 UseCounter::Count( |
| 120 document, UseCounter::kHTMLMediaElementControlsListNoRemotePlayback); |
| 121 return false; |
| 122 } |
| 123 |
| 124 if (is_overlay_button_) { |
| 125 // TODO(avayvod): Do we still need to hide the button for autoplay/paused |
| 126 // videos? Check for IsAutoplayingMuted() here instead? |
| 127 if (MediaElement().Autoplay() && MediaElement().paused()) |
| 128 return false; |
| 129 |
| 130 // Don't show the overlay button if it would cover something on top of the |
| 131 // media element. |
| 132 if (UnderlyingElement() != &MediaElement()) |
| 133 return false; |
| 134 } |
| 135 |
| 136 return remote_playback_->RemotePlaybackAvailable(); |
| 137 } |
| 138 |
120 bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { | 139 bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { |
121 return MediaControlElementsHelper::IsUserInteractionEvent(event); | 140 return MediaControlElementsHelper::IsUserInteractionEvent(event); |
122 } | 141 } |
123 | 142 |
124 void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { | 143 void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { |
125 DCHECK(is_overlay_button_); | 144 DCHECK(is_overlay_button_); |
126 DEFINE_STATIC_LOCAL( | 145 DEFINE_STATIC_LOCAL( |
127 EnumerationHistogram, overlay_histogram, | 146 EnumerationHistogram, overlay_histogram, |
128 ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount))); | 147 ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::kCount))); |
129 overlay_histogram.Count(static_cast<int>(metric)); | 148 overlay_histogram.Count(static_cast<int>(metric)); |
130 } | 149 } |
131 | 150 |
| 151 bool MediaControlCastButtonElement::IsPlayingRemotely() const { |
| 152 return remote_playback_->GetState() != WebRemotePlaybackState::kDisconnected; |
| 153 } |
| 154 |
| 155 Element* MediaControlCastButtonElement::UnderlyingElement() { |
| 156 DCHECK(is_overlay_button_); |
| 157 MediaControlElement::SetIsWanted(true); |
| 158 ClientRect* client_rect = getBoundingClientRect(); |
| 159 MediaControlElement::SetIsWanted(false); |
| 160 int center_x = |
| 161 static_cast<int>((client_rect->left() + client_rect->right()) / 2); |
| 162 int center_y = |
| 163 static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); |
| 164 |
| 165 return GetDocument().ElementFromPoint(center_x, center_y); |
| 166 } |
| 167 |
| 168 DEFINE_TRACE(MediaControlCastButtonElement) { |
| 169 MediaControlInputElement::Trace(visitor); |
| 170 visitor->Trace(remote_playback_); |
| 171 } |
| 172 |
132 } // namespace blink | 173 } // namespace blink |
OLD | NEW |