/*
 * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"

#include <memory>
#include <utility>

#include "build/build_config.h"
#include "cc/layers/layer_position_constraint.h"
#include "cc/layers/painted_overlay_scrollbar_layer.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/layers/scrollbar_layer_interface.h"
#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/input/touch_action_util.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_geometry_map.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#if defined(OS_MACOSX)
#include "third_party/blink/renderer/core/scroll/scroll_animator_mac.h"
#endif
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/scroll/main_thread_scrolling_reason.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

using blink::WebRect;
using blink::WebVector;

namespace {

cc::Layer* GraphicsLayerToCcLayer(blink::GraphicsLayer* layer) {
  return layer ? layer->CcLayer() : nullptr;
}

}  // namespace

namespace blink {

ScrollingCoordinator* ScrollingCoordinator::Create(Page* page) {
  return new ScrollingCoordinator(page);
}

ScrollingCoordinator::ScrollingCoordinator(Page* page) : page_(page) {}

ScrollingCoordinator::~ScrollingCoordinator() {
  DCHECK(!page_);
}

void ScrollingCoordinator::Trace(blink::Visitor* visitor) {
  visitor->Trace(page_);
  visitor->Trace(horizontal_scrollbars_);
  visitor->Trace(vertical_scrollbars_);
}

void ScrollingCoordinator::SetShouldHandleScrollGestureOnMainThreadRegion(
    const Region& region,
    LocalFrameView* frame_view) {
  if (cc::Layer* scroll_layer = GraphicsLayerToCcLayer(
          frame_view->LayoutViewport()->LayerForScrolling())) {
    scroll_layer->SetNonFastScrollableRegion(RegionToCCRegion(region));
  }
}

void ScrollingCoordinator::NotifyGeometryChanged(LocalFrameView* frame_view) {
  frame_view->GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
  frame_view->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(true);
  frame_view->GetScrollingContext()->SetShouldScrollOnMainThreadIsDirty(true);
}

void ScrollingCoordinator::NotifyTransformChanged(LocalFrame* frame,
                                                  const LayoutBox& box) {
  DCHECK(frame);
  if (!frame->View())
    return;

  if (frame->View()->NeedsLayout())
    return;

  if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
    // PaintTouchActionRects does not keep a list of layers with touch rects so
    // just do an update if transforms change.
    frame->View()->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(
        true);
    return;
  }

  for (PaintLayer* layer = box.EnclosingLayer(); layer;
       layer = layer->Parent()) {
    if (frame->View()
            ->GetScrollingContext()
            ->GetLayersWithTouchRects()
            ->Contains(layer)) {
      frame->View()->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(
          true);
      return;
    }
  }
}

void ScrollingCoordinator::DidScroll(const gfx::ScrollOffset& offset,
                                     const CompositorElementId& element_id) {
  for (auto* frame = page_->MainFrame(); frame;
       frame = frame->Tree().TraverseNext()) {
    // Remote frames will receive DidScroll callbacks from their own compositor.
    if (!frame->IsLocalFrame())
      continue;

    // Find the associated scrollable area using the element id and notify it
    // of the compositor-side scroll. We explicitly do not check the
    // VisualViewport which handles scroll offset differently (see:
    // VisualViewport::didScroll).
    if (LocalFrameView* view = ToLocalFrame(frame)->View()) {
      if (auto* scrollable = view->ScrollableAreaWithElementId(element_id)) {
        scrollable->DidScroll(FloatPoint(offset.x(), offset.y()));
        return;
      }
    }
  }
  // The ScrollableArea with matching ElementId may have been deleted and we can
  // safely ignore the DidScroll callback.
}

void ScrollingCoordinator::UpdateAfterPaint(LocalFrameView* frame_view) {
  LocalFrame* frame = &frame_view->GetFrame();
  DCHECK(frame->IsLocalRoot());

  bool scroll_gesture_region_dirty =
      frame_view->GetScrollingContext()->ScrollGestureRegionIsDirty();
  bool touch_event_rects_dirty =
      frame_view->GetScrollingContext()->TouchEventTargetRectsAreDirty();
  bool should_scroll_on_main_thread_dirty =
      frame_view->GetScrollingContext()->ShouldScrollOnMainThreadIsDirty();
  bool frame_scroller_dirty = FrameScrollerIsDirty(frame_view);

  if (!(scroll_gesture_region_dirty || touch_event_rects_dirty ||
        should_scroll_on_main_thread_dirty || frame_scroller_dirty)) {
    return;
  }

  SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.ScrollingCoordinator.UpdateTime");
  TRACE_EVENT0("input", "ScrollingCoordinator::UpdateAfterPaint");

  // TODO(pdr): Move the scroll gesture region logic to use touch action rects.
  // These features are similar and do not need independent implementations.
  if (scroll_gesture_region_dirty) {
    // Compute the region of the page where we can't handle scroll gestures and
    // mousewheel events
    // on the impl thread. This currently includes:
    // 1. All scrollable areas, such as subframes, overflow divs and list boxes,
    //    whose composited scrolling are not enabled. We need to do this even if
    //    the frame view whose layout was updated is not the main frame.
    // 2. Resize control areas, e.g. the small rect at the right bottom of
    //    div/textarea/iframe when CSS property "resize" is enabled.
    // 3. Plugin areas.
    Region should_handle_scroll_gesture_on_main_thread_region =
        ComputeShouldHandleScrollGestureOnMainThreadRegion(frame);
    SetShouldHandleScrollGestureOnMainThreadRegion(
        should_handle_scroll_gesture_on_main_thread_region, frame_view);
    frame_view->GetScrollingContext()->SetScrollGestureRegionIsDirty(false);
  }

  if (!(touch_event_rects_dirty || should_scroll_on_main_thread_dirty ||
        frame_scroller_dirty)) {
    return;
  }

  if (touch_event_rects_dirty) {
    UpdateTouchEventTargetRectsIfNeeded(frame);
    frame_view->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(false);
  }

  // TODO(pdr): Move the should_scroll_on_main_thread logic to use touch action
  // rects. These features are similar and do not need independent
  // implementations.
  if (should_scroll_on_main_thread_dirty ||
      frame_view->FrameIsScrollableDidChange()) {
    SetShouldUpdateScrollLayerPositionOnMainThread(
        frame, frame_view->GetMainThreadScrollingReasons());

    // Need to update scroll on main thread reasons for subframe because
    // subframe (e.g. iframe with background-attachment:fixed) should
    // scroll on main thread while the main frame scrolls on impl.
    frame_view->UpdateSubFrameScrollOnMainReason(*frame, 0);
    frame_view->GetScrollingContext()->SetShouldScrollOnMainThreadIsDirty(
        false);
  }
  frame_view->ClearFrameIsScrollableDidChange();

  UpdateUserInputScrollable(&page_->GetVisualViewport());
}

template <typename Function>
static void ForAllGraphicsLayers(GraphicsLayer& layer,
                                 const Function& function) {
  function(layer);
  for (auto* child : layer.Children())
    ForAllGraphicsLayers(*child, function);
}

// Set the touch action rects on the cc layer from the touch action data stored
// on the GraphicsLayer's paint chunks.
static void UpdateLayerTouchActionRects(GraphicsLayer& layer) {
  DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());

  // TODO(pdr): This will need to be moved to PaintArtifactCompositor (or later)
  // for SPV2 because composited layers are not known until then. The SPV2
  // implementation will iterate over the paint chunks in each composited layer
  // and will look almost the same as this function.
  DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());

  if (!layer.DrawsContent())
    return;

  const auto& layer_state = layer.GetPropertyTreeState();
  Vector<TouchActionRect> touch_action_rects_in_layer_space;
  for (const auto& chunk : layer.GetPaintController().PaintChunks()) {
    const auto* hit_test_data = chunk.GetHitTestData();
    if (!hit_test_data || hit_test_data->touch_action_rects.IsEmpty())
      continue;

    const auto& chunk_state = chunk.properties.GetPropertyTreeState();
    for (auto touch_action_rect : hit_test_data->touch_action_rects) {
      auto rect =
          FloatClipRect(FloatRect(PixelSnappedIntRect(touch_action_rect.rect)));
      if (!GeometryMapper::LocalToAncestorVisualRect(chunk_state, layer_state,
                                                     rect)) {
        continue;
      }
      LayoutRect layout_rect = LayoutRect(rect.Rect());
      layout_rect.MoveBy(-layer.GetOffsetFromTransformNode());
      touch_action_rects_in_layer_space.emplace_back(TouchActionRect(
          layout_rect, touch_action_rect.whitelisted_touch_action));
    }
  }
  layer.CcLayer()->SetTouchActionRegion(
      TouchActionRect::BuildRegion(touch_action_rects_in_layer_space));
}

static void ClearPositionConstraintExceptForLayer(GraphicsLayer* layer,
                                                  GraphicsLayer* except) {
  if (layer && layer != except && GraphicsLayerToCcLayer(layer)) {
    GraphicsLayerToCcLayer(layer)->SetPositionConstraint(
        cc::LayerPositionConstraint());
  }
}

static cc::LayerPositionConstraint ComputePositionConstraint(
    const PaintLayer* layer) {
  DCHECK(layer->HasCompositedLayerMapping());
  do {
    if (layer->GetLayoutObject().Style()->GetPosition() == EPosition::kFixed) {
      const LayoutObject& fixed_position_object = layer->GetLayoutObject();
      bool fixed_to_right = !fixed_position_object.Style()->Right().IsAuto();
      bool fixed_to_bottom = !fixed_position_object.Style()->Bottom().IsAuto();
      cc::LayerPositionConstraint constraint;
      constraint.set_is_fixed_position(true);
      constraint.set_is_fixed_to_right_edge(fixed_to_right);
      constraint.set_is_fixed_to_bottom_edge(fixed_to_bottom);
      return constraint;
    }

    layer = layer->Parent();

    // Composited layers that inherit a fixed position state will be positioned
    // with respect to the nearest compositedLayerMapping's GraphicsLayer.
    // So, once we find a layer that has its own compositedLayerMapping, we can
    // stop searching for a fixed position LayoutObject.
  } while (layer && !layer->HasCompositedLayerMapping());
  return cc::LayerPositionConstraint();
}

void ScrollingCoordinator::UpdateLayerPositionConstraint(PaintLayer* layer) {
  DCHECK(layer->HasCompositedLayerMapping());
  CompositedLayerMapping* composited_layer_mapping =
      layer->GetCompositedLayerMapping();
  GraphicsLayer* main_layer = composited_layer_mapping->ChildForSuperlayers();

  // Avoid unnecessary commits
  ClearPositionConstraintExceptForLayer(
      composited_layer_mapping->SquashingContainmentLayer(), main_layer);
  ClearPositionConstraintExceptForLayer(
      composited_layer_mapping->AncestorClippingLayer(), main_layer);
  ClearPositionConstraintExceptForLayer(
      composited_layer_mapping->MainGraphicsLayer(), main_layer);

  if (cc::Layer* scrollable_layer = GraphicsLayerToCcLayer(main_layer))
    scrollable_layer->SetPositionConstraint(ComputePositionConstraint(layer));
}

void ScrollingCoordinator::WillDestroyScrollableArea(
    ScrollableArea* scrollable_area) {
  RemoveScrollbarLayerGroup(scrollable_area, kHorizontalScrollbar);
  RemoveScrollbarLayerGroup(scrollable_area, kVerticalScrollbar);
}

void ScrollingCoordinator::RemoveScrollbarLayerGroup(
    ScrollableArea* scrollable_area,
    ScrollbarOrientation orientation) {
  ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
                                 ? horizontal_scrollbars_
                                 : vertical_scrollbars_;
  if (std::unique_ptr<ScrollbarLayerGroup> scrollbar_layer_group =
          scrollbars.Take(scrollable_area)) {
    GraphicsLayer::UnregisterContentsLayer(scrollbar_layer_group->layer.get());
  }
}

static std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
CreateScrollbarLayer(Scrollbar& scrollbar, float device_scale_factor) {
  ScrollbarTheme& theme = scrollbar.GetTheme();
  auto scrollbar_delegate =
      std::make_unique<ScrollbarLayerDelegate>(scrollbar, device_scale_factor);

  auto layer_group =
      std::make_unique<ScrollingCoordinator::ScrollbarLayerGroup>();
  if (theme.UsesOverlayScrollbars() && theme.UsesNinePatchThumbResource()) {
    auto scrollbar_layer = cc::PaintedOverlayScrollbarLayer::Create(
        std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
    scrollbar_layer->SetElementId(scrollbar.GetElementId());
    layer_group->scrollbar_layer = scrollbar_layer.get();
    layer_group->layer = std::move(scrollbar_layer);
  } else {
    auto scrollbar_layer = cc::PaintedScrollbarLayer::Create(
        std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
    scrollbar_layer->SetElementId(scrollbar.GetElementId());
    layer_group->scrollbar_layer = scrollbar_layer.get();
    layer_group->layer = std::move(scrollbar_layer);
  }

  GraphicsLayer::RegisterContentsLayer(layer_group->layer.get());

  return layer_group;
}

std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
ScrollingCoordinator::CreateSolidColorScrollbarLayer(
    ScrollbarOrientation orientation,
    int thumb_thickness,
    int track_start,
    bool is_left_side_vertical_scrollbar,
    cc::ElementId element_id) {
  cc::ScrollbarOrientation cc_orientation =
      orientation == kHorizontalScrollbar ? cc::HORIZONTAL : cc::VERTICAL;
  auto scrollbar_layer = cc::SolidColorScrollbarLayer::Create(
      cc_orientation, thumb_thickness, track_start,
      is_left_side_vertical_scrollbar, cc::ElementId());
  scrollbar_layer->SetElementId(element_id);

  auto layer_group = std::make_unique<ScrollbarLayerGroup>();
  layer_group->scrollbar_layer = scrollbar_layer.get();
  layer_group->layer = std::move(scrollbar_layer);
  GraphicsLayer::RegisterContentsLayer(layer_group->layer.get());

  return layer_group;
}

static void DetachScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer) {
  DCHECK(scrollbar_graphics_layer);

  scrollbar_graphics_layer->SetContentsToCcLayer(nullptr, false);
  scrollbar_graphics_layer->SetDrawsContent(true);
}

static void SetupScrollbarLayer(
    GraphicsLayer* scrollbar_graphics_layer,
    const ScrollingCoordinator::ScrollbarLayerGroup* scrollbar_layer_group,
    cc::Layer* scrolling_layer) {
  DCHECK(scrollbar_graphics_layer);

  if (!scrolling_layer) {
    DetachScrollbarLayer(scrollbar_graphics_layer);
    return;
  }
  scrollbar_layer_group->scrollbar_layer->SetScrollElementId(
      scrolling_layer->element_id());
  scrollbar_graphics_layer->SetContentsToCcLayer(
      scrollbar_layer_group->layer.get(),
      /*prevent_contents_opaque_changes=*/false);
  scrollbar_graphics_layer->SetDrawsContent(false);
}

void ScrollingCoordinator::AddScrollbarLayerGroup(
    ScrollableArea* scrollable_area,
    ScrollbarOrientation orientation,
    std::unique_ptr<ScrollbarLayerGroup> scrollbar_layer_group) {
  ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
                                 ? horizontal_scrollbars_
                                 : vertical_scrollbars_;
  scrollbars.insert(scrollable_area, std::move(scrollbar_layer_group));
}

ScrollingCoordinator::ScrollbarLayerGroup*
ScrollingCoordinator::GetScrollbarLayerGroup(ScrollableArea* scrollable_area,
                                             ScrollbarOrientation orientation) {
  ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
                                 ? horizontal_scrollbars_
                                 : vertical_scrollbars_;
  return scrollbars.at(scrollable_area);
}

void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
    ScrollableArea* scrollable_area,
    ScrollbarOrientation orientation) {
  if (!page_ || !page_->MainFrame())
    return;

  GraphicsLayer* scrollbar_graphics_layer =
      orientation == kHorizontalScrollbar
          ? scrollable_area->LayerForHorizontalScrollbar()
          : scrollable_area->LayerForVerticalScrollbar();

  if (scrollbar_graphics_layer) {
    Scrollbar& scrollbar = orientation == kHorizontalScrollbar
                               ? *scrollable_area->HorizontalScrollbar()
                               : *scrollable_area->VerticalScrollbar();
    if (scrollbar.IsCustomScrollbar()) {
      DetachScrollbarLayer(scrollbar_graphics_layer);
      scrollbar_graphics_layer->CcLayer()->AddMainThreadScrollingReasons(
          MainThreadScrollingReason::kCustomScrollbarScrolling);
      return;
    }

    // Invalidate custom scrollbar scrolling reason in case a custom
    // scrollbar becomes a non-custom one.
    scrollbar_graphics_layer->CcLayer()->ClearMainThreadScrollingReasons(
        MainThreadScrollingReason::kCustomScrollbarScrolling);
    ScrollbarLayerGroup* scrollbar_layer_group =
        GetScrollbarLayerGroup(scrollable_area, orientation);
    if (!scrollbar_layer_group) {
      Settings* settings = page_->MainFrame()->GetSettings();

      std::unique_ptr<ScrollbarLayerGroup> group;
      if (settings->GetUseSolidColorScrollbars()) {
        DCHECK(RuntimeEnabledFeatures::OverlayScrollbarsEnabled());
        group = CreateSolidColorScrollbarLayer(
            orientation, scrollbar.GetTheme().ThumbThickness(scrollbar),
            scrollbar.GetTheme().TrackPosition(scrollbar),
            scrollable_area->ShouldPlaceVerticalScrollbarOnLeft(),
            scrollable_area->GetScrollbarElementId(orientation));
      } else {
        group = CreateScrollbarLayer(scrollbar,
                                     page_->DeviceScaleFactorDeprecated());
      }

      scrollbar_layer_group = group.get();
      AddScrollbarLayerGroup(scrollable_area, orientation, std::move(group));
    }

    cc::Layer* scroll_layer =
        GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
    SetupScrollbarLayer(scrollbar_graphics_layer, scrollbar_layer_group,
                        scroll_layer);

    // Root layer non-overlay scrollbars should be marked opaque to disable
    // blending.
    bool is_opaque_scrollbar = !scrollbar.IsOverlayScrollbar();
    scrollbar_graphics_layer->SetContentsOpaque(
        IsForMainFrame(scrollable_area) && is_opaque_scrollbar);
  } else {
    RemoveScrollbarLayerGroup(scrollable_area, orientation);
  }
}

bool ScrollingCoordinator::UpdateCompositedScrollOffset(
    ScrollableArea* scrollable_area) {
  GraphicsLayer* scroll_layer = scrollable_area->LayerForScrolling();
  if (!scroll_layer)
    return false;

  cc::Layer* cc_layer =
      GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
  if (!cc_layer)
    return false;

  cc_layer->SetScrollOffset(
      static_cast<gfx::ScrollOffset>(scrollable_area->ScrollPosition()));
  return true;
}

void ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
    ScrollableArea* scrollable_area) {
  if (!page_ || !page_->MainFrame())
    return;

  UpdateUserInputScrollable(scrollable_area);

  cc::Layer* cc_layer =
      GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
  cc::Layer* container_layer =
      GraphicsLayerToCcLayer(scrollable_area->LayerForContainer());
  if (cc_layer) {
    cc_layer->SetScrollable(container_layer->bounds());
    FloatPoint scroll_position(scrollable_area->ScrollPosition());
    cc_layer->SetScrollOffset(static_cast<gfx::ScrollOffset>(scroll_position));
    // TODO(bokan): This method shouldn't be resizing the layer geometry. That
    // happens in CompositedLayerMapping::UpdateScrollingLayerGeometry.
    LayoutSize subpixel_accumulation =
        scrollable_area->Layer()
            ? scrollable_area->Layer()->SubpixelAccumulation()
            : LayoutSize();
    LayoutSize contents_size =
        scrollable_area->GetLayoutBox()
            ? LayoutSize(scrollable_area->GetLayoutBox()->ScrollWidth(),
                         scrollable_area->GetLayoutBox()->ScrollHeight())
            : LayoutSize(scrollable_area->ContentsSize());
    IntSize scroll_contents_size =
        PixelSnappedIntRect(
            LayoutRect(LayoutPoint(subpixel_accumulation), contents_size))
            .Size();

    if (scrollable_area != &page_->GetVisualViewport()) {
      // The scrolling contents layer must be at least as large as its clip.
      // The visual viewport is special because the size of its scrolling
      // content depends on the page scale factor. Its scrollable content is
      // the layout viewport which is sized based on the minimum allowed page
      // scale so it actually can be smaller than its clip.
      scroll_contents_size =
          scroll_contents_size.ExpandedTo(IntSize(container_layer->bounds()));

      // VisualViewport scrolling may involve pinch zoom and gets routed through
      // WebViewImpl explicitly rather than via ScrollingCoordinator::DidScroll
      // since it needs to be set in tandem with the page scale delta.
      cc_layer->set_did_scroll_callback(WTF::BindRepeating(
          &ScrollingCoordinator::DidScroll, WrapWeakPersistent(this)));
    }

    cc_layer->SetBounds(static_cast<gfx::Size>(scroll_contents_size));
  }
  if (ScrollbarLayerGroup* scrollbar_layer_group =
          GetScrollbarLayerGroup(scrollable_area, kHorizontalScrollbar)) {
    GraphicsLayer* horizontal_scrollbar_layer =
        scrollable_area->LayerForHorizontalScrollbar();
    if (horizontal_scrollbar_layer) {
      SetupScrollbarLayer(horizontal_scrollbar_layer, scrollbar_layer_group,
                          cc_layer);
    }
  }
  if (ScrollbarLayerGroup* scrollbar_layer_group =
          GetScrollbarLayerGroup(scrollable_area, kVerticalScrollbar)) {
    GraphicsLayer* vertical_scrollbar_layer =
        scrollable_area->LayerForVerticalScrollbar();

    if (vertical_scrollbar_layer) {
      SetupScrollbarLayer(vertical_scrollbar_layer, scrollbar_layer_group,
                          cc_layer);
    }
  }

  // Update the viewport layer registration if the outer viewport may have
  // changed.
  if (IsForRootLayer(scrollable_area))
    page_->GetChromeClient().RegisterViewportLayers();

  CompositorAnimationTimeline* timeline;
  // LocalFrameView::CompositorAnimationTimeline() can indirectly return
  // m_programmaticScrollAnimatorTimeline if it does not have its own
  // timeline.
  if (scrollable_area->IsPaintLayerScrollableArea()) {
    timeline = ToPaintLayerScrollableArea(scrollable_area)
                   ->GetCompositorAnimationTimeline();
  } else {
    timeline = programmatic_scroll_animator_timeline_.get();
  }
  scrollable_area->LayerForScrollingDidChange(timeline);

  return;
}

using GraphicsLayerHitTestRects =
    WTF::HashMap<const GraphicsLayer*, Vector<TouchActionRect>>;

// In order to do a DFS cross-frame walk of the Layer tree, we need to know
// which Layers have child frames inside of them. This computes a mapping for
// the current frame which we can consult while walking the layers of that
// frame.  Whenever we descend into a new frame, a new map will be created.
using LayerFrameMap =
    HeapHashMap<const PaintLayer*, HeapVector<Member<const LocalFrame>>>;
static void MakeLayerChildFrameMap(const LocalFrame* current_frame,
                                   LayerFrameMap* map) {
  map->clear();
  const FrameTree& tree = current_frame->Tree();
  for (const Frame* child = tree.FirstChild(); child;
       child = child->Tree().NextSibling()) {
    if (!child->IsLocalFrame())
      continue;
    auto* owner_layout_object = ToLocalFrame(child)->OwnerLayoutObject();
    if (!owner_layout_object)
      continue;
    const PaintLayer* containing_layer = owner_layout_object->EnclosingLayer();
    LayerFrameMap::iterator iter = map->find(containing_layer);
    if (iter == map->end())
      map->insert(containing_layer, HeapVector<Member<const LocalFrame>>())
          .stored_value->value.push_back(ToLocalFrame(child));
    else
      iter->value.push_back(ToLocalFrame(child));
  }
}

static void ProjectRectsToGraphicsLayerSpaceRecursive(
    const PaintLayer* cur_layer,
    const LayerHitTestRects& layer_rects,
    GraphicsLayerHitTestRects& graphics_rects,
    LayoutGeometryMap& geometry_map,
    HashSet<const PaintLayer*>& layers_with_rects,
    LayerFrameMap& layer_child_frame_map) {
  // Project any rects for the current layer
  LayerHitTestRects::const_iterator layer_iter = layer_rects.find(cur_layer);
  if (layer_iter != layer_rects.end()) {
    // Find the enclosing composited layer when it's in another document (for
    // non-composited iframes).
    const PaintLayer* composited_layer =
        layer_iter->key
            ->EnclosingLayerForPaintInvalidationCrossingFrameBoundaries();
    DCHECK(composited_layer);

    // Find the appropriate GraphicsLayer for the composited Layer.
    GraphicsLayer* graphics_layer =
        composited_layer->GraphicsLayerBacking(&cur_layer->GetLayoutObject());

    GraphicsLayerHitTestRects::iterator gl_iter =
        graphics_rects.find(graphics_layer);
    Vector<TouchActionRect>* gl_rects;
    if (gl_iter == graphics_rects.end()) {
      gl_rects =
          &graphics_rects.insert(graphics_layer, Vector<TouchActionRect>())
               .stored_value->value;
    } else {
      gl_rects = &gl_iter->value;
    }

    // Transform each rect to the co-ordinate space of the graphicsLayer.
    for (size_t i = 0; i < layer_iter->value.size(); ++i) {
      TouchActionRect rect = layer_iter->value[i];
      if (composited_layer != cur_layer) {
        FloatQuad compositor_quad = geometry_map.MapToAncestor(
            FloatRect(rect.rect), &composited_layer->GetLayoutObject());
        rect.rect = LayoutRect(compositor_quad.BoundingBox());
        // If the enclosing composited layer itself is scrolled, we have to undo
        // the subtraction of its scroll offset since we want the offset
        // relative to the scrolling content, not the element itself.
        if (composited_layer->GetLayoutObject().HasOverflowClip()) {
          rect.rect.Move(
              composited_layer->GetLayoutBox()->ScrolledContentOffset());
        }
      }
      PaintLayer::MapRectInPaintInvalidationContainerToBacking(
          composited_layer->GetLayoutObject(), rect.rect);
      rect.rect.Move(-graphics_layer->OffsetFromLayoutObject());

      gl_rects->push_back(rect);
    }
  }

  // Walk child layers of interest
  for (const PaintLayer* child_layer = cur_layer->FirstChild(); child_layer;
       child_layer = child_layer->NextSibling()) {
    if (layers_with_rects.Contains(child_layer)) {
      geometry_map.PushMappingsToAncestor(child_layer, cur_layer);
      ProjectRectsToGraphicsLayerSpaceRecursive(
          child_layer, layer_rects, graphics_rects, geometry_map,
          layers_with_rects, layer_child_frame_map);
      geometry_map.PopMappingsToAncestor(cur_layer);
    }
  }

  // If this layer has any frames of interest as a child of it, walk those (with
  // an updated frame map).
  LayerFrameMap::iterator map_iter = layer_child_frame_map.find(cur_layer);
  if (map_iter != layer_child_frame_map.end()) {
    for (size_t i = 0; i < map_iter->value.size(); i++) {
      const LocalFrame* child_frame = map_iter->value[i];
      if (child_frame->ShouldThrottleRendering())
        continue;

      const PaintLayer* child_layer =
          child_frame->View()->GetLayoutView()->Layer();
      if (layers_with_rects.Contains(child_layer)) {
        LayerFrameMap new_layer_child_frame_map;
        MakeLayerChildFrameMap(child_frame, &new_layer_child_frame_map);
        geometry_map.PushMappingsToAncestor(child_layer, cur_layer);
        ProjectRectsToGraphicsLayerSpaceRecursive(
            child_layer, layer_rects, graphics_rects, geometry_map,
            layers_with_rects, new_layer_child_frame_map);
        geometry_map.PopMappingsToAncestor(cur_layer);
      }
    }
  }
}

static void ProjectRectsToGraphicsLayerSpace(
    LocalFrame* main_frame,
    const LayerHitTestRects& layer_rects,
    GraphicsLayerHitTestRects& graphics_rects) {
  TRACE_EVENT0("input",
               "ScrollingCoordinator::projectRectsToGraphicsLayerSpace");

  if (main_frame->ShouldThrottleRendering())
    return;

  bool touch_handler_in_child_frame = false;

  // We have a set of rects per Layer, we need to map them to their bounding
  // boxes in their enclosing composited layer. To do this most efficiently
  // we'll walk the Layer tree using LayoutGeometryMap. First record all the
  // branches we should traverse in the tree (including all documents on the
  // page).
  HashSet<const PaintLayer*> layers_with_rects;
  for (const auto& layer_rect : layer_rects) {
    const PaintLayer* layer = layer_rect.key;
    do {
      if (!layers_with_rects.insert(layer).is_new_entry)
        break;

      if (layer->Parent()) {
        layer = layer->Parent();
      } else {
        auto* parent_doc_layout_object =
            layer->GetLayoutObject().GetFrame()->OwnerLayoutObject();
        if (parent_doc_layout_object) {
          layer = parent_doc_layout_object->EnclosingLayer();
          touch_handler_in_child_frame = true;
        }
      }
    } while (layer);
  }

  // Now walk the layer projecting rects while maintaining a LayoutGeometryMap
  MapCoordinatesFlags flags = kUseTransforms;
  if (touch_handler_in_child_frame)
    flags |= kTraverseDocumentBoundaries;
  PaintLayer* root_layer = main_frame->ContentLayoutObject()->Layer();
  LayoutGeometryMap geometry_map(flags);
  geometry_map.PushMappingsToAncestor(root_layer, nullptr);
  LayerFrameMap layer_child_frame_map;
  MakeLayerChildFrameMap(main_frame, &layer_child_frame_map);
  ProjectRectsToGraphicsLayerSpaceRecursive(
      root_layer, layer_rects, graphics_rects, geometry_map, layers_with_rects,
      layer_child_frame_map);
}

void ScrollingCoordinator::UpdateTouchEventTargetRectsIfNeeded(
    LocalFrame* frame) {
  TRACE_EVENT0("input",
               "ScrollingCoordinator::updateTouchEventTargetRectsIfNeeded");

  // TODO(chrishtr): implement touch event target rects for SPv2.
  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
    return;

  if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
    auto* view_layer = frame->View()->GetLayoutView()->Layer();
    if (auto* root = view_layer->Compositor()->PaintRootGraphicsLayer())
      ForAllGraphicsLayers(*root, UpdateLayerTouchActionRects);
  } else {
    LayerHitTestRects touch_event_target_rects;
    ComputeTouchEventTargetRects(frame, touch_event_target_rects);
    SetTouchEventTargetRects(frame, touch_event_target_rects);
  }
}

void ScrollingCoordinator::UpdateUserInputScrollable(
    ScrollableArea* scrollable_area) {
  cc::Layer* cc_layer =
      GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
  if (cc_layer) {
    bool can_scroll_x =
        scrollable_area->UserInputScrollable(kHorizontalScrollbar);
    bool can_scroll_y =
        scrollable_area->UserInputScrollable(kVerticalScrollbar);
    cc_layer->SetUserScrollable(can_scroll_x, can_scroll_y);
  }
}

void ScrollingCoordinator::Reset(LocalFrame* frame) {
  for (const auto& scrollbar : horizontal_scrollbars_)
    GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
  for (const auto& scrollbar : vertical_scrollbars_)
    GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());

  horizontal_scrollbars_.clear();
  vertical_scrollbars_.clear();
  frame->View()->GetScrollingContext()->GetLayersWithTouchRects()->clear();
  frame->View()->ClearFrameIsScrollableDidChange();
}

// Note that in principle this could be called more often than
// computeTouchEventTargetRects, for example during a non-composited scroll
// (although that's not yet implemented - crbug.com/261307).
void ScrollingCoordinator::SetTouchEventTargetRects(
    LocalFrame* frame,
    LayerHitTestRects& layer_rects) {
  TRACE_EVENT0("input", "ScrollingCoordinator::setTouchEventTargetRects");

  DCHECK(!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());

  // Ensure we have an entry for each composited layer that previously had rects
  // (so that old ones will get cleared out). Note that ideally we'd track this
  // on GraphicsLayer instead of Layer, but we have no good hook into the
  // lifetime of a GraphicsLayer.
  GraphicsLayerHitTestRects graphics_layer_rects;
  for (const PaintLayer* layer :
       *frame->View()->GetScrollingContext()->GetLayersWithTouchRects()) {
    if (layer->GetLayoutObject().GetFrameView() &&
        layer->GetLayoutObject().GetFrameView()->ShouldThrottleRendering()) {
      continue;
    }
    GraphicsLayer* main_graphics_layer =
        layer->GraphicsLayerBacking(&layer->GetLayoutObject());
    if (main_graphics_layer) {
      graphics_layer_rects.insert(main_graphics_layer,
                                  Vector<TouchActionRect>());
    }
    GraphicsLayer* scrolling_contents_layer = layer->GraphicsLayerBacking();
    if (scrolling_contents_layer &&
        scrolling_contents_layer != main_graphics_layer) {
      graphics_layer_rects.insert(scrolling_contents_layer,
                                  Vector<TouchActionRect>());
    }
  }

  frame->View()->GetScrollingContext()->GetLayersWithTouchRects()->clear();
  for (const auto& layer_rect : layer_rects) {
    if (!layer_rect.value.IsEmpty()) {
      DCHECK(layer_rect.key->IsRootLayer() || layer_rect.key->Parent());
      const PaintLayer* composited_layer =
          layer_rect.key
              ->EnclosingLayerForPaintInvalidationCrossingFrameBoundaries();
      if (!composited_layer)
        continue;
      frame->View()->GetScrollingContext()->GetLayersWithTouchRects()->insert(
          composited_layer);
    }
  }

  ProjectRectsToGraphicsLayerSpace(frame, layer_rects, graphics_layer_rects);

  for (const auto& layer_rect : graphics_layer_rects) {
    const GraphicsLayer* graphics_layer = layer_rect.key;
    graphics_layer->CcLayer()->SetTouchActionRegion(
        TouchActionRect::BuildRegion(layer_rect.value));
  }
}

void ScrollingCoordinator::TouchEventTargetRectsDidChange(LocalFrame* frame) {
  if (!frame)
    return;

  // If frame is not a local root, then the call to StaleInCompositingMode()
  // below may unexpectedly fail.
  DCHECK(frame->IsLocalRoot());
  LocalFrameView* frame_view = frame->View();
  if (!frame_view)
    return;

  // Wait until after layout to update.
  if (frame_view->NeedsLayout())
    return;

  // FIXME: scheduleAnimation() is just a method of forcing the compositor to
  // realize that it needs to commit here. We should expose a cleaner API for
  // this.
  auto* layout_view = frame->ContentLayoutObject();
  if (layout_view && layout_view->Compositor() &&
      layout_view->Compositor()->StaleInCompositingMode()) {
    frame_view->ScheduleAnimation();
  }

  frame_view->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(true);
}

void ScrollingCoordinator::UpdateScrollParentForGraphicsLayer(
    GraphicsLayer* child,
    const PaintLayer* parent) {
  cc::Layer* scroll_parent_cc_layer = nullptr;
  if (parent && parent->HasCompositedLayerMapping())
    scroll_parent_cc_layer = GraphicsLayerToCcLayer(
        parent->GetCompositedLayerMapping()->ScrollingContentsLayer());

  child->SetScrollParent(scroll_parent_cc_layer);
}

void ScrollingCoordinator::UpdateClipParentForGraphicsLayer(
    GraphicsLayer* child,
    const PaintLayer* parent) {
  cc::Layer* clip_parent_cc_layer = nullptr;
  if (parent && parent->HasCompositedLayerMapping()) {
    clip_parent_cc_layer = GraphicsLayerToCcLayer(
        parent->GetCompositedLayerMapping()->ParentForSublayers());
  }

  child->SetClipParent(clip_parent_cc_layer);
}

void ScrollingCoordinator::WillDestroyLayer(PaintLayer* layer) {
  layer->GetLayoutObject()
      .GetFrame()
      ->View()
      ->GetScrollingContext()
      ->GetLayersWithTouchRects()
      ->erase(layer);
}

void ScrollingCoordinator::SetShouldUpdateScrollLayerPositionOnMainThread(
    LocalFrame* frame,
    MainThreadScrollingReasons main_thread_scrolling_reasons) {
  VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport();
  GraphicsLayer* visual_viewport_layer = visual_viewport.ScrollLayer();
  cc::Layer* visual_viewport_scroll_layer =
      GraphicsLayerToCcLayer(visual_viewport_layer);
  ScrollableArea* scrollable_area = frame->View()->LayoutViewport();
  GraphicsLayer* layer = scrollable_area->LayerForScrolling();
  if (cc::Layer* scroll_layer = GraphicsLayerToCcLayer(layer)) {
    if (main_thread_scrolling_reasons) {
      if (ScrollAnimatorBase* scroll_animator =
              scrollable_area->ExistingScrollAnimator()) {
        DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
               frame->GetDocument()->Lifecycle().GetState() >=
                   DocumentLifecycle::kCompositingClean);
        scroll_animator->TakeOverCompositorAnimation();
      }
      scroll_layer->AddMainThreadScrollingReasons(
          main_thread_scrolling_reasons);
      if (visual_viewport_scroll_layer) {
        if (ScrollAnimatorBase* scroll_animator =
                visual_viewport.ExistingScrollAnimator()) {
          DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
                 frame->GetDocument()->Lifecycle().GetState() >=
                     DocumentLifecycle::kCompositingClean);
          scroll_animator->TakeOverCompositorAnimation();
        }
        visual_viewport_scroll_layer->AddMainThreadScrollingReasons(
            main_thread_scrolling_reasons);
      }
    } else {
      // Clear all main thread scrolling reasons except the one that's set
      // if there is a running scroll animation.
      uint32_t main_thread_scrolling_reasons_to_clear = ~0u;
      main_thread_scrolling_reasons_to_clear &=
          ~MainThreadScrollingReason::kHandlingScrollFromMainThread;
      scroll_layer->ClearMainThreadScrollingReasons(
          main_thread_scrolling_reasons_to_clear);
      if (visual_viewport_scroll_layer)
        visual_viewport_scroll_layer->ClearMainThreadScrollingReasons(
            main_thread_scrolling_reasons_to_clear);
    }
  }
}

void ScrollingCoordinator::LayerTreeViewInitialized(
    WebLayerTreeView& layer_tree_view,
    LocalFrameView* view) {
  if (Platform::Current()->IsThreadedAnimationEnabled()) {
    std::unique_ptr<CompositorAnimationTimeline> timeline =
        CompositorAnimationTimeline::Create();
    auto host = std::make_unique<CompositorAnimationHost>(
        layer_tree_view.CompositorAnimationHost());
    if (view && view->GetFrame().LocalFrameRoot() != page_->MainFrame()) {
      view->GetScrollingContext()->SetAnimationHost(std::move(host));
      view->GetScrollingContext()->SetAnimationTimeline(std::move(timeline));
      view->GetCompositorAnimationHost()->AddTimeline(
          *view->GetCompositorAnimationTimeline());
    } else {
      animation_host_ = std::move(host);
      programmatic_scroll_animator_timeline_ = std::move(timeline);
      animation_host_->AddTimeline(
          *programmatic_scroll_animator_timeline_.get());
    }
  }
}

void ScrollingCoordinator::WillCloseLayerTreeView(
    WebLayerTreeView& layer_tree_view,
    LocalFrameView* view) {
  if (view && view->GetFrame().LocalFrameRoot() != page_->MainFrame()) {
    view->GetCompositorAnimationHost()->RemoveTimeline(
        *view->GetCompositorAnimationTimeline());
    view->GetScrollingContext()->SetAnimationTimeline(nullptr);
    view->GetScrollingContext()->SetAnimationHost(nullptr);
  } else if (programmatic_scroll_animator_timeline_) {
    animation_host_->RemoveTimeline(
        *programmatic_scroll_animator_timeline_.get());
    programmatic_scroll_animator_timeline_ = nullptr;
    animation_host_ = nullptr;
  }
}

void ScrollingCoordinator::WillBeDestroyed() {
  DCHECK(page_);

  page_ = nullptr;
  for (const auto& scrollbar : horizontal_scrollbars_)
    GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
  for (const auto& scrollbar : vertical_scrollbars_)
    GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
}

bool ScrollingCoordinator::CoordinatesScrollingForFrameView(
    LocalFrameView* frame_view) const {
  DCHECK(IsMainThread());

  // We currently only support composited mode.
  auto* layout_view = frame_view->GetFrame().ContentLayoutObject();
  if (!layout_view)
    return false;
  return layout_view->UsesCompositing();
}

Region ScrollingCoordinator::ComputeShouldHandleScrollGestureOnMainThreadRegion(
    const LocalFrame* frame) const {
  Region should_handle_scroll_gesture_on_main_thread_region;
  LocalFrameView* frame_view = frame->View();

  if (!frame_view || frame_view->ShouldThrottleRendering() ||
      !frame_view->IsVisible()) {
    return should_handle_scroll_gesture_on_main_thread_region;
  }

  if (const LocalFrameView::ScrollableAreaSet* scrollable_areas =
          frame_view->ScrollableAreas()) {
    for (const ScrollableArea* scrollable_area : *scrollable_areas) {
      // Composited scrollable areas can be scrolled off the main thread.
      if (scrollable_area->UsesCompositedScrolling())
        continue;

      IntRect box = scrollable_area->ScrollableAreaBoundingBox();
      should_handle_scroll_gesture_on_main_thread_region.Unite(box);
    }
  }

  // We use GestureScrollBegin/Update/End for moving the resizer handle. So we
  // mark these small resizer areas as non-fast-scrollable to allow the scroll
  // gestures to be passed to main thread if they are targeting the resizer
  // area. (Resizing is done in EventHandler.cpp on main thread).
  if (const LocalFrameView::ResizerAreaSet* resizer_areas =
          frame_view->ResizerAreas()) {
    for (const LayoutBox* box : *resizer_areas) {
      PaintLayerScrollableArea* scrollable_area =
          box->Layer()->GetScrollableArea();
      IntRect bounds = box->AbsoluteBoundingBoxRect();
      // Get the corner in local coords.
      IntRect corner =
          scrollable_area->ResizerCornerRect(bounds, kResizerForTouch);
      // Map corner to top-frame coords.
      corner = scrollable_area->GetLayoutBox()
                   ->LocalToAbsoluteQuad(FloatRect(corner),
                                         kTraverseDocumentBoundaries)
                   .EnclosingBoundingBox();
      should_handle_scroll_gesture_on_main_thread_region.Unite(corner);
    }
  }

  for (const auto& plugin : frame_view->Plugins()) {
    if (plugin->WantsWheelEvents()) {
      IntRect box = frame_view->ConvertToRootFrame(plugin->FrameRect());
      should_handle_scroll_gesture_on_main_thread_region.Unite(box);
    }
  }

  const FrameTree& tree = frame->Tree();
  for (Frame* sub_frame = tree.FirstChild(); sub_frame;
       sub_frame = sub_frame->Tree().NextSibling()) {
    if (sub_frame->IsLocalFrame()) {
      should_handle_scroll_gesture_on_main_thread_region.Unite(
          ComputeShouldHandleScrollGestureOnMainThreadRegion(
              ToLocalFrame(sub_frame)));
    }
  }

  return should_handle_scroll_gesture_on_main_thread_region;
}

static void AccumulateDocumentTouchEventTargetRects(
    LayerHitTestRects& rects,
    EventHandlerRegistry::EventHandlerClass event_class,
    Document* document,
    TouchAction supported_fast_actions) {
  DCHECK(document);
  const EventTargetSet* targets =
      document->GetFrame()->GetEventHandlerRegistry().EventHandlerTargets(
          event_class);
  if (!targets)
    return;

  // If there's a handler on the window, document, html or body element (fairly
  // common in practice), then we can quickly mark the entire document and skip
  // looking at any other handlers.  Note that technically a handler on the body
  // doesn't cover the whole document, but it's reasonable to be conservative
  // and report the whole document anyway.
  //
  // Fullscreen HTML5 video when OverlayFullscreenVideo is enabled is
  // implemented by replacing the root cc::layer with the video layer so doing
  // this optimization causes the compositor to think that there are no
  // handlers, therefore skip it.
  if (!document->GetLayoutView()->Compositor()->InOverlayFullscreenVideo() &&
      (!document->View() || !document->View()->ShouldThrottleRendering())) {
    if (targets->Contains(document) ||
        (document->documentElement() &&
         targets->Contains(document->documentElement())) ||
        (document->body() && targets->Contains(document->body())) ||
        targets->Contains(document->GetFrame()->DomWindow())) {
      document->GetLayoutView()->ComputeLayerHitTestRects(
          rects, supported_fast_actions);
      return;
    }
  }

  for (const auto& event_target : *targets) {
    EventTarget* target = event_target.key;
    Node* node = target->ToNode();
    LocalDOMWindow* window = target->ToLocalDOMWindow();
    if (!window && (!node || !node->isConnected()))
      continue;

    Document& document_node =
        window ? *window->document() : node->GetDocument();

    // If the document belongs to an invisible subframe it does not have a
    // composited layer and should be skipped.
    if (document_node.IsInInvisibleSubframe())
      continue;

    // If the node belongs to a throttled frame, skip it.
    if (document_node.View() && document_node.View()->ShouldThrottleRendering())
      continue;

    // Only event targets belonging to the same local root as |document| should
    // be processed here.
    DCHECK_EQ(&document->GetFrame()->LocalFrameRoot(),
              &document_node.GetFrame()->LocalFrameRoot());

    if ((window || node->IsDocumentNode()) && &document_node != document) {
      AccumulateDocumentTouchEventTargetRects(
          rects, event_class, &document_node, supported_fast_actions);
    } else if (node) {
      LayoutObject* layout_object = node->GetLayoutObject();
      if (!layout_object)
        continue;
      // If the set also contains one of our ancestor nodes then processing
      // this node would be redundant.
      bool has_touch_event_target_ancestor = false;
      for (Node& ancestor : NodeTraversal::AncestorsOf(*node)) {
        if (has_touch_event_target_ancestor)
          break;
        if (targets->Contains(&ancestor))
          has_touch_event_target_ancestor = true;
      }
      if (!has_touch_event_target_ancestor) {
        // Walk up the tree to the outermost non-composited scrollable layer.
        PaintLayer* enclosing_non_composited_scroll_layer = nullptr;
        for (PaintLayer* parent = layout_object->EnclosingLayer();
             parent && parent->GetCompositingState() == kNotComposited;
             parent = parent->Parent()) {
          if (parent->ScrollsOverflow())
            enclosing_non_composited_scroll_layer = parent;
        }

        // Report the whole non-composited scroll layer as a touch hit rect
        // because any rects inside of it may move around relative to their
        // enclosing composited layer without causing the rects to be
        // recomputed. Non-composited scrolling occurs on the main thread, so
        // we're not getting much benefit from compositor touch hit testing in
        // this case anyway.
        if (enclosing_non_composited_scroll_layer) {
          enclosing_non_composited_scroll_layer->ComputeSelfHitTestRects(
              rects, supported_fast_actions);
        }

        layout_object->ComputeLayerHitTestRects(rects, supported_fast_actions);
      }
    }
  }
}

void ScrollingCoordinator::ComputeTouchEventTargetRects(
    LocalFrame* frame,
    LayerHitTestRects& rects) {
  TRACE_EVENT0("input", "ScrollingCoordinator::computeTouchEventTargetRects");

  DCHECK(!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());

  Document* document = frame->GetDocument();
  if (!document || !document->View() || !document->GetFrame())
    return;

  AccumulateDocumentTouchEventTargetRects(
      rects, EventHandlerRegistry::kTouchAction, document,
      TouchAction::kTouchActionAuto);
  AccumulateDocumentTouchEventTargetRects(
      rects, EventHandlerRegistry::kTouchStartOrMoveEventBlocking, document,
      TouchAction::kTouchActionNone);
  AccumulateDocumentTouchEventTargetRects(
      rects, EventHandlerRegistry::kTouchStartOrMoveEventBlockingLowLatency,
      document, TouchAction::kTouchActionNone);
}

void ScrollingCoordinator::
    FrameViewHasBackgroundAttachmentFixedObjectsDidChange(
        LocalFrameView* frame_view) {
  DCHECK(IsMainThread());
  DCHECK(frame_view);

  if (!CoordinatesScrollingForFrameView(frame_view))
    return;

  frame_view->GetScrollingContext()->SetShouldScrollOnMainThreadIsDirty(true);
}

void ScrollingCoordinator::FrameViewFixedObjectsDidChange(
    LocalFrameView* frame_view) {
  DCHECK(IsMainThread());
  DCHECK(frame_view);

  if (!CoordinatesScrollingForFrameView(frame_view))
    return;

  frame_view->GetScrollingContext()->SetShouldScrollOnMainThreadIsDirty(true);
}

bool ScrollingCoordinator::IsForRootLayer(
    ScrollableArea* scrollable_area) const {
  if (!page_->MainFrame()->IsLocalFrame())
    return false;

  // FIXME(305811): Refactor for OOPI.
  if (auto* layout_view =
          page_->DeprecatedLocalMainFrame()->View()->GetLayoutView())
    return scrollable_area == layout_view->Layer()->GetScrollableArea();
  return false;
}

bool ScrollingCoordinator::IsForMainFrame(
    ScrollableArea* scrollable_area) const {
  if (!page_->MainFrame()->IsLocalFrame())
    return false;

  // FIXME(305811): Refactor for OOPI.
  return scrollable_area ==
         page_->DeprecatedLocalMainFrame()->View()->LayoutViewport();
}

void ScrollingCoordinator::FrameViewRootLayerDidChange(
    LocalFrameView* frame_view) {
  DCHECK(IsMainThread());
  DCHECK(page_);

  if (!CoordinatesScrollingForFrameView(frame_view))
    return;

  NotifyGeometryChanged(frame_view);
}

bool ScrollingCoordinator::FrameScrollerIsDirty(
    LocalFrameView* frame_view) const {
  DCHECK(frame_view);
  if (frame_view->FrameIsScrollableDidChange())
    return true;

  if (cc::Layer* scroll_layer =
          frame_view ? GraphicsLayerToCcLayer(
                           frame_view->LayoutViewport()->LayerForScrolling())
                     : nullptr) {
    return static_cast<gfx::Size>(
               frame_view->LayoutViewport()->ContentsSize()) !=
           scroll_layer->bounds();
  }
  return false;
}

}  // namespace blink
