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 |