| 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 |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * | 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 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 "core/html/shadow/MediaControls.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/ResizeObserver.h" | 32 #include "core/dom/ResizeObserver.h" |
| 33 #include "core/dom/ResizeObserverCallback.h" | 33 #include "core/dom/ResizeObserverCallback.h" |
| 34 #include "core/dom/ResizeObserverEntry.h" | 34 #include "core/dom/ResizeObserverEntry.h" |
| 35 #include "core/dom/TaskRunnerHelper.h" | 35 #include "core/dom/TaskRunnerHelper.h" |
| 36 #include "core/events/MouseEvent.h" | 36 #include "core/events/MouseEvent.h" |
| 37 #include "core/frame/Settings.h" | 37 #include "core/frame/Settings.h" |
| 38 #include "core/frame/UseCounter.h" | 38 #include "core/frame/UseCounter.h" |
| 39 #include "core/html/HTMLMediaElement.h" | 39 #include "core/html/HTMLMediaElement.h" |
| 40 #include "core/html/HTMLVideoElement.h" | 40 #include "core/html/HTMLVideoElement.h" |
| 41 #include "core/html/media/HTMLMediaElementControlsList.h" | 41 #include "core/html/media/HTMLMediaElementControlsList.h" |
| 42 #include "core/html/shadow/MediaControlsMediaEventListener.h" | 42 #include "core/html/shadow/MediaControlsMediaEventListener.h" |
| 43 #include "core/html/shadow/MediaControlsOrientationLockDelegate.h" | |
| 44 #include "core/html/shadow/MediaControlsWindowEventListener.h" | 43 #include "core/html/shadow/MediaControlsWindowEventListener.h" |
| 45 #include "core/html/track/TextTrackContainer.h" | 44 #include "core/html/track/TextTrackContainer.h" |
| 46 #include "core/html/track/TextTrackList.h" | 45 #include "core/html/track/TextTrackList.h" |
| 47 #include "core/layout/LayoutObject.h" | 46 #include "core/layout/LayoutObject.h" |
| 48 #include "core/layout/LayoutTheme.h" | 47 #include "core/layout/LayoutTheme.h" |
| 48 #include "modules/media_controls/MediaControlsOrientationLockDelegate.h" |
| 49 #include "platform/EventDispatchForbiddenScope.h" | 49 #include "platform/EventDispatchForbiddenScope.h" |
| 50 | 50 |
| 51 namespace blink { | 51 namespace blink { |
| 52 | 52 |
| 53 namespace { | 53 namespace { |
| 54 | 54 |
| 55 // TODO(steimel): should have better solution than hard-coding pixel values. | 55 // TODO(steimel): should have better solution than hard-coding pixel values. |
| 56 // Defined in core/css/mediaControls.css, core/css/mediaControlsAndroid.css, | 56 // Defined in core/css/mediaControls.css, core/css/mediaControlsAndroid.css, |
| 57 // and core/paint/MediaControlsPainter.cpp. | 57 // and core/paint/MediaControlsPainter.cpp. |
| 58 constexpr int kOverlayPlayButtonWidth = 48; | 58 constexpr int kOverlayPlayButtonWidth = 48; |
| 59 constexpr int kOverlayPlayButtonHeight = 48; | 59 constexpr int kOverlayPlayButtonHeight = 48; |
| 60 constexpr int kOverlayBottomMargin = 10; | 60 constexpr int kOverlayBottomMargin = 10; |
| 61 constexpr int kAndroidMediaPanelHeight = 48; | 61 constexpr int kAndroidMediaPanelHeight = 48; |
| 62 | 62 |
| 63 constexpr int kMinWidthForOverlayPlayButton = kOverlayPlayButtonWidth; | 63 constexpr int kMinWidthForOverlayPlayButton = kOverlayPlayButtonWidth; |
| 64 constexpr int kMinHeightForOverlayPlayButton = kOverlayPlayButtonHeight + | 64 constexpr int kMinHeightForOverlayPlayButton = kOverlayPlayButtonHeight + |
| 65 kAndroidMediaPanelHeight + | 65 kAndroidMediaPanelHeight + |
| 66 (2 * kOverlayBottomMargin); | 66 (2 * kOverlayBottomMargin); |
| 67 | 67 |
| 68 } // anonymous namespace | |
| 69 | |
| 70 // If you change this value, then also update the corresponding value in | 68 // If you change this value, then also update the corresponding value in |
| 71 // LayoutTests/media/media-controls.js. | 69 // LayoutTests/media/media-controls.js. |
| 72 static const double timeWithoutMouseMovementBeforeHidingMediaControls = 3; | 70 const double timeWithoutMouseMovementBeforeHidingMediaControls = 3; |
| 73 | 71 |
| 74 static bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) { | 72 bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) { |
| 75 // Unconditionally allow the user to exit fullscreen if we are in it | 73 // Unconditionally allow the user to exit fullscreen if we are in it |
| 76 // now. Especially on android, when we might not yet know if | 74 // now. Especially on android, when we might not yet know if |
| 77 // fullscreen is supported, we sometimes guess incorrectly and show | 75 // fullscreen is supported, we sometimes guess incorrectly and show |
| 78 // the button earlier, and we don't want to remove it here if the | 76 // the button earlier, and we don't want to remove it here if the |
| 79 // user chose to enter fullscreen. crbug.com/500732 . | 77 // user chose to enter fullscreen. crbug.com/500732 . |
| 80 if (mediaElement.isFullscreen()) | 78 if (mediaElement.isFullscreen()) |
| 81 return true; | 79 return true; |
| 82 | 80 |
| 83 if (!mediaElement.isHTMLVideoElement()) | 81 if (!mediaElement.isHTMLVideoElement()) |
| 84 return false; | 82 return false; |
| 85 | 83 |
| 86 if (!mediaElement.hasVideo()) | 84 if (!mediaElement.hasVideo()) |
| 87 return false; | 85 return false; |
| 88 | 86 |
| 89 if (!Fullscreen::fullscreenEnabled(mediaElement.document())) | 87 if (!Fullscreen::fullscreenEnabled(mediaElement.document())) |
| 90 return false; | 88 return false; |
| 91 | 89 |
| 92 if (mediaElement.controlsListInternal()->shouldHideFullscreen()) { | 90 if (mediaElement.controlsListInternal()->shouldHideFullscreen()) { |
| 93 UseCounter::count(mediaElement.document(), | 91 UseCounter::count(mediaElement.document(), |
| 94 UseCounter::HTMLMediaElementControlsListNoFullscreen); | 92 UseCounter::HTMLMediaElementControlsListNoFullscreen); |
| 95 return false; | 93 return false; |
| 96 } | 94 } |
| 97 | 95 |
| 98 return true; | 96 return true; |
| 99 } | 97 } |
| 100 | 98 |
| 101 static bool shouldShowCastButton(HTMLMediaElement& mediaElement) { | 99 bool shouldShowCastButton(HTMLMediaElement& mediaElement) { |
| 102 if (mediaElement.fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) | 100 if (mediaElement.fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) |
| 103 return false; | 101 return false; |
| 104 | 102 |
| 105 // Explicitly do not show cast button when the mediaControlsEnabled setting is | 103 // Explicitly do not show cast button when the mediaControlsEnabled setting is |
| 106 // false to make sure the overlay does not appear. | 104 // false to make sure the overlay does not appear. |
| 107 Document& document = mediaElement.document(); | 105 Document& document = mediaElement.document(); |
| 108 if (document.settings() && !document.settings()->getMediaControlsEnabled()) | 106 if (document.settings() && !document.settings()->getMediaControlsEnabled()) |
| 109 return false; | 107 return false; |
| 110 | 108 |
| 111 // The page disabled the button via the attribute. | 109 // The page disabled the button via the attribute. |
| 112 if (mediaElement.controlsListInternal()->shouldHideRemotePlayback()) { | 110 if (mediaElement.controlsListInternal()->shouldHideRemotePlayback()) { |
| 113 UseCounter::count(mediaElement.document(), | 111 UseCounter::count(mediaElement.document(), |
| 114 UseCounter::HTMLMediaElementControlsListNoRemotePlayback); | 112 UseCounter::HTMLMediaElementControlsListNoRemotePlayback); |
| 115 return false; | 113 return false; |
| 116 } | 114 } |
| 117 | 115 |
| 118 return mediaElement.hasRemoteRoutes(); | 116 return mediaElement.hasRemoteRoutes(); |
| 119 } | 117 } |
| 120 | 118 |
| 121 static bool preferHiddenVolumeControls(const Document& document) { | 119 bool preferHiddenVolumeControls(const Document& document) { |
| 122 return !document.settings() || | 120 return !document.settings() || |
| 123 document.settings()->getPreferHiddenVolumeControls(); | 121 document.settings()->getPreferHiddenVolumeControls(); |
| 124 } | 122 } |
| 125 | 123 |
| 126 class MediaControls::BatchedControlUpdate { | 124 } // anonymous namespace |
| 125 |
| 126 class MediaControlsImpl::BatchedControlUpdate { |
| 127 WTF_MAKE_NONCOPYABLE(BatchedControlUpdate); | 127 WTF_MAKE_NONCOPYABLE(BatchedControlUpdate); |
| 128 STACK_ALLOCATED(); | 128 STACK_ALLOCATED(); |
| 129 | 129 |
| 130 public: | 130 public: |
| 131 explicit BatchedControlUpdate(MediaControls* controls) | 131 explicit BatchedControlUpdate(MediaControlsImpl* controls) |
| 132 : m_controls(controls) { | 132 : m_controls(controls) { |
| 133 DCHECK(isMainThread()); | 133 DCHECK(isMainThread()); |
| 134 DCHECK_GE(s_batchDepth, 0); | 134 DCHECK_GE(s_batchDepth, 0); |
| 135 ++s_batchDepth; | 135 ++s_batchDepth; |
| 136 } | 136 } |
| 137 ~BatchedControlUpdate() { | 137 ~BatchedControlUpdate() { |
| 138 DCHECK(isMainThread()); | 138 DCHECK(isMainThread()); |
| 139 DCHECK_GT(s_batchDepth, 0); | 139 DCHECK_GT(s_batchDepth, 0); |
| 140 if (!(--s_batchDepth)) | 140 if (!(--s_batchDepth)) |
| 141 m_controls->computeWhichControlsFit(); | 141 m_controls->computeWhichControlsFit(); |
| 142 } | 142 } |
| 143 | 143 |
| 144 private: | 144 private: |
| 145 Member<MediaControls> m_controls; | 145 Member<MediaControlsImpl> m_controls; |
| 146 static int s_batchDepth; | 146 static int s_batchDepth; |
| 147 }; | 147 }; |
| 148 | 148 |
| 149 // Count of number open batches for controls visibility. | 149 // Count of number open batches for controls visibility. |
| 150 int MediaControls::BatchedControlUpdate::s_batchDepth = 0; | 150 int MediaControlsImpl::BatchedControlUpdate::s_batchDepth = 0; |
| 151 | 151 |
| 152 class MediaControls::MediaControlsResizeObserverCallback final | 152 class MediaControlsImpl::MediaControlsResizeObserverCallback final |
| 153 : public ResizeObserverCallback { | 153 : public ResizeObserverCallback { |
| 154 public: | 154 public: |
| 155 explicit MediaControlsResizeObserverCallback(MediaControls* controls) | 155 explicit MediaControlsResizeObserverCallback(MediaControlsImpl* controls) |
| 156 : m_controls(controls) { | 156 : m_controls(controls) { |
| 157 DCHECK(controls); | 157 DCHECK(controls); |
| 158 } | 158 } |
| 159 ~MediaControlsResizeObserverCallback() override = default; | 159 ~MediaControlsResizeObserverCallback() override = default; |
| 160 | 160 |
| 161 void handleEvent(const HeapVector<Member<ResizeObserverEntry>>& entries, | 161 void handleEvent(const HeapVector<Member<ResizeObserverEntry>>& entries, |
| 162 ResizeObserver* observer) override { | 162 ResizeObserver* observer) override { |
| 163 DCHECK_EQ(1u, entries.size()); | 163 DCHECK_EQ(1u, entries.size()); |
| 164 DCHECK_EQ(entries[0]->target(), m_controls->m_mediaElement); | 164 DCHECK_EQ(entries[0]->target(), m_controls->mediaElement()); |
| 165 m_controls->notifyElementSizeChanged(entries[0]->contentRect()); | 165 m_controls->notifyElementSizeChanged(entries[0]->contentRect()); |
| 166 } | 166 } |
| 167 | 167 |
| 168 DEFINE_INLINE_TRACE() { | 168 DEFINE_INLINE_TRACE() { |
| 169 visitor->trace(m_controls); | 169 visitor->trace(m_controls); |
| 170 ResizeObserverCallback::trace(visitor); | 170 ResizeObserverCallback::trace(visitor); |
| 171 } | 171 } |
| 172 | 172 |
| 173 private: | 173 private: |
| 174 Member<MediaControls> m_controls; | 174 Member<MediaControlsImpl> m_controls; |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 MediaControls::MediaControls(HTMLMediaElement& mediaElement) | 177 MediaControls* MediaControlsImpl::Factory::create( |
| 178 HTMLMediaElement& mediaElement, |
| 179 ShadowRoot& shadowRoot) { |
| 180 return MediaControlsImpl::create(mediaElement, shadowRoot); |
| 181 } |
| 182 |
| 183 MediaControlsImpl::MediaControlsImpl(HTMLMediaElement& mediaElement) |
| 178 : HTMLDivElement(mediaElement.document()), | 184 : HTMLDivElement(mediaElement.document()), |
| 179 m_mediaElement(&mediaElement), | 185 MediaControls(mediaElement), |
| 180 m_overlayEnclosure(nullptr), | 186 m_overlayEnclosure(nullptr), |
| 181 m_overlayPlayButton(nullptr), | 187 m_overlayPlayButton(nullptr), |
| 182 m_overlayCastButton(nullptr), | 188 m_overlayCastButton(nullptr), |
| 183 m_enclosure(nullptr), | 189 m_enclosure(nullptr), |
| 184 m_panel(nullptr), | 190 m_panel(nullptr), |
| 185 m_playButton(nullptr), | 191 m_playButton(nullptr), |
| 186 m_timeline(nullptr), | 192 m_timeline(nullptr), |
| 187 m_currentTimeDisplay(nullptr), | 193 m_currentTimeDisplay(nullptr), |
| 188 m_durationDisplay(nullptr), | 194 m_durationDisplay(nullptr), |
| 189 m_muteButton(nullptr), | 195 m_muteButton(nullptr), |
| 190 m_volumeSlider(nullptr), | 196 m_volumeSlider(nullptr), |
| 191 m_toggleClosedCaptionsButton(nullptr), | 197 m_toggleClosedCaptionsButton(nullptr), |
| 192 m_textTrackList(nullptr), | 198 m_textTrackList(nullptr), |
| 193 m_overflowList(nullptr), | 199 m_overflowList(nullptr), |
| 194 m_castButton(nullptr), | 200 m_castButton(nullptr), |
| 195 m_fullscreenButton(nullptr), | 201 m_fullscreenButton(nullptr), |
| 196 m_downloadButton(nullptr), | 202 m_downloadButton(nullptr), |
| 197 m_mediaEventListener(new MediaControlsMediaEventListener(this)), | 203 m_mediaEventListener(new MediaControlsMediaEventListener(this)), |
| 198 m_windowEventListener(MediaControlsWindowEventListener::create( | 204 m_windowEventListener(MediaControlsWindowEventListener::create( |
| 199 this, | 205 this, |
| 200 WTF::bind(&MediaControls::hideAllMenus, wrapWeakPersistent(this)))), | 206 WTF::bind(&MediaControlsImpl::hideAllMenus, |
| 207 wrapWeakPersistent(this)))), |
| 201 m_orientationLockDelegate(nullptr), | 208 m_orientationLockDelegate(nullptr), |
| 202 m_hideMediaControlsTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, | 209 m_hideMediaControlsTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, |
| 203 &mediaElement.document()), | 210 &mediaElement.document()), |
| 204 this, | 211 this, |
| 205 &MediaControls::hideMediaControlsTimerFired), | 212 &MediaControlsImpl::hideMediaControlsTimerFired), |
| 206 m_hideTimerBehaviorFlags(IgnoreNone), | 213 m_hideTimerBehaviorFlags(IgnoreNone), |
| 207 m_isMouseOverControls(false), | 214 m_isMouseOverControls(false), |
| 208 m_isPausedForScrubbing(false), | 215 m_isPausedForScrubbing(false), |
| 209 m_resizeObserver(ResizeObserver::create( | 216 m_resizeObserver(ResizeObserver::create( |
| 210 mediaElement.document(), | 217 mediaElement.document(), |
| 211 new MediaControlsResizeObserverCallback(this))), | 218 new MediaControlsResizeObserverCallback(this))), |
| 212 m_elementSizeChangedTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer, | 219 m_elementSizeChangedTimer( |
| 213 &mediaElement.document()), | 220 TaskRunnerHelper::get(TaskType::UnspecedTimer, |
| 214 this, | 221 &mediaElement.document()), |
| 215 &MediaControls::elementSizeChangedTimerFired), | 222 this, |
| 223 &MediaControlsImpl::elementSizeChangedTimerFired), |
| 216 m_keepShowingUntilTimerFires(false) { | 224 m_keepShowingUntilTimerFires(false) { |
| 217 m_resizeObserver->observe(m_mediaElement); | 225 m_resizeObserver->observe(&mediaElement); |
| 218 } | 226 } |
| 219 | 227 |
| 220 MediaControls* MediaControls::create(HTMLMediaElement& mediaElement, | 228 MediaControlsImpl* MediaControlsImpl::create(HTMLMediaElement& mediaElement, |
| 221 ShadowRoot& shadowRoot) { | 229 ShadowRoot& shadowRoot) { |
| 222 MediaControls* controls = new MediaControls(mediaElement); | 230 MediaControlsImpl* controls = new MediaControlsImpl(mediaElement); |
| 223 controls->setShadowPseudoId(AtomicString("-webkit-media-controls")); | 231 controls->setShadowPseudoId(AtomicString("-webkit-media-controls")); |
| 224 controls->initializeControls(); | 232 controls->initializeControls(); |
| 225 controls->reset(); | 233 controls->reset(); |
| 226 | 234 |
| 227 // Initialize the orientation lock when going fullscreen feature. | 235 // Initialize the orientation lock when going fullscreen feature. |
| 228 if (RuntimeEnabledFeatures::videoFullscreenOrientationLockEnabled() && | 236 if (RuntimeEnabledFeatures::videoFullscreenOrientationLockEnabled() && |
| 229 mediaElement.isHTMLVideoElement()) { | 237 mediaElement.isHTMLVideoElement()) { |
| 230 controls->m_orientationLockDelegate = | 238 controls->m_orientationLockDelegate = |
| 231 new MediaControlsOrientationLockDelegate( | 239 new MediaControlsOrientationLockDelegate( |
| 232 toHTMLVideoElement(mediaElement)); | 240 toHTMLVideoElement(mediaElement)); |
| 233 } | 241 } |
| 234 | 242 |
| 235 shadowRoot.appendChild(controls); | 243 shadowRoot.appendChild(controls); |
| 236 return controls; | 244 return controls; |
| 237 } | 245 } |
| 238 | 246 |
| 239 // The media controls DOM structure looks like: | 247 // The media controls DOM structure looks like: |
| 240 // | 248 // |
| 241 // MediaControls | 249 // MediaControlsImpl |
| 242 // (-webkit-media-controls) | 250 // (-webkit-media-controls) |
| 243 // +-MediaControlOverlayEnclosureElement | 251 // +-MediaControlOverlayEnclosureElement |
| 244 // | (-webkit-media-controls-overlay-enclosure) | 252 // | (-webkit-media-controls-overlay-enclosure) |
| 245 // | +-MediaControlOverlayPlayButtonElement | 253 // | +-MediaControlOverlayPlayButtonElement |
| 246 // | | (-webkit-media-controls-overlay-play-button) | 254 // | | (-webkit-media-controls-overlay-play-button) |
| 247 // | | {if mediaControlsOverlayPlayButtonEnabled} | 255 // | | {if mediaControlsOverlayPlayButtonEnabled} |
| 248 // | \-MediaControlCastButtonElement | 256 // | \-MediaControlCastButtonElement |
| 249 // | (-internal-media-controls-overlay-cast-button) | 257 // | (-internal-media-controls-overlay-cast-button) |
| 250 // \-MediaControlPanelEnclosureElement | 258 // \-MediaControlPanelEnclosureElement |
| 251 // | (-webkit-media-controls-enclosure) | 259 // | (-webkit-media-controls-enclosure) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 275 // | (-internal-media-controls-text-track-list) | 283 // | (-internal-media-controls-text-track-list) |
| 276 // | {for each renderable text track} | 284 // | {for each renderable text track} |
| 277 // \-MediaControlTextTrackListItem | 285 // \-MediaControlTextTrackListItem |
| 278 // | (-internal-media-controls-text-track-list-item) | 286 // | (-internal-media-controls-text-track-list-item) |
| 279 // +-MediaControlTextTrackListItemInput | 287 // +-MediaControlTextTrackListItemInput |
| 280 // | (-internal-media-controls-text-track-list-item-input) | 288 // | (-internal-media-controls-text-track-list-item-input) |
| 281 // +-MediaControlTextTrackListItemCaptions | 289 // +-MediaControlTextTrackListItemCaptions |
| 282 // | (-internal-media-controls-text-track-list-kind-captions) | 290 // | (-internal-media-controls-text-track-list-kind-captions) |
| 283 // +-MediaControlTextTrackListItemSubtitles | 291 // +-MediaControlTextTrackListItemSubtitles |
| 284 // (-internal-media-controls-text-track-list-kind-subtitles) | 292 // (-internal-media-controls-text-track-list-kind-subtitles) |
| 285 void MediaControls::initializeControls() { | 293 void MediaControlsImpl::initializeControls() { |
| 286 MediaControlOverlayEnclosureElement* overlayEnclosure = | 294 MediaControlOverlayEnclosureElement* overlayEnclosure = |
| 287 MediaControlOverlayEnclosureElement::create(*this); | 295 MediaControlOverlayEnclosureElement::create(*this); |
| 288 | 296 |
| 289 if (RuntimeEnabledFeatures::mediaControlsOverlayPlayButtonEnabled()) { | 297 if (RuntimeEnabledFeatures::mediaControlsOverlayPlayButtonEnabled()) { |
| 290 MediaControlOverlayPlayButtonElement* overlayPlayButton = | 298 MediaControlOverlayPlayButtonElement* overlayPlayButton = |
| 291 MediaControlOverlayPlayButtonElement::create(*this); | 299 MediaControlOverlayPlayButtonElement::create(*this); |
| 292 m_overlayPlayButton = overlayPlayButton; | 300 m_overlayPlayButton = overlayPlayButton; |
| 293 overlayEnclosure->appendChild(overlayPlayButton); | 301 overlayEnclosure->appendChild(overlayPlayButton); |
| 294 } | 302 } |
| 295 | 303 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 *this, MediaControlDownloadButtonElement::create(*this))); | 402 *this, MediaControlDownloadButtonElement::create(*this))); |
| 395 m_overflowList->appendChild(m_muteButton->createOverflowElement( | 403 m_overflowList->appendChild(m_muteButton->createOverflowElement( |
| 396 *this, MediaControlMuteButtonElement::create(*this))); | 404 *this, MediaControlMuteButtonElement::create(*this))); |
| 397 m_overflowList->appendChild(m_castButton->createOverflowElement( | 405 m_overflowList->appendChild(m_castButton->createOverflowElement( |
| 398 *this, MediaControlCastButtonElement::create(*this, false))); | 406 *this, MediaControlCastButtonElement::create(*this, false))); |
| 399 m_overflowList->appendChild( | 407 m_overflowList->appendChild( |
| 400 m_toggleClosedCaptionsButton->createOverflowElement( | 408 m_toggleClosedCaptionsButton->createOverflowElement( |
| 401 *this, MediaControlToggleClosedCaptionsButtonElement::create(*this))); | 409 *this, MediaControlToggleClosedCaptionsButtonElement::create(*this))); |
| 402 } | 410 } |
| 403 | 411 |
| 404 Node::InsertionNotificationRequest MediaControls::insertedInto( | 412 Node::InsertionNotificationRequest MediaControlsImpl::insertedInto( |
| 405 ContainerNode* root) { | 413 ContainerNode* root) { |
| 406 if (!mediaElement().isConnected()) | 414 if (!mediaElement().isConnected()) |
| 407 return HTMLDivElement::insertedInto(root); | 415 return HTMLDivElement::insertedInto(root); |
| 408 | 416 |
| 409 // TODO(mlamouri): we should show the controls instead of having | 417 // TODO(mlamouri): we should show the controls instead of having |
| 410 // HTMLMediaElement do it. | 418 // HTMLMediaElement do it. |
| 411 | 419 |
| 412 // m_windowEventListener doesn't need to be re-attached as it's only needed | 420 // m_windowEventListener doesn't need to be re-attached as it's only needed |
| 413 // when a menu is visible. | 421 // when a menu is visible. |
| 414 m_mediaEventListener->attach(); | 422 m_mediaEventListener->attach(); |
| 415 if (m_orientationLockDelegate) | 423 if (m_orientationLockDelegate) |
| 416 m_orientationLockDelegate->attach(); | 424 m_orientationLockDelegate->attach(); |
| 417 | 425 |
| 418 if (!m_resizeObserver) { | 426 if (!m_resizeObserver) { |
| 419 m_resizeObserver = | 427 m_resizeObserver = |
| 420 ResizeObserver::create(m_mediaElement->document(), | 428 ResizeObserver::create(mediaElement().document(), |
| 421 new MediaControlsResizeObserverCallback(this)); | 429 new MediaControlsResizeObserverCallback(this)); |
| 422 m_resizeObserver->observe(m_mediaElement); | 430 HTMLMediaElement& htmlMediaElement = mediaElement(); |
| 431 m_resizeObserver->observe(&htmlMediaElement); |
| 423 } | 432 } |
| 424 | 433 |
| 425 return HTMLDivElement::insertedInto(root); | 434 return HTMLDivElement::insertedInto(root); |
| 426 } | 435 } |
| 427 | 436 |
| 428 void MediaControls::removedFrom(ContainerNode*) { | 437 void MediaControlsImpl::removedFrom(ContainerNode*) { |
| 429 DCHECK(!mediaElement().isConnected()); | 438 DCHECK(!mediaElement().isConnected()); |
| 430 | 439 |
| 431 // TODO(mlamouri): we hide show the controls instead of having | 440 // TODO(mlamouri): we hide show the controls instead of having |
| 432 // HTMLMediaElement do it. | 441 // HTMLMediaElement do it. |
| 433 | 442 |
| 434 m_windowEventListener->stop(); | 443 m_windowEventListener->stop(); |
| 435 m_mediaEventListener->detach(); | 444 m_mediaEventListener->detach(); |
| 436 if (m_orientationLockDelegate) | 445 if (m_orientationLockDelegate) |
| 437 m_orientationLockDelegate->detach(); | 446 m_orientationLockDelegate->detach(); |
| 438 | 447 |
| 439 m_resizeObserver.clear(); | 448 m_resizeObserver.clear(); |
| 440 } | 449 } |
| 441 | 450 |
| 442 void MediaControls::reset() { | 451 void MediaControlsImpl::reset() { |
| 443 EventDispatchForbiddenScope::AllowUserAgentEvents allowEventsInShadow; | 452 EventDispatchForbiddenScope::AllowUserAgentEvents allowEventsInShadow; |
| 444 BatchedControlUpdate batch(this); | 453 BatchedControlUpdate batch(this); |
| 445 | 454 |
| 446 const double duration = mediaElement().duration(); | 455 const double duration = mediaElement().duration(); |
| 447 m_durationDisplay->setTextContent( | 456 m_durationDisplay->setTextContent( |
| 448 LayoutTheme::theme().formatMediaControlsTime(duration)); | 457 LayoutTheme::theme().formatMediaControlsTime(duration)); |
| 449 m_durationDisplay->setCurrentValue(duration); | 458 m_durationDisplay->setCurrentValue(duration); |
| 450 | 459 |
| 451 // Show everything that we might hide. | 460 // Show everything that we might hide. |
| 452 // If we don't have a duration, then mark it to be hidden. For the | 461 // If we don't have a duration, then mark it to be hidden. For the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 466 | 475 |
| 467 m_timeline->setDuration(duration); | 476 m_timeline->setDuration(duration); |
| 468 m_timeline->setPosition(mediaElement().currentTime()); | 477 m_timeline->setPosition(mediaElement().currentTime()); |
| 469 | 478 |
| 470 onVolumeChange(); | 479 onVolumeChange(); |
| 471 onTextTracksAddedOrRemoved(); | 480 onTextTracksAddedOrRemoved(); |
| 472 | 481 |
| 473 onControlsListUpdated(); | 482 onControlsListUpdated(); |
| 474 } | 483 } |
| 475 | 484 |
| 476 void MediaControls::onControlsListUpdated() { | 485 void MediaControlsImpl::onControlsListUpdated() { |
| 477 BatchedControlUpdate batch(this); | 486 BatchedControlUpdate batch(this); |
| 478 | 487 |
| 479 m_fullscreenButton->setIsWanted(shouldShowFullscreenButton(mediaElement())); | 488 m_fullscreenButton->setIsWanted(shouldShowFullscreenButton(mediaElement())); |
| 480 | 489 |
| 481 refreshCastButtonVisibilityWithoutUpdate(); | 490 refreshCastButtonVisibilityWithoutUpdate(); |
| 482 | 491 |
| 483 m_downloadButton->setIsWanted( | 492 m_downloadButton->setIsWanted( |
| 484 m_downloadButton->shouldDisplayDownloadButton()); | 493 m_downloadButton->shouldDisplayDownloadButton()); |
| 485 } | 494 } |
| 486 | 495 |
| 487 LayoutObject* MediaControls::layoutObjectForTextTrackLayout() { | 496 LayoutObject* MediaControlsImpl::panelLayoutObject() { |
| 488 return m_panel->layoutObject(); | 497 return m_panel->layoutObject(); |
| 489 } | 498 } |
| 490 | 499 |
| 491 void MediaControls::show() { | 500 LayoutObject* MediaControlsImpl::containerLayoutObject() { |
| 501 return layoutObject(); |
| 502 } |
| 503 |
| 504 void MediaControlsImpl::show() { |
| 492 makeOpaque(); | 505 makeOpaque(); |
| 493 m_panel->setIsWanted(true); | 506 m_panel->setIsWanted(true); |
| 494 m_panel->setIsDisplayed(true); | 507 m_panel->setIsDisplayed(true); |
| 495 if (m_overlayPlayButton) | 508 if (m_overlayPlayButton) |
| 496 m_overlayPlayButton->updateDisplayType(); | 509 m_overlayPlayButton->updateDisplayType(); |
| 497 } | 510 } |
| 498 | 511 |
| 499 void MediaControls::hide() { | 512 void MediaControlsImpl::hide() { |
| 500 m_panel->setIsWanted(false); | 513 m_panel->setIsWanted(false); |
| 501 m_panel->setIsDisplayed(false); | 514 m_panel->setIsDisplayed(false); |
| 502 if (m_overlayPlayButton) | 515 if (m_overlayPlayButton) |
| 503 m_overlayPlayButton->setIsWanted(false); | 516 m_overlayPlayButton->setIsWanted(false); |
| 504 } | 517 } |
| 505 | 518 |
| 506 bool MediaControls::isVisible() const { | 519 bool MediaControlsImpl::isVisible() const { |
| 507 return m_panel->isOpaque(); | 520 return m_panel->isOpaque(); |
| 508 } | 521 } |
| 509 | 522 |
| 510 void MediaControls::makeOpaque() { | 523 void MediaControlsImpl::makeOpaque() { |
| 511 m_panel->makeOpaque(); | 524 m_panel->makeOpaque(); |
| 512 } | 525 } |
| 513 | 526 |
| 514 void MediaControls::makeTransparent() { | 527 void MediaControlsImpl::makeTransparent() { |
| 515 m_panel->makeTransparent(); | 528 m_panel->makeTransparent(); |
| 516 } | 529 } |
| 517 | 530 |
| 518 bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const { | 531 bool MediaControlsImpl::shouldHideMediaControls(unsigned behaviorFlags) const { |
| 519 // Never hide for a media element without visual representation. | 532 // Never hide for a media element without visual representation. |
| 520 if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() || | 533 if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() || |
| 521 mediaElement().isPlayingRemotely()) { | 534 mediaElement().isPlayingRemotely()) { |
| 522 return false; | 535 return false; |
| 523 } | 536 } |
| 524 | 537 |
| 525 // Keep the controls visible as long as the timer is running. | 538 // Keep the controls visible as long as the timer is running. |
| 526 const bool ignoreWaitForTimer = behaviorFlags & IgnoreWaitForTimer; | 539 const bool ignoreWaitForTimer = behaviorFlags & IgnoreWaitForTimer; |
| 527 if (!ignoreWaitForTimer && m_keepShowingUntilTimerFires) | 540 if (!ignoreWaitForTimer && m_keepShowingUntilTimerFires) |
| 528 return false; | 541 return false; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 546 return false; | 559 return false; |
| 547 } | 560 } |
| 548 | 561 |
| 549 // Don't hide the media controls when a panel is showing. | 562 // Don't hide the media controls when a panel is showing. |
| 550 if (m_textTrackList->isWanted() || m_overflowList->isWanted()) | 563 if (m_textTrackList->isWanted() || m_overflowList->isWanted()) |
| 551 return false; | 564 return false; |
| 552 | 565 |
| 553 return true; | 566 return true; |
| 554 } | 567 } |
| 555 | 568 |
| 556 void MediaControls::updatePlayState() { | 569 void MediaControlsImpl::updatePlayState() { |
| 557 if (m_isPausedForScrubbing) | 570 if (m_isPausedForScrubbing) |
| 558 return; | 571 return; |
| 559 | 572 |
| 560 if (m_overlayPlayButton) | 573 if (m_overlayPlayButton) |
| 561 m_overlayPlayButton->updateDisplayType(); | 574 m_overlayPlayButton->updateDisplayType(); |
| 562 m_playButton->updateDisplayType(); | 575 m_playButton->updateDisplayType(); |
| 563 } | 576 } |
| 564 | 577 |
| 565 void MediaControls::beginScrubbing() { | 578 void MediaControlsImpl::beginScrubbing() { |
| 566 if (!mediaElement().paused()) { | 579 if (!mediaElement().paused()) { |
| 567 m_isPausedForScrubbing = true; | 580 m_isPausedForScrubbing = true; |
| 568 mediaElement().pause(); | 581 mediaElement().pause(); |
| 569 } | 582 } |
| 570 } | 583 } |
| 571 | 584 |
| 572 void MediaControls::endScrubbing() { | 585 void MediaControlsImpl::endScrubbing() { |
| 573 if (m_isPausedForScrubbing) { | 586 if (m_isPausedForScrubbing) { |
| 574 m_isPausedForScrubbing = false; | 587 m_isPausedForScrubbing = false; |
| 575 if (mediaElement().paused()) | 588 if (mediaElement().paused()) |
| 576 mediaElement().play(); | 589 mediaElement().play(); |
| 577 } | 590 } |
| 578 } | 591 } |
| 579 | 592 |
| 580 void MediaControls::updateCurrentTimeDisplay() { | 593 void MediaControlsImpl::updateCurrentTimeDisplay() { |
| 581 double now = mediaElement().currentTime(); | 594 double now = mediaElement().currentTime(); |
| 582 double duration = mediaElement().duration(); | 595 double duration = mediaElement().duration(); |
| 583 | 596 |
| 584 // Allow the theme to format the time. | 597 // Allow the theme to format the time. |
| 585 m_currentTimeDisplay->setInnerText( | 598 m_currentTimeDisplay->setInnerText( |
| 586 LayoutTheme::theme().formatMediaControlsCurrentTime(now, duration), | 599 LayoutTheme::theme().formatMediaControlsCurrentTime(now, duration), |
| 587 IGNORE_EXCEPTION_FOR_TESTING); | 600 IGNORE_EXCEPTION_FOR_TESTING); |
| 588 m_currentTimeDisplay->setCurrentValue(now); | 601 m_currentTimeDisplay->setCurrentValue(now); |
| 589 } | 602 } |
| 590 | 603 |
| 591 void MediaControls::toggleTextTrackList() { | 604 void MediaControlsImpl::toggleTextTrackList() { |
| 592 if (!mediaElement().hasClosedCaptions()) { | 605 if (!mediaElement().hasClosedCaptions()) { |
| 593 m_textTrackList->setVisible(false); | 606 m_textTrackList->setVisible(false); |
| 594 return; | 607 return; |
| 595 } | 608 } |
| 596 | 609 |
| 597 if (!m_textTrackList->isWanted()) | 610 if (!m_textTrackList->isWanted()) |
| 598 m_windowEventListener->start(); | 611 m_windowEventListener->start(); |
| 599 | 612 |
| 600 m_textTrackList->setVisible(!m_textTrackList->isWanted()); | 613 m_textTrackList->setVisible(!m_textTrackList->isWanted()); |
| 601 } | 614 } |
| 602 | 615 |
| 603 void MediaControls::showTextTrackAtIndex(unsigned indexToEnable) { | 616 void MediaControlsImpl::showTextTrackAtIndex(unsigned indexToEnable) { |
| 604 TextTrackList* trackList = mediaElement().textTracks(); | 617 TextTrackList* trackList = mediaElement().textTracks(); |
| 605 if (indexToEnable >= trackList->length()) | 618 if (indexToEnable >= trackList->length()) |
| 606 return; | 619 return; |
| 607 TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable); | 620 TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable); |
| 608 if (track && track->canBeRendered()) | 621 if (track && track->canBeRendered()) |
| 609 track->setMode(TextTrack::showingKeyword()); | 622 track->setMode(TextTrack::showingKeyword()); |
| 610 } | 623 } |
| 611 | 624 |
| 612 void MediaControls::disableShowingTextTracks() { | 625 void MediaControlsImpl::disableShowingTextTracks() { |
| 613 TextTrackList* trackList = mediaElement().textTracks(); | 626 TextTrackList* trackList = mediaElement().textTracks(); |
| 614 for (unsigned i = 0; i < trackList->length(); ++i) { | 627 for (unsigned i = 0; i < trackList->length(); ++i) { |
| 615 TextTrack* track = trackList->anonymousIndexedGetter(i); | 628 TextTrack* track = trackList->anonymousIndexedGetter(i); |
| 616 if (track->mode() == TextTrack::showingKeyword()) | 629 if (track->mode() == TextTrack::showingKeyword()) |
| 617 track->setMode(TextTrack::disabledKeyword()); | 630 track->setMode(TextTrack::disabledKeyword()); |
| 618 } | 631 } |
| 619 } | 632 } |
| 620 | 633 |
| 621 void MediaControls::refreshCastButtonVisibility() { | 634 void MediaControlsImpl::refreshCastButtonVisibility() { |
| 622 refreshCastButtonVisibilityWithoutUpdate(); | 635 refreshCastButtonVisibilityWithoutUpdate(); |
| 623 BatchedControlUpdate batch(this); | 636 BatchedControlUpdate batch(this); |
| 624 } | 637 } |
| 625 | 638 |
| 626 void MediaControls::refreshCastButtonVisibilityWithoutUpdate() { | 639 void MediaControlsImpl::refreshCastButtonVisibilityWithoutUpdate() { |
| 627 if (!shouldShowCastButton(mediaElement())) { | 640 if (!shouldShowCastButton(mediaElement())) { |
| 628 m_castButton->setIsWanted(false); | 641 m_castButton->setIsWanted(false); |
| 629 m_overlayCastButton->setIsWanted(false); | 642 m_overlayCastButton->setIsWanted(false); |
| 630 return; | 643 return; |
| 631 } | 644 } |
| 632 | 645 |
| 633 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have | 646 // The reason for the autoplay test is that some pages (e.g. vimeo.com) have |
| 634 // an autoplay background video, which doesn't autoplay on Chrome for Android | 647 // an autoplay background video, which doesn't autoplay on Chrome for Android |
| 635 // (we prevent it) so starts paused. In such cases we don't want to | 648 // (we prevent it) so starts paused. In such cases we don't want to |
| 636 // automatically show the cast button, since it looks strange and is unlikely | 649 // automatically show the cast button, since it looks strange and is unlikely |
| (...skipping 11 matching lines...) Expand all Loading... |
| 648 // is shown, however, compute...() will take control of the | 661 // is shown, however, compute...() will take control of the |
| 649 // overlay cast button if it needs to hide it from the panel. | 662 // overlay cast button if it needs to hide it from the panel. |
| 650 m_overlayCastButton->tryShowOverlay(); | 663 m_overlayCastButton->tryShowOverlay(); |
| 651 m_castButton->setIsWanted(false); | 664 m_castButton->setIsWanted(false); |
| 652 } else if (mediaElement().shouldShowControls()) { | 665 } else if (mediaElement().shouldShowControls()) { |
| 653 m_overlayCastButton->setIsWanted(false); | 666 m_overlayCastButton->setIsWanted(false); |
| 654 m_castButton->setIsWanted(true); | 667 m_castButton->setIsWanted(true); |
| 655 } | 668 } |
| 656 } | 669 } |
| 657 | 670 |
| 658 void MediaControls::showOverlayCastButtonIfNeeded() { | 671 void MediaControlsImpl::showOverlayCastButtonIfNeeded() { |
| 659 if (mediaElement().shouldShowControls() || | 672 if (mediaElement().shouldShowControls() || |
| 660 !shouldShowCastButton(mediaElement())) | 673 !shouldShowCastButton(mediaElement())) |
| 661 return; | 674 return; |
| 662 | 675 |
| 663 m_overlayCastButton->tryShowOverlay(); | 676 m_overlayCastButton->tryShowOverlay(); |
| 664 resetHideMediaControlsTimer(); | 677 resetHideMediaControlsTimer(); |
| 665 } | 678 } |
| 666 | 679 |
| 667 void MediaControls::enterFullscreen() { | 680 void MediaControlsImpl::enterFullscreen() { |
| 668 Fullscreen::requestFullscreen(mediaElement()); | 681 Fullscreen::requestFullscreen(mediaElement()); |
| 669 } | 682 } |
| 670 | 683 |
| 671 void MediaControls::exitFullscreen() { | 684 void MediaControlsImpl::exitFullscreen() { |
| 672 Fullscreen::exitFullscreen(document()); | 685 Fullscreen::exitFullscreen(document()); |
| 673 } | 686 } |
| 674 | 687 |
| 675 void MediaControls::startedCasting() { | 688 void MediaControlsImpl::startedCasting() { |
| 676 m_castButton->setIsPlayingRemotely(true); | 689 m_castButton->setIsPlayingRemotely(true); |
| 677 m_overlayCastButton->setIsPlayingRemotely(true); | 690 m_overlayCastButton->setIsPlayingRemotely(true); |
| 678 } | 691 } |
| 679 | 692 |
| 680 void MediaControls::stoppedCasting() { | 693 void MediaControlsImpl::stoppedCasting() { |
| 681 m_castButton->setIsPlayingRemotely(false); | 694 m_castButton->setIsPlayingRemotely(false); |
| 682 m_overlayCastButton->setIsPlayingRemotely(false); | 695 m_overlayCastButton->setIsPlayingRemotely(false); |
| 683 } | 696 } |
| 684 | 697 |
| 685 void MediaControls::defaultEventHandler(Event* event) { | 698 void MediaControlsImpl::defaultEventHandler(Event* event) { |
| 686 HTMLDivElement::defaultEventHandler(event); | 699 HTMLDivElement::defaultEventHandler(event); |
| 687 | 700 |
| 688 // Do not handle events to not interfere with the rest of the page if no | 701 // Do not handle events to not interfere with the rest of the page if no |
| 689 // controls should be visible. | 702 // controls should be visible. |
| 690 if (!mediaElement().shouldShowControls()) | 703 if (!mediaElement().shouldShowControls()) |
| 691 return; | 704 return; |
| 692 | 705 |
| 693 // Add IgnoreControlsHover to m_hideTimerBehaviorFlags when we see a touch | 706 // Add IgnoreControlsHover to m_hideTimerBehaviorFlags when we see a touch |
| 694 // event, to allow the hide-timer to do the right thing when it fires. | 707 // event, to allow the hide-timer to do the right thing when it fires. |
| 695 // FIXME: Preferably we would only do this when we're actually handling the | 708 // FIXME: Preferably we would only do this when we're actually handling the |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 if (event->type() == EventTypeNames::mousemove) { | 760 if (event->type() == EventTypeNames::mousemove) { |
| 748 // When we get a mouse move, show the media controls, and start a timer | 761 // When we get a mouse move, show the media controls, and start a timer |
| 749 // that will hide the media controls after a 3 seconds without a mouse move. | 762 // that will hide the media controls after a 3 seconds without a mouse move. |
| 750 makeOpaque(); | 763 makeOpaque(); |
| 751 if (shouldHideMediaControls(IgnoreVideoHover)) | 764 if (shouldHideMediaControls(IgnoreVideoHover)) |
| 752 startHideMediaControlsTimer(); | 765 startHideMediaControlsTimer(); |
| 753 return; | 766 return; |
| 754 } | 767 } |
| 755 } | 768 } |
| 756 | 769 |
| 757 void MediaControls::hideMediaControlsTimerFired(TimerBase*) { | 770 void MediaControlsImpl::hideMediaControlsTimerFired(TimerBase*) { |
| 758 unsigned behaviorFlags = | 771 unsigned behaviorFlags = |
| 759 m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover; | 772 m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover; |
| 760 m_hideTimerBehaviorFlags = IgnoreNone; | 773 m_hideTimerBehaviorFlags = IgnoreNone; |
| 761 m_keepShowingUntilTimerFires = false; | 774 m_keepShowingUntilTimerFires = false; |
| 762 | 775 |
| 763 if (mediaElement().paused()) | 776 if (mediaElement().paused()) |
| 764 return; | 777 return; |
| 765 | 778 |
| 766 if (!shouldHideMediaControls(behaviorFlags)) | 779 if (!shouldHideMediaControls(behaviorFlags)) |
| 767 return; | 780 return; |
| 768 | 781 |
| 769 makeTransparent(); | 782 makeTransparent(); |
| 770 m_overlayCastButton->setIsWanted(false); | 783 m_overlayCastButton->setIsWanted(false); |
| 771 } | 784 } |
| 772 | 785 |
| 773 void MediaControls::startHideMediaControlsTimer() { | 786 void MediaControlsImpl::startHideMediaControlsTimer() { |
| 774 m_hideMediaControlsTimer.startOneShot( | 787 m_hideMediaControlsTimer.startOneShot( |
| 775 timeWithoutMouseMovementBeforeHidingMediaControls, BLINK_FROM_HERE); | 788 timeWithoutMouseMovementBeforeHidingMediaControls, BLINK_FROM_HERE); |
| 776 } | 789 } |
| 777 | 790 |
| 778 void MediaControls::stopHideMediaControlsTimer() { | 791 void MediaControlsImpl::stopHideMediaControlsTimer() { |
| 779 m_keepShowingUntilTimerFires = false; | 792 m_keepShowingUntilTimerFires = false; |
| 780 m_hideMediaControlsTimer.stop(); | 793 m_hideMediaControlsTimer.stop(); |
| 781 } | 794 } |
| 782 | 795 |
| 783 void MediaControls::resetHideMediaControlsTimer() { | 796 void MediaControlsImpl::resetHideMediaControlsTimer() { |
| 784 stopHideMediaControlsTimer(); | 797 stopHideMediaControlsTimer(); |
| 785 if (!mediaElement().paused()) | 798 if (!mediaElement().paused()) |
| 786 startHideMediaControlsTimer(); | 799 startHideMediaControlsTimer(); |
| 787 } | 800 } |
| 788 | 801 |
| 789 bool MediaControls::containsRelatedTarget(Event* event) { | 802 bool MediaControlsImpl::containsRelatedTarget(Event* event) { |
| 790 if (!event->isMouseEvent()) | 803 if (!event->isMouseEvent()) |
| 791 return false; | 804 return false; |
| 792 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); | 805 EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget(); |
| 793 if (!relatedTarget) | 806 if (!relatedTarget) |
| 794 return false; | 807 return false; |
| 795 return contains(relatedTarget->toNode()); | 808 return contains(relatedTarget->toNode()); |
| 796 } | 809 } |
| 797 | 810 |
| 798 void MediaControls::onVolumeChange() { | 811 void MediaControlsImpl::onVolumeChange() { |
| 799 m_muteButton->updateDisplayType(); | 812 m_muteButton->updateDisplayType(); |
| 800 m_volumeSlider->setVolume(mediaElement().muted() ? 0 | 813 m_volumeSlider->setVolume(mediaElement().muted() ? 0 |
| 801 : mediaElement().volume()); | 814 : mediaElement().volume()); |
| 802 | 815 |
| 803 // Update visibility of volume controls. | 816 // Update visibility of volume controls. |
| 804 // TODO(mlamouri): it should not be part of the volumechange handling because | 817 // TODO(mlamouri): it should not be part of the volumechange handling because |
| 805 // it is using audio availability as input. | 818 // it is using audio availability as input. |
| 806 BatchedControlUpdate batch(this); | 819 BatchedControlUpdate batch(this); |
| 807 m_volumeSlider->setIsWanted(mediaElement().hasAudio() && | 820 m_volumeSlider->setIsWanted(mediaElement().hasAudio() && |
| 808 !preferHiddenVolumeControls(document())); | 821 !preferHiddenVolumeControls(document())); |
| 809 m_muteButton->setIsWanted(mediaElement().hasAudio()); | 822 m_muteButton->setIsWanted(mediaElement().hasAudio()); |
| 810 } | 823 } |
| 811 | 824 |
| 812 void MediaControls::onFocusIn() { | 825 void MediaControlsImpl::onFocusIn() { |
| 813 if (!mediaElement().shouldShowControls()) | 826 if (!mediaElement().shouldShowControls()) |
| 814 return; | 827 return; |
| 815 | 828 |
| 816 show(); | 829 show(); |
| 817 resetHideMediaControlsTimer(); | 830 resetHideMediaControlsTimer(); |
| 818 } | 831 } |
| 819 | 832 |
| 820 void MediaControls::onTimeUpdate() { | 833 void MediaControlsImpl::onTimeUpdate() { |
| 821 m_timeline->setPosition(mediaElement().currentTime()); | 834 m_timeline->setPosition(mediaElement().currentTime()); |
| 822 updateCurrentTimeDisplay(); | 835 updateCurrentTimeDisplay(); |
| 823 | 836 |
| 824 // 'timeupdate' might be called in a paused state. The controls should not | 837 // 'timeupdate' might be called in a paused state. The controls should not |
| 825 // become transparent in that case. | 838 // become transparent in that case. |
| 826 if (mediaElement().paused()) { | 839 if (mediaElement().paused()) { |
| 827 makeOpaque(); | 840 makeOpaque(); |
| 828 return; | 841 return; |
| 829 } | 842 } |
| 830 | 843 |
| 831 if (isVisible() && shouldHideMediaControls()) | 844 if (isVisible() && shouldHideMediaControls()) |
| 832 makeTransparent(); | 845 makeTransparent(); |
| 833 } | 846 } |
| 834 | 847 |
| 835 void MediaControls::onDurationChange() { | 848 void MediaControlsImpl::onDurationChange() { |
| 836 const double duration = mediaElement().duration(); | 849 const double duration = mediaElement().duration(); |
| 837 | 850 |
| 838 // Update the displayed current time/duration. | 851 // Update the displayed current time/duration. |
| 839 m_durationDisplay->setTextContent( | 852 m_durationDisplay->setTextContent( |
| 840 LayoutTheme::theme().formatMediaControlsTime(duration)); | 853 LayoutTheme::theme().formatMediaControlsTime(duration)); |
| 841 m_durationDisplay->setCurrentValue(duration); | 854 m_durationDisplay->setCurrentValue(duration); |
| 842 updateCurrentTimeDisplay(); | 855 updateCurrentTimeDisplay(); |
| 843 | 856 |
| 844 // Update the timeline (the UI with the seek marker). | 857 // Update the timeline (the UI with the seek marker). |
| 845 m_timeline->setDuration(duration); | 858 m_timeline->setDuration(duration); |
| 846 } | 859 } |
| 847 | 860 |
| 848 void MediaControls::onPlay() { | 861 void MediaControlsImpl::onPlay() { |
| 849 updatePlayState(); | 862 updatePlayState(); |
| 850 m_timeline->setPosition(mediaElement().currentTime()); | 863 m_timeline->setPosition(mediaElement().currentTime()); |
| 851 updateCurrentTimeDisplay(); | 864 updateCurrentTimeDisplay(); |
| 852 | 865 |
| 853 startHideMediaControlsTimer(); | 866 startHideMediaControlsTimer(); |
| 854 } | 867 } |
| 855 | 868 |
| 856 void MediaControls::onPause() { | 869 void MediaControlsImpl::onPause() { |
| 857 updatePlayState(); | 870 updatePlayState(); |
| 858 m_timeline->setPosition(mediaElement().currentTime()); | 871 m_timeline->setPosition(mediaElement().currentTime()); |
| 859 updateCurrentTimeDisplay(); | 872 updateCurrentTimeDisplay(); |
| 860 makeOpaque(); | 873 makeOpaque(); |
| 861 | 874 |
| 862 stopHideMediaControlsTimer(); | 875 stopHideMediaControlsTimer(); |
| 863 } | 876 } |
| 864 | 877 |
| 865 void MediaControls::onTextTracksAddedOrRemoved() { | 878 void MediaControlsImpl::onTextTracksAddedOrRemoved() { |
| 866 m_toggleClosedCaptionsButton->setIsWanted(mediaElement().hasClosedCaptions()); | 879 m_toggleClosedCaptionsButton->setIsWanted(mediaElement().hasClosedCaptions()); |
| 867 BatchedControlUpdate batch(this); | 880 BatchedControlUpdate batch(this); |
| 868 } | 881 } |
| 869 | 882 |
| 870 void MediaControls::onTextTracksChanged() { | 883 void MediaControlsImpl::onTextTracksChanged() { |
| 871 m_toggleClosedCaptionsButton->updateDisplayType(); | 884 m_toggleClosedCaptionsButton->updateDisplayType(); |
| 872 } | 885 } |
| 873 | 886 |
| 874 void MediaControls::onError() { | 887 void MediaControlsImpl::onError() { |
| 875 // TODO(mlamouri): we should only change the aspects of the control that need | 888 // TODO(mlamouri): we should only change the aspects of the control that need |
| 876 // to be changed. | 889 // to be changed. |
| 877 reset(); | 890 reset(); |
| 878 } | 891 } |
| 879 | 892 |
| 880 void MediaControls::onLoadedMetadata() { | 893 void MediaControlsImpl::onLoadedMetadata() { |
| 881 // TODO(mlamouri): we should only change the aspects of the control that need | 894 // TODO(mlamouri): we should only change the aspects of the control that need |
| 882 // to be changed. | 895 // to be changed. |
| 883 reset(); | 896 reset(); |
| 884 } | 897 } |
| 885 | 898 |
| 886 void MediaControls::onEnteredFullscreen() { | 899 void MediaControlsImpl::onEnteredFullscreen() { |
| 887 m_fullscreenButton->setIsFullscreen(true); | 900 m_fullscreenButton->setIsFullscreen(true); |
| 888 stopHideMediaControlsTimer(); | 901 stopHideMediaControlsTimer(); |
| 889 startHideMediaControlsTimer(); | 902 startHideMediaControlsTimer(); |
| 890 } | 903 } |
| 891 | 904 |
| 892 void MediaControls::onExitedFullscreen() { | 905 void MediaControlsImpl::onExitedFullscreen() { |
| 893 m_fullscreenButton->setIsFullscreen(false); | 906 m_fullscreenButton->setIsFullscreen(false); |
| 894 stopHideMediaControlsTimer(); | 907 stopHideMediaControlsTimer(); |
| 895 startHideMediaControlsTimer(); | 908 startHideMediaControlsTimer(); |
| 896 } | 909 } |
| 897 | 910 |
| 898 void MediaControls::notifyElementSizeChanged(ClientRect* newSize) { | 911 void MediaControlsImpl::notifyElementSizeChanged(ClientRect* newSize) { |
| 899 // Note that this code permits a bad frame on resize, since it is | 912 // Note that this code permits a bad frame on resize, since it is |
| 900 // run after the relayout / paint happens. It would be great to improve | 913 // run after the relayout / paint happens. It would be great to improve |
| 901 // this, but it would be even greater to move this code entirely to | 914 // this, but it would be even greater to move this code entirely to |
| 902 // JS and fix it there. | 915 // JS and fix it there. |
| 903 | 916 |
| 904 IntSize oldSize = m_size; | 917 IntSize oldSize = m_size; |
| 905 m_size.setWidth(newSize->width()); | 918 m_size.setWidth(newSize->width()); |
| 906 m_size.setHeight(newSize->height()); | 919 m_size.setHeight(newSize->height()); |
| 907 | 920 |
| 908 // Adjust for effective zoom. | 921 // Adjust for effective zoom. |
| 909 if (m_panel->layoutObject() && m_panel->layoutObject()->style()) { | 922 if (m_panel->layoutObject() && m_panel->layoutObject()->style()) { |
| 910 m_size.setWidth(ceil(m_size.width() / | 923 m_size.setWidth(ceil(m_size.width() / |
| 911 m_panel->layoutObject()->style()->effectiveZoom())); | 924 m_panel->layoutObject()->style()->effectiveZoom())); |
| 912 m_size.setHeight(ceil(m_size.height() / | 925 m_size.setHeight(ceil(m_size.height() / |
| 913 m_panel->layoutObject()->style()->effectiveZoom())); | 926 m_panel->layoutObject()->style()->effectiveZoom())); |
| 914 } | 927 } |
| 915 | 928 |
| 916 // Don't bother to do any work if this matches the most recent size. | 929 // Don't bother to do any work if this matches the most recent size. |
| 917 if (oldSize != m_size) | 930 if (oldSize != m_size) |
| 918 m_elementSizeChangedTimer.startOneShot(0, BLINK_FROM_HERE); | 931 m_elementSizeChangedTimer.startOneShot(0, BLINK_FROM_HERE); |
| 919 } | 932 } |
| 920 | 933 |
| 921 void MediaControls::elementSizeChangedTimerFired(TimerBase*) { | 934 void MediaControlsImpl::elementSizeChangedTimerFired(TimerBase*) { |
| 922 computeWhichControlsFit(); | 935 computeWhichControlsFit(); |
| 923 } | 936 } |
| 924 | 937 |
| 925 void MediaControls::computeWhichControlsFit() { | 938 void MediaControlsImpl::computeWhichControlsFit() { |
| 926 // Hide all controls that don't fit, and show the ones that do. | 939 // Hide all controls that don't fit, and show the ones that do. |
| 927 // This might be better suited for a layout, but since JS media controls | 940 // This might be better suited for a layout, but since JS media controls |
| 928 // won't benefit from that anwyay, we just do it here like JS will. | 941 // won't benefit from that anwyay, we just do it here like JS will. |
| 929 | 942 |
| 930 // Controls that we'll hide / show, in order of decreasing priority. | 943 // Controls that we'll hide / show, in order of decreasing priority. |
| 931 MediaControlElement* elements[] = { | 944 MediaControlElement* elements[] = { |
| 932 // Exclude m_overflowMenu; we handle it specially. | 945 // Exclude m_overflowMenu; we handle it specially. |
| 933 m_playButton.get(), | 946 m_playButton.get(), |
| 934 m_fullscreenButton.get(), | 947 m_fullscreenButton.get(), |
| 935 m_downloadButton.get(), | 948 m_downloadButton.get(), |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 } | 1041 } |
| 1029 | 1042 |
| 1030 // Decide if the overlay play button fits. | 1043 // Decide if the overlay play button fits. |
| 1031 if (m_overlayPlayButton) { | 1044 if (m_overlayPlayButton) { |
| 1032 bool doesFit = m_size.width() >= kMinWidthForOverlayPlayButton && | 1045 bool doesFit = m_size.width() >= kMinWidthForOverlayPlayButton && |
| 1033 m_size.height() >= kMinHeightForOverlayPlayButton; | 1046 m_size.height() >= kMinHeightForOverlayPlayButton; |
| 1034 m_overlayPlayButton->setDoesFit(doesFit); | 1047 m_overlayPlayButton->setDoesFit(doesFit); |
| 1035 } | 1048 } |
| 1036 } | 1049 } |
| 1037 | 1050 |
| 1038 void MediaControls::invalidate(Element* element) { | 1051 void MediaControlsImpl::invalidate(Element* element) { |
| 1039 if (!element) | 1052 if (!element) |
| 1040 return; | 1053 return; |
| 1041 | 1054 |
| 1042 if (LayoutObject* layoutObject = element->layoutObject()) | 1055 if (LayoutObject* layoutObject = element->layoutObject()) { |
| 1043 layoutObject | 1056 layoutObject |
| 1044 ->setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); | 1057 ->setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); |
| 1058 } |
| 1045 } | 1059 } |
| 1046 | 1060 |
| 1047 void MediaControls::networkStateChanged() { | 1061 void MediaControlsImpl::networkStateChanged() { |
| 1048 invalidate(m_playButton); | 1062 invalidate(m_playButton); |
| 1049 invalidate(m_overlayPlayButton); | 1063 invalidate(m_overlayPlayButton); |
| 1050 invalidate(m_muteButton); | 1064 invalidate(m_muteButton); |
| 1051 invalidate(m_fullscreenButton); | 1065 invalidate(m_fullscreenButton); |
| 1052 invalidate(m_downloadButton); | 1066 invalidate(m_downloadButton); |
| 1053 invalidate(m_timeline); | 1067 invalidate(m_timeline); |
| 1054 invalidate(m_volumeSlider); | 1068 invalidate(m_volumeSlider); |
| 1055 | 1069 |
| 1056 // Update the display state of the download button in case we now have a | 1070 // Update the display state of the download button in case we now have a |
| 1057 // source or no longer have a source. | 1071 // source or no longer have a source. |
| 1058 m_downloadButton->setIsWanted( | 1072 m_downloadButton->setIsWanted( |
| 1059 m_downloadButton->shouldDisplayDownloadButton()); | 1073 m_downloadButton->shouldDisplayDownloadButton()); |
| 1060 } | 1074 } |
| 1061 | 1075 |
| 1062 bool MediaControls::overflowMenuVisible() { | 1076 bool MediaControlsImpl::overflowMenuVisible() { |
| 1063 return m_overflowList ? m_overflowList->isWanted() : false; | 1077 return m_overflowList ? m_overflowList->isWanted() : false; |
| 1064 } | 1078 } |
| 1065 | 1079 |
| 1066 void MediaControls::toggleOverflowMenu() { | 1080 void MediaControlsImpl::toggleOverflowMenu() { |
| 1067 DCHECK(m_overflowList); | 1081 DCHECK(m_overflowList); |
| 1068 | 1082 |
| 1069 if (!m_overflowList->isWanted()) | 1083 if (!m_overflowList->isWanted()) |
| 1070 m_windowEventListener->start(); | 1084 m_windowEventListener->start(); |
| 1071 m_overflowList->setIsWanted(!m_overflowList->isWanted()); | 1085 m_overflowList->setIsWanted(!m_overflowList->isWanted()); |
| 1072 } | 1086 } |
| 1073 | 1087 |
| 1074 void MediaControls::hideAllMenus() { | 1088 void MediaControlsImpl::hideAllMenus() { |
| 1075 m_windowEventListener->stop(); | 1089 m_windowEventListener->stop(); |
| 1076 | 1090 |
| 1077 if (m_overflowList->isWanted()) | 1091 if (m_overflowList->isWanted()) |
| 1078 m_overflowList->setIsWanted(false); | 1092 m_overflowList->setIsWanted(false); |
| 1079 if (m_textTrackList->isWanted()) | 1093 if (m_textTrackList->isWanted()) |
| 1080 m_textTrackList->setVisible(false); | 1094 m_textTrackList->setVisible(false); |
| 1081 } | 1095 } |
| 1082 | 1096 |
| 1083 DEFINE_TRACE(MediaControls) { | 1097 DEFINE_TRACE(MediaControlsImpl) { |
| 1084 visitor->trace(m_resizeObserver); | 1098 visitor->trace(m_resizeObserver); |
| 1085 visitor->trace(m_mediaElement); | |
| 1086 visitor->trace(m_panel); | 1099 visitor->trace(m_panel); |
| 1087 visitor->trace(m_overlayPlayButton); | 1100 visitor->trace(m_overlayPlayButton); |
| 1088 visitor->trace(m_overlayEnclosure); | 1101 visitor->trace(m_overlayEnclosure); |
| 1089 visitor->trace(m_playButton); | 1102 visitor->trace(m_playButton); |
| 1090 visitor->trace(m_currentTimeDisplay); | 1103 visitor->trace(m_currentTimeDisplay); |
| 1091 visitor->trace(m_timeline); | 1104 visitor->trace(m_timeline); |
| 1092 visitor->trace(m_muteButton); | 1105 visitor->trace(m_muteButton); |
| 1093 visitor->trace(m_volumeSlider); | 1106 visitor->trace(m_volumeSlider); |
| 1094 visitor->trace(m_toggleClosedCaptionsButton); | 1107 visitor->trace(m_toggleClosedCaptionsButton); |
| 1095 visitor->trace(m_fullscreenButton); | 1108 visitor->trace(m_fullscreenButton); |
| 1096 visitor->trace(m_downloadButton); | 1109 visitor->trace(m_downloadButton); |
| 1097 visitor->trace(m_durationDisplay); | 1110 visitor->trace(m_durationDisplay); |
| 1098 visitor->trace(m_enclosure); | 1111 visitor->trace(m_enclosure); |
| 1099 visitor->trace(m_textTrackList); | 1112 visitor->trace(m_textTrackList); |
| 1100 visitor->trace(m_overflowMenu); | 1113 visitor->trace(m_overflowMenu); |
| 1101 visitor->trace(m_overflowList); | 1114 visitor->trace(m_overflowList); |
| 1102 visitor->trace(m_castButton); | 1115 visitor->trace(m_castButton); |
| 1103 visitor->trace(m_overlayCastButton); | 1116 visitor->trace(m_overlayCastButton); |
| 1104 visitor->trace(m_mediaEventListener); | 1117 visitor->trace(m_mediaEventListener); |
| 1105 visitor->trace(m_windowEventListener); | 1118 visitor->trace(m_windowEventListener); |
| 1106 visitor->trace(m_orientationLockDelegate); | 1119 visitor->trace(m_orientationLockDelegate); |
| 1120 MediaControls::trace(visitor); |
| 1107 HTMLDivElement::trace(visitor); | 1121 HTMLDivElement::trace(visitor); |
| 1108 } | 1122 } |
| 1109 | 1123 |
| 1110 } // namespace blink | 1124 } // namespace blink |
| OLD | NEW |