/*
 * 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 "core/page/scrolling/ScrollingCoordinator.h"

#include "core/dom/Document.h"
#include "core/dom/Fullscreen.h"
#include "core/dom/Node.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLElement.h"
#include "core/layout/LayoutGeometryMap.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/layout/compositing/CompositedLayerMapping.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/plugins/PluginView.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "platform/animation/CompositorAnimationTimeline.h"
#include "platform/exported/WebScrollbarImpl.h"
#include "platform/exported/WebScrollbarThemeGeometryNative.h"
#include "platform/geometry/Region.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsLayer.h"
#if OS(MACOSX)
#include "platform/mac/ScrollAnimatorMac.h"
#endif
#include "platform/scroll/MainThreadScrollingReason.h"
#include "platform/scroll/ScrollAnimatorBase.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebLayerPositionConstraint.h"
#include "public/platform/WebLayerTreeView.h"
#include "public/platform/WebScrollbarLayer.h"
#include "public/platform/WebScrollbarThemeGeometry.h"
#include "public/platform/WebScrollbarThemePainter.h"
#include "wtf/PtrUtil.h"
#include "wtf/text/StringBuilder.h"
#include <memory>

using blink::WebLayer;
using blink::WebLayerPositionConstraint;
using blink::WebRect;
using blink::WebScrollbarLayer;
using blink::WebVector;

namespace {

WebLayer* toWebLayer(blink::GraphicsLayer* layer) {
  return layer ? layer->platformLayer() : nullptr;
}

}  // namespace

namespace blink {

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

ScrollingCoordinator::ScrollingCoordinator(Page* page)
    : m_page(page),
      m_scrollGestureRegionIsDirty(false),
      m_touchEventTargetRectsAreDirty(false),
      m_shouldScrollOnMainThreadDirty(false),
      m_wasFrameScrollable(false),
      m_lastMainThreadScrollingReasons(0) {}

ScrollingCoordinator::~ScrollingCoordinator() {
  ASSERT(!m_page);
}

DEFINE_TRACE(ScrollingCoordinator) {
  visitor->trace(m_page);
  visitor->trace(m_horizontalScrollbars);
  visitor->trace(m_verticalScrollbars);
}

void ScrollingCoordinator::setShouldHandleScrollGestureOnMainThreadRegion(
    const Region& region) {
  if (!m_page->mainFrame()->isLocalFrame() ||
      !m_page->deprecatedLocalMainFrame()->view())
    return;
  if (WebLayer* scrollLayer = toWebLayer(
          m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) {
    Vector<IntRect> rects = region.rects();
    WebVector<WebRect> webRects(rects.size());
    for (size_t i = 0; i < rects.size(); ++i)
      webRects[i] = rects[i];
    scrollLayer->setNonFastScrollableRegion(webRects);
  }
}

void ScrollingCoordinator::notifyGeometryChanged() {
  m_scrollGestureRegionIsDirty = true;
  m_touchEventTargetRectsAreDirty = true;
  m_shouldScrollOnMainThreadDirty = true;
}

void ScrollingCoordinator::notifyOverflowUpdated() {
  m_scrollGestureRegionIsDirty = true;
}

void ScrollingCoordinator::scrollableAreasDidChange() {
  ASSERT(m_page);
  if (!m_page->mainFrame()->isLocalFrame() ||
      !m_page->deprecatedLocalMainFrame()->view())
    return;

  // Layout may update scrollable area bounding boxes. It also sets the same
  // dirty flag making this one redundant (See
  // |ScrollingCoordinator::notifyGeometryChanged|).
  // So if layout is expected, ignore this call allowing scrolling coordinator
  // to be notified post-layout to recompute gesture regions.
  if (m_page->deprecatedLocalMainFrame()->view()->needsLayout())
    return;

  m_scrollGestureRegionIsDirty = true;
}

void ScrollingCoordinator::updateAfterCompositingChangeIfNeeded() {
  if (!m_page->mainFrame()->isLocalFrame())
    return;

  if (!shouldUpdateAfterCompositingChange())
    return;

  TRACE_EVENT0("input",
               "ScrollingCoordinator::updateAfterCompositingChangeIfNeeded");

  if (m_scrollGestureRegionIsDirty) {
    // 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 shouldHandleScrollGestureOnMainThreadRegion =
        computeShouldHandleScrollGestureOnMainThreadRegion(
            m_page->deprecatedLocalMainFrame(), IntPoint());
    setShouldHandleScrollGestureOnMainThreadRegion(
        shouldHandleScrollGestureOnMainThreadRegion);
    m_scrollGestureRegionIsDirty = false;
  }

  if (m_touchEventTargetRectsAreDirty) {
    updateTouchEventTargetRectsIfNeeded();
    m_touchEventTargetRectsAreDirty = false;
  }

  FrameView* frameView = m_page->deprecatedLocalMainFrame()->view();
  bool frameIsScrollable = frameView && frameView->isScrollable();
  if (m_shouldScrollOnMainThreadDirty ||
      m_wasFrameScrollable != frameIsScrollable) {
    setShouldUpdateScrollLayerPositionOnMainThread(
        mainThreadScrollingReasons());
    m_shouldScrollOnMainThreadDirty = false;
  }
  m_wasFrameScrollable = frameIsScrollable;

  if (WebLayer* layoutViewportScrollLayer =
          frameView ? toWebLayer(frameView->layerForScrolling()) : nullptr) {
    layoutViewportScrollLayer->setBounds(frameView->contentsSize());

    // If there is a non-root fullscreen element, prevent the viewport from
    // scrolling.
    Document* mainFrameDocument =
        m_page->deprecatedLocalMainFrame()->document();
    Element* fullscreenElement =
        Fullscreen::fullscreenElementFrom(*mainFrameDocument);
    WebLayer* visualViewportScrollLayer =
        toWebLayer(m_page->frameHost().visualViewport().scrollLayer());

    if (visualViewportScrollLayer) {
      if (fullscreenElement &&
          fullscreenElement != mainFrameDocument->documentElement())
        visualViewportScrollLayer->setUserScrollable(false, false);
      else
        visualViewportScrollLayer->setUserScrollable(true, true);
    }

    layoutViewportScrollLayer->setUserScrollable(
        frameView->userInputScrollable(HorizontalScrollbar),
        frameView->userInputScrollable(VerticalScrollbar));
  }

  const FrameTree& tree = m_page->mainFrame()->tree();
  for (const Frame* child = tree.firstChild(); child;
       child = child->tree().nextSibling()) {
    if (!child->isLocalFrame())
      continue;
    FrameView* frameView = toLocalFrame(child)->view();
    if (!frameView || frameView->shouldThrottleRendering())
      continue;
    if (WebLayer* scrollLayer = toWebLayer(frameView->layerForScrolling()))
      scrollLayer->setBounds(frameView->contentsSize());
  }
}

void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(
    GraphicsLayer* layer,
    bool enable) {
  if (WebLayer* scrollableLayer = toWebLayer(layer))
    scrollableLayer->setIsContainerForFixedPositionLayers(enable);
}

static void clearPositionConstraintExceptForLayer(GraphicsLayer* layer,
                                                  GraphicsLayer* except) {
  if (layer && layer != except && toWebLayer(layer))
    toWebLayer(layer)->setPositionConstraint(WebLayerPositionConstraint());
}

static WebLayerPositionConstraint computePositionConstraint(
    const PaintLayer* layer) {
  ASSERT(layer->hasCompositedLayerMapping());
  do {
    if (layer->layoutObject()->style()->position() == FixedPosition) {
      const LayoutObject* fixedPositionObject = layer->layoutObject();
      bool fixedToRight = !fixedPositionObject->style()->right().isAuto();
      bool fixedToBottom = !fixedPositionObject->style()->bottom().isAuto();
      return WebLayerPositionConstraint::fixedPosition(fixedToRight,
                                                       fixedToBottom);
    }

    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 WebLayerPositionConstraint();
}

void ScrollingCoordinator::updateLayerPositionConstraint(PaintLayer* layer) {
  ASSERT(layer->hasCompositedLayerMapping());
  CompositedLayerMapping* compositedLayerMapping =
      layer->compositedLayerMapping();
  GraphicsLayer* mainLayer = compositedLayerMapping->childForSuperlayers();

  // Avoid unnecessary commits
  clearPositionConstraintExceptForLayer(
      compositedLayerMapping->squashingContainmentLayer(), mainLayer);
  clearPositionConstraintExceptForLayer(
      compositedLayerMapping->ancestorClippingLayer(), mainLayer);
  clearPositionConstraintExceptForLayer(
      compositedLayerMapping->mainGraphicsLayer(), mainLayer);

  if (WebLayer* scrollableLayer = toWebLayer(mainLayer))
    scrollableLayer->setPositionConstraint(computePositionConstraint(layer));
}

void ScrollingCoordinator::willDestroyScrollableArea(
    ScrollableArea* scrollableArea) {
  removeWebScrollbarLayer(scrollableArea, HorizontalScrollbar);
  removeWebScrollbarLayer(scrollableArea, VerticalScrollbar);
}

void ScrollingCoordinator::removeWebScrollbarLayer(
    ScrollableArea* scrollableArea,
    ScrollbarOrientation orientation) {
  ScrollbarMap& scrollbars = orientation == HorizontalScrollbar
                                 ? m_horizontalScrollbars
                                 : m_verticalScrollbars;
  if (std::unique_ptr<WebScrollbarLayer> scrollbarLayer =
          scrollbars.take(scrollableArea))
    GraphicsLayer::unregisterContentsLayer(scrollbarLayer->layer());
}

static std::unique_ptr<WebScrollbarLayer> createScrollbarLayer(
    Scrollbar& scrollbar,
    float deviceScaleFactor) {
  ScrollbarTheme& theme = scrollbar.theme();
  WebScrollbarThemePainter painter(theme, scrollbar, deviceScaleFactor);
  std::unique_ptr<WebScrollbarThemeGeometry> geometry(
      WebScrollbarThemeGeometryNative::create(theme));

  std::unique_ptr<WebScrollbarLayer> scrollbarLayer =
      wrapUnique(Platform::current()->compositorSupport()->createScrollbarLayer(
          WebScrollbarImpl::create(&scrollbar), painter, geometry.release()));
  GraphicsLayer::registerContentsLayer(scrollbarLayer->layer());
  return scrollbarLayer;
}

std::unique_ptr<WebScrollbarLayer>
ScrollingCoordinator::createSolidColorScrollbarLayer(
    ScrollbarOrientation orientation,
    int thumbThickness,
    int trackStart,
    bool isLeftSideVerticalScrollbar) {
  WebScrollbar::Orientation webOrientation =
      (orientation == HorizontalScrollbar) ? WebScrollbar::Horizontal
                                           : WebScrollbar::Vertical;
  std::unique_ptr<WebScrollbarLayer> scrollbarLayer = wrapUnique(
      Platform::current()->compositorSupport()->createSolidColorScrollbarLayer(
          webOrientation, thumbThickness, trackStart,
          isLeftSideVerticalScrollbar));
  GraphicsLayer::registerContentsLayer(scrollbarLayer->layer());
  return scrollbarLayer;
}

static void detachScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer) {
  ASSERT(scrollbarGraphicsLayer);

  scrollbarGraphicsLayer->setContentsToPlatformLayer(nullptr);
  scrollbarGraphicsLayer->setDrawsContent(true);
}

static void setupScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer,
                                WebScrollbarLayer* scrollbarLayer,
                                WebLayer* scrollLayer) {
  ASSERT(scrollbarGraphicsLayer);
  ASSERT(scrollbarLayer);

  if (!scrollLayer) {
    detachScrollbarLayer(scrollbarGraphicsLayer);
    return;
  }
  scrollbarLayer->setScrollLayer(scrollLayer);
  scrollbarGraphicsLayer->setContentsToPlatformLayer(scrollbarLayer->layer());
  scrollbarGraphicsLayer->setDrawsContent(false);
}

WebScrollbarLayer* ScrollingCoordinator::addWebScrollbarLayer(
    ScrollableArea* scrollableArea,
    ScrollbarOrientation orientation,
    std::unique_ptr<WebScrollbarLayer> scrollbarLayer) {
  ScrollbarMap& scrollbars = orientation == HorizontalScrollbar
                                 ? m_horizontalScrollbars
                                 : m_verticalScrollbars;
  return scrollbars.add(scrollableArea, std::move(scrollbarLayer))
      .storedValue->value.get();
}

WebScrollbarLayer* ScrollingCoordinator::getWebScrollbarLayer(
    ScrollableArea* scrollableArea,
    ScrollbarOrientation orientation) {
  ScrollbarMap& scrollbars = orientation == HorizontalScrollbar
                                 ? m_horizontalScrollbars
                                 : m_verticalScrollbars;
  return scrollbars.get(scrollableArea);
}

void ScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(
    ScrollableArea* scrollableArea,
    ScrollbarOrientation orientation) {
  if (!m_page || !m_page->mainFrame())
    return;

  bool isMainFrame = isForMainFrame(scrollableArea);
  GraphicsLayer* scrollbarGraphicsLayer =
      orientation == HorizontalScrollbar
          ? scrollableArea->layerForHorizontalScrollbar()
          : scrollableArea->layerForVerticalScrollbar();

  if (scrollbarGraphicsLayer) {
    Scrollbar& scrollbar = orientation == HorizontalScrollbar
                               ? *scrollableArea->horizontalScrollbar()
                               : *scrollableArea->verticalScrollbar();
    if (scrollbar.isCustomScrollbar()) {
      detachScrollbarLayer(scrollbarGraphicsLayer);
      scrollbarGraphicsLayer->platformLayer()->addMainThreadScrollingReasons(
          MainThreadScrollingReason::kCustomScrollbarScrolling);
      return;
    }

    // Invalidate custom scrollbar scrolling reason in case a custom
    // scrollbar becomes a non-custom one.
    scrollbarGraphicsLayer->platformLayer()->clearMainThreadScrollingReasons(
        MainThreadScrollingReason::kCustomScrollbarScrolling);
    WebScrollbarLayer* scrollbarLayer =
        getWebScrollbarLayer(scrollableArea, orientation);
    if (!scrollbarLayer) {
      Settings* settings = m_page->mainFrame()->settings();

      std::unique_ptr<WebScrollbarLayer> webScrollbarLayer;
      if (settings->useSolidColorScrollbars()) {
        ASSERT(RuntimeEnabledFeatures::overlayScrollbarsEnabled());
        webScrollbarLayer = createSolidColorScrollbarLayer(
            orientation, scrollbar.theme().thumbThickness(scrollbar),
            scrollbar.theme().trackPosition(scrollbar),
            scrollableArea->shouldPlaceVerticalScrollbarOnLeft());
      } else {
        webScrollbarLayer =
            createScrollbarLayer(scrollbar, m_page->deviceScaleFactor());
      }
      scrollbarLayer = addWebScrollbarLayer(scrollableArea, orientation,
                                            std::move(webScrollbarLayer));
    }

    WebLayer* scrollLayer = toWebLayer(scrollableArea->layerForScrolling());
    setupScrollbarLayer(scrollbarGraphicsLayer, scrollbarLayer, scrollLayer);

    // Root layer non-overlay scrollbars should be marked opaque to disable
    // blending.
    bool isOpaqueScrollbar = !scrollbar.isOverlayScrollbar();
    scrollbarGraphicsLayer->setContentsOpaque(isMainFrame && isOpaqueScrollbar);
  } else {
    removeWebScrollbarLayer(scrollableArea, orientation);
  }
}

bool ScrollingCoordinator::scrollableAreaScrollLayerDidChange(
    ScrollableArea* scrollableArea) {
  if (!m_page || !m_page->mainFrame())
    return false;

  GraphicsLayer* scrollLayer = scrollableArea->layerForScrolling();

  if (scrollLayer) {
    bool isForVisualViewport =
        scrollableArea == &m_page->frameHost().visualViewport();
    scrollLayer->setScrollableArea(scrollableArea, isForVisualViewport);
  }

  WebLayer* webLayer = toWebLayer(scrollableArea->layerForScrolling());
  WebLayer* containerLayer = toWebLayer(scrollableArea->layerForContainer());
  if (webLayer) {
    webLayer->setScrollClipLayer(containerLayer);
    DoublePoint scrollPosition(scrollableArea->scrollPositionDouble() +
                               toDoubleSize(scrollableArea->scrollOrigin()));
    webLayer->setScrollPositionDouble(scrollPosition);

    webLayer->setBounds(scrollableArea->contentsSize());
    bool canScrollX = scrollableArea->userInputScrollable(HorizontalScrollbar);
    bool canScrollY = scrollableArea->userInputScrollable(VerticalScrollbar);
    webLayer->setUserScrollable(canScrollX, canScrollY);
  }
  if (WebScrollbarLayer* scrollbarLayer =
          getWebScrollbarLayer(scrollableArea, HorizontalScrollbar)) {
    GraphicsLayer* horizontalScrollbarLayer =
        scrollableArea->layerForHorizontalScrollbar();
    if (horizontalScrollbarLayer)
      setupScrollbarLayer(horizontalScrollbarLayer, scrollbarLayer, webLayer);
  }
  if (WebScrollbarLayer* scrollbarLayer =
          getWebScrollbarLayer(scrollableArea, VerticalScrollbar)) {
    GraphicsLayer* verticalScrollbarLayer =
        scrollableArea->layerForVerticalScrollbar();

    if (verticalScrollbarLayer)
      setupScrollbarLayer(verticalScrollbarLayer, scrollbarLayer, webLayer);
  }

  // Update the viewport layer registration if the outer viewport may have
  // changed.
  if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
      isForRootLayer(scrollableArea))
    m_page->chromeClient().registerViewportLayers();

  scrollableArea->layerForScrollingDidChange(
      m_programmaticScrollAnimatorTimeline.get());

  return !!webLayer;
}

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

// 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* currentFrame,
                                   LayerFrameMap* map) {
  map->clear();
  const FrameTree& tree = currentFrame->tree();
  for (const Frame* child = tree.firstChild(); child;
       child = child->tree().nextSibling()) {
    if (!child->isLocalFrame())
      continue;
    const LayoutItem ownerLayoutItem = toLocalFrame(child)->ownerLayoutItem();
    if (ownerLayoutItem.isNull())
      continue;
    const PaintLayer* containingLayer = ownerLayoutItem.enclosingLayer();
    LayerFrameMap::iterator iter = map->find(containingLayer);
    if (iter == map->end())
      map->add(containingLayer, HeapVector<Member<const LocalFrame>>())
          .storedValue->value.append(toLocalFrame(child));
    else
      iter->value.append(toLocalFrame(child));
  }
}

static void projectRectsToGraphicsLayerSpaceRecursive(
    const PaintLayer* curLayer,
    const LayerHitTestRects& layerRects,
    GraphicsLayerHitTestRects& graphicsRects,
    LayoutGeometryMap& geometryMap,
    HashSet<const PaintLayer*>& layersWithRects,
    LayerFrameMap& layerChildFrameMap) {
  // If this layer is throttled, ignore it.
  if (curLayer->layoutObject()->frameView() &&
      curLayer->layoutObject()->frameView()->shouldThrottleRendering())
    return;
  // Project any rects for the current layer
  LayerHitTestRects::const_iterator layerIter = layerRects.find(curLayer);
  if (layerIter != layerRects.end()) {
    // Find the enclosing composited layer when it's in another document (for
    // non-composited iframes).
    const PaintLayer* compositedLayer =
        layerIter->key
            ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries();
    ASSERT(compositedLayer);

    // Find the appropriate GraphicsLayer for the composited Layer.
    GraphicsLayer* graphicsLayer =
        compositedLayer->graphicsLayerBackingForScrolling();

    GraphicsLayerHitTestRects::iterator glIter =
        graphicsRects.find(graphicsLayer);
    Vector<LayoutRect>* glRects;
    if (glIter == graphicsRects.end())
      glRects = &graphicsRects.add(graphicsLayer, Vector<LayoutRect>())
                     .storedValue->value;
    else
      glRects = &glIter->value;

    // Transform each rect to the co-ordinate space of the graphicsLayer.
    for (size_t i = 0; i < layerIter->value.size(); ++i) {
      LayoutRect rect = layerIter->value[i];
      if (compositedLayer != curLayer) {
        FloatQuad compositorQuad = geometryMap.mapToAncestor(
            FloatRect(rect), compositedLayer->layoutObject());
        rect = LayoutRect(compositorQuad.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 (compositedLayer->layoutObject()->hasOverflowClip())
          rect.move(compositedLayer->layoutBox()->scrolledContentOffset());
      }
      PaintLayer::mapRectInPaintInvalidationContainerToBacking(
          *compositedLayer->layoutObject(), rect);
      glRects->append(rect);
    }
  }

  // Walk child layers of interest
  for (const PaintLayer* childLayer = curLayer->firstChild(); childLayer;
       childLayer = childLayer->nextSibling()) {
    if (layersWithRects.contains(childLayer)) {
      geometryMap.pushMappingsToAncestor(childLayer, curLayer);
      projectRectsToGraphicsLayerSpaceRecursive(
          childLayer, layerRects, graphicsRects, geometryMap, layersWithRects,
          layerChildFrameMap);
      geometryMap.popMappingsToAncestor(curLayer);
    }
  }

  // If this layer has any frames of interest as a child of it, walk those (with
  // an updated frame map).
  LayerFrameMap::iterator mapIter = layerChildFrameMap.find(curLayer);
  if (mapIter != layerChildFrameMap.end()) {
    for (size_t i = 0; i < mapIter->value.size(); i++) {
      const LocalFrame* childFrame = mapIter->value[i];
      const PaintLayer* childLayer =
          childFrame->view()->layoutViewItem().layer();
      if (layersWithRects.contains(childLayer)) {
        LayerFrameMap newLayerChildFrameMap;
        makeLayerChildFrameMap(childFrame, &newLayerChildFrameMap);
        geometryMap.pushMappingsToAncestor(childLayer, curLayer);
        projectRectsToGraphicsLayerSpaceRecursive(
            childLayer, layerRects, graphicsRects, geometryMap, layersWithRects,
            newLayerChildFrameMap);
        geometryMap.popMappingsToAncestor(curLayer);
      }
    }
  }
}

static void projectRectsToGraphicsLayerSpace(
    LocalFrame* mainFrame,
    const LayerHitTestRects& layerRects,
    GraphicsLayerHitTestRects& graphicsRects) {
  TRACE_EVENT0("input",
               "ScrollingCoordinator::projectRectsToGraphicsLayerSpace");
  bool touchHandlerInChildFrame = 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*> layersWithRects;
  for (const auto& layerRect : layerRects) {
    const PaintLayer* layer = layerRect.key;
    do {
      if (!layersWithRects.add(layer).isNewEntry)
        break;

      if (layer->parent()) {
        layer = layer->parent();
      } else {
        LayoutItem parentDocLayoutItem =
            layer->layoutObject()->frame()->ownerLayoutItem();
        if (!parentDocLayoutItem.isNull()) {
          layer = parentDocLayoutItem.enclosingLayer();
          touchHandlerInChildFrame = true;
        }
      }
    } while (layer);
  }

  // Now walk the layer projecting rects while maintaining a LayoutGeometryMap
  MapCoordinatesFlags flags = UseTransforms;
  if (touchHandlerInChildFrame)
    flags |= TraverseDocumentBoundaries;
  PaintLayer* rootLayer = mainFrame->contentLayoutItem().layer();
  LayoutGeometryMap geometryMap(flags);
  geometryMap.pushMappingsToAncestor(rootLayer, 0);
  LayerFrameMap layerChildFrameMap;
  makeLayerChildFrameMap(mainFrame, &layerChildFrameMap);
  projectRectsToGraphicsLayerSpaceRecursive(
      rootLayer, layerRects, graphicsRects, geometryMap, layersWithRects,
      layerChildFrameMap);
}

void ScrollingCoordinator::updateTouchEventTargetRectsIfNeeded() {
  TRACE_EVENT0("input",
               "ScrollingCoordinator::updateTouchEventTargetRectsIfNeeded");

  if (!RuntimeEnabledFeatures::touchEnabled())
    return;

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

  LayerHitTestRects touchEventTargetRects;
  computeTouchEventTargetRects(touchEventTargetRects);
  setTouchEventTargetRects(touchEventTargetRects);
}

void ScrollingCoordinator::reset() {
  for (const auto& scrollbar : m_horizontalScrollbars)
    GraphicsLayer::unregisterContentsLayer(scrollbar.value->layer());
  for (const auto& scrollbar : m_verticalScrollbars)
    GraphicsLayer::unregisterContentsLayer(scrollbar.value->layer());

  m_horizontalScrollbars.clear();
  m_verticalScrollbars.clear();
  m_layersWithTouchRects.clear();
  m_wasFrameScrollable = false;

  m_lastMainThreadScrollingReasons = 0;
  setShouldUpdateScrollLayerPositionOnMainThread(
      m_lastMainThreadScrollingReasons);
}

// 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(
    LayerHitTestRects& layerRects) {
  TRACE_EVENT0("input", "ScrollingCoordinator::setTouchEventTargetRects");

  // Update the list of layers with touch hit rects.
  HashSet<const PaintLayer*> oldLayersWithTouchRects;
  m_layersWithTouchRects.swap(oldLayersWithTouchRects);
  for (const auto& layerRect : layerRects) {
    if (!layerRect.value.isEmpty()) {
      const PaintLayer* compositedLayer =
          layerRect.key
              ->enclosingLayerForPaintInvalidationCrossingFrameBoundaries();
      ASSERT(compositedLayer);
      m_layersWithTouchRects.add(compositedLayer);
    }
  }

  // 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.
  for (const PaintLayer* layer : oldLayersWithTouchRects) {
    if (!layerRects.contains(layer))
      layerRects.add(layer, Vector<LayoutRect>());
  }

  GraphicsLayerHitTestRects graphicsLayerRects;
  projectRectsToGraphicsLayerSpace(m_page->deprecatedLocalMainFrame(),
                                   layerRects, graphicsLayerRects);

  for (const auto& layerRect : graphicsLayerRects) {
    const GraphicsLayer* graphicsLayer = layerRect.key;
    WebVector<WebRect> webRects(layerRect.value.size());
    for (size_t i = 0; i < layerRect.value.size(); ++i)
      webRects[i] = enclosingIntRect(layerRect.value[i]);
    graphicsLayer->platformLayer()->setTouchEventHandlerRegion(webRects);
  }
}

void ScrollingCoordinator::touchEventTargetRectsDidChange() {
  if (!RuntimeEnabledFeatures::touchEnabled())
    return;

  ASSERT(m_page);
  if (!m_page->mainFrame()->isLocalFrame() ||
      !m_page->deprecatedLocalMainFrame()->view())
    return;

  // Wait until after layout to update.
  if (m_page->deprecatedLocalMainFrame()->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.
  LayoutViewItem layoutView =
      m_page->deprecatedLocalMainFrame()->contentLayoutItem();
  if (!layoutView.isNull() && layoutView.compositor() &&
      layoutView.compositor()->staleInCompositingMode())
    m_page->deprecatedLocalMainFrame()->view()->scheduleAnimation();

  m_touchEventTargetRectsAreDirty = true;
}

void ScrollingCoordinator::updateScrollParentForGraphicsLayer(
    GraphicsLayer* child,
    const PaintLayer* parent) {
  WebLayer* scrollParentWebLayer = nullptr;
  if (parent && parent->hasCompositedLayerMapping())
    scrollParentWebLayer =
        toWebLayer(parent->compositedLayerMapping()->scrollingContentsLayer());

  child->setScrollParent(scrollParentWebLayer);
}

void ScrollingCoordinator::updateClipParentForGraphicsLayer(
    GraphicsLayer* child,
    const PaintLayer* parent) {
  WebLayer* clipParentWebLayer = nullptr;
  if (parent && parent->hasCompositedLayerMapping())
    clipParentWebLayer =
        toWebLayer(parent->compositedLayerMapping()->parentForSublayers());

  child->setClipParent(clipParentWebLayer);
}

void ScrollingCoordinator::willDestroyLayer(PaintLayer* layer) {
  m_layersWithTouchRects.remove(layer);
}

void ScrollingCoordinator::setShouldUpdateScrollLayerPositionOnMainThread(
    MainThreadScrollingReasons mainThreadScrollingReasons) {
  if (!m_page->mainFrame()->isLocalFrame() ||
      !m_page->deprecatedLocalMainFrame()->view())
    return;

  GraphicsLayer* visualViewportLayer =
      m_page->frameHost().visualViewport().scrollLayer();
  WebLayer* visualViewportScrollLayer = toWebLayer(visualViewportLayer);
  GraphicsLayer* layer =
      m_page->deprecatedLocalMainFrame()->view()->layerForScrolling();
  if (WebLayer* scrollLayer = toWebLayer(layer)) {
    m_lastMainThreadScrollingReasons = mainThreadScrollingReasons;
    if (mainThreadScrollingReasons) {
      if (ScrollAnimatorBase* scrollAnimator =
              layer->getScrollableArea()->existingScrollAnimator()) {
        DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled() ||
               m_page->deprecatedLocalMainFrame()
                       ->document()
                       ->lifecycle()
                       .state() >= DocumentLifecycle::CompositingClean);
        scrollAnimator->takeOverCompositorAnimation();
      }
      scrollLayer->addMainThreadScrollingReasons(mainThreadScrollingReasons);
      if (visualViewportScrollLayer) {
        if (ScrollAnimatorBase* scrollAnimator =
                visualViewportLayer->getScrollableArea()
                    ->existingScrollAnimator()) {
          DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled() ||
                 m_page->deprecatedLocalMainFrame()
                         ->document()
                         ->lifecycle()
                         .state() >= DocumentLifecycle::CompositingClean);
          scrollAnimator->takeOverCompositorAnimation();
        }
        visualViewportScrollLayer->addMainThreadScrollingReasons(
            mainThreadScrollingReasons);
      }
    } else {
      // Clear all main thread scrolling reasons except the one that's set
      // if there is a running scroll animation.
      uint32_t mainThreadScrollingReasonsToClear = ~0u;
      mainThreadScrollingReasonsToClear &=
          ~MainThreadScrollingReason::kHandlingScrollFromMainThread;
      scrollLayer->clearMainThreadScrollingReasons(
          mainThreadScrollingReasonsToClear);
      if (visualViewportScrollLayer)
        visualViewportScrollLayer->clearMainThreadScrollingReasons(
            mainThreadScrollingReasonsToClear);
    }
  }
}

void ScrollingCoordinator::layerTreeViewInitialized(
    WebLayerTreeView& layerTreeView) {
  if (Platform::current()->isThreadedAnimationEnabled()) {
    m_programmaticScrollAnimatorTimeline =
        CompositorAnimationTimeline::create();
    layerTreeView.attachCompositorAnimationTimeline(
        m_programmaticScrollAnimatorTimeline->animationTimeline());
  }
}

void ScrollingCoordinator::willCloseLayerTreeView(
    WebLayerTreeView& layerTreeView) {
  if (m_programmaticScrollAnimatorTimeline) {
    layerTreeView.detachCompositorAnimationTimeline(
        m_programmaticScrollAnimatorTimeline->animationTimeline());
    m_programmaticScrollAnimatorTimeline.reset();
  }
}

void ScrollingCoordinator::willBeDestroyed() {
  ASSERT(m_page);

  m_page = nullptr;
  for (const auto& scrollbar : m_horizontalScrollbars)
    GraphicsLayer::unregisterContentsLayer(scrollbar.value->layer());
  for (const auto& scrollbar : m_verticalScrollbars)
    GraphicsLayer::unregisterContentsLayer(scrollbar.value->layer());
}

bool ScrollingCoordinator::coordinatesScrollingForFrameView(
    FrameView* frameView) const {
  ASSERT(isMainThread());

  // We currently only support composited mode.
  LayoutViewItem layoutView = frameView->frame().contentLayoutItem();
  if (layoutView.isNull())
    return false;
  return layoutView.usesCompositing();
}

Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion(
    const LocalFrame* frame,
    const IntPoint& frameLocation) const {
  Region shouldHandleScrollGestureOnMainThreadRegion;
  FrameView* frameView = frame->view();
  if (!frameView || frameView->shouldThrottleRendering())
    return shouldHandleScrollGestureOnMainThreadRegion;

  IntPoint offset = frameLocation;
  offset.moveBy(frameView->frameRect().location());

  if (const FrameView::ScrollableAreaSet* scrollableAreas =
          frameView->scrollableAreas()) {
    for (const ScrollableArea* scrollableArea : *scrollableAreas) {
      if (scrollableArea->isFrameView() &&
          toFrameView(scrollableArea)->shouldThrottleRendering())
        continue;
      // Composited scrollable areas can be scrolled off the main thread.
      if (scrollableArea->usesCompositedScrolling())
        continue;
      IntRect box = scrollableArea->scrollableAreaBoundingBox();
      box.moveBy(offset);
      shouldHandleScrollGestureOnMainThreadRegion.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 FrameView::ResizerAreaSet* resizerAreas =
          frameView->resizerAreas()) {
    for (const LayoutBox* box : *resizerAreas) {
      IntRect bounds = box->absoluteBoundingBoxRect();
      IntRect corner =
          box->layer()->getScrollableArea()->touchResizerCornerRect(bounds);
      corner.moveBy(offset);
      shouldHandleScrollGestureOnMainThreadRegion.unite(corner);
    }
  }

  if (const FrameView::ChildrenWidgetSet* children = frameView->children()) {
    for (const Member<Widget>& child : *children) {
      if (!(*child).isPluginView())
        continue;

      PluginView* pluginView = toPluginView(child.get());
      if (pluginView->wantsWheelEvents()) {
        IntRect box = pluginView->frameRect();
        box.moveBy(offset);
        shouldHandleScrollGestureOnMainThreadRegion.unite(box);
      }
    }
  }

  const FrameTree& tree = frame->tree();
  for (Frame* subFrame = tree.firstChild(); subFrame;
       subFrame = subFrame->tree().nextSibling()) {
    if (subFrame->isLocalFrame())
      shouldHandleScrollGestureOnMainThreadRegion.unite(
          computeShouldHandleScrollGestureOnMainThreadRegion(
              toLocalFrame(subFrame), offset));
  }

  return shouldHandleScrollGestureOnMainThreadRegion;
}

static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects,
                                                    const Document* document) {
  ASSERT(document);
  const EventTargetSet* targets =
      document->frameHost()->eventHandlerRegistry().eventHandlerTargets(
          EventHandlerRegistry::TouchStartOrMoveEventBlocking);
  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->layoutViewItem().compositor()->inOverlayFullscreenVideo()) {
    for (const auto& eventTarget : *targets) {
      EventTarget* target = eventTarget.key;
      Node* node = target->toNode();
      LocalDOMWindow* window = target->toLocalDOMWindow();
      // If the target is inside a throttled frame, skip it.
      if (window && window->frame()->view() &&
          window->frame()->view()->shouldThrottleRendering())
        continue;
      if (node && node->document().view() &&
          node->document().view()->shouldThrottleRendering())
        continue;
      if (window || node == document || node == document->documentElement() ||
          node == document->body()) {
        if (LayoutViewItem layoutView = document->layoutViewItem()) {
          layoutView.computeLayerHitTestRects(rects);
        }
        return;
      }
    }
  }

  for (const auto& eventTarget : *targets) {
    EventTarget* target = eventTarget.key;
    Node* node = target->toNode();
    if (!node || !node->isConnected())
      continue;

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

    // If the node belongs to a throttled frame, skip it.
    if (node->document().view() &&
        node->document().view()->shouldThrottleRendering())
      continue;

    if (node->isDocumentNode() && node != document) {
      accumulateDocumentTouchEventTargetRects(rects, toDocument(node));
    } else if (LayoutObject* layoutObject = node->layoutObject()) {
      // If the set also contains one of our ancestor nodes then processing
      // this node would be redundant.
      bool hasTouchEventTargetAncestor = false;
      for (Node& ancestor : NodeTraversal::ancestorsOf(*node)) {
        if (hasTouchEventTargetAncestor)
          break;
        if (targets->contains(&ancestor))
          hasTouchEventTargetAncestor = true;
      }
      if (!hasTouchEventTargetAncestor) {
        // Walk up the tree to the outermost non-composited scrollable layer.
        PaintLayer* enclosingNonCompositedScrollLayer = nullptr;
        for (PaintLayer* parent = layoutObject->enclosingLayer();
             parent && parent->compositingState() == NotComposited;
             parent = parent->parent()) {
          if (parent->scrollsOverflow())
            enclosingNonCompositedScrollLayer = 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 (enclosingNonCompositedScrollLayer)
          enclosingNonCompositedScrollLayer->computeSelfHitTestRects(rects);

        layoutObject->computeLayerHitTestRects(rects);
      }
    }
  }
}

void ScrollingCoordinator::computeTouchEventTargetRects(
    LayerHitTestRects& rects) {
  TRACE_EVENT0("input", "ScrollingCoordinator::computeTouchEventTargetRects");
  ASSERT(RuntimeEnabledFeatures::touchEnabled());

  Document* document = m_page->deprecatedLocalMainFrame()->document();
  if (!document || !document->view())
    return;

  accumulateDocumentTouchEventTargetRects(rects, document);
}

void ScrollingCoordinator::
    frameViewHasBackgroundAttachmentFixedObjectsDidChange(
        FrameView* frameView) {
  ASSERT(isMainThread());
  ASSERT(m_page);

  if (!coordinatesScrollingForFrameView(frameView))
    return;

  m_shouldScrollOnMainThreadDirty = true;
}

void ScrollingCoordinator::frameViewFixedObjectsDidChange(
    FrameView* frameView) {
  ASSERT(isMainThread());
  ASSERT(m_page);

  if (!coordinatesScrollingForFrameView(frameView))
    return;

  m_shouldScrollOnMainThreadDirty = true;
}

bool ScrollingCoordinator::isForRootLayer(
    ScrollableArea* scrollableArea) const {
  if (!m_page->mainFrame()->isLocalFrame())
    return false;

  // FIXME(305811): Refactor for OOPI.
  LayoutViewItem layoutViewItem =
      m_page->deprecatedLocalMainFrame()->view()->layoutViewItem();
  return layoutViewItem.isNull()
             ? false
             : scrollableArea == layoutViewItem.layer()->getScrollableArea();
}

bool ScrollingCoordinator::isForMainFrame(
    ScrollableArea* scrollableArea) const {
  if (!m_page->mainFrame()->isLocalFrame())
    return false;

  // FIXME(305811): Refactor for OOPI.
  return scrollableArea == m_page->deprecatedLocalMainFrame()->view();
}

void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView) {
  ASSERT(isMainThread());
  ASSERT(m_page);

  if (!coordinatesScrollingForFrameView(frameView))
    return;

  notifyGeometryChanged();
}

#if OS(MACOSX)
void ScrollingCoordinator::handleWheelEventPhase(
    PlatformWheelEventPhase phase) {
  ASSERT(isMainThread());

  if (!m_page)
    return;

  FrameView* frameView = m_page->deprecatedLocalMainFrame()->view();
  if (!frameView)
    return;

  frameView->scrollAnimator().handleWheelEventPhase(phase);
}
#endif

bool ScrollingCoordinator::hasVisibleSlowRepaintViewportConstrainedObjects(
    FrameView* frameView) const {
  const FrameView::ViewportConstrainedObjectSet* viewportConstrainedObjects =
      frameView->viewportConstrainedObjects();
  if (!viewportConstrainedObjects)
    return false;

  for (const LayoutObject* layoutObject : *viewportConstrainedObjects) {
    ASSERT(layoutObject->isBoxModelObject() && layoutObject->hasLayer());
    ASSERT(layoutObject->style()->position() == FixedPosition ||
           layoutObject->style()->position() == StickyPosition);
    PaintLayer* layer = toLayoutBoxModelObject(layoutObject)->layer();

    // Whether the Layer scrolls with the viewport is a tree-depenent
    // property and our viewportConstrainedObjects collection is maintained
    // with only LayoutObject-level information.
    if (!layer->scrollsWithViewport())
      continue;

    // If the whole subtree is invisible, there's no reason to scroll on
    // the main thread because we don't need to generate invalidations
    // for invisible content.
    if (layer->subtreeIsInvisible())
      continue;

    // We're only smart enough to scroll viewport-constrainted objects
    // in the compositor if they have their own backing or they paint
    // into a grouped back (which necessarily all have the same viewport
    // constraints).
    CompositingState compositingState = layer->compositingState();
    if (compositingState != PaintsIntoOwnBacking &&
        compositingState != PaintsIntoGroupedBacking)
      return true;
  }
  return false;
}

MainThreadScrollingReasons ScrollingCoordinator::mainThreadScrollingReasons()
    const {
  MainThreadScrollingReasons reasons =
      static_cast<MainThreadScrollingReasons>(0);

  if (!m_page->settings().threadedScrollingEnabled())
    reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;

  if (!m_page->mainFrame()->isLocalFrame())
    return reasons;

  // TODO(flackr) Currently we combine reasons for main thread scrolling from
  // all frames but we should only look at the targetted frame (and its
  // ancestors if the scroll bubbles up). http://crbug.com/568901
  for (Frame* frame = m_page->mainFrame(); frame;
       frame = frame->tree().traverseNext()) {
    if (!frame->isLocalFrame())
      continue;

    // TODO(alexmos,kenrb): For OOPIF, local roots that are different from
    // the main frame can't be used in the calculation, since they use
    // different compositors with unrelated state, which breaks some of the
    // calculations below.
    if (toLocalFrame(frame)->localFrameRoot() != m_page->mainFrame())
      continue;

    FrameView* frameView = toLocalFrame(frame)->view();
    if (!frameView || frameView->shouldThrottleRendering())
      continue;

    if (frameView->hasBackgroundAttachmentFixedObjects())
      reasons |=
          MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
    FrameView::ScrollingReasons scrollingReasons =
        frameView->getScrollingReasons();
    const bool mayBeScrolledByInput =
        (scrollingReasons == FrameView::Scrollable);
    const bool mayBeScrolledByScript =
        mayBeScrolledByInput ||
        (scrollingReasons == FrameView::NotScrollableExplicitlyDisabled);

    // TODO(awoloszyn) Currently crbug.com/304810 will let certain
    // overflow:hidden elements scroll on the compositor thread, so we should
    // not let this move there path as an optimization, when we have
    // slow-repaint elements.
    if (mayBeScrolledByScript &&
        hasVisibleSlowRepaintViewportConstrainedObjects(frameView)) {
      reasons |=
          MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects;
    }
  }

  return reasons;
}

String ScrollingCoordinator::mainThreadScrollingReasonsAsText() const {
  ASSERT(m_page->deprecatedLocalMainFrame()->document()->lifecycle().state() >=
         DocumentLifecycle::CompositingClean);
  if (WebLayer* scrollLayer = toWebLayer(
          m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) {
    String result(MainThreadScrollingReason::mainThreadScrollingReasonsAsText(
                      scrollLayer->mainThreadScrollingReasons())
                      .c_str());
    return result;
  }

  String result(MainThreadScrollingReason::mainThreadScrollingReasonsAsText(
                    m_lastMainThreadScrollingReasons)
                    .c_str());
  return result;
}

bool ScrollingCoordinator::frameViewIsDirty() const {
  FrameView* frameView = m_page->mainFrame()->isLocalFrame()
                             ? m_page->deprecatedLocalMainFrame()->view()
                             : nullptr;
  bool frameIsScrollable = frameView && frameView->isScrollable();
  if (frameIsScrollable != m_wasFrameScrollable)
    return true;

  if (WebLayer* scrollLayer =
          frameView ? toWebLayer(frameView->layerForScrolling()) : nullptr)
    return WebSize(frameView->contentsSize()) != scrollLayer->bounds();
  return false;
}

}  // namespace blink
