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