/*
 * Copyright (C) 2007, 2008, 2009, 2010 Apple 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/core/html/media/html_video_element.h"

#include <memory>

#include "base/callback_helpers.h"
#include "base/metrics/histogram_functions.h"
#include "cc/paint/paint_canvas.h"
#include "media/base/video_frame.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_fullscreen_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.h"
#include "third_party/blink/renderer/core/html/media/media_remoting_interstitial.h"
#include "third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h"
#include "third_party/blink/renderer/core/html/media/video_frame_callback_requester.h"
#include "third_party/blink/renderer/core/html/media/video_wake_lock.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/video_frame_image_util.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/web_test_support.h"

namespace blink {

namespace {

// This enum is used to record histograms. Do not reorder.
enum VideoPersistenceControlsType {
  kNative = 0,
  kCustom = 1,
  kMaxValue = 1,
};

}  // anonymous namespace

HTMLVideoElement::HTMLVideoElement(Document& document)
    : HTMLMediaElement(html_names::kVideoTag, document),
      remoting_interstitial_(nullptr),
      picture_in_picture_interstitial_(nullptr),
      is_persistent_(false),
      is_auto_picture_in_picture_(false),
      in_overlay_fullscreen_video_(false),
      is_effectively_fullscreen_(false),
      is_default_overridden_intrinsic_size_(
          !document.IsMediaDocument() && GetExecutionContext() &&
          !GetExecutionContext()->IsFeatureEnabled(
              mojom::blink::DocumentPolicyFeature::kUnsizedMedia)),
      video_has_played_(false),
      mostly_filling_viewport_(false) {
  if (document.GetSettings()) {
    default_poster_url_ =
        AtomicString(document.GetSettings()->GetDefaultVideoPosterURL());
  }

  custom_controls_fullscreen_detector_ =
      MakeGarbageCollected<MediaCustomControlsFullscreenDetector>(*this);

  wake_lock_ = MakeGarbageCollected<VideoWakeLock>(*this);

  EnsureUserAgentShadowRoot();
  UpdateStateIfNeeded();
}

void HTMLVideoElement::Trace(Visitor* visitor) const {
  visitor->Trace(image_loader_);
  visitor->Trace(custom_controls_fullscreen_detector_);
  visitor->Trace(wake_lock_);
  visitor->Trace(remoting_interstitial_);
  visitor->Trace(picture_in_picture_interstitial_);
  Supplementable<HTMLVideoElement>::Trace(visitor);
  HTMLMediaElement::Trace(visitor);
}

bool HTMLVideoElement::HasPendingActivity() const {
  return HTMLMediaElement::HasPendingActivity() ||
         (image_loader_ && image_loader_->HasPendingActivity());
}

Node::InsertionNotificationRequest HTMLVideoElement::InsertedInto(
    ContainerNode& insertion_point) {
  if (insertion_point.isConnected())
    custom_controls_fullscreen_detector_->Attach();

  return HTMLMediaElement::InsertedInto(insertion_point);
}

void HTMLVideoElement::RemovedFrom(ContainerNode& insertion_point) {
  HTMLMediaElement::RemovedFrom(insertion_point);
  custom_controls_fullscreen_detector_->Detach();

  OnBecamePersistentVideo(false);
}

void HTMLVideoElement::ContextDestroyed() {
  custom_controls_fullscreen_detector_->ContextDestroyed();
  HTMLMediaElement::ContextDestroyed();
}

bool HTMLVideoElement::LayoutObjectIsNeeded(const ComputedStyle& style) const {
  return HTMLElement::LayoutObjectIsNeeded(style);
}

LayoutObject* HTMLVideoElement::CreateLayoutObject(const ComputedStyle&,
                                                   LegacyLayout) {
  return new LayoutVideo(this);
}

void HTMLVideoElement::AttachLayoutTree(AttachContext& context) {
  HTMLMediaElement::AttachLayoutTree(context);
  UpdatePosterImage();
}

void HTMLVideoElement::UpdatePosterImage() {
  ImageResourceContent* image_content = nullptr;

  // Load the poster if set, |VideoLayout| will decide whether to draw it.
  if (!PosterImageURL().IsEmpty()) {
    if (!image_loader_)
      image_loader_ = MakeGarbageCollected<HTMLImageLoader>(this);
    image_loader_->UpdateFromElement();
    image_content = image_loader_->GetContent();
  }

  if (GetLayoutObject()) {
    To<LayoutImage>(GetLayoutObject())
        ->ImageResource()
        ->SetImageResource(image_content);
    UpdateLayoutObject();
  }
}

void HTMLVideoElement::CollectStyleForPresentationAttribute(
    const QualifiedName& name,
    const AtomicString& value,
    MutableCSSPropertyValueSet* style) {
  if (name == html_names::kWidthAttr) {
    AddHTMLLengthToStyle(style, CSSPropertyID::kWidth, value);
    const AtomicString& height = FastGetAttribute(html_names::kHeightAttr);
    if (height)
      ApplyAspectRatioToStyle(value, height, style);
  } else if (name == html_names::kHeightAttr) {
    AddHTMLLengthToStyle(style, CSSPropertyID::kHeight, value);
    const AtomicString& width = FastGetAttribute(html_names::kWidthAttr);
    if (width)
      ApplyAspectRatioToStyle(width, value, style);
  } else {
    HTMLMediaElement::CollectStyleForPresentationAttribute(name, value, style);
  }
}

bool HTMLVideoElement::IsPresentationAttribute(
    const QualifiedName& name) const {
  if (name == html_names::kWidthAttr || name == html_names::kHeightAttr)
    return true;
  return HTMLMediaElement::IsPresentationAttribute(name);
}

void HTMLVideoElement::ParseAttribute(
    const AttributeModificationParams& params) {
  if (params.name == html_names::kPosterAttr) {
    UpdatePosterImage();

    // Notify the player when the poster image URL changes.
    if (GetWebMediaPlayer())
      GetWebMediaPlayer()->SetPoster(PosterImageURL());

    // Media remoting and picture in picture doesn't show the original poster
    // image, instead, it shows a grayscaled and blurred copy.
    if (remoting_interstitial_)
      remoting_interstitial_->OnPosterImageChanged();
    if (picture_in_picture_interstitial_)
      picture_in_picture_interstitial_->OnPosterImageChanged();
  } else if (params.name == html_names::kAutopictureinpictureAttr &&
             RuntimeEnabledFeatures::AutoPictureInPictureEnabled(
                 GetExecutionContext())) {
    if (!params.new_value.IsNull()) {
      PictureInPictureController::From(GetDocument())
          .AddToAutoPictureInPictureElementsList(this);
    } else {
      PictureInPictureController::From(GetDocument())
          .RemoveFromAutoPictureInPictureElementsList(this);
    }
  } else {
    HTMLMediaElement::ParseAttribute(params);
  }
}

unsigned HTMLVideoElement::videoWidth() const {
  if (is_default_overridden_intrinsic_size_)
    return LayoutReplaced::kDefaultWidth;
  if (!GetWebMediaPlayer())
    return 0;
  return GetWebMediaPlayer()->NaturalSize().width();
}

unsigned HTMLVideoElement::videoHeight() const {
  if (is_default_overridden_intrinsic_size_)
    return LayoutReplaced::kDefaultHeight;
  if (!GetWebMediaPlayer())
    return 0;
  return GetWebMediaPlayer()->NaturalSize().height();
}

IntSize HTMLVideoElement::videoVisibleSize() const {
  return GetWebMediaPlayer() ? IntSize(GetWebMediaPlayer()->VisibleSize())
                             : IntSize();
}

bool HTMLVideoElement::IsURLAttribute(const Attribute& attribute) const {
  return attribute.GetName() == html_names::kPosterAttr ||
         HTMLMediaElement::IsURLAttribute(attribute);
}

const AtomicString HTMLVideoElement::ImageSourceURL() const {
  const AtomicString& url = FastGetAttribute(html_names::kPosterAttr);
  if (!StripLeadingAndTrailingHTMLSpaces(url).IsEmpty())
    return url;
  return default_poster_url_;
}

void HTMLVideoElement::UpdatePictureInPictureAvailability() {
  if (!web_media_player_)
    return;

  for (auto& observer : GetMediaPlayerObserverRemoteSet())
    observer->OnPictureInPictureAvailabilityChanged(SupportsPictureInPicture());
}

// TODO(zqzhang): this callback could be used to hide native controls instead of
// using a settings. See `HTMLMediaElement::onMediaControlsEnabledChange`.
void HTMLVideoElement::OnBecamePersistentVideo(bool value) {
  is_auto_picture_in_picture_ = value;

  if (value) {
    // Record the type of video. If it is already fullscreen, it is a video with
    // native controls, otherwise it is assumed to be with custom controls.
    // This is only recorded when entering this mode.
    base::UmaHistogramEnumeration("Media.VideoPersistence.ControlsType",
                                  IsFullscreen()
                                      ? VideoPersistenceControlsType::kNative
                                      : VideoPersistenceControlsType::kCustom);

    Element* fullscreen_element =
        Fullscreen::FullscreenElementFrom(GetDocument());
    // Only set the video in persistent mode if it is not using native controls
    // and is currently fullscreen.
    if (!fullscreen_element || IsFullscreen())
      return;

    is_persistent_ = true;
    PseudoStateChanged(CSSSelector::kPseudoVideoPersistent);

    // The video is also marked as containing a persistent video to simplify the
    // internal CSS logic.
    for (Element* element = this; element && element != fullscreen_element;
         element = element->ParentOrShadowHostElement()) {
      element->SetContainsPersistentVideo(true);
    }
    fullscreen_element->SetContainsPersistentVideo(true);
  } else {
    if (!is_persistent_)
      return;

    is_persistent_ = false;
    PseudoStateChanged(CSSSelector::kPseudoVideoPersistent);

    Element* fullscreen_element =
        Fullscreen::FullscreenElementFrom(GetDocument());
    // If the page is no longer fullscreen, the full tree will have to be
    // traversed to make sure things are cleaned up.
    for (Element* element = this; element && element != fullscreen_element;
         element = element->ParentOrShadowHostElement()) {
      element->SetContainsPersistentVideo(false);
    }
    if (fullscreen_element)
      fullscreen_element->SetContainsPersistentVideo(false);
  }

  if (GetWebMediaPlayer())
    GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
}

bool HTMLVideoElement::IsPersistent() const {
  return is_persistent_;
}

void HTMLVideoElement::OnPlay() {
  if (!video_has_played_) {
    video_has_played_ = true;
    UpdatePictureInPictureAvailability();
  }

  if (!RuntimeEnabledFeatures::VideoAutoFullscreenEnabled() ||
      FastHasAttribute(html_names::kPlaysinlineAttr)) {
    return;
  }

  // TODO(mustaq): This is problematic, see https://crbug.com/1082258.
  LocalFrame::NotifyUserActivation(
      GetDocument().GetFrame(),
      mojom::blink::UserActivationNotificationType::kMedia);
  webkitEnterFullscreen();
}

void HTMLVideoElement::OnLoadStarted() {
  web_media_player_->BecameDominantVisibleContent(mostly_filling_viewport_);
}

void HTMLVideoElement::OnLoadFinished() {
  // If the player did a lazy load, it's expecting to be called when the
  // element actually becomes visible to complete the load.
  if (web_media_player_->DidLazyLoad() && !PotentiallyPlaying()) {
    lazy_load_intersection_observer_ = IntersectionObserver::Create(
        {}, {IntersectionObserver::kMinimumThreshold}, &GetDocument(),
        WTF::BindRepeating(&HTMLVideoElement::OnIntersectionChangedForLazyLoad,
                           WrapWeakPersistent(this)),
        LocalFrameUkmAggregator::kMediaIntersectionObserver);
    lazy_load_intersection_observer_->observe(this);
  }

  UpdatePictureInPictureAvailability();
}

void HTMLVideoElement::RequestEnterPictureInPicture() {
  PictureInPictureController::From(GetDocument())
      .EnterPictureInPicture(this, nullptr /* promise */,
                             nullptr /* options */);
}

void HTMLVideoElement::RequestExitPictureInPicture() {
  PictureInPictureController::From(GetDocument())
      .ExitPictureInPicture(this, nullptr);
}

void HTMLVideoElement::PaintCurrentFrame(cc::PaintCanvas* canvas,
                                         const IntRect& dest_rect,
                                         const PaintFlags* flags) const {
  if (!GetWebMediaPlayer())
    return;

  PaintFlags media_flags;
  if (flags) {
    media_flags = *flags;
  } else {
    media_flags.setAlpha(0xFF);
    media_flags.setFilterQuality(kLow_SkFilterQuality);
    media_flags.setBlendMode(SkBlendMode::kSrc);
  }

  GetWebMediaPlayer()->Paint(canvas, dest_rect, media_flags);
}

bool HTMLVideoElement::HasAvailableVideoFrame() const {
  if (auto* wmp = GetWebMediaPlayer())
    return wmp->HasAvailableVideoFrame();
  return false;
}

void HTMLVideoElement::webkitEnterFullscreen() {
  if (!IsFullscreen()) {
    FullscreenOptions* options = FullscreenOptions::Create();
    options->setNavigationUI("hide");
    Fullscreen::RequestFullscreen(*this, options,
                                  FullscreenRequestType::kPrefixed);
  }
}

void HTMLVideoElement::webkitExitFullscreen() {
  if (IsFullscreen())
    Fullscreen::ExitFullscreen(GetDocument());
}

bool HTMLVideoElement::webkitSupportsFullscreen() {
  return Fullscreen::FullscreenEnabled(GetDocument());
}

bool HTMLVideoElement::webkitDisplayingFullscreen() {
  return IsFullscreen();
}

bool HTMLVideoElement::UsesOverlayFullscreenVideo() const {
  if (RuntimeEnabledFeatures::ForceOverlayFullscreenVideoEnabled())
    return true;

  return GetWebMediaPlayer() &&
         GetWebMediaPlayer()->SupportsOverlayFullscreenVideo();
}

void HTMLVideoElement::DidEnterFullscreen() {
  UpdateControlsVisibility();

  if (GetDisplayType() == DisplayType::kPictureInPicture && !IsInAutoPIP()) {
    PictureInPictureController::From(GetDocument())
        .ExitPictureInPicture(this, nullptr);
  }

  if (GetWebMediaPlayer()) {
    // FIXME: There is no embedder-side handling in web test mode.
    if (!WebTestSupport::IsRunningWebTest())
      GetWebMediaPlayer()->EnteredFullscreen();
    GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
  }

  // Cache this in case the player is destroyed before leaving fullscreen.
  in_overlay_fullscreen_video_ = UsesOverlayFullscreenVideo();
  if (in_overlay_fullscreen_video_) {
    if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
      auto* compositor = GetDocument().GetLayoutView()->Compositor();
      compositor->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
    }
  }
}

void HTMLVideoElement::DidExitFullscreen() {
  UpdateControlsVisibility();

  if (GetWebMediaPlayer()) {
    GetWebMediaPlayer()->ExitedFullscreen();
    GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
  }

  if (in_overlay_fullscreen_video_) {
    if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
      auto* compositor = GetDocument().GetLayoutView()->Compositor();
      compositor->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
    }
  }
  in_overlay_fullscreen_video_ = false;

  if (RuntimeEnabledFeatures::VideoAutoFullscreenEnabled() &&
      !FastHasAttribute(html_names::kPlaysinlineAttr)) {
    pause();
  }
}

void HTMLVideoElement::DidMoveToNewDocument(Document& old_document) {
  if (image_loader_)
    image_loader_->ElementDidMoveToNewDocument();

  wake_lock_->ElementDidMoveToNewDocument();
  HTMLMediaElement::DidMoveToNewDocument(old_document);
}

unsigned HTMLVideoElement::webkitDecodedFrameCount() const {
  if (!GetWebMediaPlayer())
    return 0;

  return GetWebMediaPlayer()->DecodedFrameCount();
}

unsigned HTMLVideoElement::webkitDroppedFrameCount() const {
  if (!GetWebMediaPlayer())
    return 0;

  return GetWebMediaPlayer()->DroppedFrameCount();
}

KURL HTMLVideoElement::PosterImageURL() const {
  String url = StripLeadingAndTrailingHTMLSpaces(ImageSourceURL());
  if (url.IsEmpty())
    return KURL();
  return GetDocument().CompleteURL(url);
}

bool HTMLVideoElement::IsDefaultPosterImageURL() const {
  return ImageSourceURL() == default_poster_url_;
}

scoped_refptr<StaticBitmapImage> HTMLVideoElement::CreateStaticBitmapImage(
    bool allow_accelerated_images) {
  media::PaintCanvasVideoRenderer* video_renderer = nullptr;
  scoped_refptr<media::VideoFrame> media_video_frame;
  if (auto* wmp = GetWebMediaPlayer()) {
    media_video_frame = wmp->GetCurrentFrame();
    video_renderer = wmp->GetPaintCanvasVideoRenderer();
  }

  if (!media_video_frame || !video_renderer)
    return nullptr;

  const auto intrinsic_size = IntSize(media_video_frame->natural_size());
  if (!resource_provider_ ||
      allow_accelerated_images != resource_provider_->IsAccelerated() ||
      intrinsic_size != resource_provider_->Size()) {
    viz::RasterContextProvider* raster_context_provider = nullptr;
    if (allow_accelerated_images) {
      if (auto wrapper = SharedGpuContext::ContextProviderWrapper()) {
        if (auto* context_provider = wrapper->ContextProvider())
          raster_context_provider = context_provider->RasterContextProvider();
      }
    }
    // Providing a null |raster_context_provider| creates a software provider.
    resource_provider_ = CreateResourceProviderForVideoFrame(
        intrinsic_size, raster_context_provider);
    if (!resource_provider_)
      return nullptr;
  }

  const auto dest_rect = gfx::Rect(media_video_frame->natural_size());
  auto image = CreateImageFromVideoFrame(std::move(media_video_frame),
                                         /*allow_zero_copy_images=*/true,
                                         resource_provider_.get(),
                                         video_renderer, dest_rect);
  image->SetOriginClean(!WouldTaintOrigin());
  return image;
}

scoped_refptr<Image> HTMLVideoElement::GetSourceImageForCanvas(
    SourceImageStatus* status,
    const FloatSize&) {
  scoped_refptr<Image> snapshot = CreateStaticBitmapImage();
  if (!snapshot) {
    *status = kInvalidSourceImageStatus;
    return nullptr;
  }

  *status = kNormalSourceImageStatus;
  return snapshot;
}

bool HTMLVideoElement::WouldTaintOrigin() const {
  return !IsMediaDataCorsSameOrigin();
}

FloatSize HTMLVideoElement::ElementSize(
    const FloatSize&,
    const RespectImageOrientationEnum) const {
  return FloatSize(videoWidth(), videoHeight());
}

IntSize HTMLVideoElement::BitmapSourceSize() const {
  return IntSize(videoWidth(), videoHeight());
}

ScriptPromise HTMLVideoElement::CreateImageBitmap(
    ScriptState* script_state,
    base::Optional<IntRect> crop_rect,
    const ImageBitmapOptions* options,
    ExceptionState& exception_state) {
  if (getNetworkState() == HTMLMediaElement::kNetworkEmpty) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The provided element has not retrieved data.");
    return ScriptPromise();
  }
  if (!HasAvailableVideoFrame()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The provided element's player has no current data.");
    return ScriptPromise();
  }

  return ImageBitmapSource::FulfillImageBitmap(
      script_state, MakeGarbageCollected<ImageBitmap>(this, crop_rect, options),
      exception_state);
}

void HTMLVideoElement::MediaRemotingStarted(
    const WebString& remote_device_friendly_name) {
  if (!remoting_interstitial_) {
    remoting_interstitial_ =
        MakeGarbageCollected<MediaRemotingInterstitial>(*this);
    ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
    shadow_root.InsertBefore(remoting_interstitial_, shadow_root.firstChild());
    HTMLMediaElement::AssertShadowRootChildren(shadow_root);
  }
  remoting_interstitial_->Show(remote_device_friendly_name);
}

void HTMLVideoElement::MediaRemotingStopped(int error_code) {
  if (remoting_interstitial_)
    remoting_interstitial_->Hide(error_code);
}

bool HTMLVideoElement::SupportsPictureInPicture() const {
  return PictureInPictureController::From(GetDocument())
             .IsElementAllowed(*this) ==
         PictureInPictureController::Status::kEnabled;
}

DisplayType HTMLVideoElement::GetDisplayType() const {
  if (is_auto_picture_in_picture_ ||
      PictureInPictureController::IsElementInPictureInPicture(this)) {
    return DisplayType::kPictureInPicture;
  }

  if (is_effectively_fullscreen_)
    return DisplayType::kFullscreen;

  return HTMLMediaElement::GetDisplayType();
}

bool HTMLVideoElement::IsInAutoPIP() const {
  return is_auto_picture_in_picture_;
}

void HTMLVideoElement::OnPictureInPictureStateChange() {
  if (GetDisplayType() != DisplayType::kPictureInPicture || IsInAutoPIP()) {
    return;
  }

  PictureInPictureController::From(GetDocument())
      .OnPictureInPictureStateChange();
}

void HTMLVideoElement::OnEnteredPictureInPicture() {
  if (!picture_in_picture_interstitial_) {
    picture_in_picture_interstitial_ =
        MakeGarbageCollected<PictureInPictureInterstitial>(*this);
    ShadowRoot& shadow_root = EnsureUserAgentShadowRoot();
    shadow_root.InsertBefore(picture_in_picture_interstitial_,
                             shadow_root.firstChild());
    HTMLMediaElement::AssertShadowRootChildren(shadow_root);
  }
  picture_in_picture_interstitial_->Show();

  if (RuntimeEnabledFeatures::CSSPictureInPictureEnabled())
    PseudoStateChanged(CSSSelector::kPseudoPictureInPicture);

  DCHECK(GetWebMediaPlayer());
  GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
}

void HTMLVideoElement::OnExitedPictureInPicture() {
  if (picture_in_picture_interstitial_)
    picture_in_picture_interstitial_->Hide();

  if (RuntimeEnabledFeatures::CSSPictureInPictureEnabled())
    PseudoStateChanged(CSSSelector::kPseudoPictureInPicture);

  if (GetWebMediaPlayer())
    GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
}

void HTMLVideoElement::SetIsEffectivelyFullscreen(
    blink::WebFullscreenVideoStatus status) {
  is_effectively_fullscreen_ =
      status != blink::WebFullscreenVideoStatus::kNotEffectivelyFullscreen;
  if (GetWebMediaPlayer()) {
    for (auto& observer : GetMediaPlayerObserverRemoteSet())
      observer->OnMediaEffectivelyFullscreenChanged(status);

    GetWebMediaPlayer()->SetIsEffectivelyFullscreen(status);
    GetWebMediaPlayer()->OnDisplayTypeChanged(GetDisplayType());
  }
}

void HTMLVideoElement::SetIsDominantVisibleContent(bool is_dominant) {
  if (mostly_filling_viewport_ != is_dominant) {
    mostly_filling_viewport_ = is_dominant;
    auto* player = GetWebMediaPlayer();
    if (player)
      player->BecameDominantVisibleContent(mostly_filling_viewport_);

    auto* local_frame_view = GetDocument().View();
    if (local_frame_view)
      local_frame_view->NotifyVideoIsDominantVisibleStatus(this, is_dominant);
  }
}

void HTMLVideoElement::AddedEventListener(
    const AtomicString& event_type,
    RegisteredEventListener& registered_listener) {
  if (event_type == event_type_names::kEnterpictureinpicture) {
    UseCounter::Count(GetExecutionContext(),
                      WebFeature::kEnterPictureInPictureEventListener);
  } else if (event_type == event_type_names::kLeavepictureinpicture) {
    UseCounter::Count(GetExecutionContext(),
                      WebFeature::kLeavePictureInPictureEventListener);
  }

  HTMLMediaElement::AddedEventListener(event_type, registered_listener);
}

bool HTMLVideoElement::IsRemotingInterstitialVisible() const {
  return remoting_interstitial_ && remoting_interstitial_->IsVisible();
}

void HTMLVideoElement::OnIntersectionChangedForLazyLoad(
    const HeapVector<Member<IntersectionObserverEntry>>& entries) {
  bool is_visible = (entries.back()->intersectionRatio() > 0);
  if (!is_visible || !web_media_player_)
    return;

  web_media_player_->OnBecameVisible();
  lazy_load_intersection_observer_->disconnect();
  lazy_load_intersection_observer_ = nullptr;
}

void HTMLVideoElement::OnWebMediaPlayerCreated() {
  if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) {
    if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
      vfc_requester->OnWebMediaPlayerCreated();
  }
}

void HTMLVideoElement::OnWebMediaPlayerCleared() {
  if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) {
    if (auto* vfc_requester = VideoFrameCallbackRequester::From(*this))
      vfc_requester->OnWebMediaPlayerCleared();
  }
}

void HTMLVideoElement::AttributeChanged(
    const AttributeModificationParams& params) {
  HTMLElement::AttributeChanged(params);
  if (params.name == html_names::kDisablepictureinpictureAttr)
    UpdatePictureInPictureAvailability();
}

void HTMLVideoElement::OnRequestVideoFrameCallback() {
  DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled());
  VideoFrameCallbackRequester::From(*this)->OnRequestVideoFrameCallback();
}

}  // namespace blink
