Chromium Code Reviews| Index: third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
| diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
| index 2e0c50d9968e11f12b3f089532a18a3617cc402f..9f6c93b979cc1f03d8af11514eba3e96ece37b93 100644 |
| --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
| +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
| @@ -4,35 +4,54 @@ |
| #include "modules/media_controls/elements/MediaControlCastButtonElement.h" |
| +#include "bindings/core/v8/ScriptState.h" |
| +#include "bindings/core/v8/ToV8.h" |
| #include "core/InputTypeNames.h" |
| #include "core/dom/ClientRect.h" |
| #include "core/events/Event.h" |
| +#include "core/frame/Settings.h" |
| #include "core/html/HTMLMediaElement.h" |
| +#include "core/html/media/HTMLMediaElementControlsList.h" |
| #include "modules/media_controls/MediaControlsImpl.h" |
| #include "modules/media_controls/elements/MediaControlElementsHelper.h" |
| +#include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h" |
| +#include "modules/remoteplayback/RemotePlayback.h" |
| +#include "platform/wtf/Functional.h" |
| #include "public/platform/Platform.h" |
| namespace blink { |
| -namespace { |
| +MediaControlCastButtonElement::RemotePlaybackEventListener:: |
| + RemotePlaybackEventListener(MediaControlCastButtonElement* cast_button) |
| + : EventListener(kCPPEventListenerType), cast_button_(cast_button) {} |
| -Element* ElementFromCenter(Element& element) { |
| - ClientRect* client_rect = element.getBoundingClientRect(); |
| - int center_x = |
| - static_cast<int>((client_rect->left() + client_rect->right()) / 2); |
| - int center_y = |
| - static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); |
| +bool MediaControlCastButtonElement::RemotePlaybackEventListener::operator==( |
| + const EventListener& other) const { |
| + return this == &other; |
| +} |
| - return element.GetDocument().ElementFromPoint(center_x, center_y); |
| +void MediaControlCastButtonElement::RemotePlaybackEventListener::handleEvent( |
| + ExecutionContext* execution_context, |
| + Event* event) { |
| + DCHECK(event->type() == EventTypeNames::connect || |
| + event->type() == EventTypeNames::connecting || |
| + event->type() == EventTypeNames::disconnect); |
| + cast_button_->UpdateDisplayType(); |
| } |
| -} // anonymous namespace |
| +DEFINE_TRACE(MediaControlCastButtonElement::RemotePlaybackEventListener) { |
| + EventListener::Trace(visitor); |
| + visitor->Trace(cast_button_); |
| +} |
| MediaControlCastButtonElement::MediaControlCastButtonElement( |
| MediaControlsImpl& media_controls, |
| bool is_overlay_button) |
| : MediaControlInputElement(media_controls, kMediaCastOnButton), |
| - is_overlay_button_(is_overlay_button) { |
| + is_overlay_button_(is_overlay_button), |
| + remote_playback_(HTMLMediaElementRemotePlayback::remote( |
| + media_controls.MediaElement())), |
| + remote_playback_event_listener_(new RemotePlaybackEventListener(this)) { |
| EnsureUserAgentShadowRoot(); |
| SetShadowPseudoId(is_overlay_button |
| ? "-internal-media-controls-overlay-cast-button" |
| @@ -41,41 +60,19 @@ MediaControlCastButtonElement::MediaControlCastButtonElement( |
| if (is_overlay_button_) |
| RecordMetrics(CastOverlayMetrics::kCreated); |
| - SetIsPlayingRemotely(false); |
| -} |
| - |
| -void MediaControlCastButtonElement::TryShowOverlay() { |
| - DCHECK(is_overlay_button_); |
| - |
| - SetIsWanted(true); |
| - if (ElementFromCenter(*this) != &MediaElement()) { |
| - SetIsWanted(false); |
| - return; |
| - } |
| - |
| - DCHECK(IsWanted()); |
| - if (!show_use_counted_) { |
| - show_use_counted_ = true; |
| - RecordMetrics(CastOverlayMetrics::kShown); |
| - } |
| -} |
| -void MediaControlCastButtonElement::SetIsPlayingRemotely( |
| - bool is_playing_remotely) { |
| - if (is_playing_remotely) { |
| - if (is_overlay_button_) { |
| - SetDisplayType(kMediaOverlayCastOnButton); |
| - } else { |
| - SetDisplayType(kMediaCastOnButton); |
| - } |
| - } else { |
| - if (is_overlay_button_) { |
| - SetDisplayType(kMediaOverlayCastOffButton); |
| - } else { |
| - SetDisplayType(kMediaCastOffButton); |
| - } |
| - } |
| - UpdateOverflowString(); |
| + remote_playback_->addEventListener(EventTypeNames::connect, |
| + remote_playback_event_listener_); |
| + remote_playback_->addEventListener(EventTypeNames::connecting, |
| + remote_playback_event_listener_); |
| + remote_playback_->addEventListener(EventTypeNames::disconnect, |
| + remote_playback_event_listener_); |
| + UpdateDisplayType(); |
| + |
| + // IsWanted() is true by default. For this button it must be false, so that |
| + // remote playback availability callback is set on the first time |
| + // SetIsWanted(true) is called. |
| + SetIsWanted(false); |
| } |
| bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { |
| @@ -84,7 +81,7 @@ bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { |
| WebLocalizedString::Name |
| MediaControlCastButtonElement::GetOverflowStringName() { |
| - if (MediaElement().IsPlayingRemotely()) |
| + if (IsPlayingRemotely()) |
| return WebLocalizedString::kOverflowMenuStopCast; |
| return WebLocalizedString::kOverflowMenuCast; |
| } |
| @@ -98,24 +95,107 @@ void MediaControlCastButtonElement::DefaultEventHandler(Event* event) { |
| if (is_overlay_button_) { |
| Platform::Current()->RecordAction( |
| UserMetricsAction("Media.Controls.CastOverlay")); |
| + |
| + if (!click_use_counted_) { |
| + click_use_counted_ = true; |
| + RecordMetrics(CastOverlayMetrics::kClicked); |
| + } |
| } else { |
| Platform::Current()->RecordAction( |
| UserMetricsAction("Media.Controls.Cast")); |
| } |
| - if (is_overlay_button_ && !click_use_counted_) { |
| - click_use_counted_ = true; |
| - RecordMetrics(CastOverlayMetrics::kClicked); |
| - } |
| - if (MediaElement().IsPlayingRemotely()) { |
| - MediaElement().RequestRemotePlaybackControl(); |
| - } else { |
| - MediaElement().RequestRemotePlayback(); |
| - } |
| + remote_playback_->PromptInternal(); |
| } |
| MediaControlInputElement::DefaultEventHandler(event); |
| } |
| +void MediaControlCastButtonElement::UpdateDisplayType() { |
| + if (IsPlayingRemotely()) { |
| + if (is_overlay_button_) |
| + SetDisplayType(kMediaOverlayCastOnButton); |
| + else |
| + SetDisplayType(kMediaCastOnButton); |
| + } else { |
| + if (is_overlay_button_) |
| + SetDisplayType(kMediaOverlayCastOffButton); |
|
mlamouri (slow - plz ping)
2017/04/19 16:35:36
A bit surprising: why do we have this? Worth filin
whywhat
2017/04/19 22:40:48
WDYM? That MediaCastOff and MediaOverlayCastOff ar
|
| + else |
| + SetDisplayType(kMediaCastOffButton); |
| + } |
| + UpdateOverflowString(); |
| +} |
| + |
| +void MediaControlCastButtonElement::SetIsWanted(bool wanted) { |
| + if (wanted == IsWanted()) |
| + return; |
| + |
| + is_wanted_by_controls_ = wanted; |
| + if (!wanted || !ShouldShow()) { |
| + UpdateVisibility(false); |
| + if (availability_callback_id_ != -1) { |
| + remote_playback_->CancelWatchAvailabilityInternal( |
| + availability_callback_id_); |
| + availability_callback_id_ = -1; |
| + } |
| + return; |
| + } |
| + |
| + if (availability_callback_id_ == -1) { |
| + availability_callback_id_ = remote_playback_->WatchAvailabilityInternal( |
| + new RemotePlayback::AvailabilityCallback(WTF::Bind( |
| + &MediaControlCastButtonElement::OnRemotePlaybackAvailabilityChanged, |
| + WrapPersistent(this)))); |
| + } |
| + UpdateVisibility(remote_playback_->RemotePlaybackAvailable()); |
| +} |
| + |
| +void MediaControlCastButtonElement::UpdateVisibility(bool visible) { |
| + MediaControlElement::SetIsWanted(visible); |
| + if (IsWanted() && is_overlay_button_ && !show_use_counted_) { |
| + show_use_counted_ = true; |
| + RecordMetrics(CastOverlayMetrics::kShown); |
| + } |
| +} |
| + |
| +void MediaControlCastButtonElement::OnRemotePlaybackAvailabilityChanged() { |
| + DCHECK(is_wanted_by_controls_ && ShouldShow()); |
| + UpdateVisibility(remote_playback_->RemotePlaybackAvailable()); |
| +} |
| + |
| +bool MediaControlCastButtonElement::ShouldShow() { |
| + if (MediaElement().FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) |
| + return false; |
| + |
| + // Explicitly do not show cast button when the MediaControlsEnabled setting is |
| + // false to make sure the overlay does not appear. |
| + Document& document = MediaElement().GetDocument(); |
| + if (document.GetSettings() && |
| + !document.GetSettings()->GetMediaControlsEnabled()) { |
| + return false; |
| + } |
| + |
| + // The page disabled the button via the attribute. |
| + if (MediaElement().ControlsListInternal()->ShouldHideRemotePlayback()) { |
| + UseCounter::Count( |
| + document, UseCounter::kHTMLMediaElementControlsListNoRemotePlayback); |
| + return false; |
| + } |
| + |
| + if (is_overlay_button_) { |
| + // TODO(avayvod): Do we still need to hide the button for autoplay/paused |
| + // videos? Check for IsAutoplayingMuted() here instead? |
| + if (MediaElement().Autoplay() && MediaElement().paused()) |
| + return false; |
| + |
| + // Don't show the overlay button if it would cover something on top of the |
| + // media element. |
| + // TODO(avayvod): DO NOT SUBMIT, should show the button to do the hit test? |
| + if (UnderlyingElement() != &MediaElement()) |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { |
| return MediaControlElementsHelper::IsUserInteractionEvent(event); |
| } |
| @@ -128,4 +208,27 @@ void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { |
| overlay_histogram.Count(static_cast<int>(metric)); |
| } |
| +bool MediaControlCastButtonElement::IsPlayingRemotely() const { |
| + return remote_playback_->GetState() != WebRemotePlaybackState::kDisconnected; |
| +} |
| + |
| +Element* MediaControlCastButtonElement::UnderlyingElement() { |
| + DCHECK(is_overlay_button_); |
| + MediaControlElement::SetIsWanted(true); |
| + ClientRect* client_rect = getBoundingClientRect(); |
| + MediaControlElement::SetIsWanted(false); |
| + int center_x = |
| + static_cast<int>((client_rect->left() + client_rect->right()) / 2); |
| + int center_y = |
| + static_cast<int>((client_rect->top() + client_rect->bottom()) / 2); |
| + |
| + return GetDocument().ElementFromPoint(center_x, center_y); |
| +} |
| + |
| +DEFINE_TRACE(MediaControlCastButtonElement) { |
| + MediaControlInputElement::Trace(visitor); |
| + visitor->Trace(remote_playback_); |
| + visitor->Trace(remote_playback_event_listener_); |
| +} |
| + |
| } // namespace blink |