1/*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 *                     1999 Lars Knoll <knoll@kde.org>
4 *                     1999 Antti Koivisto <koivisto@kde.org>
5 *                     2000 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7 *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2009 Google Inc. All rights reserved.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB.  If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 */
26
27#include "config.h"
28#include "core/frame/FrameView.h"
29
30#include "core/HTMLNames.h"
31#include "core/MediaTypeNames.h"
32#include "core/accessibility/AXObjectCache.h"
33#include "core/css/FontFaceSet.h"
34#include "core/css/resolver/StyleResolver.h"
35#include "core/dom/DocumentMarkerController.h"
36#include "core/editing/FrameSelection.h"
37#include "core/editing/RenderedPosition.h"
38#include "core/events/OverflowEvent.h"
39#include "core/fetch/ResourceFetcher.h"
40#include "core/fetch/ResourceLoadPriorityOptimizer.h"
41#include "core/frame/FrameHost.h"
42#include "core/frame/LocalFrame.h"
43#include "core/frame/Settings.h"
44#include "core/html/HTMLFrameElement.h"
45#include "core/html/HTMLPlugInElement.h"
46#include "core/html/parser/TextResourceDecoder.h"
47#include "core/inspector/InspectorInstrumentation.h"
48#include "core/inspector/InspectorTraceEvents.h"
49#include "core/loader/FrameLoader.h"
50#include "core/loader/FrameLoaderClient.h"
51#include "core/page/Chrome.h"
52#include "core/page/ChromeClient.h"
53#include "core/page/EventHandler.h"
54#include "core/page/FocusController.h"
55#include "core/page/FrameTree.h"
56#include "core/page/Page.h"
57#include "core/page/scrolling/ScrollingCoordinator.h"
58#include "core/rendering/RenderCounter.h"
59#include "core/rendering/RenderEmbeddedObject.h"
60#include "core/rendering/RenderLayer.h"
61#include "core/rendering/RenderListBox.h"
62#include "core/rendering/RenderPart.h"
63#include "core/rendering/RenderScrollbar.h"
64#include "core/rendering/RenderScrollbarPart.h"
65#include "core/rendering/RenderTheme.h"
66#include "core/rendering/RenderView.h"
67#include "core/rendering/RenderWidget.h"
68#include "core/rendering/TextAutosizer.h"
69#include "core/rendering/compositing/CompositedLayerMapping.h"
70#include "core/rendering/compositing/CompositedSelectionBound.h"
71#include "core/rendering/compositing/RenderLayerCompositor.h"
72#include "core/rendering/style/RenderStyle.h"
73#include "core/rendering/svg/RenderSVGRoot.h"
74#include "core/svg/SVGDocumentExtensions.h"
75#include "core/svg/SVGSVGElement.h"
76#include "platform/RuntimeEnabledFeatures.h"
77#include "platform/ScriptForbiddenScope.h"
78#include "platform/TraceEvent.h"
79#include "platform/fonts/FontCache.h"
80#include "platform/geometry/FloatRect.h"
81#include "platform/graphics/GraphicsContext.h"
82#include "platform/graphics/GraphicsLayerDebugInfo.h"
83#include "platform/scroll/ScrollAnimator.h"
84#include "platform/scroll/ScrollbarTheme.h"
85#include "platform/text/TextStream.h"
86#include "wtf/CurrentTime.h"
87#include "wtf/TemporaryChange.h"
88
89namespace blink {
90
91using namespace HTMLNames;
92
93double FrameView::s_currentFrameTimeStamp = 0.0;
94bool FrameView::s_inPaintContents = false;
95
96// The maximum number of updateWidgets iterations that should be done before returning.
97static const unsigned maxUpdateWidgetsIterations = 2;
98static const double resourcePriorityUpdateDelayAfterScroll = 0.250;
99
100FrameView::FrameView(LocalFrame* frame)
101    : m_frame(frame)
102    , m_canHaveScrollbars(true)
103    , m_slowRepaintObjectCount(0)
104    , m_hasPendingLayout(false)
105    , m_layoutSubtreeRoot(0)
106    , m_inSynchronousPostLayout(false)
107    , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
108    , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired)
109    , m_isTransparent(false)
110    , m_baseBackgroundColor(Color::white)
111    , m_mediaType(MediaTypeNames::screen)
112    , m_overflowStatusDirty(true)
113    , m_viewportRenderer(0)
114    , m_wasScrolledByUser(false)
115    , m_inProgrammaticScroll(false)
116    , m_safeToPropagateScrollToParent(true)
117    , m_isTrackingPaintInvalidations(false)
118    , m_scrollCorner(nullptr)
119    , m_visibleContentScaleFactor(1)
120    , m_inputEventsScaleFactorForEmulation(1)
121    , m_layoutSizeFixedToFrameSize(true)
122    , m_didScrollTimer(this, &FrameView::didScrollTimerFired)
123    , m_needsUpdateWidgetPositions(false)
124    , m_topControlsViewportAdjustment(0)
125{
126    ASSERT(m_frame);
127    init();
128
129    if (!m_frame->isMainFrame())
130        return;
131
132    ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed);
133    ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed);
134}
135
136PassRefPtr<FrameView> FrameView::create(LocalFrame* frame)
137{
138    RefPtr<FrameView> view = adoptRef(new FrameView(frame));
139    view->show();
140    return view.release();
141}
142
143PassRefPtr<FrameView> FrameView::create(LocalFrame* frame, const IntSize& initialSize)
144{
145    RefPtr<FrameView> view = adoptRef(new FrameView(frame));
146    view->Widget::setFrameRect(IntRect(view->location(), initialSize));
147    view->setLayoutSizeInternal(initialSize);
148
149    view->show();
150    return view.release();
151}
152
153FrameView::~FrameView()
154{
155    if (m_postLayoutTasksTimer.isActive())
156        m_postLayoutTasksTimer.stop();
157
158    if (m_didScrollTimer.isActive())
159        m_didScrollTimer.stop();
160
161    removeFromAXObjectCache();
162
163    // Custom scrollbars should already be destroyed at this point
164    ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
165    ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
166
167    setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
168    setHasVerticalScrollbar(false);
169
170    ASSERT(!m_scrollCorner);
171
172    ASSERT(m_frame);
173    ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
174    // FIXME: Do we need to do something here for OOPI?
175    HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
176    if (ownerElement && ownerElement->ownedWidget() == this)
177        ownerElement->setWidget(nullptr);
178}
179
180void FrameView::reset()
181{
182    m_hasPendingLayout = false;
183    m_layoutSubtreeRoot = 0;
184    m_doFullPaintInvalidation = false;
185    m_layoutSchedulingEnabled = true;
186    m_inPerformLayout = false;
187    m_canInvalidatePaintDuringPerformLayout = false;
188    m_inSynchronousPostLayout = false;
189    m_layoutCount = 0;
190    m_nestedLayoutCount = 0;
191    m_postLayoutTasksTimer.stop();
192    m_updateWidgetsTimer.stop();
193    m_firstLayout = true;
194    m_firstLayoutCallbackPending = false;
195    m_wasScrolledByUser = false;
196    m_safeToPropagateScrollToParent = true;
197    m_lastViewportSize = IntSize();
198    m_lastZoomFactor = 1.0f;
199    m_isTrackingPaintInvalidations = false;
200    m_trackedPaintInvalidationRects.clear();
201    m_lastPaintTime = 0;
202    m_paintBehavior = PaintBehaviorNormal;
203    m_isPainting = false;
204    m_visuallyNonEmptyCharacterCount = 0;
205    m_visuallyNonEmptyPixelCount = 0;
206    m_isVisuallyNonEmpty = false;
207    m_firstVisuallyNonEmptyLayoutCallbackPending = true;
208    m_maintainScrollPositionAnchor = nullptr;
209    m_viewportConstrainedObjects.clear();
210}
211
212void FrameView::removeFromAXObjectCache()
213{
214    if (AXObjectCache* cache = axObjectCache()) {
215        cache->remove(this);
216        cache->childrenChanged(m_frame->pagePopupOwner());
217    }
218}
219
220void FrameView::init()
221{
222    reset();
223
224    m_size = LayoutSize();
225
226    // Propagate the marginwidth/height and scrolling modes to the view.
227    // FIXME: Do we need to do this for OOPI?
228    Element* ownerElement = m_frame->deprecatedLocalOwner();
229    if (ownerElement && (isHTMLFrameElement(*ownerElement) || isHTMLIFrameElement(*ownerElement))) {
230        HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement);
231        if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
232            setCanHaveScrollbars(false);
233    }
234}
235
236void FrameView::prepareForDetach()
237{
238    RELEASE_ASSERT(!isInPerformLayout());
239
240    if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
241        scrollAnimator->cancelAnimations();
242    cancelProgrammaticScrollAnimation();
243
244    detachCustomScrollbars();
245    // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
246    // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
247    removeFromAXObjectCache();
248
249    if (m_frame->page()) {
250        if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
251            scrollingCoordinator->willDestroyScrollableArea(this);
252    }
253}
254
255void FrameView::detachCustomScrollbars()
256{
257    Scrollbar* horizontalBar = horizontalScrollbar();
258    if (horizontalBar && horizontalBar->isCustomScrollbar())
259        setHasHorizontalScrollbar(false);
260
261    Scrollbar* verticalBar = verticalScrollbar();
262    if (verticalBar && verticalBar->isCustomScrollbar())
263        setHasVerticalScrollbar(false);
264
265    if (m_scrollCorner) {
266        m_scrollCorner->destroy();
267        m_scrollCorner = nullptr;
268    }
269}
270
271void FrameView::recalculateScrollbarOverlayStyle()
272{
273    ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
274    ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault;
275
276    Color backgroundColor = documentBackgroundColor();
277    // Reduce the background color from RGB to a lightness value
278    // and determine which scrollbar style to use based on a lightness
279    // heuristic.
280    double hue, saturation, lightness;
281    backgroundColor.getHSL(hue, saturation, lightness);
282    if (lightness <= .5)
283        overlayStyle = ScrollbarOverlayStyleLight;
284
285    if (oldOverlayStyle != overlayStyle)
286        setScrollbarOverlayStyle(overlayStyle);
287}
288
289void FrameView::clear()
290{
291    reset();
292    setScrollbarsSuppressed(true);
293}
294
295bool FrameView::didFirstLayout() const
296{
297    return !m_firstLayout;
298}
299
300void FrameView::invalidateRect(const IntRect& rect)
301{
302    // For querying RenderLayer::compositingState() when invalidating scrollbars.
303    // FIXME: do all scrollbar invalidations after layout of all frames is complete. It's currently not recursively true.
304    DisableCompositingQueryAsserts disabler;
305    if (!parent()) {
306        if (HostWindow* window = hostWindow())
307            window->invalidateContentsAndRootView(rect);
308        return;
309    }
310
311    RenderPart* renderer = m_frame->ownerRenderer();
312    if (!renderer)
313        return;
314
315    IntRect paintInvalidationRect = rect;
316    paintInvalidationRect.move(renderer->borderLeft() + renderer->paddingLeft(),
317                     renderer->borderTop() + renderer->paddingTop());
318    renderer->invalidatePaintRectangle(paintInvalidationRect);
319}
320
321void FrameView::setFrameRect(const IntRect& newRect)
322{
323    IntRect oldRect = frameRect();
324    if (newRect == oldRect)
325        return;
326
327    // Autosized font sizes depend on the width of the viewing area.
328    bool autosizerNeedsUpdating = false;
329    if (newRect.width() != oldRect.width() && m_frame->isMainFrame() && m_frame->settings()->textAutosizingEnabled())
330        autosizerNeedsUpdating = true;
331
332    ScrollView::setFrameRect(newRect);
333
334    updateScrollableAreaSet();
335
336    if (autosizerNeedsUpdating) {
337        // This needs to be after the call to ScrollView::setFrameRect, because it reads the new width.
338        if (TextAutosizer* textAutosizer = m_frame->document()->textAutosizer())
339            textAutosizer->updatePageInfoInAllFrames();
340    }
341
342    if (RenderView* renderView = this->renderView()) {
343        if (renderView->usesCompositing())
344            renderView->compositor()->frameViewDidChangeSize();
345    }
346
347    viewportConstrainedVisibleContentSizeChanged(newRect.width() != oldRect.width(), newRect.height() != oldRect.height());
348
349    if (oldRect.size() != newRect.size()
350        && m_frame->isMainFrame()
351        && m_frame->settings()->pinchVirtualViewportEnabled())
352        page()->frameHost().pinchViewport().mainFrameDidChangeSize();
353}
354
355Page* FrameView::page() const
356{
357    return frame().page();
358}
359
360RenderView* FrameView::renderView() const
361{
362    return frame().contentRenderer();
363}
364
365void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
366{
367    m_canHaveScrollbars = canHaveScrollbars;
368    ScrollView::setCanHaveScrollbars(canHaveScrollbars);
369}
370
371bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, LocalFrame*& customScrollbarFrame)
372{
373    customScrollbarElement = 0;
374    customScrollbarFrame = 0;
375
376    if (Settings* settings = m_frame->settings()) {
377        if (!settings->allowCustomScrollbarInMainFrame() && m_frame->isMainFrame())
378            return false;
379    }
380
381    // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
382    Document* doc = m_frame->document();
383
384    // Try the <body> element first as a scrollbar source.
385    Element* body = doc ? doc->body() : 0;
386    if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) {
387        customScrollbarElement = body;
388        return true;
389    }
390
391    // If the <body> didn't have a custom style, then the root element might.
392    Element* docElement = doc ? doc->documentElement() : 0;
393    if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) {
394        customScrollbarElement = docElement;
395        return true;
396    }
397
398    // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also.
399    RenderPart* frameRenderer = m_frame->ownerRenderer();
400    if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) {
401        customScrollbarFrame = m_frame.get();
402        return true;
403    }
404
405    return false;
406}
407
408PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
409{
410    Element* customScrollbarElement = 0;
411    LocalFrame* customScrollbarFrame = 0;
412    if (shouldUseCustomScrollbars(customScrollbarElement, customScrollbarFrame))
413        return RenderScrollbar::createCustomScrollbar(this, orientation, customScrollbarElement, customScrollbarFrame);
414
415    // Nobody set a custom style, so we just use a native scrollbar.
416    return ScrollView::createScrollbar(orientation);
417}
418
419void FrameView::setContentsSize(const IntSize& size)
420{
421    if (size == contentsSize())
422        return;
423
424    ScrollView::setContentsSize(size);
425    ScrollView::contentsResized();
426
427    Page* page = frame().page();
428    if (!page)
429        return;
430
431    updateScrollableAreaSet();
432
433    page->chrome().contentsSizeChanged(m_frame.get(), size);
434}
435
436IntPoint FrameView::clampOffsetAtScale(const IntPoint& offset, float scale) const
437{
438    IntPoint maxScrollExtent(contentsSize().width() - scrollOrigin().x(), contentsSize().height() - scrollOrigin().y());
439    FloatSize scaledSize = unscaledVisibleContentSize();
440    if (scale)
441        scaledSize.scale(1 / scale);
442
443    IntPoint clampedOffset = offset;
444    clampedOffset = clampedOffset.shrunkTo(maxScrollExtent - expandedIntSize(scaledSize));
445    clampedOffset = clampedOffset.expandedTo(-scrollOrigin());
446
447    return clampedOffset;
448}
449
450void FrameView::adjustViewSize()
451{
452    RenderView* renderView = this->renderView();
453    if (!renderView)
454        return;
455
456    ASSERT(m_frame->view() == this);
457
458    const IntRect rect = renderView->documentRect();
459    const IntSize& size = rect.size();
460    ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !m_frame->document()->printing(), size == contentsSize());
461
462    setContentsSize(size);
463}
464
465void FrameView::applyOverflowToViewportAndSetRenderer(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode)
466{
467    // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
468    // overflow:hidden and overflow:scroll on <body> as applying to the document's
469    // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
470    // use the root element.
471
472    EOverflow overflowX = o->style()->overflowX();
473    EOverflow overflowY = o->style()->overflowY();
474
475    if (o->isSVGRoot()) {
476        // Don't allow overflow to affect <img> and css backgrounds
477        if (toRenderSVGRoot(o)->isEmbeddedThroughSVGImage())
478            return;
479
480        // FIXME: evaluate if we can allow overflow for these cases too.
481        // Overflow is always hidden when stand-alone SVG documents are embedded.
482        if (toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument()) {
483            overflowX = OHIDDEN;
484            overflowY = OHIDDEN;
485        }
486    }
487
488    bool ignoreOverflowHidden = false;
489    if (m_frame->settings()->ignoreMainFrameOverflowHiddenQuirk() && m_frame->isMainFrame())
490        ignoreOverflowHidden = true;
491
492    switch (overflowX) {
493        case OHIDDEN:
494            if (!ignoreOverflowHidden)
495                hMode = ScrollbarAlwaysOff;
496            break;
497        case OSCROLL:
498            hMode = ScrollbarAlwaysOn;
499            break;
500        case OAUTO:
501            hMode = ScrollbarAuto;
502            break;
503        default:
504            // Don't set it at all.
505            ;
506    }
507
508     switch (overflowY) {
509        case OHIDDEN:
510            if (!ignoreOverflowHidden)
511                vMode = ScrollbarAlwaysOff;
512            break;
513        case OSCROLL:
514            vMode = ScrollbarAlwaysOn;
515            break;
516        case OAUTO:
517            vMode = ScrollbarAuto;
518            break;
519        default:
520            // Don't set it at all.
521            ;
522    }
523
524    m_viewportRenderer = o;
525}
526
527void FrameView::calculateScrollbarModesForLayoutAndSetViewportRenderer(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
528{
529    m_viewportRenderer = 0;
530
531    // FIXME: How do we handle this for OOPI?
532    const HTMLFrameOwnerElement* owner = m_frame->deprecatedLocalOwner();
533    if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
534        hMode = ScrollbarAlwaysOff;
535        vMode = ScrollbarAlwaysOff;
536        return;
537    }
538
539    if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
540        hMode = ScrollbarAuto;
541        vMode = ScrollbarAuto;
542    } else {
543        hMode = ScrollbarAlwaysOff;
544        vMode = ScrollbarAlwaysOff;
545    }
546
547    if (!isSubtreeLayout()) {
548        Document* document = m_frame->document();
549        Node* body = document->body();
550        if (isHTMLFrameSetElement(body) && body->renderer()) {
551            vMode = ScrollbarAlwaysOff;
552            hMode = ScrollbarAlwaysOff;
553        } else if (Element* viewportElement = document->viewportDefiningElement()) {
554            if (RenderObject* viewportRenderer = viewportElement->renderer()) {
555                if (viewportRenderer->style())
556                    applyOverflowToViewportAndSetRenderer(viewportRenderer, hMode, vMode);
557            }
558        }
559    }
560}
561
562void FrameView::updateAcceleratedCompositingSettings()
563{
564    if (RenderView* renderView = this->renderView())
565        renderView->compositor()->updateAcceleratedCompositingSettings();
566}
567
568void FrameView::recalcOverflowAfterStyleChange()
569{
570    RenderView* renderView = this->renderView();
571    RELEASE_ASSERT(renderView);
572    if (!renderView->needsOverflowRecalcAfterStyleChange())
573        return;
574
575    renderView->recalcOverflowAfterStyleChange();
576
577    IntRect documentRect = renderView->documentRect();
578    if (scrollOrigin() == -documentRect.location() && contentsSize() == documentRect.size())
579        return;
580
581    if (needsLayout())
582        return;
583
584    InUpdateScrollbarsScope inUpdateScrollbarsScope(this);
585
586    bool shouldHaveHorizontalScrollbar = false;
587    bool shouldHaveVerticalScrollbar = false;
588    computeScrollbarExistence(shouldHaveHorizontalScrollbar, shouldHaveVerticalScrollbar, documentRect.size());
589
590    bool hasHorizontalScrollbar = horizontalScrollbar();
591    bool hasVerticalScrollbar = verticalScrollbar();
592    if (hasHorizontalScrollbar != shouldHaveHorizontalScrollbar
593        || hasVerticalScrollbar != shouldHaveVerticalScrollbar) {
594        setNeedsLayout();
595        return;
596    }
597
598    adjustViewSize();
599    updateScrollbarGeometry();
600}
601
602bool FrameView::usesCompositedScrolling() const
603{
604    RenderView* renderView = this->renderView();
605    if (!renderView)
606        return false;
607    if (m_frame->settings() && m_frame->settings()->preferCompositingToLCDTextEnabled())
608        return renderView->compositor()->inCompositingMode();
609    return false;
610}
611
612GraphicsLayer* FrameView::layerForScrolling() const
613{
614    RenderView* renderView = this->renderView();
615    if (!renderView)
616        return 0;
617    return renderView->compositor()->scrollLayer();
618}
619
620GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
621{
622    RenderView* renderView = this->renderView();
623    if (!renderView)
624        return 0;
625    return renderView->compositor()->layerForHorizontalScrollbar();
626}
627
628GraphicsLayer* FrameView::layerForVerticalScrollbar() const
629{
630    RenderView* renderView = this->renderView();
631    if (!renderView)
632        return 0;
633    return renderView->compositor()->layerForVerticalScrollbar();
634}
635
636GraphicsLayer* FrameView::layerForScrollCorner() const
637{
638    RenderView* renderView = this->renderView();
639    if (!renderView)
640        return 0;
641    return renderView->compositor()->layerForScrollCorner();
642}
643
644bool FrameView::isEnclosedInCompositingLayer() const
645{
646    // FIXME: It's a bug that compositing state isn't always up to date when this is called. crbug.com/366314
647    DisableCompositingQueryAsserts disabler;
648
649    RenderObject* frameOwnerRenderer = m_frame->ownerRenderer();
650    return frameOwnerRenderer && frameOwnerRenderer->enclosingLayer()->enclosingLayerForPaintInvalidationCrossingFrameBoundaries();
651}
652
653RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
654{
655    return onlyDuringLayout && layoutPending() ? 0 : m_layoutSubtreeRoot;
656}
657
658inline void FrameView::forceLayoutParentViewIfNeeded()
659{
660    RenderPart* ownerRenderer = m_frame->ownerRenderer();
661    if (!ownerRenderer || !ownerRenderer->frame())
662        return;
663
664    RenderBox* contentBox = embeddedContentBox();
665    if (!contentBox)
666        return;
667
668    RenderSVGRoot* svgRoot = toRenderSVGRoot(contentBox);
669    if (svgRoot->everHadLayout() && !svgRoot->needsLayout())
670        return;
671
672    // If the embedded SVG document appears the first time, the ownerRenderer has already finished
673    // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
674    // embeddedContentBox() returns 0, as long as the embedded document isn't loaded yet. Before
675    // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
676    // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
677    // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
678    // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
679    RefPtr<FrameView> frameView = ownerRenderer->frame()->view();
680
681    // Mark the owner renderer as needing layout.
682    ownerRenderer->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
683
684    // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
685    ASSERT(frameView);
686    frameView->layout();
687}
688
689void FrameView::performPreLayoutTasks()
690{
691    TRACE_EVENT0("blink", "FrameView::performPreLayoutTasks");
692    lifecycle().advanceTo(DocumentLifecycle::InPreLayout);
693
694    // Don't schedule more layouts, we're in one.
695    TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
696
697    if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive()) {
698        // This is a new top-level layout. If there are any remaining tasks from the previous layout, finish them now.
699        m_inSynchronousPostLayout = true;
700        performPostLayoutTasks();
701        m_inSynchronousPostLayout = false;
702    }
703
704    Document* document = m_frame->document();
705    if (wasViewportResized())
706        document->notifyResizeForViewportUnits();
707
708    // Viewport-dependent media queries may cause us to need completely different style information.
709    if (!document->styleResolver() || document->styleResolver()->mediaQueryAffectedByViewportChange()) {
710        document->styleResolverChanged();
711        document->mediaQueryAffectingValueChanged();
712
713        // FIXME: This instrumentation event is not strictly accurate since cached media query results
714        //        do not persist across StyleResolver rebuilds.
715        InspectorInstrumentation::mediaQueryResultChanged(document);
716    } else {
717        document->evaluateMediaQueryList();
718    }
719
720    document->updateRenderTreeIfNeeded();
721    lifecycle().advanceTo(DocumentLifecycle::StyleClean);
722}
723
724void FrameView::performLayout(RenderObject* rootForThisLayout, bool inSubtreeLayout)
725{
726    TRACE_EVENT0("blink", "FrameView::performLayout");
727
728    ScriptForbiddenScope forbidScript;
729
730    ASSERT(!isInPerformLayout());
731    lifecycle().advanceTo(DocumentLifecycle::InPerformLayout);
732
733    TemporaryChange<bool> changeInPerformLayout(m_inPerformLayout, true);
734
735    // performLayout is the actual guts of layout().
736    // FIXME: The 300 other lines in layout() probably belong in other helper functions
737    // so that a single human could understand what layout() is actually doing.
738
739    LayoutState layoutState(*rootForThisLayout);
740
741    forceLayoutParentViewIfNeeded();
742
743    // FIXME (crbug.com/256657): Do not do two layouts for text autosizing.
744    rootForThisLayout->layout();
745    gatherDebugLayoutRects(rootForThisLayout);
746
747    ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities();
748
749    lifecycle().advanceTo(DocumentLifecycle::AfterPerformLayout);
750}
751
752void FrameView::scheduleOrPerformPostLayoutTasks()
753{
754    if (m_postLayoutTasksTimer.isActive())
755        return;
756
757    if (!m_inSynchronousPostLayout) {
758        m_inSynchronousPostLayout = true;
759        // Calls resumeScheduledEvents()
760        performPostLayoutTasks();
761        m_inSynchronousPostLayout = false;
762    }
763
764    if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout)) {
765        // If we need layout or are already in a synchronous call to postLayoutTasks(),
766        // defer widget updates and event dispatch until after we return. postLayoutTasks()
767        // can make us need to update again, and we can get stuck in a nasty cycle unless
768        // we call it through the timer here.
769        m_postLayoutTasksTimer.startOneShot(0, FROM_HERE);
770        if (needsLayout())
771            layout();
772    }
773}
774
775void FrameView::layout(bool allowSubtree)
776{
777    // We should never layout a Document which is not in a LocalFrame.
778    ASSERT(m_frame);
779    ASSERT(m_frame->view() == this);
780    ASSERT(m_frame->page());
781
782    ScriptForbiddenScope forbidScript;
783
784    if (isInPerformLayout() || !m_frame->document()->isActive())
785        return;
786
787    TRACE_EVENT0("blink", "FrameView::layout");
788    TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "Layout");
789
790    // Protect the view from being deleted during layout (in recalcStyle)
791    RefPtr<FrameView> protector(this);
792
793    // Every scroll that happens during layout is programmatic.
794    TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
795
796    if (m_autoSizeInfo)
797        m_autoSizeInfo->autoSizeIfNeeded();
798
799    m_hasPendingLayout = false;
800    DocumentLifecycle::Scope lifecycleScope(lifecycle(), DocumentLifecycle::LayoutClean);
801
802    RELEASE_ASSERT(!isPainting());
803
804    TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", "beginData", InspectorLayoutEvent::beginData(this));
805    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
806    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
807    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get());
808
809    if (!allowSubtree && isSubtreeLayout()) {
810        m_layoutSubtreeRoot->markContainingBlocksForLayout(false);
811        m_layoutSubtreeRoot = 0;
812    }
813
814    performPreLayoutTasks();
815
816    // If there is only one ref to this view left, then its going to be destroyed as soon as we exit,
817    // so there's no point to continuing to layout
818    if (protector->hasOneRef())
819        return;
820
821    Document* document = m_frame->document();
822    bool inSubtreeLayout = isSubtreeLayout();
823    RenderObject* rootForThisLayout = inSubtreeLayout ? m_layoutSubtreeRoot : document->renderView();
824    if (!rootForThisLayout) {
825        // FIXME: Do we need to set m_size here?
826        ASSERT_NOT_REACHED();
827        return;
828    }
829
830    FontCachePurgePreventer fontCachePurgePreventer;
831    RenderLayer* layer;
832    {
833        TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false);
834
835        m_nestedLayoutCount++;
836        if (!inSubtreeLayout) {
837            Document* document = m_frame->document();
838            Node* body = document->body();
839            if (body && body->renderer()) {
840                if (isHTMLFrameSetElement(*body)) {
841                    body->renderer()->setChildNeedsLayout();
842                } else if (isHTMLBodyElement(*body)) {
843                    if (!m_firstLayout && m_size.height() != layoutSize().height() && body->renderer()->enclosingBox()->stretchesToViewport())
844                        body->renderer()->setChildNeedsLayout();
845                }
846            }
847        }
848        updateCounters();
849
850        ScrollbarMode hMode;
851        ScrollbarMode vMode;
852        calculateScrollbarModesForLayoutAndSetViewportRenderer(hMode, vMode);
853
854        if (!inSubtreeLayout) {
855            // Now set our scrollbar state for the layout.
856            ScrollbarMode currentHMode = horizontalScrollbarMode();
857            ScrollbarMode currentVMode = verticalScrollbarMode();
858
859            if (m_firstLayout) {
860                setScrollbarsSuppressed(true);
861
862                m_doFullPaintInvalidation = true;
863                m_firstLayout = false;
864                m_firstLayoutCallbackPending = true;
865                m_lastViewportSize = layoutSize(IncludeScrollbars);
866                m_lastZoomFactor = rootForThisLayout->style()->zoom();
867
868                // Set the initial vMode to AlwaysOn if we're auto.
869                if (vMode == ScrollbarAuto)
870                    setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
871                // Set the initial hMode to AlwaysOff if we're auto.
872                if (hMode == ScrollbarAuto)
873                    setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
874
875                setScrollbarModes(hMode, vMode);
876                setScrollbarsSuppressed(false, true);
877            } else if (hMode != currentHMode || vMode != currentVMode) {
878                setScrollbarModes(hMode, vMode);
879            }
880
881            LayoutSize oldSize = m_size;
882
883            m_size = LayoutSize(layoutSize().width(), layoutSize().height());
884
885            if (oldSize != m_size && !m_firstLayout) {
886                RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0;
887                RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0;
888                if (bodyRenderer && bodyRenderer->stretchesToViewport())
889                    bodyRenderer->setChildNeedsLayout();
890                else if (rootRenderer && rootRenderer->stretchesToViewport())
891                    rootRenderer->setChildNeedsLayout();
892            }
893
894            // We need to set m_doFullPaintInvalidation before triggering layout as RenderObject::checkForPaintInvalidation
895            // checks the boolean to disable local paint invalidations.
896            m_doFullPaintInvalidation |= renderView()->shouldDoFullPaintInvalidationForNextLayout();
897        }
898
899        layer = rootForThisLayout->enclosingLayer();
900
901        performLayout(rootForThisLayout, inSubtreeLayout);
902
903        m_layoutSubtreeRoot = 0;
904        // We need to ensure that we mark up all renderers up to the RenderView
905        // for paint invalidation. This simplifies our code as we just always
906        // do a full tree walk.
907        if (RenderObject* container = rootForThisLayout->container())
908            container->setMayNeedPaintInvalidation(true);
909    } // Reset m_layoutSchedulingEnabled to its previous value.
910
911    if (!inSubtreeLayout && !toRenderView(rootForThisLayout)->document().printing())
912        adjustViewSize();
913
914    layer->updateLayerPositionsAfterLayout();
915
916    renderView()->compositor()->didLayout();
917
918    m_layoutCount++;
919
920    if (AXObjectCache* cache = rootForThisLayout->document().axObjectCache()) {
921        const KURL& url = rootForThisLayout->document().url();
922        if (url.isValid() && !url.isAboutBlankURL())
923            cache->handleLayoutComplete(rootForThisLayout);
924    }
925    updateAnnotatedRegions();
926
927    ASSERT(!rootForThisLayout->needsLayout());
928
929    if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
930        updateOverflowStatus(layoutSize().width() < contentsWidth(), layoutSize().height() < contentsHeight());
931
932    scheduleOrPerformPostLayoutTasks();
933
934    TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", "endData", InspectorLayoutEvent::endData(rootForThisLayout));
935    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
936    InspectorInstrumentation::didLayout(cookie, rootForThisLayout);
937
938    m_nestedLayoutCount--;
939    if (m_nestedLayoutCount)
940        return;
941
942#if ENABLE(ASSERT)
943    // Post-layout assert that nobody was re-marked as needing layout during layout.
944    document->renderView()->assertSubtreeIsLaidOut();
945#endif
946
947    // FIXME: It should be not possible to remove the FrameView from the frame/page during layout
948    // however m_inPerformLayout is not set for most of this function, so none of our RELEASE_ASSERTS
949    // in LocalFrame/Page will fire. One of the post-layout tasks is disconnecting the LocalFrame from
950    // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.html
951    // necessitating this check here.
952    // ASSERT(frame()->page());
953    if (frame().page())
954        frame().page()->chrome().client().layoutUpdated(m_frame.get());
955}
956
957// The plan is to move to compositor-queried paint invalidation, in which case this
958// method would setNeedsRedraw on the GraphicsLayers with invalidations and
959// let the compositor pick which to actually draw.
960// See http://crbug.com/306706
961void FrameView::invalidateTreeIfNeeded()
962{
963    ASSERT(renderView());
964    RenderView& rootForPaintInvalidation = *renderView();
965    ASSERT(!rootForPaintInvalidation.needsLayout());
966
967    TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation.debugName().ascii());
968
969    PaintInvalidationState rootPaintInvalidationState(rootForPaintInvalidation);
970
971    if (m_doFullPaintInvalidation)
972        renderView()->compositor()->fullyInvalidatePaint();
973
974    rootForPaintInvalidation.invalidateTreeIfNeeded(rootPaintInvalidationState);
975
976    // Invalidate the paint of the frameviews scrollbars if needed
977    if (hasVerticalBarDamage())
978        invalidateRect(verticalBarDamage());
979    if (hasHorizontalBarDamage())
980        invalidateRect(horizontalBarDamage());
981    resetScrollbarDamage();
982
983
984#ifndef NDEBUG
985    renderView()->assertSubtreeClearedPaintInvalidationState();
986#endif
987
988    if (m_frame->selection().isCaretBoundsDirty())
989        m_frame->selection().invalidateCaretRect();
990}
991
992DocumentLifecycle& FrameView::lifecycle() const
993{
994    return m_frame->document()->lifecycle();
995}
996
997void FrameView::gatherDebugLayoutRects(RenderObject* layoutRoot)
998{
999    bool isTracing;
1000    TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), &isTracing);
1001    if (!isTracing)
1002        return;
1003    if (!layoutRoot->enclosingLayer()->hasCompositedLayerMapping())
1004        return;
1005    // For access to compositedLayerMapping().
1006    DisableCompositingQueryAsserts disabler;
1007    GraphicsLayer* graphicsLayer = layoutRoot->enclosingLayer()->compositedLayerMapping()->mainGraphicsLayer();
1008    if (!graphicsLayer)
1009        return;
1010
1011    GraphicsLayerDebugInfo& debugInfo = graphicsLayer->debugInfo();
1012
1013    debugInfo.currentLayoutRects().clear();
1014    for (RenderObject* renderer = layoutRoot; renderer; renderer = renderer->nextInPreOrder()) {
1015        if (renderer->layoutDidGetCalled()) {
1016            FloatQuad quad = renderer->localToAbsoluteQuad(FloatQuad(renderer->previousPaintInvalidationRect()));
1017            LayoutRect rect = quad.enclosingBoundingBox();
1018            debugInfo.currentLayoutRects().append(rect);
1019            renderer->setLayoutDidGetCalled(false);
1020        }
1021    }
1022}
1023
1024RenderBox* FrameView::embeddedContentBox() const
1025{
1026    RenderView* renderView = this->renderView();
1027    if (!renderView)
1028        return 0;
1029
1030    RenderObject* firstChild = renderView->firstChild();
1031    if (!firstChild || !firstChild->isBox())
1032        return 0;
1033
1034    // Curently only embedded SVG documents participate in the size-negotiation logic.
1035    if (firstChild->isSVGRoot())
1036        return toRenderBox(firstChild);
1037
1038    return 0;
1039}
1040
1041
1042void FrameView::addWidget(RenderWidget* object)
1043{
1044    m_widgets.add(object);
1045}
1046
1047void FrameView::removeWidget(RenderWidget* object)
1048{
1049    m_widgets.remove(object);
1050}
1051
1052void FrameView::updateWidgetPositions()
1053{
1054    WillBeHeapVector<RefPtrWillBeMember<RenderWidget> > widgets;
1055    copyToVector(m_widgets, widgets);
1056
1057    // Script or plugins could detach the frame so abort processing if that happens.
1058
1059    for (size_t i = 0; i < widgets.size() && renderView(); ++i)
1060        widgets[i]->updateWidgetPosition();
1061
1062    for (size_t i = 0; i < widgets.size() && renderView(); ++i)
1063        widgets[i]->widgetPositionsUpdated();
1064}
1065
1066void FrameView::addWidgetToUpdate(RenderEmbeddedObject& object)
1067{
1068    ASSERT(isInPerformLayout());
1069    // Tell the DOM element that it needs a widget update.
1070    Node* node = object.node();
1071    ASSERT(node);
1072    if (isHTMLObjectElement(*node) || isHTMLEmbedElement(*node))
1073        toHTMLPlugInElement(node)->setNeedsWidgetUpdate(true);
1074
1075    m_widgetUpdateSet.add(&object);
1076}
1077
1078void FrameView::setMediaType(const AtomicString& mediaType)
1079{
1080    ASSERT(m_frame->document());
1081    m_frame->document()->mediaQueryAffectingValueChanged();
1082    m_mediaType = mediaType;
1083}
1084
1085AtomicString FrameView::mediaType() const
1086{
1087    // See if we have an override type.
1088    String overrideType;
1089    InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType);
1090    if (!overrideType.isNull())
1091        return AtomicString(overrideType);
1092    return m_mediaType;
1093}
1094
1095void FrameView::adjustMediaTypeForPrinting(bool printing)
1096{
1097    if (printing) {
1098        if (m_mediaTypeWhenNotPrinting.isNull())
1099            m_mediaTypeWhenNotPrinting = mediaType();
1100            setMediaType(MediaTypeNames::print);
1101    } else {
1102        if (!m_mediaTypeWhenNotPrinting.isNull())
1103            setMediaType(m_mediaTypeWhenNotPrinting);
1104        m_mediaTypeWhenNotPrinting = nullAtom;
1105    }
1106}
1107
1108bool FrameView::contentsInCompositedLayer() const
1109{
1110    RenderView* renderView = this->renderView();
1111    if (renderView && renderView->compositingState() == PaintsIntoOwnBacking) {
1112        GraphicsLayer* layer = renderView->layer()->compositedLayerMapping()->mainGraphicsLayer();
1113        if (layer && layer->drawsContent())
1114            return true;
1115    }
1116
1117    return false;
1118}
1119
1120void FrameView::addSlowRepaintObject()
1121{
1122    if (!m_slowRepaintObjectCount++) {
1123        if (Page* page = m_frame->page()) {
1124            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1125                scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1126        }
1127    }
1128}
1129
1130void FrameView::removeSlowRepaintObject()
1131{
1132    ASSERT(m_slowRepaintObjectCount > 0);
1133    m_slowRepaintObjectCount--;
1134    if (!m_slowRepaintObjectCount) {
1135        if (Page* page = m_frame->page()) {
1136            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1137                scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this);
1138        }
1139    }
1140}
1141
1142void FrameView::addViewportConstrainedObject(RenderObject* object)
1143{
1144    if (!m_viewportConstrainedObjects)
1145        m_viewportConstrainedObjects = adoptPtr(new ViewportConstrainedObjectSet);
1146
1147    if (!m_viewportConstrainedObjects->contains(object)) {
1148        m_viewportConstrainedObjects->add(object);
1149
1150        if (Page* page = m_frame->page()) {
1151            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1152                scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1153        }
1154    }
1155}
1156
1157void FrameView::removeViewportConstrainedObject(RenderObject* object)
1158{
1159    if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) {
1160        m_viewportConstrainedObjects->remove(object);
1161
1162        if (Page* page = m_frame->page()) {
1163            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1164                scrollingCoordinator->frameViewFixedObjectsDidChange(this);
1165        }
1166    }
1167}
1168
1169LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1170{
1171    LayoutRect viewportRect = visibleContentRect();
1172    // Ignore overhang. No-op when not using rubber banding.
1173    viewportRect.setLocation(clampScrollPosition(scrollPosition()));
1174    return viewportRect;
1175}
1176
1177void FrameView::viewportConstrainedVisibleContentSizeChanged(bool widthChanged, bool heightChanged)
1178{
1179    if (!hasViewportConstrainedObjects())
1180        return;
1181
1182    // If viewport is not enabled, frameRect change will cause layout size change and then layout.
1183    // Otherwise, viewport constrained objects need their layout flags set separately to ensure
1184    // they are positioned correctly. In the virtual-viewport pinch mode frame rect changes wont
1185    // necessarily cause a layout size change so only take this early-out if we're in old-style
1186    // pinch.
1187    if (m_frame->settings()
1188        && !m_frame->settings()->viewportEnabled()
1189        && !m_frame->settings()->pinchVirtualViewportEnabled())
1190        return;
1191
1192    ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1193    for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1194        RenderObject* renderer = *it;
1195        RenderStyle* style = renderer->style();
1196        if (widthChanged) {
1197            if (style->width().isFixed() && (style->left().isAuto() || style->right().isAuto()))
1198                renderer->setNeedsPositionedMovementLayout();
1199            else
1200                renderer->setNeedsLayoutAndFullPaintInvalidation();
1201        }
1202        if (heightChanged) {
1203            if (style->height().isFixed() && (style->top().isAuto() || style->bottom().isAuto()))
1204                renderer->setNeedsPositionedMovementLayout();
1205            else
1206                renderer->setNeedsLayoutAndFullPaintInvalidation();
1207        }
1208    }
1209}
1210
1211IntSize FrameView::scrollOffsetForFixedPosition() const
1212{
1213    return toIntSize(clampScrollPosition(scrollPosition()));
1214}
1215
1216IntPoint FrameView::lastKnownMousePosition() const
1217{
1218    return m_frame->eventHandler().lastKnownMousePosition();
1219}
1220
1221bool FrameView::shouldSetCursor() const
1222{
1223    Page* page = frame().page();
1224    return page && page->visibilityState() != PageVisibilityStateHidden && page->focusController().isActive() && page->settings().deviceSupportsMouse();
1225}
1226
1227void FrameView::scrollContentsIfNeededRecursive()
1228{
1229    scrollContentsIfNeeded();
1230
1231    for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1232        if (!child->isLocalFrame())
1233            continue;
1234        if (FrameView* view = toLocalFrame(child)->view())
1235            view->scrollContentsIfNeededRecursive();
1236    }
1237}
1238
1239void FrameView::scrollContentsIfNeeded()
1240{
1241    bool didScroll = !pendingScrollDelta().isZero();
1242    ScrollView::scrollContentsIfNeeded();
1243    if (didScroll)
1244        updateFixedElementPaintInvalidationRectsAfterScroll();
1245}
1246
1247static LayoutRect paintInvalidationRectIncludingNonCompositingDescendants(const RenderLayer* layer)
1248{
1249    LayoutRect paintInvalidationRect = layer->renderer()->previousPaintInvalidationRect();
1250
1251    for (const RenderLayer* child = layer->firstChild(); child; child = child->nextSibling()) {
1252        // Don't include paint invalidation rects for composited child layers; they will paint themselves and have a different origin.
1253        if (child->compositingState() == PaintsIntoOwnBacking || child->compositingState() == PaintsIntoGroupedBacking)
1254            continue;
1255
1256        paintInvalidationRect.unite(paintInvalidationRectIncludingNonCompositingDescendants(child));
1257    }
1258    return paintInvalidationRect;
1259}
1260
1261bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta)
1262{
1263    if (!contentsInCompositedLayer() || hasSlowRepaintObjects())
1264        return false;
1265
1266    if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
1267        InspectorInstrumentation::didScroll(page());
1268        return true;
1269    }
1270
1271    Region regionToUpdate;
1272    ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1273    for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1274        RenderObject* renderer = *it;
1275        ASSERT(renderer->style()->hasViewportConstrainedPosition());
1276        ASSERT(renderer->hasLayer());
1277        RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1278
1279        CompositingState state = layer->compositingState();
1280        if (state == PaintsIntoOwnBacking || state == PaintsIntoGroupedBacking)
1281            continue;
1282
1283        if (layer->subtreeIsInvisible())
1284            continue;
1285
1286        // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot
1287        // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
1288        if (layer->hasAncestorWithFilterOutsets())
1289            return false;
1290
1291        IntRect updateRect = pixelSnappedIntRect(paintInvalidationRectIncludingNonCompositingDescendants(layer));
1292
1293        const RenderLayerModelObject* repaintContainer = layer->renderer()->containerForPaintInvalidation();
1294        if (repaintContainer && !repaintContainer->isRenderView()) {
1295            // Invalidate the old and new locations of fixed position elements that are not drawn into the RenderView.
1296            updateRect.moveBy(scrollPosition());
1297            IntRect previousRect = updateRect;
1298            previousRect.move(scrollDelta);
1299            // FIXME: Rather than uniting the rects, we should just issue both invalidations.
1300            updateRect.unite(previousRect);
1301            layer->renderer()->invalidatePaintUsingContainer(repaintContainer, updateRect, InvalidationScroll);
1302        } else {
1303            // Coalesce the paint invalidations that will be issued to the renderView.
1304            updateRect = contentsToRootView(updateRect);
1305            if (!updateRect.isEmpty())
1306                regionToUpdate.unite(updateRect);
1307        }
1308    }
1309
1310    InspectorInstrumentation::didScroll(page());
1311
1312    // Invalidate the old and new locations of fixed position elements that are drawn into the RenderView.
1313    Vector<IntRect> subRectsToUpdate = regionToUpdate.rects();
1314    size_t viewportConstrainedObjectsCount = subRectsToUpdate.size();
1315    for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) {
1316        IntRect updateRect = subRectsToUpdate[i];
1317        IntRect scrolledRect = updateRect;
1318        scrolledRect.move(-scrollDelta);
1319        updateRect.unite(scrolledRect);
1320        // FIXME: We should be able to issue these invalidations separately and before we actually scroll.
1321        renderView()->setBackingNeedsPaintInvalidationInRect(rootViewToContents(updateRect));
1322    }
1323
1324    return true;
1325}
1326
1327void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
1328{
1329    if (contentsInCompositedLayer()) {
1330        IntRect updateRect = visibleContentRect();
1331        ASSERT(renderView());
1332        renderView()->invalidatePaintRectangle(updateRect);
1333    }
1334    if (RenderPart* frameRenderer = m_frame->ownerRenderer()) {
1335        if (isEnclosedInCompositingLayer()) {
1336            LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(),
1337                            frameRenderer->borderTop() + frameRenderer->paddingTop(),
1338                            visibleWidth(), visibleHeight());
1339            frameRenderer->invalidatePaintRectangle(rect);
1340            return;
1341        }
1342    }
1343
1344    ScrollView::scrollContentsSlowPath(updateRect);
1345}
1346
1347void FrameView::restoreScrollbar()
1348{
1349    setScrollbarsSuppressed(false);
1350}
1351
1352bool FrameView::scrollToFragment(const KURL& url)
1353{
1354    // If our URL has no ref, then we have no place we need to jump to.
1355    // OTOH If CSS target was set previously, we want to set it to 0, recalc
1356    // and possibly paint invalidation because :target pseudo class may have been
1357    // set (see bug 11321).
1358    if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
1359        return false;
1360
1361    String fragmentIdentifier = url.fragmentIdentifier();
1362    if (scrollToAnchor(fragmentIdentifier))
1363        return true;
1364
1365    // Try again after decoding the ref, based on the document's encoding.
1366    if (m_frame->document()->encoding().isValid())
1367        return scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, m_frame->document()->encoding()));
1368
1369    return false;
1370}
1371
1372bool FrameView::scrollToAnchor(const String& name)
1373{
1374    ASSERT(m_frame->document());
1375
1376    if (!m_frame->document()->isRenderingReady()) {
1377        m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
1378        return false;
1379    }
1380
1381    m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
1382
1383    Element* anchorNode = m_frame->document()->findAnchor(name);
1384
1385    // Setting to null will clear the current target.
1386    m_frame->document()->setCSSTarget(anchorNode);
1387
1388    if (m_frame->document()->isSVGDocument()) {
1389        if (SVGSVGElement* svg = SVGDocumentExtensions::rootElement(*m_frame->document())) {
1390            svg->setupInitialView(name, anchorNode);
1391            if (!anchorNode)
1392                return true;
1393        }
1394    }
1395
1396    // Implement the rule that "" and "top" both mean top of page as in other browsers.
1397    if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
1398        return false;
1399
1400    maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
1401
1402    // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
1403    // If anchorNode is not focusable, setFocusedElement() will still clear focus, which matches the behavior of other browsers.
1404    if (anchorNode)
1405        m_frame->document()->setFocusedElement(anchorNode);
1406
1407    return true;
1408}
1409
1410void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
1411{
1412    m_maintainScrollPositionAnchor = anchorNode;
1413    if (!m_maintainScrollPositionAnchor)
1414        return;
1415
1416    // We need to update the layout before scrolling, otherwise we could
1417    // really mess things up if an anchor scroll comes at a bad moment.
1418    m_frame->document()->updateRenderTreeIfNeeded();
1419    // Only do a layout if changes have occurred that make it necessary.
1420    RenderView* renderView = this->renderView();
1421    if (renderView && renderView->needsLayout())
1422        layout();
1423    else
1424        scrollToAnchor();
1425}
1426
1427void FrameView::scrollElementToRect(Element* element, const IntRect& rect)
1428{
1429    // FIXME(http://crbug.com/371896) - This method shouldn't be manually doing
1430    // coordinate transformations to the PinchViewport.
1431    IntRect targetRect(rect);
1432
1433    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1434
1435    bool pinchVirtualViewportEnabled = m_frame->settings()->pinchVirtualViewportEnabled();
1436
1437    if (pinchVirtualViewportEnabled) {
1438        PinchViewport& pinchViewport = m_frame->page()->frameHost().pinchViewport();
1439
1440        IntSize pinchViewportSize = expandedIntSize(pinchViewport.visibleRect().size());
1441        targetRect.moveBy(ceiledIntPoint(pinchViewport.visibleRect().location()));
1442        targetRect.setSize(pinchViewportSize.shrunkTo(targetRect.size()));
1443    }
1444
1445    LayoutRect bounds = element->boundingBox();
1446    int centeringOffsetX = (targetRect.width() - bounds.width()) / 2;
1447    int centeringOffsetY = (targetRect.height() - bounds.height()) / 2;
1448
1449    IntPoint targetOffset(
1450        bounds.x() - centeringOffsetX - targetRect.x(),
1451        bounds.y() - centeringOffsetY - targetRect.y());
1452
1453    setScrollPosition(targetOffset);
1454
1455    if (pinchVirtualViewportEnabled) {
1456        IntPoint remainder = IntPoint(targetOffset - scrollPosition());
1457        m_frame->page()->frameHost().pinchViewport().move(remainder);
1458    }
1459}
1460
1461void FrameView::setScrollPosition(const IntPoint& scrollPoint, ScrollBehavior scrollBehavior)
1462{
1463    cancelProgrammaticScrollAnimation();
1464    TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1465    m_maintainScrollPositionAnchor = nullptr;
1466
1467    IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1468
1469    if (newScrollPosition == scrollPosition())
1470        return;
1471
1472    if (scrollBehavior == ScrollBehaviorAuto) {
1473        RenderObject* renderer = m_frame->document()->documentElement() ? m_frame->document()->documentElement()->renderer() : 0;
1474        if (renderer)
1475            scrollBehavior = renderer->style()->scrollBehavior();
1476        else
1477            scrollBehavior = ScrollBehaviorInstant;
1478    }
1479    ScrollView::setScrollPosition(newScrollPosition, scrollBehavior);
1480}
1481
1482void FrameView::setScrollPositionNonProgrammatically(const IntPoint& scrollPoint)
1483{
1484    IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint);
1485
1486    if (newScrollPosition == scrollPosition())
1487        return;
1488
1489    TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, false);
1490    notifyScrollPositionChanged(newScrollPosition);
1491}
1492
1493IntSize FrameView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const
1494{
1495    return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(m_layoutSize) : m_layoutSize;
1496}
1497
1498void FrameView::setLayoutSize(const IntSize& size)
1499{
1500    ASSERT(!layoutSizeFixedToFrameSize());
1501
1502    setLayoutSizeInternal(size);
1503}
1504
1505void FrameView::scrollPositionChanged()
1506{
1507    setWasScrolledByUser(true);
1508
1509    Document* document = m_frame->document();
1510    document->enqueueScrollEventForNode(document);
1511
1512    m_frame->eventHandler().dispatchFakeMouseMoveEventSoon();
1513
1514    if (RenderView* renderView = document->renderView()) {
1515        if (renderView->usesCompositing())
1516            renderView->compositor()->frameViewDidScroll();
1517    }
1518
1519    if (m_didScrollTimer.isActive())
1520        m_didScrollTimer.stop();
1521    m_didScrollTimer.startOneShot(resourcePriorityUpdateDelayAfterScroll, FROM_HERE);
1522
1523    if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
1524        cache->handleScrollPositionChanged(this);
1525
1526    frame().loader().saveScrollState();
1527}
1528
1529void FrameView::didScrollTimerFired(Timer<FrameView>*)
1530{
1531    if (m_frame->document() && m_frame->document()->renderView()) {
1532        ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities();
1533    }
1534}
1535
1536void FrameView::updateLayersAndCompositingAfterScrollIfNeeded()
1537{
1538    // Nothing to do after scrolling if there are no fixed position elements.
1539    if (!hasViewportConstrainedObjects())
1540        return;
1541
1542    RefPtr<FrameView> protect(this);
1543
1544    // If there fixed position elements, scrolling may cause compositing layers to change.
1545    // Update widget and layer positions after scrolling, but only if we're not inside of
1546    // layout.
1547    if (!m_nestedLayoutCount) {
1548        updateWidgetPositions();
1549        if (RenderView* renderView = this->renderView())
1550            renderView->layer()->setNeedsCompositingInputsUpdate();
1551    }
1552}
1553
1554bool FrameView::computeCompositedSelectionBounds(LocalFrame& frame, CompositedSelectionBound& start, CompositedSelectionBound& end)
1555{
1556    const VisibleSelection &selection = frame.selection().selection();
1557    if (!selection.isCaretOrRange())
1558        return false;
1559
1560    VisiblePosition visibleStart(selection.visibleStart());
1561    VisiblePosition visibleEnd(selection.visibleEnd());
1562
1563    RenderedPosition renderedStart(visibleStart);
1564    RenderedPosition renderedEnd(visibleEnd);
1565
1566    renderedStart.positionInGraphicsLayerBacking(start);
1567    if (!start.layer)
1568        return false;
1569
1570    renderedEnd.positionInGraphicsLayerBacking(end);
1571    if (!end.layer)
1572        return false;
1573
1574    if (selection.isCaret()) {
1575        start.type = end.type = CompositedSelectionBound::Caret;
1576        return true;
1577    }
1578
1579    TextDirection startDir = visibleStart.deepEquivalent().primaryDirection();
1580    TextDirection endDir = visibleEnd.deepEquivalent().primaryDirection();
1581    start.type = startDir == RTL ? CompositedSelectionBound::SelectionRight : CompositedSelectionBound::SelectionLeft;
1582    end.type = endDir == RTL ? CompositedSelectionBound::SelectionLeft : CompositedSelectionBound::SelectionRight;
1583    return true;
1584}
1585
1586static void computePaintInvalidationRectsIncludingNonCompositingDescendants(RenderLayer* layer)
1587{
1588    // FIXME: boundsRectForPaintInvalidation() has to walk up the parent chain
1589    // for every layer to compute the rects. We should make this more efficient.
1590    // FIXME: it's wrong to call this when layout is not up-to-date, which we do.
1591    layer->renderer()->setPreviousPaintInvalidationRect(layer->renderer()->boundsRectForPaintInvalidation(layer->renderer()->containerForPaintInvalidation()));
1592    // FIXME: We are only updating the paint invalidation bounds but not
1593    // the positionFromPaintInvalidationContainer. This means that we may
1594    // forcing a full invaliation of the new position. Is this really correct?
1595
1596    for (RenderLayer* child = layer->firstChild(); child; child = child->nextSibling()) {
1597        if (child->compositingState() != PaintsIntoOwnBacking && child->compositingState() != PaintsIntoGroupedBacking)
1598            computePaintInvalidationRectsIncludingNonCompositingDescendants(child);
1599    }
1600}
1601
1602void FrameView::updateFixedElementPaintInvalidationRectsAfterScroll()
1603{
1604    if (!hasViewportConstrainedObjects())
1605        return;
1606
1607    // Update the paint invalidation rects for fixed elements after scrolling and invalidation to reflect
1608    // the new scroll position.
1609    ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end();
1610    for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) {
1611        RenderObject* renderer = *it;
1612        // m_viewportConstrainedObjects should not contain non-viewport constrained objects.
1613        ASSERT(renderer->style()->hasViewportConstrainedPosition());
1614
1615        // Fixed items should always have layers.
1616        ASSERT(renderer->hasLayer());
1617
1618        RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
1619
1620        // Don't need to do this for composited fixed items.
1621        if (layer->compositingState() == PaintsIntoOwnBacking)
1622            continue;
1623
1624        computePaintInvalidationRectsIncludingNonCompositingDescendants(layer);
1625    }
1626}
1627
1628void FrameView::updateCompositedSelectionBoundsIfNeeded()
1629{
1630    if (!RuntimeEnabledFeatures::compositedSelectionUpdateEnabled())
1631        return;
1632
1633    Page* page = frame().page();
1634    ASSERT(page);
1635
1636    CompositedSelectionBound start, end;
1637    LocalFrame* frame = toLocalFrame(page->focusController().focusedOrMainFrame());
1638    if (!frame || !computeCompositedSelectionBounds(*frame, start, end)) {
1639        page->chrome().client().clearCompositedSelectionBounds();
1640        return;
1641    }
1642
1643    page->chrome().client().updateCompositedSelectionBounds(start, end);
1644}
1645
1646bool FrameView::isRubberBandInProgress() const
1647{
1648    if (scrollbarsSuppressed())
1649        return false;
1650
1651    // If the main thread updates the scroll position for this FrameView, we should return
1652    // ScrollAnimator::isRubberBandInProgress().
1653    if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
1654        return scrollAnimator->isRubberBandInProgress();
1655
1656    return false;
1657}
1658
1659HostWindow* FrameView::hostWindow() const
1660{
1661    Page* page = frame().page();
1662    if (!page)
1663        return 0;
1664    return &page->chrome();
1665}
1666
1667void FrameView::contentRectangleForPaintInvalidation(const IntRect& r)
1668{
1669    ASSERT(paintInvalidationIsAllowed());
1670    ASSERT(!m_frame->ownerRenderer());
1671
1672    if (m_isTrackingPaintInvalidations) {
1673        IntRect paintInvalidationRect = r;
1674        paintInvalidationRect.move(-scrollOffset());
1675        m_trackedPaintInvalidationRects.append(paintInvalidationRect);
1676        // FIXME: http://crbug.com/368518. Eventually, invalidateContentRectangleForPaint
1677        // is going away entirely once all layout tests are FCM. In the short
1678        // term, no code should be tracking non-composited FrameView paint invalidations.
1679        RELEASE_ASSERT_NOT_REACHED();
1680    }
1681
1682    ScrollView::contentRectangleForPaintInvalidation(r);
1683}
1684
1685void FrameView::contentsResized()
1686{
1687    if (m_frame->isMainFrame() && m_frame->document()) {
1688        if (TextAutosizer* textAutosizer = m_frame->document()->textAutosizer())
1689            textAutosizer->updatePageInfoInAllFrames();
1690    }
1691
1692    ScrollView::contentsResized();
1693    setNeedsLayout();
1694}
1695
1696void FrameView::scrollbarExistenceDidChange()
1697{
1698    // We check to make sure the view is attached to a frame() as this method can
1699    // be triggered before the view is attached by LocalFrame::createView(...) setting
1700    // various values such as setScrollBarModes(...) for example.  An ASSERT is
1701    // triggered when a view is layout before being attached to a frame().
1702    if (!frame().view())
1703        return;
1704
1705    // Note that simply having overlay scrollbars is not sufficient to be
1706    // certain that scrollbars' presence does not impact layout. This should
1707    // also check if custom scrollbars (as reported by shouldUseCustomScrollbars)
1708    // are in use as well.
1709    // http://crbug.com/269692
1710    bool useOverlayScrollbars = ScrollbarTheme::theme()->usesOverlayScrollbars();
1711
1712    // FIXME: this call to layout() could be called within FrameView::layout(), but before performLayout(),
1713    // causing double-layout. See also crbug.com/429242.
1714    if (!useOverlayScrollbars && needsLayout())
1715        layout();
1716
1717    if (renderView() && renderView()->usesCompositing()) {
1718        renderView()->compositor()->frameViewScrollbarsExistenceDidChange();
1719
1720        if (!useOverlayScrollbars)
1721            renderView()->compositor()->frameViewDidChangeSize();
1722    }
1723}
1724
1725void FrameView::handleLoadCompleted()
1726{
1727    // Once loading has completed, allow autoSize one last opportunity to
1728    // reduce the size of the frame.
1729    if (m_autoSizeInfo)
1730        m_autoSizeInfo->autoSizeIfNeeded();
1731}
1732
1733void FrameView::scheduleRelayout()
1734{
1735    ASSERT(m_frame->view() == this);
1736
1737    if (isSubtreeLayout()) {
1738        m_layoutSubtreeRoot->markContainingBlocksForLayout(false);
1739        m_layoutSubtreeRoot = 0;
1740    }
1741    if (!m_layoutSchedulingEnabled)
1742        return;
1743    if (!needsLayout())
1744        return;
1745    if (!m_frame->document()->shouldScheduleLayout())
1746        return;
1747    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", "frame", m_frame.get());
1748    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
1749    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
1750    InspectorInstrumentation::didInvalidateLayout(m_frame.get());
1751
1752    if (m_hasPendingLayout)
1753        return;
1754    m_hasPendingLayout = true;
1755
1756    page()->animator().scheduleVisualUpdate();
1757    lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean);
1758}
1759
1760static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant)
1761{
1762    for (RenderObject* r = descendant; r; r = r->container()) {
1763        if (r == ancestor)
1764            return true;
1765    }
1766    return false;
1767}
1768
1769void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot)
1770{
1771    ASSERT(m_frame->view() == this);
1772
1773    // FIXME: Should this call shouldScheduleLayout instead?
1774    if (!m_frame->document()->isActive())
1775        return;
1776
1777    RenderView* renderView = this->renderView();
1778    if (renderView && renderView->needsLayout()) {
1779        if (relayoutRoot)
1780            relayoutRoot->markContainingBlocksForLayout(false);
1781        return;
1782    }
1783
1784    if (layoutPending() || !m_layoutSchedulingEnabled) {
1785        if (m_layoutSubtreeRoot != relayoutRoot) {
1786            if (isObjectAncestorContainerOf(m_layoutSubtreeRoot, relayoutRoot)) {
1787                // Keep the current root
1788                relayoutRoot->markContainingBlocksForLayout(false, m_layoutSubtreeRoot);
1789                ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout());
1790            } else if (isSubtreeLayout() && isObjectAncestorContainerOf(relayoutRoot, m_layoutSubtreeRoot)) {
1791                // Re-root at relayoutRoot
1792                m_layoutSubtreeRoot->markContainingBlocksForLayout(false, relayoutRoot);
1793                m_layoutSubtreeRoot = relayoutRoot;
1794                ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout());
1795            } else {
1796                // Just do a full relayout
1797                if (isSubtreeLayout())
1798                    m_layoutSubtreeRoot->markContainingBlocksForLayout(false);
1799                m_layoutSubtreeRoot = 0;
1800                relayoutRoot->markContainingBlocksForLayout(false);
1801            }
1802        }
1803    } else if (m_layoutSchedulingEnabled) {
1804        m_layoutSubtreeRoot = relayoutRoot;
1805        ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout());
1806        m_hasPendingLayout = true;
1807
1808        page()->animator().scheduleVisualUpdate();
1809        lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean);
1810    }
1811    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", "frame", m_frame.get());
1812    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
1813    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
1814    InspectorInstrumentation::didInvalidateLayout(m_frame.get());
1815}
1816
1817bool FrameView::layoutPending() const
1818{
1819    // FIXME: This should check Document::lifecycle instead.
1820    return m_hasPendingLayout;
1821}
1822
1823bool FrameView::isInPerformLayout() const
1824{
1825    ASSERT(m_inPerformLayout == (lifecycle().state() == DocumentLifecycle::InPerformLayout));
1826    return m_inPerformLayout;
1827}
1828
1829bool FrameView::needsLayout() const
1830{
1831    // This can return true in cases where the document does not have a body yet.
1832    // Document::shouldScheduleLayout takes care of preventing us from scheduling
1833    // layout in that case.
1834
1835    RenderView* renderView = this->renderView();
1836    return layoutPending()
1837        || (renderView && renderView->needsLayout())
1838        || isSubtreeLayout();
1839}
1840
1841void FrameView::setNeedsLayout()
1842{
1843    if (RenderView* renderView = this->renderView())
1844        renderView->setNeedsLayout();
1845}
1846
1847bool FrameView::isTransparent() const
1848{
1849    return m_isTransparent;
1850}
1851
1852void FrameView::setTransparent(bool isTransparent)
1853{
1854    m_isTransparent = isTransparent;
1855    DisableCompositingQueryAsserts disabler;
1856    if (renderView() && renderView()->layer()->hasCompositedLayerMapping())
1857        renderView()->layer()->compositedLayerMapping()->updateContentsOpaque();
1858}
1859
1860bool FrameView::hasOpaqueBackground() const
1861{
1862    return !m_isTransparent && !m_baseBackgroundColor.hasAlpha();
1863}
1864
1865Color FrameView::baseBackgroundColor() const
1866{
1867    return m_baseBackgroundColor;
1868}
1869
1870void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
1871{
1872    m_baseBackgroundColor = backgroundColor;
1873
1874    if (renderView() && renderView()->layer()->hasCompositedLayerMapping()) {
1875        CompositedLayerMapping* compositedLayerMapping = renderView()->layer()->compositedLayerMapping();
1876        compositedLayerMapping->updateContentsOpaque();
1877        if (compositedLayerMapping->mainGraphicsLayer())
1878            compositedLayerMapping->mainGraphicsLayer()->setNeedsDisplay();
1879    }
1880    recalculateScrollbarOverlayStyle();
1881}
1882
1883void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
1884{
1885    for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
1886        if (!frame->isLocalFrame())
1887            continue;
1888        if (FrameView* view = toLocalFrame(frame)->view()) {
1889            view->setTransparent(transparent);
1890            view->setBaseBackgroundColor(backgroundColor);
1891        }
1892    }
1893}
1894
1895void FrameView::scrollToAnchor()
1896{
1897    RefPtrWillBeRawPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
1898    if (!anchorNode)
1899        return;
1900
1901    if (!anchorNode->renderer())
1902        return;
1903
1904    LayoutRect rect;
1905    if (anchorNode != m_frame->document())
1906        rect = anchorNode->boundingBox();
1907
1908    RefPtrWillBeRawPtr<LocalFrame> boundaryFrame = m_frame->document()->findUnsafeParentScrollPropagationBoundary();
1909
1910    if (boundaryFrame)
1911        boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
1912
1913    // Scroll nested layers and frames to reveal the anchor.
1914    // Align to the top and to the closest side (this matches other browsers).
1915    anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
1916
1917    if (boundaryFrame)
1918        boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
1919
1920    if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
1921        cache->handleScrolledToAnchor(anchorNode.get());
1922
1923    // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
1924    m_maintainScrollPositionAnchor = anchorNode;
1925}
1926
1927bool FrameView::updateWidgets()
1928{
1929    // This is always called from updateWidgetsTimerFired.
1930    // m_updateWidgetsTimer should only be scheduled if we have widgets to update.
1931    // Thus I believe we can stop checking isEmpty here, and just ASSERT isEmpty:
1932    ASSERT(!m_widgetUpdateSet.isEmpty());
1933    if (m_nestedLayoutCount > 1 || m_widgetUpdateSet.isEmpty())
1934        return true;
1935
1936    // Need to swap because script will run inside the below loop and invalidate the iterator.
1937    EmbeddedObjectSet objects;
1938    objects.swap(m_widgetUpdateSet);
1939
1940    for (EmbeddedObjectSet::iterator it = objects.begin(); it != objects.end(); ++it) {
1941        RenderEmbeddedObject& object = **it;
1942        HTMLPlugInElement* element = toHTMLPlugInElement(object.node());
1943
1944        // The object may have already been destroyed (thus node cleared),
1945        // but FrameView holds a manual ref, so it won't have been deleted.
1946        if (!element)
1947            continue;
1948
1949        // No need to update if it's already crashed or known to be missing.
1950        if (object.showsUnavailablePluginIndicator())
1951            continue;
1952
1953        if (element->needsWidgetUpdate())
1954            element->updateWidget();
1955        object.updateWidgetPosition();
1956
1957        // Prevent plugins from causing infinite updates of themselves.
1958        // FIXME: Do we really need to prevent this?
1959        m_widgetUpdateSet.remove(&object);
1960    }
1961
1962    return m_widgetUpdateSet.isEmpty();
1963}
1964
1965void FrameView::updateWidgetsTimerFired(Timer<FrameView>*)
1966{
1967    ASSERT(!isInPerformLayout());
1968    RefPtr<FrameView> protect(this);
1969    m_updateWidgetsTimer.stop();
1970    for (unsigned i = 0; i < maxUpdateWidgetsIterations; ++i) {
1971        if (updateWidgets())
1972            return;
1973    }
1974}
1975
1976void FrameView::flushAnyPendingPostLayoutTasks()
1977{
1978    ASSERT(!isInPerformLayout());
1979    if (m_postLayoutTasksTimer.isActive())
1980        performPostLayoutTasks();
1981    if (m_updateWidgetsTimer.isActive())
1982        updateWidgetsTimerFired(0);
1983}
1984
1985void FrameView::scheduleUpdateWidgetsIfNecessary()
1986{
1987    ASSERT(!isInPerformLayout());
1988    if (m_updateWidgetsTimer.isActive() || m_widgetUpdateSet.isEmpty())
1989        return;
1990    m_updateWidgetsTimer.startOneShot(0, FROM_HERE);
1991}
1992
1993void FrameView::performPostLayoutTasks()
1994{
1995    // FIXME: We can reach here, even when the page is not active!
1996    // http/tests/inspector/elements/html-link-import.html and many other
1997    // tests hit that case.
1998    // We should ASSERT(isActive()); or at least return early if we can!
1999    ASSERT(!isInPerformLayout()); // Always before or after performLayout(), part of the highest-level layout() call.
2000    TRACE_EVENT0("blink", "FrameView::performPostLayoutTasks");
2001    RefPtr<FrameView> protect(this);
2002
2003    m_postLayoutTasksTimer.stop();
2004
2005    m_frame->selection().setCaretRectNeedsUpdate();
2006
2007    {
2008        // Hits in compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html
2009        DisableCompositingQueryAsserts disabler;
2010        m_frame->selection().updateAppearance();
2011    }
2012
2013    ASSERT(m_frame->document());
2014    if (m_nestedLayoutCount <= 1) {
2015        if (m_firstLayoutCallbackPending)
2016            m_firstLayoutCallbackPending = false;
2017
2018        // Ensure that we always send this eventually.
2019        if (!m_frame->document()->parsing() && m_frame->loader().stateMachine()->committedFirstRealDocumentLoad())
2020            m_isVisuallyNonEmpty = true;
2021
2022        // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
2023        if (m_isVisuallyNonEmpty && !m_frame->document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
2024            m_firstVisuallyNonEmptyLayoutCallbackPending = false;
2025            // FIXME: This callback is probably not needed, but is currently used
2026            // by android for setting the background color.
2027            m_frame->loader().client()->dispatchDidFirstVisuallyNonEmptyLayout();
2028        }
2029    }
2030
2031    FontFaceSet::didLayout(*m_frame->document());
2032
2033    updateWidgetPositions();
2034
2035    // Plugins could have torn down the page inside updateWidgetPositions().
2036    if (!renderView())
2037        return;
2038
2039    scheduleUpdateWidgetsIfNecessary();
2040
2041    if (Page* page = m_frame->page()) {
2042        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2043            scrollingCoordinator->notifyLayoutUpdated();
2044    }
2045
2046    scrollToAnchor();
2047
2048    sendResizeEventIfNeeded();
2049}
2050
2051bool FrameView::wasViewportResized()
2052{
2053    ASSERT(m_frame);
2054    RenderView* renderView = this->renderView();
2055    if (!renderView)
2056        return false;
2057    return (layoutSize(IncludeScrollbars) != m_lastViewportSize || renderView->style()->zoom() != m_lastZoomFactor);
2058}
2059
2060void FrameView::sendResizeEventIfNeeded()
2061{
2062    ASSERT(m_frame);
2063
2064    RenderView* renderView = this->renderView();
2065    if (!renderView || renderView->document().printing())
2066        return;
2067
2068    if (!wasViewportResized())
2069        return;
2070
2071    m_lastViewportSize = layoutSize(IncludeScrollbars);
2072    m_lastZoomFactor = renderView->style()->zoom();
2073
2074    m_frame->document()->enqueueResizeEvent();
2075
2076    if (m_frame->isMainFrame())
2077        InspectorInstrumentation::didResizeMainFrame(m_frame->page());
2078}
2079
2080void FrameView::postLayoutTimerFired(Timer<FrameView>*)
2081{
2082    performPostLayoutTasks();
2083}
2084
2085void FrameView::updateCounters()
2086{
2087    RenderView* view = renderView();
2088    if (!view->hasRenderCounters())
2089        return;
2090
2091    for (RenderObject* renderer = view; renderer; renderer = renderer->nextInPreOrder()) {
2092        if (!renderer->isCounter())
2093            continue;
2094
2095        toRenderCounter(renderer)->updateCounter();
2096    }
2097}
2098
2099void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2100{
2101    if (!m_viewportRenderer)
2102        return;
2103
2104    if (m_overflowStatusDirty) {
2105        m_horizontalOverflow = horizontalOverflow;
2106        m_verticalOverflow = verticalOverflow;
2107        m_overflowStatusDirty = false;
2108        return;
2109    }
2110
2111    bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2112    bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2113
2114    if (horizontalOverflowChanged || verticalOverflowChanged) {
2115        m_horizontalOverflow = horizontalOverflow;
2116        m_verticalOverflow = verticalOverflow;
2117
2118        RefPtrWillBeRawPtr<OverflowEvent> event = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow);
2119        event->setTarget(m_viewportRenderer->node());
2120        m_frame->document()->enqueueAnimationFrameEvent(event.release());
2121    }
2122
2123}
2124
2125IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) const
2126{
2127    ASSERT(m_frame->view() == this);
2128
2129    // Set our clip rect to be our contents.
2130    IntRect clipRect = contentsToWindow(visibleContentRect(scrollbarInclusion));
2131    if (!m_frame->deprecatedLocalOwner())
2132        return clipRect;
2133
2134    // Take our owner element and get its clip rect.
2135    // FIXME: Do we need to do this for remote frames?
2136    HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
2137    FrameView* parentView = ownerElement->document().view();
2138    if (parentView)
2139        clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement));
2140    return clipRect;
2141}
2142
2143IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement) const
2144{
2145    // The renderer can sometimes be null when style="display:none" interacts
2146    // with external content and plugins.
2147    if (!ownerElement->renderer())
2148        return windowClipRect();
2149
2150    // If we have no layer, just return our window clip rect.
2151    const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
2152    if (!enclosingLayer)
2153        return windowClipRect();
2154
2155    // FIXME: childrenClipRect relies on compositingState, which is not necessarily up to date.
2156    // https://code.google.com/p/chromium/issues/detail?id=343769
2157    DisableCompositingQueryAsserts disabler;
2158
2159    // Apply the clip from the layer.
2160    IntRect clipRect = contentsToWindow(pixelSnappedIntRect(enclosingLayer->clipper().childrenClipRect()));
2161    return intersection(clipRect, windowClipRect());
2162}
2163
2164bool FrameView::isActive() const
2165{
2166    Page* page = frame().page();
2167    return page && page->focusController().isActive();
2168}
2169
2170void FrameView::scrollTo(const IntSize& newOffset)
2171{
2172    LayoutSize offset = scrollOffset();
2173    ScrollView::scrollTo(newOffset);
2174    if (offset != scrollOffset()) {
2175        updateLayersAndCompositingAfterScrollIfNeeded();
2176        scrollPositionChanged();
2177    }
2178    frame().loader().client()->didChangeScrollOffset();
2179}
2180
2181void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2182{
2183    // Add in our offset within the FrameView.
2184    IntRect dirtyRect = rect;
2185    dirtyRect.moveBy(scrollbar->location());
2186
2187    if (isInPerformLayout())
2188        addScrollbarDamage(scrollbar, rect);
2189    else
2190        invalidateRect(dirtyRect);
2191}
2192
2193void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const
2194{
2195    if (!m_tickmarks.isEmpty())
2196        tickmarks = m_tickmarks;
2197    else
2198        tickmarks = frame().document()->markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
2199}
2200
2201IntRect FrameView::windowResizerRect() const
2202{
2203    Page* page = frame().page();
2204    if (!page)
2205        return IntRect();
2206    return page->chrome().windowResizerRect();
2207}
2208
2209void FrameView::setVisibleContentScaleFactor(float visibleContentScaleFactor)
2210{
2211    if (m_visibleContentScaleFactor == visibleContentScaleFactor)
2212        return;
2213
2214    m_visibleContentScaleFactor = visibleContentScaleFactor;
2215    updateScrollbars(scrollOffset());
2216}
2217
2218void FrameView::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor)
2219{
2220    m_inputEventsOffsetForEmulation = offset;
2221    m_inputEventsScaleFactorForEmulation = contentScaleFactor;
2222}
2223
2224IntSize FrameView::inputEventsOffsetForEmulation() const
2225{
2226    return m_inputEventsOffsetForEmulation;
2227}
2228
2229float FrameView::inputEventsScaleFactor() const
2230{
2231    float pageScale = m_frame->settings()->pinchVirtualViewportEnabled()
2232        ? m_frame->page()->frameHost().pinchViewport().scale()
2233        : visibleContentScaleFactor();
2234    return pageScale * m_inputEventsScaleFactorForEmulation;
2235}
2236
2237bool FrameView::scrollbarsCanBeActive() const
2238{
2239    if (m_frame->view() != this)
2240        return false;
2241
2242    return !!m_frame->document();
2243}
2244
2245IntRect FrameView::scrollableAreaBoundingBox() const
2246{
2247    RenderPart* ownerRenderer = frame().ownerRenderer();
2248    if (!ownerRenderer)
2249        return frameRect();
2250
2251    return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
2252}
2253
2254
2255bool FrameView::isScrollable()
2256{
2257    return scrollingReasons() == Scrollable;
2258}
2259
2260FrameView::ScrollingReasons FrameView::scrollingReasons()
2261{
2262    // Check for:
2263    // 1) If there an actual overflow.
2264    // 2) display:none or visibility:hidden set to self or inherited.
2265    // 3) overflow{-x,-y}: hidden;
2266    // 4) scrolling: no;
2267
2268    // Covers #1
2269    IntSize contentsSize = this->contentsSize();
2270    IntSize visibleContentSize = visibleContentRect().size();
2271    if ((contentsSize.height() <= visibleContentSize.height() && contentsSize.width() <= visibleContentSize.width()))
2272        return NotScrollableNoOverflow;
2273
2274    // Covers #2.
2275    // FIXME: Do we need to fix this for OOPI?
2276    HTMLFrameOwnerElement* owner = m_frame->deprecatedLocalOwner();
2277    if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
2278        return NotScrollableNotVisible;
2279
2280    // Cover #3 and #4.
2281    ScrollbarMode horizontalMode;
2282    ScrollbarMode verticalMode;
2283    calculateScrollbarModesForLayoutAndSetViewportRenderer(horizontalMode, verticalMode, RulesFromWebContentOnly);
2284    if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
2285        return NotScrollableExplicitlyDisabled;
2286
2287    return Scrollable;
2288}
2289
2290void FrameView::updateScrollableAreaSet()
2291{
2292    // That ensures that only inner frames are cached.
2293    FrameView* parentFrameView = this->parentFrameView();
2294    if (!parentFrameView)
2295        return;
2296
2297    if (!isScrollable()) {
2298        parentFrameView->removeScrollableArea(this);
2299        return;
2300    }
2301
2302    parentFrameView->addScrollableArea(this);
2303}
2304
2305bool FrameView::shouldSuspendScrollAnimations() const
2306{
2307    return m_frame->loader().state() != FrameStateComplete;
2308}
2309
2310void FrameView::scrollbarStyleChanged()
2311{
2312    // FIXME: Why does this only apply to the main frame?
2313    if (!m_frame->isMainFrame())
2314        return;
2315    ScrollView::scrollbarStyleChanged();
2316}
2317
2318void FrameView::notifyPageThatContentAreaWillPaint() const
2319{
2320    Page* page = m_frame->page();
2321    if (!page)
2322        return;
2323
2324    contentAreaWillPaint();
2325
2326    if (!m_scrollableAreas)
2327        return;
2328
2329    for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) {
2330        ScrollableArea* scrollableArea = *it;
2331
2332        if (!scrollableArea->scrollbarsCanBeActive())
2333            continue;
2334
2335        scrollableArea->contentAreaWillPaint();
2336    }
2337}
2338
2339bool FrameView::scrollAnimatorEnabled() const
2340{
2341    return m_frame->settings() && m_frame->settings()->scrollAnimatorEnabled();
2342}
2343
2344void FrameView::updateAnnotatedRegions()
2345{
2346    Document* document = m_frame->document();
2347    if (!document->hasAnnotatedRegions())
2348        return;
2349    Vector<AnnotatedRegionValue> newRegions;
2350    document->renderBox()->collectAnnotatedRegions(newRegions);
2351    if (newRegions == document->annotatedRegions())
2352        return;
2353    document->setAnnotatedRegions(newRegions);
2354    if (Page* page = m_frame->page())
2355        page->chrome().client().annotatedRegionsChanged();
2356}
2357
2358void FrameView::updateScrollCorner()
2359{
2360    RefPtr<RenderStyle> cornerStyle;
2361    IntRect cornerRect = scrollCornerRect();
2362    Document* doc = m_frame->document();
2363
2364    if (doc && !cornerRect.isEmpty()) {
2365        // Try the <body> element first as a scroll corner source.
2366        if (Element* body = doc->body()) {
2367            if (RenderObject* renderer = body->renderer())
2368                cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2369        }
2370
2371        if (!cornerStyle) {
2372            // If the <body> didn't have a custom style, then the root element might.
2373            if (Element* docElement = doc->documentElement()) {
2374                if (RenderObject* renderer = docElement->renderer())
2375                    cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2376            }
2377        }
2378
2379        if (!cornerStyle) {
2380            // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also.
2381            if (RenderPart* renderer = m_frame->ownerRenderer())
2382                cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style());
2383        }
2384    }
2385
2386    if (cornerStyle) {
2387        if (!m_scrollCorner)
2388            m_scrollCorner = RenderScrollbarPart::createAnonymous(doc);
2389        m_scrollCorner->setStyle(cornerStyle.release());
2390        invalidateScrollCorner(cornerRect);
2391    } else if (m_scrollCorner) {
2392        m_scrollCorner->destroy();
2393        m_scrollCorner = nullptr;
2394    }
2395
2396    ScrollView::updateScrollCorner();
2397}
2398
2399void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
2400{
2401    if (m_scrollCorner) {
2402        bool needsBackgorund = m_frame->isMainFrame();
2403        if (needsBackgorund)
2404            context->fillRect(cornerRect, baseBackgroundColor());
2405        m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
2406        return;
2407    }
2408
2409    ScrollView::paintScrollCorner(context, cornerRect);
2410}
2411
2412void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
2413{
2414    bool needsBackgorund = bar->isCustomScrollbar() && m_frame->isMainFrame();
2415    if (needsBackgorund) {
2416        IntRect toFill = bar->frameRect();
2417        toFill.intersect(rect);
2418        context->fillRect(toFill, baseBackgroundColor());
2419    }
2420
2421    ScrollView::paintScrollbar(context, bar, rect);
2422}
2423
2424Color FrameView::documentBackgroundColor() const
2425{
2426    // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
2427    // the document and the body against the base background color of the frame view.
2428    // Background images are unfortunately impractical to include.
2429
2430    Color result = baseBackgroundColor();
2431    if (!frame().document())
2432        return result;
2433
2434    Element* htmlElement = frame().document()->documentElement();
2435    Element* bodyElement = frame().document()->body();
2436
2437    // We take the aggregate of the base background color
2438    // the <html> background color, and the <body>
2439    // background color to find the document color. The
2440    // addition of the base background color is not
2441    // technically part of the document background, but it
2442    // otherwise poses problems when the aggregate is not
2443    // fully opaque.
2444    if (htmlElement && htmlElement->renderer())
2445        result = result.blend(htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor));
2446    if (bodyElement && bodyElement->renderer())
2447        result = result.blend(bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor));
2448
2449    return result;
2450}
2451
2452bool FrameView::hasCustomScrollbars() const
2453{
2454    const HashSet<RefPtr<Widget> >* viewChildren = children();
2455    HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
2456    for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
2457        Widget* widget = current->get();
2458        if (widget->isFrameView()) {
2459            if (toFrameView(widget)->hasCustomScrollbars())
2460                return true;
2461        } else if (widget->isScrollbar()) {
2462            Scrollbar* scrollbar = static_cast<Scrollbar*>(widget);
2463            if (scrollbar->isCustomScrollbar())
2464                return true;
2465        }
2466    }
2467
2468    return false;
2469}
2470
2471FrameView* FrameView::parentFrameView() const
2472{
2473    if (!parent())
2474        return 0;
2475
2476    Frame* parentFrame = m_frame->tree().parent();
2477    if (parentFrame && parentFrame->isLocalFrame())
2478        return toLocalFrame(parentFrame)->view();
2479
2480    return 0;
2481}
2482
2483bool FrameView::wasScrolledByUser() const
2484{
2485    return m_wasScrolledByUser;
2486}
2487
2488void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
2489{
2490    if (m_inProgrammaticScroll)
2491        return;
2492    m_maintainScrollPositionAnchor = nullptr;
2493    m_wasScrolledByUser = wasScrolledByUser;
2494}
2495
2496void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
2497{
2498    Document* document = m_frame->document();
2499
2500#ifndef NDEBUG
2501    bool fillWithRed;
2502    if (document->printing())
2503        fillWithRed = false; // Printing, don't fill with red (can't remember why).
2504    else if (m_frame->owner())
2505        fillWithRed = false; // Subframe, don't fill with red.
2506    else if (isTransparent())
2507        fillWithRed = false; // Transparent, don't fill with red.
2508    else if (m_paintBehavior & PaintBehaviorSelectionOnly)
2509        fillWithRed = false; // Selections are transparent, don't fill with red.
2510    else if (m_nodeToDraw)
2511        fillWithRed = false; // Element images are transparent, don't fill with red.
2512    else
2513        fillWithRed = true;
2514
2515    if (fillWithRed)
2516        p->fillRect(rect, Color(0xFF, 0, 0));
2517#endif
2518
2519    RenderView* renderView = this->renderView();
2520    if (!renderView) {
2521        WTF_LOG_ERROR("called FrameView::paint with nil renderer");
2522        return;
2523    }
2524
2525    RELEASE_ASSERT(!needsLayout());
2526    ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
2527
2528    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(renderView, rect, 0));
2529    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
2530    // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
2531    InspectorInstrumentation::willPaint(renderView, 0);
2532
2533    bool isTopLevelPainter = !s_inPaintContents;
2534    s_inPaintContents = true;
2535
2536    FontCachePurgePreventer fontCachePurgePreventer;
2537
2538    PaintBehavior oldPaintBehavior = m_paintBehavior;
2539
2540    if (FrameView* parentView = parentFrameView()) {
2541        if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
2542            m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2543    }
2544
2545    if (m_paintBehavior == PaintBehaviorNormal)
2546        document->markers().invalidateRenderedRectsForMarkersInRect(rect);
2547
2548    if (document->printing())
2549        m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
2550
2551    ASSERT(!m_isPainting);
2552    m_isPainting = true;
2553
2554    // m_nodeToDraw is used to draw only one element (and its descendants)
2555    RenderObject* renderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0;
2556    RenderLayer* rootLayer = renderView->layer();
2557
2558#if ENABLE(ASSERT)
2559    renderView->assertSubtreeIsLaidOut();
2560    RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->renderer());
2561#endif
2562
2563    rootLayer->paint(p, rect, m_paintBehavior, renderer);
2564
2565    if (rootLayer->containsDirtyOverlayScrollbars())
2566        rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, renderer);
2567
2568    m_isPainting = false;
2569
2570    m_paintBehavior = oldPaintBehavior;
2571    m_lastPaintTime = currentTime();
2572
2573    // Regions may have changed as a result of the visibility/z-index of element changing.
2574    if (document->annotatedRegionsDirty())
2575        updateAnnotatedRegions();
2576
2577    if (isTopLevelPainter) {
2578        // Everything that happens after paintContents completions is considered
2579        // to be part of the next frame.
2580        s_currentFrameTimeStamp = currentTime();
2581        s_inPaintContents = false;
2582    }
2583
2584    InspectorInstrumentation::didPaint(renderView, 0, p, rect);
2585}
2586
2587void FrameView::setPaintBehavior(PaintBehavior behavior)
2588{
2589    m_paintBehavior = behavior;
2590}
2591
2592PaintBehavior FrameView::paintBehavior() const
2593{
2594    return m_paintBehavior;
2595}
2596
2597bool FrameView::isPainting() const
2598{
2599    return m_isPainting;
2600}
2601
2602void FrameView::setNodeToDraw(Node* node)
2603{
2604    m_nodeToDraw = node;
2605}
2606
2607void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
2608{
2609    if (m_frame->document()->printing())
2610        return;
2611
2612    if (m_frame->isMainFrame()) {
2613        if (m_frame->page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2614            return;
2615    }
2616
2617    ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2618}
2619
2620void FrameView::updateWidgetPositionsIfNeeded()
2621{
2622    if (!m_needsUpdateWidgetPositions)
2623        return;
2624
2625    m_needsUpdateWidgetPositions = false;
2626
2627    updateWidgetPositions();
2628}
2629
2630void FrameView::updateLayoutAndStyleForPainting()
2631{
2632    // Updating layout can run script, which can tear down the FrameView.
2633    RefPtr<FrameView> protector(this);
2634
2635    updateLayoutAndStyleIfNeededRecursive();
2636
2637    updateWidgetPositionsIfNeeded();
2638
2639    if (RenderView* view = renderView()) {
2640        TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateLayerTree", "frame", m_frame.get());
2641        // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
2642        InspectorInstrumentation::willUpdateLayerTree(m_frame.get());
2643
2644        view->compositor()->updateIfNeededRecursive();
2645
2646        if (view->compositor()->inCompositingMode() && m_frame->isLocalRoot())
2647            m_frame->page()->scrollingCoordinator()->updateAfterCompositingChangeIfNeeded();
2648
2649        updateCompositedSelectionBoundsIfNeeded();
2650
2651        InspectorInstrumentation::didUpdateLayerTree(m_frame.get());
2652
2653        invalidateTreeIfNeededRecursive();
2654    }
2655
2656    scrollContentsIfNeededRecursive();
2657    ASSERT(lifecycle().state() == DocumentLifecycle::PaintInvalidationClean);
2658}
2659
2660void FrameView::updateLayoutAndStyleIfNeededRecursive()
2661{
2662    // We have to crawl our entire tree looking for any FrameViews that need
2663    // layout and make sure they are up to date.
2664    // Mac actually tests for intersection with the dirty region and tries not to
2665    // update layout for frames that are outside the dirty region.  Not only does this seem
2666    // pointless (since those frames will have set a zero timer to layout anyway), but
2667    // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2668    // region but then become included later by the second frame adding rects to the dirty region
2669    // when it lays out.
2670
2671    m_frame->document()->updateRenderTreeIfNeeded();
2672
2673    if (needsLayout())
2674        layout();
2675
2676    // FIXME: Calling layout() shouldn't trigger scripe execution or have any
2677    // observable effects on the frame tree but we're not quite there yet.
2678    Vector<RefPtr<FrameView> > frameViews;
2679    for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2680        if (!child->isLocalFrame())
2681            continue;
2682        if (FrameView* view = toLocalFrame(child)->view())
2683            frameViews.append(view);
2684    }
2685
2686    const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
2687    for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
2688        (*it)->updateLayoutAndStyleIfNeededRecursive();
2689
2690    // When an <iframe> gets composited, it triggers an extra style recalc in its containing FrameView.
2691    // To avoid pushing an invalid tree for display, we have to check for this case and do another
2692    // style recalc. The extra style recalc needs to happen after our child <iframes> were updated.
2693    // FIXME: We shouldn't be triggering an extra style recalc in the first place.
2694    if (m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()) {
2695        m_frame->document()->updateRenderTreeIfNeeded();
2696
2697        if (needsLayout())
2698            layout();
2699    }
2700
2701    // These asserts ensure that parent frames are clean, when child frames finished updating layout and style.
2702    ASSERT(!needsLayout());
2703    ASSERT(!m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate());
2704#if ENABLE(ASSERT)
2705    m_frame->document()->renderView()->assertRendererLaidOut();
2706#endif
2707
2708}
2709
2710void FrameView::invalidateTreeIfNeededRecursive()
2711{
2712    // FIXME: We should be more aggressive at cutting tree traversals.
2713    lifecycle().advanceTo(DocumentLifecycle::InPaintInvalidation);
2714    invalidateTreeIfNeeded();
2715    lifecycle().advanceTo(DocumentLifecycle::PaintInvalidationClean);
2716
2717    for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2718        if (!child->isLocalFrame())
2719            continue;
2720
2721        toLocalFrame(child)->view()->invalidateTreeIfNeededRecursive();
2722    }
2723
2724    m_doFullPaintInvalidation = false;
2725}
2726
2727void FrameView::enableAutoSizeMode(const IntSize& minSize, const IntSize& maxSize)
2728{
2729    if (!m_autoSizeInfo)
2730        m_autoSizeInfo = adoptPtr(new FrameViewAutoSizeInfo(this));
2731
2732    m_autoSizeInfo->configureAutoSizeMode(minSize, maxSize);
2733}
2734
2735void FrameView::forceLayout(bool allowSubtree)
2736{
2737    layout(allowSubtree);
2738}
2739
2740void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor)
2741{
2742    // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2743    // the state of things before and after the layout
2744    if (RenderView* renderView = this->renderView()) {
2745        float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2746        float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2747
2748        LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2749        LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2750        renderView->setLogicalWidth(flooredPageLogicalWidth);
2751        renderView->setPageLogicalHeight(flooredPageLogicalHeight);
2752        renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
2753        forceLayout();
2754
2755        // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2756        // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2757        // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
2758        // implementation should not do this!
2759        bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
2760        const LayoutRect& documentRect = renderView->documentRect();
2761        LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
2762        if (docLogicalWidth > pageLogicalWidth) {
2763            FloatSize expectedPageSize(std::min<float>(documentRect.width().toFloat(), pageSize.width() * maximumShrinkFactor), std::min<float>(documentRect.height().toFloat(), pageSize.height() * maximumShrinkFactor));
2764            FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), expectedPageSize);
2765            pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
2766            pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
2767
2768            flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2769            flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2770            renderView->setLogicalWidth(flooredPageLogicalWidth);
2771            renderView->setPageLogicalHeight(flooredPageLogicalHeight);
2772            renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
2773            forceLayout();
2774
2775            const LayoutRect& updatedDocumentRect = renderView->documentRect();
2776            LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
2777            LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
2778            LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
2779            LayoutUnit clippedLogicalLeft = 0;
2780            if (!renderView->style()->isLeftToRightDirection())
2781                clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
2782            LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
2783
2784            if (!horizontalWritingMode)
2785                overflow = overflow.transposedRect();
2786            renderView->clearLayoutOverflow();
2787            renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2788        }
2789    }
2790
2791    adjustViewSize();
2792}
2793
2794IntRect FrameView::convertFromRenderer(const RenderObject& renderer, const IntRect& rendererRect) const
2795{
2796    IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer.localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox()));
2797
2798    // Convert from page ("absolute") to FrameView coordinates.
2799    rect.moveBy(-scrollPosition());
2800
2801    return rect;
2802}
2803
2804IntRect FrameView::convertToRenderer(const RenderObject& renderer, const IntRect& viewRect) const
2805{
2806    IntRect rect = viewRect;
2807
2808    // Convert from FrameView coords into page ("absolute") coordinates.
2809    rect.moveBy(scrollPosition());
2810
2811    // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2812    // move the rect for now.
2813    rect.setLocation(roundedIntPoint(renderer.absoluteToLocal(rect.location(), UseTransforms)));
2814    return rect;
2815}
2816
2817IntPoint FrameView::convertFromRenderer(const RenderObject& renderer, const IntPoint& rendererPoint) const
2818{
2819    IntPoint point = roundedIntPoint(renderer.localToAbsolute(rendererPoint, UseTransforms));
2820
2821    // Convert from page ("absolute") to FrameView coordinates.
2822    point.moveBy(-scrollPosition());
2823    return point;
2824}
2825
2826IntPoint FrameView::convertToRenderer(const RenderObject& renderer, const IntPoint& viewPoint) const
2827{
2828    IntPoint point = viewPoint;
2829
2830    // Convert from FrameView coords into page ("absolute") coordinates.
2831    point += IntSize(scrollX(), scrollY());
2832
2833    return roundedIntPoint(renderer.absoluteToLocal(point, UseTransforms));
2834}
2835
2836IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2837{
2838    if (const ScrollView* parentScrollView = toScrollView(parent())) {
2839        if (parentScrollView->isFrameView()) {
2840            const FrameView* parentView = toFrameView(parentScrollView);
2841            // Get our renderer in the parent view
2842            RenderPart* renderer = m_frame->ownerRenderer();
2843            if (!renderer)
2844                return localRect;
2845
2846            IntRect rect(localRect);
2847            // Add borders and padding??
2848            rect.move(renderer->borderLeft() + renderer->paddingLeft(),
2849                renderer->borderTop() + renderer->paddingTop());
2850            return parentView->convertFromRenderer(*renderer, rect);
2851        }
2852
2853        return Widget::convertToContainingView(localRect);
2854    }
2855
2856    return localRect;
2857}
2858
2859IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
2860{
2861    if (const ScrollView* parentScrollView = toScrollView(parent())) {
2862        if (parentScrollView->isFrameView()) {
2863            const FrameView* parentView = toFrameView(parentScrollView);
2864
2865            // Get our renderer in the parent view
2866            RenderPart* renderer = m_frame->ownerRenderer();
2867            if (!renderer)
2868                return parentRect;
2869
2870            IntRect rect = parentView->convertToRenderer(*renderer, parentRect);
2871            // Subtract borders and padding
2872            rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
2873                      -renderer->borderTop() - renderer->paddingTop());
2874            return rect;
2875        }
2876
2877        return Widget::convertFromContainingView(parentRect);
2878    }
2879
2880    return parentRect;
2881}
2882
2883IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
2884{
2885    if (const ScrollView* parentScrollView = toScrollView(parent())) {
2886        if (parentScrollView->isFrameView()) {
2887            const FrameView* parentView = toFrameView(parentScrollView);
2888
2889            // Get our renderer in the parent view
2890            RenderPart* renderer = m_frame->ownerRenderer();
2891            if (!renderer)
2892                return localPoint;
2893
2894            IntPoint point(localPoint);
2895
2896            // Add borders and padding
2897            point.move(renderer->borderLeft() + renderer->paddingLeft(),
2898                       renderer->borderTop() + renderer->paddingTop());
2899            return parentView->convertFromRenderer(*renderer, point);
2900        }
2901
2902        return Widget::convertToContainingView(localPoint);
2903    }
2904
2905    return localPoint;
2906}
2907
2908IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
2909{
2910    if (const ScrollView* parentScrollView = toScrollView(parent())) {
2911        if (parentScrollView->isFrameView()) {
2912            const FrameView* parentView = toFrameView(parentScrollView);
2913
2914            // Get our renderer in the parent view
2915            RenderPart* renderer = m_frame->ownerRenderer();
2916            if (!renderer)
2917                return parentPoint;
2918
2919            IntPoint point = parentView->convertToRenderer(*renderer, parentPoint);
2920            // Subtract borders and padding
2921            point.move(-renderer->borderLeft() - renderer->paddingLeft(),
2922                       -renderer->borderTop() - renderer->paddingTop());
2923            return point;
2924        }
2925
2926        return Widget::convertFromContainingView(parentPoint);
2927    }
2928
2929    return parentPoint;
2930}
2931
2932void FrameView::setTracksPaintInvalidations(bool trackPaintInvalidations)
2933{
2934    if (trackPaintInvalidations == m_isTrackingPaintInvalidations)
2935        return;
2936
2937    for (Frame* frame = m_frame->tree().top(); frame; frame = frame->tree().traverseNext()) {
2938        if (!frame->isLocalFrame())
2939            continue;
2940        if (RenderView* renderView = toLocalFrame(frame)->contentRenderer())
2941            renderView->compositor()->setTracksPaintInvalidations(trackPaintInvalidations);
2942    }
2943
2944    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
2945        "FrameView::setTracksPaintInvalidations", "enabled", trackPaintInvalidations);
2946
2947    resetTrackedPaintInvalidations();
2948    m_isTrackingPaintInvalidations = trackPaintInvalidations;
2949}
2950
2951void FrameView::resetTrackedPaintInvalidations()
2952{
2953    m_trackedPaintInvalidationRects.clear();
2954    if (RenderView* renderView = this->renderView())
2955        renderView->compositor()->resetTrackedPaintInvalidationRects();
2956}
2957
2958String FrameView::trackedPaintInvalidationRectsAsText() const
2959{
2960    TextStream ts;
2961    if (!m_trackedPaintInvalidationRects.isEmpty()) {
2962        ts << "(repaint rects\n";
2963        for (size_t i = 0; i < m_trackedPaintInvalidationRects.size(); ++i)
2964            ts << "  (rect " << m_trackedPaintInvalidationRects[i].x() << " " << m_trackedPaintInvalidationRects[i].y() << " " << m_trackedPaintInvalidationRects[i].width() << " " << m_trackedPaintInvalidationRects[i].height() << ")\n";
2965        ts << ")\n";
2966    }
2967    return ts.release();
2968}
2969
2970void FrameView::addResizerArea(RenderBox& resizerBox)
2971{
2972    if (!m_resizerAreas)
2973        m_resizerAreas = adoptPtr(new ResizerAreaSet);
2974    m_resizerAreas->add(&resizerBox);
2975}
2976
2977void FrameView::removeResizerArea(RenderBox& resizerBox)
2978{
2979    if (!m_resizerAreas)
2980        return;
2981
2982    ResizerAreaSet::iterator it = m_resizerAreas->find(&resizerBox);
2983    if (it != m_resizerAreas->end())
2984        m_resizerAreas->remove(it);
2985}
2986
2987void FrameView::addScrollableArea(ScrollableArea* scrollableArea)
2988{
2989    ASSERT(scrollableArea);
2990    if (!m_scrollableAreas)
2991        m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
2992    m_scrollableAreas->add(scrollableArea);
2993}
2994
2995void FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
2996{
2997    if (!m_scrollableAreas)
2998        return;
2999    m_scrollableAreas->remove(scrollableArea);
3000}
3001
3002void FrameView::setParent(Widget* widget)
3003{
3004    ScrollView::setParent(widget);
3005    updateScrollableAreaSet();
3006}
3007
3008void FrameView::removeChild(Widget* widget)
3009{
3010    if (widget->isFrameView())
3011        removeScrollableArea(toFrameView(widget));
3012
3013    ScrollView::removeChild(widget);
3014}
3015
3016bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
3017{
3018    bool allowScrolling = userInputScrollable(HorizontalScrollbar) || userInputScrollable(VerticalScrollbar);
3019
3020    // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
3021    // should handle wheel events.
3022#if !USE(RUBBER_BANDING)
3023    if (!isScrollable())
3024        allowScrolling = false;
3025#endif
3026
3027    if (allowScrolling && ScrollableArea::handleWheelEvent(wheelEvent))
3028        return true;
3029
3030    // If the frame didn't handle the event, give the pinch-zoom viewport a chance to
3031    // process the scroll event.
3032    if (m_frame->settings()->pinchVirtualViewportEnabled() && m_frame->isMainFrame())
3033        return page()->frameHost().pinchViewport().handleWheelEvent(wheelEvent);
3034
3035    return false;
3036}
3037
3038bool FrameView::isVerticalDocument() const
3039{
3040    RenderView* renderView = this->renderView();
3041    if (!renderView)
3042        return true;
3043
3044    return renderView->style()->isHorizontalWritingMode();
3045}
3046
3047bool FrameView::isFlippedDocument() const
3048{
3049    RenderView* renderView = this->renderView();
3050    if (!renderView)
3051        return false;
3052
3053    return renderView->style()->isFlippedBlocksWritingMode();
3054}
3055
3056bool FrameView::scrollbarsDisabled() const
3057{
3058    if (!m_frame->settings() || !m_frame->settings()->pinchVirtualViewportEnabled())
3059        return false;
3060
3061    return m_frame->isMainFrame() && ScrollbarTheme::theme()->usesOverlayScrollbars();
3062}
3063
3064AXObjectCache* FrameView::axObjectCache() const
3065{
3066    if (frame().document())
3067        return frame().document()->existingAXObjectCache();
3068    return 0;
3069}
3070
3071void FrameView::setCursor(const Cursor& cursor)
3072{
3073    Page* page = frame().page();
3074    if (!page || !page->settings().deviceSupportsMouse())
3075        return;
3076    page->chrome().setCursor(cursor);
3077}
3078
3079void FrameView::frameRectsChanged()
3080{
3081    if (layoutSizeFixedToFrameSize())
3082        setLayoutSizeInternal(frameRect().size());
3083
3084    ScrollView::frameRectsChanged();
3085}
3086
3087void FrameView::setLayoutSizeInternal(const IntSize& size)
3088{
3089    if (m_layoutSize == size)
3090        return;
3091
3092    m_layoutSize = size;
3093    contentsResized();
3094}
3095
3096void FrameView::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3097{
3098    ScrollableArea::didAddScrollbar(scrollbar, orientation);
3099    if (AXObjectCache* cache = axObjectCache())
3100        cache->handleScrollbarUpdate(this);
3101}
3102
3103void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3104{
3105    ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
3106    if (AXObjectCache* cache = axObjectCache()) {
3107        cache->remove(scrollbar);
3108        cache->handleScrollbarUpdate(this);
3109    }
3110}
3111
3112void FrameView::setTopControlsViewportAdjustment(float adjustment)
3113{
3114    m_topControlsViewportAdjustment = adjustment;
3115}
3116
3117IntPoint FrameView::maximumScrollPosition() const
3118{
3119    FloatSize visibleContentSizeF = unscaledVisibleContentSize(ExcludeScrollbars);
3120    visibleContentSizeF.expand(0, -m_topControlsViewportAdjustment);
3121    visibleContentSizeF.scale(1 / visibleContentScaleFactor());
3122    IntSize visibleSize = expandedIntSize(visibleContentSizeF);
3123
3124    IntPoint maximumOffset(
3125        contentsWidth() - visibleSize.width() - scrollOrigin().x(),
3126        contentsHeight() - visibleSize.height() - scrollOrigin().y());
3127    maximumOffset.clampNegativeToZero();
3128    return maximumOffset;
3129}
3130
3131} // namespace blink
3132