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