/*
   Copyright (C) 1997 Martin Jones (mjones@kde.org)
             (C) 1998 Waldo Bastian (bastian@kde.org)
             (C) 1998, 1999 Torben Weis (weis@kde.org)
             (C) 1999 Lars Knoll (knoll@kde.org)
             (C) 1999 Antti Koivisto (koivisto@kde.org)
   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#ifndef FrameView_h
#define FrameView_h

#include "core/CoreExport.h"
#include "core/dom/DocumentLifecycle.h"
#include "core/frame/FrameViewAutoSizeInfo.h"
#include "core/frame/LayoutSubtreeRootList.h"
#include "core/frame/RootFrameViewport.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/paint/PaintInvalidationCapableScrollableArea.h"
#include "core/paint/PaintPhase.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/Widget.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/paint/ClipPaintPropertyNode.h"
#include "platform/graphics/paint/TransformPaintPropertyNode.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/scroll/Scrollbar.h"
#include "public/platform/WebDisplayMode.h"
#include "public/platform/WebRect.h"
#include "wtf/Allocator.h"
#include "wtf/Forward.h"
#include "wtf/HashSet.h"
#include "wtf/ListHashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/WTFString.h"

namespace blink {

class AXObjectCache;
class CancellableTaskFactory;
class ComputedStyle;
class DocumentLifecycle;
class Cursor;
class Element;
class FloatSize;
class HTMLFrameOwnerElement;
class LayoutPart;
class LocalFrame;
class KURL;
class Node;
class LayoutBox;
class LayoutEmbeddedObject;
class LayoutObject;
class LayoutScrollbarPart;
class LayoutView;
class PaintInvalidationState;
class Page;
class ScrollingCoordinator;
class TracedValue;
struct AnnotatedRegionValue;
struct CompositedSelection;

typedef unsigned long long DOMTimeStamp;

class CORE_EXPORT FrameView final : public Widget, public PaintInvalidationCapableScrollableArea {
    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FrameView);

    friend class PaintControllerPaintTestBase;
    friend class Internals;
    friend class LayoutPart; // for invalidateTreeIfNeeded

public:
    static PassRefPtrWillBeRawPtr<FrameView> create(LocalFrame*);
    static PassRefPtrWillBeRawPtr<FrameView> create(LocalFrame*, const IntSize& initialSize);

    ~FrameView() override;

    void invalidateRect(const IntRect&) override;
    void setFrameRect(const IntRect&) override;

    LocalFrame& frame() const
    {
        ASSERT(m_frame);
        return *m_frame;
    }

    Page* page() const;

    LayoutView* layoutView() const;

    void setCanHaveScrollbars(bool);

    PassRefPtrWillBeRawPtr<Scrollbar> createScrollbar(ScrollbarOrientation);

    void setContentsSize(const IntSize&);

    void layout();
    bool didFirstLayout() const;
    void scheduleRelayout();
    void scheduleRelayoutOfSubtree(LayoutObject*);
    bool layoutPending() const;
    bool isInPerformLayout() const;

    void clearLayoutSubtreeRoot(const LayoutObject&);
    int layoutCount() const { return m_layoutCount; }

    void countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial);

    bool needsLayout() const;
    void setNeedsLayout();

    void setNeedsUpdateWidgetGeometries() { m_needsUpdateWidgetGeometries = true; }

    // Methods for getting/setting the size Blink should use to layout the contents.
    // NOTE: Scrollbar exclusion is based on the FrameView's scrollbars. To exclude
    // scrollbars on the root PaintLayer, use LayoutView::layoutSize.
    IntSize layoutSize(IncludeScrollbarsInRect = ExcludeScrollbars) const;
    void setLayoutSize(const IntSize&);

    // If this is set to false, the layout size will need to be explicitly set by the owner.
    // E.g. WebViewImpl sets its mainFrame's layout size manually
    void setLayoutSizeFixedToFrameSize(bool isFixed) { m_layoutSizeFixedToFrameSize = isFixed; }
    bool layoutSizeFixedToFrameSize() { return m_layoutSizeFixedToFrameSize; }

    bool needsFullPaintInvalidation() const { return m_doFullPaintInvalidation; }

    void updateAcceleratedCompositingSettings();

    void recalcOverflowAfterStyleChange();

    bool isEnclosedInCompositingLayer() const;

    void dispose() override;
    void detachScrollbars();
    void recalculateCustomScrollbarStyle();
    void invalidateAllCustomScrollbarsOnActiveChanged();
    virtual void recalculateScrollbarOverlayStyle();

    void clear();

    bool isTransparent() const;
    void setTransparent(bool isTransparent);

    // True if the FrameView is not transparent, and the base background color is opaque.
    bool hasOpaqueBackground() const;

    Color baseBackgroundColor() const;
    void setBaseBackgroundColor(const Color&);
    void updateBackgroundRecursively(const Color&, bool);

    void adjustViewSize();

    // Scale used to convert incoming input events.
    float inputEventsScaleFactor() const;

    // Offset used to convert incoming input events while emulating device metics.
    IntSize inputEventsOffsetForEmulation() const;
    void setInputEventsTransformForEmulation(const IntSize&, float);

    void setScrollPosition(const DoublePoint&, ScrollType, ScrollBehavior = ScrollBehaviorInstant) override;

    void didUpdateElasticOverscroll();

    void viewportSizeChanged(bool widthChanged, bool heightChanged);

    AtomicString mediaType() const;
    void setMediaType(const AtomicString&);
    void adjustMediaTypeForPrinting(bool printing);

    WebDisplayMode displayMode() { return m_displayMode; }
    void setDisplayMode(WebDisplayMode);

    // Fixed-position objects.
    typedef HashSet<LayoutObject*> ViewportConstrainedObjectSet;
    void addViewportConstrainedObject(LayoutObject*);
    void removeViewportConstrainedObject(LayoutObject*);
    const ViewportConstrainedObjectSet* viewportConstrainedObjects() const { return m_viewportConstrainedObjects.get(); }
    bool hasViewportConstrainedObjects() const { return m_viewportConstrainedObjects && m_viewportConstrainedObjects->size() > 0; }

    // Objects with background-attachment:fixed.
    void addBackgroundAttachmentFixedObject(LayoutObject*);
    void removeBackgroundAttachmentFixedObject(LayoutObject*);
    bool hasBackgroundAttachmentFixedObjects() const { return m_backgroundAttachmentFixedObjects.size(); }
    void invalidateBackgroundAttachmentFixedObjects();

    void handleLoadCompleted();

    void updateDocumentAnnotatedRegions() const;

    void restoreScrollbar();

    void postLayoutTimerFired(Timer<FrameView>*);

    bool safeToPropagateScrollToParent() const { return m_safeToPropagateScrollToParent; }
    void setSafeToPropagateScrollToParent(bool isSafe) { m_safeToPropagateScrollToParent = isSafe; }

    void addPart(LayoutPart*);
    void removePart(LayoutPart*);

    void updateWidgetGeometries();

    void addPartToUpdate(LayoutEmbeddedObject&);

    void setIsPainting(bool val) const { m_isPainting = val; }
    bool isPainting() const;

    Color documentBackgroundColor() const;

    // Run all needed lifecycle stages. After calling this method, all frames will be in the lifecycle state PaintInvalidationClean.
    // If lifecycle throttling is allowed (see DocumentLifecycle::PreventThrottlingScope), some frames may skip the lifecycle update
    // (e.g., based on visibility) and will not end up being PaintInvalidationClean.
    void updateAllLifecyclePhases();

    // Computes the style, layout and compositing lifecycle stages if needed. After calling this method, all frames will be in a lifecycle
    // state >= CompositingClean, and scrolling has been updated (unless throttling is allowed).
    void updateLifecycleToCompositingCleanPlusScrolling();

    // Computes only the style and layout lifecycle stages.
    // After calling this method, all frames will be in a lifecycle state >= LayoutClean (unless throttling is allowed).
    void updateLifecycleToLayoutClean();

    void scheduleVisualUpdateForPaintInvalidationIfNeeded();

    bool invalidateViewportConstrainedObjects();

    void incrementVisuallyNonEmptyCharacterCount(unsigned);
    void incrementVisuallyNonEmptyPixelCount(const IntSize&);
    bool isVisuallyNonEmpty() const { return m_isVisuallyNonEmpty; }
    void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; }
    void enableAutoSizeMode(const IntSize& minSize, const IntSize& maxSize);
    void disableAutoSizeMode();

    void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor);

    enum UrlFragmentBehavior {
        UrlFragmentScroll,
        UrlFragmentDontScroll
    };
    bool processUrlFragment(const KURL&, UrlFragmentBehavior = UrlFragmentScroll);
    void clearScrollAnchor();

    // Methods to convert points and rects between the coordinate space of the layoutObject, and this view.
    IntRect convertFromLayoutObject(const LayoutObject&, const IntRect&) const;
    IntRect convertToLayoutObject(const LayoutObject&, const IntRect&) const;
    IntPoint convertFromLayoutObject(const LayoutObject&, const IntPoint&) const;
    IntPoint convertToLayoutObject(const LayoutObject&, const IntPoint&) const;

    bool isFrameViewScrollCorner(LayoutScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; }

    enum ScrollingReasons {
        Scrollable,
        NotScrollableNoOverflow,
        NotScrollableNotVisible,
        NotScrollableExplicitlyDisabled
    };

    ScrollingReasons scrollingReasons();
    bool isScrollable() override;
    bool isProgrammaticallyScrollable() override;

    enum ScrollbarModesCalculationStrategy { RulesFromWebContentOnly, AnyRule };
    void calculateScrollbarModes(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy = AnyRule);

    IntPoint lastKnownMousePosition() const override;
    bool shouldSetCursor() const;

    void setCursor(const Cursor&);

    bool scrollbarsCanBeActive() const override;
    void scrollbarVisibilityChanged() override;

    // FIXME: Remove this method once plugin loading is decoupled from layout.
    void flushAnyPendingPostLayoutTasks();

    bool shouldSuspendScrollAnimations() const override;
    void scrollbarStyleChanged() override;

    LayoutBox* embeddedContentBox() const;

    static void setInitialTracksPaintInvalidationsForTesting(bool);

    void setTracksPaintInvalidations(bool);
    bool isTrackingPaintInvalidations() const { return m_isTrackingPaintInvalidations; }
    void resetTrackedPaintInvalidations();

    using ScrollableAreaSet = WillBeHeapHashSet<RawPtrWillBeMember<ScrollableArea>>;
    void addScrollableArea(ScrollableArea*);
    void removeScrollableArea(ScrollableArea*);
    const ScrollableAreaSet* scrollableAreas() const { return m_scrollableAreas.get(); }

    void addAnimatingScrollableArea(ScrollableArea*);
    void removeAnimatingScrollableArea(ScrollableArea*);
    const ScrollableAreaSet* animatingScrollableAreas() const { return m_animatingScrollableAreas.get(); }

    // With CSS style "resize:" enabled, a little resizer handle will appear at the bottom
    // right of the object. We keep track of these resizer areas for checking if touches
    // (implemented using Scroll gesture) are targeting the resizer.
    typedef HashSet<LayoutBox*> ResizerAreaSet;
    void addResizerArea(LayoutBox&);
    void removeResizerArea(LayoutBox&);
    const ResizerAreaSet* resizerAreas() const { return m_resizerAreas.get(); }

    bool shouldUseIntegerScrollOffset() const override;

    bool isActive() const override;

    // Override scrollbar notifications to update the AXObject cache.
    void didAddScrollbar(Scrollbar&, ScrollbarOrientation) override;

    // FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter
    // passed around the FrameView layout methods can be true while this returns
    // false.
    bool isSubtreeLayout() const { return !m_layoutSubtreeRootList.isEmpty(); }

    // Sets the tickmarks for the FrameView, overriding the default behavior
    // which is to display the tickmarks corresponding to find results.
    // If |m_tickmarks| is empty, the default behavior is restored.
    void setTickmarks(const Vector<IntRect>& tickmarks)
    {
        m_tickmarks = tickmarks;
        invalidatePaintForTickmarks();
    }

    void invalidatePaintForTickmarks();

    // Since the compositor can resize the viewport due to top controls and
    // commit scroll offsets before a WebView::resize occurs, we need to adjust
    // our scroll extents to prevent clamping the scroll offsets.
    void setTopControlsViewportAdjustment(float);
    IntSize topControlsSize() const { return IntSize(0, roundf(m_topControlsViewportAdjustment)); }

    IntPoint maximumScrollPosition() const override;

    // ScrollableArea interface
    void scrollControlWasSetNeedsPaintInvalidation() override { }
    void getTickmarks(Vector<IntRect>&) const override;
    void scrollTo(const DoublePoint&);
    IntRect scrollableAreaBoundingBox() const override;
    bool scrollAnimatorEnabled() const override;
    bool usesCompositedScrolling() const override;
    GraphicsLayer* layerForScrolling() const override;
    GraphicsLayer* layerForHorizontalScrollbar() const override;
    GraphicsLayer* layerForVerticalScrollbar() const override;
    GraphicsLayer* layerForScrollCorner() const override;
    int scrollSize(ScrollbarOrientation) const override;
    bool isScrollCornerVisible() const override;
    bool userInputScrollable(ScrollbarOrientation) const override;
    bool shouldPlaceVerticalScrollbarOnLeft() const override;
    Widget* widget() override;

    LayoutRect scrollIntoView(
        const LayoutRect& rectInContent,
        const ScrollAlignment& alignX,
        const ScrollAlignment& alignY,
        ScrollType = ProgrammaticScroll) override;

    // The window that hosts the FrameView. The FrameView will communicate scrolls and repaints to the
    // host window in the window's coordinate space.
    HostWindow* hostWindow() const;

    // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll.
    IntRect windowClipRect(IncludeScrollbarsInRect = ExcludeScrollbars) const;

    typedef WillBeHeapHashSet<RefPtrWillBeMember<Widget>> ChildrenWidgetSet;

    // Functions for child manipulation and inspection.
    void setParent(Widget*) override;
    void removeChild(Widget*);
    void addChild(PassRefPtrWillBeRawPtr<Widget>);
    const ChildrenWidgetSet* children() const { return &m_children; }

    // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions
    // can be used to obtain those scrollbars.
    Scrollbar* horizontalScrollbar() const override { return m_horizontalScrollbar.get(); }
    Scrollbar* verticalScrollbar() const override { return m_verticalScrollbar.get(); }
    LayoutScrollbarPart* scrollCorner() const override { return m_scrollCorner; }

    void positionScrollbarLayers();

    // Functions for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of
    // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar.
    // Auto means show a scrollbar only when one is needed.
    // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native
    // widget may choose not to honor the requested modes.
    void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false);
    void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); }
    void setVerticalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(horizontalScrollbarMode(), mode, horizontalScrollbarLock(), lock); }
    ScrollbarMode horizontalScrollbarMode() const { return m_horizontalScrollbarMode; }
    ScrollbarMode verticalScrollbarMode() const { return m_verticalScrollbarMode; }

    void setHorizontalScrollbarLock(bool lock = true) { m_horizontalScrollbarLock = lock; }
    bool horizontalScrollbarLock() const { return m_horizontalScrollbarLock; }
    void setVerticalScrollbarLock(bool lock = true) { m_verticalScrollbarLock = lock; }
    bool verticalScrollbarLock() const { return m_verticalScrollbarLock; }

    void setScrollingModesLock(bool lock = true) { m_horizontalScrollbarLock = m_verticalScrollbarLock = lock; }

    bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; }

    // The visible content rect has a location that is the scrolled offset of
    // the document. The width and height are the layout viewport width and
    // height. By default the scrollbars themselves are excluded from this
    // rectangle, but an optional boolean argument allows them to be included.
    IntRect visibleContentRect(IncludeScrollbarsInRect = ExcludeScrollbars) const override;
    IntSize visibleContentSize(IncludeScrollbarsInRect = ExcludeScrollbars) const;

    // Functions for getting/setting the size of the document contained inside the FrameView (as an IntSize or as individual width and height
    // values).
    IntSize contentsSize() const override; // Always at least as big as the visibleWidth()/visibleHeight().
    int contentsWidth() const { return contentsSize().width(); }
    int contentsHeight() const { return contentsSize().height(); }

    // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
    // Be careful in using the Double version scrollPositionDouble() and scrollOffsetDouble(). They are meant to be
    // used to communicate the fractional scroll position/offset with chromium compositor which can do sub-pixel positioning.
    // Do not call these if the scroll position/offset is used in Blink for positioning. Use the Int version instead.
    IntPoint scrollPosition() const override { return visibleContentRect().location(); }
    DoublePoint scrollPositionDouble() const override { return m_scrollPosition; }
    IntSize scrollOffset() const { return toIntSize(visibleContentRect().location()); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes.
    DoubleSize scrollOffsetDouble() const { return DoubleSize(m_scrollPosition.x(), m_scrollPosition.y()); }
    DoubleSize pendingScrollDelta() const { return m_pendingScrollDelta; }
    IntPoint minimumScrollPosition() const override; // The minimum position we can be scrolled to.
    int scrollX() const { return scrollPosition().x(); }
    int scrollY() const { return scrollPosition().y(); }

    // Scroll the actual contents of the view (either blitting or invalidating as needed).
    void scrollContents(const IntSize& scrollDelta);

    // This gives us a means of blocking updating our scrollbars until the first layout has occurred.
    void setScrollbarsSuppressed(bool suppressed) { m_scrollbarsSuppressed = suppressed; }
    bool scrollbarsSuppressed() const { return m_scrollbarsSuppressed; }

    // Methods for converting between this frame and other coordinate spaces.
    // For definitions and an explanation of the varous spaces, please see:
    // http://www.chromium.org/developers/design-documents/blink-coordinate-spaces
    IntPoint rootFrameToContents(const IntPoint&) const;
    FloatPoint rootFrameToContents(const FloatPoint&) const;
    IntRect rootFrameToContents(const IntRect&) const;
    IntPoint contentsToRootFrame(const IntPoint&) const;
    IntRect contentsToRootFrame(const IntRect&) const;

    IntRect viewportToContents(const IntRect&) const;
    IntRect contentsToViewport(const IntRect&) const;
    IntPoint contentsToViewport(const IntPoint&) const;
    IntPoint viewportToContents(const IntPoint&) const;

    // FIXME: Some external callers expect to get back a rect that's positioned
    // in viewport space, but sized in CSS pixels. This is an artifact of the
    // old pinch-zoom path. These callers should be converted to expect a rect
    // fully in viewport space. crbug.com/459591.
    IntRect soonToBeRemovedContentsToUnscaledViewport(const IntRect&) const;
    IntPoint soonToBeRemovedUnscaledViewportToContents(const IntPoint&) const;

    // Methods for converting between Frame and Content (i.e. Document) coordinates.
    // Frame coordinates are relative to the top left corner of the frame and so
    // they are affected by scroll offset. Content coordinates are relative to the
    // document's top left corner and thus are not affected by scroll offset.
    IntPoint contentsToFrame(const IntPoint&) const;
    IntRect contentsToFrame(const IntRect&) const;
    IntPoint frameToContents(const IntPoint&) const;
    FloatPoint frameToContents(const FloatPoint&) const;
    IntRect frameToContents(const IntRect&) const;

    // Functions for converting to screen coordinates.
    IntRect contentsToScreen(const IntRect&) const;

    // These functions are used to enable scrollbars to avoid window resizer controls that overlap the scroll view.
    // This happens only on Mac OS X 10.6.
    IntRect windowResizerRect() const;
    bool containsScrollbarsAvoidingResizer() const;
    void adjustScrollbarsAvoidingResizerCount(int overlapDelta);
    void windowResizerRectChanged();

    // For platforms that need to hit test scrollbars from within the engine's event handlers (like Win32).
    Scrollbar* scrollbarAtFramePoint(const IntPoint&);

    IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const override
    {
        IntPoint newPoint = point;
        if (!isFrameViewScrollbar(child))
            newPoint = contentsToFrame(point);
        newPoint.moveBy(child->location());
        return newPoint;
    }

    IntPoint convertSelfToChild(const Widget* child, const IntPoint& point) const override
    {
        IntPoint newPoint = point;
        if (!isFrameViewScrollbar(child))
            newPoint = frameToContents(point);
        newPoint.moveBy(-child->location());
        return newPoint;
    }

    // Widget override. Handles painting of the contents of the view as well as the scrollbars.
    void paint(GraphicsContext&, const CullRect&) const override;
    void paint(GraphicsContext&, const GlobalPaintFlags, const CullRect&) const;
    void paintContents(GraphicsContext&, const GlobalPaintFlags, const IntRect& damageRect) const;

    // Widget overrides to ensure that our children's visibility status is kept up to date when we get shown and hidden.
    void show() override;
    void hide() override;
    void setParentVisible(bool) override;

    bool isPointInScrollbarCorner(const IntPoint&);
    bool scrollbarCornerPresent() const;
    IntRect scrollCornerRect() const override;

    IntRect convertFromScrollbarToContainingWidget(const Scrollbar&, const IntRect&) const override;
    IntRect convertFromContainingWidgetToScrollbar(const Scrollbar&, const IntRect&) const override;
    IntPoint convertFromScrollbarToContainingWidget(const Scrollbar&, const IntPoint&) const override;
    IntPoint convertFromContainingWidgetToScrollbar(const Scrollbar&, const IntPoint&) const override;

    bool isFrameView() const override { return true; }

    DECLARE_VIRTUAL_TRACE();
    void notifyPageThatContentAreaWillPaint() const;
    FrameView* parentFrameView() const;

    // Returns the scrollable area for the frame. For the root frame, this will
    // be the RootFrameViewport, which adds pinch-zoom semantics to scrolling.
    // For non-root frames, this will be the the ScrollableArea used by the
    // FrameView, depending on whether root-layer-scrolls is enabled.
    ScrollableArea* scrollableArea();

    // Used to get at the underlying layoutViewport in the rare instances where
    // we actually want to scroll *just* the layout viewport (e.g. when sending
    // deltas from CC). For typical scrolling cases, use scrollableArea().
    ScrollableArea* layoutViewportScrollableArea();

    int viewportWidth() const;

    LayoutAnalyzer* layoutAnalyzer() { return m_analyzer.get(); }

    // Returns true if the default scrolling direction is vertical. i.e. writing mode
    // is horiziontal. In a vertical document, a spacebar scrolls down.
    bool isVerticalDocument() const;

    // Returns true if the document's writing mode is right-to-left or bottom-to-top.
    bool isFlippedDocument() const;

    void setFrameTimingRequestsDirty(bool isDirty) { m_frameTimingRequestsDirty = isDirty; }
    bool frameTimingRequestsDirty() { return m_frameTimingRequestsDirty; }

    // Returns true if this frame should not render or schedule visual updates.
    bool shouldThrottleRendering() const;

    // Returns true if this frame could potentially skip rendering and avoid
    // scheduling visual updates.
    bool canThrottleRendering() const;
    bool isHiddenForThrottling() const { return m_hiddenForThrottling; }

    // Paint properties for SPv2 Only.
    void setPreTranslation(PassRefPtr<TransformPaintPropertyNode> preTranslation) { m_preTranslation = preTranslation; }
    const TransformPaintPropertyNode* preTranslation() const { return m_preTranslation.get(); }

    void setScrollTranslation(PassRefPtr<TransformPaintPropertyNode> scrollTranslation) { m_scrollTranslation = scrollTranslation; }
    const TransformPaintPropertyNode* scrollTranslation() const { return m_scrollTranslation.get(); }

    void setContentClip(PassRefPtr<ClipPaintPropertyNode> contentClip) { m_contentClip = contentClip; }
    const ClipPaintPropertyNode* contentClip() const { return m_contentClip.get(); }

    // TODO(ojan): Merge this with IntersectionObserver once it lands.
    IntRect computeVisibleArea();

protected:
    // Scroll the content via the compositor.
    bool scrollContentsFastPath(const IntSize& scrollDelta);

    // Scroll the content by invalidating everything.
    void scrollContentsSlowPath(const IntRect& updateRect);

    // These functions are used to create/destroy scrollbars.
    void setHasHorizontalScrollbar(bool);
    void setHasVerticalScrollbar(bool);

    ScrollBehavior scrollBehaviorStyle() const override;

    void scrollContentsIfNeeded();

    void setScrollOrigin(const IntPoint&, bool updatePositionAtAll, bool updatePositionSynchronously);

    enum ComputeScrollbarExistenceOption {
        FirstPass,
        Incremental
    };
    void computeScrollbarExistence(bool& newHasHorizontalScrollbar, bool& newHasVerticalScrollbar, const IntSize& docSize, ComputeScrollbarExistenceOption = FirstPass) const;
    void updateScrollbarGeometry();
    IntRect adjustScrollbarRectForResizer(const IntRect&, Scrollbar&);

    // Called to update the scrollbars to accurately reflect the state of the view.
    void updateScrollbars(const DoubleSize& desiredOffset);

    class InUpdateScrollbarsScope {
        STACK_ALLOCATED();
    public:
        explicit InUpdateScrollbarsScope(FrameView* view)
            : m_scope(view->m_inUpdateScrollbars, true)
        { }
    private:
        TemporaryChange<bool> m_scope;
    };

    // Only for LayoutPart to traverse into sub frames during paint invalidation.
    void invalidateTreeIfNeeded(PaintInvalidationState&);

private:
    explicit FrameView(LocalFrame*);

    void setScrollOffset(const IntPoint&, ScrollType) override;
    void setScrollOffset(const DoublePoint&, ScrollType) override;

    enum LifeCycleUpdateOption {
        OnlyUpToLayoutClean,
        OnlyUpToCompositingCleanPlusScrolling,
        AllPhases,
    };

    void updateLifecyclePhasesInternal(LifeCycleUpdateOption);
    void invalidateTreeIfNeededRecursive();
    void scrollContentsIfNeededRecursive();
    void updateStyleAndLayoutIfNeededRecursive();
    void updatePaintProperties();
    void synchronizedPaint();
    void synchronizedPaintRecursively(GraphicsLayer*);

    void pushPaintArtifactToCompositor();

    void reset();
    void init();

    void clearLayoutSubtreeRootsAndMarkContainingBlocks();

    // Called when our frame rect changes (or the rect/scroll position of an ancestor changes).
    void frameRectsChanged() override;

    bool contentsInCompositedLayer() const;

    void calculateScrollbarModesFromOverflowStyle(const ComputedStyle*, ScrollbarMode& hMode, ScrollbarMode& vMode);

    void updateCounters();
    void forceLayoutParentViewIfNeeded();
    void performPreLayoutTasks();
    void performLayout(bool inSubtreeLayout);
    void scheduleOrPerformPostLayoutTasks();
    void performPostLayoutTasks();

    DocumentLifecycle& lifecycle() const;

    void contentsResized() override;
    void scrollbarExistenceDidChange();

    // Override Widget methods to do point conversion via layoutObjects, in order to
    // take transforms into account.
    IntRect convertToContainingWidget(const IntRect&) const override;
    IntRect convertFromContainingWidget(const IntRect&) const override;
    IntPoint convertToContainingWidget(const IntPoint&) const override;
    IntPoint convertFromContainingWidget(const IntPoint&) const override;

    void updateWidgetGeometriesIfNeeded();

    bool wasViewportResized();
    void sendResizeEventIfNeeded();

    void updateScrollableAreaSet();

    void scheduleUpdateWidgetsIfNecessary();
    void updateWidgetsTimerFired(Timer<FrameView>*);
    bool updateWidgets();

    bool processUrlFragmentHelper(const String&, UrlFragmentBehavior);
    void maintainScrollPositionAtAnchor(Node*);
    void scrollToAnchor();
    void scrollPositionChanged();
    void didScrollTimerFired(Timer<FrameView>*);

    void updateLayersAndCompositingAfterScrollIfNeeded();

    static bool computeCompositedSelection(LocalFrame&, CompositedSelection&);
    void updateCompositedSelectionIfNeeded();

    // Returns true if the FrameView's own scrollbars overlay its content when visible.
    bool hasOverlayScrollbars() const;

    // Returns true if the frame should use custom scrollbars. If true, one of
    // either |customScrollbarElement| or |customScrollbarFrame| will be set to
    // the element or frame which owns the scrollbar with the other set to null.
    bool shouldUseCustomScrollbars(Element*& customScrollbarElement, LocalFrame*& customScrollbarFrame) const;

    // Returns true if a scrollbar needs to go from native -> custom or vice versa.
    bool needsScrollbarReconstruction() const;

    bool shouldIgnoreOverflowHidden() const;

    void updateScrollCorner();

    AXObjectCache* axObjectCache() const;
    void removeFromAXObjectCache();

    void setLayoutSizeInternal(const IntSize&);

    bool adjustScrollbarExistence(ComputeScrollbarExistenceOption = FirstPass);
    void adjustScrollbarOpacity();
    void setScrollOffsetFromUpdateScrollbars(const DoubleSize&);
    bool visualViewportSuppliesScrollbars() const;

    IntRect rectToCopyOnScroll() const;

    bool isFrameViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; }

    ScrollingCoordinator* scrollingCoordinator();

    void prepareLayoutAnalyzer();
    PassRefPtr<TracedValue> analyzerCounters();

    // LayoutObject for the viewport-defining element (see Document::viewportDefiningElement).
    LayoutObject* viewportLayoutObject();

    void collectAnnotatedRegions(LayoutObject&, Vector<AnnotatedRegionValue>&) const;

    typedef WTF::HashMap <const GraphicsLayer*, Vector<std::pair<int64_t, WebRect>>> GraphicsLayerFrameTimingRequests;
    void updateFrameTimingRequestsIfNeeded();
    void collectFrameTimingRequests(GraphicsLayerFrameTimingRequests&);
    void collectFrameTimingRequestsRecursive(GraphicsLayerFrameTimingRequests&);

    template <typename Function> void forAllNonThrottledFrameViews(Function);

    void setNeedsUpdateViewportIntersection();
    void updateViewportIntersectionsForSubtree(LifeCycleUpdateOption);
    void updateViewportIntersectionIfNeeded();
    void notifyRenderThrottlingObservers();

    // PaintInvalidationCapableScrollableArea
    LayoutBox& boxForScrollControlPaintInvalidation() const override;
    LayoutScrollbarPart* resizer() const override { return nullptr; }

    LayoutSize m_size;

    typedef HashSet<RefPtr<LayoutEmbeddedObject>> EmbeddedObjectSet;
    EmbeddedObjectSet m_partUpdateSet;

    // FIXME: These are just "children" of the FrameView and should be RefPtrWillBeMember<Widget> instead.
    HashSet<RefPtr<LayoutPart>> m_parts;

    // The RefPtr cycle between LocalFrame and FrameView is broken
    // when a LocalFrame is detached by LocalFrame::detach().
    // It clears the LocalFrame's m_view reference via setView(nullptr).
    //
    // For Oilpan, Member reference cycles pose no problem, but
    // LocalFrame's FrameView is also cleared by that setView(), so as to
    // keep the observable lifespan of LocalFrame::view() identical.
    RefPtrWillBeMember<LocalFrame> m_frame;

    WebDisplayMode m_displayMode;

    bool m_doFullPaintInvalidation;

    bool m_canHaveScrollbars;

    bool m_hasPendingLayout;
    LayoutSubtreeRootList m_layoutSubtreeRootList;

    bool m_layoutSchedulingEnabled;
    bool m_inSynchronousPostLayout;
    int m_layoutCount;
    unsigned m_nestedLayoutCount;
    Timer<FrameView> m_postLayoutTasksTimer;
    Timer<FrameView> m_updateWidgetsTimer;
    OwnPtr<CancellableTaskFactory> m_renderThrottlingObserverNotificationFactory;

    bool m_firstLayout;
    bool m_isTransparent;
    Color m_baseBackgroundColor;
    IntSize m_lastViewportSize;
    float m_lastZoomFactor;

    AtomicString m_mediaType;
    AtomicString m_mediaTypeWhenNotPrinting;

    bool m_safeToPropagateScrollToParent;

    bool m_isTrackingPaintInvalidations; // Used for testing.

    // TODO(wangxianzhu): Use document cycle state for spv2 and synchronzied painting.
    mutable bool m_isPainting;

    unsigned m_visuallyNonEmptyCharacterCount;
    unsigned m_visuallyNonEmptyPixelCount;
    bool m_isVisuallyNonEmpty;

    RefPtrWillBeMember<Node> m_scrollAnchor;

    // layoutObject to hold our custom scroll corner.
    LayoutScrollbarPart* m_scrollCorner;

    OwnPtrWillBeMember<ScrollableAreaSet> m_scrollableAreas;
    OwnPtrWillBeMember<ScrollableAreaSet> m_animatingScrollableAreas;
    OwnPtr<ResizerAreaSet> m_resizerAreas;
    OwnPtr<ViewportConstrainedObjectSet> m_viewportConstrainedObjects;
    ViewportConstrainedObjectSet m_backgroundAttachmentFixedObjects;
    OwnPtrWillBeMember<FrameViewAutoSizeInfo> m_autoSizeInfo;

    IntSize m_inputEventsOffsetForEmulation;
    float m_inputEventsScaleFactorForEmulation;

    IntSize m_layoutSize;
    bool m_layoutSizeFixedToFrameSize;

    Timer<FrameView> m_didScrollTimer;

    Vector<IntRect> m_tickmarks;

    float m_topControlsViewportAdjustment;

    bool m_needsUpdateWidgetGeometries;
    bool m_needsUpdateViewportIntersection;
    bool m_needsUpdateViewportIntersectionInSubtree;

#if ENABLE(ASSERT)
    // Verified when finalizing.
    bool m_hasBeenDisposed;
#endif

    RefPtrWillBeMember<Scrollbar> m_horizontalScrollbar;
    RefPtrWillBeMember<Scrollbar> m_verticalScrollbar;
    ScrollbarMode m_horizontalScrollbarMode;
    ScrollbarMode m_verticalScrollbarMode;

    bool m_horizontalScrollbarLock;
    bool m_verticalScrollbarLock;

    ChildrenWidgetSet m_children;

    DoubleSize m_pendingScrollDelta;
    DoublePoint m_scrollPosition;
    IntSize m_contentsSize;

    int m_scrollbarsAvoidingResizer;
    bool m_scrollbarsSuppressed;

    bool m_inUpdateScrollbars;

    OwnPtr<LayoutAnalyzer> m_analyzer;

    // Mark if something has changed in the mapping from Frame to GraphicsLayer
    // and the Frame Timing regions should be recalculated.
    bool m_frameTimingRequestsDirty;

    // Exists only on root frame.
    // TODO(bokan): crbug.com/484188. We should specialize FrameView for the
    // main frame.
    OwnPtrWillBeMember<ScrollableArea> m_viewportScrollableArea;

    // This frame's bounds in the root frame's content coordinates, clipped
    // recursively through every ancestor view.
    IntRect m_viewportIntersection;
    bool m_viewportIntersectionValid;

    // The following members control rendering pipeline throttling for this
    // frame. They are only updated in response to intersection observer
    // notifications, i.e., not in the middle of the lifecycle.
    bool m_hiddenForThrottling;
    bool m_crossOriginForThrottling;

    // Paint properties for SPv2 Only.
    // The hierarchy of transform subtree created by a FrameView.
    // [ preTranslation ]               The offset from Widget::frameRect. Establishes viewport.
    //     +---[ scrollTranslation ]    Frame scrolling.
    //                                  TODO(trchen): This is going away in favor of Settings::rootLayerScrolls.
    RefPtr<TransformPaintPropertyNode> m_preTranslation;
    RefPtr<TransformPaintPropertyNode> m_scrollTranslation;
    // The content clip clips the document (= LayoutView) but not the scrollbars.
    // TODO(trchen): Going away in favor of Settings::rootLayerScrolls too.
    RefPtr<ClipPaintPropertyNode> m_contentClip;

    bool m_isUpdatingAllLifecyclePhases;
};

inline void FrameView::incrementVisuallyNonEmptyCharacterCount(unsigned count)
{
    if (m_isVisuallyNonEmpty)
        return;
    m_visuallyNonEmptyCharacterCount += count;
    // Use a threshold value to prevent very small amounts of visible content from triggering didMeaningfulLayout.
    // The first few hundred characters rarely contain the interesting content of the page.
    static const unsigned visualCharacterThreshold = 200;
    if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
        setIsVisuallyNonEmpty();
}

inline void FrameView::incrementVisuallyNonEmptyPixelCount(const IntSize& size)
{
    if (m_isVisuallyNonEmpty)
        return;
    m_visuallyNonEmptyPixelCount += size.width() * size.height();
    // Use a threshold value to prevent very small amounts of visible content from triggering didMeaningfulLayout.
    static const unsigned visualPixelThreshold = 32 * 32;
    if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
        setIsVisuallyNonEmpty();
}

DEFINE_TYPE_CASTS(FrameView, Widget, widget, widget->isFrameView(), widget.isFrameView());

} // namespace blink

#endif // FrameView_h
