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