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..30cb25f3e454338521729505c0ea19c0fca2fc31 100644 |
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlCastButtonElement.cpp |
@@ -4,12 +4,19 @@ |
#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 { |
@@ -28,11 +35,37 @@ Element* ElementFromCenter(Element& element) { |
} // anonymous namespace |
+MediaControlCastButtonElement::RemotePlaybackEventListener:: |
+ RemotePlaybackEventListener(MediaControlCastButtonElement* cast_button) |
+ : EventListener(kCPPEventListenerType), cast_button_(cast_button) {} |
+ |
+bool MediaControlCastButtonElement::RemotePlaybackEventListener::operator==( |
+ const EventListener& other) const { |
+ return this == &other; |
+} |
+ |
+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(); |
+} |
+ |
+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 +74,14 @@ 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(); |
mlamouri (slow - plz ping)
2017/04/18 13:02:40
I think you should stop listening to those when th
whywhat
2017/04/19 02:27:56
Okay. Seems like availability callbacks should be
whywhat
2017/04/24 14:16:38
RE: tests - I'd have to add them in RemotePlayback
|
} |
bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { |
@@ -84,7 +90,7 @@ bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() { |
WebLocalizedString::Name |
MediaControlCastButtonElement::GetOverflowStringName() { |
- if (MediaElement().IsPlayingRemotely()) |
+ if (IsPlayingRemotely()) |
return WebLocalizedString::kOverflowMenuStopCast; |
return WebLocalizedString::kOverflowMenuCast; |
} |
@@ -98,24 +104,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); |
+ else |
+ SetDisplayType(kMediaCastOffButton); |
+ } |
+ UpdateOverflowString(); |
+} |
+ |
+void MediaControlCastButtonElement::SetIsWanted(bool wanted) { |
+ if (wanted == is_wanted_by_controls_) |
+ return; |
+ |
+ is_wanted_by_controls_ = wanted; |
+ UpdateVisibility(); |
+} |
+ |
+void MediaControlCastButtonElement::UpdateVisibility() { |
+ if (!ShouldShow()) { |
+ DCHECK_NE(-1, availability_callback_id_); |
+ remote_playback_->CancelWatchAvailabilityInternal( |
+ availability_callback_id_); |
+ MediaControlElement::SetIsWanted(false); |
+ return; |
+ } |
+ |
+ // TODO(avayvod): DO NOT SUBMIT, set watch availability callback. |
+ availability_callback_id_ = remote_playback_->WatchAvailabilityInternal( |
+ WTF::Bind(&MediaControlCastButtonElement::UpdateVisibility, |
+ WrapPersistent(this))); |
+ MediaControlElement::SetIsWanted(remote_playback_->RemotePlaybackAvailable()); |
+ if (IsWanted() && is_overlay_button_ && !show_use_counted_) { |
+ show_use_counted_ = true; |
+ RecordMetrics(CastOverlayMetrics::kShown); |
+ } |
+} |
+ |
+bool MediaControlCastButtonElement::ShouldShow() { |
+ if (!is_wanted_by_controls_) |
+ return false; |
+ |
+ 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_) { |
+ // The reason for the autoplay test is that some pages (e.g. vimeo.com) have |
+ // an autoplay background video, which doesn't autoplay on Chrome for |
+ // Android (we prevent it) so starts paused. In such cases we don't want to |
+ // automatically show the cast button, since it looks strange and is |
+ // unlikely to correspond with anything the user wants to do. If a user |
+ // does want to cast a paused autoplay video then they can still do so by |
+ // touching or clicking on the video, which will cause the cast button to |
+ // appear. |
+ 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 (ElementFromCenter(*this) != &MediaElement()) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
bool MediaControlCastButtonElement::KeepEventInNode(Event* event) { |
return MediaControlElementsHelper::IsUserInteractionEvent(event); |
} |
@@ -128,4 +217,16 @@ void MediaControlCastButtonElement::RecordMetrics(CastOverlayMetrics metric) { |
overlay_histogram.Count(static_cast<int>(metric)); |
} |
+bool MediaControlCastButtonElement::IsPlayingRemotely() const { |
+ // TODO(avayvod): DO NOT SUBMIT, find a way to use a named constant shared |
+ // with RemotePlayback.h. |
+ return remote_playback_->state() != "disconnected"; |
mlamouri (slow - plz ping)
2017/04/18 13:02:40
Can't use add `constexpr` to the header? Or even h
whywhat
2017/04/19 02:27:57
With GetState() I don't really need ...ForBindings
mlamouri (slow - plz ping)
2017/04/19 16:35:36
I was suggesting to have stateForBindings() instea
|
+} |
+ |
+DEFINE_TRACE(MediaControlCastButtonElement) { |
+ MediaControlInputElement::Trace(visitor); |
+ visitor->Trace(remote_playback_); |
+ visitor->Trace(remote_playback_event_listener_); |
+} |
+ |
} // namespace blink |