OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. |
3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 11 matching lines...) Expand all Loading... |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "modules/media_controls/MediaControlsImpl.h" | 27 #include "modules/media_controls/MediaControlsImpl.h" |
28 | 28 |
29 #include "bindings/core/v8/ExceptionState.h" | 29 #include "bindings/core/v8/ExceptionState.h" |
30 #include "core/dom/ClientRect.h" | 30 #include "core/dom/ClientRect.h" |
31 #include "core/dom/Fullscreen.h" | 31 #include "core/dom/Fullscreen.h" |
| 32 #include "core/dom/MutationCallback.h" |
| 33 #include "core/dom/MutationObserver.h" |
| 34 #include "core/dom/MutationObserverInit.h" |
| 35 #include "core/dom/MutationRecord.h" |
32 #include "core/dom/ResizeObserver.h" | 36 #include "core/dom/ResizeObserver.h" |
33 #include "core/dom/ResizeObserverCallback.h" | 37 #include "core/dom/ResizeObserverCallback.h" |
34 #include "core/dom/ResizeObserverEntry.h" | 38 #include "core/dom/ResizeObserverEntry.h" |
35 #include "core/dom/TaskRunnerHelper.h" | 39 #include "core/dom/TaskRunnerHelper.h" |
36 #include "core/events/MouseEvent.h" | 40 #include "core/events/MouseEvent.h" |
37 #include "core/frame/Settings.h" | 41 #include "core/frame/Settings.h" |
38 #include "core/frame/UseCounter.h" | 42 #include "core/frame/UseCounter.h" |
39 #include "core/html/HTMLMediaElement.h" | 43 #include "core/html/HTMLMediaElement.h" |
40 #include "core/html/HTMLVideoElement.h" | 44 #include "core/html/HTMLVideoElement.h" |
41 #include "core/html/media/HTMLMediaElementControlsList.h" | 45 #include "core/html/media/HTMLMediaElementControlsList.h" |
(...skipping 14 matching lines...) Expand all Loading... |
56 #include "modules/media_controls/elements/MediaControlOverlayEnclosureElement.h" | 60 #include "modules/media_controls/elements/MediaControlOverlayEnclosureElement.h" |
57 #include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
" | 61 #include "modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
" |
58 #include "modules/media_controls/elements/MediaControlPanelElement.h" | 62 #include "modules/media_controls/elements/MediaControlPanelElement.h" |
59 #include "modules/media_controls/elements/MediaControlPanelEnclosureElement.h" | 63 #include "modules/media_controls/elements/MediaControlPanelEnclosureElement.h" |
60 #include "modules/media_controls/elements/MediaControlPlayButtonElement.h" | 64 #include "modules/media_controls/elements/MediaControlPlayButtonElement.h" |
61 #include "modules/media_controls/elements/MediaControlRemainingTimeDisplayElemen
t.h" | 65 #include "modules/media_controls/elements/MediaControlRemainingTimeDisplayElemen
t.h" |
62 #include "modules/media_controls/elements/MediaControlTextTrackListElement.h" | 66 #include "modules/media_controls/elements/MediaControlTextTrackListElement.h" |
63 #include "modules/media_controls/elements/MediaControlTimelineElement.h" | 67 #include "modules/media_controls/elements/MediaControlTimelineElement.h" |
64 #include "modules/media_controls/elements/MediaControlToggleClosedCaptionsButton
Element.h" | 68 #include "modules/media_controls/elements/MediaControlToggleClosedCaptionsButton
Element.h" |
65 #include "modules/media_controls/elements/MediaControlVolumeSliderElement.h" | 69 #include "modules/media_controls/elements/MediaControlVolumeSliderElement.h" |
| 70 #include "modules/remoteplayback/HTMLMediaElementRemotePlayback.h" |
| 71 #include "modules/remoteplayback/RemotePlayback.h" |
66 #include "platform/EventDispatchForbiddenScope.h" | 72 #include "platform/EventDispatchForbiddenScope.h" |
67 | 73 |
68 namespace blink { | 74 namespace blink { |
69 | 75 |
70 namespace { | 76 namespace { |
71 | 77 |
72 // TODO(steimel): should have better solution than hard-coding pixel values. | 78 // TODO(steimel): should have better solution than hard-coding pixel values. |
73 // Defined in core/css/mediaControls.css, core/css/mediaControlsAndroid.css, | 79 // Defined in core/css/mediaControls.css, core/css/mediaControlsAndroid.css, |
74 // and core/paint/MediaControlsPainter.cpp. | 80 // and core/paint/MediaControlsPainter.cpp. |
75 constexpr int kOverlayPlayButtonWidth = 48; | 81 constexpr int kOverlayPlayButtonWidth = 48; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 return false; | 131 return false; |
126 | 132 |
127 // The page disabled the button via the attribute. | 133 // The page disabled the button via the attribute. |
128 if (media_element.ControlsListInternal()->ShouldHideRemotePlayback()) { | 134 if (media_element.ControlsListInternal()->ShouldHideRemotePlayback()) { |
129 UseCounter::Count( | 135 UseCounter::Count( |
130 media_element.GetDocument(), | 136 media_element.GetDocument(), |
131 UseCounter::kHTMLMediaElementControlsListNoRemotePlayback); | 137 UseCounter::kHTMLMediaElementControlsListNoRemotePlayback); |
132 return false; | 138 return false; |
133 } | 139 } |
134 | 140 |
135 return media_element.HasRemoteRoutes(); | 141 RemotePlayback* remote = |
| 142 HTMLMediaElementRemotePlayback::remote(media_element); |
| 143 return remote && remote->RemotePlaybackAvailable(); |
136 } | 144 } |
137 | 145 |
138 bool PreferHiddenVolumeControls(const Document& document) { | 146 bool PreferHiddenVolumeControls(const Document& document) { |
139 return !document.GetSettings() || | 147 return !document.GetSettings() || |
140 document.GetSettings()->GetPreferHiddenVolumeControls(); | 148 document.GetSettings()->GetPreferHiddenVolumeControls(); |
141 } | 149 } |
142 | 150 |
143 } // anonymous namespace | 151 } // anonymous namespace |
144 | 152 |
145 class MediaControlsImpl::BatchedControlUpdate { | 153 class MediaControlsImpl::BatchedControlUpdate { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 | 194 |
187 DEFINE_INLINE_TRACE() { | 195 DEFINE_INLINE_TRACE() { |
188 visitor->Trace(controls_); | 196 visitor->Trace(controls_); |
189 ResizeObserverCallback::Trace(visitor); | 197 ResizeObserverCallback::Trace(visitor); |
190 } | 198 } |
191 | 199 |
192 private: | 200 private: |
193 Member<MediaControlsImpl> controls_; | 201 Member<MediaControlsImpl> controls_; |
194 }; | 202 }; |
195 | 203 |
| 204 // Observes changes to the HTMLMediaElement attributes that affect controls. |
| 205 // Currently only observes the disableRemotePlayback attribute. |
| 206 class MediaControlsImpl::MediaElementMutationCallback |
| 207 : public MutationCallback { |
| 208 public: |
| 209 explicit MediaElementMutationCallback(MediaControlsImpl* controls) |
| 210 : controls_(controls) { |
| 211 observer_ = MutationObserver::Create(this); |
| 212 Vector<String> filter; |
| 213 filter.push_back(HTMLNames::disableremoteplaybackAttr.ToString()); |
| 214 MutationObserverInit init; |
| 215 init.setAttributeOldValue(true); |
| 216 init.setAttributes(true); |
| 217 init.setAttributeFilter(filter); |
| 218 observer_->observe(&controls_->MediaElement(), init, ASSERT_NO_EXCEPTION); |
| 219 } |
| 220 |
| 221 DEFINE_INLINE_VIRTUAL_TRACE() { |
| 222 visitor->Trace(controls_); |
| 223 visitor->Trace(observer_); |
| 224 MutationCallback::Trace(visitor); |
| 225 } |
| 226 |
| 227 void Disconnect() { observer_->disconnect(); } |
| 228 |
| 229 private: |
| 230 void Call(const HeapVector<Member<MutationRecord>>& records, |
| 231 MutationObserver*) override { |
| 232 for (const auto& record : records) { |
| 233 if (record->type() != "attributes") |
| 234 continue; |
| 235 |
| 236 const Element& element = *ToElement(record->target()); |
| 237 if (record->oldValue() == element.getAttribute(record->attributeName())) |
| 238 continue; |
| 239 |
| 240 DCHECK_EQ(HTMLNames::disableremoteplaybackAttr.ToString(), |
| 241 record->attributeName()); |
| 242 controls_->RefreshCastButtonVisibility(); |
| 243 return; |
| 244 } |
| 245 } |
| 246 |
| 247 ExecutionContext* GetExecutionContext() const override { |
| 248 return &controls_->GetDocument(); |
| 249 } |
| 250 |
| 251 Member<MediaControlsImpl> controls_; |
| 252 Member<MutationObserver> observer_; |
| 253 }; |
| 254 |
196 MediaControls* MediaControlsImpl::Factory::Create( | 255 MediaControls* MediaControlsImpl::Factory::Create( |
197 HTMLMediaElement& media_element, | 256 HTMLMediaElement& media_element, |
198 ShadowRoot& shadow_root) { | 257 ShadowRoot& shadow_root) { |
199 return MediaControlsImpl::Create(media_element, shadow_root); | 258 return MediaControlsImpl::Create(media_element, shadow_root); |
200 } | 259 } |
201 | 260 |
202 MediaControlsImpl::MediaControlsImpl(HTMLMediaElement& media_element) | 261 MediaControlsImpl::MediaControlsImpl(HTMLMediaElement& media_element) |
203 : HTMLDivElement(media_element.GetDocument()), | 262 : HTMLDivElement(media_element.GetDocument()), |
204 MediaControls(media_element), | 263 MediaControls(media_element), |
205 overlay_enclosure_(nullptr), | 264 overlay_enclosure_(nullptr), |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 orientation_lock_delegate_->Attach(); | 469 orientation_lock_delegate_->Attach(); |
411 | 470 |
412 if (!resize_observer_) { | 471 if (!resize_observer_) { |
413 resize_observer_ = | 472 resize_observer_ = |
414 ResizeObserver::Create(MediaElement().GetDocument(), | 473 ResizeObserver::Create(MediaElement().GetDocument(), |
415 new MediaControlsResizeObserverCallback(this)); | 474 new MediaControlsResizeObserverCallback(this)); |
416 HTMLMediaElement& html_media_element = MediaElement(); | 475 HTMLMediaElement& html_media_element = MediaElement(); |
417 resize_observer_->observe(&html_media_element); | 476 resize_observer_->observe(&html_media_element); |
418 } | 477 } |
419 | 478 |
| 479 if (!element_mutation_callback_) |
| 480 element_mutation_callback_ = new MediaElementMutationCallback(this); |
| 481 |
420 return HTMLDivElement::InsertedInto(root); | 482 return HTMLDivElement::InsertedInto(root); |
421 } | 483 } |
422 | 484 |
423 void MediaControlsImpl::RemovedFrom(ContainerNode*) { | 485 void MediaControlsImpl::RemovedFrom(ContainerNode*) { |
424 DCHECK(!MediaElement().isConnected()); | 486 DCHECK(!MediaElement().isConnected()); |
425 | 487 |
426 // TODO(mlamouri): we hide show the controls instead of having | 488 // TODO(mlamouri): we hide show the controls instead of having |
427 // HTMLMediaElement do it. | 489 // HTMLMediaElement do it. |
428 | 490 |
429 window_event_listener_->Stop(); | 491 window_event_listener_->Stop(); |
430 media_event_listener_->Detach(); | 492 media_event_listener_->Detach(); |
431 if (orientation_lock_delegate_) | 493 if (orientation_lock_delegate_) |
432 orientation_lock_delegate_->Detach(); | 494 orientation_lock_delegate_->Detach(); |
433 | 495 |
434 resize_observer_.Clear(); | 496 resize_observer_.Clear(); |
| 497 |
| 498 if (element_mutation_callback_) { |
| 499 element_mutation_callback_->Disconnect(); |
| 500 element_mutation_callback_.Clear(); |
| 501 } |
435 } | 502 } |
436 | 503 |
437 void MediaControlsImpl::Reset() { | 504 void MediaControlsImpl::Reset() { |
438 EventDispatchForbiddenScope::AllowUserAgentEvents allow_events_in_shadow; | 505 EventDispatchForbiddenScope::AllowUserAgentEvents allow_events_in_shadow; |
439 BatchedControlUpdate batch(this); | 506 BatchedControlUpdate batch(this); |
440 | 507 |
441 const double duration = MediaElement().duration(); | 508 const double duration = MediaElement().duration(); |
442 duration_display_->setTextContent( | 509 duration_display_->setTextContent( |
443 LayoutTheme::GetTheme().FormatMediaControlsTime(duration)); | 510 LayoutTheme::GetTheme().FormatMediaControlsTime(duration)); |
444 duration_display_->SetCurrentValue(duration); | 511 duration_display_->SetCurrentValue(duration); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 panel_->MakeOpaque(); | 577 panel_->MakeOpaque(); |
511 } | 578 } |
512 | 579 |
513 void MediaControlsImpl::MakeTransparent() { | 580 void MediaControlsImpl::MakeTransparent() { |
514 panel_->MakeTransparent(); | 581 panel_->MakeTransparent(); |
515 } | 582 } |
516 | 583 |
517 bool MediaControlsImpl::ShouldHideMediaControls(unsigned behavior_flags) const { | 584 bool MediaControlsImpl::ShouldHideMediaControls(unsigned behavior_flags) const { |
518 // Never hide for a media element without visual representation. | 585 // Never hide for a media element without visual representation. |
519 if (!MediaElement().IsHTMLVideoElement() || !MediaElement().HasVideo() || | 586 if (!MediaElement().IsHTMLVideoElement() || !MediaElement().HasVideo() || |
520 MediaElement().IsPlayingRemotely() || | |
521 toHTMLVideoElement(MediaElement()).GetMediaRemotingStatus() == | 587 toHTMLVideoElement(MediaElement()).GetMediaRemotingStatus() == |
522 HTMLVideoElement::MediaRemotingStatus::kStarted) { | 588 HTMLVideoElement::MediaRemotingStatus::kStarted) { |
523 return false; | 589 return false; |
524 } | 590 } |
525 | 591 |
| 592 RemotePlayback* remote = |
| 593 HTMLMediaElementRemotePlayback::remote(MediaElement()); |
| 594 if (remote && remote->GetState() != WebRemotePlaybackState::kDisconnected) |
| 595 return false; |
| 596 |
526 // Keep the controls visible as long as the timer is running. | 597 // Keep the controls visible as long as the timer is running. |
527 const bool ignore_wait_for_timer = behavior_flags & kIgnoreWaitForTimer; | 598 const bool ignore_wait_for_timer = behavior_flags & kIgnoreWaitForTimer; |
528 if (!ignore_wait_for_timer && keep_showing_until_timer_fires_) | 599 if (!ignore_wait_for_timer && keep_showing_until_timer_fires_) |
529 return false; | 600 return false; |
530 | 601 |
531 // Don't hide if the mouse is over the controls. | 602 // Don't hide if the mouse is over the controls. |
532 const bool ignore_controls_hover = behavior_flags & kIgnoreControlsHover; | 603 const bool ignore_controls_hover = behavior_flags & kIgnoreControlsHover; |
533 if (!ignore_controls_hover && panel_->IsHovered()) | 604 if (!ignore_controls_hover && panel_->IsHovered()) |
534 return false; | 605 return false; |
535 | 606 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 overlay_cast_button_->TryShowOverlay(); | 726 overlay_cast_button_->TryShowOverlay(); |
656 cast_button_->SetIsWanted(false); | 727 cast_button_->SetIsWanted(false); |
657 } else if (MediaElement().ShouldShowControls()) { | 728 } else if (MediaElement().ShouldShowControls()) { |
658 overlay_cast_button_->SetIsWanted(false); | 729 overlay_cast_button_->SetIsWanted(false); |
659 cast_button_->SetIsWanted(true); | 730 cast_button_->SetIsWanted(true); |
660 } | 731 } |
661 } | 732 } |
662 | 733 |
663 void MediaControlsImpl::ShowOverlayCastButtonIfNeeded() { | 734 void MediaControlsImpl::ShowOverlayCastButtonIfNeeded() { |
664 if (MediaElement().ShouldShowControls() || | 735 if (MediaElement().ShouldShowControls() || |
665 !ShouldShowCastButton(MediaElement())) | 736 !ShouldShowCastButton(MediaElement())) { |
666 return; | 737 return; |
| 738 } |
667 | 739 |
668 overlay_cast_button_->TryShowOverlay(); | 740 overlay_cast_button_->TryShowOverlay(); |
669 ResetHideMediaControlsTimer(); | 741 ResetHideMediaControlsTimer(); |
670 } | 742 } |
671 | 743 |
672 void MediaControlsImpl::EnterFullscreen() { | 744 void MediaControlsImpl::EnterFullscreen() { |
673 Fullscreen::RequestFullscreen(MediaElement()); | 745 Fullscreen::RequestFullscreen(MediaElement()); |
674 } | 746 } |
675 | 747 |
676 void MediaControlsImpl::ExitFullscreen() { | 748 void MediaControlsImpl::ExitFullscreen() { |
677 Fullscreen::ExitFullscreen(GetDocument()); | 749 Fullscreen::ExitFullscreen(GetDocument()); |
678 } | 750 } |
679 | 751 |
680 void MediaControlsImpl::StartedCasting() { | 752 void MediaControlsImpl::RemotePlaybackStateChanged() { |
681 cast_button_->SetIsPlayingRemotely(true); | 753 cast_button_->UpdateDisplayType(); |
682 overlay_cast_button_->SetIsPlayingRemotely(true); | 754 overlay_cast_button_->UpdateDisplayType(); |
683 } | |
684 | |
685 void MediaControlsImpl::StoppedCasting() { | |
686 cast_button_->SetIsPlayingRemotely(false); | |
687 overlay_cast_button_->SetIsPlayingRemotely(false); | |
688 } | 755 } |
689 | 756 |
690 void MediaControlsImpl::DefaultEventHandler(Event* event) { | 757 void MediaControlsImpl::DefaultEventHandler(Event* event) { |
691 HTMLDivElement::DefaultEventHandler(event); | 758 HTMLDivElement::DefaultEventHandler(event); |
692 | 759 |
693 // Do not handle events to not interfere with the rest of the page if no | 760 // Do not handle events to not interfere with the rest of the page if no |
694 // controls should be visible. | 761 // controls should be visible. |
695 if (!MediaElement().ShouldShowControls()) | 762 if (!MediaElement().ShouldShowControls()) |
696 return; | 763 return; |
697 | 764 |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 void MediaControlsImpl::HideAllMenus() { | 1168 void MediaControlsImpl::HideAllMenus() { |
1102 window_event_listener_->Stop(); | 1169 window_event_listener_->Stop(); |
1103 | 1170 |
1104 if (overflow_list_->IsWanted()) | 1171 if (overflow_list_->IsWanted()) |
1105 overflow_list_->SetIsWanted(false); | 1172 overflow_list_->SetIsWanted(false); |
1106 if (text_track_list_->IsWanted()) | 1173 if (text_track_list_->IsWanted()) |
1107 text_track_list_->SetVisible(false); | 1174 text_track_list_->SetVisible(false); |
1108 } | 1175 } |
1109 | 1176 |
1110 DEFINE_TRACE(MediaControlsImpl) { | 1177 DEFINE_TRACE(MediaControlsImpl) { |
| 1178 visitor->Trace(element_mutation_callback_); |
1111 visitor->Trace(resize_observer_); | 1179 visitor->Trace(resize_observer_); |
1112 visitor->Trace(panel_); | 1180 visitor->Trace(panel_); |
1113 visitor->Trace(overlay_play_button_); | 1181 visitor->Trace(overlay_play_button_); |
1114 visitor->Trace(overlay_enclosure_); | 1182 visitor->Trace(overlay_enclosure_); |
1115 visitor->Trace(play_button_); | 1183 visitor->Trace(play_button_); |
1116 visitor->Trace(current_time_display_); | 1184 visitor->Trace(current_time_display_); |
1117 visitor->Trace(timeline_); | 1185 visitor->Trace(timeline_); |
1118 visitor->Trace(mute_button_); | 1186 visitor->Trace(mute_button_); |
1119 visitor->Trace(volume_slider_); | 1187 visitor->Trace(volume_slider_); |
1120 visitor->Trace(toggle_closed_captions_button_); | 1188 visitor->Trace(toggle_closed_captions_button_); |
1121 visitor->Trace(fullscreen_button_); | 1189 visitor->Trace(fullscreen_button_); |
1122 visitor->Trace(download_button_); | 1190 visitor->Trace(download_button_); |
1123 visitor->Trace(duration_display_); | 1191 visitor->Trace(duration_display_); |
1124 visitor->Trace(enclosure_); | 1192 visitor->Trace(enclosure_); |
1125 visitor->Trace(text_track_list_); | 1193 visitor->Trace(text_track_list_); |
1126 visitor->Trace(overflow_menu_); | 1194 visitor->Trace(overflow_menu_); |
1127 visitor->Trace(overflow_list_); | 1195 visitor->Trace(overflow_list_); |
1128 visitor->Trace(cast_button_); | 1196 visitor->Trace(cast_button_); |
1129 visitor->Trace(overlay_cast_button_); | 1197 visitor->Trace(overlay_cast_button_); |
1130 visitor->Trace(media_event_listener_); | 1198 visitor->Trace(media_event_listener_); |
1131 visitor->Trace(window_event_listener_); | 1199 visitor->Trace(window_event_listener_); |
1132 visitor->Trace(orientation_lock_delegate_); | 1200 visitor->Trace(orientation_lock_delegate_); |
1133 MediaControls::Trace(visitor); | 1201 MediaControls::Trace(visitor); |
1134 HTMLDivElement::Trace(visitor); | 1202 HTMLDivElement::Trace(visitor); |
1135 } | 1203 } |
1136 | 1204 |
1137 } // namespace blink | 1205 } // namespace blink |
OLD | NEW |