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