/*
 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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/MediaControlElements.h"

#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/InputTypeNames.h"
#include "core/dom/ClientRect.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/MouseEvent.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLLabelElement.h"
#include "core/html/HTMLMediaSource.h"
#include "core/html/HTMLSpanElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/html/TimeRanges.h"
#include "core/html/shadow/MediaControls.h"
#include "core/html/track/TextTrackList.h"
#include "core/input/EventHandler.h"
#include "core/layout/api/LayoutSliderItem.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/Histogram.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/text/PlatformLocale.h"
#include "public/platform/Platform.h"
#include "public/platform/UserMetricsAction.h"

namespace blink {

using namespace HTMLNames;

namespace {

// This is the duration from mediaControls.css
const double fadeOutDuration = 0.3;

const QualifiedName& trackIndexAttrName() {
  // Save the track index in an attribute to avoid holding a pointer to the text
  // track.
  DEFINE_STATIC_LOCAL(QualifiedName, trackIndexAttr,
                      (nullAtom, "data-track-index", nullAtom));
  return trackIndexAttr;
}

// When specified as trackIndex, disable text tracks.
const int trackIndexOffValue = -1;

bool isUserInteractionEvent(Event* event) {
  const AtomicString& type = event->type();
  return type == EventTypeNames::mousedown || type == EventTypeNames::mouseup ||
         type == EventTypeNames::click || type == EventTypeNames::dblclick ||
         event->isKeyboardEvent() || event->isTouchEvent();
}

// Sliders (the volume control and timeline) need to capture some additional
// events used when dragging the thumb.
bool isUserInteractionEventForSlider(Event* event, LayoutObject* layoutObject) {
  // It is unclear if this can be converted to isUserInteractionEvent(), since
  // mouse* events seem to be eaten during a drag anyway.  crbug.com/516416 .
  if (isUserInteractionEvent(event))
    return true;

  // Some events are only captured during a slider drag.
  LayoutSliderItem slider = LayoutSliderItem(toLayoutSlider(layoutObject));
  if (!slider.isNull() && !slider.inDragMode())
    return false;

  const AtomicString& type = event->type();
  return type == EventTypeNames::mouseover ||
         type == EventTypeNames::mouseout || type == EventTypeNames::mousemove;
}

Element* elementFromCenter(Element& element) {
  ClientRect* clientRect = element.getBoundingClientRect();
  int centerX =
      static_cast<int>((clientRect->left() + clientRect->right()) / 2);
  int centerY =
      static_cast<int>((clientRect->top() + clientRect->bottom()) / 2);

  return element.document().elementFromPoint(centerX, centerY);
}

bool hasDuplicateLabel(TextTrack* currentTrack) {
  DCHECK(currentTrack);
  TextTrackList* trackList = currentTrack->trackList();
  // The runtime of this method is quadratic but since there are usually very
  // few text tracks it won't affect the performance much.
  String currentTrackLabel = currentTrack->label();
  for (unsigned i = 0; i < trackList->length(); i++) {
    TextTrack* track = trackList->anonymousIndexedGetter(i);
    if (currentTrack != track && currentTrackLabel == track->label())
      return true;
  }
  return false;
}

}  // anonymous namespace

MediaControlPanelElement::MediaControlPanelElement(MediaControls& mediaControls)
    : MediaControlDivElement(mediaControls, MediaControlsPanel),
      m_isDisplayed(false),
      m_opaque(true),
      m_transitionTimer(this, &MediaControlPanelElement::transitionTimerFired) {
}

MediaControlPanelElement* MediaControlPanelElement::create(
    MediaControls& mediaControls) {
  MediaControlPanelElement* panel = new MediaControlPanelElement(mediaControls);
  panel->setShadowPseudoId(AtomicString("-webkit-media-controls-panel"));
  return panel;
}

void MediaControlPanelElement::defaultEventHandler(Event* event) {
  // Suppress the media element activation behavior (toggle play/pause) when
  // any part of the control panel is clicked.
  if (event->type() == EventTypeNames::click) {
    event->setDefaultHandled();
    return;
  }
  HTMLDivElement::defaultEventHandler(event);
}

void MediaControlPanelElement::startTimer() {
  stopTimer();

  // The timer is required to set the property display:'none' on the panel,
  // such that captions are correctly displayed at the bottom of the video
  // at the end of the fadeout transition.
  // FIXME: Racing a transition with a setTimeout like this is wrong.
  m_transitionTimer.startOneShot(fadeOutDuration, BLINK_FROM_HERE);
}

void MediaControlPanelElement::stopTimer() {
  if (m_transitionTimer.isActive())
    m_transitionTimer.stop();
}

void MediaControlPanelElement::transitionTimerFired(TimerBase*) {
  if (!m_opaque)
    setIsWanted(false);

  stopTimer();
}

void MediaControlPanelElement::didBecomeVisible() {
  DCHECK(m_isDisplayed && m_opaque);
  mediaElement().mediaControlsDidBecomeVisible();
}

void MediaControlPanelElement::makeOpaque() {
  if (m_opaque)
    return;

  setInlineStyleProperty(CSSPropertyOpacity, 1.0,
                         CSSPrimitiveValue::UnitType::Number);
  m_opaque = true;

  if (m_isDisplayed) {
    setIsWanted(true);
    didBecomeVisible();
  }
}

void MediaControlPanelElement::makeTransparent() {
  if (!m_opaque)
    return;

  setInlineStyleProperty(CSSPropertyOpacity, 0.0,
                         CSSPrimitiveValue::UnitType::Number);

  m_opaque = false;
  startTimer();
}

void MediaControlPanelElement::setIsDisplayed(bool isDisplayed) {
  if (m_isDisplayed == isDisplayed)
    return;

  m_isDisplayed = isDisplayed;
  if (m_isDisplayed && m_opaque)
    didBecomeVisible();
}

bool MediaControlPanelElement::keepEventInNode(Event* event) {
  return isUserInteractionEvent(event);
}

// ----------------------------

MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(
    MediaControls& mediaControls)
    // Mapping onto same MediaControlElementType as panel element, since it has
    // similar properties.
    : MediaControlDivElement(mediaControls, MediaControlsPanel) {}

MediaControlPanelEnclosureElement* MediaControlPanelEnclosureElement::create(
    MediaControls& mediaControls) {
  MediaControlPanelEnclosureElement* enclosure =
      new MediaControlPanelEnclosureElement(mediaControls);
  enclosure->setShadowPseudoId(
      AtomicString("-webkit-media-controls-enclosure"));
  return enclosure;
}

// ----------------------------

MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(
    MediaControls& mediaControls)
    // Mapping onto same MediaControlElementType as panel element, since it has
    // similar properties.
    : MediaControlDivElement(mediaControls, MediaControlsPanel) {}

MediaControlOverlayEnclosureElement*
MediaControlOverlayEnclosureElement::create(MediaControls& mediaControls) {
  MediaControlOverlayEnclosureElement* enclosure =
      new MediaControlOverlayEnclosureElement(mediaControls);
  enclosure->setShadowPseudoId(
      AtomicString("-webkit-media-controls-overlay-enclosure"));
  return enclosure;
}

EventDispatchHandlingState*
MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event* event) {
  // When the media element is clicked or touched we want to make the overlay
  // cast button visible (if the other requirements are right) even if
  // JavaScript is doing its own handling of the event.  Doing it in
  // preDispatchEventHandler prevents any interference from JavaScript.
  // Note that we can't simply test for click, since JS handling of touch events
  // can prevent their translation to click events.
  if (event && (event->type() == EventTypeNames::click ||
                event->type() == EventTypeNames::touchstart))
    mediaControls().showOverlayCastButtonIfNeeded();
  return MediaControlDivElement::preDispatchEventHandler(event);
}

// ----------------------------

MediaControlMuteButtonElement::MediaControlMuteButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaMuteButton) {}

MediaControlMuteButtonElement* MediaControlMuteButtonElement::create(
    MediaControls& mediaControls) {
  MediaControlMuteButtonElement* button =
      new MediaControlMuteButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(AtomicString("-webkit-media-controls-mute-button"));
  return button;
}

void MediaControlMuteButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click) {
    if (mediaElement().muted())
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.Unmute"));
    else
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.Mute"));

    mediaElement().setMuted(!mediaElement().muted());
    event->setDefaultHandled();
  }

  MediaControlInputElement::defaultEventHandler(event);
}

void MediaControlMuteButtonElement::updateDisplayType() {
  setDisplayType(mediaElement().muted() ? MediaUnMuteButton : MediaMuteButton);
  updateOverflowString();
}

WebLocalizedString::Name
MediaControlMuteButtonElement::getOverflowStringName() {
  if (mediaElement().muted())
    return WebLocalizedString::OverflowMenuUnmute;
  return WebLocalizedString::OverflowMenuMute;
}

// ----------------------------

MediaControlPlayButtonElement::MediaControlPlayButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaPlayButton) {}

MediaControlPlayButtonElement* MediaControlPlayButtonElement::create(
    MediaControls& mediaControls) {
  MediaControlPlayButtonElement* button =
      new MediaControlPlayButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(AtomicString("-webkit-media-controls-play-button"));
  return button;
}

void MediaControlPlayButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click) {
    if (mediaElement().paused())
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.Play"));
    else
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.Pause"));

    // Allow play attempts for plain src= media to force a reload in the error
    // state. This allows potential recovery for transient network and decoder
    // resource issues.
    const String& url = mediaElement().currentSrc().getString();
    if (mediaElement().error() && !HTMLMediaElement::isMediaStreamURL(url) &&
        !HTMLMediaSource::lookup(url))
      mediaElement().load();

    mediaElement().togglePlayState();
    updateDisplayType();
    event->setDefaultHandled();
  }
  MediaControlInputElement::defaultEventHandler(event);
}

void MediaControlPlayButtonElement::updateDisplayType() {
  setDisplayType(mediaElement().paused() ? MediaPlayButton : MediaPauseButton);
  updateOverflowString();
}

WebLocalizedString::Name
MediaControlPlayButtonElement::getOverflowStringName() {
  if (mediaElement().paused())
    return WebLocalizedString::OverflowMenuPlay;
  return WebLocalizedString::OverflowMenuPause;
}

// ----------------------------

MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaOverlayPlayButton) {}

MediaControlOverlayPlayButtonElement*
MediaControlOverlayPlayButtonElement::create(MediaControls& mediaControls) {
  MediaControlOverlayPlayButtonElement* button =
      new MediaControlOverlayPlayButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(
      AtomicString("-webkit-media-controls-overlay-play-button"));
  return button;
}

void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click && mediaElement().paused()) {
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.PlayOverlay"));
    mediaElement().play();
    updateDisplayType();
    event->setDefaultHandled();
  }
}

void MediaControlOverlayPlayButtonElement::updateDisplayType() {
  setIsWanted(mediaElement().shouldShowControls() && mediaElement().paused());
}

bool MediaControlOverlayPlayButtonElement::keepEventInNode(Event* event) {
  return isUserInteractionEvent(event);
}

// ----------------------------

MediaControlToggleClosedCaptionsButtonElement::
    MediaControlToggleClosedCaptionsButtonElement(MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaShowClosedCaptionsButton) {}

MediaControlToggleClosedCaptionsButtonElement*
MediaControlToggleClosedCaptionsButtonElement::create(
    MediaControls& mediaControls) {
  MediaControlToggleClosedCaptionsButtonElement* button =
      new MediaControlToggleClosedCaptionsButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(
      AtomicString("-webkit-media-controls-toggle-closed-captions-button"));
  button->setIsWanted(false);
  return button;
}

void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() {
  bool captionsVisible = mediaElement().textTracksVisible();
  setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton
                                 : MediaShowClosedCaptionsButton);
}

void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(
    Event* event) {
  if (event->type() == EventTypeNames::click) {
    mediaControls().toggleTextTrackList();
    updateDisplayType();
    event->setDefaultHandled();
  }

  MediaControlInputElement::defaultEventHandler(event);
}

WebLocalizedString::Name
MediaControlToggleClosedCaptionsButtonElement::getOverflowStringName() {
  return WebLocalizedString::OverflowMenuCaptions;
}

// ----------------------------

MediaControlTextTrackListElement::MediaControlTextTrackListElement(
    MediaControls& mediaControls)
    : MediaControlDivElement(mediaControls, MediaTextTrackList) {}

MediaControlTextTrackListElement* MediaControlTextTrackListElement::create(
    MediaControls& mediaControls) {
  MediaControlTextTrackListElement* element =
      new MediaControlTextTrackListElement(mediaControls);
  element->setShadowPseudoId(
      AtomicString("-internal-media-controls-text-track-list"));
  element->setIsWanted(false);
  return element;
}

void MediaControlTextTrackListElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::change) {
    // Identify which input element was selected and set track to showing
    Node* target = event->target()->toNode();
    if (!target || !target->isElementNode())
      return;

    disableShowingTextTracks();
    int trackIndex =
        toElement(target)->getIntegralAttribute(trackIndexAttrName());
    if (trackIndex != trackIndexOffValue) {
      DCHECK_GE(trackIndex, 0);
      showTextTrackAtIndex(trackIndex);
      mediaElement().disableAutomaticTextTrackSelection();
    }

    event->setDefaultHandled();
  }
  MediaControlDivElement::defaultEventHandler(event);
}

void MediaControlTextTrackListElement::setVisible(bool visible) {
  if (visible) {
    setIsWanted(true);
    refreshTextTrackListMenu();
  } else {
    setIsWanted(false);
  }
}

void MediaControlTextTrackListElement::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 MediaControlTextTrackListElement::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());
  }
}

String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track) {
  if (!track)
    return mediaElement().locale().queryString(
        WebLocalizedString::TextTracksOff);

  String trackLabel = track->label();

  if (trackLabel.isEmpty())
    trackLabel = String(mediaElement().locale().queryString(
        WebLocalizedString::TextTracksNoLabel));

  return trackLabel;
}

// TextTrack parameter when passed in as a nullptr, creates the "Off" list item
// in the track list.
Element* MediaControlTextTrackListElement::createTextTrackListItem(
    TextTrack* track) {
  int trackIndex = track ? track->trackIndex() : trackIndexOffValue;
  HTMLLabelElement* trackItem = HTMLLabelElement::create(document());
  trackItem->setShadowPseudoId(
      AtomicString("-internal-media-controls-text-track-list-item"));
  HTMLInputElement* trackItemInput =
      HTMLInputElement::create(document(), nullptr, false);
  trackItemInput->setShadowPseudoId(
      AtomicString("-internal-media-controls-text-track-list-item-input"));
  trackItemInput->setType(InputTypeNames::checkbox);
  trackItemInput->setIntegralAttribute(trackIndexAttrName(), trackIndex);
  if (!mediaElement().textTracksVisible()) {
    if (!track)
      trackItemInput->setChecked(true);
  } else {
    // If there are multiple text tracks set to showing, they must all have
    // checkmarks displayed.
    if (track && track->mode() == TextTrack::showingKeyword())
      trackItemInput->setChecked(true);
  }

  trackItem->appendChild(trackItemInput);
  String trackLabel = getTextTrackLabel(track);
  trackItem->appendChild(Text::create(document(), trackLabel));
  // Add a track kind marker icon if there are multiple tracks with the same
  // label or if the track has no label.
  if (track && (track->label().isEmpty() || hasDuplicateLabel(track))) {
    HTMLSpanElement* trackKindMarker = HTMLSpanElement::create(document());
    if (track->kind() == track->captionsKeyword()) {
      trackKindMarker->setShadowPseudoId(AtomicString(
          "-internal-media-controls-text-track-list-kind-captions"));
    } else {
      DCHECK_EQ(track->kind(), track->subtitlesKeyword());
      trackKindMarker->setShadowPseudoId(AtomicString(
          "-internal-media-controls-text-track-list-kind-subtitles"));
    }
    trackItem->appendChild(trackKindMarker);
  }
  return trackItem;
}

void MediaControlTextTrackListElement::refreshTextTrackListMenu() {
  if (!mediaElement().hasClosedCaptions() ||
      !mediaElement().textTracksAreReady())
    return;

  EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
  removeChildren(OmitSubtreeModifiedEvent);

  // Construct a menu for subtitles and captions.  Pass in a nullptr to
  // createTextTrackListItem to create the "Off" track item.
  appendChild(createTextTrackListItem(nullptr));

  TextTrackList* trackList = mediaElement().textTracks();
  for (unsigned i = 0; i < trackList->length(); i++) {
    TextTrack* track = trackList->anonymousIndexedGetter(i);
    if (!track->canBeRendered())
      continue;
    appendChild(createTextTrackListItem(track));
  }
}

// ----------------------------
MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaOverflowButton) {}

MediaControlOverflowMenuButtonElement*
MediaControlOverflowMenuButtonElement::create(MediaControls& mediaControls) {
  MediaControlOverflowMenuButtonElement* button =
      new MediaControlOverflowMenuButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(
      AtomicString("-internal-media-controls-overflow-button"));
  button->setIsWanted(false);
  return button;
}

void MediaControlOverflowMenuButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click) {
    if (mediaControls().overflowMenuVisible())
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.OverflowClose"));
    else
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.OverflowOpen"));

    mediaControls().toggleOverflowMenu();
    event->setDefaultHandled();
  }

  MediaControlInputElement::defaultEventHandler(event);
}

// ----------------------------
MediaControlOverflowMenuListElement::MediaControlOverflowMenuListElement(
    MediaControls& mediaControls)
    : MediaControlDivElement(mediaControls, MediaOverflowList) {}

MediaControlOverflowMenuListElement*
MediaControlOverflowMenuListElement::create(MediaControls& mediaControls) {
  MediaControlOverflowMenuListElement* element =
      new MediaControlOverflowMenuListElement(mediaControls);
  element->setIsWanted(false);
  element->setShadowPseudoId(
      AtomicString("-internal-media-controls-overflow-menu-list"));
  return element;
}

void MediaControlOverflowMenuListElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click)
    event->setDefaultHandled();

  MediaControlDivElement::defaultEventHandler(event);
}

// ----------------------------
MediaControlDownloadButtonElement::MediaControlDownloadButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaDownloadButton) {}

MediaControlDownloadButtonElement* MediaControlDownloadButtonElement::create(
    MediaControls& mediaControls) {
  MediaControlDownloadButtonElement* button =
      new MediaControlDownloadButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(
      AtomicString("-internal-media-controls-download-button"));
  button->setIsWanted(false);
  return button;
}

WebLocalizedString::Name
MediaControlDownloadButtonElement::getOverflowStringName() {
  return WebLocalizedString::OverflowMenuDownload;
}

bool MediaControlDownloadButtonElement::shouldDisplayDownloadButton() {
  const KURL& url = mediaElement().currentSrc();

  // URLs that lead to nowhere are ignored.
  if (url.isNull() || url.isEmpty())
    return false;

  // Local files and blobs should not have a download button.
  if (url.isLocalFile() || url.protocolIs("blob"))
    return false;

  // MediaStream can't be downloaded.
  if (HTMLMediaElement::isMediaStreamURL(url.getString()))
    return false;

  // MediaSource can't be downloaded.
  if (HTMLMediaSource::lookup(url))
    return false;

  return true;
}

void MediaControlDownloadButtonElement::defaultEventHandler(Event* event) {
  const KURL& url = mediaElement().currentSrc();
  if (event->type() == EventTypeNames::click &&
      !(url.isNull() || url.isEmpty())) {
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.Download"));
    if (!m_anchor) {
      HTMLAnchorElement* anchor = HTMLAnchorElement::create(document());
      anchor->setAttribute(HTMLNames::downloadAttr, "");
      m_anchor = anchor;
    }
    m_anchor->setURL(url);
    m_anchor->dispatchSimulatedClick(event);
  }
  MediaControlInputElement::defaultEventHandler(event);
}

DEFINE_TRACE(MediaControlDownloadButtonElement) {
  visitor->trace(m_anchor);
  MediaControlInputElement::trace(visitor);
}

// ----------------------------

MediaControlTimelineElement::MediaControlTimelineElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaSlider) {}

MediaControlTimelineElement* MediaControlTimelineElement::create(
    MediaControls& mediaControls) {
  MediaControlTimelineElement* timeline =
      new MediaControlTimelineElement(mediaControls);
  timeline->ensureUserAgentShadowRoot();
  timeline->setType(InputTypeNames::range);
  timeline->setAttribute(stepAttr, "any");
  timeline->setShadowPseudoId(AtomicString("-webkit-media-controls-timeline"));
  return timeline;
}

void MediaControlTimelineElement::defaultEventHandler(Event* event) {
  if (event->isMouseEvent() &&
      toMouseEvent(event)->button() !=
          static_cast<short>(WebPointerProperties::Button::Left))
    return;

  if (!isConnected() || !document().isActive())
    return;

  if (event->type() == EventTypeNames::mousedown) {
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.ScrubbingBegin"));
    mediaControls().beginScrubbing();
  }

  if (event->type() == EventTypeNames::mouseup) {
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.ScrubbingEnd"));
    mediaControls().endScrubbing();
  }

  MediaControlInputElement::defaultEventHandler(event);

  if (event->type() == EventTypeNames::mouseover ||
      event->type() == EventTypeNames::mouseout ||
      event->type() == EventTypeNames::mousemove)
    return;

  double time = value().toDouble();
  if (event->type() == EventTypeNames::input) {
    // FIXME: This will need to take the timeline offset into consideration
    // once that concept is supported, see https://crbug.com/312699
    if (mediaElement().seekable()->contain(time))
      mediaElement().setCurrentTime(time);
  }

  LayoutSliderItem slider = LayoutSliderItem(toLayoutSlider(layoutObject()));
  if (!slider.isNull() && slider.inDragMode())
    mediaControls().updateCurrentTimeDisplay();
}

bool MediaControlTimelineElement::willRespondToMouseClickEvents() {
  return isConnected() && document().isActive();
}

void MediaControlTimelineElement::setPosition(double currentTime) {
  setValue(String::number(currentTime));

  if (LayoutObject* layoutObject = this->layoutObject())
    layoutObject->setShouldDoFullPaintInvalidation();
}

void MediaControlTimelineElement::setDuration(double duration) {
  setFloatingPointAttribute(maxAttr, std::isfinite(duration) ? duration : 0);

  if (LayoutObject* layoutObject = this->layoutObject())
    layoutObject->setShouldDoFullPaintInvalidation();
}

bool MediaControlTimelineElement::keepEventInNode(Event* event) {
  return isUserInteractionEventForSlider(event, layoutObject());
}

// ----------------------------

MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaVolumeSlider) {}

MediaControlVolumeSliderElement* MediaControlVolumeSliderElement::create(
    MediaControls& mediaControls) {
  MediaControlVolumeSliderElement* slider =
      new MediaControlVolumeSliderElement(mediaControls);
  slider->ensureUserAgentShadowRoot();
  slider->setType(InputTypeNames::range);
  slider->setAttribute(stepAttr, "any");
  slider->setAttribute(maxAttr, "1");
  slider->setShadowPseudoId(
      AtomicString("-webkit-media-controls-volume-slider"));
  return slider;
}

void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) {
  if (event->isMouseEvent() &&
      toMouseEvent(event)->button() !=
          static_cast<short>(WebPointerProperties::Button::Left))
    return;

  if (!isConnected() || !document().isActive())
    return;

  MediaControlInputElement::defaultEventHandler(event);

  if (event->type() == EventTypeNames::mouseover ||
      event->type() == EventTypeNames::mouseout ||
      event->type() == EventTypeNames::mousemove)
    return;

  if (event->type() == EventTypeNames::mousedown)
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.VolumeChangeBegin"));

  if (event->type() == EventTypeNames::mouseup)
    Platform::current()->recordAction(
        UserMetricsAction("Media.Controls.VolumeChangeEnd"));

  double volume = value().toDouble();
  mediaElement().setVolume(volume, ASSERT_NO_EXCEPTION);
  mediaElement().setMuted(false);
}

bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents() {
  if (!isConnected() || !document().isActive())
    return false;

  return MediaControlInputElement::willRespondToMouseMoveEvents();
}

bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents() {
  if (!isConnected() || !document().isActive())
    return false;

  return MediaControlInputElement::willRespondToMouseClickEvents();
}

void MediaControlVolumeSliderElement::setVolume(double volume) {
  if (value().toDouble() != volume)
    setValue(String::number(volume));
}

bool MediaControlVolumeSliderElement::keepEventInNode(Event* event) {
  return isUserInteractionEventForSlider(event, layoutObject());
}

// ----------------------------

MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(
    MediaControls& mediaControls)
    : MediaControlInputElement(mediaControls, MediaEnterFullscreenButton) {}

MediaControlFullscreenButtonElement*
MediaControlFullscreenButtonElement::create(MediaControls& mediaControls) {
  MediaControlFullscreenButtonElement* button =
      new MediaControlFullscreenButtonElement(mediaControls);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  button->setShadowPseudoId(
      AtomicString("-webkit-media-controls-fullscreen-button"));
  button->setIsWanted(false);
  return button;
}

void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click) {
    if (mediaElement().isFullscreen()) {
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.ExitFullscreen"));
      mediaElement().exitFullscreen();
    } else {
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.EnterFullscreen"));
      mediaElement().enterFullscreen();
    }
    event->setDefaultHandled();
  }
  MediaControlInputElement::defaultEventHandler(event);
}

void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen) {
  setDisplayType(isFullscreen ? MediaExitFullscreenButton
                              : MediaEnterFullscreenButton);
}

WebLocalizedString::Name
MediaControlFullscreenButtonElement::getOverflowStringName() {
  if (mediaElement().isFullscreen())
    return WebLocalizedString::OverflowMenuExitFullscreen;
  return WebLocalizedString::OverflowMenuEnterFullscreen;
}

// ----------------------------

MediaControlCastButtonElement::MediaControlCastButtonElement(
    MediaControls& mediaControls,
    bool isOverlayButton)
    : MediaControlInputElement(mediaControls, MediaCastOnButton),
      m_isOverlayButton(isOverlayButton) {
  if (m_isOverlayButton)
    recordMetrics(CastOverlayMetrics::Created);
  setIsPlayingRemotely(false);
}

MediaControlCastButtonElement* MediaControlCastButtonElement::create(
    MediaControls& mediaControls,
    bool isOverlayButton) {
  MediaControlCastButtonElement* button =
      new MediaControlCastButtonElement(mediaControls, isOverlayButton);
  button->ensureUserAgentShadowRoot();
  button->setType(InputTypeNames::button);
  return button;
}

void MediaControlCastButtonElement::defaultEventHandler(Event* event) {
  if (event->type() == EventTypeNames::click) {
    if (m_isOverlayButton)
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.CastOverlay"));
    else
      Platform::current()->recordAction(
          UserMetricsAction("Media.Controls.Cast"));

    if (m_isOverlayButton && !m_clickUseCounted) {
      m_clickUseCounted = true;
      recordMetrics(CastOverlayMetrics::Clicked);
    }
    if (mediaElement().isPlayingRemotely()) {
      mediaElement().requestRemotePlaybackControl();
    } else {
      mediaElement().requestRemotePlayback();
    }
  }
  MediaControlInputElement::defaultEventHandler(event);
}

const AtomicString& MediaControlCastButtonElement::shadowPseudoId() const {
  DEFINE_STATIC_LOCAL(AtomicString, id_nonOverlay,
                      ("-internal-media-controls-cast-button"));
  DEFINE_STATIC_LOCAL(AtomicString, id_overlay,
                      ("-internal-media-controls-overlay-cast-button"));
  return m_isOverlayButton ? id_overlay : id_nonOverlay;
}

void MediaControlCastButtonElement::setIsPlayingRemotely(
    bool isPlayingRemotely) {
  if (isPlayingRemotely) {
    if (m_isOverlayButton) {
      setDisplayType(MediaOverlayCastOnButton);
    } else {
      setDisplayType(MediaCastOnButton);
    }
  } else {
    if (m_isOverlayButton) {
      setDisplayType(MediaOverlayCastOffButton);
    } else {
      setDisplayType(MediaCastOffButton);
    }
  }
  updateOverflowString();
}

WebLocalizedString::Name
MediaControlCastButtonElement::getOverflowStringName() {
  if (mediaElement().isPlayingRemotely())
    return WebLocalizedString::OverflowMenuStopCast;
  return WebLocalizedString::OverflowMenuCast;
}

void MediaControlCastButtonElement::tryShowOverlay() {
  DCHECK(m_isOverlayButton);

  setIsWanted(true);
  if (elementFromCenter(*this) != &mediaElement()) {
    setIsWanted(false);
    return;
  }

  DCHECK(isWanted());
  if (!m_showUseCounted) {
    m_showUseCounted = true;
    recordMetrics(CastOverlayMetrics::Shown);
  }
}

bool MediaControlCastButtonElement::keepEventInNode(Event* event) {
  return isUserInteractionEvent(event);
}

void MediaControlCastButtonElement::recordMetrics(CastOverlayMetrics metric) {
  DCHECK(m_isOverlayButton);
  DEFINE_STATIC_LOCAL(
      EnumerationHistogram, overlayHistogram,
      ("Cast.Sender.Overlay", static_cast<int>(CastOverlayMetrics::Count)));
  overlayHistogram.count(static_cast<int>(metric));
}

// ----------------------------

MediaControlTimeRemainingDisplayElement::
    MediaControlTimeRemainingDisplayElement(MediaControls& mediaControls)
    : MediaControlTimeDisplayElement(mediaControls, MediaTimeRemainingDisplay) {
}

MediaControlTimeRemainingDisplayElement*
MediaControlTimeRemainingDisplayElement::create(MediaControls& mediaControls) {
  MediaControlTimeRemainingDisplayElement* element =
      new MediaControlTimeRemainingDisplayElement(mediaControls);
  element->setShadowPseudoId(
      AtomicString("-webkit-media-controls-time-remaining-display"));
  return element;
}

// ----------------------------

MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(
    MediaControls& mediaControls)
    : MediaControlTimeDisplayElement(mediaControls, MediaCurrentTimeDisplay) {}

MediaControlCurrentTimeDisplayElement*
MediaControlCurrentTimeDisplayElement::create(MediaControls& mediaControls) {
  MediaControlCurrentTimeDisplayElement* element =
      new MediaControlCurrentTimeDisplayElement(mediaControls);
  element->setShadowPseudoId(
      AtomicString("-webkit-media-controls-current-time-display"));
  return element;
}

}  // namespace blink
