// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"

#include "build/build_config.h"
#include "third_party/blink/public/mojom/autoplay/autoplay.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/media/autoplay_uma_helper.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"

namespace blink {

namespace {

const char kWarningUnmuteFailed[] =
    "Unmuting failed and the element was paused instead because the user "
    "didn't interact with the document before. https://goo.gl/xX8pDD";
const char kErrorAutoplayFuncUnified[] =
    "play() failed because the user didn't interact with the document first. "
    "https://goo.gl/xX8pDD";
const char kErrorAutoplayFuncMobile[] =
    "play() can only be initiated by a user gesture.";

// Return true if and only if the document settings specifies media playback
// requires user gesture on the element.
bool ComputeLockPendingUserGestureRequired(const Document& document) {
  switch (AutoplayPolicy::GetAutoplayPolicyForDocument(document)) {
    case AutoplayPolicy::Type::kNoUserGestureRequired:
      return false;
    case AutoplayPolicy::Type::kUserGestureRequired:
      return true;
    // kDocumentUserActivationRequired policy does not imply that a user gesture
    // is required on the element but instead requires a user gesture on the
    // document, therefore the element is not locked.
    case AutoplayPolicy::Type::kDocumentUserActivationRequired:
      return false;
  }

  NOTREACHED();
  return true;
}

}  // anonymous namespace

// static
AutoplayPolicy::Type AutoplayPolicy::GetAutoplayPolicyForDocument(
    const Document& document) {
  if (!document.GetSettings())
    return Type::kNoUserGestureRequired;

  if (document.IsInWebAppScope())
    return Type::kNoUserGestureRequired;

  if (DocumentHasUserExceptionFlag(document))
    return Type::kNoUserGestureRequired;

  if (document.GetSettings()->GetPresentationReceiver())
    return Type::kNoUserGestureRequired;

  return document.GetSettings()->GetAutoplayPolicy();
}

// static
bool AutoplayPolicy::IsDocumentAllowedToPlay(const Document& document) {
  if (DocumentHasForceAllowFlag(document))
    return true;

  if (DocumentIsCapturingUserMedia(document))
    return true;

  if (!document.GetFrame())
    return false;

  bool feature_policy_enabled =
      document.GetExecutionContext()->IsFeatureEnabled(
          mojom::blink::FeaturePolicyFeature::kAutoplay);

  for (Frame* frame = document.GetFrame(); frame;
       frame = frame->Tree().Parent()) {
    if (frame->HasStickyUserActivation() ||
        frame->HadStickyUserActivationBeforeNavigation()) {
      return true;
    }

    if (RuntimeEnabledFeatures::
            MediaEngagementBypassAutoplayPoliciesEnabled() &&
        frame->IsMainFrame() && DocumentHasHighMediaEngagement(document)) {
      return true;
    }

    if (!feature_policy_enabled)
      return false;
  }

  return false;
}

// static
bool AutoplayPolicy::DocumentHasHighMediaEngagement(const Document& document) {
  if (!document.GetPage())
    return false;
  return document.GetPage()->AutoplayFlags() &
         mojom::blink::kAutoplayFlagHighMediaEngagement;
}

// static
bool AutoplayPolicy::DocumentHasForceAllowFlag(const Document& document) {
  if (!document.GetPage())
    return false;
  return document.GetPage()->AutoplayFlags() &
         mojom::blink::kAutoplayFlagForceAllow;
}

// static
bool AutoplayPolicy::DocumentHasUserExceptionFlag(const Document& document) {
  if (!document.GetPage())
    return false;
  return document.GetPage()->AutoplayFlags() &
         mojom::blink::kAutoplayFlagUserException;
}

// static
bool AutoplayPolicy::DocumentShouldAutoplayMutedVideos(
    const Document& document) {
  return GetAutoplayPolicyForDocument(document) !=
         AutoplayPolicy::Type::kNoUserGestureRequired;
}

// static
bool AutoplayPolicy::DocumentIsCapturingUserMedia(const Document& document) {
  if (auto* local_frame = document.GetFrame())
    return local_frame->IsCapturingMedia();

  return false;
}

AutoplayPolicy::AutoplayPolicy(HTMLMediaElement* element)
    : locked_pending_user_gesture_(false),
      element_(element),
      autoplay_uma_helper_(MakeGarbageCollected<AutoplayUmaHelper>(element)) {
  locked_pending_user_gesture_ =
      ComputeLockPendingUserGestureRequired(element->GetDocument());
}

void AutoplayPolicy::VideoWillBeDrawnToCanvas() const {
  autoplay_uma_helper_->VideoWillBeDrawnToCanvas();
}

void AutoplayPolicy::DidMoveToNewDocument(Document& old_document) {
  // If any experiment is enabled, then we want to enable a user gesture by
  // default, otherwise the experiment does nothing.
  bool old_document_requires_user_gesture =
      ComputeLockPendingUserGestureRequired(old_document);
  bool new_document_requires_user_gesture =
      ComputeLockPendingUserGestureRequired(element_->GetDocument());
  if (new_document_requires_user_gesture && !old_document_requires_user_gesture)
    locked_pending_user_gesture_ = true;

  autoplay_uma_helper_->DidMoveToNewDocument(old_document);
}

bool AutoplayPolicy::IsEligibleForAutoplayMuted() const {
  if (!IsA<HTMLVideoElement>(element_.Get()))
    return false;

  if (RuntimeEnabledFeatures::VideoAutoFullscreenEnabled() &&
      !element_->FastHasAttribute(html_names::kPlaysinlineAttr)) {
    return false;
  }

  return !element_->EffectiveMediaVolume() &&
         DocumentShouldAutoplayMutedVideos(element_->GetDocument());
}

void AutoplayPolicy::StartAutoplayMutedWhenVisible() {
  // We might end up in a situation where the previous
  // observer didn't had time to fire yet. We can avoid
  // creating a new one in this case.
  if (autoplay_intersection_observer_)
    return;

  autoplay_intersection_observer_ = IntersectionObserver::Create(
      {}, {IntersectionObserver::kMinimumThreshold}, &element_->GetDocument(),
      WTF::BindRepeating(&AutoplayPolicy::OnIntersectionChangedForAutoplay,
                         WrapWeakPersistent(this)),
      LocalFrameUkmAggregator::kMediaIntersectionObserver);
  autoplay_intersection_observer_->observe(element_);
}

void AutoplayPolicy::StopAutoplayMutedWhenVisible() {
  if (!autoplay_intersection_observer_)
    return;

  autoplay_intersection_observer_->disconnect();
  autoplay_intersection_observer_ = nullptr;
}

bool AutoplayPolicy::RequestAutoplayUnmute() {
  DCHECK_NE(0, element_->EffectiveMediaVolume());
  bool was_autoplaying_muted = IsAutoplayingMutedInternal(true);

  TryUnlockingUserGesture();

  if (was_autoplaying_muted) {
    if (IsGestureNeededForPlayback()) {
      if (IsUsingDocumentUserActivationRequiredPolicy()) {
        element_->GetDocument().AddConsoleMessage(
            MakeGarbageCollected<ConsoleMessage>(
                mojom::ConsoleMessageSource::kJavaScript,
                mojom::ConsoleMessageLevel::kWarning, kWarningUnmuteFailed));
      }

      autoplay_uma_helper_->RecordAutoplayUnmuteStatus(
          AutoplayUnmuteActionStatus::kFailure);
      return false;
    }
    autoplay_uma_helper_->RecordAutoplayUnmuteStatus(
        AutoplayUnmuteActionStatus::kSuccess);
  }
  return true;
}

bool AutoplayPolicy::RequestAutoplayByAttribute() {
  if (!ShouldAutoplay())
    return false;

  autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kAttribute);

  if (IsGestureNeededForPlayback())
    return false;

  // If it's the first playback, track that it started because of autoplay.
  MaybeSetAutoplayInitiated();

  // At this point the gesture is not needed for playback per the if statement
  // above.
  if (!IsEligibleForAutoplayMuted())
    return true;

  // Autoplay muted video should be handled by AutoplayPolicy based on the
  // visibily.
  StartAutoplayMutedWhenVisible();
  return false;
}

base::Optional<DOMExceptionCode> AutoplayPolicy::RequestPlay() {
  if (!LocalFrame::HasTransientUserActivation(
          element_->GetDocument().GetFrame())) {
    autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kMethod);
    if (IsGestureNeededForPlayback())
      return DOMExceptionCode::kNotAllowedError;
  } else {
    TryUnlockingUserGesture();
  }

  MaybeSetAutoplayInitiated();

  return base::nullopt;
}

bool AutoplayPolicy::IsAutoplayingMutedInternal(bool muted) const {
  return !element_->paused() && IsOrWillBeAutoplayingMutedInternal(muted);
}

bool AutoplayPolicy::IsOrWillBeAutoplayingMuted() const {
  return IsOrWillBeAutoplayingMutedInternal(!element_->EffectiveMediaVolume());
}

bool AutoplayPolicy::IsOrWillBeAutoplayingMutedInternal(bool muted) const {
  if (!IsA<HTMLVideoElement>(element_.Get()) ||
      !DocumentShouldAutoplayMutedVideos(element_->GetDocument())) {
    return false;
  }

  return muted && IsLockedPendingUserGesture();
}

bool AutoplayPolicy::IsLockedPendingUserGesture() const {
  if (IsUsingDocumentUserActivationRequiredPolicy())
    return !IsDocumentAllowedToPlay(element_->GetDocument());

  return locked_pending_user_gesture_;
}

void AutoplayPolicy::TryUnlockingUserGesture() {
  if (IsLockedPendingUserGesture() && LocalFrame::HasTransientUserActivation(
                                          element_->GetDocument().GetFrame())) {
    locked_pending_user_gesture_ = false;
  }
}

bool AutoplayPolicy::IsGestureNeededForPlayback() const {
  if (!IsLockedPendingUserGesture())
    return false;

  // We want to allow muted video to autoplay if the element is allowed to
  // autoplay muted.
  return !IsEligibleForAutoplayMuted();
}

String AutoplayPolicy::GetPlayErrorMessage() const {
  return IsUsingDocumentUserActivationRequiredPolicy()
             ? kErrorAutoplayFuncUnified
             : kErrorAutoplayFuncMobile;
}

bool AutoplayPolicy::WasAutoplayInitiated() const {
  if (!autoplay_initiated_.has_value())
    return false;

  return *autoplay_initiated_;
}

void AutoplayPolicy::EnsureAutoplayInitiatedSet() {
  if (autoplay_initiated_)
    return;
  autoplay_initiated_ = false;
}

void AutoplayPolicy::OnIntersectionChangedForAutoplay(
    const HeapVector<Member<IntersectionObserverEntry>>& entries) {
  bool is_visible = (entries.back()->intersectionRatio() > 0);
  if (!is_visible) {
    if (element_->can_autoplay_ && element_->Autoplay()) {
      element_->PauseInternal();
      element_->can_autoplay_ = true;
    }
    return;
  }

  if (ShouldAutoplay()) {
    element_->paused_ = false;
    element_->SetShowPosterFlag(false);
    element_->ScheduleEvent(event_type_names::kPlay);
    element_->ScheduleNotifyPlaying();

    element_->UpdatePlayState();
  }
}

bool AutoplayPolicy::IsUsingDocumentUserActivationRequiredPolicy() const {
  return GetAutoplayPolicyForDocument(element_->GetDocument()) ==
         AutoplayPolicy::Type::kDocumentUserActivationRequired;
}

void AutoplayPolicy::MaybeSetAutoplayInitiated() {
  if (autoplay_initiated_.has_value())
    return;

  autoplay_initiated_ = true;

  bool feature_policy_enabled =
      element_->GetExecutionContext() &&
      element_->GetExecutionContext()->IsFeatureEnabled(
          mojom::blink::FeaturePolicyFeature::kAutoplay);

  for (Frame* frame = element_->GetDocument().GetFrame(); frame;
       frame = frame->Tree().Parent()) {
    if (frame->HasStickyUserActivation() ||
        frame->HadStickyUserActivationBeforeNavigation()) {
      autoplay_initiated_ = false;
      break;
    }
    if (!feature_policy_enabled)
      break;
  }
}

bool AutoplayPolicy::ShouldAutoplay() {
  if (!element_->GetExecutionContext() ||
      element_->GetExecutionContext()->IsSandboxed(
          network::mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
    return false;
  }
  return element_->can_autoplay_ && element_->paused_ && element_->Autoplay();
}

void AutoplayPolicy::Trace(Visitor* visitor) const {
  visitor->Trace(element_);
  visitor->Trace(autoplay_intersection_observer_);
  visitor->Trace(autoplay_uma_helper_);
}

STATIC_ASSERT_ENUM(mojom::blink::AutoplayPolicy::kNoUserGestureRequired,
                   AutoplayPolicy::Type::kNoUserGestureRequired);
STATIC_ASSERT_ENUM(mojom::blink::AutoplayPolicy::kUserGestureRequired,
                   AutoplayPolicy::Type::kUserGestureRequired);
STATIC_ASSERT_ENUM(
    mojom::blink::AutoplayPolicy::kDocumentUserActivationRequired,
    AutoplayPolicy::Type::kDocumentUserActivationRequired);

}  // namespace blink
