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