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