/*
 * 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 "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"

#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_init.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element_controls_list.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/text_track_container.h"
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_animated_arrow_container_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_button_panel_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_enclosure_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_panel_enclosure_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h"
#include "third_party/blink/renderer/modules/media_controls/media_download_in_product_help_manager.h"
#include "third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.h"
#include "third_party/blink/renderer/modules/remoteplayback/remote_playback.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/web_test_support.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);

// TODO(steimel): When modern media controls launches, remove above constants
// and rename below constants.
// (2px left border + 6px left padding + 56px button + 6px right padding + 2px
// right border) = 72px.
constexpr int kModernMinWidthForOverlayPlayButton = 72;

constexpr int kMinScrubbingMessageWidth = 300;

const char* kStateCSSClasses[7] = {
    "state-no-source",         // kNoSource
    "state-no-metadata",       // kNotLoaded
    "state-loading-metadata",  // kLoadingMetadata
    "state-stopped",           // kStopped
    "state-playing",           // kPlaying
    "state-buffering",         // kBuffering
    "state-scrubbing",         // kScrubbing
};

// The padding in pixels inside the button panel.
constexpr int kModernControlsAudioButtonPadding = 20;
constexpr int kModernControlsVideoButtonPadding = 26;

const char kShowDefaultPosterCSSClass[] = "use-default-poster";
const char kActAsAudioControlsCSSClass[] = "audio-only";
const char kScrubbingMessageCSSClass[] = "scrubbing-message";
const char kTestModeCSSClass[] = "test-mode";
const char kImmersiveModeCSSClass[] = "immersive-mode";
const char kPipPresentedCSSClass[] = "pip-presented";

// The delay between two taps to be recognized as a double tap gesture.
constexpr WTF::TimeDelta kDoubleTapDelay = TimeDelta::FromMilliseconds(300);

// The time user have to hover on mute button to show volume slider.
// If this value is changed, you need to change the corresponding value in
// media_controls_impl_test.cc
constexpr WTF::TimeDelta kTimeToShowVolumeSlider =
    TimeDelta::FromMilliseconds(200);
constexpr WTF::TimeDelta kTimeToShowVolumeSliderTest =
    TimeDelta::FromMilliseconds(0);

// The number of seconds to jump when double tapping.
constexpr int kNumberOfSecondsToJump = 10;

bool ShouldShowFullscreenButton(const HTMLMediaElement& media_element) {
  // 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 (media_element.IsFullscreen())
    return true;

  if (!media_element.IsHTMLVideoElement())
    return false;

  if (!media_element.HasVideo())
    return false;

  if (!Fullscreen::FullscreenEnabled(media_element.GetDocument()))
    return false;

  if (media_element.ControlsListInternal()->ShouldHideFullscreen()) {
    UseCounter::Count(media_element.GetDocument(),
                      WebFeature::kHTMLMediaElementControlsListNoFullscreen);
    return false;
  }

  return true;
}

void MaybeParserAppendChild(Element* parent, Element* child) {
  DCHECK(parent);
  if (child)
    parent->ParserAppendChild(child);
}

bool ShouldShowPictureInPictureButton(HTMLMediaElement& media_element) {
  return media_element.SupportsPictureInPicture();
}

bool ShouldShowCastButton(HTMLMediaElement& media_element) {
  if (media_element.FastHasAttribute(html_names::kDisableremoteplaybackAttr))
    return false;

  // Explicitly do not show cast button when:
  // - the mediaControlsEnabled setting is false, to make sure the overlay does
  //   not appear;
  // - the immersiveModeEnabled setting is true.
  Document& document = media_element.GetDocument();
  if (document.GetSettings() &&
      (!document.GetSettings()->GetMediaControlsEnabled() ||
       document.GetSettings()->GetImmersiveModeEnabled())) {
    return false;
  }

  // The page disabled the button via the attribute.
  if (media_element.ControlsListInternal()->ShouldHideRemotePlayback()) {
    UseCounter::Count(
        media_element.GetDocument(),
        WebFeature::kHTMLMediaElementControlsListNoRemotePlayback);
    return false;
  }

  RemotePlayback* remote =
      HTMLMediaElementRemotePlayback::remote(media_element);
  return remote && remote->RemotePlaybackAvailable();
}

bool PreferHiddenVolumeControls(const Document& document) {
  return !document.GetSettings() ||
         document.GetSettings()->GetPreferHiddenVolumeControls();
}

// If you change this value, then also update the corresponding value in
// web_tests/media/media-controls.js.
constexpr TimeDelta kTimeWithoutMouseMovementBeforeHidingMediaControls =
    TimeDelta::FromSeconds(3);
constexpr TimeDelta kModernTimeWithoutMouseMovementBeforeHidingMediaControls =
    TimeDelta::FromSecondsD(2.5);

TimeDelta GetTimeWithoutMouseMovementBeforeHidingMediaControls() {
  return MediaControlsImpl::IsModern()
             ? kModernTimeWithoutMouseMovementBeforeHidingMediaControls
             : kTimeWithoutMouseMovementBeforeHidingMediaControls;
}

}  // namespace

class MediaControlsImpl::BatchedControlUpdate {
  WTF_MAKE_NONCOPYABLE(BatchedControlUpdate);
  STACK_ALLOCATED();

 public:
  explicit BatchedControlUpdate(MediaControlsImpl* controls)
      : controls_(controls) {
    DCHECK(IsMainThread());
    DCHECK_GE(batch_depth_, 0);
    ++batch_depth_;
  }
  ~BatchedControlUpdate() {
    DCHECK(IsMainThread());
    DCHECK_GT(batch_depth_, 0);
    if (!(--batch_depth_))
      controls_->ComputeWhichControlsFit();
  }

 private:
  Member<MediaControlsImpl> controls_;
  static int batch_depth_;
};

// Count of number open batches for controls visibility.
int MediaControlsImpl::BatchedControlUpdate::batch_depth_ = 0;

class MediaControlsImpl::MediaControlsResizeObserverDelegate final
    : public ResizeObserver::Delegate {
 public:
  explicit MediaControlsResizeObserverDelegate(MediaControlsImpl* controls)
      : controls_(controls) {
    DCHECK(controls);
  }
  ~MediaControlsResizeObserverDelegate() override = default;

  void OnResize(
      const HeapVector<Member<ResizeObserverEntry>>& entries) override {
    DCHECK_EQ(1u, entries.size());
    DCHECK_EQ(entries[0]->target(), controls_->MediaElement());
    controls_->NotifyElementSizeChanged(entries[0]->contentRect());
  }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(controls_);
    ResizeObserver::Delegate::Trace(visitor);
  }

 private:
  Member<MediaControlsImpl> controls_;
};

// Observes changes to the HTMLMediaElement attributes that affect controls.
class MediaControlsImpl::MediaElementMutationCallback
    : public MutationObserver::Delegate {
 public:
  explicit MediaElementMutationCallback(MediaControlsImpl* controls)
      : controls_(controls), observer_(MutationObserver::Create(this)) {
    MutationObserverInit* init = MutationObserverInit::Create();
    init->setAttributeOldValue(true);
    init->setAttributes(true);
    init->setAttributeFilter(
        {html_names::kDisableremoteplaybackAttr.ToString(),
         html_names::kDisablepictureinpictureAttr.ToString(),
         html_names::kPosterAttr.ToString()});
    observer_->observe(&controls_->MediaElement(), init, ASSERT_NO_EXCEPTION);
  }

  ExecutionContext* GetExecutionContext() const override {
    return &controls_->GetDocument();
  }

  void Deliver(const MutationRecordVector& records,
               MutationObserver&) override {
    for (const auto& record : records) {
      if (record->type() != "attributes")
        continue;

      const Element& element = *ToElement(record->target());
      if (record->oldValue() == element.getAttribute(record->attributeName()))
        continue;

      if (record->attributeName() ==
          html_names::kDisableremoteplaybackAttr.ToString()) {
        controls_->RefreshCastButtonVisibilityWithoutUpdate();
      }

      if (record->attributeName() ==
              html_names::kDisablepictureinpictureAttr.ToString() &&
          controls_->picture_in_picture_button_) {
        controls_->picture_in_picture_button_->SetIsWanted(
            ShouldShowPictureInPictureButton(controls_->MediaElement()));
      }

      if (record->attributeName() == html_names::kPosterAttr.ToString())
        controls_->UpdateCSSClassFromState();

      BatchedControlUpdate batch(controls_);
    }
  }

  void Disconnect() { observer_->disconnect(); }

  void Trace(blink::Visitor* visitor) override {
    visitor->Trace(controls_);
    visitor->Trace(observer_);
    MutationObserver::Delegate::Trace(visitor);
  }

 private:
  Member<MediaControlsImpl> controls_;
  Member<MutationObserver> observer_;
};

// static
bool MediaControlsImpl::IsModern() {
  return RuntimeEnabledFeatures::ModernMediaControlsEnabled();
}

bool MediaControlsImpl::IsTouchEvent(Event* event) {
  return event->IsTouchEvent() || event->IsGestureEvent() ||
         (event->IsMouseEvent() && ToMouseEvent(event)->FromTouch());
}

MediaControlsImpl::MediaControlsImpl(HTMLMediaElement& media_element)
    : HTMLDivElement(media_element.GetDocument()),
      MediaControls(media_element),
      overlay_enclosure_(nullptr),
      overlay_play_button_(nullptr),
      overlay_cast_button_(nullptr),
      enclosure_(nullptr),
      panel_(nullptr),
      play_button_(nullptr),
      timeline_(nullptr),
      scrubbing_message_(nullptr),
      current_time_display_(nullptr),
      duration_display_(nullptr),
      mute_button_(nullptr),
      volume_slider_(nullptr),
      toggle_closed_captions_button_(nullptr),
      text_track_list_(nullptr),
      overflow_list_(nullptr),
      media_button_panel_(nullptr),
      loading_panel_(nullptr),
      picture_in_picture_button_(nullptr),
      animated_arrow_container_element_(nullptr),
      cast_button_(nullptr),
      fullscreen_button_(nullptr),
      display_cutout_fullscreen_button_(nullptr),
      download_button_(nullptr),
      media_event_listener_(
          MakeGarbageCollected<MediaControlsMediaEventListener>(this)),
      orientation_lock_delegate_(nullptr),
      rotate_to_fullscreen_delegate_(nullptr),
      display_cutout_delegate_(nullptr),
      hide_media_controls_timer_(
          media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
          this,
          &MediaControlsImpl::HideMediaControlsTimerFired),
      hide_timer_behavior_flags_(kIgnoreNone),
      is_mouse_over_controls_(false),
      is_paused_for_scrubbing_(false),
      resize_observer_(ResizeObserver::Create(
          media_element.GetDocument(),
          MakeGarbageCollected<MediaControlsResizeObserverDelegate>(this))),
      element_size_changed_timer_(
          media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
          this,
          &MediaControlsImpl::ElementSizeChangedTimerFired),
      keep_showing_until_timer_fires_(false),
      tap_timer_(
          media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
          this,
          &MediaControlsImpl::TapTimerFired),
      volume_slider_wanted_timer_(
          media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
          this,
          &MediaControlsImpl::VolumeSliderWantedTimerFired) {
  // On touch devices, start with the assumption that the user will interact via
  // touch events.
  Settings* settings = media_element.GetDocument().GetSettings();
  is_touch_interaction_ = settings ? settings->GetMaxTouchPoints() > 0 : false;

  resize_observer_->observe(&media_element);
}

MediaControlsImpl* MediaControlsImpl::Create(HTMLMediaElement& media_element,
                                             ShadowRoot& shadow_root) {
  MediaControlsImpl* controls =
      MakeGarbageCollected<MediaControlsImpl>(media_element);
  controls->SetShadowPseudoId(AtomicString("-webkit-media-controls"));
  controls->InitializeControls();
  controls->Reset();

  if (RuntimeEnabledFeatures::VideoFullscreenOrientationLockEnabled() &&
      media_element.IsHTMLVideoElement()) {
    // Initialize the orientation lock when going fullscreen feature.
    controls->orientation_lock_delegate_ =
        MakeGarbageCollected<MediaControlsOrientationLockDelegate>(
            ToHTMLVideoElement(media_element));
  }

  if (MediaControlsDisplayCutoutDelegate::IsEnabled() &&
      media_element.IsHTMLVideoElement()) {
    // Initialize the pinch gesture to expand into the display cutout feature.
    controls->display_cutout_delegate_ =
        MakeGarbageCollected<MediaControlsDisplayCutoutDelegate>(
            ToHTMLVideoElement(media_element));
  }

  if (RuntimeEnabledFeatures::VideoRotateToFullscreenEnabled() &&
      media_element.IsHTMLVideoElement()) {
    // Initialize the rotate-to-fullscreen feature.
    controls->rotate_to_fullscreen_delegate_ =
        MakeGarbageCollected<MediaControlsRotateToFullscreenDelegate>(
            ToHTMLVideoElement(media_element));
  }

  // Initialize download in-product-help for video elements if enabled.
  if (media_element.GetDocument().GetSettings() &&
      media_element.GetDocument()
          .GetSettings()
          ->GetMediaDownloadInProductHelpEnabled() &&
      media_element.IsHTMLVideoElement()) {
    controls->download_iph_manager_ =
        MakeGarbageCollected<MediaDownloadInProductHelpManager>(*controls);
  }

  MediaControlsResourceLoader::InjectMediaControlsUAStyleSheet();

  shadow_root.ParserAppendChild(controls);
  return controls;
}

// The media controls DOM structure looks like:
//
// MediaControlsImpl
//     (-webkit-media-controls)
// +-MediaControlLoadingPanelElement
// |    (-internal-media-controls-loading-panel)
// |    {if ModernMediaControlsEnabled}
// +-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)
//     |  {if ModernMediaControlsEnabled and is video element and is Android}
//     +-MediaControlScrubbingMessageElement
//     |  (-internal-media-controls-scrubbing-message)
//     |  {if ModernMediaControlsEnabled, otherwise
//     |   contents are directly attached to parent.
//     +-MediaControlOverlayPlayButtonElement
//     |  (-webkit-media-controls-overlay-play-button)
//     |  {if ModernMediaControlsEnabled}
//     +-MediaControlButtonPanelElement
//     |  |  (-internal-media-controls-button-panel)
//     |  |  <video> only, otherwise children are directly attached to parent
//     |  +-MediaControlPlayButtonElement
//     |  |    (-webkit-media-controls-play-button)
//     |  |    {only present if audio only or ModernMediaControls is disabled}
//     |  +-MediaControlCurrentTimeDisplayElement
//     |  |    (-webkit-media-controls-current-time-display)
//     |  +-MediaControlRemainingTimeDisplayElement
//     |  |    (-webkit-media-controls-time-remaining-display)
//     |  +-HTMLDivElement
//     |  |    (-internal-media-controls-button-spacer)
//     |  |    {if ModernMediaControls is enabled and is video element}
//     |  +-MediaControlMuteButtonElement
//     |  |    (-webkit-media-controls-mute-button)
//     |  +-MediaControlVolumeSliderElement
//     |  |    (-webkit-media-controls-volume-slider)
//     |  |    {if not ModernMediaControlsEnabled}
//     |  +-MediaControlPictureInPictureButtonElement
//     |  |    (-webkit-media-controls-picture-in-picture-button)
//     |  +-MediaControlFullscreenButtonElement
//     |  |    (-webkit-media-controls-fullscreen-button)
//     |  +-MediaControlDownloadButtonElement
//     |  |    (-internal-media-controls-download-button)
//     |  |    {on the overflow menu if ModernMediaControls is enabled}
//     |  +-MediaControlToggleClosedCaptionsButtonElement
//     |  |    (-webkit-media-controls-toggle-closed-captions-button)
//     |  |    {on the overflow menu if ModernMediaControls is enabled}
//     |  +-MediaControlCastButtonElement
//     |       (-internal-media-controls-cast-button)
//     |       {on the overflow menu if ModernMediaControls is enabled}
//     \-MediaControlTimelineElement
//          (-webkit-media-controls-timeline)
// +-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)
// +-MediaControlDisplayCutoutFullscreenElement
//       (-internal-media-controls-display-cutout-fullscreen-button)
void MediaControlsImpl::InitializeControls() {
  if (IsModern() && ShouldShowVideoControls()) {
    loading_panel_ =
        MakeGarbageCollected<MediaControlLoadingPanelElement>(*this);
    ParserAppendChild(loading_panel_);
  }

  overlay_enclosure_ =
      MakeGarbageCollected<MediaControlOverlayEnclosureElement>(*this);

  if (RuntimeEnabledFeatures::MediaControlsOverlayPlayButtonEnabled()) {
    overlay_play_button_ =
        MakeGarbageCollected<MediaControlOverlayPlayButtonElement>(*this);

    if (!IsModern())
      overlay_enclosure_->ParserAppendChild(overlay_play_button_);
  }

  overlay_cast_button_ =
      MakeGarbageCollected<MediaControlCastButtonElement>(*this, true);
  overlay_enclosure_->ParserAppendChild(overlay_cast_button_);

  ParserAppendChild(overlay_enclosure_);

  // Create an enclosing element for the panel so we can visually offset the
  // controls correctly.
  enclosure_ = MakeGarbageCollected<MediaControlPanelEnclosureElement>(*this);

  panel_ = MakeGarbageCollected<MediaControlPanelElement>(*this);

  // If using the modern media controls, the buttons should belong to a
  // seperate button panel. This is because they are displayed in two lines.
  if (IsModern() && ShouldShowVideoControls()) {
    media_button_panel_ =
        MakeGarbageCollected<MediaControlButtonPanelElement>(*this);
    scrubbing_message_ =
        MakeGarbageCollected<MediaControlScrubbingMessageElement>(*this);
  }

  play_button_ = MakeGarbageCollected<MediaControlPlayButtonElement>(*this);

  current_time_display_ =
      MakeGarbageCollected<MediaControlCurrentTimeDisplayElement>(*this);
  current_time_display_->SetIsWanted(true);

  duration_display_ =
      MakeGarbageCollected<MediaControlRemainingTimeDisplayElement>(*this);
  timeline_ = MakeGarbageCollected<MediaControlTimelineElement>(*this);
  mute_button_ = MakeGarbageCollected<MediaControlMuteButtonElement>(*this);

  volume_slider_ = MakeGarbageCollected<MediaControlVolumeSliderElement>(*this);
  if (PreferHiddenVolumeControls(GetDocument()))
    volume_slider_->SetIsWanted(false);

  if (RuntimeEnabledFeatures::PictureInPictureEnabled() &&
      GetDocument().GetSettings() &&
      GetDocument().GetSettings()->GetPictureInPictureEnabled() &&
      MediaElement().IsHTMLVideoElement()) {
    picture_in_picture_button_ =
        MakeGarbageCollected<MediaControlPictureInPictureButtonElement>(*this);
    picture_in_picture_button_->SetIsWanted(
        ShouldShowPictureInPictureButton(MediaElement()));
  }

  if (RuntimeEnabledFeatures::DisplayCutoutAPIEnabled() &&
      MediaElement().IsHTMLVideoElement()) {
    display_cutout_fullscreen_button_ =
        MakeGarbageCollected<MediaControlDisplayCutoutFullscreenButtonElement>(
            *this);
  }

  fullscreen_button_ =
      MakeGarbageCollected<MediaControlFullscreenButtonElement>(*this);
  download_button_ =
      MakeGarbageCollected<MediaControlDownloadButtonElement>(*this);
  cast_button_ =
      MakeGarbageCollected<MediaControlCastButtonElement>(*this, false);
  toggle_closed_captions_button_ =
      MakeGarbageCollected<MediaControlToggleClosedCaptionsButtonElement>(
          *this);
  overflow_menu_ =
      MakeGarbageCollected<MediaControlOverflowMenuButtonElement>(*this);

  PopulatePanel();
  enclosure_->ParserAppendChild(panel_);

  ParserAppendChild(enclosure_);

  text_track_list_ =
      MakeGarbageCollected<MediaControlTextTrackListElement>(*this);
  ParserAppendChild(text_track_list_);

  overflow_list_ =
      MakeGarbageCollected<MediaControlOverflowMenuListElement>(*this);
  ParserAppendChild(overflow_list_);

  // 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.
  overflow_list_->ParserAppendChild(play_button_->CreateOverflowElement(
      MakeGarbageCollected<MediaControlPlayButtonElement>(*this)));
  overflow_list_->ParserAppendChild(fullscreen_button_->CreateOverflowElement(
      MakeGarbageCollected<MediaControlFullscreenButtonElement>(*this)));
  overflow_list_->ParserAppendChild(download_button_->CreateOverflowElement(
      MakeGarbageCollected<MediaControlDownloadButtonElement>(*this)));
  overflow_list_->ParserAppendChild(mute_button_->CreateOverflowElement(
      MakeGarbageCollected<MediaControlMuteButtonElement>(*this)));
  overflow_list_->ParserAppendChild(cast_button_->CreateOverflowElement(
      MakeGarbageCollected<MediaControlCastButtonElement>(*this, false)));
  overflow_list_->ParserAppendChild(
      toggle_closed_captions_button_->CreateOverflowElement(
          MakeGarbageCollected<MediaControlToggleClosedCaptionsButtonElement>(
              *this)));
  if (picture_in_picture_button_) {
    overflow_list_->ParserAppendChild(
        picture_in_picture_button_->CreateOverflowElement(
            MakeGarbageCollected<MediaControlPictureInPictureButtonElement>(
                *this)));
  }

  // Set the default CSS classes.
  UpdateCSSClassFromState();
}

void MediaControlsImpl::PopulatePanel() {
  // Clear the panels.
  panel_->setInnerHTML(StringOrTrustedHTML::FromString(""));
  if (media_button_panel_)
    media_button_panel_->setInnerHTML(StringOrTrustedHTML::FromString(""));

  Element* button_panel = panel_;
  if (IsModern() && ShouldShowVideoControls()) {
    MaybeParserAppendChild(panel_, scrubbing_message_);
    if (display_cutout_fullscreen_button_)
      panel_->ParserAppendChild(display_cutout_fullscreen_button_);

    MaybeParserAppendChild(panel_, overlay_play_button_);
    panel_->ParserAppendChild(media_button_panel_);
    button_panel = media_button_panel_;
  }

  button_panel->ParserAppendChild(play_button_);
  button_panel->ParserAppendChild(current_time_display_);
  button_panel->ParserAppendChild(duration_display_);

  if (IsModern() && ShouldShowVideoControls()) {
    MediaControlElementsHelper::CreateDiv(
        "-internal-media-controls-button-spacer", button_panel);
  }

  panel_->ParserAppendChild(timeline_);

  // On modern controls, the volume slider is to the left of the mute button.
  if (IsModern()) {
    MaybeParserAppendChild(button_panel, volume_slider_);
    button_panel->ParserAppendChild(mute_button_);
  } else {
    button_panel->ParserAppendChild(mute_button_);
    MaybeParserAppendChild(button_panel, volume_slider_);
  }

  MaybeParserAppendChild(button_panel, picture_in_picture_button_);

  button_panel->ParserAppendChild(fullscreen_button_);

  // The download, cast and captions buttons should not be present on the modern
  // controls button panel.
  if (!IsModern()) {
    button_panel->ParserAppendChild(download_button_);
    button_panel->ParserAppendChild(cast_button_);
    button_panel->ParserAppendChild(toggle_closed_captions_button_);
  }

  button_panel->ParserAppendChild(overflow_menu_);
}

Node::InsertionNotificationRequest MediaControlsImpl::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.
  media_event_listener_->Attach();
  if (orientation_lock_delegate_)
    orientation_lock_delegate_->Attach();
  if (rotate_to_fullscreen_delegate_)
    rotate_to_fullscreen_delegate_->Attach();
  if (display_cutout_delegate_)
    display_cutout_delegate_->Attach();

  if (!resize_observer_) {
    resize_observer_ = ResizeObserver::Create(
        MediaElement().GetDocument(),
        MakeGarbageCollected<MediaControlsResizeObserverDelegate>(this));
    HTMLMediaElement& html_media_element = MediaElement();
    resize_observer_->observe(&html_media_element);
  }

  if (!element_mutation_callback_) {
    element_mutation_callback_ =
        MakeGarbageCollected<MediaElementMutationCallback>(this);
  }

  return HTMLDivElement::InsertedInto(root);
}

void MediaControlsImpl::UpdateCSSClassFromState() {
  const ControlsState state = State();

  Vector<String> toAdd;
  Vector<String> toRemove;

  if (state < kLoadingMetadata)
    toAdd.push_back("phase-pre-ready");
  else
    toRemove.push_back("phase-pre-ready");

  if (state > kLoadingMetadata)
    toAdd.push_back("phase-ready");
  else
    toRemove.push_back("phase-ready");

  for (int i = 0; i < 7; i++) {
    if (i == state)
      toAdd.push_back(kStateCSSClasses[i]);
    else
      toRemove.push_back(kStateCSSClasses[i]);
  }

  if (MediaElement().ShouldShowControls() && ShouldShowVideoControls() &&
      !VideoElement().HasAvailableVideoFrame() &&
      VideoElement().PosterImageURL().IsEmpty() &&
      state <= ControlsState::kLoadingMetadata) {
    toAdd.push_back(kShowDefaultPosterCSSClass);
  } else {
    toRemove.push_back(kShowDefaultPosterCSSClass);
  }

  if (ShouldShowVideoControls() && GetDocument().GetSettings() &&
      GetDocument().GetSettings()->GetImmersiveModeEnabled()) {
    toAdd.push_back(kImmersiveModeCSSClass);
  } else {
    toRemove.push_back(kImmersiveModeCSSClass);
  }

  classList().add(toAdd, ASSERT_NO_EXCEPTION);
  classList().remove(toRemove, ASSERT_NO_EXCEPTION);

  if (loading_panel_)
    loading_panel_->UpdateDisplayState();

  // If we are in the "no-source" state we should show the overflow menu on a
  // video element.
  if (IsModern()) {
    bool updated = false;

    if (state == kNoSource) {
      // Check if the play button or overflow menu has the "disabled" attribute
      // set so we avoid unnecessarily resetting it.
      if (!play_button_->hasAttribute(html_names::kDisabledAttr)) {
        play_button_->setAttribute(html_names::kDisabledAttr, "");
        updated = true;
      }

      if (ShouldShowVideoControls() &&
          !overflow_menu_->hasAttribute(html_names::kDisabledAttr)) {
        overflow_menu_->setAttribute(html_names::kDisabledAttr, "");
        updated = true;
      }
    } else {
      if (play_button_->hasAttribute(html_names::kDisabledAttr)) {
        play_button_->removeAttribute(html_names::kDisabledAttr);
        updated = true;
      }

      if (overflow_menu_->hasAttribute(html_names::kDisabledAttr)) {
        overflow_menu_->removeAttribute(html_names::kDisabledAttr);
        updated = true;
      }
    }

    if (updated)
      UpdateOverflowMenuWanted();
  }
}

void MediaControlsImpl::SetClass(const AtomicString& class_name,
                                 bool should_have_class) {
  if (should_have_class && !classList().contains(class_name))
    classList().Add(class_name);
  else if (!should_have_class && classList().contains(class_name))
    classList().Remove(class_name);
}

MediaControlsImpl::ControlsState MediaControlsImpl::State() const {
  HTMLMediaElement::NetworkState network_state =
      MediaElement().getNetworkState();
  HTMLMediaElement::ReadyState ready_state = MediaElement().getReadyState();

  if (is_scrubbing_ && ready_state != HTMLMediaElement::kHaveNothing)
    return ControlsState::kScrubbing;

  switch (network_state) {
    case HTMLMediaElement::kNetworkEmpty:
    case HTMLMediaElement::kNetworkNoSource:
      return ControlsState::kNoSource;
    case HTMLMediaElement::kNetworkLoading:
      if (ready_state == HTMLMediaElement::kHaveNothing)
        return ControlsState::kLoadingMetadata;
      if (!MediaElement().paused() &&
          ready_state != HTMLMediaElement::kHaveEnoughData) {
        return ControlsState::kBuffering;
      }
      break;
    case HTMLMediaElement::kNetworkIdle:
      if (ready_state == HTMLMediaElement::kHaveNothing)
        return ControlsState::kNotLoaded;
      break;
  }

  if (!MediaElement().paused())
    return ControlsState::kPlaying;
  return ControlsState::kStopped;
}

void MediaControlsImpl::RemovedFrom(ContainerNode& insertion_point) {
  DCHECK(!MediaElement().isConnected());

  HTMLDivElement::RemovedFrom(insertion_point);

  Hide();

  media_event_listener_->Detach();
  if (orientation_lock_delegate_)
    orientation_lock_delegate_->Detach();
  if (rotate_to_fullscreen_delegate_)
    rotate_to_fullscreen_delegate_->Detach();
  if (display_cutout_delegate_)
    display_cutout_delegate_->Detach();

  if (resize_observer_) {
    resize_observer_->disconnect();
    resize_observer_.Clear();
  }

  if (element_mutation_callback_) {
    element_mutation_callback_->Disconnect();
    element_mutation_callback_.Clear();
  }
}

void MediaControlsImpl::Reset() {
  EventDispatchForbiddenScope::AllowUserAgentEvents allow_events_in_shadow;
  BatchedControlUpdate batch(this);

  OnDurationChange();

  // Show everything that we might hide.
  current_time_display_->SetIsWanted(true);
  timeline_->SetIsWanted(true);

  // If the player has entered an error state, force it into the paused state.
  if (MediaElement().error())
    MediaElement().pause();

  UpdatePlayState();

  UpdateCurrentTimeDisplay();

  timeline_->SetPosition(MediaElement().currentTime());

  OnVolumeChange();
  OnTextTracksAddedOrRemoved();

  if (picture_in_picture_button_) {
    picture_in_picture_button_->SetIsWanted(
        ShouldShowPictureInPictureButton(MediaElement()));
  }

  UpdateCSSClassFromState();
  UpdateSizingCSSClass();
  OnControlsListUpdated();
}

void MediaControlsImpl::OnControlsListUpdated() {
  BatchedControlUpdate batch(this);

  if (IsModern() && ShouldShowVideoControls()) {
    fullscreen_button_->SetIsWanted(true);
    fullscreen_button_->setAttribute(html_names::kDisabledAttr,
                                     ShouldShowFullscreenButton(MediaElement())
                                         ? AtomicString()
                                         : AtomicString(""));
  } else {
    fullscreen_button_->SetIsWanted(ShouldShowFullscreenButton(MediaElement()));
    fullscreen_button_->removeAttribute(html_names::kDisabledAttr);
  }

  RefreshCastButtonVisibilityWithoutUpdate();

  download_button_->SetIsWanted(
      download_button_->ShouldDisplayDownloadButton());
}

LayoutObject* MediaControlsImpl::PanelLayoutObject() {
  return panel_->GetLayoutObject();
}

LayoutObject* MediaControlsImpl::TimelineLayoutObject() {
  return timeline_->GetLayoutObject();
}

LayoutObject* MediaControlsImpl::ButtonPanelLayoutObject() {
  return media_button_panel_->GetLayoutObject();
}

LayoutObject* MediaControlsImpl::ContainerLayoutObject() {
  return GetLayoutObject();
}

void MediaControlsImpl::SetTestMode(bool enable) {
  is_test_mode_ = enable;
  SetClass(kTestModeCSSClass, enable);
}

void MediaControlsImpl::MaybeShow() {
  panel_->SetIsWanted(true);
  panel_->SetIsDisplayed(true);

  UpdateCurrentTimeDisplay();

  if (overlay_play_button_ && !is_paused_for_scrubbing_)
    overlay_play_button_->UpdateDisplayType();
  // Only make the controls visible if they won't get hidden by OnTimeUpdate.
  if (MediaElement().paused() || !ShouldHideMediaControls())
    MakeOpaque();
  if (download_iph_manager_)
    download_iph_manager_->SetControlsVisibility(true);
  if (loading_panel_)
    loading_panel_->OnControlsShown();

  timeline_->OnControlsShown();
  UpdateCSSClassFromState();
  UpdateActingAsAudioControls();
}

void MediaControlsImpl::Hide() {
  panel_->SetIsWanted(false);
  panel_->SetIsDisplayed(false);

  // When we permanently hide the native media controls, we no longer want to
  // hide the cursor, since the video will be using custom controls.
  ShowCursor();

  if (overlay_play_button_)
    overlay_play_button_->SetIsWanted(false);
  if (download_iph_manager_)
    download_iph_manager_->SetControlsVisibility(false);
  if (loading_panel_)
    loading_panel_->OnControlsHidden();

  // Cancel scrubbing if necessary.
  if (is_scrubbing_) {
    is_paused_for_scrubbing_ = false;
    EndScrubbing();
  }
  timeline_->OnControlsHidden();

  UpdateCSSClassFromState();

  // Hide is called when the HTMLMediaElement is removed from a document. If we
  // stop acting as audio controls during this removal, we end up inserting
  // nodes during the removal, firing a DCHECK. To avoid this, only update here
  // when the media element is connected.
  if (MediaElement().isConnected())
    UpdateActingAsAudioControls();
}

bool MediaControlsImpl::IsVisible() const {
  return panel_->IsOpaque();
}

void MediaControlsImpl::MaybeShowOverlayPlayButton() {
  if (overlay_play_button_)
    overlay_play_button_->SetIsDisplayed(true);
}

void MediaControlsImpl::MakeOpaque() {
  ShowCursor();
  panel_->MakeOpaque();
  MaybeShowOverlayPlayButton();
}

void MediaControlsImpl::MakeOpaqueFromPointerEvent() {
  // If we have quickly hidden the controls we should always show them when we
  // have a pointer event. If the controls are hidden the play button will
  // remain hidden.
  MaybeShowOverlayPlayButton();

  if (IsVisible())
    return;

  MakeOpaque();
}

void MediaControlsImpl::MakeTransparent() {
  // Only hide the cursor if the controls are enabled.
  if (MediaElement().ShouldShowControls())
    HideCursor();
  panel_->MakeTransparent();
}

bool MediaControlsImpl::ShouldHideMediaControls(unsigned behavior_flags) const {
  // Never hide for a media element without visual representation.
  if (!MediaElement().IsHTMLVideoElement() || !MediaElement().HasVideo() ||
      ToHTMLVideoElement(MediaElement()).IsRemotingInterstitialVisible()) {
    return false;
  }

  RemotePlayback* remote =
      HTMLMediaElementRemotePlayback::remote(MediaElement());
  if (remote && remote->GetState() != WebRemotePlaybackState::kDisconnected)
    return false;

  // Keep the controls visible as long as the timer is running.
  const bool ignore_wait_for_timer = behavior_flags & kIgnoreWaitForTimer;
  if (!ignore_wait_for_timer && keep_showing_until_timer_fires_)
    return false;

  // Don't hide if the mouse is over the controls.
  // Touch focus shouldn't affect controls visibility.
  const bool ignore_controls_hover = behavior_flags & kIgnoreControlsHover;
  if (!ignore_controls_hover && AreVideoControlsHovered() &&
      !is_touch_interaction_)
    return false;

  // Don't hide if the mouse is over the video area.
  const bool ignore_video_hover = behavior_flags & kIgnoreVideoHover;
  if (!ignore_video_hover && is_mouse_over_controls_)
    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 ignore_focus = behavior_flags & kIgnoreFocus;
  if (!ignore_focus && (MediaElement().IsFocused() ||
                        contains(GetDocument().FocusedElement()))) {
    return false;
  }

  // Don't hide the media controls when a panel is showing.
  if (text_track_list_->IsWanted() || overflow_list_->IsWanted())
    return false;

  // Don't hide the media controls while the in product help is showing.
  if (download_iph_manager_ && download_iph_manager_->IsShowingInProductHelp())
    return false;

  // Don't hide if we have accessiblity focus.
  if (panel_->KeepDisplayedForAccessibility())
    return false;

  return true;
}

bool MediaControlsImpl::AreVideoControlsHovered() const {
  DCHECK(MediaElement().IsHTMLVideoElement());

  if (IsModern())
    return media_button_panel_->IsHovered() || timeline_->IsHovered();

  return panel_->IsHovered();
}

void MediaControlsImpl::UpdatePlayState() {
  if (is_paused_for_scrubbing_)
    return;

  if (overlay_play_button_)
    overlay_play_button_->UpdateDisplayType();
  play_button_->UpdateDisplayType();
}

HTMLDivElement* MediaControlsImpl::PanelElement() {
  return panel_;
}

void MediaControlsImpl::BeginScrubbing(bool is_touch_event) {
  if (!MediaElement().paused()) {
    is_paused_for_scrubbing_ = true;
    MediaElement().pause();
  }

  if (scrubbing_message_ && is_touch_event) {
    scrubbing_message_->SetIsWanted(true);
    if (scrubbing_message_->DoesFit())
      panel_->setAttribute("class", kScrubbingMessageCSSClass);
  }

  is_scrubbing_ = true;
  UpdateCSSClassFromState();
}

void MediaControlsImpl::EndScrubbing() {
  if (is_paused_for_scrubbing_) {
    is_paused_for_scrubbing_ = false;
    if (MediaElement().paused())
      MediaElement().Play();
  }

  if (scrubbing_message_) {
    scrubbing_message_->SetIsWanted(false);
    panel_->removeAttribute("class");
  }

  is_scrubbing_ = false;
  UpdateCSSClassFromState();
}

void MediaControlsImpl::UpdateCurrentTimeDisplay() {
  if (panel_->IsWanted())
    current_time_display_->SetCurrentValue(MediaElement().currentTime());
}

void MediaControlsImpl::ToggleTextTrackList() {
  if (!MediaElement().HasClosedCaptions()) {
    text_track_list_->SetIsWanted(false);
    return;
  }

  text_track_list_->SetIsWanted(!text_track_list_->IsWanted());
}

void MediaControlsImpl::ShowTextTrackAtIndex(unsigned index_to_enable) {
  TextTrackList* track_list = MediaElement().textTracks();
  if (index_to_enable >= track_list->length())
    return;
  TextTrack* track = track_list->AnonymousIndexedGetter(index_to_enable);
  if (track && track->CanBeRendered())
    track->setMode(TextTrack::ShowingKeyword());
}

void MediaControlsImpl::DisableShowingTextTracks() {
  TextTrackList* track_list = MediaElement().textTracks();
  for (unsigned i = 0; i < track_list->length(); ++i) {
    TextTrack* track = track_list->AnonymousIndexedGetter(i);
    if (track->mode() == TextTrack::ShowingKeyword())
      track->setMode(TextTrack::DisabledKeyword());
  }
}

bool MediaControlsImpl::TextTrackListIsWanted() {
  return text_track_list_->IsWanted();
}

String MediaControlsImpl::GetTextTrackLabel(TextTrack* track) const {
  if (!track) {
    return MediaElement().GetLocale().QueryString(
        WebLocalizedString::kTextTracksOff);
  }

  String track_label = track->label();

  if (track_label.IsEmpty())
    track_label = track->language();

  if (track_label.IsEmpty()) {
    track_label = String(MediaElement().GetLocale().QueryString(
        WebLocalizedString::kTextTracksNoLabel,
        String::Number(track->TrackIndex() + 1)));
  }

  return track_label;
}

void MediaControlsImpl::RefreshCastButtonVisibility() {
  RefreshCastButtonVisibilityWithoutUpdate();
  BatchedControlUpdate batch(this);
}

void MediaControlsImpl::RefreshCastButtonVisibilityWithoutUpdate() {
  if (!ShouldShowCastButton(MediaElement())) {
    cast_button_->SetIsWanted(false);
    overlay_cast_button_->SetIsWanted(false);
    return;
  }

  // The reason for the autoplay muted test is that some pages (e.g. vimeo.com)
  // have an autoplay background video which has to be muted on Android to play.
  // 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 muted autoplay video then they can
  // still do so by touching or clicking on the video, which will cause the cast
  // button to appear. Note that this concerns various animated images websites
  // too.
  if (!MediaElement().ShouldShowControls() &&
      !MediaElement().GetAutoplayPolicy().IsOrWillBeAutoplayingMuted()) {
    // 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.
    if (RuntimeEnabledFeatures::MediaCastOverlayButtonEnabled())
      overlay_cast_button_->TryShowOverlay();
    cast_button_->SetIsWanted(false);
  } else if (MediaElement().ShouldShowControls()) {
    overlay_cast_button_->SetIsWanted(false);
    cast_button_->SetIsWanted(true);
  }
}

void MediaControlsImpl::ShowOverlayCastButtonIfNeeded() {
  if (MediaElement().ShouldShowControls() ||
      !ShouldShowCastButton(MediaElement()) ||
      !RuntimeEnabledFeatures::MediaCastOverlayButtonEnabled()) {
    return;
  }

  overlay_cast_button_->TryShowOverlay();
  ResetHideMediaControlsTimer();
}

void MediaControlsImpl::EnterFullscreen() {
  Fullscreen::RequestFullscreen(MediaElement());
}

void MediaControlsImpl::ExitFullscreen() {
  Fullscreen::ExitFullscreen(GetDocument());
}

bool MediaControlsImpl::IsFullscreenEnabled() const {
  return fullscreen_button_->IsWanted() &&
         !fullscreen_button_->hasAttribute(html_names::kDisabledAttr);
}

void MediaControlsImpl::RemotePlaybackStateChanged() {
  cast_button_->UpdateDisplayType();
  overlay_cast_button_->UpdateDisplayType();
}

void MediaControlsImpl::UpdateOverflowMenuWanted() const {
  // If the bool is true then the element is "sticky" this means that we will
  // always try and show it unless there is not room for it.
  std::pair<MediaControlElementBase*, bool> row_elements[] = {
      std::make_pair(play_button_.Get(), true),
      std::make_pair(mute_button_.Get(), true),
      std::make_pair(fullscreen_button_.Get(), true),
      std::make_pair(current_time_display_.Get(), true),
      std::make_pair(duration_display_.Get(), true),
      picture_in_picture_button_.Get()
          ? std::make_pair(picture_in_picture_button_.Get(), false)
          : std::make_pair(nullptr, false),
      std::make_pair(cast_button_.Get(), false),
      std::make_pair(download_button_.Get(), false),
      std::make_pair(toggle_closed_captions_button_.Get(), false),
  };

  // These are the elements in order of priority that take up vertical room.
  MediaControlElementBase* column_elements[] = {
      media_button_panel_.Get(), timeline_.Get(),
  };

  // Current size of the media controls.
  WebSize controls_size = size_;

  // The video controls are more than one row so we need to allocate vertical
  // room and hide the overlay play button if there is not enough room.
  if (ShouldShowVideoControls()) {
    // Allocate vertical room for overlay play button if necessary.
    if (overlay_play_button_) {
      WebSize overlay_play_button_size =
          overlay_play_button_->GetSizeOrDefault();
      if (controls_size.height >= overlay_play_button_size.height &&
          controls_size.width >= kModernMinWidthForOverlayPlayButton) {
        overlay_play_button_->SetDoesFit(true);
        controls_size.height -= overlay_play_button_size.height;
      } else {
        overlay_play_button_->SetDoesFit(false);
      }
    }

    controls_size.width -= kModernControlsVideoButtonPadding;

    // Allocate vertical room for the column elements.
    for (MediaControlElementBase* element : column_elements) {
      WebSize element_size = element->GetSizeOrDefault();
      if (controls_size.height - element_size.height >= 0) {
        element->SetDoesFit(true);
        controls_size.height -= element_size.height;
      } else {
        element->SetDoesFit(false);
      }
    }

    // If we cannot show the overlay play button, show the normal one.
    play_button_->SetIsWanted(!overlay_play_button_ ||
                              !overlay_play_button_->DoesFit());
  } else {
    controls_size.width -= kModernControlsAudioButtonPadding;

    // Undo any IsWanted/DoesFit changes made in the above block if we're
    // switching to act as audio controls.
    if (is_acting_as_audio_controls_) {
      play_button_->SetIsWanted(true);

      for (MediaControlElementBase* element : column_elements)
        element->SetDoesFit(true);
    }
  }

  // Go through the elements and if they are sticky allocate them to the panel
  // if we have enough room. If not (or they are not sticky) then add them to
  // the overflow menu. Once we have run out of room add_elements will be
  // made false and no more elements will be added.
  MediaControlElementBase* last_element = nullptr;
  bool add_elements = true;
  bool overflow_wanted = false;
  for (std::pair<MediaControlElementBase*, bool> pair : row_elements) {
    MediaControlElementBase* element = pair.first;
    if (!element)
      continue;

    // If the element is wanted then it should take up space, otherwise skip it.
    element->SetOverflowElementIsWanted(false);
    if (!element->IsWanted())
      continue;

    // Get the size of the element and see if we should allocate space to it.
    WebSize element_size = element->GetSizeOrDefault();
    bool does_fit = add_elements && pair.second &&
                    ((controls_size.width - element_size.width) >= 0);
    element->SetDoesFit(does_fit);

    // The element does fit and is sticky so we should allocate space for it. If
    // we cannot fit this element we should stop allocating space for other
    // elements.
    if (does_fit) {
      controls_size.width -= element_size.width;
      last_element = element;
    } else {
      add_elements = false;
      if (element->HasOverflowButton() && !element->IsDisabled()) {
        overflow_wanted = true;
        element->SetOverflowElementIsWanted(true);
      }
    }
  }

  // The overflow menu is always wanted if it has the "disabled" attr set.
  overflow_wanted = overflow_wanted ||
                    overflow_menu_->hasAttribute(html_names::kDisabledAttr);
  overflow_menu_->SetDoesFit(overflow_wanted);
  overflow_menu_->SetIsWanted(overflow_wanted);

  // If we want to show the overflow button and we do not have any space to show
  // it then we should hide the last shown element.
  int overflow_icon_width = overflow_menu_->GetSizeOrDefault().width;
  if (overflow_wanted && last_element &&
      controls_size.width < overflow_icon_width) {
    last_element->SetDoesFit(false);
    last_element->SetOverflowElementIsWanted(true);
  }

  MaybeRecordElementsDisplayed();

  if (download_iph_manager_)
    download_iph_manager_->UpdateInProductHelp();

  UpdateOverflowAndTrackListCSSClassForPip();
  UpdateOverflowMenuItemCSSClass();
}

// This method is responsible for adding css class to overflow menu list
// items to achieve the animation that items appears one after another when
// open the overflow menu.
void MediaControlsImpl::UpdateOverflowMenuItemCSSClass() const {
  unsigned int id = 0;
  for (Element* item = ElementTraversal::LastChild(*overflow_list_); item;
       item = ElementTraversal::PreviousSibling(*item)) {
    const CSSPropertyValueSet* inline_style = item->InlineStyle();
    DOMTokenList& class_list = item->classList();

    // We don't care if the hidden element still have animated-* CSS class
    if (inline_style &&
        inline_style->GetPropertyValue(CSSPropertyDisplay) == "none")
      continue;

    AtomicString css_class =
        AtomicString("animated-") + AtomicString::Number(id++);
    if (!class_list.contains(css_class))
      class_list.setValue(css_class);
  }
}

void MediaControlsImpl::UpdateScrubbingMessageFits() const {
  if (scrubbing_message_)
    scrubbing_message_->SetDoesFit(size_.Width() >= kMinScrubbingMessageWidth);
}

// We want to have wider menu when pip is enabled so that "Exit picture in
// picture" text won't be truncated. When pip is disable (e.g. on mobile
// device), we don't want to enlarged the menu because it would look empty
// when "picture in picture" text is not presented.
void MediaControlsImpl::UpdateOverflowAndTrackListCSSClassForPip() const {
  if (picture_in_picture_button_.Get() &&
      picture_in_picture_button_.Get()->OverflowElementIsWanted()) {
    overflow_list_->classList().Add(kPipPresentedCSSClass);
    text_track_list_->classList().Add(kPipPresentedCSSClass);
  } else {
    overflow_list_->classList().Remove(kPipPresentedCSSClass);
    text_track_list_->classList().Remove(kPipPresentedCSSClass);
  }
}

void MediaControlsImpl::UpdateSizingCSSClass() {
  MediaControlsSizingClass sizing_class =
      MediaControls::GetSizingClass(size_.Width());

  SetClass(kMediaControlsSizingSmallCSSClass,
           ShouldShowVideoControls() &&
               sizing_class == MediaControlsSizingClass::kSmall);
  SetClass(kMediaControlsSizingMediumCSSClass,
           ShouldShowVideoControls() &&
               (sizing_class == MediaControlsSizingClass::kMedium ||
                sizing_class == MediaControlsSizingClass::kLarge));
}

void MediaControlsImpl::MaybeToggleControlsFromTap() {
  if (MediaElement().paused())
    return;

  // If the controls are visible then hide them. If the controls are not visible
  // then show them and start the timer to automatically hide them.
  if (IsVisible()) {
    MakeTransparent();
  } else {
    MakeOpaque();
    // Touch focus shouldn't affect controls visibility.
    if (ShouldHideMediaControls(kIgnoreWaitForTimer | kIgnoreFocus)) {
      keep_showing_until_timer_fires_ = true;
      StartHideMediaControlsTimer();
    }
  }
}

void MediaControlsImpl::OnAccessibleFocus() {
  if (panel_->KeepDisplayedForAccessibility())
    return;

  panel_->SetKeepDisplayedForAccessibility(true);

  if (!MediaElement().ShouldShowControls())
    return;

  OpenVolumeSliderIfNecessary();

  keep_showing_until_timer_fires_ = true;
  StartHideMediaControlsTimer();
  MaybeShow();
}

void MediaControlsImpl::OnAccessibleBlur() {
  panel_->SetKeepDisplayedForAccessibility(false);

  if (MediaElement().ShouldShowControls())
    return;

  CloseVolumeSliderIfNecessary();

  keep_showing_until_timer_fires_ = false;
  ResetHideMediaControlsTimer();
}

void MediaControlsImpl::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 is_touch_event = IsTouchEvent(&event);
  hide_timer_behavior_flags_ |=
      is_touch_event ? kIgnoreControlsHover : kIgnoreNone;

  // 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 (is_touch_event)
    HandleTouchEvent(&event);

  if (event.type() == event_type_names::kMouseover && !is_touch_event)
    is_touch_interaction_ = false;

  if ((event.type() == event_type_names::kPointerover ||
       event.type() == event_type_names::kPointermove ||
       event.type() == event_type_names::kPointerout) &&
      !is_touch_interaction_) {
    HandlePointerEvent(&event);
  }

  if (event.type() == event_type_names::kClick && !is_touch_interaction_)
    HandleClickEvent(&event);

  // If the user is interacting with the controls via the keyboard, don't hide
  // the controls. This will fire when the user tabs between controls (focusin)
  // or when they seek either the timeline or volume sliders (input).
  if (event.type() == event_type_names::kFocusin ||
      event.type() == event_type_names::kInput) {
    ResetHideMediaControlsTimer();
  }

  if (event.IsKeyboardEvent() &&
      !IsSpatialNavigationEnabled(GetDocument().GetFrame())) {
    const String& key = ToKeyboardEvent(event).key();
    if (key == "Enter" || ToKeyboardEvent(event).keyCode() == ' ') {
      if (IsModern() && overlay_play_button_) {
        overlay_play_button_->OnMediaKeyboardEvent(&event);
      } else {
        play_button_->OnMediaKeyboardEvent(&event);
      }
      return;
    }
    if (key == "ArrowLeft" || key == "ArrowRight" || key == "Home" ||
        key == "End") {
      timeline_->OnMediaKeyboardEvent(&event);
      return;
    }
    if (volume_slider_ && (key == "ArrowDown" || key == "ArrowUp")) {
      for (int i = 0; i < 5; i++)
        volume_slider_->OnMediaKeyboardEvent(&event);
      return;
    }
  }
}

void MediaControlsImpl::HandlePointerEvent(Event* event) {
  if (event->type() == event_type_names::kPointerover) {
    if (!ContainsRelatedTarget(event)) {
      is_mouse_over_controls_ = true;
      if (!MediaElement().paused()) {
        MakeOpaqueFromPointerEvent();
        StartHideMediaControlsIfNecessary();
      }
    }
  } else if (event->type() == event_type_names::kPointerout) {
    if (!ContainsRelatedTarget(event)) {
      is_mouse_over_controls_ = false;
      StopHideMediaControlsTimer();

      // When we get a mouse out, if video is playing and control should
      // hide regardless of focus, hide the control.
      // This will fix the issue that when mouse out event happen while video is
      // focused, control never hides.
      if (!MediaElement().paused() && ShouldHideMediaControls(kIgnoreFocus))
        MakeTransparent();
    }
  } else if (event->type() == event_type_names::kPointermove) {
    // 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.
    is_mouse_over_controls_ = true;
    MakeOpaqueFromPointerEvent();

    // Start the timer regardless of focus state
    if (ShouldHideMediaControls(kIgnoreVideoHover | kIgnoreFocus))
      StartHideMediaControlsTimer();
  }
}

void MediaControlsImpl::HandleClickEvent(Event* event) {
  if (!IsModern() || ContainsRelatedTarget(event) || !IsFullscreenEnabled())
    return;

  if (tap_timer_.IsActive()) {
    tap_timer_.Stop();

    // Toggle fullscreen.
    if (MediaElement().IsFullscreen())
      ExitFullscreen();
    else
      EnterFullscreen();

    // If we paused for the first click of this double-click, then we need to
    // resume playback, since the user was just toggling fullscreen.
    if (is_paused_for_double_tap_) {
      MediaElement().Play();
      is_paused_for_double_tap_ = false;
    }
  } else {
    // If the video is not paused, assume the user is clicking to pause the
    // video. If the user clicks again for a fullscreen-toggling double-tap, we
    // will resume playback.
    if (!MediaElement().paused()) {
      MediaElement().pause();
      is_paused_for_double_tap_ = true;
    }
    tap_timer_.StartOneShot(kDoubleTapDelay, FROM_HERE);
  }
}

void MediaControlsImpl::HandleTouchEvent(Event* event) {
  if (IsModern()) {
    is_mouse_over_controls_ = false;
    is_touch_interaction_ = true;

    if (event->type() == event_type_names::kClick &&
        !ContainsRelatedTarget(event)) {
      event->SetDefaultHandled();

      // In immersive mode we don't use double-tap features, so instead of
      // waiting 300 ms for a potential second tap, we just immediately toggle
      // controls visiblity.
      if (GetDocument().GetSettings() &&
          GetDocument().GetSettings()->GetImmersiveModeEnabled()) {
        MaybeToggleControlsFromTap();
        return;
      }

      if (tap_timer_.IsActive()) {
        // Cancel the visibility toggle event.
        tap_timer_.Stop();

        if (IsOnLeftSide(event)) {
          MaybeJump(kNumberOfSecondsToJump * -1);
        } else {
          MaybeJump(kNumberOfSecondsToJump);
        }
      } else {
        tap_timer_.StartOneShot(kDoubleTapDelay, FROM_HERE);
      }
    }
    return;
  }

  if (event->type() == event_type_names::kGesturetap &&
      !ContainsRelatedTarget(event) && !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(kIgnoreWaitForTimer)) {
      keep_showing_until_timer_fires_ = true;
      StartHideMediaControlsTimer();
    }
  }
}

void MediaControlsImpl::EnsureAnimatedArrowContainer() {
  if (!animated_arrow_container_element_) {
    animated_arrow_container_element_ =
        new MediaControlAnimatedArrowContainerElement(*this);
    ParserAppendChild(animated_arrow_container_element_);
  }
}

void MediaControlsImpl::MaybeJump(int seconds) {
  // Update the current time.
  double new_time = std::max(0.0, MediaElement().currentTime() + seconds);
  new_time = std::min(new_time, MediaElement().duration());
  MediaElement().setCurrentTime(new_time);

  // Show the arrow animation.
  EnsureAnimatedArrowContainer();
  MediaControlAnimatedArrowContainerElement::ArrowDirection direction =
      (seconds > 0)
          ? MediaControlAnimatedArrowContainerElement::ArrowDirection::kRight
          : MediaControlAnimatedArrowContainerElement::ArrowDirection::kLeft;
  animated_arrow_container_element_->ShowArrowAnimation(direction);
}

bool MediaControlsImpl::IsOnLeftSide(Event* event) {
  if (!event->IsMouseEvent())
    return false;

  MouseEvent* mouse_event = ToMouseEvent(event);
  if (!mouse_event->HasPosition())
    return false;

  DOMRect* rect = getBoundingClientRect();
  double middle = rect->x() + (rect->width() / 2);
  return mouse_event->clientX() < middle;
}

void MediaControlsImpl::TapTimerFired(TimerBase*) {
  if (is_touch_interaction_) {
    MaybeToggleControlsFromTap();
  } else if (MediaElement().paused()) {
    // If this is not a touch interaction and the video is paused, then either
    // the user has just paused via click (in which case we've already paused
    // and there's nothing to do), or the user is playing by click (in which
    // case we need to start playing).
    if (is_paused_for_double_tap_) {
      Platform::Current()->RecordAction(
          UserMetricsAction("Media.Controls.ClickAnywhereToPause"));
      // TODO(https://crbug.com/896252): Show overlay pause animation.
      is_paused_for_double_tap_ = false;
    } else {
      Platform::Current()->RecordAction(
          UserMetricsAction("Media.Controls.ClickAnywhereToPlay"));
      // TODO(https://crbug.com/896252): Show overlay play animation.
      MediaElement().Play();
    }
  }
}

void MediaControlsImpl::HideMediaControlsTimerFired(TimerBase*) {
  unsigned behavior_flags =
      hide_timer_behavior_flags_ | kIgnoreFocus | kIgnoreVideoHover;
  hide_timer_behavior_flags_ = kIgnoreNone;
  keep_showing_until_timer_fires_ = false;

  if (MediaElement().paused())
    return;

  if (!ShouldHideMediaControls(behavior_flags))
    return;

  MakeTransparent();
  overlay_cast_button_->SetIsWanted(false);
}

void MediaControlsImpl::StartHideMediaControlsTimer() {
  hide_media_controls_timer_.StartOneShot(
      GetTimeWithoutMouseMovementBeforeHidingMediaControls(), FROM_HERE);
}

void MediaControlsImpl::StopHideMediaControlsTimer() {
  keep_showing_until_timer_fires_ = false;
  hide_media_controls_timer_.Stop();
}

void MediaControlsImpl::ResetHideMediaControlsTimer() {
  StopHideMediaControlsTimer();
  if (!MediaElement().paused())
    StartHideMediaControlsTimer();
}

void MediaControlsImpl::HideCursor() {
  SetInlineStyleProperty(CSSPropertyCursor, "none", false);
}

void MediaControlsImpl::ShowCursor() {
  RemoveInlineStyleProperty(CSSPropertyCursor);
}

bool MediaControlsImpl::ContainsRelatedTarget(Event* event) {
  if (!event->IsPointerEvent())
    return false;
  EventTarget* related_target = ToPointerEvent(event)->relatedTarget();
  if (!related_target)
    return false;
  return contains(related_target->ToNode());
}

void MediaControlsImpl::OnVolumeChange() {
  mute_button_->UpdateDisplayType();

  // Update visibility of volume controls.
  // TODO(mlamouri): it should not be part of the volumechange handling because
  // it is using audio availability as input.
  if (volume_slider_) {
    volume_slider_->SetVolume(MediaElement().muted() ? 0
                                                     : MediaElement().volume());
    volume_slider_->SetIsWanted(MediaElement().HasAudio() &&
                                !PreferHiddenVolumeControls(GetDocument()));
  }
  if (IsModern()) {
    mute_button_->SetIsWanted(true);
    mute_button_->setAttribute(
        html_names::kDisabledAttr,
        MediaElement().HasAudio() ? AtomicString() : AtomicString(""));
  } else {
    mute_button_->SetIsWanted(MediaElement().HasAudio());
    mute_button_->removeAttribute(html_names::kDisabledAttr);
  }

  // On modern media controls, if the volume slider is being used we don't want
  // to update controls visiblity, since this can shift the position of the
  // volume slider and make it unusable.
  if (!IsModern() || !volume_slider_ || !volume_slider_->IsHovered())
    BatchedControlUpdate batch(this);
}

void MediaControlsImpl::OnFocusIn() {
  // Touch focus shouldn't affect controls visibility.
  if (!MediaElement().ShouldShowControls() || is_touch_interaction_)
    return;

  ResetHideMediaControlsTimer();
  MaybeShow();
}

void MediaControlsImpl::OnTimeUpdate() {
  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();

  if (download_iph_manager_)
    download_iph_manager_->UpdateInProductHelp();
}

void MediaControlsImpl::OnDurationChange() {
  BatchedControlUpdate batch(this);

  const double duration = MediaElement().duration();
  bool was_finite_duration = std::isfinite(duration_display_->CurrentValue());

  // Update the displayed current time/duration.
  duration_display_->SetCurrentValue(duration);

  // Show the duration display if we have a duration or if we are showing the
  // audio controls without a source.
  duration_display_->SetIsWanted(
      std::isfinite(duration) ||
      (ShouldShowAudioControls() && State() == kNoSource));

  // TODO(crbug.com/756698): Determine if this is still needed since the format
  // of the current time no longer depends on the duration.
  UpdateCurrentTimeDisplay();

  // Update the timeline (the UI with the seek marker).
  timeline_->SetDuration(duration);
  if (!was_finite_duration && std::isfinite(duration)) {
    download_button_->SetIsWanted(
        download_button_->ShouldDisplayDownloadButton());
  }
}

void MediaControlsImpl::OnPlay() {
  UpdatePlayState();
  timeline_->SetPosition(MediaElement().currentTime());
  UpdateCurrentTimeDisplay();
  UpdateCSSClassFromState();
}

void MediaControlsImpl::OnPlaying() {
  timeline_->OnPlaying();
  if (download_iph_manager_)
    download_iph_manager_->SetIsPlaying(true);

  StartHideMediaControlsTimer();
  UpdateCSSClassFromState();
}

void MediaControlsImpl::OnPause() {
  UpdatePlayState();
  timeline_->SetPosition(MediaElement().currentTime());
  UpdateCurrentTimeDisplay();
  MakeOpaque();

  StopHideMediaControlsTimer();

  if (download_iph_manager_)
    download_iph_manager_->SetIsPlaying(false);

  UpdateCSSClassFromState();
}

void MediaControlsImpl::OnTextTracksAddedOrRemoved() {
  toggle_closed_captions_button_->UpdateDisplayType();
  toggle_closed_captions_button_->SetIsWanted(
      MediaElement().HasClosedCaptions());
  BatchedControlUpdate batch(this);
}

void MediaControlsImpl::OnTextTracksChanged() {
  toggle_closed_captions_button_->UpdateDisplayType();
}

void MediaControlsImpl::OnError() {
  // TODO(mlamouri): we should only change the aspects of the control that need
  // to be changed.
  Reset();
  UpdateCSSClassFromState();
}

void MediaControlsImpl::OnLoadedMetadata() {
  // TODO(mlamouri): we should only change the aspects of the control that need
  // to be changed.
  Reset();
  UpdateCSSClassFromState();
  UpdateActingAsAudioControls();
}

void MediaControlsImpl::OnEnteredFullscreen() {
  fullscreen_button_->SetIsFullscreen(true);
  if (display_cutout_fullscreen_button_)
    display_cutout_fullscreen_button_->SetIsWanted(true);

  StopHideMediaControlsTimer();
  StartHideMediaControlsTimer();
}

void MediaControlsImpl::OnExitedFullscreen() {
  fullscreen_button_->SetIsFullscreen(false);
  if (display_cutout_fullscreen_button_)
    display_cutout_fullscreen_button_->SetIsWanted(false);

  StopHideMediaControlsTimer();
  StartHideMediaControlsTimer();
}

void MediaControlsImpl::OnPictureInPictureChanged() {
  // This will only be called if the media controls are listening to the
  // Picture-in-Picture events which only happen when they provide a
  // Picture-in-Picture button.
  DCHECK(picture_in_picture_button_);
  picture_in_picture_button_->UpdateDisplayType();
}

void MediaControlsImpl::OnPanelKeypress() {
  // If the user is interacting with the controls via the keyboard, don't hide
  // the controls. This is called when the user mutes/unmutes, turns CC on/off,
  // etc.
  ResetHideMediaControlsTimer();
}

void MediaControlsImpl::NotifyElementSizeChanged(DOMRectReadOnly* new_size) {
  // 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 old_size = size_;
  size_.SetWidth(new_size->width());
  size_.SetHeight(new_size->height());

  // Don't bother to do any work if this matches the most recent size.
  if (old_size != size_) {
    // Update the sizing CSS class before computing which controls fit so that
    // the element sizes can update from the CSS class change before we start
    // calculating.
    if (IsModern())
      UpdateSizingCSSClass();
    element_size_changed_timer_.StartOneShot(TimeDelta(), FROM_HERE);
  }
}

void MediaControlsImpl::ElementSizeChangedTimerFired(TimerBase*) {
  ComputeWhichControlsFit();
}

void MediaControlsImpl::OnLoadingProgress() {
  timeline_->RenderBarSegments();
}

void MediaControlsImpl::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.
  if (IsModern()) {
    UpdateOverflowMenuWanted();
    UpdateScrubbingMessageFits();
    return;
  }

  // Controls that we'll hide / show, in order of decreasing priority.
  MediaControlElementBase* elements[] = {
      // Exclude m_overflowMenu; we handle it specially.
      play_button_.Get(),
      fullscreen_button_.Get(),
      download_button_.Get(),
      timeline_.Get(),
      mute_button_.Get(),
      volume_slider_.Get(),
      toggle_closed_captions_button_.Get(),
      picture_in_picture_button_.Get() ? picture_in_picture_button_.Get()
                                       : nullptr,
      cast_button_.Get(),
      current_time_display_.Get(),
      duration_display_.Get(),
  };

  // TODO(mlamouri): we need a more dynamic way to find out the width of an
  // element.
  const int kSliderMargin = 36;  // Sliders have 18px margin on each side.

  if (!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 (MediaControlElementBase* 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 minimum_width = 48;
  if (play_button_->GetLayoutObject() &&
      play_button_->GetLayoutObject()->Style()) {
    const ComputedStyle* style = play_button_->GetLayoutObject()->Style();
    minimum_width = ceil(style->Width().Pixels() / style->EffectiveZoom());
  } else if (overflow_menu_->GetLayoutObject() &&
             overflow_menu_->GetLayoutObject()->Style()) {
    const ComputedStyle* style = overflow_menu_->GetLayoutObject()->Style();
    minimum_width = 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.
  overflow_menu_->SetDoesFit(true);
  overflow_menu_->SetIsWanted(true);
  int used_width = minimum_width;

  std::list<MediaControlElementBase*> overflow_elements;
  MediaControlElementBase* first_displaced_element = nullptr;
  // For each control that fits, enable it in order of decreasing priority.
  for (MediaControlElementBase* element : elements) {
    if (!element)
      continue;

    int width = minimum_width;
    if ((element == timeline_.Get()) || (element == volume_slider_.Get()))
      width += kSliderMargin;

    element->SetOverflowElementIsWanted(false);
    if (!element->IsWanted())
      continue;

    if (used_width + width <= size_.Width()) {
      element->SetDoesFit(true);
      used_width += width;
    } else {
      element->SetDoesFit(false);
      element->SetOverflowElementIsWanted(true);
      if (element->HasOverflowButton())
        overflow_elements.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() && !first_displaced_element)
        first_displaced_element = element;
    }
  }

  // If we don't have at least two overflow elements, we will not show the
  // overflow menu.
  if (overflow_elements.empty()) {
    overflow_menu_->SetIsWanted(false);
    used_width -= minimum_width;
    if (first_displaced_element) {
      int width = minimum_width;
      if ((first_displaced_element == timeline_.Get()) ||
          (first_displaced_element == volume_slider_.Get()))
        width += kSliderMargin;
      if (used_width + width <= size_.Width())
        first_displaced_element->SetDoesFit(true);
    }
  } else if (overflow_elements.size() == 1) {
    overflow_menu_->SetIsWanted(false);
    overflow_elements.front()->SetDoesFit(true);
  }

  // Decide if the overlay play button fits.
  if (overlay_play_button_) {
    bool does_fit = size_.Width() >= kMinWidthForOverlayPlayButton &&
                    size_.Height() >= kMinHeightForOverlayPlayButton;
    overlay_play_button_->SetDoesFit(does_fit);
  }

  if (download_iph_manager_)
    download_iph_manager_->UpdateInProductHelp();

  MaybeRecordElementsDisplayed();
}

void MediaControlsImpl::MaybeRecordElementsDisplayed() const {
  // Record the display state when needed. It is only recorded when the media
  // element is in a state that allows it in order to reduce noise in the
  // metrics.
  if (!MediaControlInputElement::ShouldRecordDisplayStates(MediaElement()))
    return;

  MediaControlElementBase* elements[] = {
      play_button_.Get(),
      fullscreen_button_.Get(),
      download_button_.Get(),
      timeline_.Get(),
      mute_button_.Get(),
      volume_slider_.Get(),
      toggle_closed_captions_button_.Get(),
      picture_in_picture_button_.Get() ? picture_in_picture_button_.Get()
                                       : nullptr,
      cast_button_.Get(),
      current_time_display_.Get(),
      duration_display_.Get(),
      overlay_play_button_.Get(),
      overlay_cast_button_.Get(),
  };

  // Record which controls are used.
  for (auto* const element : elements) {
    if (element)
      element->MaybeRecordDisplayed();
  }
  overflow_menu_->MaybeRecordDisplayed();
}

const MediaControlCurrentTimeDisplayElement&
MediaControlsImpl::CurrentTimeDisplay() const {
  return *current_time_display_;
}

MediaControlToggleClosedCaptionsButtonElement&
MediaControlsImpl::ToggleClosedCaptions() {
  return *toggle_closed_captions_button_;
}

bool MediaControlsImpl::ShouldActAsAudioControls() const {
  // A video element should act like an audio element when it has an audio track
  // but no video track.
  return IsModern() && MediaElement().ShouldShowControls() &&
         MediaElement().IsHTMLVideoElement() && MediaElement().HasAudio() &&
         !MediaElement().HasVideo();
}

void MediaControlsImpl::StartActingAsAudioControls() {
  DCHECK(ShouldActAsAudioControls());
  DCHECK(!is_acting_as_audio_controls_);

  is_acting_as_audio_controls_ = true;
  SetClass(kActAsAudioControlsCSSClass, true);
  PopulatePanel();
  Reset();
}

void MediaControlsImpl::StopActingAsAudioControls() {
  DCHECK(!ShouldActAsAudioControls());
  DCHECK(is_acting_as_audio_controls_);

  is_acting_as_audio_controls_ = false;
  SetClass(kActAsAudioControlsCSSClass, false);
  PopulatePanel();
  Reset();
}

void MediaControlsImpl::UpdateActingAsAudioControls() {
  if (ShouldActAsAudioControls() != is_acting_as_audio_controls_) {
    if (is_acting_as_audio_controls_)
      StopActingAsAudioControls();
    else
      StartActingAsAudioControls();
  }
}

bool MediaControlsImpl::ShouldShowAudioControls() const {
  return IsModern() &&
         (MediaElement().IsHTMLAudioElement() || is_acting_as_audio_controls_);
}

bool MediaControlsImpl::ShouldShowVideoControls() const {
  return MediaElement().IsHTMLVideoElement() && !ShouldShowAudioControls();
}

void MediaControlsImpl::NetworkStateChanged() {
  // Update the display state of the download button in case we now have a
  // source or no longer have a source.
  download_button_->SetIsWanted(
      download_button_->ShouldDisplayDownloadButton());

  UpdateCSSClassFromState();
}

void MediaControlsImpl::OpenOverflowMenu() {
  overflow_list_->OpenOverflowMenu();
}

void MediaControlsImpl::CloseOverflowMenu() {
  overflow_list_->CloseOverflowMenu();
}

bool MediaControlsImpl::OverflowMenuIsWanted() {
  return overflow_list_->IsWanted();
}

bool MediaControlsImpl::OverflowMenuVisible() {
  return overflow_list_ ? overflow_list_->IsWanted() : false;
}

void MediaControlsImpl::ToggleOverflowMenu() {
  DCHECK(overflow_list_);

  overflow_list_->SetIsWanted(!overflow_list_->IsWanted());
}

void MediaControlsImpl::StartHideMediaControlsIfNecessary() {
  if (ShouldHideMediaControls())
    StartHideMediaControlsTimer();
}

void MediaControlsImpl::VolumeSliderWantedTimerFired(TimerBase*) {
  volume_slider_->OpenSlider();
}

void MediaControlsImpl::OpenVolumeSliderIfNecessary() {
  if (ShouldOpenVolumeSlider()) {
    volume_slider_wanted_timer_.StartOneShot(WebTestSupport::IsRunningWebTest()
                                                 ? kTimeToShowVolumeSliderTest
                                                 : kTimeToShowVolumeSlider,
                                             FROM_HERE);
  }
}

void MediaControlsImpl::CloseVolumeSliderIfNecessary() {
  if (ShouldCloseVolumeSlider()) {
    volume_slider_->CloseSlider();

    if (volume_slider_wanted_timer_.IsActive())
      volume_slider_wanted_timer_.Stop();
  }
}

bool MediaControlsImpl::ShouldOpenVolumeSlider() const {
  if (!volume_slider_ || !IsModern())
    return false;

  return !PreferHiddenVolumeControls(GetDocument());
}

bool MediaControlsImpl::ShouldCloseVolumeSlider() const {
  if (!volume_slider_ || !IsModern())
    return false;

  return !(volume_slider_->IsHovered() || mute_button_->IsHovered());
}

const MediaControlDownloadButtonElement& MediaControlsImpl::DownloadButton()
    const {
  return *download_button_;
}

const MediaControlOverflowMenuButtonElement& MediaControlsImpl::OverflowButton()
    const {
  return *overflow_menu_;
}

MediaControlOverflowMenuButtonElement& MediaControlsImpl::OverflowButton() {
  return *overflow_menu_;
}

void MediaControlsImpl::DidDismissDownloadInProductHelp() {
  StartHideMediaControlsIfNecessary();
}

MediaDownloadInProductHelpManager* MediaControlsImpl::DownloadInProductHelp() {
  return download_iph_manager_;
}

void MediaControlsImpl::OnWaiting() {
  UpdateCSSClassFromState();
}

void MediaControlsImpl::OnLoadedData() {
  UpdateCSSClassFromState();
}

HTMLVideoElement& MediaControlsImpl::VideoElement() {
  DCHECK(MediaElement().IsHTMLVideoElement());
  return *ToHTMLVideoElement(&MediaElement());
}

void MediaControlsImpl::Trace(blink::Visitor* visitor) {
  visitor->Trace(element_mutation_callback_);
  visitor->Trace(resize_observer_);
  visitor->Trace(panel_);
  visitor->Trace(overlay_play_button_);
  visitor->Trace(overlay_enclosure_);
  visitor->Trace(play_button_);
  visitor->Trace(current_time_display_);
  visitor->Trace(timeline_);
  visitor->Trace(scrubbing_message_);
  visitor->Trace(mute_button_);
  visitor->Trace(volume_slider_);
  visitor->Trace(picture_in_picture_button_);
  visitor->Trace(animated_arrow_container_element_);
  visitor->Trace(toggle_closed_captions_button_);
  visitor->Trace(fullscreen_button_);
  visitor->Trace(download_button_);
  visitor->Trace(duration_display_);
  visitor->Trace(enclosure_);
  visitor->Trace(text_track_list_);
  visitor->Trace(overflow_menu_);
  visitor->Trace(overflow_list_);
  visitor->Trace(cast_button_);
  visitor->Trace(overlay_cast_button_);
  visitor->Trace(media_event_listener_);
  visitor->Trace(orientation_lock_delegate_);
  visitor->Trace(rotate_to_fullscreen_delegate_);
  visitor->Trace(display_cutout_delegate_);
  visitor->Trace(download_iph_manager_);
  visitor->Trace(media_button_panel_);
  visitor->Trace(loading_panel_);
  visitor->Trace(display_cutout_fullscreen_button_);
  MediaControls::Trace(visitor);
  HTMLDivElement::Trace(visitor);
}

}  // namespace blink
