98e3c7f77d34a25fa3a8c2ddbcd9d5a43205b4b6
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / FrameView.cpp
1 /*
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  *                     1999 Lars Knoll <knoll@kde.org>
4  *                     1999 Antti Koivisto <koivisto@kde.org>
5  *                     2000 Dirk Mueller <mueller@kde.org>
6  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
7  *           (C) 2006 Graham Dennis (graham.dennis@gmail.com)
8  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  * Copyright (C) 2009 Google Inc. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26
27 #include "config.h"
28 #include "core/frame/FrameView.h"
29
30 #include "core/HTMLNames.h"
31 #include "core/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     RenderObject* enclosingLayerRenderer = renderer ? renderer->enclosingLayer()->renderer() : 0;
2738     rootLayer->paint(p, rect, m_paintBehavior, enclosingLayerRenderer);
2739
2740     if (rootLayer->containsDirtyOverlayScrollbars())
2741         rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, renderer);
2742
2743     m_isPainting = false;
2744
2745     m_paintBehavior = oldPaintBehavior;
2746     m_lastPaintTime = currentTime();
2747
2748     // Regions may have changed as a result of the visibility/z-index of element changing.
2749     if (document->annotatedRegionsDirty())
2750         updateAnnotatedRegions();
2751
2752     if (isTopLevelPainter) {
2753         // Everythin that happens after paintContents completions is considered
2754         // to be part of the next frame.
2755         s_currentFrameTimeStamp = currentTime();
2756         s_inPaintContents = false;
2757     }
2758
2759     InspectorInstrumentation::didPaint(renderView, 0, p, rect);
2760 }
2761
2762 void FrameView::setPaintBehavior(PaintBehavior behavior)
2763 {
2764     m_paintBehavior = behavior;
2765 }
2766
2767 PaintBehavior FrameView::paintBehavior() const
2768 {
2769     return m_paintBehavior;
2770 }
2771
2772 bool FrameView::isPainting() const
2773 {
2774     return m_isPainting;
2775 }
2776
2777 void FrameView::setNodeToDraw(Node* node)
2778 {
2779     m_nodeToDraw = node;
2780 }
2781
2782 void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
2783 {
2784     if (context->paintingDisabled())
2785         return;
2786
2787     if (m_frame->document()->printing())
2788         return;
2789
2790     if (m_frame->isMainFrame()) {
2791         if (m_frame->page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
2792             return;
2793     }
2794
2795     ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
2796 }
2797
2798 void FrameView::updateLayoutAndStyleForPainting()
2799 {
2800     // Updating layout can run script, which can tear down the FrameView.
2801     RefPtr<FrameView> protector(this);
2802
2803     updateLayoutAndStyleIfNeededRecursive();
2804
2805     if (RenderView* view = renderView()) {
2806         InspectorInstrumentation::willUpdateLayerTree(view->frame());
2807
2808         view->compositor()->updateIfNeededRecursive();
2809
2810         if (view->compositor()->inCompositingMode() && m_frame->isMainFrame())
2811             m_frame->page()->scrollingCoordinator()->updateAfterCompositingChangeIfNeeded();
2812
2813         InspectorInstrumentation::didUpdateLayerTree(view->frame());
2814     }
2815
2816     scrollContentsIfNeededRecursive();
2817 }
2818
2819 void FrameView::updateLayoutAndStyleIfNeededRecursive()
2820 {
2821     // We have to crawl our entire tree looking for any FrameViews that need
2822     // layout and make sure they are up to date.
2823     // Mac actually tests for intersection with the dirty region and tries not to
2824     // update layout for frames that are outside the dirty region.  Not only does this seem
2825     // pointless (since those frames will have set a zero timer to layout anyway), but
2826     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
2827     // region but then become included later by the second frame adding rects to the dirty region
2828     // when it lays out.
2829
2830     m_frame->document()->updateRenderTreeIfNeeded();
2831
2832     if (needsLayout())
2833         layout();
2834
2835     // FIXME: Calling layout() shouldn't trigger scripe execution or have any
2836     // observable effects on the frame tree but we're not quite there yet.
2837     Vector<RefPtr<FrameView> > frameViews;
2838     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2839         if (!child->isLocalFrame())
2840             continue;
2841         if (FrameView* view = toLocalFrame(child)->view())
2842             frameViews.append(view);
2843     }
2844
2845     const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
2846     for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
2847         (*it)->updateLayoutAndStyleIfNeededRecursive();
2848
2849     // When an <iframe> gets composited, it triggers an extra style recalc in its containing FrameView.
2850     // To avoid pushing an invalid tree for display, we have to check for this case and do another
2851     // style recalc. The extra style recalc needs to happen after our child <iframes> were updated.
2852     // FIXME: We shouldn't be triggering an extra style recalc in the first place.
2853     if (m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()) {
2854         m_frame->document()->updateRenderTreeIfNeeded();
2855
2856         if (needsLayout())
2857             layout();
2858     }
2859
2860     // These asserts ensure that parent frames are clean, when child frames finished updating layout and style.
2861     ASSERT(!needsLayout());
2862     ASSERT(!m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate());
2863 #ifndef NDEBUG
2864     m_frame->document()->renderView()->assertRendererLaidOut();
2865 #endif
2866
2867 }
2868
2869 void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
2870 {
2871     ASSERT(!enable || !minSize.isEmpty());
2872     ASSERT(minSize.width() <= maxSize.width());
2873     ASSERT(minSize.height() <= maxSize.height());
2874
2875     if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
2876         return;
2877
2878
2879     m_shouldAutoSize = enable;
2880     m_minAutoSize = minSize;
2881     m_maxAutoSize = maxSize;
2882     m_didRunAutosize = false;
2883
2884     setLayoutSizeFixedToFrameSize(enable);
2885     setNeedsLayout();
2886     scheduleRelayout();
2887     if (m_shouldAutoSize)
2888         return;
2889
2890     // Since autosize mode forces the scrollbar mode, change them to being auto.
2891     setVerticalScrollbarLock(false);
2892     setHorizontalScrollbarLock(false);
2893     setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
2894 }
2895
2896 void FrameView::forceLayout(bool allowSubtree)
2897 {
2898     layout(allowSubtree);
2899 }
2900
2901 void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor)
2902 {
2903     // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
2904     // the state of things before and after the layout
2905     if (RenderView* renderView = this->renderView()) {
2906         float pageLogicalWidth = renderView->style()->isHorizontalWritingMode() ? pageSize.width() : pageSize.height();
2907         float pageLogicalHeight = renderView->style()->isHorizontalWritingMode() ? pageSize.height() : pageSize.width();
2908
2909         LayoutUnit flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2910         LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2911         renderView->setLogicalWidth(flooredPageLogicalWidth);
2912         renderView->setPageLogicalHeight(flooredPageLogicalHeight);
2913         renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
2914         forceLayout();
2915
2916         // If we don't fit in the given page width, we'll lay out again. If we don't fit in the
2917         // page width when shrunk, we will lay out at maximum shrink and clip extra content.
2918         // FIXME: We are assuming a shrink-to-fit printing implementation.  A cropping
2919         // implementation should not do this!
2920         bool horizontalWritingMode = renderView->style()->isHorizontalWritingMode();
2921         const LayoutRect& documentRect = renderView->documentRect();
2922         LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height();
2923         if (docLogicalWidth > pageLogicalWidth) {
2924             FloatSize expectedPageSize(std::min<float>(documentRect.width().toFloat(), pageSize.width() * maximumShrinkFactor), std::min<float>(documentRect.height().toFloat(), pageSize.height() * maximumShrinkFactor));
2925             FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), expectedPageSize);
2926             pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height();
2927             pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width();
2928
2929             flooredPageLogicalWidth = static_cast<LayoutUnit>(pageLogicalWidth);
2930             flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight);
2931             renderView->setLogicalWidth(flooredPageLogicalWidth);
2932             renderView->setPageLogicalHeight(flooredPageLogicalHeight);
2933             renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
2934             forceLayout();
2935
2936             const LayoutRect& updatedDocumentRect = renderView->documentRect();
2937             LayoutUnit docLogicalHeight = horizontalWritingMode ? updatedDocumentRect.height() : updatedDocumentRect.width();
2938             LayoutUnit docLogicalTop = horizontalWritingMode ? updatedDocumentRect.y() : updatedDocumentRect.x();
2939             LayoutUnit docLogicalRight = horizontalWritingMode ? updatedDocumentRect.maxX() : updatedDocumentRect.maxY();
2940             LayoutUnit clippedLogicalLeft = 0;
2941             if (!renderView->style()->isLeftToRightDirection())
2942                 clippedLogicalLeft = docLogicalRight - pageLogicalWidth;
2943             LayoutRect overflow(clippedLogicalLeft, docLogicalTop, pageLogicalWidth, docLogicalHeight);
2944
2945             if (!horizontalWritingMode)
2946                 overflow = overflow.transposedRect();
2947             renderView->clearLayoutOverflow();
2948             renderView->addLayoutOverflow(overflow); // This is how we clip in case we overflow again.
2949         }
2950     }
2951
2952     adjustViewSize();
2953 }
2954
2955 IntRect FrameView::convertFromRenderer(const RenderObject& renderer, const IntRect& rendererRect) const
2956 {
2957     IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer.localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox()));
2958
2959     // Convert from page ("absolute") to FrameView coordinates.
2960     rect.moveBy(-scrollPosition());
2961
2962     return rect;
2963 }
2964
2965 IntRect FrameView::convertToRenderer(const RenderObject& renderer, const IntRect& viewRect) const
2966 {
2967     IntRect rect = viewRect;
2968
2969     // Convert from FrameView coords into page ("absolute") coordinates.
2970     rect.moveBy(scrollPosition());
2971
2972     // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
2973     // move the rect for now.
2974     rect.setLocation(roundedIntPoint(renderer.absoluteToLocal(rect.location(), UseTransforms)));
2975     return rect;
2976 }
2977
2978 IntPoint FrameView::convertFromRenderer(const RenderObject& renderer, const IntPoint& rendererPoint) const
2979 {
2980     IntPoint point = roundedIntPoint(renderer.localToAbsolute(rendererPoint, UseTransforms));
2981
2982     // Convert from page ("absolute") to FrameView coordinates.
2983     point.moveBy(-scrollPosition());
2984     return point;
2985 }
2986
2987 IntPoint FrameView::convertToRenderer(const RenderObject& renderer, const IntPoint& viewPoint) const
2988 {
2989     IntPoint point = viewPoint;
2990
2991     // Convert from FrameView coords into page ("absolute") coordinates.
2992     point += IntSize(scrollX(), scrollY());
2993
2994     return roundedIntPoint(renderer.absoluteToLocal(point, UseTransforms));
2995 }
2996
2997 IntRect FrameView::convertToContainingView(const IntRect& localRect) const
2998 {
2999     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3000         if (parentScrollView->isFrameView()) {
3001             const FrameView* parentView = toFrameView(parentScrollView);
3002             // Get our renderer in the parent view
3003             RenderPart* renderer = m_frame->ownerRenderer();
3004             if (!renderer)
3005                 return localRect;
3006
3007             IntRect rect(localRect);
3008             // Add borders and padding??
3009             rect.move(renderer->borderLeft() + renderer->paddingLeft(),
3010                 renderer->borderTop() + renderer->paddingTop());
3011             return parentView->convertFromRenderer(*renderer, rect);
3012         }
3013
3014         return Widget::convertToContainingView(localRect);
3015     }
3016
3017     return localRect;
3018 }
3019
3020 IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
3021 {
3022     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3023         if (parentScrollView->isFrameView()) {
3024             const FrameView* parentView = toFrameView(parentScrollView);
3025
3026             // Get our renderer in the parent view
3027             RenderPart* renderer = m_frame->ownerRenderer();
3028             if (!renderer)
3029                 return parentRect;
3030
3031             IntRect rect = parentView->convertToRenderer(*renderer, parentRect);
3032             // Subtract borders and padding
3033             rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
3034                       -renderer->borderTop() - renderer->paddingTop());
3035             return rect;
3036         }
3037
3038         return Widget::convertFromContainingView(parentRect);
3039     }
3040
3041     return parentRect;
3042 }
3043
3044 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
3045 {
3046     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3047         if (parentScrollView->isFrameView()) {
3048             const FrameView* parentView = toFrameView(parentScrollView);
3049
3050             // Get our renderer in the parent view
3051             RenderPart* renderer = m_frame->ownerRenderer();
3052             if (!renderer)
3053                 return localPoint;
3054
3055             IntPoint point(localPoint);
3056
3057             // Add borders and padding
3058             point.move(renderer->borderLeft() + renderer->paddingLeft(),
3059                        renderer->borderTop() + renderer->paddingTop());
3060             return parentView->convertFromRenderer(*renderer, point);
3061         }
3062
3063         return Widget::convertToContainingView(localPoint);
3064     }
3065
3066     return localPoint;
3067 }
3068
3069 IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
3070 {
3071     if (const ScrollView* parentScrollView = toScrollView(parent())) {
3072         if (parentScrollView->isFrameView()) {
3073             const FrameView* parentView = toFrameView(parentScrollView);
3074
3075             // Get our renderer in the parent view
3076             RenderPart* renderer = m_frame->ownerRenderer();
3077             if (!renderer)
3078                 return parentPoint;
3079
3080             IntPoint point = parentView->convertToRenderer(*renderer, parentPoint);
3081             // Subtract borders and padding
3082             point.move(-renderer->borderLeft() - renderer->paddingLeft(),
3083                        -renderer->borderTop() - renderer->paddingTop());
3084             return point;
3085         }
3086
3087         return Widget::convertFromContainingView(parentPoint);
3088     }
3089
3090     return parentPoint;
3091 }
3092
3093 void FrameView::setTracksPaintInvalidations(bool trackPaintInvalidations)
3094 {
3095     if (trackPaintInvalidations == m_isTrackingPaintInvalidations)
3096         return;
3097
3098     for (Frame* frame = m_frame->tree().top(); frame; frame = frame->tree().traverseNext()) {
3099         if (!frame->isLocalFrame())
3100             continue;
3101         if (RenderView* renderView = toLocalFrame(frame)->contentRenderer())
3102             renderView->compositor()->setTracksRepaints(trackPaintInvalidations);
3103     }
3104
3105     TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
3106         "FrameView::setTracksPaintInvalidations", "enabled", trackPaintInvalidations);
3107
3108     resetTrackedPaintInvalidations();
3109     m_isTrackingPaintInvalidations = trackPaintInvalidations;
3110 }
3111
3112 void FrameView::resetTrackedPaintInvalidations()
3113 {
3114     m_trackedPaintInvalidationRects.clear();
3115     if (RenderView* renderView = this->renderView())
3116         renderView->compositor()->resetTrackedRepaintRects();
3117 }
3118
3119 String FrameView::trackedPaintInvalidationRectsAsText() const
3120 {
3121     TextStream ts;
3122     if (!m_trackedPaintInvalidationRects.isEmpty()) {
3123         ts << "(repaint rects\n";
3124         for (size_t i = 0; i < m_trackedPaintInvalidationRects.size(); ++i)
3125             ts << "  (rect " << m_trackedPaintInvalidationRects[i].x() << " " << m_trackedPaintInvalidationRects[i].y() << " " << m_trackedPaintInvalidationRects[i].width() << " " << m_trackedPaintInvalidationRects[i].height() << ")\n";
3126         ts << ")\n";
3127     }
3128     return ts.release();
3129 }
3130
3131 void FrameView::addResizerArea(RenderBox& resizerBox)
3132 {
3133     if (!m_resizerAreas)
3134         m_resizerAreas = adoptPtr(new ResizerAreaSet);
3135     m_resizerAreas->add(&resizerBox);
3136 }
3137
3138 void FrameView::removeResizerArea(RenderBox& resizerBox)
3139 {
3140     if (!m_resizerAreas)
3141         return;
3142
3143     ResizerAreaSet::iterator it = m_resizerAreas->find(&resizerBox);
3144     if (it != m_resizerAreas->end())
3145         m_resizerAreas->remove(it);
3146 }
3147
3148 void FrameView::addScrollableArea(ScrollableArea* scrollableArea)
3149 {
3150     ASSERT(scrollableArea);
3151     if (!m_scrollableAreas)
3152         m_scrollableAreas = adoptPtr(new ScrollableAreaSet);
3153     m_scrollableAreas->add(scrollableArea);
3154 }
3155
3156 void FrameView::removeScrollableArea(ScrollableArea* scrollableArea)
3157 {
3158     if (!m_scrollableAreas)
3159         return;
3160     m_scrollableAreas->remove(scrollableArea);
3161 }
3162
3163 void FrameView::removeChild(Widget* widget)
3164 {
3165     if (widget->isFrameView())
3166         removeScrollableArea(toFrameView(widget));
3167
3168     ScrollView::removeChild(widget);
3169 }
3170
3171 bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent)
3172 {
3173     bool allowScrolling = userInputScrollable(HorizontalScrollbar) || userInputScrollable(VerticalScrollbar);
3174
3175     // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views
3176     // should handle wheel events.
3177 #if !USE(RUBBER_BANDING)
3178     if (!isScrollable())
3179         allowScrolling = false;
3180 #endif
3181
3182     if (allowScrolling && ScrollableArea::handleWheelEvent(wheelEvent))
3183         return true;
3184
3185     // If the frame didn't handle the event, give the pinch-zoom viewport a chance to
3186     // process the scroll event.
3187     if (m_frame->settings()->pinchVirtualViewportEnabled() && m_frame->isMainFrame())
3188         return page()->frameHost().pinchViewport().handleWheelEvent(wheelEvent);
3189
3190     return false;
3191 }
3192
3193 bool FrameView::isVerticalDocument() const
3194 {
3195     RenderView* renderView = this->renderView();
3196     if (!renderView)
3197         return true;
3198
3199     return renderView->style()->isHorizontalWritingMode();
3200 }
3201
3202 bool FrameView::isFlippedDocument() const
3203 {
3204     RenderView* renderView = this->renderView();
3205     if (!renderView)
3206         return false;
3207
3208     return renderView->style()->isFlippedBlocksWritingMode();
3209 }
3210
3211 AXObjectCache* FrameView::axObjectCache() const
3212 {
3213     if (frame().document())
3214         return frame().document()->existingAXObjectCache();
3215     return 0;
3216 }
3217
3218 void FrameView::setCursor(const Cursor& cursor)
3219 {
3220     Page* page = frame().page();
3221     if (!page || !page->settings().deviceSupportsMouse())
3222         return;
3223     page->chrome().setCursor(cursor);
3224 }
3225
3226 void FrameView::frameRectsChanged()
3227 {
3228     if (layoutSizeFixedToFrameSize())
3229         setLayoutSizeInternal(frameRect().size());
3230
3231     ScrollView::frameRectsChanged();
3232 }
3233
3234 void FrameView::setLayoutSizeInternal(const IntSize& size)
3235 {
3236     if (m_layoutSize == size)
3237         return;
3238
3239     m_layoutSize = size;
3240     contentsResized();
3241 }
3242
3243 void FrameView::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3244 {
3245     ScrollableArea::didAddScrollbar(scrollbar, orientation);
3246     if (AXObjectCache* cache = axObjectCache())
3247         cache->handleScrollbarUpdate(this);
3248 }
3249
3250 void FrameView::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
3251 {
3252     ScrollableArea::willRemoveScrollbar(scrollbar, orientation);
3253     if (AXObjectCache* cache = axObjectCache()) {
3254         cache->remove(scrollbar);
3255         cache->handleScrollbarUpdate(this);
3256     }
3257 }
3258
3259 } // namespace WebCore