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