| Index: third_party/WebKit/Source/core/html/shadow/MediaControls.cpp
|
| diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp
|
| deleted file mode 100644
|
| index 811996a545f6752fcf5a449b696119c926d17b1c..0000000000000000000000000000000000000000
|
| --- a/third_party/WebKit/Source/core/html/shadow/MediaControls.cpp
|
| +++ /dev/null
|
| @@ -1,1110 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
|
| - * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions
|
| - * are met:
|
| - * 1. Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright
|
| - * notice, this list of conditions and the following disclaimer in the
|
| - * documentation and/or other materials provided with the distribution.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
| - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
| - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
| - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
| - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
| - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
| - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "core/html/shadow/MediaControls.h"
|
| -
|
| -#include "bindings/core/v8/ExceptionState.h"
|
| -#include "core/dom/ClientRect.h"
|
| -#include "core/dom/Fullscreen.h"
|
| -#include "core/dom/ResizeObserver.h"
|
| -#include "core/dom/ResizeObserverCallback.h"
|
| -#include "core/dom/ResizeObserverEntry.h"
|
| -#include "core/dom/TaskRunnerHelper.h"
|
| -#include "core/events/MouseEvent.h"
|
| -#include "core/frame/Settings.h"
|
| -#include "core/frame/UseCounter.h"
|
| -#include "core/html/HTMLMediaElement.h"
|
| -#include "core/html/HTMLVideoElement.h"
|
| -#include "core/html/media/HTMLMediaElementControlsList.h"
|
| -#include "core/html/shadow/MediaControlsMediaEventListener.h"
|
| -#include "core/html/shadow/MediaControlsOrientationLockDelegate.h"
|
| -#include "core/html/shadow/MediaControlsWindowEventListener.h"
|
| -#include "core/html/track/TextTrackContainer.h"
|
| -#include "core/html/track/TextTrackList.h"
|
| -#include "core/layout/LayoutObject.h"
|
| -#include "core/layout/LayoutTheme.h"
|
| -#include "platform/EventDispatchForbiddenScope.h"
|
| -
|
| -namespace blink {
|
| -
|
| -namespace {
|
| -
|
| -// TODO(steimel): should have better solution than hard-coding pixel values.
|
| -// Defined in core/css/mediaControls.css, core/css/mediaControlsAndroid.css,
|
| -// and core/paint/MediaControlsPainter.cpp.
|
| -constexpr int kOverlayPlayButtonWidth = 48;
|
| -constexpr int kOverlayPlayButtonHeight = 48;
|
| -constexpr int kOverlayBottomMargin = 10;
|
| -constexpr int kAndroidMediaPanelHeight = 48;
|
| -
|
| -constexpr int kMinWidthForOverlayPlayButton = kOverlayPlayButtonWidth;
|
| -constexpr int kMinHeightForOverlayPlayButton = kOverlayPlayButtonHeight +
|
| - kAndroidMediaPanelHeight +
|
| - (2 * kOverlayBottomMargin);
|
| -
|
| -} // anonymous namespace
|
| -
|
| -// If you change this value, then also update the corresponding value in
|
| -// LayoutTests/media/media-controls.js.
|
| -static const double timeWithoutMouseMovementBeforeHidingMediaControls = 3;
|
| -
|
| -static bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) {
|
| - // Unconditionally allow the user to exit fullscreen if we are in it
|
| - // now. Especially on android, when we might not yet know if
|
| - // fullscreen is supported, we sometimes guess incorrectly and show
|
| - // the button earlier, and we don't want to remove it here if the
|
| - // user chose to enter fullscreen. crbug.com/500732 .
|
| - if (mediaElement.isFullscreen())
|
| - return true;
|
| -
|
| - if (!mediaElement.isHTMLVideoElement())
|
| - return false;
|
| -
|
| - if (!mediaElement.hasVideo())
|
| - return false;
|
| -
|
| - if (!Fullscreen::fullscreenEnabled(mediaElement.document()))
|
| - return false;
|
| -
|
| - if (mediaElement.controlsListInternal()->shouldHideFullscreen()) {
|
| - UseCounter::count(mediaElement.document(),
|
| - UseCounter::HTMLMediaElementControlsListNoFullscreen);
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -static bool shouldShowCastButton(HTMLMediaElement& mediaElement) {
|
| - 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.document();
|
| - if (document.settings() && !document.settings()->getMediaControlsEnabled())
|
| - return false;
|
| -
|
| - // The page disabled the button via the attribute.
|
| - if (mediaElement.controlsListInternal()->shouldHideRemotePlayback()) {
|
| - UseCounter::count(mediaElement.document(),
|
| - UseCounter::HTMLMediaElementControlsListNoRemotePlayback);
|
| - return false;
|
| - }
|
| -
|
| - return mediaElement.hasRemoteRoutes();
|
| -}
|
| -
|
| -static bool preferHiddenVolumeControls(const Document& document) {
|
| - return !document.settings() ||
|
| - document.settings()->getPreferHiddenVolumeControls();
|
| -}
|
| -
|
| -class MediaControls::BatchedControlUpdate {
|
| - WTF_MAKE_NONCOPYABLE(BatchedControlUpdate);
|
| - STACK_ALLOCATED();
|
| -
|
| - public:
|
| - explicit BatchedControlUpdate(MediaControls* controls)
|
| - : m_controls(controls) {
|
| - DCHECK(isMainThread());
|
| - DCHECK_GE(s_batchDepth, 0);
|
| - ++s_batchDepth;
|
| - }
|
| - ~BatchedControlUpdate() {
|
| - DCHECK(isMainThread());
|
| - DCHECK_GT(s_batchDepth, 0);
|
| - if (!(--s_batchDepth))
|
| - m_controls->computeWhichControlsFit();
|
| - }
|
| -
|
| - private:
|
| - Member<MediaControls> m_controls;
|
| - static int s_batchDepth;
|
| -};
|
| -
|
| -// Count of number open batches for controls visibility.
|
| -int MediaControls::BatchedControlUpdate::s_batchDepth = 0;
|
| -
|
| -class MediaControls::MediaControlsResizeObserverCallback final
|
| - : public ResizeObserverCallback {
|
| - public:
|
| - explicit MediaControlsResizeObserverCallback(MediaControls* controls)
|
| - : m_controls(controls) {
|
| - DCHECK(controls);
|
| - }
|
| - ~MediaControlsResizeObserverCallback() override = default;
|
| -
|
| - void handleEvent(const HeapVector<Member<ResizeObserverEntry>>& entries,
|
| - ResizeObserver* observer) override {
|
| - DCHECK_EQ(1u, entries.size());
|
| - DCHECK_EQ(entries[0]->target(), m_controls->m_mediaElement);
|
| - m_controls->notifyElementSizeChanged(entries[0]->contentRect());
|
| - }
|
| -
|
| - DEFINE_INLINE_TRACE() {
|
| - visitor->trace(m_controls);
|
| - ResizeObserverCallback::trace(visitor);
|
| - }
|
| -
|
| - private:
|
| - Member<MediaControls> m_controls;
|
| -};
|
| -
|
| -MediaControls::MediaControls(HTMLMediaElement& mediaElement)
|
| - : HTMLDivElement(mediaElement.document()),
|
| - m_mediaElement(&mediaElement),
|
| - m_overlayEnclosure(nullptr),
|
| - m_overlayPlayButton(nullptr),
|
| - m_overlayCastButton(nullptr),
|
| - m_enclosure(nullptr),
|
| - m_panel(nullptr),
|
| - m_playButton(nullptr),
|
| - m_timeline(nullptr),
|
| - m_currentTimeDisplay(nullptr),
|
| - m_durationDisplay(nullptr),
|
| - m_muteButton(nullptr),
|
| - m_volumeSlider(nullptr),
|
| - m_toggleClosedCaptionsButton(nullptr),
|
| - m_textTrackList(nullptr),
|
| - m_overflowList(nullptr),
|
| - m_castButton(nullptr),
|
| - m_fullscreenButton(nullptr),
|
| - m_downloadButton(nullptr),
|
| - m_mediaEventListener(new MediaControlsMediaEventListener(this)),
|
| - m_windowEventListener(MediaControlsWindowEventListener::create(
|
| - this,
|
| - WTF::bind(&MediaControls::hideAllMenus, wrapWeakPersistent(this)))),
|
| - m_orientationLockDelegate(nullptr),
|
| - m_hideMediaControlsTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer,
|
| - &mediaElement.document()),
|
| - this,
|
| - &MediaControls::hideMediaControlsTimerFired),
|
| - m_hideTimerBehaviorFlags(IgnoreNone),
|
| - m_isMouseOverControls(false),
|
| - m_isPausedForScrubbing(false),
|
| - m_resizeObserver(ResizeObserver::create(
|
| - mediaElement.document(),
|
| - new MediaControlsResizeObserverCallback(this))),
|
| - m_elementSizeChangedTimer(TaskRunnerHelper::get(TaskType::UnspecedTimer,
|
| - &mediaElement.document()),
|
| - this,
|
| - &MediaControls::elementSizeChangedTimerFired),
|
| - m_keepShowingUntilTimerFires(false) {
|
| - m_resizeObserver->observe(m_mediaElement);
|
| -}
|
| -
|
| -MediaControls* MediaControls::create(HTMLMediaElement& mediaElement,
|
| - ShadowRoot& shadowRoot) {
|
| - MediaControls* controls = new MediaControls(mediaElement);
|
| - controls->setShadowPseudoId(AtomicString("-webkit-media-controls"));
|
| - controls->initializeControls();
|
| - controls->reset();
|
| -
|
| - // Initialize the orientation lock when going fullscreen feature.
|
| - if (RuntimeEnabledFeatures::videoFullscreenOrientationLockEnabled() &&
|
| - mediaElement.isHTMLVideoElement()) {
|
| - controls->m_orientationLockDelegate =
|
| - new MediaControlsOrientationLockDelegate(
|
| - toHTMLVideoElement(mediaElement));
|
| - }
|
| -
|
| - shadowRoot.appendChild(controls);
|
| - return controls;
|
| -}
|
| -
|
| -// The media controls DOM structure looks like:
|
| -//
|
| -// MediaControls
|
| -// (-webkit-media-controls)
|
| -// +-MediaControlOverlayEnclosureElement
|
| -// | (-webkit-media-controls-overlay-enclosure)
|
| -// | +-MediaControlOverlayPlayButtonElement
|
| -// | | (-webkit-media-controls-overlay-play-button)
|
| -// | | {if mediaControlsOverlayPlayButtonEnabled}
|
| -// | \-MediaControlCastButtonElement
|
| -// | (-internal-media-controls-overlay-cast-button)
|
| -// \-MediaControlPanelEnclosureElement
|
| -// | (-webkit-media-controls-enclosure)
|
| -// \-MediaControlPanelElement
|
| -// | (-webkit-media-controls-panel)
|
| -// +-MediaControlPlayButtonElement
|
| -// | (-webkit-media-controls-play-button)
|
| -// +-MediaControlCurrentTimeDisplayElement
|
| -// | (-webkit-media-controls-current-time-display)
|
| -// +-MediaControlTimeRemainingDisplayElement
|
| -// | (-webkit-media-controls-time-remaining-display)
|
| -// +-MediaControlTimelineElement
|
| -// | (-webkit-media-controls-timeline)
|
| -// +-MediaControlMuteButtonElement
|
| -// | (-webkit-media-controls-mute-button)
|
| -// +-MediaControlVolumeSliderElement
|
| -// | (-webkit-media-controls-volume-slider)
|
| -// +-MediaControlFullscreenButtonElement
|
| -// | (-webkit-media-controls-fullscreen-button)
|
| -// +-MediaControlDownloadButtonElement
|
| -// | (-internal-media-controls-download-button)
|
| -// +-MediaControlToggleClosedCaptionsButtonElement
|
| -// | (-webkit-media-controls-toggle-closed-captions-button)
|
| -// \-MediaControlCastButtonElement
|
| -// (-internal-media-controls-cast-button)
|
| -// +-MediaControlTextTrackListElement
|
| -// | (-internal-media-controls-text-track-list)
|
| -// | {for each renderable text track}
|
| -// \-MediaControlTextTrackListItem
|
| -// | (-internal-media-controls-text-track-list-item)
|
| -// +-MediaControlTextTrackListItemInput
|
| -// | (-internal-media-controls-text-track-list-item-input)
|
| -// +-MediaControlTextTrackListItemCaptions
|
| -// | (-internal-media-controls-text-track-list-kind-captions)
|
| -// +-MediaControlTextTrackListItemSubtitles
|
| -// (-internal-media-controls-text-track-list-kind-subtitles)
|
| -void MediaControls::initializeControls() {
|
| - MediaControlOverlayEnclosureElement* overlayEnclosure =
|
| - MediaControlOverlayEnclosureElement::create(*this);
|
| -
|
| - if (RuntimeEnabledFeatures::mediaControlsOverlayPlayButtonEnabled()) {
|
| - MediaControlOverlayPlayButtonElement* overlayPlayButton =
|
| - MediaControlOverlayPlayButtonElement::create(*this);
|
| - m_overlayPlayButton = overlayPlayButton;
|
| - overlayEnclosure->appendChild(overlayPlayButton);
|
| - }
|
| -
|
| - MediaControlCastButtonElement* overlayCastButton =
|
| - MediaControlCastButtonElement::create(*this, true);
|
| - m_overlayCastButton = overlayCastButton;
|
| - overlayEnclosure->appendChild(overlayCastButton);
|
| -
|
| - m_overlayEnclosure = overlayEnclosure;
|
| - appendChild(overlayEnclosure);
|
| -
|
| - // Create an enclosing element for the panel so we can visually offset the
|
| - // controls correctly.
|
| - MediaControlPanelEnclosureElement* enclosure =
|
| - MediaControlPanelEnclosureElement::create(*this);
|
| -
|
| - MediaControlPanelElement* panel = MediaControlPanelElement::create(*this);
|
| -
|
| - MediaControlPlayButtonElement* playButton =
|
| - MediaControlPlayButtonElement::create(*this);
|
| - m_playButton = playButton;
|
| - panel->appendChild(playButton);
|
| -
|
| - MediaControlCurrentTimeDisplayElement* currentTimeDisplay =
|
| - MediaControlCurrentTimeDisplayElement::create(*this);
|
| - m_currentTimeDisplay = currentTimeDisplay;
|
| - m_currentTimeDisplay->setIsWanted(true);
|
| - panel->appendChild(currentTimeDisplay);
|
| -
|
| - MediaControlTimeRemainingDisplayElement* durationDisplay =
|
| - MediaControlTimeRemainingDisplayElement::create(*this);
|
| - m_durationDisplay = durationDisplay;
|
| - panel->appendChild(durationDisplay);
|
| -
|
| - MediaControlTimelineElement* timeline =
|
| - MediaControlTimelineElement::create(*this);
|
| - m_timeline = timeline;
|
| - panel->appendChild(timeline);
|
| -
|
| - MediaControlMuteButtonElement* muteButton =
|
| - MediaControlMuteButtonElement::create(*this);
|
| - m_muteButton = muteButton;
|
| - panel->appendChild(muteButton);
|
| -
|
| - MediaControlVolumeSliderElement* slider =
|
| - MediaControlVolumeSliderElement::create(*this);
|
| - m_volumeSlider = slider;
|
| - panel->appendChild(slider);
|
| - if (preferHiddenVolumeControls(document()))
|
| - m_volumeSlider->setIsWanted(false);
|
| -
|
| - MediaControlFullscreenButtonElement* fullscreenButton =
|
| - MediaControlFullscreenButtonElement::create(*this);
|
| - m_fullscreenButton = fullscreenButton;
|
| - panel->appendChild(fullscreenButton);
|
| -
|
| - MediaControlDownloadButtonElement* downloadButton =
|
| - MediaControlDownloadButtonElement::create(*this);
|
| - m_downloadButton = downloadButton;
|
| - panel->appendChild(downloadButton);
|
| -
|
| - MediaControlCastButtonElement* castButton =
|
| - MediaControlCastButtonElement::create(*this, false);
|
| - m_castButton = castButton;
|
| - panel->appendChild(castButton);
|
| -
|
| - MediaControlToggleClosedCaptionsButtonElement* toggleClosedCaptionsButton =
|
| - MediaControlToggleClosedCaptionsButtonElement::create(*this);
|
| - m_toggleClosedCaptionsButton = toggleClosedCaptionsButton;
|
| - panel->appendChild(toggleClosedCaptionsButton);
|
| -
|
| - m_panel = panel;
|
| - enclosure->appendChild(panel);
|
| -
|
| - m_enclosure = enclosure;
|
| - appendChild(enclosure);
|
| -
|
| - MediaControlTextTrackListElement* textTrackList =
|
| - MediaControlTextTrackListElement::create(*this);
|
| - m_textTrackList = textTrackList;
|
| - appendChild(textTrackList);
|
| -
|
| - MediaControlOverflowMenuButtonElement* overflowMenu =
|
| - MediaControlOverflowMenuButtonElement::create(*this);
|
| - m_overflowMenu = overflowMenu;
|
| - panel->appendChild(overflowMenu);
|
| -
|
| - MediaControlOverflowMenuListElement* overflowList =
|
| - MediaControlOverflowMenuListElement::create(*this);
|
| - m_overflowList = overflowList;
|
| - appendChild(overflowList);
|
| -
|
| - // The order in which we append elements to the overflow list is significant
|
| - // because it determines how the elements show up in the overflow menu
|
| - // relative to each other. The first item appended appears at the top of the
|
| - // overflow menu.
|
| - m_overflowList->appendChild(m_playButton->createOverflowElement(
|
| - *this, MediaControlPlayButtonElement::create(*this)));
|
| - m_overflowList->appendChild(m_fullscreenButton->createOverflowElement(
|
| - *this, MediaControlFullscreenButtonElement::create(*this)));
|
| - m_overflowList->appendChild(m_downloadButton->createOverflowElement(
|
| - *this, MediaControlDownloadButtonElement::create(*this)));
|
| - m_overflowList->appendChild(m_muteButton->createOverflowElement(
|
| - *this, MediaControlMuteButtonElement::create(*this)));
|
| - m_overflowList->appendChild(m_castButton->createOverflowElement(
|
| - *this, MediaControlCastButtonElement::create(*this, false)));
|
| - m_overflowList->appendChild(
|
| - m_toggleClosedCaptionsButton->createOverflowElement(
|
| - *this, MediaControlToggleClosedCaptionsButtonElement::create(*this)));
|
| -}
|
| -
|
| -Node::InsertionNotificationRequest MediaControls::insertedInto(
|
| - ContainerNode* root) {
|
| - if (!mediaElement().isConnected())
|
| - return HTMLDivElement::insertedInto(root);
|
| -
|
| - // TODO(mlamouri): we should show the controls instead of having
|
| - // HTMLMediaElement do it.
|
| -
|
| - // m_windowEventListener doesn't need to be re-attached as it's only needed
|
| - // when a menu is visible.
|
| - m_mediaEventListener->attach();
|
| - if (m_orientationLockDelegate)
|
| - m_orientationLockDelegate->attach();
|
| -
|
| - if (!m_resizeObserver) {
|
| - m_resizeObserver =
|
| - ResizeObserver::create(m_mediaElement->document(),
|
| - new MediaControlsResizeObserverCallback(this));
|
| - m_resizeObserver->observe(m_mediaElement);
|
| - }
|
| -
|
| - return HTMLDivElement::insertedInto(root);
|
| -}
|
| -
|
| -void MediaControls::removedFrom(ContainerNode*) {
|
| - DCHECK(!mediaElement().isConnected());
|
| -
|
| - // TODO(mlamouri): we hide show the controls instead of having
|
| - // HTMLMediaElement do it.
|
| -
|
| - m_windowEventListener->stop();
|
| - m_mediaEventListener->detach();
|
| - if (m_orientationLockDelegate)
|
| - m_orientationLockDelegate->detach();
|
| -
|
| - m_resizeObserver.clear();
|
| -}
|
| -
|
| -void MediaControls::reset() {
|
| - EventDispatchForbiddenScope::AllowUserAgentEvents allowEventsInShadow;
|
| - BatchedControlUpdate batch(this);
|
| -
|
| - const double duration = mediaElement().duration();
|
| - m_durationDisplay->setTextContent(
|
| - LayoutTheme::theme().formatMediaControlsTime(duration));
|
| - m_durationDisplay->setCurrentValue(duration);
|
| -
|
| - // Show everything that we might hide.
|
| - // If we don't have a duration, then mark it to be hidden. For the
|
| - // old UI case, want / don't want is the same as show / hide since
|
| - // it is never marked as not fitting.
|
| - m_durationDisplay->setIsWanted(std::isfinite(duration));
|
| - m_currentTimeDisplay->setIsWanted(true);
|
| - m_timeline->setIsWanted(true);
|
| -
|
| - // If the player has entered an error state, force it into the paused state.
|
| - if (mediaElement().error())
|
| - mediaElement().pause();
|
| -
|
| - updatePlayState();
|
| -
|
| - updateCurrentTimeDisplay();
|
| -
|
| - m_timeline->setDuration(duration);
|
| - m_timeline->setPosition(mediaElement().currentTime());
|
| -
|
| - onVolumeChange();
|
| - onTextTracksAddedOrRemoved();
|
| -
|
| - onControlsListUpdated();
|
| -}
|
| -
|
| -void MediaControls::onControlsListUpdated() {
|
| - BatchedControlUpdate batch(this);
|
| -
|
| - m_fullscreenButton->setIsWanted(shouldShowFullscreenButton(mediaElement()));
|
| -
|
| - refreshCastButtonVisibilityWithoutUpdate();
|
| -
|
| - m_downloadButton->setIsWanted(
|
| - m_downloadButton->shouldDisplayDownloadButton());
|
| -}
|
| -
|
| -LayoutObject* MediaControls::layoutObjectForTextTrackLayout() {
|
| - return m_panel->layoutObject();
|
| -}
|
| -
|
| -void MediaControls::show() {
|
| - makeOpaque();
|
| - m_panel->setIsWanted(true);
|
| - m_panel->setIsDisplayed(true);
|
| - if (m_overlayPlayButton)
|
| - m_overlayPlayButton->updateDisplayType();
|
| -}
|
| -
|
| -void MediaControls::hide() {
|
| - m_panel->setIsWanted(false);
|
| - m_panel->setIsDisplayed(false);
|
| - if (m_overlayPlayButton)
|
| - m_overlayPlayButton->setIsWanted(false);
|
| -}
|
| -
|
| -bool MediaControls::isVisible() const {
|
| - return m_panel->isOpaque();
|
| -}
|
| -
|
| -void MediaControls::makeOpaque() {
|
| - m_panel->makeOpaque();
|
| -}
|
| -
|
| -void MediaControls::makeTransparent() {
|
| - m_panel->makeTransparent();
|
| -}
|
| -
|
| -bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const {
|
| - // Never hide for a media element without visual representation.
|
| - if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() ||
|
| - mediaElement().isPlayingRemotely()) {
|
| - return false;
|
| - }
|
| -
|
| - // Keep the controls visible as long as the timer is running.
|
| - const bool ignoreWaitForTimer = behaviorFlags & IgnoreWaitForTimer;
|
| - if (!ignoreWaitForTimer && m_keepShowingUntilTimerFires)
|
| - return false;
|
| -
|
| - // Don't hide if the mouse is over the controls.
|
| - const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover;
|
| - if (!ignoreControlsHover && m_panel->isHovered())
|
| - return false;
|
| -
|
| - // Don't hide if the mouse is over the video area.
|
| - const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover;
|
| - if (!ignoreVideoHover && m_isMouseOverControls)
|
| - return false;
|
| -
|
| - // Don't hide if focus is on the HTMLMediaElement or within the
|
| - // controls/shadow tree. (Perform the checks separately to avoid going
|
| - // through all the potential ancestor hosts for the focused element.)
|
| - const bool ignoreFocus = behaviorFlags & IgnoreFocus;
|
| - if (!ignoreFocus &&
|
| - (mediaElement().isFocused() || contains(document().focusedElement()))) {
|
| - return false;
|
| - }
|
| -
|
| - // Don't hide the media controls when a panel is showing.
|
| - if (m_textTrackList->isWanted() || m_overflowList->isWanted())
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void MediaControls::updatePlayState() {
|
| - if (m_isPausedForScrubbing)
|
| - return;
|
| -
|
| - if (m_overlayPlayButton)
|
| - m_overlayPlayButton->updateDisplayType();
|
| - m_playButton->updateDisplayType();
|
| -}
|
| -
|
| -void MediaControls::beginScrubbing() {
|
| - if (!mediaElement().paused()) {
|
| - m_isPausedForScrubbing = true;
|
| - mediaElement().pause();
|
| - }
|
| -}
|
| -
|
| -void MediaControls::endScrubbing() {
|
| - if (m_isPausedForScrubbing) {
|
| - m_isPausedForScrubbing = false;
|
| - if (mediaElement().paused())
|
| - mediaElement().play();
|
| - }
|
| -}
|
| -
|
| -void MediaControls::updateCurrentTimeDisplay() {
|
| - double now = mediaElement().currentTime();
|
| - double duration = mediaElement().duration();
|
| -
|
| - // Allow the theme to format the time.
|
| - m_currentTimeDisplay->setInnerText(
|
| - LayoutTheme::theme().formatMediaControlsCurrentTime(now, duration),
|
| - IGNORE_EXCEPTION_FOR_TESTING);
|
| - m_currentTimeDisplay->setCurrentValue(now);
|
| -}
|
| -
|
| -void MediaControls::toggleTextTrackList() {
|
| - if (!mediaElement().hasClosedCaptions()) {
|
| - m_textTrackList->setVisible(false);
|
| - return;
|
| - }
|
| -
|
| - if (!m_textTrackList->isWanted())
|
| - m_windowEventListener->start();
|
| -
|
| - m_textTrackList->setVisible(!m_textTrackList->isWanted());
|
| -}
|
| -
|
| -void MediaControls::showTextTrackAtIndex(unsigned indexToEnable) {
|
| - TextTrackList* trackList = mediaElement().textTracks();
|
| - if (indexToEnable >= trackList->length())
|
| - return;
|
| - TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable);
|
| - if (track && track->canBeRendered())
|
| - track->setMode(TextTrack::showingKeyword());
|
| -}
|
| -
|
| -void MediaControls::disableShowingTextTracks() {
|
| - TextTrackList* trackList = mediaElement().textTracks();
|
| - for (unsigned i = 0; i < trackList->length(); ++i) {
|
| - TextTrack* track = trackList->anonymousIndexedGetter(i);
|
| - if (track->mode() == TextTrack::showingKeyword())
|
| - track->setMode(TextTrack::disabledKeyword());
|
| - }
|
| -}
|
| -
|
| -void MediaControls::refreshCastButtonVisibility() {
|
| - refreshCastButtonVisibilityWithoutUpdate();
|
| - BatchedControlUpdate batch(this);
|
| -}
|
| -
|
| -void MediaControls::refreshCastButtonVisibilityWithoutUpdate() {
|
| - if (!shouldShowCastButton(mediaElement())) {
|
| - m_castButton->setIsWanted(false);
|
| - m_overlayCastButton->setIsWanted(false);
|
| - return;
|
| - }
|
| -
|
| - // 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().shouldShowControls() && !mediaElement().autoplay() &&
|
| - mediaElement().paused()) {
|
| - // Note that this is a case where we add the overlay cast button
|
| - // without wanting the panel cast button. We depend on the fact
|
| - // that computeWhichControlsFit() won't change overlay cast button
|
| - // visibility in the case where the cast button isn't wanted.
|
| - // We don't call compute...() here, but it will be called as
|
| - // non-cast changes (e.g., resize) occur. If the panel button
|
| - // is shown, however, compute...() will take control of the
|
| - // overlay cast button if it needs to hide it from the panel.
|
| - m_overlayCastButton->tryShowOverlay();
|
| - m_castButton->setIsWanted(false);
|
| - } else if (mediaElement().shouldShowControls()) {
|
| - m_overlayCastButton->setIsWanted(false);
|
| - m_castButton->setIsWanted(true);
|
| - }
|
| -}
|
| -
|
| -void MediaControls::showOverlayCastButtonIfNeeded() {
|
| - if (mediaElement().shouldShowControls() ||
|
| - !shouldShowCastButton(mediaElement()))
|
| - return;
|
| -
|
| - m_overlayCastButton->tryShowOverlay();
|
| - resetHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::enterFullscreen() {
|
| - Fullscreen::requestFullscreen(mediaElement());
|
| -}
|
| -
|
| -void MediaControls::exitFullscreen() {
|
| - Fullscreen::exitFullscreen(document());
|
| -}
|
| -
|
| -void MediaControls::startedCasting() {
|
| - m_castButton->setIsPlayingRemotely(true);
|
| - m_overlayCastButton->setIsPlayingRemotely(true);
|
| -}
|
| -
|
| -void MediaControls::stoppedCasting() {
|
| - m_castButton->setIsPlayingRemotely(false);
|
| - m_overlayCastButton->setIsPlayingRemotely(false);
|
| -}
|
| -
|
| -void MediaControls::defaultEventHandler(Event* event) {
|
| - HTMLDivElement::defaultEventHandler(event);
|
| -
|
| - // Do not handle events to not interfere with the rest of the page if no
|
| - // controls should be visible.
|
| - if (!mediaElement().shouldShowControls())
|
| - return;
|
| -
|
| - // Add IgnoreControlsHover to m_hideTimerBehaviorFlags when we see a touch
|
| - // event, to allow the hide-timer to do the right thing when it fires.
|
| - // FIXME: Preferably we would only do this when we're actually handling the
|
| - // event here ourselves.
|
| - bool isTouchEvent =
|
| - event->isTouchEvent() || event->isGestureEvent() ||
|
| - (event->isMouseEvent() && toMouseEvent(event)->fromTouch());
|
| - m_hideTimerBehaviorFlags |= isTouchEvent ? IgnoreControlsHover : IgnoreNone;
|
| -
|
| - // Touch events are treated differently to avoid fake mouse events to trigger
|
| - // random behavior. The expect behaviour for touch is that a tap will show the
|
| - // controls and they will hide when the timer to hide fires.
|
| - if (isTouchEvent) {
|
| - if (event->type() != EventTypeNames::gesturetap)
|
| - return;
|
| -
|
| - if (!containsRelatedTarget(event)) {
|
| - if (!mediaElement().paused()) {
|
| - if (!isVisible()) {
|
| - makeOpaque();
|
| - // When the panel switches from invisible to visible, we need to mark
|
| - // the event handled to avoid buttons below the tap to be activated.
|
| - event->setDefaultHandled();
|
| - }
|
| - if (shouldHideMediaControls(IgnoreWaitForTimer)) {
|
| - m_keepShowingUntilTimerFires = true;
|
| - startHideMediaControlsTimer();
|
| - }
|
| - }
|
| - }
|
| -
|
| - return;
|
| - }
|
| -
|
| - if (event->type() == EventTypeNames::mouseover) {
|
| - if (!containsRelatedTarget(event)) {
|
| - m_isMouseOverControls = true;
|
| - if (!mediaElement().paused()) {
|
| - makeOpaque();
|
| - if (shouldHideMediaControls())
|
| - startHideMediaControlsTimer();
|
| - }
|
| - }
|
| - return;
|
| - }
|
| -
|
| - if (event->type() == EventTypeNames::mouseout) {
|
| - if (!containsRelatedTarget(event)) {
|
| - m_isMouseOverControls = false;
|
| - stopHideMediaControlsTimer();
|
| - }
|
| - return;
|
| - }
|
| -
|
| - if (event->type() == EventTypeNames::mousemove) {
|
| - // When we get a mouse move, show the media controls, and start a timer
|
| - // that will hide the media controls after a 3 seconds without a mouse move.
|
| - makeOpaque();
|
| - if (shouldHideMediaControls(IgnoreVideoHover))
|
| - startHideMediaControlsTimer();
|
| - return;
|
| - }
|
| -}
|
| -
|
| -void MediaControls::hideMediaControlsTimerFired(TimerBase*) {
|
| - unsigned behaviorFlags =
|
| - m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover;
|
| - m_hideTimerBehaviorFlags = IgnoreNone;
|
| - m_keepShowingUntilTimerFires = false;
|
| -
|
| - if (mediaElement().paused())
|
| - return;
|
| -
|
| - if (!shouldHideMediaControls(behaviorFlags))
|
| - return;
|
| -
|
| - makeTransparent();
|
| - m_overlayCastButton->setIsWanted(false);
|
| -}
|
| -
|
| -void MediaControls::startHideMediaControlsTimer() {
|
| - m_hideMediaControlsTimer.startOneShot(
|
| - timeWithoutMouseMovementBeforeHidingMediaControls, BLINK_FROM_HERE);
|
| -}
|
| -
|
| -void MediaControls::stopHideMediaControlsTimer() {
|
| - m_keepShowingUntilTimerFires = false;
|
| - m_hideMediaControlsTimer.stop();
|
| -}
|
| -
|
| -void MediaControls::resetHideMediaControlsTimer() {
|
| - stopHideMediaControlsTimer();
|
| - if (!mediaElement().paused())
|
| - startHideMediaControlsTimer();
|
| -}
|
| -
|
| -bool MediaControls::containsRelatedTarget(Event* event) {
|
| - if (!event->isMouseEvent())
|
| - return false;
|
| - EventTarget* relatedTarget = toMouseEvent(event)->relatedTarget();
|
| - if (!relatedTarget)
|
| - return false;
|
| - return contains(relatedTarget->toNode());
|
| -}
|
| -
|
| -void MediaControls::onVolumeChange() {
|
| - m_muteButton->updateDisplayType();
|
| - m_volumeSlider->setVolume(mediaElement().muted() ? 0
|
| - : mediaElement().volume());
|
| -
|
| - // Update visibility of volume controls.
|
| - // TODO(mlamouri): it should not be part of the volumechange handling because
|
| - // it is using audio availability as input.
|
| - BatchedControlUpdate batch(this);
|
| - m_volumeSlider->setIsWanted(mediaElement().hasAudio() &&
|
| - !preferHiddenVolumeControls(document()));
|
| - m_muteButton->setIsWanted(mediaElement().hasAudio());
|
| -}
|
| -
|
| -void MediaControls::onFocusIn() {
|
| - if (!mediaElement().shouldShowControls())
|
| - return;
|
| -
|
| - show();
|
| - resetHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::onTimeUpdate() {
|
| - m_timeline->setPosition(mediaElement().currentTime());
|
| - updateCurrentTimeDisplay();
|
| -
|
| - // 'timeupdate' might be called in a paused state. The controls should not
|
| - // become transparent in that case.
|
| - if (mediaElement().paused()) {
|
| - makeOpaque();
|
| - return;
|
| - }
|
| -
|
| - if (isVisible() && shouldHideMediaControls())
|
| - makeTransparent();
|
| -}
|
| -
|
| -void MediaControls::onDurationChange() {
|
| - const double duration = mediaElement().duration();
|
| -
|
| - // Update the displayed current time/duration.
|
| - m_durationDisplay->setTextContent(
|
| - LayoutTheme::theme().formatMediaControlsTime(duration));
|
| - m_durationDisplay->setCurrentValue(duration);
|
| - updateCurrentTimeDisplay();
|
| -
|
| - // Update the timeline (the UI with the seek marker).
|
| - m_timeline->setDuration(duration);
|
| -}
|
| -
|
| -void MediaControls::onPlay() {
|
| - updatePlayState();
|
| - m_timeline->setPosition(mediaElement().currentTime());
|
| - updateCurrentTimeDisplay();
|
| -
|
| - startHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::onPause() {
|
| - updatePlayState();
|
| - m_timeline->setPosition(mediaElement().currentTime());
|
| - updateCurrentTimeDisplay();
|
| - makeOpaque();
|
| -
|
| - stopHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::onTextTracksAddedOrRemoved() {
|
| - m_toggleClosedCaptionsButton->setIsWanted(mediaElement().hasClosedCaptions());
|
| - BatchedControlUpdate batch(this);
|
| -}
|
| -
|
| -void MediaControls::onTextTracksChanged() {
|
| - m_toggleClosedCaptionsButton->updateDisplayType();
|
| -}
|
| -
|
| -void MediaControls::onError() {
|
| - // TODO(mlamouri): we should only change the aspects of the control that need
|
| - // to be changed.
|
| - reset();
|
| -}
|
| -
|
| -void MediaControls::onLoadedMetadata() {
|
| - // TODO(mlamouri): we should only change the aspects of the control that need
|
| - // to be changed.
|
| - reset();
|
| -}
|
| -
|
| -void MediaControls::onEnteredFullscreen() {
|
| - m_fullscreenButton->setIsFullscreen(true);
|
| - stopHideMediaControlsTimer();
|
| - startHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::onExitedFullscreen() {
|
| - m_fullscreenButton->setIsFullscreen(false);
|
| - stopHideMediaControlsTimer();
|
| - startHideMediaControlsTimer();
|
| -}
|
| -
|
| -void MediaControls::notifyElementSizeChanged(ClientRect* newSize) {
|
| - // Note that this code permits a bad frame on resize, since it is
|
| - // run after the relayout / paint happens. It would be great to improve
|
| - // this, but it would be even greater to move this code entirely to
|
| - // JS and fix it there.
|
| -
|
| - IntSize oldSize = m_size;
|
| - m_size.setWidth(newSize->width());
|
| - m_size.setHeight(newSize->height());
|
| -
|
| - // Adjust for effective zoom.
|
| - if (m_panel->layoutObject() && m_panel->layoutObject()->style()) {
|
| - m_size.setWidth(ceil(m_size.width() /
|
| - m_panel->layoutObject()->style()->effectiveZoom()));
|
| - m_size.setHeight(ceil(m_size.height() /
|
| - m_panel->layoutObject()->style()->effectiveZoom()));
|
| - }
|
| -
|
| - // Don't bother to do any work if this matches the most recent size.
|
| - if (oldSize != m_size)
|
| - m_elementSizeChangedTimer.startOneShot(0, BLINK_FROM_HERE);
|
| -}
|
| -
|
| -void MediaControls::elementSizeChangedTimerFired(TimerBase*) {
|
| - computeWhichControlsFit();
|
| -}
|
| -
|
| -void MediaControls::computeWhichControlsFit() {
|
| - // Hide all controls that don't fit, and show the ones that do.
|
| - // This might be better suited for a layout, but since JS media controls
|
| - // won't benefit from that anwyay, we just do it here like JS will.
|
| -
|
| - // Controls that we'll hide / show, in order of decreasing priority.
|
| - MediaControlElement* elements[] = {
|
| - // Exclude m_overflowMenu; we handle it specially.
|
| - m_playButton.get(),
|
| - m_fullscreenButton.get(),
|
| - m_downloadButton.get(),
|
| - m_timeline.get(),
|
| - m_muteButton.get(),
|
| - m_volumeSlider.get(),
|
| - m_toggleClosedCaptionsButton.get(),
|
| - m_castButton.get(),
|
| - m_currentTimeDisplay.get(),
|
| - m_durationDisplay.get(),
|
| - };
|
| -
|
| - // TODO(mlamouri): we need a more dynamic way to find out the width of an
|
| - // element.
|
| - const int sliderMargin = 36; // Sliders have 18px margin on each side.
|
| -
|
| - if (!m_size.width()) {
|
| - // No layout yet -- hide everything, then make them show up later.
|
| - // This prevents the wrong controls from being shown briefly
|
| - // immediately after the first layout and paint, but before we have
|
| - // a chance to revise them.
|
| - for (MediaControlElement* element : elements) {
|
| - if (element)
|
| - element->setDoesFit(false);
|
| - }
|
| - return;
|
| - }
|
| -
|
| - // Assume that all controls require 48px, unless we can get the computed
|
| - // style for a button. The minimumWidth is recorded and re-use for future
|
| - // MediaControls instances and future calls to this method given that at the
|
| - // moment the controls button width is per plataform.
|
| - // TODO(mlamouri): improve the mechanism without bandaid.
|
| - static int minimumWidth = 48;
|
| - if (m_playButton->layoutObject() && m_playButton->layoutObject()->style()) {
|
| - const ComputedStyle* style = m_playButton->layoutObject()->style();
|
| - minimumWidth = ceil(style->width().pixels() / style->effectiveZoom());
|
| - } else if (m_overflowMenu->layoutObject() &&
|
| - m_overflowMenu->layoutObject()->style()) {
|
| - const ComputedStyle* style = m_overflowMenu->layoutObject()->style();
|
| - minimumWidth = ceil(style->width().pixels() / style->effectiveZoom());
|
| - }
|
| -
|
| - // Insert an overflow menu. However, if we see that the overflow menu
|
| - // doesn't end up containing at least two elements, we will not display it
|
| - // but instead make place for the first element that was dropped.
|
| - m_overflowMenu->setDoesFit(true);
|
| - m_overflowMenu->setIsWanted(true);
|
| - int usedWidth = minimumWidth;
|
| -
|
| - std::list<MediaControlElement*> overflowElements;
|
| - MediaControlElement* firstDisplacedElement = nullptr;
|
| - // For each control that fits, enable it in order of decreasing priority.
|
| - for (MediaControlElement* element : elements) {
|
| - if (!element)
|
| - continue;
|
| - int width = minimumWidth;
|
| - if ((element == m_timeline.get()) || (element == m_volumeSlider.get()))
|
| - width += sliderMargin;
|
| - element->shouldShowButtonInOverflowMenu(false);
|
| - if (element->isWanted()) {
|
| - if (usedWidth + width <= m_size.width()) {
|
| - element->setDoesFit(true);
|
| - usedWidth += width;
|
| - } else {
|
| - element->setDoesFit(false);
|
| - element->shouldShowButtonInOverflowMenu(true);
|
| - if (element->hasOverflowButton())
|
| - overflowElements.push_front(element);
|
| - // We want a way to access the first media element that was
|
| - // removed. If we don't end up needing an overflow menu, we can
|
| - // use the space the overflow menu would have taken up to
|
| - // instead display that media element.
|
| - if (!element->hasOverflowButton() && !firstDisplacedElement)
|
| - firstDisplacedElement = element;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // If we don't have at least two overflow elements, we will not show the
|
| - // overflow menu.
|
| - if (overflowElements.empty()) {
|
| - m_overflowMenu->setIsWanted(false);
|
| - usedWidth -= minimumWidth;
|
| - if (firstDisplacedElement) {
|
| - int width = minimumWidth;
|
| - if ((firstDisplacedElement == m_timeline.get()) ||
|
| - (firstDisplacedElement == m_volumeSlider.get()))
|
| - width += sliderMargin;
|
| - if (usedWidth + width <= m_size.width())
|
| - firstDisplacedElement->setDoesFit(true);
|
| - }
|
| - } else if (overflowElements.size() == 1) {
|
| - m_overflowMenu->setIsWanted(false);
|
| - overflowElements.front()->setDoesFit(true);
|
| - }
|
| -
|
| - // Decide if the overlay play button fits.
|
| - if (m_overlayPlayButton) {
|
| - bool doesFit = m_size.width() >= kMinWidthForOverlayPlayButton &&
|
| - m_size.height() >= kMinHeightForOverlayPlayButton;
|
| - m_overlayPlayButton->setDoesFit(doesFit);
|
| - }
|
| -}
|
| -
|
| -void MediaControls::invalidate(Element* element) {
|
| - if (!element)
|
| - return;
|
| -
|
| - if (LayoutObject* layoutObject = element->layoutObject())
|
| - layoutObject
|
| - ->setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
|
| -}
|
| -
|
| -void MediaControls::networkStateChanged() {
|
| - invalidate(m_playButton);
|
| - invalidate(m_overlayPlayButton);
|
| - invalidate(m_muteButton);
|
| - invalidate(m_fullscreenButton);
|
| - invalidate(m_downloadButton);
|
| - invalidate(m_timeline);
|
| - invalidate(m_volumeSlider);
|
| -
|
| - // Update the display state of the download button in case we now have a
|
| - // source or no longer have a source.
|
| - m_downloadButton->setIsWanted(
|
| - m_downloadButton->shouldDisplayDownloadButton());
|
| -}
|
| -
|
| -bool MediaControls::overflowMenuVisible() {
|
| - return m_overflowList ? m_overflowList->isWanted() : false;
|
| -}
|
| -
|
| -void MediaControls::toggleOverflowMenu() {
|
| - DCHECK(m_overflowList);
|
| -
|
| - if (!m_overflowList->isWanted())
|
| - m_windowEventListener->start();
|
| - m_overflowList->setIsWanted(!m_overflowList->isWanted());
|
| -}
|
| -
|
| -void MediaControls::hideAllMenus() {
|
| - m_windowEventListener->stop();
|
| -
|
| - if (m_overflowList->isWanted())
|
| - m_overflowList->setIsWanted(false);
|
| - if (m_textTrackList->isWanted())
|
| - m_textTrackList->setVisible(false);
|
| -}
|
| -
|
| -DEFINE_TRACE(MediaControls) {
|
| - visitor->trace(m_resizeObserver);
|
| - visitor->trace(m_mediaElement);
|
| - visitor->trace(m_panel);
|
| - visitor->trace(m_overlayPlayButton);
|
| - visitor->trace(m_overlayEnclosure);
|
| - visitor->trace(m_playButton);
|
| - visitor->trace(m_currentTimeDisplay);
|
| - visitor->trace(m_timeline);
|
| - visitor->trace(m_muteButton);
|
| - visitor->trace(m_volumeSlider);
|
| - visitor->trace(m_toggleClosedCaptionsButton);
|
| - visitor->trace(m_fullscreenButton);
|
| - visitor->trace(m_downloadButton);
|
| - visitor->trace(m_durationDisplay);
|
| - visitor->trace(m_enclosure);
|
| - visitor->trace(m_textTrackList);
|
| - visitor->trace(m_overflowMenu);
|
| - visitor->trace(m_overflowList);
|
| - visitor->trace(m_castButton);
|
| - visitor->trace(m_overlayCastButton);
|
| - visitor->trace(m_mediaEventListener);
|
| - visitor->trace(m_windowEventListener);
|
| - visitor->trace(m_orientationLockDelegate);
|
| - HTMLDivElement::trace(visitor);
|
| -}
|
| -
|
| -} // namespace blink
|
|
|