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