// Copyright 2019 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/frame/frame_view.h"

#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_geometry.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "ui/gfx/transform.h"

namespace blink {

FrameView::FrameView(const IntRect& frame_rect)
    : EmbeddedContentView(frame_rect),
      frame_visibility_(blink::mojom::FrameVisibility::kRenderedInViewport) {}

Frame& FrameView::GetFrame() const {
  if (const LocalFrameView* lfv = DynamicTo<LocalFrameView>(this))
    return lfv->GetFrame();
  return DynamicTo<RemoteFrameView>(this)->GetFrame();
}

bool FrameView::CanThrottleRenderingForPropagation() const {
  if (CanThrottleRendering())
    return true;
  Frame& frame = GetFrame();
  if (!frame.IsCrossOriginToMainFrame())
    return false;
  if (frame.IsLocalFrame() && To<LocalFrame>(frame).IsHidden())
    return true;
  LocalFrame* parent_frame = DynamicTo<LocalFrame>(GetFrame().Tree().Parent());
  return (parent_frame && !frame.OwnerLayoutObject());
}

bool FrameView::DisplayLockedInParentFrame() {
  Frame& frame = GetFrame();
  LayoutEmbeddedContent* owner = frame.OwnerLayoutObject();
  if (!owner)
    return false;
  DCHECK(owner->GetFrameView());
  if (owner->GetFrameView()->IsDisplayLocked())
    return true;
  // We check the inclusive ancestor to determine whether the subtree is locked,
  // since the contents of the frame are in the subtree of the frame, so they
  // would be locked if the frame owner is itself locked.
  return DisplayLockUtilities::NearestLockedInclusiveAncestor(*owner);
}

void FrameView::UpdateViewportIntersection(unsigned flags,
                                           bool needs_occlusion_tracking) {
  if (!(flags & IntersectionObservation::kImplicitRootObserversNeedUpdate))
    return;

  // This should only run in child frames.
  Frame& frame = GetFrame();
  HTMLFrameOwnerElement* owner_element = frame.DeprecatedLocalOwner();
  if (!owner_element)
    return;

  Document& owner_document = owner_element->GetDocument();
  IntRect viewport_intersection, mainframe_intersection;
  TransformationMatrix main_frame_transform_matrix;
  DocumentLifecycle::LifecycleState parent_lifecycle_state =
      owner_document.Lifecycle().GetState();
  mojom::blink::FrameOcclusionState occlusion_state =
      owner_document.GetFrame()->GetOcclusionState();
  bool should_compute_occlusion =
      needs_occlusion_tracking &&
      occlusion_state ==
          mojom::blink::FrameOcclusionState::kGuaranteedNotOccluded &&
      parent_lifecycle_state >= DocumentLifecycle::kPrePaintClean;

  LayoutEmbeddedContent* owner_layout_object =
      owner_element->GetLayoutEmbeddedContent();
  if (!owner_layout_object || owner_layout_object->ContentSize().IsEmpty()) {
    // The frame is detached from layout, not visible, or zero size; leave
    // viewport_intersection empty, and signal the frame as occluded if
    // necessary.
    occlusion_state = mojom::blink::FrameOcclusionState::kPossiblyOccluded;
  } else if (parent_lifecycle_state >= DocumentLifecycle::kLayoutClean &&
             !owner_document.View()->NeedsLayout()) {
    unsigned geometry_flags =
        IntersectionGeometry::kShouldUseReplacedContentRect;
    if (should_compute_occlusion)
      geometry_flags |= IntersectionGeometry::kShouldComputeVisibility;

    IntersectionGeometry geometry(nullptr, *owner_element, {} /* root_margin */,
                                  {IntersectionObserver::kMinimumThreshold},
                                  {} /* target_margin */, geometry_flags);
    PhysicalRect new_rect_in_parent = geometry.IntersectionRect();
    if (new_rect_in_parent.size != rect_in_parent_.size ||
        ((new_rect_in_parent.X() - rect_in_parent_.X()).Abs() +
             (new_rect_in_parent.Y() - rect_in_parent_.Y()).Abs() >
         LayoutUnit(mojom::blink::kMaxChildFrameScreenRectMovement))) {
      rect_in_parent_ = new_rect_in_parent;
      if (Page* page = GetFrame().GetPage()) {
        rect_in_parent_stable_since_ = page->Animator().Clock().CurrentTime();
      } else {
        rect_in_parent_stable_since_ = base::TimeTicks::Now();
      }
    }
    if (should_compute_occlusion && !geometry.IsVisible())
      occlusion_state = mojom::blink::FrameOcclusionState::kPossiblyOccluded;

    // Generate matrix to transform from the space of the containing document
    // to the space of the iframe's contents.
    TransformState parent_frame_to_iframe_content_transform(
        TransformState::kUnapplyInverseTransformDirection);
    // First transform to box coordinates of the iframe element...
    owner_layout_object->MapAncestorToLocal(
        nullptr, parent_frame_to_iframe_content_transform, 0);
    // ... then apply content_box_offset to translate to the coordinate of the
    // child frame.
    parent_frame_to_iframe_content_transform.Move(
        owner_layout_object->PhysicalContentBoxOffset());
    TransformationMatrix matrix =
        parent_frame_to_iframe_content_transform.AccumulatedTransform()
            .Inverse();
    if (geometry.IsIntersecting()) {
      PhysicalRect intersection_rect = PhysicalRect::EnclosingRect(
          matrix.ProjectQuad(FloatRect(geometry.IntersectionRect()))
              .BoundingBox());

      // Don't let EnclosingRect turn an empty rect into a non-empty one.
      if (intersection_rect.IsEmpty()) {
        viewport_intersection =
            IntRect(FlooredIntPoint(intersection_rect.offset), IntSize());
      } else {
        viewport_intersection = EnclosingIntRect(intersection_rect);
      }

      // Because the geometry code uses enclosing rects, we may end up with an
      // intersection rect that is bigger than the rect we started with. Clamp
      // the size of the viewport intersection to the bounds of the iframe's
      // content rect.
      viewport_intersection.SetLocation(
          viewport_intersection.Location().ExpandedTo(IntPoint()));
      viewport_intersection.SetSize(viewport_intersection.Size().ShrunkTo(
          RoundedIntSize(owner_layout_object->ContentSize())));
    }

    PhysicalRect mainframe_intersection_rect;
    if (!geometry.UnclippedIntersectionRect().IsEmpty()) {
      mainframe_intersection_rect = PhysicalRect::EnclosingRect(
          matrix.ProjectQuad(FloatRect(geometry.UnclippedIntersectionRect()))
              .BoundingBox());

      if (mainframe_intersection_rect.IsEmpty()) {
        mainframe_intersection = IntRect(
            FlooredIntPoint(mainframe_intersection_rect.offset), IntSize());
      } else {
        mainframe_intersection = EnclosingIntRect(mainframe_intersection_rect);
      }
      mainframe_intersection.SetLocation(
          mainframe_intersection.Location().ExpandedTo(IntPoint()));
      mainframe_intersection.SetSize(mainframe_intersection.Size().ShrunkTo(
          RoundedIntSize(owner_layout_object->ContentSize())));
    }

    TransformState child_frame_to_root_frame(
        TransformState::kUnapplyInverseTransformDirection);
    if (owner_layout_object) {
      owner_layout_object->MapAncestorToLocal(
          nullptr, child_frame_to_root_frame,
          kTraverseDocumentBoundaries | kApplyRemoteMainFrameTransform);
      child_frame_to_root_frame.Move(
          owner_layout_object->PhysicalContentBoxOffset());
    }
    main_frame_transform_matrix =
        child_frame_to_root_frame.AccumulatedTransform();
  } else if (occlusion_state ==
             mojom::blink::FrameOcclusionState::kGuaranteedNotOccluded) {
    // If the parent LocalFrameView is throttled and out-of-date, then we can't
    // get any useful information.
    occlusion_state = mojom::blink::FrameOcclusionState::kUnknown;
  }

  // An iframe's content is always pixel-snapped, even if the iframe element has
  // non-pixel-aligned location.
  gfx::Transform main_frame_gfx_transform =
      TransformationMatrix::ToTransform(main_frame_transform_matrix);
  main_frame_gfx_transform.RoundTranslationComponents();

  SetViewportIntersection(mojom::blink::ViewportIntersectionState(
      viewport_intersection, mainframe_intersection, gfx::Rect(),
      occlusion_state, gfx::Size(frame.GetMainFrameViewportSize()),
      gfx::Point(frame.GetMainFrameScrollOffset()), main_frame_gfx_transform));

  UpdateFrameVisibility(!viewport_intersection.IsEmpty());

  if (ShouldReportMainFrameIntersection()) {
    IntRect projected_rect = EnclosingIntRect(PhysicalRect::EnclosingRect(
        main_frame_transform_matrix
            .ProjectQuad(FloatRect(IntRect(mainframe_intersection)))
            .BoundingBox()));
    // Return <0, 0, 0, 0> if there is no area.
    if (projected_rect.IsEmpty())
      projected_rect.SetLocation(IntPoint(0, 0));
    GetFrame().Client()->OnMainFrameIntersectionChanged(projected_rect);
  }

  // We don't throttle 0x0 or display:none iframes, because in practice they are
  // sometimes used to drive UI logic.
  bool hidden_for_throttling = viewport_intersection.IsEmpty() &&
                               !FrameRect().IsEmpty() && owner_layout_object;
  bool subtree_throttled = false;
  Frame* parent_frame = GetFrame().Tree().Parent();
  if (parent_frame && parent_frame->View()) {
    subtree_throttled =
        parent_frame->View()->CanThrottleRenderingForPropagation();
  }
  UpdateRenderThrottlingStatus(hidden_for_throttling, subtree_throttled,
                               DisplayLockedInParentFrame());
}

void FrameView::UpdateFrameVisibility(bool intersects_viewport) {
  blink::mojom::FrameVisibility frame_visibility;
  if (LifecycleUpdatesThrottled())
    return;
  if (IsVisible()) {
    frame_visibility =
        intersects_viewport
            ? blink::mojom::FrameVisibility::kRenderedInViewport
            : blink::mojom::FrameVisibility::kRenderedOutOfViewport;
  } else {
    frame_visibility = blink::mojom::FrameVisibility::kNotRendered;
  }
  if (frame_visibility != frame_visibility_) {
    frame_visibility_ = frame_visibility;
    VisibilityChanged(frame_visibility);
  }
}

void FrameView::UpdateRenderThrottlingStatus(bool hidden_for_throttling,
                                             bool subtree_throttled,
                                             bool display_locked,
                                             bool recurse) {
  bool visibility_changed =
      (hidden_for_throttling_ || subtree_throttled_ || display_locked_) !=
      (hidden_for_throttling || subtree_throttled || display_locked);
  hidden_for_throttling_ = hidden_for_throttling;
  subtree_throttled_ = subtree_throttled;
  display_locked_ = display_locked;
  if (visibility_changed)
    VisibilityForThrottlingChanged();
  if (recurse) {
    for (Frame* child = GetFrame().Tree().FirstChild(); child;
         child = child->Tree().NextSibling()) {
      if (FrameView* child_view = child->View()) {
        child_view->UpdateRenderThrottlingStatus(
            child_view->IsHiddenForThrottling(),
            child_view->IsAttached() && CanThrottleRenderingForPropagation(),
            child_view->IsDisplayLocked(), true);
      }
    }
  }
}

bool FrameView::RectInParentIsStable(
    const base::TimeTicks& event_timestamp) const {
  if (event_timestamp - rect_in_parent_stable_since_ <
      base::TimeDelta::FromMilliseconds(
          mojom::blink::kMinScreenRectStableTimeMs)) {
    return false;
  }
  LocalFrameView* parent = ParentFrameView();
  if (!parent)
    return true;
  return parent->RectInParentIsStable(event_timestamp);
}

}  // namespace blink
