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