013dd459f2c77511bc12ddc7107420f06c57c203
[WebKit-https.git] / Source / WebCore / page / 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-2017 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 "FrameView.h"
29
30 #include "AXObjectCache.h"
31 #include "BackForwardController.h"
32 #include "CSSAnimationController.h"
33 #include "CachedImage.h"
34 #include "CachedResourceLoader.h"
35 #include "Chrome.h"
36 #include "ChromeClient.h"
37 #include "DOMWindow.h"
38 #include "DebugPageOverlays.h"
39 #include "DeprecatedGlobalSettings.h"
40 #include "DocumentMarkerController.h"
41 #include "EventHandler.h"
42 #include "EventNames.h"
43 #include "FloatRect.h"
44 #include "FocusController.h"
45 #include "Frame.h"
46 #include "FrameLoader.h"
47 #include "FrameLoaderClient.h"
48 #include "FrameSelection.h"
49 #include "FrameTree.h"
50 #include "GraphicsContext.h"
51 #include "HTMLBodyElement.h"
52 #include "HTMLDocument.h"
53 #include "HTMLEmbedElement.h"
54 #include "HTMLFrameElement.h"
55 #include "HTMLFrameSetElement.h"
56 #include "HTMLHtmlElement.h"
57 #include "HTMLIFrameElement.h"
58 #include "HTMLNames.h"
59 #include "HTMLObjectElement.h"
60 #include "HTMLPlugInImageElement.h"
61 #include "ImageDocument.h"
62 #include "InspectorClient.h"
63 #include "InspectorController.h"
64 #include "InspectorInstrumentation.h"
65 #include "Logging.h"
66 #include "MemoryCache.h"
67 #include "OverflowEvent.h"
68 #include "Page.h"
69 #include "PageCache.h"
70 #include "PageOverlayController.h"
71 #include "ProgressTracker.h"
72 #include "RenderEmbeddedObject.h"
73 #include "RenderFullScreen.h"
74 #include "RenderIFrame.h"
75 #include "RenderInline.h"
76 #include "RenderLayer.h"
77 #include "RenderLayerBacking.h"
78 #include "RenderLayerCompositor.h"
79 #include "RenderSVGRoot.h"
80 #include "RenderScrollbar.h"
81 #include "RenderScrollbarPart.h"
82 #include "RenderStyle.h"
83 #include "RenderText.h"
84 #include "RenderTheme.h"
85 #include "RenderView.h"
86 #include "RenderWidget.h"
87 #include "RuntimeEnabledFeatures.h"
88 #include "SVGDocument.h"
89 #include "SVGSVGElement.h"
90 #include "ScriptedAnimationController.h"
91 #include "ScrollAnimator.h"
92 #include "ScrollingCoordinator.h"
93 #include "Settings.h"
94 #include "StyleResolver.h"
95 #include "StyleScope.h"
96 #include "TextResourceDecoder.h"
97 #include "TiledBacking.h"
98 #include "VisualViewport.h"
99 #include "WheelEventTestTrigger.h"
100 #include <wtf/text/TextStream.h>
101
102 #include <wtf/IsoMallocInlines.h>
103 #include <wtf/MemoryPressureHandler.h>
104 #include <wtf/Ref.h>
105 #include <wtf/SetForScope.h>
106 #include <wtf/SystemTracing.h>
107
108 #if USE(COORDINATED_GRAPHICS)
109 #include "TiledBackingStore.h"
110 #endif
111
112 #if ENABLE(CSS_SCROLL_SNAP)
113 #include "AxisScrollSnapOffsets.h"
114 #endif
115
116 #if PLATFORM(IOS)
117 #include "DocumentLoader.h"
118 #include "LegacyTileCache.h"
119 #endif
120
121 namespace WebCore {
122
123 using namespace HTMLNames;
124
125 WTF_MAKE_ISO_ALLOCATED_IMPL(FrameView);
126
127 MonotonicTime FrameView::sCurrentPaintTimeStamp { };
128
129 // The maximum number of updateEmbeddedObjects iterations that should be done before returning.
130 static const unsigned maxUpdateEmbeddedObjectsIterations = 2;
131
132 static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint)
133 {
134     RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags;
135     if (didFullRepaint) {
136         flags &= ~RenderLayer::CheckForRepaint;
137         flags |= RenderLayer::NeedsFullRepaintInBacking;
138     }
139     if (isRelayoutingSubtree && layer->enclosingPaginationLayer(RenderLayer::IncludeCompositedPaginatedLayers))
140         flags |= RenderLayer::UpdatePagination;
141     return flags;
142 }
143
144 Pagination::Mode paginationModeForRenderStyle(const RenderStyle& style)
145 {
146     EOverflow overflow = style.overflowY();
147     if (overflow != OPAGEDX && overflow != OPAGEDY)
148         return Pagination::Unpaginated;
149
150     bool isHorizontalWritingMode = style.isHorizontalWritingMode();
151     TextDirection textDirection = style.direction();
152     WritingMode writingMode = style.writingMode();
153
154     // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode
155     // is horizontal, then we use TextDirection to choose between those options. If the WritingMode
156     // is vertical, then the direction of the verticality dictates the choice.
157     if (overflow == OPAGEDX) {
158         if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode)
159             return Pagination::LeftToRightPaginated;
160         return Pagination::RightToLeftPaginated;
161     }
162
163     // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode
164     // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode
165     // is vertical, then we use TextDirection to choose between those options. 
166     if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL))
167         return Pagination::TopToBottomPaginated;
168     return Pagination::BottomToTopPaginated;
169 }
170
171 FrameView::FrameView(Frame& frame)
172     : m_frame(frame)
173     , m_canHaveScrollbars(true)
174     , m_updateEmbeddedObjectsTimer(*this, &FrameView::updateEmbeddedObjectsTimerFired)
175     , m_updateWidgetPositionsTimer(*this, &FrameView::updateWidgetPositionsTimerFired)
176     , m_isTransparent(false)
177     , m_baseBackgroundColor(Color::white)
178     , m_mediaType("screen")
179     , m_overflowStatusDirty(true)
180     , m_wasScrolledByUser(false)
181     , m_inProgrammaticScroll(false)
182     , m_safeToPropagateScrollToParent(true)
183     , m_delayedScrollEventTimer(*this, &FrameView::sendScrollEvent)
184     , m_selectionRevealModeForFocusedElement(SelectionRevealMode::DoNotReveal)
185     , m_delayedScrollToFocusedElementTimer(*this, &FrameView::scrollToFocusedElementTimerFired)
186     , m_isTrackingRepaints(false)
187     , m_shouldUpdateWhileOffscreen(true)
188     , m_speculativeTilingEnabled(false)
189     , m_speculativeTilingEnableTimer(*this, &FrameView::speculativeTilingEnableTimerFired)
190 #if PLATFORM(IOS)
191     , m_useCustomFixedPositionLayoutRect(false)
192     , m_useCustomSizeForResizeEvent(false)
193 #endif
194     , m_hasOverrideViewportSize(false)
195     , m_shouldAutoSize(false)
196     , m_inAutoSize(false)
197     , m_didRunAutosize(false)
198     , m_autoSizeFixedMinimumHeight(0)
199     , m_headerHeight(0)
200     , m_footerHeight(0)
201     , m_milestonesPendingPaint(0)
202     , m_visualUpdatesAllowedByClient(true)
203     , m_hasFlippedBlockRenderers(false)
204     , m_scrollPinningBehavior(DoNotPin)
205     , m_layoutContext(*this)
206 {
207     init();
208
209 #if ENABLE(RUBBER_BANDING)
210     ScrollElasticity verticalElasticity = ScrollElasticityNone;
211     ScrollElasticity horizontalElasticity = ScrollElasticityNone;
212     if (m_frame->isMainFrame()) {
213         verticalElasticity = m_frame->page() ? m_frame->page()->verticalScrollElasticity() : ScrollElasticityAllowed;
214         horizontalElasticity = m_frame->page() ? m_frame->page()->horizontalScrollElasticity() : ScrollElasticityAllowed;
215     } else if (m_frame->settings().rubberBandingForSubScrollableRegionsEnabled()) {
216         verticalElasticity = ScrollElasticityAutomatic;
217         horizontalElasticity = ScrollElasticityAutomatic;
218     }
219
220     ScrollableArea::setVerticalScrollElasticity(verticalElasticity);
221     ScrollableArea::setHorizontalScrollElasticity(horizontalElasticity);
222 #endif
223 }
224
225 Ref<FrameView> FrameView::create(Frame& frame)
226 {
227     Ref<FrameView> view = adoptRef(*new FrameView(frame));
228     if (frame.page() && frame.page()->isVisible())
229         view->show();
230     return view;
231 }
232
233 Ref<FrameView> FrameView::create(Frame& frame, const IntSize& initialSize)
234 {
235     Ref<FrameView> view = adoptRef(*new FrameView(frame));
236     view->Widget::setFrameRect(IntRect(view->location(), initialSize));
237     if (frame.page() && frame.page()->isVisible())
238         view->show();
239     return view;
240 }
241
242 FrameView::~FrameView()
243 {
244     removeFromAXObjectCache();
245     resetScrollbars();
246
247     // Custom scrollbars should already be destroyed at this point
248     ASSERT(!horizontalScrollbar() || !horizontalScrollbar()->isCustomScrollbar());
249     ASSERT(!verticalScrollbar() || !verticalScrollbar()->isCustomScrollbar());
250
251     setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow.
252     setHasVerticalScrollbar(false);
253     
254     ASSERT(!m_scrollCorner);
255
256     ASSERT(frame().view() != this || !frame().contentRenderer());
257 }
258
259 void FrameView::reset()
260 {
261     m_cannotBlitToWindow = false;
262     m_isOverlapped = false;
263     m_contentIsOpaque = false;
264     m_updateEmbeddedObjectsTimer.stop();
265     m_firstLayoutCallbackPending = false;
266     m_wasScrolledByUser = false;
267     m_safeToPropagateScrollToParent = true;
268     m_delayedScrollEventTimer.stop();
269     m_shouldScrollToFocusedElement = false;
270     m_delayedScrollToFocusedElementTimer.stop();
271     m_lastViewportSize = IntSize();
272     m_lastZoomFactor = 1.0f;
273     m_isTrackingRepaints = false;
274     m_trackedRepaintRects.clear();
275     m_lastPaintTime = MonotonicTime();
276     m_paintBehavior = PaintBehaviorNormal;
277     m_isPainting = false;
278     m_visuallyNonEmptyCharacterCount = 0;
279     m_visuallyNonEmptyPixelCount = 0;
280     m_isVisuallyNonEmpty = false;
281     m_firstVisuallyNonEmptyLayoutCallbackPending = true;
282     m_needsDeferredScrollbarsUpdate = false;
283     m_maintainScrollPositionAnchor = nullptr;
284     layoutContext().reset();
285 }
286
287 void FrameView::removeFromAXObjectCache()
288 {
289     if (AXObjectCache* cache = axObjectCache()) {
290         if (HTMLFrameOwnerElement* owner = frame().ownerElement())
291             cache->childrenChanged(owner->renderer());
292         cache->remove(this);
293     }
294 }
295
296 void FrameView::resetScrollbars()
297 {
298     // FIXME: Do we really need this?
299     layoutContext().resetFirstLayoutFlag();
300     // Reset the document's scrollbars back to our defaults before we yield the floor.
301     setScrollbarsSuppressed(true);
302     if (m_canHaveScrollbars)
303         setScrollbarModes(ScrollbarAuto, ScrollbarAuto);
304     else
305         setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
306     setScrollbarsSuppressed(false);
307 }
308
309 void FrameView::resetScrollbarsAndClearContentsSize()
310 {
311     resetScrollbars();
312
313     LOG(Layout, "FrameView %p resetScrollbarsAndClearContentsSize", this);
314
315     setScrollbarsSuppressed(true);
316     setContentsSize(IntSize());
317     setScrollbarsSuppressed(false);
318 }
319
320 void FrameView::init()
321 {
322     reset();
323
324     m_margins = LayoutSize(-1, -1); // undefined
325     m_size = LayoutSize();
326
327     // Propagate the marginwidth/height and scrolling modes to the view.
328     Element* ownerElement = frame().ownerElement();
329     if (is<HTMLFrameElementBase>(ownerElement)) {
330         HTMLFrameElementBase& frameElement = downcast<HTMLFrameElementBase>(*ownerElement);
331         if (frameElement.scrollingMode() == ScrollbarAlwaysOff)
332             setCanHaveScrollbars(false);
333         LayoutUnit marginWidth = frameElement.marginWidth();
334         LayoutUnit marginHeight = frameElement.marginHeight();
335         if (marginWidth != -1)
336             setMarginWidth(marginWidth);
337         if (marginHeight != -1)
338             setMarginHeight(marginHeight);
339     }
340
341     Page* page = frame().page();
342     if (page && page->chrome().client().shouldPaintEntireContents())
343         setPaintsEntireContents(true);
344 }
345     
346 void FrameView::prepareForDetach()
347 {
348     detachCustomScrollbars();
349     // When the view is no longer associated with a frame, it needs to be removed from the ax object cache
350     // right now, otherwise it won't be able to reach the topDocument()'s axObject cache later.
351     removeFromAXObjectCache();
352
353     if (frame().page()) {
354         if (ScrollingCoordinator* scrollingCoordinator = frame().page()->scrollingCoordinator())
355             scrollingCoordinator->willDestroyScrollableArea(*this);
356     }
357 }
358
359 void FrameView::detachCustomScrollbars()
360 {
361     Scrollbar* horizontalBar = horizontalScrollbar();
362     if (horizontalBar && horizontalBar->isCustomScrollbar())
363         setHasHorizontalScrollbar(false);
364
365     Scrollbar* verticalBar = verticalScrollbar();
366     if (verticalBar && verticalBar->isCustomScrollbar())
367         setHasVerticalScrollbar(false);
368
369     m_scrollCorner = nullptr;
370 }
371
372 void FrameView::recalculateScrollbarOverlayStyle()
373 {
374     ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle();
375     std::optional<ScrollbarOverlayStyle> clientOverlayStyle = frame().page() ? frame().page()->chrome().client().preferredScrollbarOverlayStyle() : ScrollbarOverlayStyleDefault;
376     if (clientOverlayStyle) {
377         if (clientOverlayStyle.value() != oldOverlayStyle)
378             setScrollbarOverlayStyle(clientOverlayStyle.value());
379         return;
380     }
381
382     ScrollbarOverlayStyle computedOverlayStyle = ScrollbarOverlayStyleDefault;
383
384     Color backgroundColor = documentBackgroundColor();
385     if (backgroundColor.isValid()) {
386         // Reduce the background color from RGB to a lightness value
387         // and determine which scrollbar style to use based on a lightness
388         // heuristic.
389         double hue, saturation, lightness;
390         backgroundColor.getHSL(hue, saturation, lightness);
391         if (lightness <= .5 && backgroundColor.isVisible())
392             computedOverlayStyle = ScrollbarOverlayStyleLight;
393     }
394
395     if (oldOverlayStyle != computedOverlayStyle)
396         setScrollbarOverlayStyle(computedOverlayStyle);
397 }
398
399 void FrameView::clear()
400 {
401     setCanBlitOnScroll(true);
402     
403     reset();
404
405     setScrollbarsSuppressed(true);
406
407 #if PLATFORM(IOS)
408     // To avoid flashes of white, disable tile updates immediately when view is cleared at the beginning of a page load.
409     // Tiling will be re-enabled from UIKit via [WAKWindow setTilingMode:] when we have content to draw.
410     if (LegacyTileCache* tileCache = legacyTileCache())
411         tileCache->setTilingMode(LegacyTileCache::Disabled);
412 #endif
413 }
414
415 #if PLATFORM(IOS)
416 void FrameView::didReplaceMultipartContent()
417 {
418     // Re-enable tile updates that were disabled in clear().
419     if (LegacyTileCache* tileCache = legacyTileCache())
420         tileCache->setTilingMode(LegacyTileCache::Normal);
421 }
422 #endif
423
424 bool FrameView::didFirstLayout() const
425 {
426     return layoutContext().didFirstLayout();
427 }
428
429 void FrameView::invalidateRect(const IntRect& rect)
430 {
431     if (!parent()) {
432         if (auto* page = frame().page())
433             page->chrome().invalidateContentsAndRootView(rect);
434         return;
435     }
436
437     auto* renderer = frame().ownerRenderer();
438     if (!renderer)
439         return;
440
441     IntRect repaintRect = rect;
442     repaintRect.moveBy(roundedIntPoint(renderer->contentBoxLocation()));
443     renderer->repaintRectangle(repaintRect);
444 }
445
446 void FrameView::setFrameRect(const IntRect& newRect)
447 {
448     Ref<FrameView> protectedThis(*this);
449     IntRect oldRect = frameRect();
450     if (newRect == oldRect)
451         return;
452     // Every scroll that happens as the result of frame size change is programmatic.
453     SetForScope<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
454     ScrollView::setFrameRect(newRect);
455
456     updateScrollableAreaSet();
457
458     if (RenderView* renderView = this->renderView()) {
459         if (renderView->usesCompositing())
460             renderView->compositor().frameViewDidChangeSize();
461     }
462
463     if (frame().isMainFrame() && frame().page())
464         frame().page()->pageOverlayController().didChangeViewSize();
465
466     viewportContentsChanged();
467 }
468
469 bool FrameView::scheduleAnimation()
470 {
471     auto* page = frame().page();
472     if (!page)
473         return false;
474     page->chrome().scheduleAnimation();
475     return true;
476 }
477
478 void FrameView::setMarginWidth(LayoutUnit w)
479 {
480     // make it update the rendering area when set
481     m_margins.setWidth(w);
482 }
483
484 void FrameView::setMarginHeight(LayoutUnit h)
485 {
486     // make it update the rendering area when set
487     m_margins.setHeight(h);
488 }
489
490 FrameFlattening FrameView::effectiveFrameFlattening() const
491 {
492 #if PLATFORM(IOS)
493     // On iOS when async frame scrolling is enabled, it does not make sense to use full frame flattening.
494     // In that case, we just consider that frame flattening is disabled. This allows people to test
495     // frame scrolling on iOS by enabling "Async Frame Scrolling" via the Safari menu.
496     if (frame().settings().asyncFrameScrollingEnabled() && frame().settings().frameFlattening() == FrameFlattening::FullyEnabled)
497         return FrameFlattening::Disabled;
498 #endif
499     return frame().settings().frameFlattening();
500 }
501
502 bool FrameView::frameFlatteningEnabled() const
503 {
504     return effectiveFrameFlattening() != FrameFlattening::Disabled;
505 }
506
507 bool FrameView::isFrameFlatteningValidForThisFrame() const
508 {
509     if (!frameFlatteningEnabled())
510         return false;
511
512     HTMLFrameOwnerElement* owner = frame().ownerElement();
513     if (!owner)
514         return false;
515
516     // Frame flattening is valid only for <frame> and <iframe>.
517     return owner->hasTagName(frameTag) || owner->hasTagName(iframeTag);
518 }
519
520 bool FrameView::avoidScrollbarCreation() const
521 {
522     // with frame flattening no subframe can have scrollbars
523     // but we also cannot turn scrollbars off as we determine
524     // our flattening policy using that.
525     return isFrameFlatteningValidForThisFrame();
526 }
527
528 void FrameView::setCanHaveScrollbars(bool canHaveScrollbars)
529 {
530     m_canHaveScrollbars = canHaveScrollbars;
531     ScrollView::setCanHaveScrollbars(canHaveScrollbars);
532 }
533
534 void FrameView::updateCanHaveScrollbars()
535 {
536     ScrollbarMode hMode;
537     ScrollbarMode vMode;
538     scrollbarModes(hMode, vMode);
539     if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff)
540         setCanHaveScrollbars(false);
541     else
542         setCanHaveScrollbars(true);
543 }
544
545 Ref<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation)
546 {
547     // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
548     Document* doc = frame().document();
549
550     // Try the <body> element first as a scrollbar source.
551     HTMLElement* body = doc ? doc->bodyOrFrameset() : nullptr;
552     if (body && body->renderer() && body->renderer()->style().hasPseudoStyle(SCROLLBAR))
553         return RenderScrollbar::createCustomScrollbar(*this, orientation, body);
554     
555     // If the <body> didn't have a custom style, then the root element might.
556     Element* docElement = doc ? doc->documentElement() : nullptr;
557     if (docElement && docElement->renderer() && docElement->renderer()->style().hasPseudoStyle(SCROLLBAR))
558         return RenderScrollbar::createCustomScrollbar(*this, orientation, docElement);
559         
560     // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
561     RenderWidget* frameRenderer = frame().ownerRenderer();
562     if (frameRenderer && frameRenderer->style().hasPseudoStyle(SCROLLBAR))
563         return RenderScrollbar::createCustomScrollbar(*this, orientation, nullptr, &frame());
564     
565     // Nobody set a custom style, so we just use a native scrollbar.
566     return ScrollView::createScrollbar(orientation);
567 }
568
569 void FrameView::didRestoreFromPageCache()
570 {
571     // When restoring from page cache, the main frame stays in place while subframes get swapped in.
572     // We update the scrollable area set to ensure that scrolling data structures get invalidated.
573     updateScrollableAreaSet();
574 }
575
576 void FrameView::willDestroyRenderTree()
577 {
578     detachCustomScrollbars();
579     layoutContext().clearSubtreeLayoutRoot();
580 }
581
582 void FrameView::didDestroyRenderTree()
583 {
584     ASSERT(!layoutContext().subtreeLayoutRoot());
585     ASSERT(m_widgetsInRenderTree.isEmpty());
586
587     // If the render tree is destroyed below FrameView::updateEmbeddedObjects(), there will still be a null sentinel in the set.
588     // Everything else should have removed itself as the tree was felled.
589     ASSERT(!m_embeddedObjectsToUpdate || m_embeddedObjectsToUpdate->isEmpty() || (m_embeddedObjectsToUpdate->size() == 1 && m_embeddedObjectsToUpdate->first() == nullptr));
590
591     ASSERT(!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty());
592     ASSERT(!m_slowRepaintObjects || m_slowRepaintObjects->isEmpty());
593
594     if (!RuntimeEnabledFeatures::sharedFeatures().cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled())
595         ASSERT(!frame().animation().hasAnimations());
596 }
597
598 void FrameView::setContentsSize(const IntSize& size)
599 {
600     if (size == contentsSize())
601         return;
602
603     layoutContext().disableSetNeedsLayout();
604
605     ScrollView::setContentsSize(size);
606     contentsResized();
607     
608     Page* page = frame().page();
609     if (!page)
610         return;
611
612     updateScrollableAreaSet();
613
614     page->chrome().contentsSizeChanged(frame(), size); // Notify only.
615
616     if (frame().isMainFrame()) {
617         page->pageOverlayController().didChangeDocumentSize();
618         PageCache::singleton().markPagesForContentsSizeChanged(*page);
619     }
620     layoutContext().enableSetNeedsLayout();
621 }
622
623 void FrameView::adjustViewSize()
624 {
625     RenderView* renderView = this->renderView();
626     if (!renderView)
627         return;
628
629     ASSERT(frame().view() == this);
630
631     const IntRect rect = renderView->documentRect();
632     const IntSize& size = rect.size();
633     ScrollView::setScrollOrigin(IntPoint(-rect.x(), -rect.y()), !frame().document()->printing(), size == contentsSize());
634
635     LOG_WITH_STREAM(Layout, stream << "FrameView " << this << " adjustViewSize: unscaled document rect changed to " << renderView->unscaledDocumentRect() << " (scaled to " << size << ")");
636
637     setContentsSize(size);
638 }
639
640 void FrameView::applyOverflowToViewport(const RenderElement& renderer, ScrollbarMode& hMode, ScrollbarMode& vMode)
641 {
642     // Handle the overflow:hidden/scroll case for the body/html elements.  WinIE treats
643     // overflow:hidden and overflow:scroll on <body> as applying to the document's
644     // scrollbars.  The CSS2.1 draft states that HTML UAs should use the <html> or <body> element and XML/XHTML UAs should
645     // use the root element.
646
647     // To combat the inability to scroll on a page with overflow:hidden on the root when scaled, disregard hidden when
648     // there is a frameScaleFactor that is greater than one on the main frame. Also disregard hidden if there is a
649     // header or footer.
650
651     bool overrideHidden = frame().isMainFrame() && ((frame().frameScaleFactor() > 1) || headerHeight() || footerHeight());
652
653     EOverflow overflowX = renderer.style().overflowX();
654     EOverflow overflowY = renderer.style().overflowY();
655
656     if (is<RenderSVGRoot>(renderer)) {
657         // FIXME: evaluate if we can allow overflow for these cases too.
658         // Overflow is always hidden when stand-alone SVG documents are embedded.
659         if (downcast<RenderSVGRoot>(renderer).isEmbeddedThroughFrameContainingSVGDocument()) {
660             overflowX = OHIDDEN;
661             overflowY = OHIDDEN;
662         }
663     }
664
665     switch (overflowX) {
666         case OHIDDEN:
667             if (overrideHidden)
668                 hMode = ScrollbarAuto;
669             else
670                 hMode = ScrollbarAlwaysOff;
671             break;
672         case OSCROLL:
673             hMode = ScrollbarAlwaysOn;
674             break;
675         case OAUTO:
676             hMode = ScrollbarAuto;
677             break;
678         default:
679             // Don't set it at all.
680             ;
681     }
682     
683      switch (overflowY) {
684         case OHIDDEN:
685             if (overrideHidden)
686                 vMode = ScrollbarAuto;
687             else
688                 vMode = ScrollbarAlwaysOff;
689             break;
690         case OSCROLL:
691             vMode = ScrollbarAlwaysOn;
692             break;
693         case OAUTO:
694             vMode = ScrollbarAuto;
695             break;
696         default:
697             // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort().
698             ;
699     }
700 }
701
702 void FrameView::applyPaginationToViewport()
703 {
704     auto* document = frame().document();
705     auto* documentElement = document ? document->documentElement() : nullptr;
706     if (!documentElement || !documentElement->renderer()) {
707         setPagination(Pagination());
708         return;
709     }
710
711     auto& documentRenderer = *documentElement->renderer();
712     auto* documentOrBodyRenderer = &documentRenderer;
713
714     auto* body = document->body();
715     if (body && body->renderer()) {
716         documentOrBodyRenderer = documentRenderer.style().overflowX() == OVISIBLE && is<HTMLHtmlElement>(*documentElement) ?
717             body->renderer() : &documentRenderer;
718     }
719
720     Pagination pagination;
721     EOverflow overflowY = documentOrBodyRenderer->style().overflowY();
722     if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
723         pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
724         GapLength columnGapLength = documentOrBodyRenderer->style().columnGap();
725         pagination.gap = 0;
726         if (!columnGapLength.isNormal()) {
727             if (auto* containerForPaginationGap = is<RenderBox>(documentOrBodyRenderer) ? downcast<RenderBox>(documentOrBodyRenderer) : documentOrBodyRenderer->containingBlock())
728                 pagination.gap = valueForLength(columnGapLength.length(), containerForPaginationGap->availableLogicalWidth()).toUnsigned();
729         }
730     }
731     setPagination(pagination);
732 }
733
734 void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy)
735 {
736     m_viewportRendererType = ViewportRendererType::None;
737
738     const HTMLFrameOwnerElement* owner = frame().ownerElement();
739     if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) {
740         hMode = ScrollbarAlwaysOff;
741         vMode = ScrollbarAlwaysOff;
742         return;
743     }  
744     
745     if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) {
746         hMode = ScrollbarAuto;
747         vMode = ScrollbarAuto;
748     } else {
749         hMode = ScrollbarAlwaysOff;
750         vMode = ScrollbarAlwaysOff;
751     }
752     
753     if (layoutContext().subtreeLayoutRoot())
754         return;
755     
756     auto* document = frame().document();
757     if (!document)
758         return;
759
760     auto* documentElement = document->documentElement();
761     if (!documentElement)
762         return;
763
764     auto* bodyOrFrameset = document->bodyOrFrameset();
765     auto* rootRenderer = documentElement->renderer();
766     if (!bodyOrFrameset || !bodyOrFrameset->renderer()) {
767         if (rootRenderer) {
768             applyOverflowToViewport(*rootRenderer, hMode, vMode);
769             m_viewportRendererType = ViewportRendererType::Document;
770         }
771         return;
772     }
773     
774     if (is<HTMLFrameSetElement>(*bodyOrFrameset) && !frameFlatteningEnabled()) {
775         vMode = ScrollbarAlwaysOff;
776         hMode = ScrollbarAlwaysOff;
777         return;
778     }
779
780     if (is<HTMLBodyElement>(*bodyOrFrameset) && rootRenderer) {
781         // It's sufficient to just check the X overflow,
782         // since it's illegal to have visible in only one direction.
783         if (rootRenderer->style().overflowX() == OVISIBLE && is<HTMLHtmlElement>(documentElement)) {
784             auto* bodyRenderer = bodyOrFrameset->renderer();
785             if (bodyRenderer) {
786                 applyOverflowToViewport(*bodyRenderer, hMode, vMode);
787                 m_viewportRendererType = ViewportRendererType::Body;
788             }
789         } else {
790             applyOverflowToViewport(*rootRenderer, hMode, vMode);
791             m_viewportRendererType = ViewportRendererType::Document;
792         }
793     }
794 }
795
796 void FrameView::willRecalcStyle()
797 {
798     RenderView* renderView = this->renderView();
799     if (!renderView)
800         return;
801
802     renderView->compositor().willRecalcStyle();
803 }
804
805 bool FrameView::updateCompositingLayersAfterStyleChange()
806 {
807     // If we expect to update compositing after an incipient layout, don't do so here.
808     if (!renderView() || needsLayout() || layoutContext().isInLayout())
809         return false;
810     return renderView()->compositor().didRecalcStyleWithNoPendingLayout();
811 }
812
813 void FrameView::updateCompositingLayersAfterLayout()
814 {
815     RenderView* renderView = this->renderView();
816     if (!renderView)
817         return;
818
819     renderView->compositor().updateCompositingLayers(CompositingUpdateType::AfterLayout);
820 }
821
822 void FrameView::clearBackingStores()
823 {
824     RenderView* renderView = this->renderView();
825     if (!renderView)
826         return;
827
828     RenderLayerCompositor& compositor = renderView->compositor();
829     ASSERT(compositor.inCompositingMode());
830     compositor.enableCompositingMode(false);
831     compositor.clearBackingForAllLayers();
832 }
833
834 GraphicsLayer* FrameView::layerForScrolling() const
835 {
836     RenderView* renderView = this->renderView();
837     if (!renderView)
838         return nullptr;
839     return renderView->compositor().scrollLayer();
840 }
841
842 GraphicsLayer* FrameView::layerForHorizontalScrollbar() const
843 {
844     RenderView* renderView = this->renderView();
845     if (!renderView)
846         return nullptr;
847     return renderView->compositor().layerForHorizontalScrollbar();
848 }
849
850 GraphicsLayer* FrameView::layerForVerticalScrollbar() const
851 {
852     RenderView* renderView = this->renderView();
853     if (!renderView)
854         return nullptr;
855     return renderView->compositor().layerForVerticalScrollbar();
856 }
857
858 GraphicsLayer* FrameView::layerForScrollCorner() const
859 {
860     RenderView* renderView = this->renderView();
861     if (!renderView)
862         return nullptr;
863     return renderView->compositor().layerForScrollCorner();
864 }
865
866 TiledBacking* FrameView::tiledBacking() const
867 {
868     RenderView* renderView = this->renderView();
869     if (!renderView)
870         return nullptr;
871
872     RenderLayerBacking* backing = renderView->layer()->backing();
873     if (!backing)
874         return nullptr;
875
876     return backing->tiledBacking();
877 }
878
879 uint64_t FrameView::scrollLayerID() const
880 {
881     RenderView* renderView = this->renderView();
882     if (!renderView)
883         return 0;
884
885     RenderLayerBacking* backing = renderView->layer()->backing();
886     if (!backing)
887         return 0;
888
889     return backing->scrollingNodeIDForRole(Scrolling);
890 }
891
892 ScrollableArea* FrameView::scrollableAreaForScrollLayerID(uint64_t nodeID) const
893 {
894     RenderView* renderView = this->renderView();
895     if (!renderView)
896         return nullptr;
897
898     return renderView->compositor().scrollableAreaForScrollLayerID(nodeID);
899 }
900
901 #if ENABLE(RUBBER_BANDING)
902 GraphicsLayer* FrameView::layerForOverhangAreas() const
903 {
904     RenderView* renderView = this->renderView();
905     if (!renderView)
906         return nullptr;
907     return renderView->compositor().layerForOverhangAreas();
908 }
909
910 GraphicsLayer* FrameView::setWantsLayerForTopOverHangArea(bool wantsLayer) const
911 {
912     RenderView* renderView = this->renderView();
913     if (!renderView)
914         return nullptr;
915
916     return renderView->compositor().updateLayerForTopOverhangArea(wantsLayer);
917 }
918
919 GraphicsLayer* FrameView::setWantsLayerForBottomOverHangArea(bool wantsLayer) const
920 {
921     RenderView* renderView = this->renderView();
922     if (!renderView)
923         return nullptr;
924
925     return renderView->compositor().updateLayerForBottomOverhangArea(wantsLayer);
926 }
927
928 #endif // ENABLE(RUBBER_BANDING)
929
930 #if ENABLE(CSS_SCROLL_SNAP)
931 void FrameView::updateSnapOffsets()
932 {
933     if (!frame().document())
934         return;
935
936     // FIXME: Should we allow specifying snap points through <html> tags too?
937     HTMLElement* body = frame().document()->bodyOrFrameset();
938     if (!renderView() || !body || !body->renderer())
939         return;
940     
941     updateSnapOffsetsForScrollableArea(*this, *body, *renderView(), body->renderer()->style());
942 }
943
944 bool FrameView::isScrollSnapInProgress() const
945 {
946     if (scrollbarsSuppressed())
947         return false;
948     
949     // If the scrolling thread updates the scroll position for this FrameView, then we should return
950     // ScrollingCoordinator::isScrollSnapInProgress().
951     if (Page* page = frame().page()) {
952         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
953             if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously(*this))
954                 return scrollingCoordinator->isScrollSnapInProgress();
955         }
956     }
957     
958     // If the main thread updates the scroll position for this FrameView, we should return
959     // ScrollAnimator::isScrollSnapInProgress().
960     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
961         return scrollAnimator->isScrollSnapInProgress();
962     
963     return false;
964 }
965
966 void FrameView::updateScrollingCoordinatorScrollSnapProperties() const
967 {
968     renderView()->compositor().updateScrollSnapPropertiesWithFrameView(*this);
969 }
970 #endif
971
972 bool FrameView::flushCompositingStateForThisFrame(const Frame& rootFrameForFlush)
973 {
974     RenderView* renderView = this->renderView();
975     if (!renderView)
976         return true; // We don't want to keep trying to update layers if we have no renderer.
977
978     ASSERT(frame().view() == this);
979
980     // If we sync compositing layers when a layout is pending, we may cause painting of compositing
981     // layer content to occur before layout has happened, which will cause paintContents() to bail.
982     if (needsLayout())
983         return false;
984
985 #if PLATFORM(IOS)
986     if (LegacyTileCache* tileCache = legacyTileCache())
987         tileCache->doPendingRepaints();
988 #endif
989
990     renderView->compositor().flushPendingLayerChanges(&rootFrameForFlush == m_frame.ptr());
991     return true;
992 }
993
994 void FrameView::setNeedsOneShotDrawingSynchronization()
995 {
996     if (Page* page = frame().page())
997         page->chrome().client().setNeedsOneShotDrawingSynchronization();
998 }
999
1000 GraphicsLayer* FrameView::graphicsLayerForPlatformWidget(PlatformWidget platformWidget)
1001 {
1002     // To find the Widget that corresponds with platformWidget we have to do a linear
1003     // search of our child widgets.
1004     const Widget* foundWidget = nullptr;
1005     for (auto& widget : children()) {
1006         if (widget->platformWidget() != platformWidget)
1007             continue;
1008         foundWidget = widget.ptr();
1009         break;
1010     }
1011
1012     if (!foundWidget)
1013         return nullptr;
1014
1015     auto* renderWidget = RenderWidget::find(*foundWidget);
1016     if (!renderWidget)
1017         return nullptr;
1018
1019     auto* widgetLayer = renderWidget->layer();
1020     if (!widgetLayer || !widgetLayer->isComposited())
1021         return nullptr;
1022
1023     return widgetLayer->backing()->parentForSublayers();
1024 }
1025
1026 void FrameView::scheduleLayerFlushAllowingThrottling()
1027 {
1028     RenderView* view = this->renderView();
1029     if (!view)
1030         return;
1031     view->compositor().scheduleLayerFlush(true /* canThrottle */);
1032 }
1033
1034 LayoutRect FrameView::fixedScrollableAreaBoundsInflatedForScrolling(const LayoutRect& uninflatedBounds) const
1035 {
1036     LayoutPoint scrollPosition;
1037     LayoutSize topLeftExpansion;
1038     LayoutSize bottomRightExpansion;
1039
1040     if (frame().settings().visualViewportEnabled()) {
1041         // FIXME: this is wrong under zooming; uninflatedBounds is scaled but the scroll positions are not.
1042         scrollPosition = layoutViewportRect().location();
1043         topLeftExpansion = scrollPosition - unscaledMinimumScrollPosition();
1044         bottomRightExpansion = unscaledMaximumScrollPosition() - scrollPosition;
1045     } else {
1046         scrollPosition = scrollPositionRespectingCustomFixedPosition();
1047         topLeftExpansion = scrollPosition - minimumScrollPosition();
1048         bottomRightExpansion = maximumScrollPosition() - scrollPosition;
1049     }
1050
1051     return LayoutRect(uninflatedBounds.location() - topLeftExpansion, uninflatedBounds.size() + topLeftExpansion + bottomRightExpansion);
1052 }
1053
1054 LayoutPoint FrameView::scrollPositionRespectingCustomFixedPosition() const
1055 {
1056 #if PLATFORM(IOS)
1057     if (!frame().settings().visualViewportEnabled())
1058         return useCustomFixedPositionLayoutRect() ? customFixedPositionLayoutRect().location() : scrollPosition();
1059 #endif
1060
1061     return scrollPositionForFixedPosition();
1062 }
1063
1064 void FrameView::setHeaderHeight(int headerHeight)
1065 {
1066     if (frame().page())
1067         ASSERT(frame().isMainFrame());
1068     m_headerHeight = headerHeight;
1069
1070     if (RenderView* renderView = this->renderView())
1071         renderView->setNeedsLayout();
1072 }
1073
1074 void FrameView::setFooterHeight(int footerHeight)
1075 {
1076     if (frame().page())
1077         ASSERT(frame().isMainFrame());
1078     m_footerHeight = footerHeight;
1079
1080     if (RenderView* renderView = this->renderView())
1081         renderView->setNeedsLayout();
1082 }
1083
1084 float FrameView::topContentInset(TopContentInsetType contentInsetTypeToReturn) const
1085 {
1086     if (platformWidget() && contentInsetTypeToReturn == TopContentInsetType::WebCoreOrPlatformContentInset)
1087         return platformTopContentInset();
1088
1089     if (!frame().isMainFrame())
1090         return 0;
1091     
1092     Page* page = frame().page();
1093     return page ? page->topContentInset() : 0;
1094 }
1095     
1096 void FrameView::topContentInsetDidChange(float newTopContentInset)
1097 {
1098     RenderView* renderView = this->renderView();
1099     if (!renderView)
1100         return;
1101
1102     if (platformWidget())
1103         platformSetTopContentInset(newTopContentInset);
1104     
1105     layoutContext().layout();
1106     // Every scroll that happens as the result of content inset change is programmatic.
1107     SetForScope<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
1108     updateScrollbars(scrollPosition());
1109     if (renderView->usesCompositing())
1110         renderView->compositor().frameViewDidChangeSize();
1111
1112     if (TiledBacking* tiledBacking = this->tiledBacking())
1113         tiledBacking->setTopContentInset(newTopContentInset);
1114 }
1115
1116 void FrameView::topContentDirectionDidChange()
1117 {
1118     m_needsDeferredScrollbarsUpdate = true;
1119 }
1120
1121 void FrameView::handleDeferredScrollbarsUpdateAfterDirectionChange()
1122 {
1123     if (!m_needsDeferredScrollbarsUpdate)
1124         return;
1125
1126     m_needsDeferredScrollbarsUpdate = false;
1127
1128     updateScrollbars(scrollPosition());
1129     positionScrollbarLayers();
1130 }
1131     
1132 bool FrameView::hasCompositedContent() const
1133 {
1134     if (RenderView* renderView = this->renderView())
1135         return renderView->compositor().inCompositingMode();
1136     return false;
1137 }
1138
1139 // Sometimes (for plug-ins) we need to eagerly go into compositing mode.
1140 void FrameView::enterCompositingMode()
1141 {
1142     if (RenderView* renderView = this->renderView()) {
1143         renderView->compositor().enableCompositingMode();
1144         if (!needsLayout())
1145             renderView->compositor().scheduleCompositingLayerUpdate();
1146     }
1147 }
1148
1149 bool FrameView::isEnclosedInCompositingLayer() const
1150 {
1151     auto frameOwnerRenderer = frame().ownerRenderer();
1152     if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint())
1153         return true;
1154
1155     if (FrameView* parentView = parentFrameView())
1156         return parentView->isEnclosedInCompositingLayer();
1157     return false;
1158 }
1159
1160 bool FrameView::flushCompositingStateIncludingSubframes()
1161 {
1162 #if PLATFORM(COCOA)
1163     InspectorInstrumentation::willComposite(frame());
1164 #endif
1165
1166     bool allFramesFlushed = flushCompositingStateForThisFrame(frame());
1167
1168     for (Frame* child = frame().tree().firstRenderedChild(); child; child = child->tree().traverseNextRendered(m_frame.ptr())) {
1169         if (!child->view())
1170             continue;
1171         bool flushed = child->view()->flushCompositingStateForThisFrame(frame());
1172         allFramesFlushed &= flushed;
1173     }
1174     return allFramesFlushed;
1175 }
1176
1177 bool FrameView::isSoftwareRenderable() const
1178 {
1179     RenderView* renderView = this->renderView();
1180     return !renderView || !renderView->compositor().has3DContent();
1181 }
1182
1183 void FrameView::setIsInWindow(bool isInWindow)
1184 {
1185     if (RenderView* renderView = this->renderView())
1186         renderView->setIsInWindow(isInWindow);
1187 }
1188
1189 void FrameView::forceLayoutParentViewIfNeeded()
1190 {
1191     RenderWidget* ownerRenderer = frame().ownerRenderer();
1192     if (!ownerRenderer)
1193         return;
1194
1195     RenderBox* contentBox = embeddedContentBox();
1196     if (!contentBox)
1197         return;
1198
1199     auto& svgRoot = downcast<RenderSVGRoot>(*contentBox);
1200     if (svgRoot.everHadLayout() && !svgRoot.needsLayout())
1201         return;
1202
1203     LOG(Layout, "FrameView %p forceLayoutParentViewIfNeeded scheduling layout on parent FrameView %p", this, &ownerRenderer->view().frameView());
1204
1205     // If the embedded SVG document appears the first time, the ownerRenderer has already finished
1206     // layout without knowing about the existence of the embedded SVG document, because RenderReplaced
1207     // embeddedContentBox() returns nullptr, as long as the embedded document isn't loaded yet. Before
1208     // bothering to lay out the SVG document, mark the ownerRenderer needing layout and ask its
1209     // FrameView for a layout. After that the RenderEmbeddedObject (ownerRenderer) carries the
1210     // correct size, which RenderSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying
1211     // out for the first time, or when the RenderSVGRoot size has changed dynamically (eg. via <script>).
1212
1213     ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
1214     ownerRenderer->view().frameView().layoutContext().scheduleLayout();
1215 }
1216
1217 void FrameView::markRootOrBodyRendererDirty() const
1218 {
1219     auto& document = *frame().document();
1220     RenderBox* rootRenderer = document.documentElement() ? document.documentElement()->renderBox() : nullptr;
1221     auto* body = document.bodyOrFrameset();
1222     RenderBox* bodyRenderer = rootRenderer && body ? body->renderBox() : nullptr;
1223     if (bodyRenderer && bodyRenderer->stretchesToViewport())
1224         bodyRenderer->setChildNeedsLayout();
1225     else if (rootRenderer && rootRenderer->stretchesToViewport())
1226         rootRenderer->setChildNeedsLayout();
1227 }
1228
1229 void FrameView::adjustScrollbarsForLayout(bool isFirstLayout)
1230 {
1231     ScrollbarMode hMode;
1232     ScrollbarMode vMode;
1233     calculateScrollbarModesForLayout(hMode, vMode);
1234     if (isFirstLayout && !layoutContext().isLayoutNested()) {
1235         setScrollbarsSuppressed(true);
1236         // Set the initial vMode to AlwaysOn if we're auto.
1237         if (vMode == ScrollbarAuto)
1238             setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear.
1239         // Set the initial hMode to AlwaysOff if we're auto.
1240         if (hMode == ScrollbarAuto)
1241             setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear.
1242         ASSERT(frame().page());
1243         if (frame().page()->expectsWheelEventTriggers())
1244             scrollAnimator().setWheelEventTestTrigger(frame().page()->testTrigger());
1245         setScrollbarModes(hMode, vMode);
1246         setScrollbarsSuppressed(false, true);
1247     } else if (hMode != horizontalScrollbarMode() || vMode != verticalScrollbarMode())
1248         setScrollbarModes(hMode, vMode);
1249 }
1250
1251 void FrameView::willDoLayout(WeakPtr<RenderElement> layoutRoot)
1252 {
1253     bool subtreeLayout = !is<RenderView>(*layoutRoot);
1254     if (subtreeLayout)
1255         return;
1256     
1257     if (auto* body = frame().document()->bodyOrFrameset()) {
1258         if (is<HTMLFrameSetElement>(*body) && !frameFlatteningEnabled() && body->renderer())
1259             body->renderer()->setChildNeedsLayout();
1260     }
1261     auto firstLayout = !layoutContext().didFirstLayout();
1262     if (firstLayout) {
1263         m_lastViewportSize = sizeForResizeEvent();
1264         m_lastZoomFactor = layoutRoot->style().zoom();
1265         m_firstLayoutCallbackPending = true;
1266     }
1267     adjustScrollbarsForLayout(firstLayout);
1268         
1269     auto oldSize = m_size;
1270     LayoutSize newSize = layoutSize();
1271     if (oldSize != newSize) {
1272         m_size = newSize;
1273         LOG(Layout, "  layout size changed from %.3fx%.3f to %.3fx%.3f", oldSize.width().toFloat(), oldSize.height().toFloat(),     newSize.width().toFloat(), newSize.height().toFloat());
1274         layoutContext().setNeedsFullRepaint();
1275         if (!firstLayout)
1276             markRootOrBodyRendererDirty();
1277     }
1278     forceLayoutParentViewIfNeeded();
1279 }
1280
1281 void FrameView::didLayout(WeakPtr<RenderElement> layoutRoot)
1282 {
1283     renderView()->releaseProtectedRenderWidgets();
1284     auto* layoutRootEnclosingLayer = layoutRoot->enclosingLayer();
1285     layoutRootEnclosingLayer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layoutRootEnclosingLayer, !is<RenderView>(*layoutRoot), layoutContext().needsFullRepaint()));
1286
1287     updateCompositingLayersAfterLayout();
1288
1289 #if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK)
1290     if (auto* cache = frame().document()->existingAXObjectCache())
1291         cache->postNotification(layoutRoot.get(), AXObjectCache::AXLayoutComplete);
1292 #endif
1293
1294 #if ENABLE(DASHBOARD_SUPPORT)
1295     updateAnnotatedRegions();
1296 #endif
1297
1298 #if ENABLE(IOS_TOUCH_EVENTS)
1299     frame().document()->setTouchEventRegionsNeedUpdate();
1300 #endif
1301
1302     updateCanBlitOnScrollRecursively();
1303
1304     handleDeferredScrollUpdateAfterContentSizeChange();
1305
1306     handleDeferredScrollbarsUpdateAfterDirectionChange();
1307
1308     if (frame().document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1309         updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight());
1310
1311     frame().document()->markers().invalidateRectsForAllMarkers();
1312 }
1313
1314 bool FrameView::shouldDeferScrollUpdateAfterContentSizeChange()
1315 {
1316     return (layoutContext().layoutPhase() < FrameViewLayoutContext::LayoutPhase::InPostLayout) && (layoutContext().layoutPhase() != FrameViewLayoutContext::LayoutPhase::OutsideLayout);
1317 }
1318
1319 RenderBox* FrameView::embeddedContentBox() const
1320 {
1321     RenderView* renderView = this->renderView();
1322     if (!renderView)
1323         return nullptr;
1324
1325     RenderObject* firstChild = renderView->firstChild();
1326
1327     // Curently only embedded SVG documents participate in the size-negotiation logic.
1328     if (is<RenderSVGRoot>(firstChild))
1329         return downcast<RenderSVGRoot>(firstChild);
1330
1331     return nullptr;
1332 }
1333
1334 void FrameView::addEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1335 {
1336     if (!m_embeddedObjectsToUpdate)
1337         m_embeddedObjectsToUpdate = std::make_unique<ListHashSet<RenderEmbeddedObject*>>();
1338
1339     HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
1340     if (is<HTMLObjectElement>(element) || is<HTMLEmbedElement>(element)) {
1341         // Tell the DOM element that it needs a widget update.
1342         HTMLPlugInImageElement& pluginElement = downcast<HTMLPlugInImageElement>(element);
1343         if (!pluginElement.needsCheckForSizeChange())
1344             pluginElement.setNeedsWidgetUpdate(true);
1345     }
1346
1347     m_embeddedObjectsToUpdate->add(&embeddedObject);
1348 }
1349
1350 void FrameView::removeEmbeddedObjectToUpdate(RenderEmbeddedObject& embeddedObject)
1351 {
1352     if (!m_embeddedObjectsToUpdate)
1353         return;
1354
1355     m_embeddedObjectsToUpdate->remove(&embeddedObject);
1356 }
1357
1358 void FrameView::setMediaType(const String& mediaType)
1359 {
1360     m_mediaType = mediaType;
1361 }
1362
1363 String FrameView::mediaType() const
1364 {
1365     // See if we have an override type.
1366     String overrideType = frame().loader().client().overrideMediaType();
1367     InspectorInstrumentation::applyEmulatedMedia(frame(), overrideType);
1368     if (!overrideType.isNull())
1369         return overrideType;
1370     return m_mediaType;
1371 }
1372
1373 void FrameView::adjustMediaTypeForPrinting(bool printing)
1374 {
1375     if (printing) {
1376         if (m_mediaTypeWhenNotPrinting.isNull())
1377             m_mediaTypeWhenNotPrinting = mediaType();
1378         setMediaType("print");
1379     } else {
1380         if (!m_mediaTypeWhenNotPrinting.isNull())
1381             setMediaType(m_mediaTypeWhenNotPrinting);
1382         m_mediaTypeWhenNotPrinting = String();
1383     }
1384 }
1385
1386 bool FrameView::useSlowRepaints(bool considerOverlap) const
1387 {
1388     bool mustBeSlow = hasSlowRepaintObjects() || (platformWidget() && hasViewportConstrainedObjects());
1389
1390     // FIXME: WidgetMac.mm makes the assumption that useSlowRepaints ==
1391     // m_contentIsOpaque, so don't take the fast path for composited layers
1392     // if they are a platform widget in order to get painting correctness
1393     // for transparent layers. See the comment in WidgetMac::paint.
1394     if (usesCompositedScrolling() && !platformWidget())
1395         return mustBeSlow;
1396
1397     bool isOverlapped = m_isOverlapped && considerOverlap;
1398
1399     if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque)
1400         return true;
1401
1402     if (FrameView* parentView = parentFrameView())
1403         return parentView->useSlowRepaints(considerOverlap);
1404
1405     return false;
1406 }
1407
1408 bool FrameView::useSlowRepaintsIfNotOverlapped() const
1409 {
1410     return useSlowRepaints(false);
1411 }
1412
1413 void FrameView::updateCanBlitOnScrollRecursively()
1414 {
1415     for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr())) {
1416         if (FrameView* view = frame->view())
1417             view->setCanBlitOnScroll(!view->useSlowRepaints());
1418     }
1419 }
1420
1421 bool FrameView::usesCompositedScrolling() const
1422 {
1423     RenderView* renderView = this->renderView();
1424     if (renderView && renderView->isComposited()) {
1425         GraphicsLayer* layer = renderView->layer()->backing()->graphicsLayer();
1426         if (layer && layer->drawsContent())
1427             return true;
1428     }
1429
1430     return false;
1431 }
1432
1433 bool FrameView::usesAsyncScrolling() const
1434 {
1435 #if ENABLE(ASYNC_SCROLLING)
1436     if (Page* page = frame().page()) {
1437         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1438             return scrollingCoordinator->coordinatesScrollingForFrameView(*this);
1439     }
1440 #endif
1441     return false;
1442 }
1443
1444 bool FrameView::usesMockScrollAnimator() const
1445 {
1446     return DeprecatedGlobalSettings::usesMockScrollAnimator();
1447 }
1448
1449 void FrameView::logMockScrollAnimatorMessage(const String& message) const
1450 {
1451     Document* document = frame().document();
1452     if (!document)
1453         return;
1454     StringBuilder builder;
1455     if (frame().isMainFrame())
1456         builder.appendLiteral("Main");
1457     builder.appendLiteral("FrameView: ");
1458     builder.append(message);
1459     document->addConsoleMessage(MessageSource::Other, MessageLevel::Debug, builder.toString());
1460 }
1461
1462 void FrameView::setCannotBlitToWindow()
1463 {
1464     m_cannotBlitToWindow = true;
1465     updateCanBlitOnScrollRecursively();
1466 }
1467
1468 void FrameView::addSlowRepaintObject(RenderElement& renderer)
1469 {
1470     bool hadSlowRepaintObjects = hasSlowRepaintObjects();
1471
1472     if (!m_slowRepaintObjects)
1473         m_slowRepaintObjects = std::make_unique<HashSet<const RenderElement*>>();
1474
1475     m_slowRepaintObjects->add(&renderer);
1476     if (hadSlowRepaintObjects)
1477         return;
1478
1479     updateCanBlitOnScrollRecursively();
1480
1481     if (auto* page = frame().page()) {
1482         if (auto* scrollingCoordinator = page->scrollingCoordinator())
1483             scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(*this);
1484     }
1485 }
1486
1487 void FrameView::removeSlowRepaintObject(RenderElement& renderer)
1488 {
1489     if (!m_slowRepaintObjects)
1490         return;
1491
1492     m_slowRepaintObjects->remove(&renderer);
1493     if (!m_slowRepaintObjects->isEmpty())
1494         return;
1495
1496     m_slowRepaintObjects = nullptr;
1497     updateCanBlitOnScrollRecursively();
1498
1499     if (auto* page = frame().page()) {
1500         if (auto* scrollingCoordinator = page->scrollingCoordinator())
1501             scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(*this);
1502     }
1503 }
1504
1505 void FrameView::addViewportConstrainedObject(RenderElement* object)
1506 {
1507     if (!m_viewportConstrainedObjects)
1508         m_viewportConstrainedObjects = std::make_unique<ViewportConstrainedObjectSet>();
1509
1510     if (!m_viewportConstrainedObjects->contains(object)) {
1511         m_viewportConstrainedObjects->add(object);
1512         if (platformWidget())
1513             updateCanBlitOnScrollRecursively();
1514
1515         if (Page* page = frame().page()) {
1516             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1517                 scrollingCoordinator->frameViewFixedObjectsDidChange(*this);
1518         }
1519     }
1520 }
1521
1522 void FrameView::removeViewportConstrainedObject(RenderElement* object)
1523 {
1524     if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->remove(object)) {
1525         if (Page* page = frame().page()) {
1526             if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
1527                 scrollingCoordinator->frameViewFixedObjectsDidChange(*this);
1528         }
1529
1530         // FIXME: In addFixedObject() we only call this if there's a platform widget,
1531         // why isn't the same check being made here?
1532         updateCanBlitOnScrollRecursively();
1533     }
1534 }
1535
1536 LayoutSize FrameView::expandedLayoutViewportSize(const LayoutSize& baseLayoutViewportSize, const LayoutSize& documentSize, double heightExpansionFactor)
1537 {
1538     if (!heightExpansionFactor)
1539         return baseLayoutViewportSize;
1540
1541     auto documentHeight = documentSize.height();
1542     auto layoutViewportHeight = baseLayoutViewportSize.height();
1543     if (layoutViewportHeight > documentHeight)
1544         return baseLayoutViewportSize;
1545
1546     return { baseLayoutViewportSize.width(), std::min<LayoutUnit>(documentHeight, (1 + heightExpansionFactor) * layoutViewportHeight) };
1547 }
1548
1549 LayoutRect FrameView::computeUpdatedLayoutViewportRect(const LayoutRect& layoutViewport, const LayoutRect& documentRect, const LayoutSize& unobscuredContentSize, const LayoutRect& unobscuredContentRect, const LayoutSize& baseLayoutViewportSize, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, LayoutViewportConstraint constraint)
1550 {
1551     LayoutRect layoutViewportRect = layoutViewport;
1552     
1553     // The layout viewport is never smaller than baseLayoutViewportSize, and never be smaller than the unobscuredContentRect.
1554     LayoutSize constrainedSize = baseLayoutViewportSize;
1555     layoutViewportRect.setSize(constrainedSize.expandedTo(unobscuredContentSize));
1556         
1557     LayoutPoint layoutViewportOrigin = computeLayoutViewportOrigin(unobscuredContentRect, stableLayoutViewportOriginMin, stableLayoutViewportOriginMax, layoutViewportRect, StickToViewportBounds);
1558
1559     // FIXME: Is this equivalent to calling computeLayoutViewportOrigin() with StickToDocumentBounds?
1560     if (constraint == LayoutViewportConstraint::ConstrainedToDocumentRect) {
1561         // The max stable layout viewport origin really depends on the size of the layout viewport itself, so we need to adjust the location of the layout viewport one final time to make sure it does not end up out of bounds of the document.
1562         // Without this adjustment (and with using the non-constrained unobscuredContentRect's size as the size of the layout viewport) the layout viewport can be pushed past the bounds of the document during rubber-banding, and cannot be pushed
1563         // back in until the user scrolls back in the other direction.
1564         layoutViewportOrigin.setX(clampTo<float>(layoutViewportOrigin.x(), 0, documentRect.width() - layoutViewportRect.width()));
1565         layoutViewportOrigin.setY(clampTo<float>(layoutViewportOrigin.y(), 0, documentRect.height() - layoutViewportRect.height()));
1566     }
1567     layoutViewportRect.setLocation(layoutViewportOrigin);
1568     
1569     return layoutViewportRect;
1570 }
1571
1572 // visualViewport and layoutViewport are both in content coordinates (unzoomed).
1573 LayoutPoint FrameView::computeLayoutViewportOrigin(const LayoutRect& visualViewport, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, const LayoutRect& layoutViewport, ScrollBehaviorForFixedElements fixedBehavior)
1574 {
1575     LayoutPoint layoutViewportOrigin = layoutViewport.location();
1576     bool allowRubberBanding = fixedBehavior == StickToViewportBounds;
1577
1578     if (visualViewport.width() > layoutViewport.width()) {
1579         layoutViewportOrigin.setX(visualViewport.x());
1580         if (!allowRubberBanding) {
1581             if (layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
1582                 layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
1583             else if (layoutViewportOrigin.x() > stableLayoutViewportOriginMax.x())
1584                 layoutViewportOrigin.setX(stableLayoutViewportOriginMax.x());
1585         }
1586     } else {
1587         bool rubberbandingAtLeft = allowRubberBanding && visualViewport.x() < stableLayoutViewportOriginMin.x();
1588         bool rubberbandingAtRight = allowRubberBanding && (visualViewport.maxX() - layoutViewport.width()) > stableLayoutViewportOriginMax.x();
1589
1590         if (visualViewport.x() < layoutViewport.x() || rubberbandingAtLeft)
1591             layoutViewportOrigin.setX(visualViewport.x());
1592
1593         if (visualViewport.maxX() > layoutViewport.maxX() || rubberbandingAtRight)
1594             layoutViewportOrigin.setX(visualViewport.maxX() - layoutViewport.width());
1595
1596         if (!rubberbandingAtLeft && layoutViewportOrigin.x() < stableLayoutViewportOriginMin.x())
1597             layoutViewportOrigin.setX(stableLayoutViewportOriginMin.x());
1598         
1599         if (!rubberbandingAtRight && layoutViewportOrigin.x() > stableLayoutViewportOriginMax.x())
1600             layoutViewportOrigin.setX(stableLayoutViewportOriginMax.x());
1601     }
1602
1603     if (visualViewport.height() > layoutViewport.height()) {
1604         layoutViewportOrigin.setY(visualViewport.y());
1605         if (!allowRubberBanding) {
1606             if (layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
1607                 layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
1608             else if (layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
1609                 layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
1610         }
1611     } else {
1612         bool rubberbandingAtTop = allowRubberBanding && visualViewport.y() < stableLayoutViewportOriginMin.y();
1613         bool rubberbandingAtBottom = allowRubberBanding && (visualViewport.maxY() - layoutViewport.height()) > stableLayoutViewportOriginMax.y();
1614
1615         if (visualViewport.y() < layoutViewport.y() || rubberbandingAtTop)
1616             layoutViewportOrigin.setY(visualViewport.y());
1617
1618         if (visualViewport.maxY() > layoutViewport.maxY() || rubberbandingAtBottom)
1619             layoutViewportOrigin.setY(visualViewport.maxY() - layoutViewport.height());
1620
1621         if (!rubberbandingAtTop && layoutViewportOrigin.y() < stableLayoutViewportOriginMin.y())
1622             layoutViewportOrigin.setY(stableLayoutViewportOriginMin.y());
1623
1624         if (!rubberbandingAtBottom && layoutViewportOrigin.y() > stableLayoutViewportOriginMax.y())
1625             layoutViewportOrigin.setY(stableLayoutViewportOriginMax.y());
1626     }
1627
1628     return layoutViewportOrigin;
1629 }
1630
1631 void FrameView::setBaseLayoutViewportOrigin(LayoutPoint origin, TriggerLayoutOrNot layoutTriggering)
1632 {
1633     ASSERT(frame().settings().visualViewportEnabled());
1634
1635     if (origin == m_layoutViewportOrigin)
1636         return;
1637
1638     m_layoutViewportOrigin = origin;
1639     if (layoutTriggering == TriggerLayoutOrNot::Yes)
1640         setViewportConstrainedObjectsNeedLayout();
1641     
1642     if (TiledBacking* tiledBacking = this->tiledBacking()) {
1643         FloatRect layoutViewport = layoutViewportRect();
1644         layoutViewport.moveBy(unscaledScrollOrigin()); // tiledBacking deals in top-left relative coordinates.
1645         tiledBacking->setLayoutViewportRect(layoutViewport);
1646     }
1647 }
1648
1649 void FrameView::setLayoutViewportOverrideRect(std::optional<LayoutRect> rect, TriggerLayoutOrNot layoutTriggering)
1650 {
1651     if (rect == m_layoutViewportOverrideRect)
1652         return;
1653
1654     LayoutRect oldRect = layoutViewportRect();
1655     m_layoutViewportOverrideRect = rect;
1656
1657     // Triggering layout on height changes is necessary to make bottom-fixed elements behave correctly.
1658     if (oldRect.height() != layoutViewportRect().height())
1659         layoutTriggering = TriggerLayoutOrNot::Yes;
1660
1661     LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " setLayoutViewportOverrideRect() - changing override layout viewport from " << oldRect << " to " << m_layoutViewportOverrideRect.value_or(LayoutRect()) << " layoutTriggering " << (layoutTriggering == TriggerLayoutOrNot::Yes ? "yes" : "no"));
1662
1663     if (oldRect != layoutViewportRect() && layoutTriggering == TriggerLayoutOrNot::Yes)
1664         setViewportConstrainedObjectsNeedLayout();
1665 }
1666
1667 void FrameView::setVisualViewportOverrideRect(std::optional<LayoutRect> rect)
1668 {
1669     m_visualViewportOverrideRect = rect;
1670 }
1671
1672 LayoutSize FrameView::baseLayoutViewportSize() const
1673 {
1674     return renderView() ? renderView()->size() : size();
1675 }
1676
1677 void FrameView::updateLayoutViewport()
1678 {
1679     if (!frame().settings().visualViewportEnabled())
1680         return;
1681     
1682     // Don't update the layout viewport if we're in the middle of adjusting scrollbars. We'll get another call
1683     // as a post-layout task.
1684     if (layoutContext().layoutPhase() == FrameViewLayoutContext::LayoutPhase::InViewSizeAdjust)
1685         return;
1686
1687     LayoutRect layoutViewport = layoutViewportRect();
1688
1689     LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport() totalContentSize " << totalContentsSize() << " unscaledDocumentRect " << (renderView() ? renderView()->unscaledDocumentRect() : IntRect()) << " header height " << headerHeight() << " footer height " << footerHeight() << " fixed behavior " << scrollBehaviorForFixedElements());
1690     LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
1691     LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewportRect() << " (is override " << (bool)m_visualViewportOverrideRect << ")");
1692     LOG_WITH_STREAM(Scrolling, stream << "stable origins: min: " << minStableLayoutViewportOrigin() << " max: "<< maxStableLayoutViewportOrigin());
1693     
1694     if (m_layoutViewportOverrideRect) {
1695         if (m_inProgrammaticScroll) {
1696             LOG_WITH_STREAM(Scrolling, stream << "computing new override layout viewport because of programmatic scrolling");
1697             LayoutPoint newOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, StickToDocumentBounds);
1698             setLayoutViewportOverrideRect(LayoutRect(newOrigin, m_layoutViewportOverrideRect.value().size()));
1699         }
1700         if (frame().settings().visualViewportAPIEnabled()) {
1701             if (Document* document = frame().document()) {
1702                 if (VisualViewport* visualViewport = document->domWindow()->visualViewport())
1703                     visualViewport->update();
1704             }
1705         }
1706         return;
1707     }
1708
1709     LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport, scrollBehaviorForFixedElements());
1710     if (newLayoutViewportOrigin != m_layoutViewportOrigin) {
1711         setBaseLayoutViewportOrigin(newLayoutViewportOrigin);
1712         LOG_WITH_STREAM(Scrolling, stream << "layoutViewport changed to " << layoutViewportRect());
1713     }
1714     if (frame().settings().visualViewportAPIEnabled()) {
1715         if (Document* document = frame().document()) {
1716             if (VisualViewport* visualViewport = document->domWindow()->visualViewport())
1717                 visualViewport->update();
1718         }
1719     }
1720 }
1721
1722 LayoutPoint FrameView::minStableLayoutViewportOrigin() const
1723 {
1724     return unscaledMinimumScrollPosition();
1725 }
1726
1727 LayoutPoint FrameView::maxStableLayoutViewportOrigin() const
1728 {
1729     LayoutPoint maxPosition = unscaledMaximumScrollPosition();
1730     maxPosition = (maxPosition - LayoutSize(0, headerHeight() + footerHeight())).expandedTo({ });
1731     return maxPosition;
1732 }
1733
1734 IntPoint FrameView::unscaledScrollOrigin() const
1735 {
1736     if (RenderView* renderView = this->renderView())
1737         return -renderView->unscaledDocumentRect().location(); // Akin to code in adjustViewSize().
1738
1739     return { };
1740 }
1741
1742 LayoutRect FrameView::layoutViewportRect() const
1743 {
1744     if (m_layoutViewportOverrideRect)
1745         return m_layoutViewportOverrideRect.value();
1746
1747     // Size of initial containing block, anchored at scroll position, in document coordinates (unchanged by scale factor).
1748     return LayoutRect(m_layoutViewportOrigin, baseLayoutViewportSize());
1749 }
1750
1751 // visibleContentRect is in the bounds of the scroll view content. That consists of an
1752 // optional header, the document, and an optional footer. Only the document is scaled,
1753 // so we have to compute the visible part of the document in unscaled document coordinates.
1754 // On iOS, pageScaleFactor is always 1 here, and we never have headers and footers.
1755 LayoutRect FrameView::visibleDocumentRect(const FloatRect& visibleContentRect, float headerHeight, float footerHeight, const FloatSize& totalContentsSize, float pageScaleFactor)
1756 {
1757     float contentsHeight = totalContentsSize.height() - headerHeight - footerHeight;
1758
1759     float rubberBandTop = std::min<float>(visibleContentRect.y(), 0);
1760     float visibleScaledDocumentTop = std::max<float>(visibleContentRect.y() - headerHeight, 0) + rubberBandTop;
1761     
1762     float rubberBandBottom = std::min<float>((totalContentsSize.height() - visibleContentRect.y()) - visibleContentRect.height(), 0);
1763     float visibleScaledDocumentBottom = std::min<float>(visibleContentRect.maxY() - headerHeight, contentsHeight) - rubberBandBottom;
1764
1765     FloatRect visibleDocumentRect = visibleContentRect;
1766     visibleDocumentRect.setY(visibleScaledDocumentTop);
1767     visibleDocumentRect.setHeight(std::max<float>(visibleScaledDocumentBottom - visibleScaledDocumentTop, 0));
1768     visibleDocumentRect.scale(1 / pageScaleFactor);
1769     
1770     return LayoutRect(visibleDocumentRect);
1771 }
1772
1773 LayoutRect FrameView::visualViewportRect() const
1774 {
1775     if (m_visualViewportOverrideRect)
1776         return m_visualViewportOverrideRect.value();
1777
1778     FloatRect visibleContentRect = this->visibleContentRect(LegacyIOSDocumentVisibleRect);
1779     return visibleDocumentRect(visibleContentRect, headerHeight(), footerHeight(), totalContentsSize(), frameScaleFactor());
1780 }
1781
1782 LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
1783 {
1784     ASSERT(!frame().settings().visualViewportEnabled());
1785
1786 #if PLATFORM(IOS)
1787     if (useCustomFixedPositionLayoutRect())
1788         return customFixedPositionLayoutRect();
1789 #endif
1790     LayoutRect viewportRect = visibleContentRect();
1791
1792     viewportRect.setLocation(scrollPositionForFixedPosition());
1793     return viewportRect;
1794 }
1795
1796 LayoutRect FrameView::rectForFixedPositionLayout() const
1797 {
1798     if (frame().settings().visualViewportEnabled())
1799         return layoutViewportRect();
1800
1801     return viewportConstrainedVisibleContentRect();
1802 }
1803
1804 float FrameView::frameScaleFactor() const
1805 {
1806     return frame().frameScaleFactor();
1807 }
1808
1809 LayoutPoint FrameView::scrollPositionForFixedPosition() const
1810 {
1811     if (frame().settings().visualViewportEnabled())
1812         return layoutViewportRect().location();
1813
1814     return scrollPositionForFixedPosition(visibleContentRect(), totalContentsSize(), scrollPosition(), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), scrollBehaviorForFixedElements(), headerHeight(), footerHeight());
1815 }
1816
1817 LayoutPoint FrameView::scrollPositionForFixedPosition(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements behaviorForFixed, int headerHeight, int footerHeight)
1818 {
1819     LayoutPoint position;
1820     if (behaviorForFixed == StickToDocumentBounds)
1821         position = ScrollableArea::constrainScrollPositionForOverhang(visibleContentRect, totalContentsSize, scrollPosition, scrollOrigin, headerHeight, footerHeight);
1822     else {
1823         position = scrollPosition;
1824         position.setY(position.y() - headerHeight);
1825     }
1826
1827     LayoutSize maxSize = totalContentsSize - visibleContentRect.size();
1828
1829     float dragFactorX = (fixedElementsLayoutRelativeToFrame || !maxSize.width()) ? 1 : (totalContentsSize.width() - visibleContentRect.width() * frameScaleFactor) / maxSize.width();
1830     float dragFactorY = (fixedElementsLayoutRelativeToFrame || !maxSize.height()) ? 1 : (totalContentsSize.height() - visibleContentRect.height() * frameScaleFactor) / maxSize.height();
1831
1832     return LayoutPoint(position.x() * dragFactorX / frameScaleFactor, position.y() * dragFactorY / frameScaleFactor);
1833 }
1834
1835 float FrameView::yPositionForInsetClipLayer(const FloatPoint& scrollPosition, float topContentInset)
1836 {
1837     if (!topContentInset)
1838         return 0;
1839
1840     // The insetClipLayer should not move for negative scroll values.
1841     float scrollY = std::max<float>(0, scrollPosition.y());
1842
1843     if (scrollY >= topContentInset)
1844         return 0;
1845
1846     return topContentInset - scrollY;
1847 }
1848
1849 float FrameView::yPositionForHeaderLayer(const FloatPoint& scrollPosition, float topContentInset)
1850 {
1851     if (!topContentInset)
1852         return 0;
1853
1854     float scrollY = std::max<float>(0, scrollPosition.y());
1855
1856     if (scrollY >= topContentInset)
1857         return topContentInset;
1858
1859     return scrollY;
1860 }
1861
1862 float FrameView::yPositionForFooterLayer(const FloatPoint& scrollPosition, float topContentInset, float totalContentsHeight, float footerHeight)
1863 {
1864     return yPositionForHeaderLayer(scrollPosition, topContentInset) + totalContentsHeight - footerHeight;
1865 }
1866
1867 FloatPoint FrameView::positionForRootContentLayer(const FloatPoint& scrollPosition, const FloatPoint& scrollOrigin, float topContentInset, float headerHeight)
1868 {
1869     return FloatPoint(0, yPositionForHeaderLayer(scrollPosition, topContentInset) + headerHeight) - toFloatSize(scrollOrigin);
1870 }
1871
1872 FloatPoint FrameView::positionForRootContentLayer() const
1873 {
1874     return positionForRootContentLayer(scrollPosition(), scrollOrigin(), topContentInset(), headerHeight());
1875 }
1876
1877 #if PLATFORM(IOS)
1878 LayoutRect FrameView::rectForViewportConstrainedObjects(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements scrollBehavior)
1879 {
1880     if (fixedElementsLayoutRelativeToFrame)
1881         return visibleContentRect;
1882     
1883     if (totalContentsSize.isEmpty())
1884         return visibleContentRect;
1885
1886     // We impose an lower limit on the size (so an upper limit on the scale) of
1887     // the rect used to position fixed objects so that they don't crowd into the
1888     // center of the screen at larger scales.
1889     const LayoutUnit maxContentWidthForZoomThreshold = LayoutUnit::fromPixel(1024);
1890     float zoomedOutScale = frameScaleFactor * visibleContentRect.width() / std::min(maxContentWidthForZoomThreshold, totalContentsSize.width());
1891     float constraintThresholdScale = 1.5 * zoomedOutScale;
1892     float maxPostionedObjectsRectScale = std::min(frameScaleFactor, constraintThresholdScale);
1893
1894     LayoutRect viewportConstrainedObjectsRect = visibleContentRect;
1895
1896     if (frameScaleFactor > constraintThresholdScale) {
1897         FloatRect contentRect(FloatPoint(), totalContentsSize);
1898         FloatRect viewportRect = visibleContentRect;
1899         
1900         // Scale the rect up from a point that is relative to its position in the viewport.
1901         FloatSize sizeDelta = contentRect.size() - viewportRect.size();
1902
1903         FloatPoint scaleOrigin;
1904         scaleOrigin.setX(contentRect.x() + sizeDelta.width() > 0 ? contentRect.width() * (viewportRect.x() - contentRect.x()) / sizeDelta.width() : 0);
1905         scaleOrigin.setY(contentRect.y() + sizeDelta.height() > 0 ? contentRect.height() * (viewportRect.y() - contentRect.y()) / sizeDelta.height() : 0);
1906         
1907         AffineTransform rescaleTransform = AffineTransform::translation(scaleOrigin.x(), scaleOrigin.y());
1908         rescaleTransform.scale(frameScaleFactor / maxPostionedObjectsRectScale, frameScaleFactor / maxPostionedObjectsRectScale);
1909         rescaleTransform = CGAffineTransformTranslate(rescaleTransform, -scaleOrigin.x(), -scaleOrigin.y());
1910
1911         viewportConstrainedObjectsRect = enclosingLayoutRect(rescaleTransform.mapRect(visibleContentRect));
1912     }
1913     
1914     if (scrollBehavior == StickToDocumentBounds) {
1915         LayoutRect documentBounds(LayoutPoint(), totalContentsSize);
1916         viewportConstrainedObjectsRect.intersect(documentBounds);
1917     }
1918
1919     return viewportConstrainedObjectsRect;
1920 }
1921     
1922 LayoutRect FrameView::viewportConstrainedObjectsRect() const
1923 {
1924     return rectForViewportConstrainedObjects(visibleContentRect(), totalContentsSize(), frame().frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), scrollBehaviorForFixedElements());
1925 }
1926 #endif
1927     
1928 ScrollPosition FrameView::minimumScrollPosition() const
1929 {
1930     ScrollPosition minimumPosition = ScrollView::minimumScrollPosition();
1931
1932     if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
1933         minimumPosition.setY(maximumScrollPosition().y());
1934     
1935     return minimumPosition;
1936 }
1937
1938 ScrollPosition FrameView::maximumScrollPosition() const
1939 {
1940     ScrollPosition maximumPosition = ScrollView::maximumScrollPosition();
1941
1942     if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
1943         maximumPosition.setY(minimumScrollPosition().y());
1944     
1945     return maximumPosition;
1946 }
1947
1948 ScrollPosition FrameView::unscaledMinimumScrollPosition() const
1949 {
1950     if (RenderView* renderView = this->renderView()) {
1951         IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
1952         ScrollPosition minimumPosition = unscaledDocumentRect.location();
1953
1954         if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
1955             minimumPosition.setY(unscaledMaximumScrollPosition().y());
1956
1957         return minimumPosition;
1958     }
1959
1960     return minimumScrollPosition();
1961 }
1962
1963 ScrollPosition FrameView::unscaledMaximumScrollPosition() const
1964 {
1965     if (RenderView* renderView = this->renderView()) {
1966         IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
1967         unscaledDocumentRect.expand(0, headerHeight() + footerHeight());
1968         ScrollPosition maximumPosition = ScrollPosition(unscaledDocumentRect.maxXMaxYCorner() - visibleSize()).expandedTo({ 0, 0 });
1969         if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
1970             maximumPosition.setY(unscaledMinimumScrollPosition().y());
1971
1972         return maximumPosition;
1973     }
1974
1975     return maximumScrollPosition();
1976 }
1977
1978 void FrameView::viewportContentsChanged()
1979 {
1980     if (!frame().view()) {
1981         // The frame is being destroyed.
1982         return;
1983     }
1984
1985     if (auto* page = frame().page())
1986         page->updateValidationBubbleStateIfNeeded();
1987
1988     // When the viewport contents changes (scroll, resize, style recalc, layout, ...),
1989     // check if we should resume animated images or unthrottle DOM timers.
1990     applyRecursivelyWithVisibleRect([] (FrameView& frameView, const IntRect& visibleRect) {
1991         frameView.resumeVisibleImageAnimations(visibleRect);
1992         frameView.updateScriptedAnimationsAndTimersThrottlingState(visibleRect);
1993
1994         if (auto* renderView = frameView.frame().contentRenderer())
1995             renderView->updateVisibleViewportRect(visibleRect);
1996     });
1997 }
1998
1999 bool FrameView::fixedElementsLayoutRelativeToFrame() const
2000 {
2001     return frame().settings().fixedElementsLayoutRelativeToFrame();
2002 }
2003
2004 IntPoint FrameView::lastKnownMousePosition() const
2005 {
2006     return frame().eventHandler().lastKnownMousePosition();
2007 }
2008
2009 bool FrameView::isHandlingWheelEvent() const
2010 {
2011     return frame().eventHandler().isHandlingWheelEvent();
2012 }
2013
2014 bool FrameView::shouldSetCursor() const
2015 {
2016     Page* page = frame().page();
2017     return page && page->isVisible() && page->focusController().isActive();
2018 }
2019
2020 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
2021 {
2022     if (!m_viewportConstrainedObjects || m_viewportConstrainedObjects->isEmpty()) {
2023         frame().page()->chrome().scroll(scrollDelta, rectToScroll, clipRect);
2024         return true;
2025     }
2026
2027     bool isCompositedContentLayer = usesCompositedScrolling();
2028
2029     // Get the rects of the fixed objects visible in the rectToScroll
2030     Region regionToUpdate;
2031     for (auto& renderer : *m_viewportConstrainedObjects) {
2032         if (!renderer->style().hasViewportConstrainedPosition())
2033             continue;
2034         if (renderer->isComposited())
2035             continue;
2036
2037         // Fixed items should always have layers.
2038         ASSERT(renderer->hasLayer());
2039         RenderLayer* layer = downcast<RenderBoxModelObject>(*renderer).layer();
2040
2041         if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView
2042             || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) {
2043             // Don't invalidate for invisible fixed layers.
2044             continue;
2045         }
2046
2047         if (layer->hasAncestorWithFilterOutsets()) {
2048             // If the fixed layer has a blur/drop-shadow filter applied on at least one of its parents, we cannot 
2049             // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
2050             return false;
2051         }
2052
2053         // FIXME: use pixel snapping instead of enclosing when ScrollView has finished transitioning from IntRect to Float/LayoutRect.
2054         IntRect updateRect = enclosingIntRect(layer->repaintRectIncludingNonCompositingDescendants());
2055         updateRect = contentsToRootView(updateRect);
2056         if (!isCompositedContentLayer)
2057             updateRect.intersect(rectToScroll);
2058         if (!updateRect.isEmpty())
2059             regionToUpdate.unite(updateRect);
2060     }
2061
2062     // 1) scroll
2063     frame().page()->chrome().scroll(scrollDelta, rectToScroll, clipRect);
2064
2065     // 2) update the area of fixed objects that has been invalidated
2066     for (auto& updateRect : regionToUpdate.rects()) {
2067         IntRect scrolledRect = updateRect;
2068         scrolledRect.move(scrollDelta);
2069         updateRect.unite(scrolledRect);
2070         if (isCompositedContentLayer) {
2071             updateRect = rootViewToContents(updateRect);
2072             ASSERT(renderView());
2073             renderView()->layer()->setBackingNeedsRepaintInRect(updateRect);
2074             continue;
2075         }
2076         updateRect.intersect(rectToScroll);
2077         frame().page()->chrome().invalidateContentsAndRootView(updateRect);
2078     }
2079
2080     return true;
2081 }
2082
2083 void FrameView::scrollContentsSlowPath(const IntRect& updateRect)
2084 {
2085     repaintSlowRepaintObjects();
2086
2087     if (!usesCompositedScrolling() && isEnclosedInCompositingLayer()) {
2088         if (RenderWidget* frameRenderer = frame().ownerRenderer()) {
2089             LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(), frameRenderer->borderTop() + frameRenderer->paddingTop(),
2090                 visibleWidth(), visibleHeight());
2091             frameRenderer->repaintRectangle(rect);
2092             return;
2093         }
2094     }
2095
2096     ScrollView::scrollContentsSlowPath(updateRect);
2097 }
2098
2099 void FrameView::repaintSlowRepaintObjects()
2100 {
2101     if (!m_slowRepaintObjects)
2102         return;
2103
2104     // Renderers with fixed backgrounds may be in compositing layers, so we need to explicitly
2105     // repaint them after scrolling.
2106     for (auto& renderer : *m_slowRepaintObjects)
2107         renderer->repaintSlowRepaintObject();
2108 }
2109
2110 // Note that this gets called at painting time.
2111 void FrameView::setIsOverlapped(bool isOverlapped)
2112 {
2113     if (isOverlapped == m_isOverlapped)
2114         return;
2115
2116     m_isOverlapped = isOverlapped;
2117     updateCanBlitOnScrollRecursively();
2118 }
2119
2120 void FrameView::setContentIsOpaque(bool contentIsOpaque)
2121 {
2122     if (contentIsOpaque == m_contentIsOpaque)
2123         return;
2124
2125     m_contentIsOpaque = contentIsOpaque;
2126     updateCanBlitOnScrollRecursively();
2127 }
2128
2129 void FrameView::restoreScrollbar()
2130 {
2131     setScrollbarsSuppressed(false);
2132 }
2133
2134 bool FrameView::scrollToFragment(const URL& url)
2135 {
2136     String fragmentIdentifier = url.fragmentIdentifier();
2137     if (scrollToAnchor(fragmentIdentifier))
2138         return true;
2139
2140     // Try again after decoding the ref, based on the document's encoding.
2141     if (TextResourceDecoder* decoder = frame().document()->decoder()) {
2142         if (scrollToAnchor(decodeURLEscapeSequences(fragmentIdentifier, decoder->encoding())))
2143             return true;
2144     }
2145
2146     resetScrollAnchor();
2147     return false;
2148 }
2149
2150 bool FrameView::scrollToAnchor(const String& fragmentIdentifier)
2151 {
2152     LOG(Scrolling, "FrameView::scrollToAnchor %s", fragmentIdentifier.utf8().data());
2153
2154     // If our URL has no ref, then we have no place we need to jump to.
2155     if (fragmentIdentifier.isNull())
2156         return false;
2157
2158     ASSERT(frame().document());
2159     auto& document = *frame().document();
2160
2161     if (!document.haveStylesheetsLoaded()) {
2162         document.setGotoAnchorNeededAfterStylesheetsLoad(true);
2163         return false;
2164     }
2165
2166     document.setGotoAnchorNeededAfterStylesheetsLoad(false);
2167
2168     Element* anchorElement = document.findAnchor(fragmentIdentifier);
2169
2170     LOG(Scrolling, " anchorElement is %p", anchorElement);
2171
2172     // Setting to null will clear the current target.
2173     document.setCSSTarget(anchorElement);
2174
2175     if (is<SVGDocument>(document)) {
2176         if (fragmentIdentifier.isEmpty())
2177             return false;
2178         if (auto rootElement = SVGDocument::rootElement(document)) {
2179             if (rootElement->scrollToFragment(fragmentIdentifier))
2180                 return true;
2181             // If SVG failed to scrollToAnchor() and anchorElement is null, no other scrolling will be possible.
2182             if (!anchorElement)
2183                 return false;
2184         }
2185     } else if (!anchorElement && !(fragmentIdentifier.isEmpty() || equalLettersIgnoringASCIICase(fragmentIdentifier, "top"))) {
2186         // Implement the rule that "" and "top" both mean top of page as in other browsers.
2187         return false;
2188     }
2189
2190     ContainerNode* scrollPositionAnchor = anchorElement;
2191     if (!scrollPositionAnchor)
2192         scrollPositionAnchor = frame().document();
2193     maintainScrollPositionAtAnchor(scrollPositionAnchor);
2194     
2195     // If the anchor accepts keyboard focus, move focus there to aid users relying on keyboard navigation.
2196     if (anchorElement) {
2197         if (anchorElement->isFocusable())
2198             document.setFocusedElement(anchorElement);
2199         else {
2200             document.setFocusedElement(nullptr);
2201             document.setFocusNavigationStartingNode(anchorElement);
2202         }
2203     }
2204     
2205     return true;
2206 }
2207
2208 void FrameView::maintainScrollPositionAtAnchor(ContainerNode* anchorNode)
2209 {
2210     LOG(Scrolling, "FrameView::maintainScrollPositionAtAnchor at %p", anchorNode);
2211
2212     m_maintainScrollPositionAnchor = anchorNode;
2213     if (!m_maintainScrollPositionAnchor)
2214         return;
2215     m_shouldScrollToFocusedElement = false;
2216     m_delayedScrollToFocusedElementTimer.stop();
2217
2218     // We need to update the layout before scrolling, otherwise we could
2219     // really mess things up if an anchor scroll comes at a bad moment.
2220     frame().document()->updateStyleIfNeeded();
2221     // Only do a layout if changes have occurred that make it necessary.
2222     RenderView* renderView = this->renderView();
2223     if (renderView && renderView->needsLayout())
2224         layoutContext().layout();
2225     else
2226         scrollToAnchor();
2227 }
2228
2229 void FrameView::scrollElementToRect(const Element& element, const IntRect& rect)
2230 {
2231     frame().document()->updateLayoutIgnorePendingStylesheets();
2232
2233     LayoutRect bounds;
2234     if (RenderElement* renderer = element.renderer())
2235         bounds = renderer->absoluteAnchorRect();
2236     int centeringOffsetX = (rect.width() - bounds.width()) / 2;
2237     int centeringOffsetY = (rect.height() - bounds.height()) / 2;
2238     setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y()));
2239 }
2240
2241 void FrameView::setScrollPosition(const ScrollPosition& scrollPosition)
2242 {
2243     LOG_WITH_STREAM(Scrolling, stream << "FrameView::setScrollPosition " << scrollPosition << " , clearing anchor");
2244
2245     SetForScope<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
2246     m_maintainScrollPositionAnchor = nullptr;
2247     m_shouldScrollToFocusedElement = false;
2248     m_delayedScrollToFocusedElementTimer.stop();
2249     Page* page = frame().page();
2250     if (page && page->expectsWheelEventTriggers())
2251         scrollAnimator().setWheelEventTestTrigger(page->testTrigger());
2252     ScrollView::setScrollPosition(scrollPosition);
2253 }
2254
2255 void FrameView::resetScrollAnchor()
2256 {
2257     ASSERT(frame().document());
2258     auto& document = *frame().document();
2259
2260     // If CSS target was set previously, we want to set it to 0, recalc
2261     // and possibly repaint because :target pseudo class may have been
2262     // set (see bug 11321).
2263     document.setCSSTarget(nullptr);
2264
2265     if (is<SVGDocument>(document)) {
2266         if (auto rootElement = SVGDocument::rootElement(document)) {
2267             // We need to update the layout before resetScrollAnchor(), otherwise we
2268             // could really mess things up if resetting the anchor comes at a bad moment.
2269             document.updateStyleIfNeeded();
2270             rootElement->resetScrollAnchor();
2271         }
2272     }
2273 }
2274
2275 void FrameView::scheduleScrollToFocusedElement(SelectionRevealMode selectionRevealMode)
2276 {
2277     if (selectionRevealMode == SelectionRevealMode::DoNotReveal)
2278         return;
2279
2280     m_selectionRevealModeForFocusedElement = selectionRevealMode;
2281     if (m_shouldScrollToFocusedElement)
2282         return;
2283     m_shouldScrollToFocusedElement = true;
2284     m_delayedScrollToFocusedElementTimer.startOneShot(0_s);
2285 }
2286
2287 void FrameView::scrollToFocusedElementImmediatelyIfNeeded()
2288 {
2289     if (!m_shouldScrollToFocusedElement)
2290         return;
2291
2292     m_delayedScrollToFocusedElementTimer.stop();
2293     scrollToFocusedElementInternal();
2294 }
2295
2296 void FrameView::scrollToFocusedElementTimerFired()
2297 {
2298     scrollToFocusedElementInternal();
2299 }
2300
2301 void FrameView::scrollToFocusedElementInternal()
2302 {
2303     RELEASE_ASSERT(m_shouldScrollToFocusedElement);
2304     auto document = makeRefPtr(frame().document());
2305     if (!document)
2306         return;
2307
2308     document->updateLayoutIgnorePendingStylesheets();
2309     if (!m_shouldScrollToFocusedElement)
2310         return; // Updating the layout may have ran scripts.
2311     m_shouldScrollToFocusedElement = false;
2312
2313     auto focusedElement = makeRefPtr(document->focusedElement());
2314     if (!focusedElement)
2315         return;
2316     auto updateTarget = focusedElement->focusAppearanceUpdateTarget();
2317     if (!updateTarget)
2318         return;
2319
2320     auto* renderer = updateTarget->renderer();
2321     if (!renderer || renderer->isWidget())
2322         return;
2323
2324     bool insideFixed;
2325     LayoutRect absoluteBounds = renderer->absoluteAnchorRect(&insideFixed);
2326     renderer->scrollRectToVisible(m_selectionRevealModeForFocusedElement, absoluteBounds, insideFixed);
2327 }
2328
2329 void FrameView::contentsResized()
2330 {
2331     // For non-delegated scrolling, updateTiledBackingAdaptiveSizing() is called via addedOrRemovedScrollbar() which occurs less often.
2332     if (delegatesScrolling())
2333         updateTiledBackingAdaptiveSizing();
2334 }
2335
2336 void FrameView::delegatesScrollingDidChange()
2337 {
2338     // When we switch to delgatesScrolling mode, we should destroy the scrolling/clipping layers in RenderLayerCompositor.
2339     if (hasCompositedContent())
2340         clearBackingStores();
2341 }
2342
2343 #if USE(COORDINATED_GRAPHICS)
2344 void FrameView::setFixedVisibleContentRect(const IntRect& visibleContentRect)
2345 {
2346     bool visibleContentSizeDidChange = false;
2347     if (visibleContentRect.size() != this->fixedVisibleContentRect().size()) {
2348         // When the viewport size changes or the content is scaled, we need to
2349         // reposition the fixed and sticky positioned elements.
2350         setViewportConstrainedObjectsNeedLayout();
2351         visibleContentSizeDidChange = true;
2352     }
2353
2354     IntPoint oldPosition = scrollPosition();
2355     ScrollView::setFixedVisibleContentRect(visibleContentRect);
2356     IntPoint newPosition = scrollPosition();
2357     if (oldPosition != newPosition) {
2358         updateLayerPositionsAfterScrolling();
2359         if (frame().settings().acceleratedCompositingForFixedPositionEnabled())
2360             updateCompositingLayersAfterScrolling();
2361         scrollAnimator().setCurrentPosition(newPosition);
2362         scrollPositionChanged(oldPosition, newPosition);
2363     }
2364     if (visibleContentSizeDidChange) {
2365         // Update the scroll-bars to calculate new page-step size.
2366         updateScrollbars(scrollPosition());
2367     }
2368     didChangeScrollOffset();
2369 }
2370 #endif
2371
2372 void FrameView::setViewportConstrainedObjectsNeedLayout()
2373 {
2374     if (!hasViewportConstrainedObjects())
2375         return;
2376
2377     for (auto& renderer : *m_viewportConstrainedObjects)
2378         renderer->setNeedsLayout();
2379 }
2380
2381 void FrameView::didChangeScrollOffset()
2382 {
2383     if (auto* page = frame().page())
2384         page->pageOverlayController().didScrollFrame(frame());
2385     frame().loader().client().didChangeScrollOffset();
2386 }
2387
2388 void FrameView::scrollOffsetChangedViaPlatformWidgetImpl(const ScrollOffset& oldOffset, const ScrollOffset& newOffset)
2389 {
2390     updateLayerPositionsAfterScrolling();
2391     updateCompositingLayersAfterScrolling();
2392     repaintSlowRepaintObjects();
2393     scrollPositionChanged(scrollPositionFromOffset(oldOffset), scrollPositionFromOffset(newOffset));
2394 }
2395
2396 // These scroll positions are affected by zooming.
2397 void FrameView::scrollPositionChanged(const ScrollPosition& oldPosition, const ScrollPosition& newPosition)
2398 {
2399     UNUSED_PARAM(oldPosition);
2400     UNUSED_PARAM(newPosition);
2401
2402     Page* page = frame().page();
2403     Seconds throttlingDelay = page ? page->chrome().client().eventThrottlingDelay() : 0_s;
2404
2405     if (throttlingDelay == 0_s) {
2406         m_delayedScrollEventTimer.stop();
2407         sendScrollEvent();
2408     } else if (!m_delayedScrollEventTimer.isActive())
2409         m_delayedScrollEventTimer.startOneShot(throttlingDelay);
2410
2411     if (RenderView* renderView = this->renderView()) {
2412         if (renderView->usesCompositing())
2413             renderView->compositor().frameViewDidScroll();
2414     }
2415
2416     LOG_WITH_STREAM(Scrolling, stream << "FrameView " << this << " scrollPositionChanged from " << oldPosition << " to " << newPosition << " (scale " << frameScaleFactor() << " )");
2417     updateLayoutViewport();
2418     viewportContentsChanged();
2419 }
2420
2421 void FrameView::applyRecursivelyWithVisibleRect(const WTF::Function<void (FrameView& frameView, const IntRect& visibleRect)>& apply)
2422 {
2423     IntRect windowClipRect = this->windowClipRect();
2424     auto visibleRect = windowToContents(windowClipRect);
2425     apply(*this, visibleRect);
2426
2427     // Recursive call for subframes. We cache the current FrameView's windowClipRect to avoid recomputing it for every subframe.
2428     SetForScope<IntRect*> windowClipRectCache(m_cachedWindowClipRect, &windowClipRect);
2429     for (Frame* childFrame = frame().tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) {
2430         if (auto* childView = childFrame->view())
2431             childView->applyRecursivelyWithVisibleRect(apply);
2432     }
2433 }
2434
2435 void FrameView::resumeVisibleImageAnimations(const IntRect& visibleRect)
2436 {
2437     if (visibleRect.isEmpty())
2438         return;
2439
2440     if (auto* renderView = frame().contentRenderer())
2441         renderView->resumePausedImageAnimationsIfNeeded(visibleRect);
2442 }
2443
2444 void FrameView::updateScriptedAnimationsAndTimersThrottlingState(const IntRect& visibleRect)
2445 {
2446     if (frame().isMainFrame())
2447         return;
2448
2449     auto* document = frame().document();
2450     if (!document)
2451         return;
2452
2453     // We don't throttle zero-size or display:none frames because those are usually utility frames.
2454     bool shouldThrottle = visibleRect.isEmpty() && !m_size.isEmpty() && frame().ownerRenderer();
2455
2456     if (auto* scriptedAnimationController = document->scriptedAnimationController()) {
2457         if (shouldThrottle)
2458             scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::OutsideViewport);
2459         else
2460             scriptedAnimationController->removeThrottlingReason(ScriptedAnimationController::ThrottlingReason::OutsideViewport);
2461     }
2462
2463     document->setTimerThrottlingEnabled(shouldThrottle);
2464 }
2465
2466
2467 void FrameView::resumeVisibleImageAnimationsIncludingSubframes()
2468 {
2469     applyRecursivelyWithVisibleRect([] (FrameView& frameView, const IntRect& visibleRect) {
2470         frameView.resumeVisibleImageAnimations(visibleRect);
2471     });
2472 }
2473
2474 void FrameView::updateLayerPositionsAfterScrolling()
2475 {
2476     // If we're scrolling as a result of updating the view size after layout, we'll update widgets and layer positions soon anyway.
2477     if (layoutContext().layoutPhase() == FrameViewLayoutContext::LayoutPhase::InViewSizeAdjust)
2478         return;
2479
2480     if (!layoutContext().isLayoutNested() && hasViewportConstrainedObjects()) {
2481         if (RenderView* renderView = this->renderView()) {
2482             updateWidgetPositions();
2483             renderView->layer()->updateLayerPositionsAfterDocumentScroll();
2484         }
2485     }
2486 }
2487
2488 bool FrameView::shouldUpdateCompositingLayersAfterScrolling() const
2489 {
2490 #if ENABLE(ASYNC_SCROLLING)
2491     // If the scrolling thread is updating the fixed elements, then the FrameView should not update them as well.
2492
2493     Page* page = frame().page();
2494     if (!page)
2495         return true;
2496
2497     if (&page->mainFrame() != m_frame.ptr())
2498         return true;
2499
2500     ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
2501     if (!scrollingCoordinator)
2502         return true;
2503
2504     if (scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously(*this))
2505         return true;
2506
2507     if (inProgrammaticScroll())
2508         return true;
2509
2510     return false;
2511 #endif
2512     return true;
2513 }
2514
2515 void FrameView::updateCompositingLayersAfterScrolling()
2516 {
2517     ASSERT(layoutContext().layoutPhase() >= FrameViewLayoutContext::LayoutPhase::InPostLayout || layoutContext().layoutPhase() == FrameViewLayoutContext::LayoutPhase::OutsideLayout);
2518
2519     if (!shouldUpdateCompositingLayersAfterScrolling())
2520         return;
2521
2522     if (!layoutContext().isLayoutNested() && hasViewportConstrainedObjects()) {
2523         if (RenderView* renderView = this->renderView())
2524             renderView->compositor().updateCompositingLayers(CompositingUpdateType::OnScroll);
2525     }
2526 }
2527
2528 bool FrameView::isRubberBandInProgress() const
2529 {
2530     if (scrollbarsSuppressed())
2531         return false;
2532
2533     // If the scrolling thread updates the scroll position for this FrameView, then we should return
2534     // ScrollingCoordinator::isRubberBandInProgress().
2535     if (Page* page = frame().page()) {
2536         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
2537             if (!scrollingCoordinator->shouldUpdateScrollLayerPositionSynchronously(*this))
2538                 return scrollingCoordinator->isRubberBandInProgress();
2539         }
2540     }
2541
2542     // If the main thread updates the scroll position for this FrameView, we should return
2543     // ScrollAnimator::isRubberBandInProgress().
2544     if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
2545         return scrollAnimator->isRubberBandInProgress();
2546
2547     return false;
2548 }
2549
2550 bool FrameView::requestScrollPositionUpdate(const ScrollPosition& position)
2551 {
2552     LOG_WITH_STREAM(Scrolling, stream << "FrameView::requestScrollPositionUpdate " << position);
2553
2554 #if ENABLE(ASYNC_SCROLLING)
2555     if (TiledBacking* tiledBacking = this->tiledBacking())
2556         tiledBacking->prepopulateRect(FloatRect(position, visibleContentRect().size()));
2557 #endif
2558
2559 #if ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
2560     if (Page* page = frame().page()) {
2561         if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
2562             return scrollingCoordinator->requestScrollPositionUpdate(*this, position);
2563     }
2564 #else
2565     UNUSED_PARAM(position);
2566 #endif
2567
2568     return false;
2569 }
2570
2571 HostWindow* FrameView::hostWindow() const
2572 {
2573     auto* page = frame().page();
2574     if (!page)
2575         return nullptr;
2576     return &page->chrome();
2577 }
2578
2579 void FrameView::addTrackedRepaintRect(const FloatRect& r)
2580 {
2581     if (!m_isTrackingRepaints || r.isEmpty())
2582         return;
2583
2584     FloatRect repaintRect = r;
2585     repaintRect.moveBy(-scrollPosition());
2586     m_trackedRepaintRects.append(repaintRect);
2587 }
2588
2589 void FrameView::repaintContentRectangle(const IntRect& r)
2590 {
2591     ASSERT(!frame().ownerElement());
2592
2593     if (!shouldUpdate())
2594         return;
2595
2596     ScrollView::repaintContentRectangle(r);
2597 }
2598
2599 static unsigned countRenderedCharactersInRenderObjectWithThreshold(const RenderElement& renderer, unsigned threshold)
2600 {
2601     unsigned count = 0;
2602     for (const RenderObject* descendant = &renderer; descendant; descendant = descendant->nextInPreOrder()) {
2603         if (is<RenderText>(*descendant)) {
2604             count += downcast<RenderText>(*descendant).text().length();
2605             if (count >= threshold)
2606                 break;
2607         }
2608     }
2609     return count;
2610 }
2611
2612 bool FrameView::renderedCharactersExceed(unsigned threshold)
2613 {
2614     if (!frame().contentRenderer())
2615         return false;
2616     return countRenderedCharactersInRenderObjectWithThreshold(*frame().contentRenderer(), threshold) >= threshold;
2617 }
2618
2619 void FrameView::availableContentSizeChanged(AvailableSizeChangeReason reason)
2620 {
2621     if (Document* document = frame().document()) {
2622         // FIXME: Merge this logic with m_setNeedsLayoutWasDeferred and find a more appropriate
2623         // way of handling potential recursive layouts when the viewport is resized to accomodate
2624         // the content but the content always overflows the viewport. See webkit.org/b/165781.
2625         if (!(layoutContext().layoutPhase() == FrameViewLayoutContext::LayoutPhase::InViewSizeAdjust && useFixedLayout()))
2626             document->updateViewportUnitsOnResize();
2627     }
2628
2629     updateLayoutViewport();
2630     setNeedsLayout();
2631     ScrollView::availableContentSizeChanged(reason);
2632 }
2633
2634 bool FrameView::shouldLayoutAfterContentsResized() const
2635 {
2636     return !useFixedLayout() || useCustomFixedPositionLayoutRect();
2637 }
2638
2639 void FrameView::updateContentsSize()
2640 {
2641     // We check to make sure the view is attached to a frame() as this method can
2642     // be triggered before the view is attached by Frame::createView(...) setting
2643     // various values such as setScrollBarModes(...) for example.  An ASSERT is
2644     // triggered when a view is layout before being attached to a frame().
2645     if (!frame().view())
2646         return;
2647
2648 #if PLATFORM(IOS)
2649     if (RenderView* root = m_frame->contentRenderer()) {
2650         if (useCustomFixedPositionLayoutRect() && hasViewportConstrainedObjects()) {
2651             setViewportConstrainedObjectsNeedLayout();
2652             // We must eagerly enter compositing mode because fixed position elements
2653             // will not have been made compositing via a preceding style change before
2654             // m_useCustomFixedPositionLayoutRect was true.
2655             root->compositor().enableCompositingMode();
2656         }
2657     }
2658 #endif
2659
2660     if (shouldLayoutAfterContentsResized() && needsLayout())
2661         layoutContext().layout();
2662
2663     if (RenderView* renderView = this->renderView()) {
2664         if (renderView->usesCompositing())
2665             renderView->compositor().frameViewDidChangeSize();
2666     }
2667 }
2668
2669 void FrameView::addedOrRemovedScrollbar()
2670 {
2671     if (RenderView* renderView = this->renderView()) {
2672         if (renderView->usesCompositing())
2673             renderView->compositor().frameViewDidAddOrRemoveScrollbars();
2674     }
2675
2676     updateTiledBackingAdaptiveSizing();
2677 }
2678
2679 TiledBacking::Scrollability FrameView::computeScrollability() const
2680 {
2681     auto* page = frame().page();
2682
2683     // Use smaller square tiles if the Window is not active to facilitate app napping.
2684     if (!page || !page->isWindowActive())
2685         return TiledBacking::HorizontallyScrollable | TiledBacking::VerticallyScrollable;
2686
2687     bool horizontallyScrollable;
2688     bool verticallyScrollable;
2689     bool clippedByAncestorView = static_cast<bool>(m_viewExposedRect);
2690
2691 #if PLATFORM(IOS)
2692     if (page)
2693         clippedByAncestorView |= page->enclosedInScrollableAncestorView();
2694 #endif
2695
2696     if (delegatesScrolling()) {
2697         IntSize documentSize = contentsSize();
2698         IntSize visibleSize = this->visibleSize();
2699
2700         horizontallyScrollable = clippedByAncestorView || documentSize.width() > visibleSize.width();
2701         verticallyScrollable = clippedByAncestorView || documentSize.height() > visibleSize.height();
2702     } else {
2703         horizontallyScrollable = clippedByAncestorView || horizontalScrollbar();
2704         verticallyScrollable = clippedByAncestorView || verticalScrollbar();
2705     }
2706
2707     TiledBacking::Scrollability scrollability = TiledBacking::NotScrollable;
2708     if (horizontallyScrollable)
2709         scrollability = TiledBacking::HorizontallyScrollable;
2710
2711     if (verticallyScrollable)
2712         scrollability |= TiledBacking::VerticallyScrollable;
2713
2714     return scrollability;
2715 }
2716
2717 void FrameView::updateTiledBackingAdaptiveSizing()
2718 {
2719     auto* tiledBacking = this->tiledBacking();
2720     if (!tiledBacking)
2721         return;
2722
2723     tiledBacking->setScrollability(computeScrollability());
2724 }
2725
2726 #if PLATFORM(IOS)
2727
2728 void FrameView::unobscuredContentSizeChanged()
2729 {
2730     updateTiledBackingAdaptiveSizing();
2731 }
2732
2733 #endif
2734
2735 static LayerFlushThrottleState::Flags determineLayerFlushThrottleState(Page& page)
2736 {
2737     // We only throttle when constantly receiving new data during the inital page load.
2738     if (!page.progress().isMainLoadProgressing())
2739         return 0;
2740     // Scrolling during page loading disables throttling.
2741     if (page.mainFrame().view()->wasScrolledByUser())
2742         return 0;
2743     // Disable for image documents so large GIF animations don't get throttled during loading.
2744     auto* document = page.mainFrame().document();
2745     if (!document || is<ImageDocument>(*document))
2746         return 0;
2747     return LayerFlushThrottleState::Enabled;
2748 }
2749
2750 void FrameView::disableLayerFlushThrottlingTemporarilyForInteraction()
2751 {
2752     if (!frame().page())
2753         return;
2754     auto& page = *frame().page();
2755
2756     LayerFlushThrottleState::Flags flags = LayerFlushThrottleState::UserIsInteracting | determineLayerFlushThrottleState(page);
2757     if (page.chrome().client().adjustLayerFlushThrottling(flags))
2758         return;
2759
2760     if (RenderView* view = renderView())
2761         view->compositor().disableLayerFlushThrottlingTemporarilyForInteraction();
2762 }
2763
2764 void FrameView::loadProgressingStatusChanged()
2765 {
2766     updateLayerFlushThrottling();
2767     adjustTiledBackingCoverage();
2768 }
2769
2770 void FrameView::updateLayerFlushThrottling()
2771 {
2772     Page* page = frame().page();
2773     if (!page)
2774         return;
2775
2776     ASSERT(frame().isMainFrame());
2777
2778     LayerFlushThrottleState::Flags flags = determineLayerFlushThrottleState(*page);
2779
2780     // See if the client is handling throttling.
2781     if (page->chrome().client().adjustLayerFlushThrottling(flags))
2782         return;
2783
2784     for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr())) {
2785         if (RenderView* renderView = frame->contentRenderer())
2786             renderView->compositor().setLayerFlushThrottlingEnabled(flags & LayerFlushThrottleState::Enabled);
2787     }
2788 }
2789
2790 void FrameView::adjustTiledBackingCoverage()
2791 {
2792     if (!m_speculativeTilingEnabled)
2793         enableSpeculativeTilingIfNeeded();
2794
2795     RenderView* renderView = this->renderView();
2796     if (renderView && renderView->layer() && renderView->layer()->backing())
2797         renderView->layer()->backing()->adjustTiledBackingCoverage();
2798 #if PLATFORM(IOS)
2799     if (LegacyTileCache* tileCache = legacyTileCache())
2800         tileCache->setSpeculativeTileCreationEnabled(m_speculativeTilingEnabled);
2801 #endif
2802 }
2803
2804 static bool shouldEnableSpeculativeTilingDuringLoading(const FrameView& view)
2805 {
2806     Page* page = view.frame().page();
2807     return page && view.isVisuallyNonEmpty() && !page->progress().isMainLoadProgressing();
2808 }
2809
2810 void FrameView::enableSpeculativeTilingIfNeeded()
2811 {
2812     ASSERT(!m_speculativeTilingEnabled);
2813     if (m_wasScrolledByUser) {
2814         m_speculativeTilingEnabled = true;
2815         return;
2816     }
2817     if (!shouldEnableSpeculativeTilingDuringLoading(*this))
2818         return;
2819
2820     if (m_speculativeTilingDelayDisabledForTesting) {
2821         speculativeTilingEnableTimerFired();
2822         return;
2823     }
2824
2825     if (m_speculativeTilingEnableTimer.isActive())
2826         return;
2827     // Delay enabling a bit as load completion may trigger further loading from scripts.
2828     static const Seconds speculativeTilingEnableDelay { 500_ms };
2829     m_speculativeTilingEnableTimer.startOneShot(speculativeTilingEnableDelay);
2830 }
2831
2832 void FrameView::speculativeTilingEnableTimerFired()
2833 {
2834     if (m_speculativeTilingEnabled)
2835         return;
2836     m_speculativeTilingEnabled = shouldEnableSpeculativeTilingDuringLoading(*this);
2837     adjustTiledBackingCoverage();
2838 }
2839
2840 void FrameView::show()
2841 {
2842     ScrollView::show();
2843
2844     if (frame().isMainFrame()) {
2845         // Turn off speculative tiling for a brief moment after a FrameView appears on screen.
2846         // Note that adjustTiledBackingCoverage() kicks the (500ms) timer to re-enable it.
2847         m_speculativeTilingEnabled = false;
2848         m_wasScrolledByUser = false;
2849         adjustTiledBackingCoverage();
2850     }
2851 }
2852
2853 void FrameView::hide()
2854 {
2855     ScrollView::hide();
2856     adjustTiledBackingCoverage();
2857 }
2858
2859 bool FrameView::needsLayout() const
2860 {
2861     return layoutContext().needsLayout();
2862 }
2863
2864 void FrameView::setNeedsLayout()
2865 {
2866     layoutContext().setNeedsLayout();
2867 }
2868
2869 void FrameView::scheduleSelectionUpdate()
2870 {
2871     if (needsLayout())
2872         return;
2873     // FIXME: We should not need to go through the layout process since selection update does not change dimension/geometry.
2874     // However we can't tell at this point if the tree is stable yet, so let's just schedule a root only layout for now.
2875     setNeedsLayout();
2876     layoutContext().scheduleLayout();
2877 }
2878
2879 bool FrameView::isTransparent() const
2880 {
2881     return m_isTransparent;
2882 }
2883
2884 void FrameView::setTransparent(bool isTransparent)
2885 {
2886     if (m_isTransparent == isTransparent)
2887         return;
2888
2889     m_isTransparent = isTransparent;
2890
2891     // setTransparent can be called in the window between FrameView initialization
2892     // and switching in the new Document; this means that the RenderView that we
2893     // retrieve is actually attached to the previous Document, which is going away,
2894     // and must not update compositing layers.
2895     if (!isViewForDocumentInFrame())
2896         return;
2897
2898     renderView()->compositor().rootBackgroundTransparencyChanged();
2899 }
2900
2901 bool FrameView::hasOpaqueBackground() const
2902 {
2903     return !m_isTransparent && m_baseBackgroundColor.isOpaque();
2904 }
2905
2906 Color FrameView::baseBackgroundColor() const
2907 {
2908     return m_baseBackgroundColor;
2909 }
2910
2911 void FrameView::setBaseBackgroundColor(const Color& backgroundColor)
2912 {
2913     bool wasOpaque = m_baseBackgroundColor.isOpaque();
2914     
2915     if (!backgroundColor.isValid())
2916         m_baseBackgroundColor = Color::white;
2917     else
2918         m_baseBackgroundColor = backgroundColor;
2919
2920     if (!isViewForDocumentInFrame())
2921         return;
2922
2923     recalculateScrollbarOverlayStyle();
2924
2925     if (m_baseBackgroundColor.isOpaque() != wasOpaque)
2926         renderView()->compositor().rootBackgroundTransparencyChanged();
2927 }
2928
2929 void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent)
2930 {
2931     for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr())) {
2932         if (FrameView* view = frame->view()) {
2933             view->setTransparent(transparent);
2934             view->setBaseBackgroundColor(backgroundColor);
2935         }
2936     }
2937 }
2938
2939 bool FrameView::hasExtendedBackgroundRectForPainting() const
2940 {
2941     TiledBacking* tiledBacking = this->tiledBacking();
2942     if (!tiledBacking)
2943         return false;
2944
2945     return tiledBacking->hasMargins();
2946 }
2947
2948 void FrameView::updateExtendBackgroundIfNecessary()
2949 {
2950     ExtendedBackgroundMode mode = calculateExtendedBackgroundMode();
2951     if (mode == ExtendedBackgroundModeNone)
2952         return;
2953
2954     updateTilesForExtendedBackgroundMode(mode);
2955 }
2956
2957 FrameView::ExtendedBackgroundMode FrameView::calculateExtendedBackgroundMode() const
2958 {
2959 #if PLATFORM(IOS)
2960     // <rdar://problem/16201373>
2961     return ExtendedBackgroundModeNone;
2962 #else
2963     if (!frame().settings().backgroundShouldExtendBeyondPage())
2964         return ExtendedBackgroundModeNone;
2965
2966     // Just because Settings::backgroundShouldExtendBeyondPage() is true does not necessarily mean
2967     // that the background rect needs to be extended for painting. Simple backgrounds can be extended
2968     // just with RenderLayerCompositor::setRootExtendedBackgroundColor(). More complicated backgrounds,
2969     // such as images, require extending the background rect to continue painting into the extended
2970     // region. This function finds out if it is necessary to extend the background rect for painting.
2971
2972     if (!frame().isMainFrame())
2973         return ExtendedBackgroundModeNone;
2974
2975     Document* document = frame().document();
2976     if (!document)
2977         return ExtendedBackgroundModeNone;
2978
2979     if (!renderView())
2980         return ExtendedBackgroundModeNone;
2981     
2982     auto* rootBackgroundRenderer = renderView()->rendererForRootBackground();
2983     if (!rootBackgroundRenderer)
2984         return ExtendedBackgroundModeNone;
2985
2986     if (!rootBackgroundRenderer->style().hasBackgroundImage())
2987         return ExtendedBackgroundModeNone;
2988
2989     ExtendedBackgroundMode mode = ExtendedBackgroundModeNone;
2990     if (rootBackgroundRenderer->style().backgroundRepeatX() == RepeatFill)
2991         mode |= ExtendedBackgroundModeHorizontal;
2992     if (rootBackgroundRenderer->style().backgroundRepeatY() == RepeatFill)
2993         mode |= ExtendedBackgroundModeVertical;
2994
2995     return mode;
2996 #endif
2997 }
2998
2999 void FrameView::updateTilesForExtendedBackgroundMode(ExtendedBackgroundMode mode)
3000 {
3001     RenderView* renderView = this->renderView();
3002     if (!renderView)
3003         return;
3004
3005     RenderLayerBacking* backing = renderView->layer()->backing();
3006     if (!backing)
3007         return;
3008
3009     TiledBacking* tiledBacking = backing->tiledBacking();
3010     if (!tiledBacking)
3011         return;
3012
3013     ExtendedBackgroundMode existingMode = ExtendedBackgroundModeNone;
3014     if (tiledBacking->hasVerticalMargins())
3015         existingMode |= ExtendedBackgroundModeVertical;
3016     if (tiledBacking->hasHorizontalMargins())
3017         existingMode |= ExtendedBackgroundModeHorizontal;
3018
3019     if (existingMode == mode)
3020         return;
3021
3022     renderView->compositor().setRootExtendedBackgroundColor(mode == ExtendedBackgroundModeAll ? Color() : documentBackgroundColor());
3023     backing->setTiledBackingHasMargins(mode & ExtendedBackgroundModeHorizontal, mode & ExtendedBackgroundModeVertical);
3024 }
3025
3026 IntRect FrameView::extendedBackgroundRectForPainting() const
3027 {
3028     TiledBacking* tiledBacking = this->tiledBacking();
3029     if (!tiledBacking)
3030         return IntRect();
3031     
3032     RenderView* renderView = this->renderView();
3033     if (!renderView)
3034         return IntRect();
3035     
3036     LayoutRect extendedRect = renderView->unextendedBackgroundRect();
3037     if (!tiledBacking->hasMargins())
3038         return snappedIntRect(extendedRect);
3039     
3040     extendedRect.moveBy(LayoutPoint(-tiledBacking->leftMarginWidth(), -tiledBacking->topMarginHeight()));
3041     extendedRect.expand(LayoutSize(tiledBacking->leftMarginWidth() + tiledBacking->rightMarginWidth(), tiledBacking->topMarginHeight() + tiledBacking->bottomMarginHeight()));
3042     return snappedIntRect(extendedRect);
3043 }
3044
3045 bool FrameView::shouldUpdateWhileOffscreen() const
3046 {
3047     return m_shouldUpdateWhileOffscreen;
3048 }
3049
3050 void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
3051 {
3052     m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
3053 }
3054
3055 bool FrameView::shouldUpdate() const
3056 {
3057     if (isOffscreen() && !shouldUpdateWhileOffscreen())
3058         return false;
3059     return true;
3060 }
3061
3062 void FrameView::scrollToAnchor()
3063 {
3064     RefPtr<ContainerNode> anchorNode = m_maintainScrollPositionAnchor;
3065
3066     LOG_WITH_STREAM(Scrolling, stream << "FrameView::scrollToAnchor() " << anchorNode.get());
3067
3068     if (!anchorNode)
3069         return;
3070
3071     if (!anchorNode->renderer())
3072         return;
3073     m_shouldScrollToFocusedElement = false;
3074     m_delayedScrollToFocusedElementTimer.stop();
3075
3076     LayoutRect rect;
3077     bool insideFixed = false;
3078     if (anchorNode != frame().document() && anchorNode->renderer())
3079         rect = anchorNode->renderer()->absoluteAnchorRect(&insideFixed);
3080
3081     LOG_WITH_STREAM(Scrolling, stream << " anchor node rect " << rect);
3082
3083     // Scroll nested layers and frames to reveal the anchor.
3084     // Align to the top and to the closest side (this matches other browsers).
3085     if (anchorNode->renderer()->style().isHorizontalWritingMode())
3086         anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
3087     else if (anchorNode->renderer()->style().isFlippedBlocksWritingMode())
3088         anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignRightAlways, ScrollAlignment::alignToEdgeIfNeeded);
3089     else
3090         anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, insideFixed, ScrollAlignment::alignLeftAlways, ScrollAlignment::alignToEdgeIfNeeded);
3091
3092     if (AXObjectCache* cache = frame().document()->existingAXObjectCache())
3093         cache->handleScrolledToAnchor(anchorNode.get());
3094
3095     // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor.
3096     LOG_WITH_STREAM(Scrolling, stream << " restoring anchor node to " << anchorNode.get());
3097     m_maintainScrollPositionAnchor = anchorNode;
3098     m_shouldScrollToFocusedElement = false;
3099     m_delayedScrollToFocusedElementTimer.stop();
3100 }
3101
3102 void FrameView::updateEmbeddedObject(RenderEmbeddedObject& embeddedObject)
3103 {
3104     // No need to update if it's already crashed or known to be missing.
3105     if (embeddedObject.isPluginUnavailable())
3106         return;
3107
3108     HTMLFrameOwnerElement& element = embeddedObject.frameOwnerElement();
3109
3110     if (embeddedObject.isSnapshottedPlugIn()) {
3111         if (is<HTMLObjectElement>(element) || is<HTMLEmbedElement>(element)) {
3112             HTMLPlugInImageElement& pluginElement = downcast<HTMLPlugInImageElement>(element);
3113             pluginElement.checkSnapshotStatus();
3114         }
3115         return;
3116     }
3117
3118     auto weakRenderer = makeWeakPtr(embeddedObject);
3119
3120     // FIXME: This could turn into a real virtual dispatch if we defined
3121     // updateWidget(PluginCreationOption) on HTMLElement.
3122     if (is<HTMLPlugInImageElement>(element)) {
3123         HTMLPlugInImageElement& pluginElement = downcast<HTMLPlugInImageElement>(element);
3124         if (pluginElement.needsCheckForSizeChange()) {
3125             pluginElement.checkSnapshotStatus();
3126             return;
3127         }
3128         if (pluginElement.needsWidgetUpdate())
3129             pluginElement.updateWidget(CreatePlugins::Yes);
3130     } else
3131         ASSERT_NOT_REACHED();
3132
3133     // It's possible the renderer was destroyed below updateWidget() since loading a plugin may execute arbitrary JavaScript.
3134     if (!weakRenderer)
3135         return;
3136
3137     auto ignoreWidgetState = embeddedObject.updateWidgetPosition();
3138     UNUSED_PARAM(ignoreWidgetState);
3139 }
3140
3141 bool FrameView::updateEmbeddedObjects()
3142 {
3143     if (layoutContext().isLayoutNested() || !m_embeddedObjectsToUpdate || m_embeddedObjectsToUpdate->isEmpty())
3144         return true;
3145
3146     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
3147
3148     // Insert a marker for where we should stop.
3149     ASSERT(!m_embeddedObjectsToUpdate->contains(nullptr));
3150     m_embeddedObjectsToUpdate->add(nullptr);
3151
3152     while (!m_embeddedObjectsToUpdate->isEmpty()) {
3153         RenderEmbeddedObject* embeddedObject = m_embeddedObjectsToUpdate->takeFirst();
3154         if (!embeddedObject)
3155             break;
3156         updateEmbeddedObject(*embeddedObject);
3157     }
3158
3159     return m_embeddedObjectsToUpdate->isEmpty();
3160 }
3161
3162 void FrameView::updateEmbeddedObjectsTimerFired()
3163 {
3164     RefPtr<FrameView> protectedThis(this);
3165     m_updateEmbeddedObjectsTimer.stop();
3166     for (unsigned i = 0; i < maxUpdateEmbeddedObjectsIterations; i++) {
3167         if (updateEmbeddedObjects())
3168             break;
3169     }
3170 }
3171
3172 void FrameView::flushAnyPendingPostLayoutTasks()
3173 {
3174     layoutContext().flushAsynchronousTasks();
3175     if (m_updateEmbeddedObjectsTimer.isActive())
3176         updateEmbeddedObjectsTimerFired();
3177 }
3178
3179 void FrameView::queuePostLayoutCallback(Function<void()>&& callback)
3180 {
3181     m_postLayoutCallbackQueue.append(WTFMove(callback));
3182 }
3183
3184 void FrameView::flushPostLayoutTasksQueue()
3185 {
3186     if (layoutContext().isLayoutNested())
3187         return;
3188
3189     if (!m_postLayoutCallbackQueue.size())
3190         return;
3191
3192     Vector<Function<void()>> queue = WTFMove(m_postLayoutCallbackQueue);
3193     for (auto& task : queue)
3194         task();
3195 }
3196
3197 void FrameView::performPostLayoutTasks()
3198 {
3199     // FIXME: We should not run any JavaScript code in this function.
3200     LOG(Layout, "FrameView %p performPostLayoutTasks", this);
3201
3202     frame().selection().updateAppearanceAfterLayout();
3203
3204     flushPostLayoutTasksQueue();
3205
3206     if (!layoutContext().isLayoutNested() && frame().document()->documentElement())
3207         fireLayoutRelatedMilestonesIfNeeded();
3208
3209 #if PLATFORM(IOS)
3210     // Only send layout-related delegate callbacks synchronously for the main frame to
3211     // avoid re-entering layout for the main frame while delivering a layout-related delegate
3212     // callback for a subframe.
3213     if (frame().isMainFrame()) {
3214         if (Page* page = frame().page())
3215             page->chrome().client().didLayout();
3216     }
3217 #endif
3218     
3219     // FIXME: We should consider adding DidLayout as a LayoutMilestone. That would let us merge this
3220     // with didLayout(LayoutMilestones).
3221     frame().loader().client().dispatchDidLayout();
3222
3223     updateWidgetPositions();
3224
3225 #if ENABLE(CSS_SCROLL_SNAP)
3226     updateSnapOffsets();
3227 #endif
3228     m_updateEmbeddedObjectsTimer.startOneShot(0_s);
3229
3230     if (auto* page = frame().page()) {
3231         if (auto* scrollingCoordinator = page->scrollingCoordinator())
3232             scrollingCoordinator->frameViewLayoutUpdated(*this);
3233     }
3234
3235     if (RenderView* renderView = this->renderView()) {
3236         if (renderView->usesCompositing())
3237             renderView->compositor().frameViewDidLayout();
3238     }
3239
3240     scrollToAnchor();
3241
3242     sendResizeEventIfNeeded();
3243     
3244     updateLayoutViewport();
3245     viewportContentsChanged();
3246
3247     updateScrollSnapState();
3248
3249     if (AXObjectCache* cache = frame().document()->existingAXObjectCache())
3250         cache->performDeferredCacheUpdate();
3251 }
3252
3253 IntSize FrameView::sizeForResizeEvent() const
3254 {
3255 #if PLATFORM(IOS)
3256     if (m_useCustomSizeForResizeEvent)
3257         return m_customSizeForResizeEvent;
3258 #endif
3259     if (useFixedLayout() && !fixedLayoutSize().isEmpty() && delegatesScrolling())
3260         return fixedLayoutSize();
3261     return visibleContentRectIncludingScrollbars().size();
3262 }
3263
3264 void FrameView::sendResizeEventIfNeeded()
3265 {
3266     if (layoutContext().isInRenderTreeLayout() || needsLayout())
3267         return;
3268
3269     RenderView* renderView = this->renderView();
3270     if (!renderView || renderView->printing())
3271         return;
3272
3273     if (frame().page() && frame().page()->chrome().client().isSVGImageChromeClient())
3274         return;
3275
3276     IntSize currentSize = sizeForResizeEvent();
3277     float currentZoomFactor = renderView->style().zoom();
3278
3279     if (currentSize == m_lastViewportSize && currentZoomFactor == m_lastZoomFactor)
3280         return;
3281
3282     m_lastViewportSize = currentSize;
3283     m_lastZoomFactor = currentZoomFactor;
3284
3285     if (!layoutContext().didFirstLayout())
3286         return;
3287
3288 #if PLATFORM(IOS)
3289     // Don't send the resize event if the document is loading. Some pages automatically reload
3290     // when the window is resized; Safari on iOS often resizes the window while setting up its
3291     // viewport. This obviously can cause problems.
3292     if (DocumentLoader* documentLoader = frame().loader().documentLoader()) {
3293         if (documentLoader->isLoadingInAPISense())
3294             return;
3295     }
3296 #endif
3297
3298     bool isMainFrame = frame().isMainFrame();
3299     bool canSendResizeEventSynchronously = isMainFrame && !m_shouldAutoSize;
3300
3301     LOG(Events, "FrameView %p sendResizeEventIfNeeded sending resize event, size %dx%d (canSendResizeEventSynchronously %d)", this, currentSize.width(), currentSize.height(), canSendResizeEventSynchronously);
3302
3303     Ref<Event> resizeEvent = Event::create(eventNames().resizeEvent, false, false);
3304     if (canSendResizeEventSynchronously)
3305         frame().document()->dispatchWindowEvent(resizeEvent);
3306     else {
3307         // FIXME: Queueing this event for an unpredictable time in the future seems
3308         // intrinsically racy. By the time this resize event fires, the frame might
3309         // be resized again, so we could end up with two resize events for the same size.
3310         frame().document()->enqueueWindowEvent(WTFMove(resizeEvent));
3311     }
3312
3313     if (InspectorInstrumentation::hasFrontends() && isMainFrame) {
3314         if (Page* page = frame().page()) {
3315             if (InspectorClient* inspectorClient = page->inspectorController().inspectorClient())
3316                 inspectorClient->didResizeMainFrame(&frame());
3317         }
3318     }
3319 }
3320
3321 void FrameView::willStartLiveResize()
3322 {
3323     ScrollView::willStartLiveResize();
3324     adjustTiledBackingCoverage();
3325 }
3326     
3327 void FrameView::willEndLiveResize()
3328 {
3329     ScrollView::willEndLiveResize();
3330     adjustTiledBackingCoverage();
3331 }
3332
3333 void FrameView::autoSizeIfEnabled()
3334 {
3335     if (!m_shouldAutoSize)
3336         return;
3337
3338     if (m_inAutoSize)
3339         return;
3340
3341     auto* document = frame().document();
3342     if (!document)
3343         return;
3344
3345     auto* renderView = document->renderView();
3346     if (!renderView)
3347         return;
3348
3349     LOG(Layout, "FrameView %p autoSizeIfEnabled", this);
3350     SetForScope<bool> changeInAutoSize(m_inAutoSize, true);
3351     if (layoutContext().subtreeLayoutRoot())
3352         layoutContext().convertSubtreeLayoutToFullLayout();
3353     // Start from the minimum size and allow it to grow.
3354     resize(m_minAutoSize.width(), m_minAutoSize.height());
3355     IntSize size = frameRect().size();
3356     // Do the resizing twice. The first time is basically a rough calculation using the preferred width
3357     // which may result in a height change during the second iteration.
3358     for (int i = 0; i < 2; i++) {
3359         // Update various sizes including contentsSize, scrollHeight, etc.
3360         document->updateLayoutIgnorePendingStylesheets();
3361         int width = renderView->minPreferredLogicalWidth();
3362         int height = renderView->documentRect().height();
3363         IntSize newSize(width, height);
3364
3365         // Check to see if a scrollbar is needed for a given dimension and
3366         // if so, increase the other dimension to account for the scrollbar.
3367         // Since the dimensions are only for the view rectangle, once a
3368         // dimension exceeds the maximum, there is no need to increase it further.
3369         if (newSize.width() > m_maxAutoSize.width()) {
3370             RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
3371             if (!localHorizontalScrollbar)
3372                 localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
3373             newSize.expand(0, localHorizontalScrollbar->occupiedHeight());
3374
3375             // Don't bother checking for a vertical scrollbar because the width is at
3376             // already greater the maximum.
3377         } else if (newSize.height() > m_maxAutoSize.height()) {
3378             RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
3379             if (!localVerticalScrollbar)
3380                 localVerticalScrollbar = createScrollbar(VerticalScrollbar);
3381             newSize.expand(localVerticalScrollbar->occupiedWidth(), 0);
3382
3383             // Don't bother checking for a horizontal scrollbar because the height is
3384             // already greater the maximum.
3385         }
3386
3387         // Ensure the size is at least the min bounds.
3388         newSize = newSize.expandedTo(m_minAutoSize);
3389
3390         // Bound the dimensions by the max bounds and determine what scrollbars to show.
3391         ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
3392         if (newSize.width() > m_maxAutoSize.width()) {
3393             newSize.setWidth(m_maxAutoSize.width());
3394             horizonalScrollbarMode = ScrollbarAlwaysOn;
3395         }
3396         ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
3397         if (newSize.height() > m_maxAutoSize.height()) {
3398             newSize.setHeight(m_maxAutoSize.height());
3399             verticalScrollbarMode = ScrollbarAlwaysOn;
3400         }
3401
3402         if (newSize == size)
3403             continue;
3404
3405         // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
3406         // unless autoresize has just been turned on or the maximum size is smaller than the current size.
3407         if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
3408             && !frame().loader().isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
3409             break;
3410
3411         // The first time around, resize to the minimum height again; otherwise,
3412         // on pages (e.g. quirks mode) where the body/document resize to the view size,
3413         // we'll end up not shrinking back down after resizing to the computed preferred width.
3414         resize(newSize.width(), i ? newSize.height() : m_minAutoSize.height());
3415         // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
3416         // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
3417         setVerticalScrollbarLock(false);
3418         setHorizontalScrollbarLock(false);
3419         setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
3420     }
3421     // All the resizing above may have invalidated style (for example if viewport units are being used).
3422     document->updateStyleIfNeeded();
3423     // FIXME: Use the final layout's result as the content size (webkit.org/b/173561).
3424     m_autoSizeContentSize = contentsSize();
3425     if (m_autoSizeFixedMinimumHeight) {
3426         auto contentsSize = this->contentsSize();
3427         resize(contentsSize.width(), std::max(m_autoSizeFixedMinimumHeight, contentsSize.height()));
3428         document->updateLayoutIgnorePendingStylesheets();
3429     }
3430     m_didRunAutosize = true;
3431
3432     LOG_WITH_STREAM(Layout, stream << "FrameView " << this << " autoSizeIfEnabled() changed size from " << size << " to " << frameRect().size());
3433 }
3434
3435 void FrameView::setAutoSizeFixedMinimumHeight(int fixedMinimumHeight)
3436 {
3437     if (m_autoSizeFixedMinimumHeight == fixedMinimumHeight)
3438         return;
3439
3440     m_autoSizeFixedMinimumHeight = fixedMinimumHeight;
3441
3442     setNeedsLayout();
3443 }
3444
3445 RenderElement* FrameView::viewportRenderer() const
3446 {
3447     if (m_viewportRendererType == ViewportRendererType::None)
3448         return nullptr;
3449
3450     auto* document = frame().document();
3451     if (!document)
3452         return nullptr;
3453
3454     if (m_viewportRendererType == ViewportRendererType::Document) {
3455         auto* documentElement = document->documentElement();
3456         if (!documentElement)
3457             return nullptr;
3458         return documentElement->renderer();
3459     }
3460
3461     if (m_viewportRendererType == ViewportRendererType::Body) {
3462         auto* body = document->body();
3463         if (!body)
3464             return nullptr;
3465         return body->renderer();
3466     }
3467
3468     ASSERT_NOT_REACHED();
3469     return nullptr;
3470 }
3471
3472 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
3473 {
3474     auto* viewportRenderer = this->viewportRenderer();
3475     if (!viewportRenderer)
3476         return;
3477     
3478     if (m_overflowStatusDirty) {
3479         m_horizontalOverflow = horizontalOverflow;
3480         m_verticalOverflow = verticalOverflow;
3481         m_overflowStatusDirty = false;
3482         return;
3483     }
3484     
3485     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
3486     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
3487     
3488     if (horizontalOverflowChanged || verticalOverflowChanged) {
3489         m_horizontalOverflow = horizontalOverflow;
3490         m_verticalOverflow = verticalOverflow;
3491
3492         Ref<OverflowEvent> overflowEvent = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
3493             verticalOverflowChanged, verticalOverflow);
3494         overflowEvent->setTarget(viewportRenderer->element());
3495
3496         frame().document()->enqueueOverflowEvent(WTFMove(overflowEvent));
3497     }
3498 }
3499
3500 const Pagination& FrameView::pagination() const
3501 {
3502     if (m_pagination != Pagination())
3503         return m_pagination;
3504
3505     if (frame().isMainFrame()) {
3506         if (Page* page = frame().page())
3507             return page->pagination();
3508     }
3509
3510     return m_pagination;
3511 }
3512
3513 void FrameView::setPagination(const Pagination& pagination)
3514 {
3515     if (m_pagination == pagination)
3516         return;
3517
3518     m_pagination = pagination;
3519
3520     frame().document()->styleScope().didChangeStyleSheetEnvironment();
3521 }
3522
3523 IntRect FrameView::windowClipRect() const
3524 {
3525     ASSERT(frame().view() == this);
3526
3527     if (m_cachedWindowClipRect)
3528         return *m_cachedWindowClipRect;
3529
3530     if (paintsEntireContents())
3531         return contentsToWindow(IntRect(IntPoint(), totalContentsSize()));
3532
3533     // Set our clip rect to be our contents.
3534     IntRect clipRect = contentsToWindow(visibleContentRect(LegacyIOSDocumentVisibleRect));
3535
3536     if (!frame().ownerElement())
3537         return clipRect;
3538
3539     // Take our owner element and get its clip rect.
3540     HTMLFrameOwnerElement* ownerElement = frame().ownerElement();
3541     if (FrameView* parentView = ownerElement->document().view())
3542         clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true));
3543     return clipRect;
3544 }
3545
3546 IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const
3547 {
3548     // The renderer can sometimes be null when style="display:none" interacts
3549     // with external content and plugins.
3550     if (!ownerElement->renderer())
3551         return windowClipRect();
3552
3553     // If we have no layer, just return our window clip rect.
3554     const RenderLayer* enclosingLayer = ownerElement->renderer()->enclosingLayer();
3555     if (!enclosingLayer)
3556         return windowClipRect();
3557
3558     // Apply the clip from the layer.
3559     IntRect clipRect;
3560     if (clipToLayerContents)
3561         clipRect = snappedIntRect(enclosingLayer->childrenClipRect());
3562     else
3563         clipRect = snappedIntRect(enclosingLayer->selfClipRect());
3564     clipRect = contentsToWindow(clipRect); 
3565     return intersection(clipRect, windowClipRect());
3566 }
3567
3568 bool FrameView::isActive() const
3569 {
3570     Page* page = frame().page();
3571     return page && page->focusController().isActive();
3572 }
3573
3574 bool FrameView::forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const
3575 {
3576     Page* page = frame().page();
3577     return page && page->settings().forceUpdateScrollbarsOnMainThreadForPerformanceTesting();
3578 }
3579
3580 void FrameView::scrollTo(const ScrollPosition& newPosition)
3581 {
3582     IntPoint oldPosition = scrollPosition();
3583     ScrollView::scrollTo(newPosition);
3584     if (oldPosition != scrollPosition())
3585         scrollPositionChanged(oldPosition, scrollPosition());
3586
3587     didChangeScrollOffset();
3588 }
3589
3590 float FrameView::adjustScrollStepForFixedContent(float step, ScrollbarOrientation orientation, ScrollGranularity granularity)
3591 {
3592     if (granularity != ScrollByPage || orientation == HorizontalScrollbar)
3593         return step;
3594
3595     TrackedRendererListHashSet* positionedObjects = nullptr;
3596     if (RenderView* root = frame().contentRenderer()) {
3597         if (!root->hasPositionedObjects())
3598             return step;
3599         positionedObjects = root->positionedObjects();
3600     }
3601
3602     FloatRect unobscuredContentRect = this->unobscuredContentRect();
3603     float topObscuredArea = 0;
3604     float bottomObscuredArea = 0;
3605     for (const auto& positionedObject : *positionedObjects) {
3606         const RenderStyle& style = positionedObject->style();
3607         if (style.position() != FixedPosition || style.visibility() == HIDDEN || !style.opacity())
3608             continue;
3609
3610         FloatQuad contentQuad = positionedObject->absoluteContentQuad();
3611         if (!contentQuad.isRectilinear())
3612             continue;
3613
3614         FloatRect contentBoundingBox = contentQuad.boundingBox();
3615         FloatRect fixedRectInView = intersection(unobscuredContentRect, contentBoundingBox);
3616
3617         if (fixedRectInView.width() < unobscuredContentRect.width())
3618             continue;
3619
3620         if (fixedRectInView.y() == unobscuredContentRect.y())
3621             topObscuredArea = std::max(topObscuredArea, fixedRectInView.height());
3622         else if (fixedRectInView.maxY() == unobscuredContentRect.maxY())
3623             bottomObscuredArea = std::max(bottomObscuredArea, fixedRectInView.height());
3624     }
3625
3626     return Scrollbar::pageStep(unobscuredContentRect.height(), unobscuredContentRect.height() - topObscuredArea - bottomObscuredArea);
3627 }
3628
3629 void FrameView::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect)
3630 {
3631     // Add in our offset within the FrameView.
3632     IntRect dirtyRect = rect;
3633     dirtyRect.moveBy(scrollbar.location());
3634     invalidateRect(dirtyRect);
3635 }
3636
3637 float FrameView::visibleContentScaleFactor() const
3638 {
3639     if (!frame().isMainFrame() || !frame().settings().delegatesPageScaling())
3640         return 1;
3641
3642     Page* page = frame().page();
3643     if (!page)
3644         return 1;
3645
3646     return page->pageScaleFactor();
3647 }
3648
3649 void FrameView::setVisibleScrollerThumbRect(const IntRect& scrollerThumb)
3650 {
3651     if (!frame().isMainFrame())
3652         return;
3653
3654     if (Page* page = frame().page())
3655         page->chrome().client().notifyScrollerThumbIsVisibleInRect(scrollerThumb);
3656 }
3657
3658 ScrollableArea* FrameView::enclosingScrollableArea() const
3659 {
3660     // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer.
3661     return nullptr;
3662 }
3663
3664 IntRect FrameView::scrollableAreaBoundingBox(bool*) const
3665 {
3666     RenderWidget* ownerRenderer = frame().ownerRenderer();
3667     if (!ownerRenderer)
3668         return frameRect();
3669
3670     return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
3671 }
3672
3673 bool FrameView::isScrollable(Scrollability definitionOfScrollable)
3674 {
3675     // Check for:
3676     // 1) If there an actual overflow.
3677     // 2) display:none or visibility:hidden set to self or inherited.
3678     // 3) overflow{-x,-y}: hidden;
3679     // 4) scrolling: no;
3680     if (!didFirstLayout())
3681         return false;
3682
3683     bool requiresActualOverflowToBeConsideredScrollable = !frame().isMainFrame() || definitionOfScrollable != Scrollability::ScrollableOrRubberbandable;
3684 #if !ENABLE(RUBBER_BANDING)
3685     requiresActualOverflowToBeConsideredScrollable = true;
3686 #endif
3687
3688     // Covers #1
3689     if (requiresActualOverflowToBeConsideredScrollable) {
3690         IntSize totalContentsSize = this->totalContentsSize();
3691         IntSize visibleContentSize = visibleContentRect(LegacyIOSDocumentVisibleRect).size();
3692         if (totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width())
3693             return false;
3694     }
3695
3696     // Covers #2.
3697     HTMLFrameOwnerElement* owner = frame().ownerElement();
3698     if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting()))
3699         return false;
3700
3701     // Cover #3 and #4.
3702     ScrollbarMode horizontalMode;
3703     ScrollbarMode verticalMode;
3704     calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly);
3705     if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff)
3706         return false;
3707
3708     return true;
3709 }
3710
3711 bool FrameView::isScrollableOrRubberbandable()
3712 {
3713     return isScrollable(Scrollability::ScrollableOrRubberbandable);
3714 }
3715
3716 bool FrameView::hasScrollableOrRubberbandableAncestor()
3717 {
3718     if (frame().isMainFrame())
3719         return isScrollableOrRubberbandable();
3720
3721     for (FrameView* parent = this->parentFrameView(); parent; parent = parent->parentFrameView()) {
3722         Scrollability frameScrollability = parent->frame().isMainFrame() ? Scrollability::ScrollableOrRubberbandable : Scrollability::Scrollable;
3723         if (parent->isScrollable(frameScrollability))
3724             return true;
3725     }
3726
3727     return false;
3728 }
3729
3730 void FrameView::updateScrollableAreaSet()
3731 {
3732     // That ensures that only inner frames are cached.
3733     FrameView* parentFrameView = this->parentFrameView();
3734     if (!parentFrameView)
3735         return;
3736
3737     if (!isScrollable()) {
3738         parentFrameView->removeScrollableArea(this);
3739         return;
3740     }
3741
3742     parentFrameView->addScrollableArea(this);
3743 }
3744
3745 bool FrameView::shouldSuspendScrollAnimations() const
3746 {
3747     return frame().loader().state() != FrameStateComplete;
3748 }
3749
3750 void FrameView::scrollbarStyleChanged(ScrollbarStyle newStyle, bool forceUpdate)
3751 {
3752     if (!frame().isMainFrame())
3753         return;
3754
3755     if (Page* page = frame().page())
3756         page->chrome().client().recommendedScrollbarStyleDidChange(newStyle);
3757
3758     ScrollView::scrollbarStyleChanged(newStyle, forceUpdate);
3759 }
3760
3761 void FrameView::notifyPageThatContentAreaWillPaint() const
3762 {
3763     Page* page = frame().page();
3764     if (!page)
3765         return;
3766
3767     contentAreaWillPaint();
3768
3769     if (!m_scrollableAreas)
3770         return;
3771
3772     for (auto& scrollableArea : *m_scrollableAreas)
3773         scrollableArea->contentAreaWillPaint();
3774 }
3775
3776 bool FrameView::scrollAnimatorEnabled() const
3777 {
3778 #if ENABLE(SMOOTH_SCROLLING)
3779     if (Page* page = frame().page())
3780         return page->settings().scrollAnimatorEnabled();
3781 #endif
3782
3783     return false;
3784 }
3785
3786 #if ENABLE(DASHBOARD_SUPPORT)
3787 void FrameView::updateAnnotatedRegions()
3788 {
3789     Document* document = frame().document();
3790     if (!document->hasAnnotatedRegions())
3791         return;
3792     Vector<AnnotatedRegionValue> newRegions;
3793     document->renderBox()->collectAnnotatedRegions(newRegions);
3794     if (newRegions == document->annotatedRegions())
3795         return;
3796     document->setAnnotatedRegions(newRegions);
3797     Page* page = frame().page();
3798     if (!page)
3799         return;
3800     page->chrome().client().annotatedRegionsChanged();
3801 }
3802 #endif
3803
3804 void FrameView::updateScrollCorner()
3805 {
3806     RenderElement* renderer = nullptr;
3807     std::unique_ptr<RenderStyle> cornerStyle;
3808     IntRect cornerRect = scrollCornerRect();
3809     
3810     if (!cornerRect.isEmpty()) {
3811         // Try the <body> element first as a scroll corner source.
3812         Document* doc = frame().document();
3813         Element* body = doc ? doc->bodyOrFrameset() : nullptr;
3814         if (body && body->renderer()) {
3815             renderer = body->renderer();
3816             cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3817         }
3818         
3819         if (!cornerStyle) {
3820             // If the <body> didn't have a custom style, then the root element might.
3821             Element* docElement = doc ? doc->documentElement() : nullptr;
3822             if (docElement && docElement->renderer()) {
3823                 renderer = docElement->renderer();
3824                 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3825             }
3826         }
3827         
3828         if (!cornerStyle) {
3829             // If we have an owning iframe/frame element, then it can set the custom scrollbar also.
3830             if (RenderWidget* renderer = frame().ownerRenderer())
3831                 cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), &renderer->style());
3832         }
3833     }
3834
3835     if (!cornerStyle)
3836         m_scrollCorner = nullptr;
3837     else {
3838         if (!m_scrollCorner) {
3839             m_scrollCorner = createRenderer<RenderScrollbarPart>(renderer->document(), WTFMove(*cornerStyle));
3840             m_scrollCorner->initializeStyle();
3841         } else
3842             m_scrollCorner->setStyle(WTFMove(*cornerStyle));
3843         invalidateScrollCorner(cornerRect);
3844     }
3845 }
3846
3847 void FrameView::paintScrollCorner(GraphicsContext& context, const IntRect& cornerRect)
3848 {
3849     if (context.updatingControlTints()) {
3850         updateScrollCorner();
3851         return;
3852     }
3853
3854     if (m_scrollCorner) {
3855         if (frame().isMainFrame())
3856             context.fillRect(cornerRect, baseBackgroundColor());
3857         m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect);
3858         return;
3859     }
3860
3861     ScrollView::paintScrollCorner(context, cornerRect);
3862 }
3863
3864 void FrameView::paintScrollbar(GraphicsContext& context, Scrollbar& bar, const IntRect& rect)
3865 {
3866     if (bar.isCustomScrollbar() && frame().isMainFrame()) {
3867         IntRect toFill = bar.frameRect();
3868         toFill.intersect(rect);
3869         context.fillRect(toFill, baseBackgroundColor());
3870     }
3871
3872     ScrollView::paintScrollbar(context, bar, rect);
3873 }
3874
3875 Color FrameView::documentBackgroundColor() const
3876 {
3877     // <https://bugs.webkit.org/show_bug.cgi?id=59540> We blend the background color of
3878     // the document and the body against the base background color of the frame view.
3879     // Background images are unfortunately impractical to include.
3880
3881     // Return invalid Color objects whenever there is insufficient information.
3882     if (!frame().document())
3883         return Color();
3884
3885     auto* htmlElement = frame().document()->documentElement();
3886     auto* bodyElement = frame().document()->bodyOrFrameset();
3887
3888     // Start with invalid colors.
3889     Color htmlBackgroundColor;
3890     Color bodyBackgroundColor;
3891     if (htmlElement && htmlElement->renderer())
3892         htmlBackgroundColor = htmlElement->renderer()->style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
3893     if (bodyElement && bodyElement->renderer())
3894         bodyBackgroundColor = bodyElement->renderer()->style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
3895
3896     if (!bodyBackgroundColor.isValid()) {
3897         if (!htmlBackgroundColor.isValid())
3898             return Color();
3899         return baseBackgroundColor().blend(htmlBackgroundColor);
3900     }
3901
3902     if (!htmlBackgroundColor.isValid())
3903         return baseBackgroundColor().blend(bodyBackgroundColor);
3904
3905     // We take the aggregate of the base background color
3906     // the <html> background color, and the <body>
3907     // background color to find the document color. The
3908     // addition of the base background color is not
3909     // technically part of the document background, but it
3910     // otherwise poses problems when the aggregate is not
3911     // fully opaque.
3912     return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor);
3913 }
3914
3915 bool FrameView::hasCustomScrollbars() const
3916 {
3917     for (auto& widget : children()) {
3918         if (is<FrameView>(widget)) {
3919             if (downcast<FrameView>(widget.get()).hasCustomScrollbars())
3920                 return true;
3921         } else if (is<Scrollbar>(widget)) {
3922             if (downcast<Scrollbar>(widget.get()).isCustomScrollbar())
3923                 return true;
3924         }
3925     }
3926     return false;
3927 }
3928
3929 FrameView* FrameView::parentFrameView() const
3930 {
3931     if (!parent())
3932         return nullptr;
3933     auto* parentFrame = frame().tree().parent();
3934     if (!parentFrame)
3935         return nullptr;
3936     return parentFrame->view();
3937 }
3938
3939 bool FrameView::isInChildFrameWithFrameFlattening() const
3940 {
3941     if (!frameFlatteningEnabled())
3942         return false;
3943
3944     if (!parent())
3945         return false;
3946
3947     HTMLFrameOwnerElement* ownerElement = frame().ownerElement();
3948     if (!ownerElement)
3949         return false;
3950
3951     if (!ownerElement->renderWidget())
3952         return false;
3953
3954     // Frame flattening applies when the owner element is either in a frameset or
3955     // an iframe with flattening parameters.
3956     if (is<HTMLIFrameElement>(*ownerElement))
3957         return downcast<RenderIFrame>(*ownerElement->renderWidget()).flattenFrame();
3958
3959     if (is<HTMLFrameElement>(*ownerElement))
3960         return true;
3961
3962     return false;
3963 }
3964
3965 void FrameView::updateControlTints()
3966 {
3967     // This is called when control tints are changed from aqua/graphite to clear and vice versa.
3968     // We do a "fake" paint, and when the theme gets a paint call, it can then do an invalidate.
3969     // This is only done if the theme supports control tinting. It's up to the theme and platform
3970     // to define when controls get the tint and to call this function when that changes.
3971     
3972     // Optimize the common case where we bring a window to the front while it's still empty.
3973     if (frame().document()->url().isEmpty())
3974         return;
3975
3976     // As noted above, this is a "fake" paint, so we should pause counting relevant repainted objects.
3977     Page* page = frame().page();
3978     bool isCurrentlyCountingRelevantRepaintedObject = false;
3979     if (page) {
3980         isCurrentlyCountingRelevantRepaintedObject = page->isCountingRelevantRepaintedObjects();
3981         page->setIsCountingRelevantRepaintedObjects(false);
3982     }
3983
3984     RenderView* renderView = this->renderView();
3985     if ((renderView && renderView->theme().supportsControlTints()) || hasCustomScrollbars())
3986         paintControlTints();
3987
3988     if (page)
3989         page->setIsCountingRelevantRepaintedObjects(isCurrentlyCountingRelevantRepaintedObject);
3990 }
3991
3992 void FrameView::paintControlTints()
3993 {
3994     if (needsLayout())
3995         layoutContext().layout();
3996
3997     GraphicsContext context(GraphicsContext::NonPaintingReasons::UpdatingControlTints);
3998     if (platformWidget()) {
3999         // FIXME: consult paintsEntireContents().
4000         paintContents(context, visibleContentRect(LegacyIOSDocumentVisibleRect));
4001     } else
4002         paint(context, frameRect());
4003 }
4004
4005 bool FrameView::wasScrolledByUser() const
4006 {
4007     return m_wasScrolledByUser;
4008 }
4009
4010 void FrameView::setWasScrolledByUser(bool wasScrolledByUser)
4011 {
4012     LOG(Scrolling, "FrameView::setWasScrolledByUser at %d", wasScrolledByUser);
4013
4014     m_shouldScrollToFocusedElement = false;
4015     m_delayedScrollToFocusedElementTimer.stop();
4016     if (m_inProgrammaticScroll)
4017         return;
4018     m_maintainScrollPositionAnchor = nullptr;
4019     if (m_wasScrolledByUser == wasScrolledByUser)
4020         return;
4021     m_wasScrolledByUser = wasScrolledByUser;
4022     if (frame().isMainFrame())
4023         updateLayerFlushThrottling();
4024     adjustTiledBackingCoverage();
4025 }
4026
4027 void FrameView::willPaintContents(GraphicsContext& context, const IntRect&, PaintingState& paintingState)
4028 {
4029     Document* document = frame().document();
4030
4031     if (!context.paintingDisabled())
4032         InspectorInstrumentation::willPaint(*renderView());
4033
4034     paintingState.isTopLevelPainter = !sCurrentPaintTimeStamp;
4035
4036     if (paintingState.isTopLevelPainter)
4037         sCurrentPaintTimeStamp = MonotonicTime::now();
4038
4039     paintingState.paintBehavior = m_paintBehavior;
4040     
4041     if (FrameView* parentView = parentFrameView()) {
4042         if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
4043             m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
4044         
4045         if (parentView->paintBehavior() & PaintBehaviorSnapshotting)
4046             m_paintBehavior |= PaintBehaviorSnapshotting;
4047         
4048         if (parentView->paintBehavior() & PaintBehaviorTileFirstPaint)
4049             m_paintBehavior |= PaintBehaviorTileFirstPaint;
4050     }
4051
4052     if (document->printing())
4053         m_paintBehavior |= (PaintBehaviorFlattenCompositingLayers | PaintBehaviorSnapshotting);
4054
4055     paintingState.isFlatteningPaintOfRootFrame = (m_paintBehavior & PaintBehaviorFlattenCompositingLayers) && !frame().ownerElement();
4056     if (paintingState.isFlatteningPaintOfRootFrame)
4057         notifyWidgetsInAllFrames(WillPaintFlattened);
4058
4059     ASSERT(!m_isPainting);
4060     m_isPainting = true;
4061 }
4062
4063 void FrameView::didPaintContents(GraphicsContext& context, const IntRect& dirtyRect, PaintingState& paintingState)
4064 {
4065     m_isPainting = false;
4066
4067     if (paintingState.isFlatteningPaintOfRootFrame)
4068         notifyWidgetsInAllFrames(DidPaintFlattened);
4069
4070     m_paintBehavior = paintingState.paintBehavior;
4071     m_lastPaintTime = MonotonicTime::now();
4072
4073     // Regions may have changed as a result of the visibility/z-index of element changing.
4074 #if ENABLE(DASHBOARD_SUPPORT)
4075     if (frame().document()->annotatedRegionsDirty())
4076         updateAnnotatedRegions();
4077 #endif
4078
4079     if (paintingState.isTopLevelPainter)
4080         sCurrentPaintTimeStamp = MonotonicTime();
4081
4082     if (!context.paintingDisabled()) {
4083         InspectorInstrumentation::didPaint(*renderView(), dirtyRect);
4084         // FIXME: should probably not fire milestones for snapshot painting. https://bugs.webkit.org/show_bug.cgi?id=117623
4085         firePaintRelatedMilestonesIfNeeded();
4086     }
4087 }
4088
4089 void FrameView::paintContents(GraphicsContext& context, const IntRect& dirtyRect, SecurityOriginPaintPolicy securityOriginPaintPolicy)
4090 {
4091 #ifndef NDEBUG
4092     bool fillWithWarningColor;
4093     if (frame().document()->printing())
4094         fillWithWarningColor = false; // Printing, don't fill with red (can't remember why).
4095     else if (frame().ownerElement())
4096         fillWithWarningColor = false; // Subframe, don't fill with red.
4097     else if (isTransparent())
4098         fillWithWarningColor = false; // Transparent, don't fill with red.
4099     else if (m_paintBehavior & PaintBehaviorSelectionOnly)
4100         fillWithWarningColor = false; // Selections are transparent, don't fill with red.
4101     else if (m_nodeToDraw)
4102         fillWithWarningColor = false; // Element images are transparent, don't fill with red.
4103     else
4104         fillWithWarningColor = true;
4105     
4106     if (fillWithWarningColor)
4107         context.fillRect(dirtyRect, Color(255, 64, 255));
4108 #endif
4109
4110     RenderView* renderView = this->renderView();
4111     if (!renderView) {
4112         LOG_ERROR("called FrameView::paint with nil renderer");
4113         return;
4114     }
4115
4116     if (!layoutContext().inPaintableState())
4117         return;
4118
4119     ASSERT(!needsLayout());
4120     if (needsLayout())
4121         return;
4122
4123     PaintingState paintingState;
4124     willPaintContents(context, dirtyRect, paintingState);
4125
4126     // m_nodeToDraw is used to draw only one element (and its descendants)
4127     RenderObject* renderer = m_nodeToDraw ? m_nodeToDraw->renderer() : nullptr;
4128     RenderLayer* rootLayer = renderView->layer();
4129
4130 #ifndef NDEBUG
4131     RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&rootLayer->renderer());
4132 #endif
4133
4134     // To work around http://webkit.org/b/135106, ensure that the paint root isn't an inline with culled line boxes.
4135     // FIXME: This can cause additional content to be included in the snapshot, so remove this once that bug is fixed.
4136     while (is<RenderInline>(renderer) && !downcast<RenderInline>(*renderer).firstLineBox())
4137         renderer = renderer->parent();
4138
4139     rootLayer->paint(context, dirtyRect, LayoutSize(), m_paintBehavior, renderer, 0, securityOriginPaintPolicy == SecurityOriginPaintPolicy::AnyOrigin ? RenderLayer::SecurityOriginPaintPolicy::AnyOrigin : RenderLayer::SecurityOriginPaintPolicy::AccessibleOriginOnly);
4140     if (rootLayer->containsDirtyOverlayScrollbars())
4141         rootLayer->paintOverlayScrollbars(context, dirtyRect, m_paintBehavior, renderer);
4142
4143     didPaintContents(context, dirtyRect, paintingState);
4144 }
4145
4146 void FrameView::setPaintBehavior(PaintBehavior behavior)
4147 {
4148     m_paintBehavior = behavior;
4149 }
4150
4151 PaintBehavior FrameView::paintBehavior() const
4152 {
4153     return m_paintBehavior;
4154 }
4155
4156 bool FrameView::isPainting() const
4157 {
4158     return m_isPainting;
4159 }
4160
4161 // FIXME: change this to use the subtreePaint terminology.
4162 void FrameView::setNodeToDraw(Node* node)
4163 {
4164     m_nodeToDraw = node;
4165 }
4166
4167 void FrameView::paintContentsForSnapshot(GraphicsContext& context, const IntRect& imageRect, SelectionInSnapshot shouldPaintSelection, CoordinateSpaceForSnapshot coordinateSpace)
4168 {
4169     updateLayoutAndStyleIfNeededRecursive();
4170
4171     // Cache paint behavior and set a new behavior appropriate for snapshots.
4172     PaintBehavior oldBehavior = paintBehavior();
4173     setPaintBehavior(oldBehavior | (PaintBehaviorFlattenCompositingLayers | PaintBehaviorSnapshotting));
4174
4175     // If the snapshot should exclude selection, then we'll clear the current selection
4176     // in the render tree only. This will allow us to restore the selection from the DOM
4177     // after we paint the snapshot.
4178     if (shouldPaintSelection == ExcludeSelection) {
4179         for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr())) {
4180             if (auto* renderView = frame->contentRenderer())
4181                 renderView->selection().clear();
4182         }
4183     }
4184
4185     if (coordinateSpace == DocumentCoordinates)
4186         paintContents(context, imageRect);
4187     else {
4188         // A snapshot in ViewCoordinates will include a scrollbar, and the snapshot will contain
4189         // whatever content the document is currently scrolled to.
4190         paint(context, imageRect);
4191     }
4192
4193     // Restore selection.
4194     if (shouldPaintSelection == ExcludeSelection) {
4195         for (auto* frame = m_frame.ptr(); frame; frame = frame->tree().traverseNext(m_frame.ptr()))
4196             frame->selection().updateAppearance();
4197     }
4198
4199     // Restore cached paint behavior.
4200     setPaintBehavior(oldBehavior);
4201 }
4202
4203 void FrameView::paintOverhangAreas(GraphicsContext& context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
4204 {
4205     if (context.paintingDisabled())
4206         return;
4207
4208     if (frame().document()->printing())
4209         return;
4210
4211     ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
4212 }
4213
4214 void FrameView::updateLayoutAndStyleIfNeededRecursive()
4215 {
4216     // Style updating, render tree creation, and layout needs to be done multiple times
4217     // for more than one reason. But one reason is that when an <object> element determines
4218     // what it needs to load a subframe, a second pass is needed. That requires update
4219     // passes equal to the number of levels of DOM nesting. That is why this number is large.
4220     // There are test cases where we have roughly 10 levels of DOM nesting, so this needs to
4221     // be greater than that. We have a limit to avoid the possibility of an infinite loop.
4222     // Typical calls will run the loop 2 times (once to do work, once to detect no further work
4223     // is needed).
4224     // FIXME: We should find an approach that does not require a loop at all.
4225     const unsigned maxUpdatePasses = 25;
4226
4227     // Style updates can trigger script, which can cause this FrameView to be destroyed.
4228     Ref<FrameView> protectedThis(*this);
4229
4230     AnimationUpdateBlock animationUpdateBlock(&frame().animation());
4231
4232     using DescendantsDeque = Deque<Ref<FrameView>, 16>;
4233     auto nextRenderedDescendant = [this] (DescendantsDeque& descendantsDeque) -> RefPtr<FrameView> {
4234         if (descendantsDeque.isEmpty())
4235             descendantsDeque.append(*this);
4236         else {
4237             // Append renderered children after processing the parent, in case the processing
4238             // affects the set of rendered children.
4239             auto previousView = descendantsDeque.takeFirst();
4240             for (auto* frame = previousView->frame().tree().firstRenderedChild(); frame; frame = frame->tree().nextRenderedSibling()) {
4241                 if (auto* view = frame->view())
4242                     descendantsDeque.append(*view);
4243             }
4244             if (descendantsDeque.isEmpty())
4245                 return nullptr;
4246         }
4247         return descendantsDeque.first().ptr();
4248     };
4249
4250  &