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