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