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