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, 2005, 2006, 2007, 2008 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 "third_party/blink/renderer/core/frame/local_frame_view.h"
28 
29 #include <algorithm>
30 #include <memory>
31 #include <utility>
32 
33 #include "base/feature_list.h"
34 #include "base/memory/ptr_util.h"
35 #include "base/metrics/field_trial_params.h"
36 #include "base/numerics/safe_conversions.h"
37 #include "cc/input/main_thread_scrolling_reason.h"
38 #include "cc/layers/picture_layer.h"
39 #include "cc/tiles/frame_viewer_instrumentation.h"
40 #include "cc/trees/layer_tree_host.h"
41 #include "third_party/blink/public/common/features.h"
42 #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
43 #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
44 #include "third_party/blink/public/platform/task_type.h"
45 #include "third_party/blink/public/platform/web_rect.h"
46 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
47 #include "third_party/blink/renderer/core/accessibility/apply_dark_mode.h"
48 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
49 #include "third_party/blink/renderer/core/animation/document_animations.h"
50 #include "third_party/blink/renderer/core/css/font_face_set_document.h"
51 #include "third_party/blink/renderer/core/css/style_change_reason.h"
52 #include "third_party/blink/renderer/core/dom/static_node_list.h"
53 #include "third_party/blink/renderer/core/editing/compute_layer_selection.h"
54 #include "third_party/blink/renderer/core/editing/drag_caret.h"
55 #include "third_party/blink/renderer/core/editing/frame_selection.h"
56 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
57 #include "third_party/blink/renderer/core/events/error_event.h"
58 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
59 #include "third_party/blink/renderer/core/frame/browser_controls.h"
60 #include "third_party/blink/renderer/core/frame/find_in_page.h"
61 #include "third_party/blink/renderer/core/frame/frame_overlay.h"
62 #include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.h"
63 #include "third_party/blink/renderer/core/frame/local_frame.h"
64 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
65 #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
66 #include "third_party/blink/renderer/core/frame/location.h"
67 #include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
68 #include "third_party/blink/renderer/core/frame/remote_frame.h"
69 #include "third_party/blink/renderer/core/frame/remote_frame_view.h"
70 #include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
71 #include "third_party/blink/renderer/core/frame/settings.h"
72 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
73 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
74 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
75 #include "third_party/blink/renderer/core/html/forms/text_control_element.h"
76 #include "third_party/blink/renderer/core/html/html_frame_element.h"
77 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
78 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
79 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
80 #include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
81 #include "third_party/blink/renderer/core/html/portal/portal_contents.h"
82 #include "third_party/blink/renderer/core/html_names.h"
83 #include "third_party/blink/renderer/core/input/event_handler.h"
84 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
85 #include "third_party/blink/renderer/core/intersection_observer/intersection_observation.h"
86 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
87 #include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
88 #include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
89 #include "third_party/blink/renderer/core/layout/layout_analyzer.h"
90 #include "third_party/blink/renderer/core/layout/layout_counter.h"
91 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
92 #include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
93 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
94 #include "third_party/blink/renderer/core/layout/layout_view.h"
95 #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
96 #include "third_party/blink/renderer/core/layout/style_retain_scope.h"
97 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
98 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
99 #include "third_party/blink/renderer/core/layout/traced_layout_object.h"
100 #include "third_party/blink/renderer/core/loader/document_loader.h"
101 #include "third_party/blink/renderer/core/loader/frame_loader.h"
102 #include "third_party/blink/renderer/core/media_type_names.h"
103 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
104 #include "third_party/blink/renderer/core/page/chrome_client.h"
105 #include "third_party/blink/renderer/core/page/focus_controller.h"
106 #include "third_party/blink/renderer/core/page/frame_tree.h"
107 #include "third_party/blink/renderer/core/page/link_highlight.h"
108 #include "third_party/blink/renderer/core/page/page.h"
109 #include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
110 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
111 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
112 #include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
113 #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
114 #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
115 #include "third_party/blink/renderer/core/page/validation_message_client.h"
116 #include "third_party/blink/renderer/core/paint/block_paint_invalidator.h"
117 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
118 #include "third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h"
119 #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
120 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
121 #include "third_party/blink/renderer/core/paint/frame_painter.h"
122 #include "third_party/blink/renderer/core/paint/paint_layer.h"
123 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
124 #include "third_party/blink/renderer/core/paint/paint_timing.h"
125 #include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
126 #include "third_party/blink/renderer/core/paint/pre_paint_tree_walk.h"
127 #include "third_party/blink/renderer/core/probe/core_probes.h"
128 #include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
129 #include "third_party/blink/renderer/core/scroll/scroll_alignment.h"
130 #include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
131 #include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
132 #include "third_party/blink/renderer/core/style/computed_style.h"
133 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
134 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
135 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
136 #include "third_party/blink/renderer/platform/geometry/double_rect.h"
137 #include "third_party/blink/renderer/platform/geometry/float_quad.h"
138 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
139 #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
140 #include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
141 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
142 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
143 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
144 #include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
145 #include "third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.h"
146 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
147 #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
148 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
149 #include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
150 #include "third_party/blink/renderer/platform/language.h"
151 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
152 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
153 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
154 #include "third_party/blink/renderer/platform/web_test_support.h"
155 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
156 #include "third_party/skia/include/core/SkBitmap.h"
157 #include "ui/base/cursor/cursor.h"
158 #include "ui/base/mojom/cursor_type.mojom-blink.h"
159 
160 // Used to check for dirty layouts violating document lifecycle rules.
161 // If arg evaluates to true, the program will continue. If arg evaluates to
162 // false, program will crash if DCHECK_IS_ON() or return false from the current
163 // function.
164 #define CHECK_FOR_DIRTY_LAYOUT(arg) \
165   do {                              \
166     if (!(arg)) {                   \
167       NOTREACHED();                 \
168       return false;                 \
169     }                               \
170   } while (false)
171 
172 namespace blink {
173 namespace {
174 
175 // Logs a UseCounter for the size of the cursor that will be set. This will be
176 // used for compatibility analysis to determine whether the maximum size can be
177 // reduced.
LogCursorSizeCounter(LocalFrame * frame,const ui::Cursor & cursor)178 void LogCursorSizeCounter(LocalFrame* frame, const ui::Cursor& cursor) {
179   DCHECK(frame);
180   SkBitmap bitmap = cursor.custom_bitmap();
181   if (cursor.type() != ui::mojom::blink::CursorType::kCustom || bitmap.isNull())
182     return;
183   // Should not overflow, this calculation is done elsewhere when determining
184   // whether the cursor exceeds its maximum size (see event_handler.cc).
185   auto scaled_size = IntSize(bitmap.width(), bitmap.height());
186   scaled_size.Scale(1 / cursor.image_scale_factor());
187   if (scaled_size.Width() > 64 || scaled_size.Height() > 64) {
188     UseCounter::Count(frame->GetDocument(), WebFeature::kCursorImageGT64x64);
189   } else if (scaled_size.Width() > 32 || scaled_size.Height() > 32) {
190     UseCounter::Count(frame->GetDocument(), WebFeature::kCursorImageGT32x32);
191   } else {
192     UseCounter::Count(frame->GetDocument(), WebFeature::kCursorImageLE32x32);
193   }
194 }
195 
196 // Default value and parameter name for how long we want to delay the
197 // compositor commit beyond the start of document lifdecycle updates to avoid
198 // flash between navigations. The delay should be small enough so that it won't
199 // confuse users expecting a new page to appear after navigation and the omnibar
200 // has updated the url display.
201 constexpr int kPaintHoldingCommitDelayDefaultInMs = 500;  // 30 frames @ 60hz
202 constexpr char kPaintHoldingCommitDelayParameterName[] = "commit_delay";
203 
204 // Get the field trial parameter value for Paint Holding.
GetCommitDelayForPaintHolding()205 base::TimeDelta GetCommitDelayForPaintHolding() {
206   DCHECK(base::FeatureList::IsEnabled(blink::features::kPaintHolding));
207   return base::TimeDelta::FromMilliseconds(
208       base::GetFieldTrialParamByFeatureAsInt(
209           blink::features::kPaintHolding, kPaintHoldingCommitDelayParameterName,
210           kPaintHoldingCommitDelayDefaultInMs));
211 }
212 
213 }  // namespace
214 
215 // The maximum number of updatePlugins iterations that should be done before
216 // returning.
217 static const unsigned kMaxUpdatePluginsIterations = 2;
218 
LocalFrameView(LocalFrame & frame)219 LocalFrameView::LocalFrameView(LocalFrame& frame)
220     : LocalFrameView(frame, IntRect()) {
221   Show();
222 }
223 
LocalFrameView(LocalFrame & frame,const IntSize & initial_size)224 LocalFrameView::LocalFrameView(LocalFrame& frame, const IntSize& initial_size)
225     : LocalFrameView(frame, IntRect(IntPoint(), initial_size)) {
226   SetLayoutSizeInternal(initial_size);
227   Show();
228 }
229 
LocalFrameView(LocalFrame & frame,IntRect frame_rect)230 LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
231     : FrameView(frame_rect),
232       frame_(frame),
233       display_mode_(blink::mojom::DisplayMode::kBrowser),
234       can_have_scrollbars_(true),
235       has_pending_layout_(false),
236       layout_scheduling_enabled_(true),
237       layout_count_for_testing_(0),
238       lifecycle_update_count_for_testing_(0),
239       nested_layout_count_(0),
240       // We want plugin updates to happen in FIFO order with loading tasks.
241       update_plugins_timer_(frame.GetTaskRunner(TaskType::kInternalLoading),
242                             this,
243                             &LocalFrameView::UpdatePluginsTimerFired),
244       first_layout_(true),
245       base_background_color_(Color::kWhite),
246       last_zoom_factor_(1.0f),
247       media_type_(media_type_names::kScreen),
248       safe_to_propagate_scroll_to_parent_(true),
249       visually_non_empty_character_count_(0),
250       visually_non_empty_pixel_count_(0),
251       is_visually_non_empty_(false),
252       sticky_position_object_count_(0),
253       layout_size_fixed_to_frame_size_(true),
254       needs_update_geometries_(false),
255       root_layer_did_scroll_(false),
256       frame_timing_requests_dirty_(true),
257       // The compositor throttles the main frame using deferred begin main frame
258       // updates. We can't throttle it here or it seems the root compositor
259       // doesn't get setup properly.
260       lifecycle_updates_throttled_(!GetFrame().IsMainFrame()),
261       current_update_lifecycle_phases_target_state_(
262           DocumentLifecycle::kUninitialized),
263       past_layout_lifecycle_update_(false),
264       suppress_adjust_view_size_(false),
265       intersection_observation_state_(kNotNeeded),
266       needs_forced_compositing_update_(false),
267       needs_focus_on_fragment_(false),
268       in_lifecycle_update_(false),
269       main_thread_scrolling_reasons_(0),
270       forced_layout_stack_depth_(0),
271       forced_layout_start_time_(base::TimeTicks()),
272       paint_frame_count_(0),
273       unique_id_(NewUniqueObjectId()),
274       layout_shift_tracker_(std::make_unique<LayoutShiftTracker>(this)),
275       paint_timing_detector_(MakeGarbageCollected<PaintTimingDetector>(this))
276 #if DCHECK_IS_ON()
277       ,
278       is_updating_descendant_dependent_flags_(false)
279 #endif
280 {
281   // Propagate the marginwidth/height and scrolling modes to the view.
282   if (frame_->Owner() && frame_->Owner()->ScrollbarMode() ==
283                              mojom::blink::ScrollbarMode::kAlwaysOff)
284     SetCanHaveScrollbars(false);
285 }
286 
~LocalFrameView()287 LocalFrameView::~LocalFrameView() {
288 #if DCHECK_IS_ON()
289   DCHECK(has_been_disposed_);
290 #endif
291 }
292 
Trace(Visitor * visitor)293 void LocalFrameView::Trace(Visitor* visitor) {
294   visitor->Trace(frame_);
295   visitor->Trace(fragment_anchor_);
296   visitor->Trace(scrollable_areas_);
297   visitor->Trace(animating_scrollable_areas_);
298   visitor->Trace(auto_size_info_);
299   visitor->Trace(plugins_);
300   visitor->Trace(scrollbars_);
301   visitor->Trace(viewport_scrollable_area_);
302   visitor->Trace(anchoring_adjustment_queue_);
303   visitor->Trace(scroll_event_queue_);
304   visitor->Trace(paint_timing_detector_);
305   visitor->Trace(lifecycle_observers_);
306 }
307 
308 template <typename Function>
ForAllChildViewsAndPlugins(const Function & function)309 void LocalFrameView::ForAllChildViewsAndPlugins(const Function& function) {
310   for (Frame* child = frame_->Tree().FirstChild(); child;
311        child = child->Tree().NextSibling()) {
312     if (child->View())
313       function(*child->View());
314   }
315 
316   for (const auto& plugin : plugins_) {
317     function(*plugin);
318   }
319 
320   if (Document* document = frame_->GetDocument()) {
321     for (PortalContents* portal :
322          DocumentPortals::From(*document).GetPortals()) {
323       if (Frame* frame = portal->GetFrame())
324         function(*frame->View());
325     }
326   }
327 }
328 
329 template <typename Function>
ForAllChildLocalFrameViews(const Function & function)330 void LocalFrameView::ForAllChildLocalFrameViews(const Function& function) {
331   for (Frame* child = frame_->Tree().FirstChild(); child;
332        child = child->Tree().NextSibling()) {
333     auto* child_local_frame = DynamicTo<LocalFrame>(child);
334     if (!child_local_frame)
335       continue;
336     if (LocalFrameView* child_view = child_local_frame->View())
337       function(*child_view);
338   }
339 }
340 
341 // Call function for each non-throttled frame view in pre-order. If this logic
342 // is updated, consider updating |ForAllThrottledLocalFrameViews| too.
343 template <typename Function>
ForAllNonThrottledLocalFrameViews(const Function & function)344 void LocalFrameView::ForAllNonThrottledLocalFrameViews(
345     const Function& function) {
346   if (ShouldThrottleRendering())
347     return;
348 
349   function(*this);
350 
351   for (Frame* child = frame_->Tree().FirstChild(); child;
352        child = child->Tree().NextSibling()) {
353     auto* child_local_frame = DynamicTo<LocalFrame>(child);
354     if (!child_local_frame)
355       continue;
356     if (LocalFrameView* child_view = child_local_frame->View())
357       child_view->ForAllNonThrottledLocalFrameViews(function);
358   }
359 }
360 
361 // Call function for each throttled frame view in pre-order. If this logic is
362 // updated, consider updating |ForAllNonThrottledLocalFrameViews| too.
363 template <typename Function>
ForAllThrottledLocalFrameViews(const Function & function)364 void LocalFrameView::ForAllThrottledLocalFrameViews(const Function& function) {
365   if (!ShouldThrottleRendering())
366     return;
367 
368   function(*this);
369 
370   for (Frame* child = frame_->Tree().FirstChild(); child;
371        child = child->Tree().NextSibling()) {
372     auto* child_local_frame = DynamicTo<LocalFrame>(child);
373     if (!child_local_frame)
374       continue;
375     if (LocalFrameView* child_view = child_local_frame->View())
376       child_view->ForAllNonThrottledLocalFrameViews(function);
377   }
378 }
379 
380 template <typename Function>
ForAllRemoteFrameViews(const Function & function)381 void LocalFrameView::ForAllRemoteFrameViews(const Function& function) {
382   for (Frame* child = frame_->Tree().FirstChild(); child;
383        child = child->Tree().NextSibling()) {
384     if (child->IsLocalFrame()) {
385       To<LocalFrame>(child)->View()->ForAllRemoteFrameViews(function);
386     } else {
387       DCHECK(child->IsRemoteFrame());
388       if (RemoteFrameView* view = To<RemoteFrame>(child)->View())
389         function(*view);
390     }
391   }
392   if (Document* document = frame_->GetDocument()) {
393     for (PortalContents* portal :
394          DocumentPortals::From(*document).GetPortals()) {
395       if (RemoteFrame* frame = portal->GetFrame()) {
396         if (RemoteFrameView* view = frame->View())
397           function(*view);
398       }
399     }
400   }
401 }
402 
Dispose()403 void LocalFrameView::Dispose() {
404   CHECK(!IsInPerformLayout());
405 
406   // TODO(dcheng): It's wrong that the frame can be detached before the
407   // LocalFrameView. Figure out what's going on and fix LocalFrameView to be
408   // disposed with the correct timing.
409 
410   // We need to clear the RootFrameViewport's animator since it gets called
411   // from non-GC'd objects and RootFrameViewport will still have a pointer to
412   // this class.
413   if (viewport_scrollable_area_)
414     viewport_scrollable_area_->ClearScrollableArea();
415 
416   // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
417   // partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
418   auto_size_info_.Clear();
419 
420   // FIXME: Do we need to do something here for OOPI?
421   HTMLFrameOwnerElement* owner_element = frame_->DeprecatedLocalOwner();
422   // TODO(dcheng): It seems buggy that we can have an owner element that points
423   // to another EmbeddedContentView. This can happen when a plugin element loads
424   // a frame (EmbeddedContentView A of type LocalFrameView) and then loads a
425   // plugin (EmbeddedContentView B of type WebPluginContainerImpl). In this
426   // case, the frame's view is A and the frame element's
427   // OwnedEmbeddedContentView is B. See https://crbug.com/673170 for an example.
428   if (owner_element && owner_element->OwnedEmbeddedContentView() == this)
429     owner_element->SetEmbeddedContentView(nullptr);
430 
431   ukm_aggregator_.reset();
432   layout_shift_tracker_->Dispose();
433 
434 #if DCHECK_IS_ON()
435   has_been_disposed_ = true;
436 #endif
437 }
438 
InvalidateAllCustomScrollbarsOnActiveChanged()439 void LocalFrameView::InvalidateAllCustomScrollbarsOnActiveChanged() {
440   bool uses_window_inactive_selector =
441       frame_->GetDocument()->GetStyleEngine().UsesWindowInactiveSelector();
442 
443   ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
444     frame_view.InvalidateAllCustomScrollbarsOnActiveChanged();
445   });
446 
447   for (const auto& scrollbar : scrollbars_) {
448     if (uses_window_inactive_selector && scrollbar->IsCustomScrollbar())
449       scrollbar->StyleChanged();
450   }
451 }
452 
DidFirstLayout() const453 bool LocalFrameView::DidFirstLayout() const {
454   return !first_layout_;
455 }
456 
LifecycleUpdatesActive() const457 bool LocalFrameView::LifecycleUpdatesActive() const {
458   return !lifecycle_updates_throttled_;
459 }
460 
SetLifecycleUpdatesThrottledForTesting()461 void LocalFrameView::SetLifecycleUpdatesThrottledForTesting() {
462   lifecycle_updates_throttled_ = true;
463 }
464 
InvalidateRect(const IntRect & rect)465 void LocalFrameView::InvalidateRect(const IntRect& rect) {
466   auto* layout_object = GetLayoutEmbeddedContent();
467   if (!layout_object)
468     return;
469 
470   IntRect paint_invalidation_rect = rect;
471   paint_invalidation_rect.Move(
472       (layout_object->BorderLeft() + layout_object->PaddingLeft()).ToInt(),
473       (layout_object->BorderTop() + layout_object->PaddingTop()).ToInt());
474   layout_object->InvalidatePaintRectangle(
475       PhysicalRect(paint_invalidation_rect));
476 }
477 
FrameRectsChanged(const IntRect & old_rect)478 void LocalFrameView::FrameRectsChanged(const IntRect& old_rect) {
479   const bool width_changed = Size().Width() != old_rect.Width();
480   const bool height_changed = Size().Height() != old_rect.Height();
481 
482   PropagateFrameRects();
483 
484   if (FrameRect() != old_rect) {
485     if (auto* layout_view = GetLayoutView())
486       layout_view->SetShouldCheckForPaintInvalidation();
487   }
488 
489   if (width_changed || height_changed) {
490     ViewportSizeChanged(width_changed, height_changed);
491     if (frame_->IsMainFrame())
492       frame_->GetPage()->GetVisualViewport().MainFrameDidChangeSize();
493     GetFrame().Loader().RestoreScrollPositionAndViewState();
494   }
495 }
496 
GetPage() const497 Page* LocalFrameView::GetPage() const {
498   return GetFrame().GetPage();
499 }
500 
GetLayoutView() const501 LayoutView* LocalFrameView::GetLayoutView() const {
502   return GetFrame().ContentLayoutObject();
503 }
504 
GetScrollingCoordinator() const505 ScrollingCoordinator* LocalFrameView::GetScrollingCoordinator() const {
506   Page* p = GetPage();
507   return p ? p->GetScrollingCoordinator() : nullptr;
508 }
509 
GetScrollingContext() const510 ScrollingCoordinatorContext* LocalFrameView::GetScrollingContext() const {
511   LocalFrame* root = &GetFrame().LocalFrameRoot();
512   if (GetFrame() != root)
513     return root->View()->GetScrollingContext();
514 
515   if (!scrolling_context_)
516     scrolling_context_.reset(new ScrollingCoordinatorContext());
517   return scrolling_context_.get();
518 }
519 
GetCompositorAnimationHost() const520 cc::AnimationHost* LocalFrameView::GetCompositorAnimationHost() const {
521   if (GetScrollingContext()->GetCompositorAnimationHost())
522     return GetScrollingContext()->GetCompositorAnimationHost();
523 
524   if (!GetFrame().LocalFrameRoot().IsMainFrame())
525     return nullptr;
526 
527   // TODO(kenrb): Compositor animation host and timeline for the main frame
528   // still live on ScrollingCoordinator. https://crbug.com/680606.
529   ScrollingCoordinator* c = GetScrollingCoordinator();
530   return c ? c->GetCompositorAnimationHost() : nullptr;
531 }
532 
GetCompositorAnimationTimeline() const533 CompositorAnimationTimeline* LocalFrameView::GetCompositorAnimationTimeline()
534     const {
535   if (GetScrollingContext()->GetCompositorAnimationTimeline())
536     return GetScrollingContext()->GetCompositorAnimationTimeline();
537 
538   if (!GetFrame().LocalFrameRoot().IsMainFrame())
539     return nullptr;
540 
541   // TODO(kenrb): Compositor animation host and timeline for the main frame
542   // still live on ScrollingCoordinator. https://crbug.com/680606.
543   ScrollingCoordinator* c = GetScrollingCoordinator();
544   return c ? c->GetCompositorAnimationTimeline() : nullptr;
545 }
546 
SetLayoutOverflowSize(const IntSize & size)547 void LocalFrameView::SetLayoutOverflowSize(const IntSize& size) {
548   if (size == layout_overflow_size_)
549     return;
550 
551   layout_overflow_size_ = size;
552 
553   Page* page = GetFrame().GetPage();
554   if (!page)
555     return;
556   page->GetChromeClient().ContentsSizeChanged(frame_.Get(), size);
557 }
558 
AdjustViewSize()559 void LocalFrameView::AdjustViewSize() {
560   if (suppress_adjust_view_size_)
561     return;
562 
563   LayoutView* layout_view = GetLayoutView();
564   if (!layout_view)
565     return;
566 
567   DCHECK_EQ(frame_->View(), this);
568   SetLayoutOverflowSize(
569       PixelSnappedIntRect(layout_view->DocumentRect()).Size());
570 }
571 
AdjustViewSizeAndLayout()572 void LocalFrameView::AdjustViewSizeAndLayout() {
573   AdjustViewSize();
574   if (NeedsLayout()) {
575     base::AutoReset<bool> suppress_adjust_view_size(&suppress_adjust_view_size_,
576                                                     true);
577     UpdateLayout();
578   }
579 }
580 
UpdateCountersAfterStyleChange()581 void LocalFrameView::UpdateCountersAfterStyleChange() {
582   auto* layout_view = GetLayoutView();
583   DCHECK(layout_view);
584   layout_view->UpdateCounters();
585 }
586 
CountObjectsNeedingLayout(unsigned & needs_layout_objects,unsigned & total_objects,bool & is_subtree)587 void LocalFrameView::CountObjectsNeedingLayout(unsigned& needs_layout_objects,
588                                                unsigned& total_objects,
589                                                bool& is_subtree) {
590   needs_layout_objects = 0;
591   total_objects = 0;
592   is_subtree = IsSubtreeLayout();
593   if (is_subtree) {
594     layout_subtree_root_list_.CountObjectsNeedingLayout(needs_layout_objects,
595                                                         total_objects);
596   } else {
597     LayoutSubtreeRootList::CountObjectsNeedingLayoutInRoot(
598         GetLayoutView(), needs_layout_objects, total_objects);
599   }
600 }
601 
PerformPreLayoutTasks()602 void LocalFrameView::PerformPreLayoutTasks() {
603   TRACE_EVENT0("blink,benchmark", "LocalFrameView::performPreLayoutTasks");
604   Lifecycle().AdvanceTo(DocumentLifecycle::kInPreLayout);
605 
606   // Don't schedule more layouts, we're in one.
607   base::AutoReset<bool> change_scheduling_enabled(&layout_scheduling_enabled_,
608                                                   false);
609 
610   bool was_resized = WasViewportResized();
611   Document* document = frame_->GetDocument();
612   if (was_resized)
613     document->SetResizedForViewportUnits();
614 
615   // Viewport-dependent or device-dependent media queries may cause us to need
616   // completely different style information.
617   bool main_frame_rotation =
618       frame_->IsMainFrame() && frame_->GetSettings() &&
619       frame_->GetSettings()->GetMainFrameResizesAreOrientationChanges();
620   if ((was_resized &&
621        document->GetStyleEngine().MediaQueryAffectedByViewportChange()) ||
622       (was_resized && main_frame_rotation &&
623        document->GetStyleEngine().MediaQueryAffectedByDeviceChange())) {
624     document->MediaQueryAffectingValueChanged(MediaValueChange::kSize);
625   } else if (was_resized) {
626     document->EvaluateMediaQueryList();
627   }
628 
629   document->UpdateStyleAndLayoutTree();
630 
631   // Update style for all embedded SVG documents underneath this frame, so
632   // that intrinsic size computation for any embedded objects has up-to-date
633   // information before layout.
634   ForAllChildLocalFrameViews([](LocalFrameView& view) {
635     Document& document = *view.GetFrame().GetDocument();
636     if (document.IsSVGDocument())
637       document.UpdateStyleAndLayoutTree();
638   });
639 
640   Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean);
641 
642   if (was_resized)
643     document->ClearResizedForViewportUnits();
644 }
645 
LayoutFromRootObject(LayoutObject & root)646 void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
647   LayoutState layout_state(root);
648   if (scrollable_areas_) {
649     for (auto& scrollable_area : *scrollable_areas_) {
650       if (scrollable_area->GetScrollAnchor() &&
651           scrollable_area->ShouldPerformScrollAnchoring())
652         scrollable_area->GetScrollAnchor()->NotifyBeforeLayout();
653     }
654   }
655 
656   root.UpdateLayout();
657 }
658 
PrepareLayoutAnalyzer()659 void LocalFrameView::PrepareLayoutAnalyzer() {
660   bool is_tracing = false;
661   TRACE_EVENT_CATEGORY_GROUP_ENABLED(
662       TRACE_DISABLED_BY_DEFAULT("blink.debug.layout"), &is_tracing);
663   if (!is_tracing) {
664     analyzer_.reset();
665     return;
666   }
667   if (!analyzer_)
668     analyzer_ = std::make_unique<LayoutAnalyzer>();
669   analyzer_->Reset();
670 }
671 
AnalyzerCounters()672 std::unique_ptr<TracedValue> LocalFrameView::AnalyzerCounters() {
673   if (!analyzer_)
674     return std::make_unique<TracedValue>();
675   std::unique_ptr<TracedValue> value = analyzer_->ToTracedValue();
676   value->SetString("host", GetLayoutView()->GetDocument().location()->host());
677   value->SetString(
678       "frame",
679       String::Format("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(frame_.Get())));
680   value->SetInteger(
681       "contentsHeightAfterLayout",
682       PixelSnappedIntRect(GetLayoutView()->DocumentRect()).Height());
683   value->SetInteger("visibleHeight", Height());
684   value->SetInteger("approximateBlankCharacterCount",
685                     base::saturated_cast<int>(
686                         FontFaceSetDocument::ApproximateBlankCharacterCount(
687                             *frame_->GetDocument())));
688   return value;
689 }
690 
691 #define PERFORM_LAYOUT_TRACE_CATEGORIES \
692   "blink,benchmark,rail," TRACE_DISABLED_BY_DEFAULT("blink.debug.layout")
693 
PerformLayout(bool in_subtree_layout)694 void LocalFrameView::PerformLayout(bool in_subtree_layout) {
695   DCHECK(in_subtree_layout || layout_subtree_root_list_.IsEmpty());
696 
697   double contents_height_before_layout =
698       GetLayoutView()->DocumentRect().Height();
699   TRACE_EVENT_BEGIN1(
700       PERFORM_LAYOUT_TRACE_CATEGORIES, "LocalFrameView::performLayout",
701       "contentsHeightBeforeLayout", contents_height_before_layout);
702   PrepareLayoutAnalyzer();
703 
704   ScriptForbiddenScope forbid_script;
705 
706   if (in_subtree_layout && HasOrthogonalWritingModeRoots()) {
707     // If we're going to lay out from each subtree root, rather than once from
708     // LayoutView, we need to merge the depth-ordered orthogonal writing mode
709     // root list into the depth-ordered list of subtrees scheduled for
710     // layout. Otherwise, during layout of one such subtree, we'd risk skipping
711     // over a subtree of objects needing layout.
712     DCHECK(!layout_subtree_root_list_.IsEmpty());
713     ScheduleOrthogonalWritingModeRootsForLayout();
714   }
715 
716   DCHECK(!IsInPerformLayout());
717   Lifecycle().AdvanceTo(DocumentLifecycle::kInPerformLayout);
718 
719   // performLayout is the actual guts of layout().
720   // FIXME: The 300 other lines in layout() probably belong in other helper
721   // functions so that a single human could understand what layout() is actually
722   // doing.
723 
724   {
725     // TODO(szager): Remove this after diagnosing crash.
726     DocumentLifecycle::CheckNoTransitionScope check_no_transition(Lifecycle());
727     if (in_subtree_layout) {
728       if (analyzer_) {
729         analyzer_->Increment(LayoutAnalyzer::kPerformLayoutRootLayoutObjects,
730                              layout_subtree_root_list_.size());
731       }
732       for (auto& root : layout_subtree_root_list_.Ordered()) {
733         if (!root->NeedsLayout())
734           continue;
735         LayoutFromRootObject(*root);
736 
737         root->PaintingLayer()->UpdateLayerPositionsAfterLayout();
738 
739         // We need to ensure that we mark up all layoutObjects up to the
740         // LayoutView for paint invalidation. This simplifies our code as we
741         // just always do a full tree walk.
742         if (LayoutObject* container = root->Container())
743           container->SetShouldCheckForPaintInvalidation();
744       }
745       layout_subtree_root_list_.Clear();
746     } else {
747       if (HasOrthogonalWritingModeRoots())
748         LayoutOrthogonalWritingModeRoots();
749       GetLayoutView()->UpdateLayout();
750     }
751   }
752 
753   frame_->GetDocument()->Fetcher()->UpdateAllImageResourcePriorities();
754 
755   Lifecycle().AdvanceTo(DocumentLifecycle::kAfterPerformLayout);
756 
757   TRACE_EVENT_END1(PERFORM_LAYOUT_TRACE_CATEGORIES,
758                    "LocalFrameView::performLayout", "counters",
759                    AnalyzerCounters());
760   FirstMeaningfulPaintDetector::From(*frame_->GetDocument())
761       .MarkNextPaintAsMeaningfulIfNeeded(
762           layout_object_counter_, contents_height_before_layout,
763           GetLayoutView()->DocumentRect().Height(), Height());
764 }
765 
UpdateLayout()766 void LocalFrameView::UpdateLayout() {
767   // We should never layout a Document which is not in a LocalFrame.
768   DCHECK(frame_);
769   DCHECK_EQ(frame_->View(), this);
770   DCHECK(frame_->GetPage());
771 
772   ScriptForbiddenScope forbid_script;
773 
774   if (IsInPerformLayout() || ShouldThrottleRendering() ||
775       !frame_->GetDocument()->IsActive() || frame_->IsProvisional())
776     return;
777 
778   TRACE_EVENT0("blink,benchmark", "LocalFrameView::layout");
779 
780   RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
781                            RuntimeCallStats::CounterId::kUpdateLayout);
782 
783   // The actual call to UpdateGeometries is in PerformPostLayoutTasks.
784   SetNeedsUpdateGeometries();
785 
786   if (auto_size_info_)
787     auto_size_info_->AutoSizeIfNeeded();
788 
789   has_pending_layout_ = false;
790 
791   Document* document = frame_->GetDocument();
792   TRACE_EVENT_BEGIN1("devtools.timeline", "Layout", "beginData",
793                      inspector_layout_event::BeginData(this));
794   probe::UpdateLayout probe(document);
795 
796   PerformPreLayoutTasks();
797 
798   VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport();
799   DoubleSize viewport_size(visual_viewport.VisibleWidthCSSPx(),
800                            visual_viewport.VisibleHeightCSSPx());
801 
802   // TODO(crbug.com/460956): The notion of a single root for layout is no
803   // longer applicable. Remove or update this code.
804   LayoutObject* root_for_this_layout = GetLayoutView();
805 
806   FontCachePurgePreventer font_cache_purge_preventer;
807   StyleRetainScope style_retain_scope;
808   bool in_subtree_layout = false;
809   {
810     base::AutoReset<bool> change_scheduling_enabled(&layout_scheduling_enabled_,
811                                                     false);
812     nested_layout_count_++;
813 
814     // If the layout view was marked as needing layout after we added items in
815     // the subtree roots we need to clear the roots and do the layout from the
816     // layoutView.
817     if (GetLayoutView()->NeedsLayout())
818       ClearLayoutSubtreeRootsAndMarkContainingBlocks();
819     GetLayoutView()->ClearHitTestCache();
820 
821     in_subtree_layout = IsSubtreeLayout();
822 
823     // TODO(crbug.com/460956): The notion of a single root for layout is no
824     // longer applicable. Remove or update this code.
825     if (in_subtree_layout)
826       root_for_this_layout = layout_subtree_root_list_.RandomRoot();
827 
828     if (!root_for_this_layout) {
829       // FIXME: Do we need to set m_size here?
830       NOTREACHED();
831       return;
832     }
833 
834     if (!in_subtree_layout) {
835       ClearLayoutSubtreeRootsAndMarkContainingBlocks();
836       Node* body = document->body();
837       if (body && body->GetLayoutObject()) {
838         if (IsA<HTMLFrameSetElement>(*body)) {
839           body->GetLayoutObject()->SetChildNeedsLayout();
840         } else if (IsA<HTMLBodyElement>(*body)) {
841           if (!first_layout_ && size_.Height() != GetLayoutSize().Height() &&
842               body->GetLayoutObject()->EnclosingBox()->StretchesToViewport())
843             body->GetLayoutObject()->SetChildNeedsLayout();
844         }
845       }
846 
847       if (first_layout_) {
848         first_layout_ = false;
849         last_viewport_size_ = GetLayoutSize();
850         last_zoom_factor_ = GetLayoutView()->StyleRef().Zoom();
851 
852         mojom::blink::ScrollbarMode h_mode;
853         mojom::blink::ScrollbarMode v_mode;
854         GetLayoutView()->CalculateScrollbarModes(h_mode, v_mode);
855         if (v_mode == mojom::blink::ScrollbarMode::kAuto) {
856           GetLayoutView()
857               ->GetScrollableArea()
858               ->ForceVerticalScrollbarForFirstLayout();
859         }
860       }
861 
862       LayoutSize old_size = size_;
863 
864       size_ = LayoutSize(GetLayoutSize());
865 
866       if (old_size != size_ && !first_layout_) {
867         LayoutBox* root_layout_object =
868             document->documentElement()
869                 ? document->documentElement()->GetLayoutBox()
870                 : nullptr;
871         LayoutBox* body_layout_object = root_layout_object && document->body()
872                                             ? document->body()->GetLayoutBox()
873                                             : nullptr;
874         if (body_layout_object && body_layout_object->StretchesToViewport())
875           body_layout_object->SetChildNeedsLayout();
876         else if (root_layout_object &&
877                  root_layout_object->StretchesToViewport())
878           root_layout_object->SetChildNeedsLayout();
879       }
880     }
881 
882     TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
883         TRACE_DISABLED_BY_DEFAULT("blink.debug.layout.trees"), "LayoutTree",
884         this, TracedLayoutObject::Create(*GetLayoutView(), false));
885 
886     IntSize old_size(Size());
887 
888     PerformLayout(in_subtree_layout);
889 
890     IntSize new_size(Size());
891     if (old_size != new_size) {
892       MarkViewportConstrainedObjectsForLayout(
893           old_size.Width() != new_size.Width(),
894           old_size.Height() != new_size.Height());
895     }
896 
897     if (frame_->IsMainFrame()) {
898       if (auto* text_autosizer = frame_->GetDocument()->GetTextAutosizer()) {
899         if (text_autosizer->HasLayoutInlineSizeChanged())
900           text_autosizer->UpdatePageInfoInAllFrames(frame_);
901       }
902     }
903 
904     if (NeedsLayout()) {
905       base::AutoReset<bool> suppress(&suppress_adjust_view_size_, true);
906       UpdateLayout();
907     }
908 
909     DCHECK(layout_subtree_root_list_.IsEmpty());
910   }  // Reset m_layoutSchedulingEnabled to its previous value.
911   CheckDoesNotNeedLayout();
912 
913   DocumentLifecycle::Scope lifecycle_scope(Lifecycle(),
914                                            DocumentLifecycle::kLayoutClean);
915 
916   frame_timing_requests_dirty_ = true;
917 
918   if (!in_subtree_layout)
919     GetLayoutView()->EnclosingLayer()->UpdateLayerPositionsAfterLayout();
920 
921   TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
922       TRACE_DISABLED_BY_DEFAULT("blink.debug.layout.trees"), "LayoutTree", this,
923       TracedLayoutObject::Create(*GetLayoutView(), true));
924 
925   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
926     GetLayoutView()->Compositor()->DidLayout();
927   layout_count_for_testing_++;
928 
929   if (AXObjectCache* cache = document->ExistingAXObjectCache()) {
930     const KURL& url = document->Url();
931     if (url.IsValid() && !url.IsAboutBlankURL()) {
932       // TODO(kschmi) move HandleLayoutComplete to the accessibility lifecycle
933       // stage. crbug.com/1062122
934       cache->HandleLayoutComplete(document);
935     }
936   }
937 
938   UpdateDocumentAnnotatedRegions();
939   CheckDoesNotNeedLayout();
940 
941   if (nested_layout_count_ == 1) {
942     PerformPostLayoutTasks();
943     CheckDoesNotNeedLayout();
944   }
945 
946   // FIXME: The notion of a single root for layout is no longer applicable.
947   // Remove or update this code. crbug.com/460596
948   TRACE_EVENT_END1("devtools.timeline", "Layout", "endData",
949                    inspector_layout_event::EndData(root_for_this_layout));
950   probe::DidChangeViewport(frame_.Get());
951 
952   nested_layout_count_--;
953   if (nested_layout_count_)
954     return;
955 
956 #if DCHECK_IS_ON()
957   // Post-layout assert that nobody was re-marked as needing layout during
958   // layout.
959   GetLayoutView()->AssertSubtreeIsLaidOut();
960 #endif
961 
962   if (frame_->IsMainFrame()) {
963     // Scrollbars changing state can cause a visual viewport size change.
964     DoubleSize new_viewport_size(visual_viewport.VisibleWidthCSSPx(),
965                                  visual_viewport.VisibleHeightCSSPx());
966     if (new_viewport_size != viewport_size)
967       frame_->GetDocument()->EnqueueVisualViewportResizeEvent();
968   }
969 
970   GetFrame().GetDocument()->LayoutUpdated();
971   CheckDoesNotNeedLayout();
972 }
973 
WillStartForcedLayout()974 void LocalFrameView::WillStartForcedLayout() {
975   // UpdateLayout is re-entrant for auto-sizing and plugins. So keep
976   // track of stack depth to include all the time in the top-level call.
977   forced_layout_stack_depth_++;
978   if (forced_layout_stack_depth_ > 1)
979     return;
980   forced_layout_start_time_ = base::TimeTicks::Now();
981 }
982 
DidFinishForcedLayout(DocumentUpdateReason reason)983 void LocalFrameView::DidFinishForcedLayout(DocumentUpdateReason reason) {
984   CHECK_GT(forced_layout_stack_depth_, (unsigned)0);
985   forced_layout_stack_depth_--;
986   if (!forced_layout_stack_depth_ && base::TimeTicks::IsHighResolution()) {
987     LocalFrameUkmAggregator& aggregator = EnsureUkmAggregator();
988     aggregator.RecordSample(
989         static_cast<size_t>(LocalFrameUkmAggregator::kForcedStyleAndLayout),
990         forced_layout_start_time_, base::TimeTicks::Now());
991     if (reason == DocumentUpdateReason::kHitTest) {
992       aggregator.RecordSample(
993           static_cast<size_t>(LocalFrameUkmAggregator::kHitTestDocumentUpdate),
994           forced_layout_start_time_, base::TimeTicks::Now());
995     }
996   }
997 }
998 
SetNeedsPaintPropertyUpdate()999 void LocalFrameView::SetNeedsPaintPropertyUpdate() {
1000   if (auto* layout_view = GetLayoutView())
1001     layout_view->SetNeedsPaintPropertyUpdate();
1002 }
1003 
ViewportSizeForViewportUnits() const1004 FloatSize LocalFrameView::ViewportSizeForViewportUnits() const {
1005   float zoom = 1;
1006   if (!frame_->GetDocument() || !frame_->GetDocument()->Printing())
1007     zoom = GetFrame().PageZoomFactor();
1008 
1009   auto* layout_view = GetLayoutView();
1010   if (!layout_view)
1011     return FloatSize();
1012 
1013   FloatSize layout_size;
1014   layout_size.SetWidth(layout_view->ViewWidth(kIncludeScrollbars) / zoom);
1015   layout_size.SetHeight(layout_view->ViewHeight(kIncludeScrollbars) / zoom);
1016 
1017   BrowserControls& browser_controls = frame_->GetPage()->GetBrowserControls();
1018   if (browser_controls.PermittedState() != cc::BrowserControlsState::kHidden) {
1019     // We use the layoutSize rather than frameRect to calculate viewport units
1020     // so that we get correct results on mobile where the page is laid out into
1021     // a rect that may be larger than the viewport (e.g. the 980px fallback
1022     // width for desktop pages). Since the layout height is statically set to
1023     // be the viewport with browser controls showing, we add the browser
1024     // controls height, compensating for page scale as well, since we want to
1025     // use the viewport with browser controls hidden for vh (to match Safari).
1026     int viewport_width = frame_->GetPage()->GetVisualViewport().Size().Width();
1027     if (frame_->IsMainFrame() && layout_size.Width() && viewport_width) {
1028       // TODO(bokan/eirage): BrowserControl height may need to account for the
1029       // zoom factor when use-zoom-for-dsf is enabled on Android. Confirm this
1030       // works correctly when that's turned on. https://crbug.com/737777.
1031       float page_scale_at_layout_width = viewport_width / layout_size.Width();
1032       layout_size.Expand(0, (browser_controls.TotalHeight() -
1033                              browser_controls.TotalMinHeight()) /
1034                                 page_scale_at_layout_width);
1035     }
1036   }
1037 
1038   return layout_size;
1039 }
1040 
ViewportSizeForMediaQueries() const1041 FloatSize LocalFrameView::ViewportSizeForMediaQueries() const {
1042   FloatSize viewport_size(layout_size_);
1043   if (!frame_->GetDocument()->Printing()) {
1044     float zoom = GetFrame().PageZoomFactor();
1045     viewport_size.SetWidth(
1046         AdjustForAbsoluteZoom::AdjustInt(layout_size_.Width(), zoom));
1047     viewport_size.SetHeight(
1048         AdjustForAbsoluteZoom::AdjustInt(layout_size_.Height(), zoom));
1049   }
1050   return viewport_size;
1051 }
1052 
Lifecycle() const1053 DocumentLifecycle& LocalFrameView::Lifecycle() const {
1054   DCHECK(frame_);
1055   DCHECK(frame_->GetDocument());
1056   return frame_->GetDocument()->Lifecycle();
1057 }
1058 
RunPostLifecycleSteps()1059 void LocalFrameView::RunPostLifecycleSteps() {
1060   RunIntersectionObserverSteps();
1061 }
1062 
RunIntersectionObserverSteps()1063 void LocalFrameView::RunIntersectionObserverSteps() {
1064 #if DCHECK_IS_ON()
1065   bool was_dirty = NeedsLayout();
1066 #endif
1067   if (ShouldThrottleRendering() || Lifecycle().LifecyclePostponed() ||
1068       !frame_->GetDocument()->IsActive()) {
1069     return;
1070   }
1071 
1072   if (frame_->IsMainFrame()) {
1073     EnsureOverlayInterstitialAdDetector().MaybeFireDetection(frame_.Get());
1074 
1075     // Report the main frame's document intersection with itself.
1076     LayoutObject* layout_object = GetLayoutView();
1077     IntRect main_frame_dimensions =
1078         ToLayoutBox(layout_object)->PixelSnappedLayoutOverflowRect();
1079     GetFrame().Client()->OnMainFrameDocumentIntersectionChanged(WebRect(
1080         0, 0, main_frame_dimensions.Width(), main_frame_dimensions.Height()));
1081   }
1082 
1083   TRACE_EVENT0("blink,benchmark",
1084                "LocalFrameView::UpdateViewportIntersectionsForSubtree");
1085   SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
1086                            LocalFrameUkmAggregator::kIntersectionObservation);
1087 
1088   unsigned flags = 0;
1089   if (frame_->CanSkipStickyFrameTracking())
1090     flags |= IntersectionObservation::kCanSkipStickyFrameTracking;
1091 
1092   bool needs_occlusion_tracking = UpdateViewportIntersectionsForSubtree(flags);
1093   if (FrameOwner* owner = frame_->Owner())
1094     owner->SetNeedsOcclusionTracking(needs_occlusion_tracking);
1095 #if DCHECK_IS_ON()
1096   DCHECK(was_dirty || !NeedsLayout());
1097 #endif
1098   DeliverSynchronousIntersectionObservations();
1099 }
1100 
ForceUpdateViewportIntersections()1101 void LocalFrameView::ForceUpdateViewportIntersections() {
1102   // IntersectionObserver targets in this frame (and its frame tree) need to
1103   // update; but we can't wait for a lifecycle update to run them, because a
1104   // hidden frame won't run lifecycle updates. Force layout and run them now.
1105   DocumentLifecycle::DisallowThrottlingScope disallow_throttling(Lifecycle());
1106   UpdateLifecycleToCompositingCleanPlusScrolling(
1107       DocumentUpdateReason::kIntersectionObservation);
1108   UpdateViewportIntersectionsForSubtree(
1109       IntersectionObservation::kImplicitRootObserversNeedUpdate |
1110       IntersectionObservation::kIgnoreDelay);
1111 }
1112 
EmbeddedReplacedContent() const1113 LayoutSVGRoot* LocalFrameView::EmbeddedReplacedContent() const {
1114   auto* layout_view = this->GetLayoutView();
1115   if (!layout_view)
1116     return nullptr;
1117 
1118   LayoutObject* first_child = layout_view->FirstChild();
1119   if (!first_child || !first_child->IsBox())
1120     return nullptr;
1121 
1122   // Currently only embedded SVG documents participate in the size-negotiation
1123   // logic.
1124   return ToLayoutSVGRootOrNull(first_child);
1125 }
1126 
GetIntrinsicSizingInfo(IntrinsicSizingInfo & intrinsic_sizing_info) const1127 bool LocalFrameView::GetIntrinsicSizingInfo(
1128     IntrinsicSizingInfo& intrinsic_sizing_info) const {
1129   if (LayoutSVGRoot* content_layout_object = EmbeddedReplacedContent()) {
1130     content_layout_object->UnscaledIntrinsicSizingInfo(intrinsic_sizing_info);
1131     return true;
1132   }
1133   return false;
1134 }
1135 
HasIntrinsicSizingInfo() const1136 bool LocalFrameView::HasIntrinsicSizingInfo() const {
1137   return EmbeddedReplacedContent();
1138 }
1139 
UpdateGeometry()1140 void LocalFrameView::UpdateGeometry() {
1141   LayoutEmbeddedContent* layout = GetLayoutEmbeddedContent();
1142   if (!layout)
1143     return;
1144 
1145   bool did_need_layout = NeedsLayout();
1146 
1147   PhysicalRect new_frame = layout->ReplacedContentRect();
1148 #if DCHECK_IS_ON()
1149   if (new_frame.Width() != LayoutUnit::Max().RawValue() &&
1150       new_frame.Height() != LayoutUnit::Max().RawValue())
1151     DCHECK(!new_frame.size.HasFraction());
1152 #endif
1153   bool bounds_will_change = PhysicalSize(Size()) != new_frame.size;
1154 
1155   // If frame bounds are changing mark the view for layout. Also check the
1156   // frame's page to make sure that the frame isn't in the process of being
1157   // destroyed. If iframe scrollbars needs reconstruction from native to custom
1158   // scrollbar, then also we need to layout the frameview.
1159   if (bounds_will_change)
1160     SetNeedsLayout();
1161 
1162   layout->UpdateGeometry(*this);
1163   // If view needs layout, either because bounds have changed or possibly
1164   // indicating content size is wrong, we have to do a layout to set the right
1165   // LocalFrameView size.
1166   if (NeedsLayout())
1167     UpdateLayout();
1168 
1169   if (!did_need_layout && !ShouldThrottleRendering())
1170     CheckDoesNotNeedLayout();
1171 }
1172 
AddPartToUpdate(LayoutEmbeddedObject & object)1173 void LocalFrameView::AddPartToUpdate(LayoutEmbeddedObject& object) {
1174   DCHECK(IsInPerformLayout());
1175   // Tell the DOM element that it needs a Plugin update.
1176   Node* node = object.GetNode();
1177   DCHECK(node);
1178   if (IsA<HTMLObjectElement>(*node) || IsA<HTMLEmbedElement>(*node))
1179     To<HTMLPlugInElement>(node)->SetNeedsPluginUpdate(true);
1180 
1181   part_update_set_.insert(&object);
1182 }
1183 
SetDisplayMode(blink::mojom::DisplayMode mode)1184 void LocalFrameView::SetDisplayMode(blink::mojom::DisplayMode mode) {
1185   if (mode == display_mode_)
1186     return;
1187 
1188   display_mode_ = mode;
1189 
1190   if (frame_->GetDocument()) {
1191     frame_->GetDocument()->MediaQueryAffectingValueChanged(
1192         MediaValueChange::kOther);
1193   }
1194 }
1195 
SetDisplayShape(DisplayShape display_shape)1196 void LocalFrameView::SetDisplayShape(DisplayShape display_shape) {
1197   if (display_shape == display_shape_)
1198     return;
1199 
1200   display_shape_ = display_shape;
1201 
1202   if (frame_->GetDocument()) {
1203     frame_->GetDocument()->MediaQueryAffectingValueChanged(
1204         MediaValueChange::kOther);
1205   }
1206 }
1207 
SetMediaType(const AtomicString & media_type)1208 void LocalFrameView::SetMediaType(const AtomicString& media_type) {
1209   DCHECK(frame_->GetDocument());
1210   media_type_ = media_type;
1211   frame_->GetDocument()->MediaQueryAffectingValueChanged(
1212       MediaValueChange::kOther);
1213 }
1214 
MediaType() const1215 AtomicString LocalFrameView::MediaType() const {
1216   // See if we have an override type.
1217   if (frame_->GetSettings() &&
1218       !frame_->GetSettings()->GetMediaTypeOverride().IsEmpty())
1219     return AtomicString(frame_->GetSettings()->GetMediaTypeOverride());
1220   return media_type_;
1221 }
1222 
AdjustMediaTypeForPrinting(bool printing)1223 void LocalFrameView::AdjustMediaTypeForPrinting(bool printing) {
1224   if (printing) {
1225     if (media_type_when_not_printing_.IsNull())
1226       media_type_when_not_printing_ = MediaType();
1227     SetMediaType(media_type_names::kPrint);
1228   } else {
1229     if (!media_type_when_not_printing_.IsNull())
1230       SetMediaType(media_type_when_not_printing_);
1231     media_type_when_not_printing_ = g_null_atom;
1232   }
1233 
1234   frame_->GetDocument()->GetStyleEngine().MarkViewportStyleDirty();
1235   frame_->GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc(
1236       StyleChangeReasonForTracing::Create(
1237           style_change_reason::kStyleSheetChange));
1238 }
1239 
AddBackgroundAttachmentFixedObject(LayoutObject * object)1240 void LocalFrameView::AddBackgroundAttachmentFixedObject(LayoutObject* object) {
1241   DCHECK(!background_attachment_fixed_objects_.Contains(object));
1242 
1243   background_attachment_fixed_objects_.insert(object);
1244 
1245   // Ensure main thread scrolling reasons are recomputed.
1246   SetNeedsPaintPropertyUpdate();
1247   // The object's scroll properties are not affected by its own background.
1248   object->SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling();
1249 }
1250 
RemoveBackgroundAttachmentFixedObject(LayoutObject * object)1251 void LocalFrameView::RemoveBackgroundAttachmentFixedObject(
1252     LayoutObject* object) {
1253   DCHECK(background_attachment_fixed_objects_.Contains(object));
1254 
1255   background_attachment_fixed_objects_.erase(object);
1256 
1257   // Ensure main thread scrolling reasons are recomputed.
1258   SetNeedsPaintPropertyUpdate();
1259   // The object's scroll properties are not affected by its own background.
1260   object->SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling();
1261 }
1262 
RequiresMainThreadScrollingForBackgroundAttachmentFixed() const1263 bool LocalFrameView::RequiresMainThreadScrollingForBackgroundAttachmentFixed()
1264     const {
1265   if (background_attachment_fixed_objects_.IsEmpty())
1266     return false;
1267   if (background_attachment_fixed_objects_.size() > 1)
1268     return true;
1269 
1270   const auto* object =
1271       ToLayoutBoxModelObject(*background_attachment_fixed_objects_.begin());
1272   // We should not add such object in the set.
1273   DCHECK(!object->BackgroundTransfersToView());
1274   // If the background is viewport background and it paints onto the main
1275   // graphics layer only, then it doesn't need main thread scrolling.
1276   if (IsA<LayoutView>(object) &&
1277       object->GetBackgroundPaintLocation() == kBackgroundPaintInGraphicsLayer)
1278     return false;
1279   return true;
1280 }
1281 
AddViewportConstrainedObject(LayoutObject & object)1282 void LocalFrameView::AddViewportConstrainedObject(LayoutObject& object) {
1283   if (!viewport_constrained_objects_)
1284     viewport_constrained_objects_ = std::make_unique<ObjectSet>();
1285 
1286   viewport_constrained_objects_->insert(&object);
1287 }
1288 
RemoveViewportConstrainedObject(LayoutObject & object)1289 void LocalFrameView::RemoveViewportConstrainedObject(LayoutObject& object) {
1290   if (viewport_constrained_objects_)
1291     viewport_constrained_objects_->erase(&object);
1292 }
1293 
ViewportSizeChanged(bool width_changed,bool height_changed)1294 void LocalFrameView::ViewportSizeChanged(bool width_changed,
1295                                          bool height_changed) {
1296   DCHECK(width_changed || height_changed);
1297   DCHECK(frame_->GetPage());
1298   if (frame_->GetDocument() &&
1299       frame_->GetDocument()->Lifecycle().LifecyclePostponed())
1300     return;
1301 
1302   if (frame_->IsMainFrame())
1303     layout_shift_tracker_->NotifyViewportSizeChanged();
1304 
1305   auto* layout_view = GetLayoutView();
1306   if (layout_view) {
1307     // If this is the main frame, we might have got here by hiding/showing the
1308     // top controls.  In that case, layout won't be triggered, so we need to
1309     // clamp the scroll offset here.
1310     if (GetFrame().IsMainFrame()) {
1311       layout_view->Layer()->UpdateSize();
1312       layout_view->GetScrollableArea()->ClampScrollOffsetAfterOverflowChange();
1313     }
1314 
1315     // TODO(pdr): |UsesCompositing()| will be false with CompositeAfterPaint but
1316     // do we need to do these updates?
1317     if (layout_view->UsesCompositing()) {
1318       layout_view->Layer()->SetNeedsCompositingInputsUpdate();
1319       SetNeedsPaintPropertyUpdate();
1320     }
1321   }
1322 
1323   if (GetFrame().GetDocument())
1324     GetFrame().GetDocument()->GetRootScrollerController().DidResizeFrameView();
1325 
1326   // Change of viewport size after browser controls showing/hiding may affect
1327   // painting of the background.
1328   if (layout_view && frame_->IsMainFrame() &&
1329       frame_->GetPage()->GetBrowserControls().TotalHeight())
1330     layout_view->SetShouldCheckForPaintInvalidation();
1331 
1332   if (GetFrame().GetDocument() && !IsInPerformLayout())
1333     MarkViewportConstrainedObjectsForLayout(width_changed, height_changed);
1334 
1335   if (GetPaintTimingDetector().Visualizer())
1336     GetPaintTimingDetector().Visualizer()->OnViewportChanged();
1337 }
1338 
MarkViewportConstrainedObjectsForLayout(bool width_changed,bool height_changed)1339 void LocalFrameView::MarkViewportConstrainedObjectsForLayout(
1340     bool width_changed,
1341     bool height_changed) {
1342   if (!HasViewportConstrainedObjects() || !(width_changed || height_changed))
1343     return;
1344 
1345   for (auto* const viewport_constrained_object :
1346        *viewport_constrained_objects_) {
1347     LayoutObject* layout_object = viewport_constrained_object;
1348     const ComputedStyle& style = layout_object->StyleRef();
1349     if (width_changed) {
1350       if (style.Width().IsFixed() &&
1351           (style.Left().IsAuto() || style.Right().IsAuto())) {
1352         layout_object->SetNeedsPositionedMovementLayout();
1353       } else {
1354         layout_object->SetNeedsLayoutAndFullPaintInvalidation(
1355             layout_invalidation_reason::kSizeChanged);
1356       }
1357     }
1358     if (height_changed) {
1359       if (style.Height().IsFixed() &&
1360           (style.Top().IsAuto() || style.Bottom().IsAuto())) {
1361         layout_object->SetNeedsPositionedMovementLayout();
1362       } else {
1363         layout_object->SetNeedsLayoutAndFullPaintInvalidation(
1364             layout_invalidation_reason::kSizeChanged);
1365       }
1366     }
1367   }
1368 }
1369 
ShouldSetCursor() const1370 bool LocalFrameView::ShouldSetCursor() const {
1371   Page* page = GetFrame().GetPage();
1372   return page && page->IsPageVisible() &&
1373          !frame_->GetEventHandler().IsMousePositionUnknown() &&
1374          page->GetFocusController().IsActive();
1375 }
1376 
InvalidateBackgroundAttachmentFixedDescendantsOnScroll(const LayoutObject & scrolled_object)1377 void LocalFrameView::InvalidateBackgroundAttachmentFixedDescendantsOnScroll(
1378     const LayoutObject& scrolled_object) {
1379   for (auto* const layout_object : background_attachment_fixed_objects_) {
1380     if (scrolled_object != GetLayoutView() &&
1381         !layout_object->IsDescendantOf(&scrolled_object))
1382       continue;
1383     // An object needs to repaint the background on scroll when it has
1384     // background-attachment:fixed unless the object is the LayoutView and the
1385     // background is not painted on the scrolling contents.
1386     if (layout_object == GetLayoutView() &&
1387         !(GetLayoutView()->GetBackgroundPaintLocation() &
1388           kBackgroundPaintInScrollingContents))
1389       continue;
1390     layout_object->SetBackgroundNeedsFullPaintInvalidation();
1391   }
1392 }
1393 
InvalidateViewportConstrainedObjects()1394 bool LocalFrameView::InvalidateViewportConstrainedObjects() {
1395   bool fast_path_allowed = true;
1396   for (auto* const viewport_constrained_object :
1397        *viewport_constrained_objects_) {
1398     LayoutObject* layout_object = viewport_constrained_object;
1399     DCHECK(layout_object->StyleRef().HasViewportConstrainedPosition() ||
1400            layout_object->StyleRef().HasStickyConstrainedPosition());
1401     DCHECK(layout_object->HasLayer());
1402     PaintLayer* layer = ToLayoutBoxModelObject(layout_object)->Layer();
1403 
1404     if (layer->IsPaintInvalidationContainer())
1405       continue;
1406 
1407     // If the layer has no visible content, then we shouldn't invalidate; but
1408     // if we're not compositing-inputs-clean, then we can't query
1409     // layer->SubtreeIsInvisible() here.
1410     layout_object->SetSubtreeShouldCheckForPaintInvalidation();
1411     if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
1412         !layer->SelfOrDescendantNeedsRepaint()) {
1413       // Paint properties of the layer relative to its containing graphics
1414       // layer may change if the paint properties escape the graphics layer's
1415       // property state. Need to check raster invalidation for relative paint
1416       // property changes.
1417       if (auto* paint_invalidation_layer =
1418               layer->EnclosingLayerForPaintInvalidation()) {
1419         auto* mapping = paint_invalidation_layer->GetCompositedLayerMapping();
1420         if (!mapping)
1421           mapping = paint_invalidation_layer->GroupedMapping();
1422         if (mapping)
1423           mapping->SetNeedsCheckRasterInvalidation();
1424       }
1425     }
1426 
1427     // If the fixed layer has a blur/drop-shadow filter applied on at least one
1428     // of its parents, we cannot scroll using the fast path, otherwise the
1429     // outsets of the filter will be moved around the page.
1430     if (layer->HasAncestorWithFilterThatMovesPixels())
1431       fast_path_allowed = false;
1432   }
1433   return fast_path_allowed;
1434 }
1435 
ProcessUrlFragment(const KURL & url,bool same_document_navigation,bool should_scroll)1436 void LocalFrameView::ProcessUrlFragment(const KURL& url,
1437                                         bool same_document_navigation,
1438                                         bool should_scroll) {
1439   // We want to create the anchor even if we don't need to scroll. This ensures
1440   // all the side effects like setting CSS :target are correctly set.
1441   FragmentAnchor* anchor = FragmentAnchor::TryCreate(
1442       url, *frame_, same_document_navigation, should_scroll);
1443 
1444   if (anchor) {
1445     fragment_anchor_ = anchor;
1446     fragment_anchor_->Installed();
1447     // Post-load, same-document navigations need to schedule a frame in which
1448     // the fragment anchor will be invoked. It will be done after layout as
1449     // part of the lifecycle.
1450     if (same_document_navigation)
1451       ScheduleAnimation();
1452   }
1453 }
1454 
SetLayoutSize(const IntSize & size)1455 void LocalFrameView::SetLayoutSize(const IntSize& size) {
1456   DCHECK(!LayoutSizeFixedToFrameSize());
1457   if (frame_->GetDocument() &&
1458       frame_->GetDocument()->Lifecycle().LifecyclePostponed())
1459     return;
1460 
1461   SetLayoutSizeInternal(size);
1462 }
1463 
SetLayoutSizeFixedToFrameSize(bool is_fixed)1464 void LocalFrameView::SetLayoutSizeFixedToFrameSize(bool is_fixed) {
1465   if (layout_size_fixed_to_frame_size_ == is_fixed)
1466     return;
1467 
1468   layout_size_fixed_to_frame_size_ = is_fixed;
1469   if (is_fixed)
1470     SetLayoutSizeInternal(Size());
1471 }
1472 
ComputeLayerSelection(LocalFrame & frame)1473 static cc::LayerSelection ComputeLayerSelection(LocalFrame& frame) {
1474   if (!frame.View() || frame.View()->ShouldThrottleRendering())
1475     return {};
1476 
1477   return ComputeLayerSelection(frame.Selection());
1478 }
1479 
UpdateCompositedSelectionIfNeeded()1480 void LocalFrameView::UpdateCompositedSelectionIfNeeded() {
1481   if (!RuntimeEnabledFeatures::CompositedSelectionUpdateEnabled())
1482     return;
1483 
1484   TRACE_EVENT0("blink", "LocalFrameView::updateCompositedSelectionIfNeeded");
1485 
1486   Page* page = GetFrame().GetPage();
1487   DCHECK(page);
1488 
1489   LocalFrame* focused_frame = page->GetFocusController().FocusedFrame();
1490   LocalFrame* local_frame =
1491       (focused_frame &&
1492        (focused_frame->LocalFrameRoot() == frame_->LocalFrameRoot()))
1493           ? focused_frame
1494           : nullptr;
1495 
1496   if (local_frame) {
1497     const cc::LayerSelection& selection = ComputeLayerSelection(*local_frame);
1498     if (selection != cc::LayerSelection()) {
1499       page->GetChromeClient().UpdateLayerSelection(local_frame, selection);
1500       return;
1501     }
1502   }
1503 
1504   if (!local_frame) {
1505     // Clearing the mainframe when there is no focused frame (and hence
1506     // no localFrame) is legacy behaviour, and implemented here to
1507     // satisfy WebFrameTest.CompositedSelectionBoundsCleared's
1508     // first check that the composited selection has been cleared even
1509     // though no frame has focus yet. If this is not desired, then the
1510     // expectation needs to be removed from the test.
1511     local_frame = &frame_->LocalFrameRoot();
1512   }
1513   DCHECK(local_frame);
1514   page->GetChromeClient().ClearLayerSelection(local_frame);
1515 }
1516 
SetNeedsCompositingUpdate(CompositingUpdateType update_type)1517 void LocalFrameView::SetNeedsCompositingUpdate(
1518     CompositingUpdateType update_type) {
1519   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1520     return;
1521   if (auto* layout_view = GetLayoutView()) {
1522     if (frame_->GetDocument()->IsActive())
1523       layout_view->Compositor()->SetNeedsCompositingUpdate(update_type);
1524   }
1525 }
1526 
GetChromeClient() const1527 ChromeClient* LocalFrameView::GetChromeClient() const {
1528   Page* page = GetFrame().GetPage();
1529   if (!page)
1530     return nullptr;
1531   return &page->GetChromeClient();
1532 }
1533 
HandleLoadCompleted()1534 void LocalFrameView::HandleLoadCompleted() {
1535   // Once loading has completed, allow autoSize one last opportunity to
1536   // reduce the size of the frame.
1537   if (auto_size_info_)
1538     auto_size_info_->AutoSizeIfNeeded();
1539 }
1540 
ClearLayoutSubtreeRoot(const LayoutObject & root)1541 void LocalFrameView::ClearLayoutSubtreeRoot(const LayoutObject& root) {
1542   layout_subtree_root_list_.Remove(const_cast<LayoutObject&>(root));
1543 }
1544 
ClearLayoutSubtreeRootsAndMarkContainingBlocks()1545 void LocalFrameView::ClearLayoutSubtreeRootsAndMarkContainingBlocks() {
1546   layout_subtree_root_list_.ClearAndMarkContainingBlocksForLayout();
1547 }
1548 
AddOrthogonalWritingModeRoot(LayoutBox & root)1549 void LocalFrameView::AddOrthogonalWritingModeRoot(LayoutBox& root) {
1550   DCHECK(!root.IsLayoutCustomScrollbarPart());
1551   orthogonal_writing_mode_root_list_.Add(root);
1552 }
1553 
RemoveOrthogonalWritingModeRoot(LayoutBox & root)1554 void LocalFrameView::RemoveOrthogonalWritingModeRoot(LayoutBox& root) {
1555   orthogonal_writing_mode_root_list_.Remove(root);
1556 }
1557 
HasOrthogonalWritingModeRoots() const1558 bool LocalFrameView::HasOrthogonalWritingModeRoots() const {
1559   return !orthogonal_writing_mode_root_list_.IsEmpty();
1560 }
1561 
RemoveFloatingObjectsForSubtreeRoot(LayoutObject & root)1562 static inline void RemoveFloatingObjectsForSubtreeRoot(LayoutObject& root) {
1563   // TODO(kojii): Under certain conditions, moveChildTo() defers
1564   // removeFloatingObjects() until the containing block layouts. For
1565   // instance, when descendants of the moving child is floating,
1566   // removeChildNode() does not clear them. In such cases, at this
1567   // point, FloatingObjects may contain old or even deleted objects.
1568   // Dealing this in markAllDescendantsWithFloatsForLayout() could
1569   // solve, but since that is likely to suffer the performance and
1570   // since the containing block of orthogonal writing mode roots
1571   // having floats is very rare, prefer to re-create
1572   // FloatingObjects.
1573   if (LayoutBlock* cb = root.ContainingBlock()) {
1574     auto* child_block_flow = DynamicTo<LayoutBlockFlow>(cb);
1575     if ((cb->NormalChildNeedsLayout() || cb->SelfNeedsLayout()) &&
1576         child_block_flow) {
1577       child_block_flow->RemoveFloatingObjectsFromDescendants();
1578     }
1579   }
1580 }
1581 
PrepareOrthogonalWritingModeRootForLayout(LayoutObject & root)1582 static bool PrepareOrthogonalWritingModeRootForLayout(LayoutObject& root) {
1583   DCHECK(root.IsBox() && ToLayoutBox(root).IsOrthogonalWritingModeRoot());
1584   if (!root.NeedsLayout() || root.IsOutOfFlowPositioned() ||
1585       root.IsColumnSpanAll() ||
1586       !root.StyleRef().LogicalHeight().IsIntrinsicOrAuto() ||
1587       ToLayoutBox(root).IsGridItem() || root.IsTablePart())
1588     return false;
1589 
1590   if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
1591     // Do not pre-layout objects that are fully managed by LayoutNG; it is not
1592     // necessary and may lead to double layouts. We do need to pre-layout
1593     // objects whose containing block is a legacy object so that it can
1594     // properly compute its intrinsic size.
1595     if (IsManagedByLayoutNG(root))
1596       return false;
1597 
1598     // If the root is legacy but has |CachedLayoutResult|, its parent is NG,
1599     // which called |RunLegacyLayout()|. This parent not only needs to run
1600     // pre-layout, but also clearing |NeedsLayout()| without updating
1601     // |CachedLayoutResult| is harmful.
1602     if (const auto* box = ToLayoutBoxOrNull(&root)) {
1603       if (box->GetCachedLayoutResult())
1604         return false;
1605     }
1606   }
1607 
1608   RemoveFloatingObjectsForSubtreeRoot(root);
1609   return true;
1610 }
1611 
LayoutOrthogonalWritingModeRoots()1612 void LocalFrameView::LayoutOrthogonalWritingModeRoots() {
1613   for (auto& root : orthogonal_writing_mode_root_list_.Ordered()) {
1614     if (PrepareOrthogonalWritingModeRootForLayout(*root))
1615       LayoutFromRootObject(*root);
1616   }
1617 }
1618 
ScheduleOrthogonalWritingModeRootsForLayout()1619 void LocalFrameView::ScheduleOrthogonalWritingModeRootsForLayout() {
1620   for (auto& root : orthogonal_writing_mode_root_list_.Ordered()) {
1621     if (PrepareOrthogonalWritingModeRootForLayout(*root))
1622       layout_subtree_root_list_.Add(*root);
1623   }
1624 }
1625 
CheckLayoutInvalidationIsAllowed() const1626 bool LocalFrameView::CheckLayoutInvalidationIsAllowed() const {
1627 #if DCHECK_IS_ON()
1628   if (allows_layout_invalidation_after_layout_clean_)
1629     return true;
1630 
1631   // If we are updating all lifecycle phases beyond LayoutClean, we don't expect
1632   // dirty layout after LayoutClean.
1633   CHECK_FOR_DIRTY_LAYOUT(Lifecycle().GetState() <
1634                          DocumentLifecycle::kLayoutClean);
1635 
1636 #endif
1637   return true;
1638 }
1639 
ScheduleRelayout()1640 void LocalFrameView::ScheduleRelayout() {
1641   DCHECK(frame_->View() == this);
1642 
1643   if (!layout_scheduling_enabled_)
1644     return;
1645   // TODO(crbug.com/590856): It's still broken when we choose not to crash when
1646   // the check fails.
1647   if (!CheckLayoutInvalidationIsAllowed())
1648     return;
1649   if (!NeedsLayout())
1650     return;
1651   if (!frame_->GetDocument()->ShouldScheduleLayout())
1652     return;
1653   TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
1654                        "InvalidateLayout", TRACE_EVENT_SCOPE_THREAD, "data",
1655                        inspector_invalidate_layout_event::Data(frame_.Get()));
1656 
1657   ClearLayoutSubtreeRootsAndMarkContainingBlocks();
1658 
1659   if (has_pending_layout_)
1660     return;
1661   has_pending_layout_ = true;
1662 
1663   if (!ShouldThrottleRendering())
1664     GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
1665 }
1666 
ScheduleRelayoutOfSubtree(LayoutObject * relayout_root)1667 void LocalFrameView::ScheduleRelayoutOfSubtree(LayoutObject* relayout_root) {
1668   DCHECK(frame_->View() == this);
1669 
1670   // TODO(crbug.com/590856): It's still broken when we choose not to crash when
1671   // the check fails.
1672   if (!CheckLayoutInvalidationIsAllowed())
1673     return;
1674 
1675   // FIXME: Should this call shouldScheduleLayout instead?
1676   if (!frame_->GetDocument()->IsActive())
1677     return;
1678 
1679   LayoutView* layout_view = this->GetLayoutView();
1680   if (layout_view && layout_view->NeedsLayout()) {
1681     if (relayout_root)
1682       relayout_root->MarkContainerChainForLayout(false);
1683     return;
1684   }
1685 
1686   if (relayout_root == layout_view)
1687     layout_subtree_root_list_.ClearAndMarkContainingBlocksForLayout();
1688   else
1689     layout_subtree_root_list_.Add(*relayout_root);
1690 
1691   if (layout_scheduling_enabled_) {
1692     has_pending_layout_ = true;
1693 
1694     if (!ShouldThrottleRendering())
1695       GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
1696 
1697     Lifecycle().EnsureStateAtMost(DocumentLifecycle::kStyleClean);
1698   }
1699   TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
1700                        "InvalidateLayout", TRACE_EVENT_SCOPE_THREAD, "data",
1701                        inspector_invalidate_layout_event::Data(frame_.Get()));
1702 }
1703 
LayoutPending() const1704 bool LocalFrameView::LayoutPending() const {
1705   // FIXME: This should check Document::lifecycle instead.
1706   return has_pending_layout_;
1707 }
1708 
IsInPerformLayout() const1709 bool LocalFrameView::IsInPerformLayout() const {
1710   return Lifecycle().GetState() == DocumentLifecycle::kInPerformLayout;
1711 }
1712 
NeedsLayout() const1713 bool LocalFrameView::NeedsLayout() const {
1714   // This can return true in cases where the document does not have a body yet.
1715   // Document::shouldScheduleLayout takes care of preventing us from scheduling
1716   // layout in that case.
1717 
1718   auto* layout_view = GetLayoutView();
1719   return LayoutPending() || (layout_view && layout_view->NeedsLayout()) ||
1720          IsSubtreeLayout();
1721 }
1722 
CheckDoesNotNeedLayout() const1723 NOINLINE bool LocalFrameView::CheckDoesNotNeedLayout() const {
1724   CHECK_FOR_DIRTY_LAYOUT(!LayoutPending());
1725   CHECK_FOR_DIRTY_LAYOUT(!GetLayoutView() || !GetLayoutView()->NeedsLayout());
1726   CHECK_FOR_DIRTY_LAYOUT(!IsSubtreeLayout());
1727   return true;
1728 }
1729 
SetNeedsLayout()1730 void LocalFrameView::SetNeedsLayout() {
1731   auto* layout_view = GetLayoutView();
1732   if (!layout_view)
1733     return;
1734   // TODO(crbug.com/590856): It's still broken if we choose not to crash when
1735   // the check fails.
1736   if (!CheckLayoutInvalidationIsAllowed())
1737     return;
1738   layout_view->SetNeedsLayout(layout_invalidation_reason::kUnknown);
1739 }
1740 
HasOpaqueBackground() const1741 bool LocalFrameView::HasOpaqueBackground() const {
1742   return !base_background_color_.HasAlpha();
1743 }
1744 
BaseBackgroundColor() const1745 Color LocalFrameView::BaseBackgroundColor() const {
1746   if (use_dark_scheme_background_ &&
1747       base_background_color_ != Color::kTransparent) {
1748     return Color::kBlack;
1749   }
1750   return base_background_color_;
1751 }
1752 
SetBaseBackgroundColor(const Color & background_color)1753 void LocalFrameView::SetBaseBackgroundColor(const Color& background_color) {
1754   if (base_background_color_ == background_color)
1755     return;
1756 
1757   base_background_color_ = background_color;
1758   if (auto* layout_view = GetLayoutView()) {
1759     if (layout_view->Layer()->HasCompositedLayerMapping()) {
1760       CompositedLayerMapping* composited_layer_mapping =
1761           layout_view->Layer()->GetCompositedLayerMapping();
1762       composited_layer_mapping->UpdateContentsOpaque();
1763       if (composited_layer_mapping->MainGraphicsLayer())
1764         composited_layer_mapping->MainGraphicsLayer()->SetNeedsDisplay();
1765       if (composited_layer_mapping->ScrollingContentsLayer())
1766         composited_layer_mapping->ScrollingContentsLayer()->SetNeedsDisplay();
1767     }
1768   }
1769 
1770   if (!ShouldThrottleRendering())
1771     GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
1772 }
1773 
SetUseDarkSchemeBackground(bool dark_scheme)1774 void LocalFrameView::SetUseDarkSchemeBackground(bool dark_scheme) {
1775   if (use_dark_scheme_background_ == dark_scheme)
1776     return;
1777 
1778   use_dark_scheme_background_ = dark_scheme;
1779   if (auto* layout_view = GetLayoutView())
1780     layout_view->SetBackgroundNeedsFullPaintInvalidation();
1781 }
1782 
UpdateBaseBackgroundColorRecursively(const Color & base_background_color)1783 void LocalFrameView::UpdateBaseBackgroundColorRecursively(
1784     const Color& base_background_color) {
1785   ForAllNonThrottledLocalFrameViews(
1786       [base_background_color](LocalFrameView& frame_view) {
1787         frame_view.SetBaseBackgroundColor(base_background_color);
1788       });
1789 }
1790 
InvokeFragmentAnchor()1791 void LocalFrameView::InvokeFragmentAnchor() {
1792   if (!fragment_anchor_)
1793     return;
1794 
1795   if (!fragment_anchor_->Invoke())
1796     fragment_anchor_ = nullptr;
1797 }
1798 
DismissFragmentAnchor()1799 void LocalFrameView::DismissFragmentAnchor() {
1800   if (!fragment_anchor_)
1801     return;
1802 
1803   if (fragment_anchor_->Dismiss())
1804     fragment_anchor_ = nullptr;
1805 }
1806 
UpdatePlugins()1807 bool LocalFrameView::UpdatePlugins() {
1808   // This is always called from UpdatePluginsTimerFired.
1809   // update_plugins_timer should only be scheduled if we have FrameViews to
1810   // update. Thus I believe we can stop checking isEmpty here, and just ASSERT
1811   // isEmpty:
1812   // FIXME: This assert has been temporarily removed due to
1813   // https://crbug.com/430344
1814   if (nested_layout_count_ > 1 || part_update_set_.IsEmpty())
1815     return true;
1816 
1817   // Need to swap because script will run inside the below loop and invalidate
1818   // the iterator.
1819   EmbeddedObjectSet objects;
1820   objects.swap(part_update_set_);
1821 
1822   for (const auto& embedded_object : objects) {
1823     LayoutEmbeddedObject& object = *embedded_object;
1824     auto* element = To<HTMLPlugInElement>(object.GetNode());
1825 
1826     // The object may have already been destroyed (thus node cleared),
1827     // but LocalFrameView holds a manual ref, so it won't have been deleted.
1828     if (!element)
1829       continue;
1830 
1831     // No need to update if it's already crashed or known to be missing.
1832     if (object.ShowsUnavailablePluginIndicator())
1833       continue;
1834 
1835     if (element->NeedsPluginUpdate())
1836       element->UpdatePlugin();
1837     if (EmbeddedContentView* view = element->OwnedEmbeddedContentView())
1838       view->UpdateGeometry();
1839 
1840     // Prevent plugins from causing infinite updates of themselves.
1841     // FIXME: Do we really need to prevent this?
1842     part_update_set_.erase(&object);
1843   }
1844 
1845   return part_update_set_.IsEmpty();
1846 }
1847 
UpdatePluginsTimerFired(TimerBase *)1848 void LocalFrameView::UpdatePluginsTimerFired(TimerBase*) {
1849   DCHECK(!IsInPerformLayout());
1850   for (unsigned i = 0; i < kMaxUpdatePluginsIterations; ++i) {
1851     if (UpdatePlugins())
1852       return;
1853   }
1854 }
1855 
FlushAnyPendingPostLayoutTasks()1856 void LocalFrameView::FlushAnyPendingPostLayoutTasks() {
1857   DCHECK(!IsInPerformLayout());
1858   if (update_plugins_timer_.IsActive()) {
1859     update_plugins_timer_.Stop();
1860     UpdatePluginsTimerFired(nullptr);
1861   }
1862 }
1863 
ScheduleUpdatePluginsIfNecessary()1864 void LocalFrameView::ScheduleUpdatePluginsIfNecessary() {
1865   DCHECK(!IsInPerformLayout());
1866   if (update_plugins_timer_.IsActive() || part_update_set_.IsEmpty())
1867     return;
1868   update_plugins_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
1869 }
1870 
PerformPostLayoutTasks()1871 void LocalFrameView::PerformPostLayoutTasks() {
1872   // FIXME: We can reach here, even when the page is not active!
1873   // http/tests/inspector/elements/html-link-import.html and many other
1874   // tests hit that case.
1875   // We should DCHECK(isActive()); or at least return early if we can!
1876 
1877   // Always called before or after performLayout(), part of the highest-level
1878   // layout() call.
1879   DCHECK(!IsInPerformLayout());
1880   TRACE_EVENT0("blink,benchmark", "LocalFrameView::performPostLayoutTasks");
1881 
1882   frame_->Selection().DidLayout();
1883 
1884   DCHECK(frame_->GetDocument());
1885 
1886   FontFaceSetDocument::DidLayout(*frame_->GetDocument());
1887   // Fire a fake a mouse move event to update hover state and mouse cursor, and
1888   // send the right mouse out/over events.
1889   // TODO(lanwei): we should check whether the mouse is inside the frame before
1890   // dirtying the hover state.
1891   frame_->LocalFrameRoot().GetEventHandler().MarkHoverStateDirty();
1892 
1893   UpdateGeometriesIfNeeded();
1894 
1895   // Plugins could have torn down the page inside updateGeometries().
1896   if (!GetLayoutView())
1897     return;
1898 
1899   ScheduleUpdatePluginsIfNecessary();
1900 
1901   if (ScrollingCoordinator* scrolling_coordinator =
1902           this->GetScrollingCoordinator()) {
1903     scrolling_coordinator->NotifyGeometryChanged(this);
1904   }
1905 
1906   SendResizeEventIfNeeded();
1907 }
1908 
WasViewportResized()1909 bool LocalFrameView::WasViewportResized() {
1910   DCHECK(frame_);
1911   auto* layout_view = GetLayoutView();
1912   if (!layout_view)
1913     return false;
1914   return (GetLayoutSize() != last_viewport_size_ ||
1915           layout_view->StyleRef().Zoom() != last_zoom_factor_);
1916 }
1917 
SendResizeEventIfNeeded()1918 void LocalFrameView::SendResizeEventIfNeeded() {
1919   DCHECK(frame_);
1920 
1921   auto* layout_view = GetLayoutView();
1922   if (!layout_view || layout_view->GetDocument().Printing())
1923     return;
1924 
1925   if (!WasViewportResized())
1926     return;
1927 
1928   last_viewport_size_ = GetLayoutSize();
1929   last_zoom_factor_ = layout_view->StyleRef().Zoom();
1930 
1931   frame_->GetDocument()->EnqueueVisualViewportResizeEvent();
1932 
1933   frame_->GetDocument()->EnqueueResizeEvent();
1934 
1935   if (frame_->IsMainFrame())
1936     probe::DidResizeMainFrame(frame_.Get());
1937 }
1938 
InputEventsScaleFactor() const1939 float LocalFrameView::InputEventsScaleFactor() const {
1940   float page_scale = frame_->GetPage()->GetVisualViewport().Scale();
1941   return page_scale *
1942          frame_->GetPage()->GetChromeClient().InputEventsScaleForEmulation();
1943 }
1944 
NotifyPageThatContentAreaWillPaint() const1945 void LocalFrameView::NotifyPageThatContentAreaWillPaint() const {
1946   Page* page = frame_->GetPage();
1947   if (!page)
1948     return;
1949 
1950   if (!scrollable_areas_)
1951     return;
1952 
1953   for (const auto& scrollable_area : *scrollable_areas_) {
1954     if (!scrollable_area->ScrollbarsCanBeActive())
1955       continue;
1956 
1957     scrollable_area->ContentAreaWillPaint();
1958   }
1959 }
1960 
UpdateDocumentAnnotatedRegions() const1961 void LocalFrameView::UpdateDocumentAnnotatedRegions() const {
1962   Document* document = frame_->GetDocument();
1963   if (!document->HasAnnotatedRegions())
1964     return;
1965   Vector<AnnotatedRegionValue> new_regions;
1966   CollectAnnotatedRegions(*(document->GetLayoutBox()), new_regions);
1967   if (new_regions == document->AnnotatedRegions())
1968     return;
1969   document->SetAnnotatedRegions(new_regions);
1970 
1971   DCHECK(frame_->Client());
1972   frame_->Client()->AnnotatedRegionsChanged();
1973 }
1974 
DidAttachDocument()1975 void LocalFrameView::DidAttachDocument() {
1976   Page* page = frame_->GetPage();
1977   DCHECK(page);
1978 
1979   DCHECK(frame_->GetDocument());
1980 
1981   if (frame_->IsMainFrame()) {
1982     ScrollableArea& visual_viewport = frame_->GetPage()->GetVisualViewport();
1983     ScrollableArea* layout_viewport = LayoutViewport();
1984     DCHECK(layout_viewport);
1985 
1986     auto* root_frame_viewport = MakeGarbageCollected<RootFrameViewport>(
1987         visual_viewport, *layout_viewport);
1988     viewport_scrollable_area_ = root_frame_viewport;
1989 
1990     page->GlobalRootScrollerController().InitializeViewportScrollCallback(
1991         *root_frame_viewport, *frame_->GetDocument());
1992 
1993     // Allow for commits to be deferred because this is a new document.
1994     have_deferred_commits_ = false;
1995   }
1996 }
1997 
DocumentBackgroundColor() const1998 Color LocalFrameView::DocumentBackgroundColor() const {
1999   // The LayoutView's background color is set in
2000   // Document::inheritHtmlAndBodyElementStyles.  Blend this with the base
2001   // background color of the LocalFrameView. This should match the color drawn
2002   // by ViewPainter::paintBoxDecorationBackground.
2003   Color result = BaseBackgroundColor();
2004 
2005   // If we have a fullscreen element grab the fullscreen color from the
2006   // backdrop.
2007   if (Document* doc = frame_->GetDocument()) {
2008     if (Element* element = Fullscreen::FullscreenElementFrom(*doc)) {
2009       if (doc->IsXrOverlay()) {
2010         // Use the fullscreened element's background directly. Don't bother
2011         // blending with the backdrop since that's transparent.
2012         if (LayoutObject* layout_object = element->GetLayoutObject()) {
2013           return layout_object->ResolveColor(GetCSSPropertyBackgroundColor());
2014         }
2015         if (LayoutObject* layout_object =
2016                 element->PseudoElementLayoutObject(kPseudoIdBackdrop)) {
2017           return layout_object->ResolveColor(GetCSSPropertyBackgroundColor());
2018         }
2019       }
2020       if (LayoutObject* layout_object =
2021               element->PseudoElementLayoutObject(kPseudoIdBackdrop)) {
2022         return result.Blend(
2023             layout_object->ResolveColor(GetCSSPropertyBackgroundColor()));
2024       }
2025     }
2026   }
2027   auto* layout_view = GetLayoutView();
2028   if (layout_view) {
2029     result = result.Blend(
2030         layout_view->ResolveColor(GetCSSPropertyBackgroundColor()));
2031   }
2032   return result;
2033 }
2034 
WillBeRemovedFromFrame()2035 void LocalFrameView::WillBeRemovedFromFrame() {
2036   if (paint_artifact_compositor_)
2037     paint_artifact_compositor_->WillBeRemovedFromFrame();
2038 
2039   if (Settings* settings = frame_->GetSettings()) {
2040     DCHECK(frame_->GetPage());
2041     if (settings->GetSpatialNavigationEnabled()) {
2042       frame_->GetPage()->GetSpatialNavigationController().DidDetachFrameView(
2043           *this);
2044     }
2045   }
2046 }
2047 
ParentFrameView() const2048 LocalFrameView* LocalFrameView::ParentFrameView() const {
2049   if (!IsAttached())
2050     return nullptr;
2051 
2052   Frame* parent_frame = frame_->Tree().Parent();
2053   if (auto* parent_local_frame = DynamicTo<LocalFrame>(parent_frame))
2054     return parent_local_frame->View();
2055 
2056   return nullptr;
2057 }
2058 
GetLayoutEmbeddedContent() const2059 LayoutEmbeddedContent* LocalFrameView::GetLayoutEmbeddedContent() const {
2060   return frame_->OwnerLayoutObject();
2061 }
2062 
VisualViewportScrollbarsChanged()2063 void LocalFrameView::VisualViewportScrollbarsChanged() {
2064   SetVisualViewportNeedsRepaint();
2065   if (LayoutView* layout_view = GetLayoutView())
2066     layout_view->Layer()->ClearClipRects();
2067 }
2068 
UpdateGeometriesIfNeeded()2069 void LocalFrameView::UpdateGeometriesIfNeeded() {
2070   if (!needs_update_geometries_)
2071     return;
2072   needs_update_geometries_ = false;
2073   HeapVector<Member<EmbeddedContentView>> views;
2074   ForAllChildViewsAndPlugins(
2075       [&](EmbeddedContentView& view) { views.push_back(view); });
2076 
2077   for (const auto& view : views) {
2078     // Script or plugins could detach the frame so abort processing if that
2079     // happens.
2080     if (!GetLayoutView())
2081       break;
2082 
2083     view->UpdateGeometry();
2084   }
2085   // Explicitly free the backing store to avoid memory regressions.
2086   // TODO(bikineev): Revisit after young generation is there.
2087   views.clear();
2088 }
2089 
UpdateAllLifecyclePhases(DocumentUpdateReason reason)2090 bool LocalFrameView::UpdateAllLifecyclePhases(DocumentUpdateReason reason) {
2091   bool updated = GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
2092       DocumentLifecycle::kPaintClean, reason);
2093 
2094 #if DCHECK_IS_ON()
2095   if (updated) {
2096     // This function should return true iff all non-throttled frames are in the
2097     // kPaintClean lifecycle state.
2098     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2099       DCHECK_EQ(frame_view.Lifecycle().GetState(),
2100                 DocumentLifecycle::kPaintClean);
2101     });
2102 
2103     // A required intersection observation should run throttled frames to
2104     // kLayoutClean.
2105     ForAllThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2106       DCHECK(frame_view.intersection_observation_state_ != kRequired ||
2107              frame_view.Lifecycle().GetState() >=
2108                  DocumentLifecycle::kLayoutClean);
2109     });
2110   }
2111 #endif
2112 
2113   return updated;
2114 }
2115 
2116 // TODO(schenney): add a scrolling update lifecycle phase.
2117 // TODO(schenney): Pass a LifecycleUpdateReason in here
UpdateLifecycleToCompositingCleanPlusScrolling(DocumentUpdateReason reason)2118 bool LocalFrameView::UpdateLifecycleToCompositingCleanPlusScrolling(
2119     DocumentUpdateReason reason) {
2120   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
2121     return UpdateAllLifecyclePhasesExceptPaint(reason);
2122   return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
2123       DocumentLifecycle::kCompositingClean, reason);
2124 }
2125 
2126 // TODO(schenney): Pass a LifecycleUpdateReason in here
UpdateLifecycleToCompositingInputsClean(DocumentUpdateReason reason)2127 bool LocalFrameView::UpdateLifecycleToCompositingInputsClean(
2128     DocumentUpdateReason reason) {
2129   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
2130     return UpdateAllLifecyclePhasesExceptPaint(reason);
2131   return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
2132       DocumentLifecycle::kCompositingInputsClean, reason);
2133 }
2134 
2135 // TODO(schenney): Pass a LifecycleUpdateReason in here
UpdateAllLifecyclePhasesExceptPaint(DocumentUpdateReason reason)2136 bool LocalFrameView::UpdateAllLifecyclePhasesExceptPaint(
2137     DocumentUpdateReason reason) {
2138   return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
2139       DocumentLifecycle::kPrePaintClean, reason);
2140 }
2141 
UpdateLifecyclePhasesForPrinting()2142 void LocalFrameView::UpdateLifecyclePhasesForPrinting() {
2143   auto* local_frame_view_root = GetFrame().LocalFrameRoot().View();
2144   local_frame_view_root->UpdateLifecyclePhases(
2145       DocumentLifecycle::kPrePaintClean, DocumentUpdateReason::kPrinting);
2146 
2147   auto* detached_frame_view = this;
2148   while (detached_frame_view->IsAttached() &&
2149          detached_frame_view != local_frame_view_root) {
2150     detached_frame_view = detached_frame_view->ParentFrameView();
2151     CHECK(detached_frame_view);
2152   }
2153 
2154   if (detached_frame_view == local_frame_view_root)
2155     return;
2156   DCHECK(!detached_frame_view->IsAttached());
2157 
2158   // We are printing a detached frame or a descendant of a detached frame which
2159   // was not reached in some phases during during |local_frame_view_root->
2160   // UpdateLifecyclePhasesnormal()|. We need the subtree to be ready for
2161   // painting.
2162   detached_frame_view->UpdateLifecyclePhases(DocumentLifecycle::kPrePaintClean,
2163                                              DocumentUpdateReason::kPrinting);
2164 }
2165 
2166 // TODO(schenney): Pass a LifecycleUpdateReason in here
UpdateLifecycleToLayoutClean(DocumentUpdateReason reason)2167 bool LocalFrameView::UpdateLifecycleToLayoutClean(DocumentUpdateReason reason) {
2168   return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
2169       DocumentLifecycle::kLayoutClean, reason);
2170 }
2171 
ScheduleVisualUpdateForPaintInvalidationIfNeeded()2172 void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() {
2173   LocalFrame& local_frame_root = GetFrame().LocalFrameRoot();
2174   if (local_frame_root.View()->current_update_lifecycle_phases_target_state_ <
2175           DocumentLifecycle::kPrePaintClean ||
2176       Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean) {
2177     // Schedule visual update to process the paint invalidation in the next
2178     // cycle.
2179     local_frame_root.ScheduleVisualUpdateUnlessThrottled();
2180   }
2181   // Otherwise the paint invalidation will be handled in the pre-paint
2182   // phase of this cycle.
2183 }
2184 
NotifyResizeObservers(DocumentLifecycle::LifecycleState target_state)2185 bool LocalFrameView::NotifyResizeObservers(
2186     DocumentLifecycle::LifecycleState target_state) {
2187   // Return true if lifecycles need to be re-run
2188   TRACE_EVENT0("blink,benchmark", "LocalFrameView::NotifyResizeObservers");
2189 
2190   if (target_state < DocumentLifecycle::kPaintClean)
2191     return false;
2192 
2193   // Controller exists only if ResizeObserver was created.
2194   if (!GetFrame().GetDocument()->GetResizeObserverController())
2195     return false;
2196 
2197   ResizeObserverController& resize_controller =
2198       frame_->GetDocument()->EnsureResizeObserverController();
2199 
2200   DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
2201 
2202   size_t min_depth = resize_controller.GatherObservations();
2203 
2204   if (min_depth != ResizeObserverController::kDepthBottom) {
2205     resize_controller.DeliverObservations();
2206   } else {
2207     // Observation depth limit reached
2208     if (resize_controller.SkippedObservations()) {
2209       resize_controller.ClearObservations();
2210       ErrorEvent* error = ErrorEvent::Create(
2211           "ResizeObserver loop limit exceeded",
2212           SourceLocation::Capture(frame_->GetDocument()->ToExecutionContext()),
2213           nullptr);
2214       // We're using |SanitizeScriptErrors::kDoNotSanitize| as the error is made
2215       // by blink itself.
2216       // TODO(yhirano): Reconsider this.
2217       frame_->GetDocument()->ToExecutionContext()->DispatchErrorEvent(
2218           error, SanitizeScriptErrors::kDoNotSanitize);
2219       // Ensure notifications will get delivered in next cycle.
2220       ScheduleAnimation();
2221       DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
2222     }
2223     if (Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean)
2224       return false;
2225   }
2226 
2227   // Lifecycle needs to be run again because Resize Observer affected layout
2228   return true;
2229 }
2230 
2231 // TODO(leviw): We don't assert lifecycle information from documents in child
2232 // WebPluginContainerImpls.
UpdateLifecyclePhases(DocumentLifecycle::LifecycleState target_state,DocumentUpdateReason reason)2233 bool LocalFrameView::UpdateLifecyclePhases(
2234     DocumentLifecycle::LifecycleState target_state,
2235     DocumentUpdateReason reason) {
2236   // If the lifecycle is postponed, which can happen if the inspector requests
2237   // it, then we shouldn't update any lifecycle phases.
2238   if (UNLIKELY(frame_->GetDocument() &&
2239                frame_->GetDocument()->Lifecycle().LifecyclePostponed())) {
2240     return false;
2241   }
2242 
2243   // Prevent reentrance.
2244   // TODO(vmpstr): Should we just have a DCHECK instead here?
2245   if (UNLIKELY(current_update_lifecycle_phases_target_state_ !=
2246                DocumentLifecycle::kUninitialized)) {
2247     NOTREACHED()
2248         << "LocalFrameView::updateLifecyclePhasesInternal() reentrance";
2249     return false;
2250   }
2251 
2252   // This must be called from the root frame, or a detached frame for printing,
2253   // since it recurses down, not up. Otherwise the lifecycles of the frames
2254   // might be out of sync.
2255   DCHECK(frame_->IsLocalRoot() || !IsAttached());
2256 
2257   // Only the following target states are supported.
2258   DCHECK(target_state == DocumentLifecycle::kLayoutClean ||
2259          target_state == DocumentLifecycle::kAccessibilityClean ||
2260          target_state == DocumentLifecycle::kCompositingInputsClean ||
2261          target_state == DocumentLifecycle::kCompositingClean ||
2262          target_state == DocumentLifecycle::kPrePaintClean ||
2263          target_state == DocumentLifecycle::kPaintClean);
2264   lifecycle_update_count_for_testing_++;
2265 
2266   // If the document is not active then it is either not yet initialized, or it
2267   // is stopping. In either case, we can't reach one of the supported target
2268   // states.
2269   if (!frame_->GetDocument()->IsActive())
2270     return false;
2271 
2272   if (frame_->IsLocalRoot())
2273     UpdateLayerDebugInfoEnabled();
2274 
2275   // This is used to guard against reentrance. It is also used in conjunction
2276   // with the current lifecycle state to determine which phases are yet to run
2277   // in this cycle.
2278   base::AutoReset<DocumentLifecycle::LifecycleState> target_state_scope(
2279       &current_update_lifecycle_phases_target_state_, target_state);
2280   // This is used to check if we're within a lifecycle update but have passed
2281   // the layout update phase. Note there is a bit of a subtlety here: it's not
2282   // sufficient for us to check the current lifecycle state, since it can be
2283   // past kLayoutClean but the function to run style and layout phase has not
2284   // actually been run yet. Since this bool affects throttling, and throttling,
2285   // in turn, determines whether style and layout function will run, we need a
2286   // separate bool.
2287   base::AutoReset<bool> past_layout_lifecycle_resetter(
2288       &past_layout_lifecycle_update_, false);
2289   base::AutoReset<bool> in_lifecycle_scope(&in_lifecycle_update_, true);
2290 
2291   // If we're throttling, then we don't need to update lifecycle phases. The
2292   // throttling status will get updated in RunPostLifecycleSteps().
2293   if (ShouldThrottleRendering()) {
2294     return Lifecycle().GetState() == target_state;
2295   }
2296 
2297   lifecycle_data_.start_time = base::TimeTicks::Now();
2298   ++lifecycle_data_.count;
2299 
2300   {
2301     TRACE_EVENT0("blink", "LocalFrameView::WillStartLifecycleUpdate");
2302 
2303     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2304       auto lifecycle_observers = frame_view.lifecycle_observers_;
2305       for (auto& observer : lifecycle_observers)
2306         observer->WillStartLifecycleUpdate(frame_view);
2307     });
2308   }
2309 
2310   {
2311     TRACE_EVENT0(
2312         "blink",
2313         "LocalFrameView::UpdateLifecyclePhases - start of lifecycle tasks");
2314     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2315       WTF::Vector<base::OnceClosure> tasks;
2316       frame_view.start_of_lifecycle_tasks_.swap(tasks);
2317       for (auto& task : tasks)
2318         std::move(task).Run();
2319     });
2320   }
2321 
2322   // Run the lifecycle updates.
2323   UpdateLifecyclePhasesInternal(target_state);
2324 
2325   {
2326     TRACE_EVENT0("blink", "LocalFrameView::DidFinishLifecycleUpdate");
2327 
2328     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2329       auto lifecycle_observers = frame_view.lifecycle_observers_;
2330       for (auto& observer : lifecycle_observers)
2331         observer->DidFinishLifecycleUpdate(frame_view);
2332     });
2333   }
2334 
2335   // Hit testing metrics include the entire time processing a document update
2336   // in preparation for a hit test.
2337   if (reason == DocumentUpdateReason::kHitTest) {
2338     LocalFrameUkmAggregator& aggregator = EnsureUkmAggregator();
2339     aggregator.RecordSample(
2340         static_cast<size_t>(LocalFrameUkmAggregator::kHitTestDocumentUpdate),
2341         lifecycle_data_.start_time, base::TimeTicks::Now());
2342   }
2343 
2344   return Lifecycle().GetState() == target_state;
2345 }
2346 
UpdateLifecyclePhasesInternal(DocumentLifecycle::LifecycleState target_state)2347 void LocalFrameView::UpdateLifecyclePhasesInternal(
2348     DocumentLifecycle::LifecycleState target_state) {
2349   // Run style, layout, compositing and prepaint lifecycle phases and deliver
2350   // resize observations if required. Resize observer callbacks/delegates have
2351   // the potential to dirty layout (until loop limit is reached) and therefore
2352   // the above lifecycle phases need to be re-run until the limit is reached
2353   // or no layout is pending.
2354   while (true) {
2355     bool run_more_lifecycle_phases =
2356         RunStyleAndLayoutLifecyclePhases(target_state);
2357     if (!run_more_lifecycle_phases)
2358       return;
2359     DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean);
2360 
2361     if (!GetLayoutView())
2362       return;
2363 
2364     {
2365       // We need scoping braces here because this
2366       // DisallowLayoutInvalidationScope is meant to be in effect during
2367       // pre-paint, but not during ResizeObserver.
2368 #if DCHECK_IS_ON()
2369       DisallowLayoutInvalidationScope disallow_layout_invalidation(this);
2370 #endif
2371 
2372       DCHECK_GE(target_state, DocumentLifecycle::kAccessibilityClean);
2373       run_more_lifecycle_phases = RunAccessibilityLifecyclePhase(target_state);
2374       DCHECK(ShouldThrottleRendering() || !ExistingAXObjectCache() ||
2375              Lifecycle().GetState() == DocumentLifecycle::kAccessibilityClean);
2376       if (!run_more_lifecycle_phases)
2377         return;
2378 
2379       TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
2380                            "SetLayerTreeId", TRACE_EVENT_SCOPE_THREAD, "data",
2381                            inspector_set_layer_tree_id::Data(frame_.Get()));
2382       TRACE_EVENT1("devtools.timeline", "UpdateLayerTree", "data",
2383                    inspector_update_layer_tree_event::Data(frame_.Get()));
2384 
2385       run_more_lifecycle_phases = RunCompositingLifecyclePhase(target_state);
2386       if (!run_more_lifecycle_phases)
2387         return;
2388 
2389       // TODO(pdr): PrePaint should be under the "Paint" devtools timeline step
2390       // when CompositeAfterPaint is enabled.
2391       run_more_lifecycle_phases = RunPrePaintLifecyclePhase(target_state);
2392       DCHECK(ShouldThrottleRendering() ||
2393              Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
2394       if (!run_more_lifecycle_phases)
2395         return;
2396     }
2397 
2398     run_more_lifecycle_phases = RunResizeObserverSteps(target_state);
2399     if (!run_more_lifecycle_phases)
2400       break;
2401   }
2402   // Layout invalidation scope was disabled for resize observer
2403   // re-enable it for subsequent steps
2404 #if DCHECK_IS_ON()
2405   DisallowLayoutInvalidationScope disallow_layout_invalidation(this);
2406 #endif
2407   // Now that we have run the lifecycle up to paint, we can reset
2408   // |need_paint_phase_after_throttling_| so that the paint phase will
2409   // properly see us as being throttled (if that was the only reason we remained
2410   // unthrottled), and clear the painted output.
2411   need_paint_phase_after_throttling_ = false;
2412 
2413   DCHECK_EQ(target_state, DocumentLifecycle::kPaintClean);
2414   RunPaintLifecyclePhase();
2415   DCHECK(ShouldThrottleRendering() ||
2416          frame_->GetDocument()->IsCapturingLayout() ||
2417          Lifecycle().GetState() == DocumentLifecycle::kPaintClean);
2418 
2419   ForAllRemoteFrameViews(
2420       [](RemoteFrameView& frame_view) { frame_view.UpdateCompositingRect(); });
2421 }
2422 
RunResizeObserverSteps(DocumentLifecycle::LifecycleState target_state)2423 bool LocalFrameView::RunResizeObserverSteps(
2424     DocumentLifecycle::LifecycleState target_state) {
2425   bool re_run_lifecycles = false;
2426   if (target_state == DocumentLifecycle::kPaintClean) {
2427     ForAllNonThrottledLocalFrameViews(
2428         [&re_run_lifecycles](LocalFrameView& frame_view) {
2429           bool result =
2430               frame_view.NotifyResizeObservers(DocumentLifecycle::kPaintClean);
2431           re_run_lifecycles = re_run_lifecycles || result;
2432         });
2433   }
2434   if (!re_run_lifecycles) {
2435     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2436       ResizeObserverController& resize_controller =
2437           frame_view.frame_->GetDocument()->EnsureResizeObserverController();
2438       resize_controller.ClearMinDepth();
2439     });
2440   }
2441   return re_run_lifecycles;
2442 }
2443 
RunStyleAndLayoutLifecyclePhases(DocumentLifecycle::LifecycleState target_state)2444 bool LocalFrameView::RunStyleAndLayoutLifecyclePhases(
2445     DocumentLifecycle::LifecycleState target_state) {
2446   TRACE_EVENT0("blink,benchmark",
2447                "LocalFrameView::RunStyleAndLayoutLifecyclePhases");
2448   UpdateStyleAndLayoutIfNeededRecursive();
2449   DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean);
2450 
2451   frame_->GetDocument()
2452       ->GetRootScrollerController()
2453       .PerformRootScrollerSelection();
2454 
2455   // PerformRootScrollerSelection can dirty layout if an effective root
2456   // scroller is changed so make sure we get back to LayoutClean.
2457   if (RuntimeEnabledFeatures::ImplicitRootScrollerEnabled() ||
2458       RuntimeEnabledFeatures::SetRootScrollerEnabled()) {
2459     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2460       if (frame_view.NeedsLayout())
2461         frame_view.UpdateLayout();
2462 
2463       DCHECK(frame_view.Lifecycle().GetState() >=
2464              DocumentLifecycle::kLayoutClean);
2465     });
2466   }
2467 
2468   if (target_state == DocumentLifecycle::kLayoutClean)
2469     return false;
2470 
2471   // This will be reset by AutoReset in the calling function
2472   // (UpdateLifecyclePhases()).
2473   past_layout_lifecycle_update_ = true;
2474 
2475   // After layout and the |past_layout_lifecycle_update_| update, the value of
2476   // ShouldThrottleRendering() can change. OOPIF local frame roots that are
2477   // throttled can return now that layout is clean. This situation happens if
2478   // the throttling was disabled due to required intersection observation, which
2479   // can now be run.
2480   if (ShouldThrottleRendering())
2481     return false;
2482 
2483   // Now we can run post layout steps in preparation for further phases.
2484   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2485     frame_view.PerformScrollAnchoringAdjustments();
2486   });
2487 
2488   frame_->GetDocument()->PerformScrollSnappingTasks();
2489 
2490   EnqueueScrollEvents();
2491 
2492   frame_->GetPage()->GetValidationMessageClient().LayoutOverlay();
2493 
2494   if (target_state == DocumentLifecycle::kPaintClean) {
2495     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2496       frame_view.NotifyFrameRectsChangedIfNeeded();
2497     });
2498   }
2499 
2500   return Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean;
2501 }
2502 
RunCompositingLifecyclePhase(DocumentLifecycle::LifecycleState target_state)2503 bool LocalFrameView::RunCompositingLifecyclePhase(
2504     DocumentLifecycle::LifecycleState target_state) {
2505   TRACE_EVENT0("blink,benchmark",
2506                "LocalFrameView::RunCompositingLifecyclePhase");
2507   auto* layout_view = GetLayoutView();
2508   DCHECK(layout_view);
2509 
2510   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2511     SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
2512                              LocalFrameUkmAggregator::kCompositing);
2513     layout_view->Compositor()->UpdateIfNeededRecursive(target_state);
2514   }
2515 
2516   return target_state > DocumentLifecycle::kCompositingClean;
2517 }
2518 
RunPrePaintLifecyclePhase(DocumentLifecycle::LifecycleState target_state)2519 bool LocalFrameView::RunPrePaintLifecyclePhase(
2520     DocumentLifecycle::LifecycleState target_state) {
2521   TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPrePaintLifecyclePhase");
2522 
2523   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2524     // TODO(pdr): This descendant dependent treewalk should be integrated into
2525     // the prepaint tree walk.
2526 #if DCHECK_IS_ON()
2527     SetIsUpdatingDescendantDependentFlags(true);
2528 #endif
2529     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2530       frame_view.GetLayoutView()->Layer()->UpdateDescendantDependentFlags();
2531       frame_view.GetLayoutView()->CommitPendingSelection();
2532     });
2533 #if DCHECK_IS_ON()
2534     SetIsUpdatingDescendantDependentFlags(false);
2535 #endif
2536   }
2537 
2538   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2539     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPrePaint);
2540     if (frame_view.CanThrottleRendering()) {
2541       // This frame can be throttled but not throttled, meaning we are not in an
2542       // AllowThrottlingScope. Now this frame may contain dirty paint flags, and
2543       // we need to propagate the flags into the ancestor chain so that
2544       // PrePaintTreeWalk can reach this frame.
2545       frame_view.SetNeedsPaintPropertyUpdate();
2546       // We may record more foreign layers under the frame.
2547       if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
2548         frame_view.SetForeignLayerListNeedsUpdate();
2549       if (auto* owner = frame_view.GetLayoutEmbeddedContent())
2550         owner->SetShouldCheckForPaintInvalidation();
2551     }
2552   });
2553 
2554   {
2555     SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
2556                              LocalFrameUkmAggregator::kPrePaint);
2557 
2558     GetPage()->GetLinkHighlight().UpdateBeforePrePaint();
2559     PrePaintTreeWalk().WalkTree(*this);
2560     GetPage()->GetLinkHighlight().UpdateAfterPrePaint();
2561   }
2562 
2563   UpdateCompositedSelectionIfNeeded();
2564 
2565   frame_->GetPage()->GetValidationMessageClient().UpdatePrePaint();
2566   ForAllNonThrottledLocalFrameViews([](LocalFrameView& view) {
2567     view.frame_->UpdateFrameColorOverlayPrePaint();
2568   });
2569   if (auto* web_local_frame_impl = WebLocalFrameImpl::FromFrame(frame_))
2570     web_local_frame_impl->UpdateDevToolsOverlaysPrePaint();
2571 
2572   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2573     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPrePaintClean);
2574   });
2575 
2576   return target_state > DocumentLifecycle::kPrePaintClean;
2577 }
2578 
2579 template <typename Function>
ForAllGraphicsLayers(GraphicsLayer & layer,const Function & function)2580 static void ForAllGraphicsLayers(GraphicsLayer& layer,
2581                                  const Function& function) {
2582   function(layer);
2583   for (auto* child : layer.Children())
2584     ForAllGraphicsLayers(*child, function);
2585 }
2586 
RunPaintLifecyclePhase()2587 void LocalFrameView::RunPaintLifecyclePhase() {
2588   TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
2589   // While printing or capturing a paint preview of a document, the paint walk
2590   // is done into a special canvas. There is no point doing a normal paint step
2591   // (or animations update) when in this mode.
2592   bool is_capturing_layout = frame_->GetDocument()->IsCapturingLayout();
2593   if (!is_capturing_layout)
2594     PaintTree();
2595 
2596   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2597     if (GetLayoutView()->Compositor()->InCompositingMode()) {
2598       GetScrollingCoordinator()->UpdateAfterPaint(this);
2599     }
2600   }
2601 
2602   if (!is_capturing_layout) {
2603     bool needed_update = !paint_artifact_compositor_ ||
2604                          paint_artifact_compositor_->NeedsUpdate();
2605     PushPaintArtifactToCompositor();
2606     ForAllNonThrottledLocalFrameViews([this](LocalFrameView& frame_view) {
2607       frame_view.GetScrollableArea()->UpdateCompositorScrollAnimations();
2608       if (const auto* animating_scrollable_areas =
2609               frame_view.AnimatingScrollableAreas()) {
2610         for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
2611           area->UpdateCompositorScrollAnimations();
2612       }
2613       frame_view.GetLayoutView()
2614           ->GetDocument()
2615           .GetDocumentAnimations()
2616           .UpdateAnimations(DocumentLifecycle::kPaintClean,
2617                             paint_artifact_compositor_.get());
2618     });
2619 
2620     // Initialize animation properties in the newly created paint property
2621     // nodes according to the current animation state. This is mainly for
2622     // the running composited animations which didn't change state during
2623     // above UpdateAnimations() but associated with new paint property nodes.
2624     if (needed_update) {
2625       auto* root_layer = RootCcLayer();
2626       if (root_layer && root_layer->layer_tree_host()) {
2627         root_layer->layer_tree_host()
2628             ->mutator_host()
2629             ->InitClientAnimationState();
2630       }
2631     }
2632 
2633     // Notify the controller that the artifact has been pushed and some
2634     // lifecycle state can be freed (such as raster invalidations).
2635     if (paint_controller_)
2636       paint_controller_->FinishCycle();
2637 
2638     if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2639       // Property tree changed state is typically cleared through
2640       // |PaintController::FinishCycle| but that will be a no-op because
2641       // the paint controller is transient, so force the changed state to be
2642       // cleared here.
2643       if (paint_controller_) {
2644         paint_controller_->ClearPropertyTreeChangedStateTo(
2645             PropertyTreeState::Root());
2646       }
2647       auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
2648       if (root) {
2649         ForAllGraphicsLayers(*root, [](GraphicsLayer& layer) {
2650           if (layer.PaintsContentOrHitTest() && layer.HasLayerState()) {
2651             layer.GetPaintController().ClearPropertyTreeChangedStateTo(
2652                 layer.GetPropertyTreeState());
2653           }
2654         });
2655       }
2656     }
2657   }
2658 }
2659 
RunAccessibilityLifecyclePhase(DocumentLifecycle::LifecycleState target_state)2660 bool LocalFrameView::RunAccessibilityLifecyclePhase(
2661     DocumentLifecycle::LifecycleState target_state) {
2662   TRACE_EVENT0("blink,benchmark",
2663                "LocalFrameView::RunAccessibilityLifecyclePhase");
2664   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2665     if (AXObjectCache* cache = frame_view.ExistingAXObjectCache()) {
2666       frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInAccessibility);
2667       cache->ProcessDeferredAccessibilityEvents(
2668           *frame_view.GetFrame().GetDocument());
2669       frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kAccessibilityClean);
2670     }
2671   });
2672 
2673   return target_state > DocumentLifecycle::kAccessibilityClean;
2674 }
2675 
EnqueueScrollAnchoringAdjustment(ScrollableArea * scrollable_area)2676 void LocalFrameView::EnqueueScrollAnchoringAdjustment(
2677     ScrollableArea* scrollable_area) {
2678   anchoring_adjustment_queue_.insert(scrollable_area);
2679 }
2680 
DequeueScrollAnchoringAdjustment(ScrollableArea * scrollable_area)2681 void LocalFrameView::DequeueScrollAnchoringAdjustment(
2682     ScrollableArea* scrollable_area) {
2683   anchoring_adjustment_queue_.erase(scrollable_area);
2684 }
2685 
SetNeedsEnqueueScrollEvent(PaintLayerScrollableArea * scrollable_area)2686 void LocalFrameView::SetNeedsEnqueueScrollEvent(
2687     PaintLayerScrollableArea* scrollable_area) {
2688   scroll_event_queue_.insert(scrollable_area);
2689   GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
2690 }
2691 
PerformScrollAnchoringAdjustments()2692 void LocalFrameView::PerformScrollAnchoringAdjustments() {
2693   // Adjust() will cause a scroll which could end up causing a layout and
2694   // reentering this method. Copy and clear the queue so we don't modify it
2695   // during iteration.
2696   AnchoringAdjustmentQueue queue_copy = anchoring_adjustment_queue_;
2697   anchoring_adjustment_queue_.clear();
2698 
2699   for (const WeakMember<ScrollableArea>& scroller : queue_copy) {
2700     if (scroller) {
2701       DCHECK(scroller->GetScrollAnchor());
2702       scroller->GetScrollAnchor()->Adjust();
2703     }
2704   }
2705 }
2706 
EnqueueScrollEvents()2707 void LocalFrameView::EnqueueScrollEvents() {
2708   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2709     for (const WeakMember<PaintLayerScrollableArea>& scroller :
2710          frame_view.scroll_event_queue_) {
2711       if (scroller)
2712         scroller->EnqueueScrollEventIfNeeded();
2713     }
2714     frame_view.scroll_event_queue_.clear();
2715   });
2716 }
2717 
2718 template <typename MainLayerFunction, typename ContentsLayerFunction>
ForAllDrawableGraphicsLayers(const GraphicsLayer * layer,const MainLayerFunction & main_layer_function,const ContentsLayerFunction & contents_layer_function)2719 static void ForAllDrawableGraphicsLayers(
2720     const GraphicsLayer* layer,
2721     const MainLayerFunction& main_layer_function,
2722     const ContentsLayerFunction& contents_layer_function) {
2723   if (!layer || layer->Client().ShouldThrottleRendering() ||
2724       layer->Client().IsUnderSVGHiddenContainer()) {
2725     return;
2726   }
2727 
2728   if (layer->Client().PaintBlockedByDisplayLockIncludingAncestors(
2729           DisplayLockContextLifecycleTarget::kSelf)) {
2730     // If we skip the layer, then we need to ensure to notify the
2731     // display-lock, since we need to force recollect the layers when we commit.
2732     layer->Client().NotifyDisplayLockNeedsGraphicsLayerCollection();
2733     return;
2734   }
2735 
2736   // We need to collect all layers that draw content, as well as some layers
2737   // that don't for the purposes of hit testing. For example, an empty div
2738   // will not draw content but needs to create a layer to ensure scroll events
2739   // do not pass through it.
2740   if (layer->PaintsContentOrHitTest() || layer->GetHitTestable())
2741     main_layer_function(layer);
2742 
2743   if (auto* contents_layer = layer->ContentsLayer())
2744     contents_layer_function(layer, contents_layer);
2745 
2746   for (const auto* child : layer->Children()) {
2747     ForAllDrawableGraphicsLayers(child, main_layer_function,
2748                                  contents_layer_function);
2749   }
2750   ForAllDrawableGraphicsLayers(layer->MaskLayer(), main_layer_function,
2751                                contents_layer_function);
2752 }
2753 
CollectDrawableLayersForLayerListRecursively(GraphicsContext & context,const GraphicsLayer * root)2754 static void CollectDrawableLayersForLayerListRecursively(
2755     GraphicsContext& context,
2756     const GraphicsLayer* root) {
2757   ForAllDrawableGraphicsLayers(
2758       root,
2759       [&](const GraphicsLayer* layer) { RecordGraphicsLayer(context, *layer); },
2760       [&](const GraphicsLayer* layer, cc::Layer* contents_layer) {
2761         RecordForeignLayer(
2762             context, *layer, DisplayItem::kForeignLayerContentsWrapper,
2763             contents_layer,
2764             FloatPoint(layer->GetContentsOffsetFromTransformNode()),
2765             &layer->GetContentsPropertyTreeState());
2766       });
2767 }
2768 
UpdateLayerDebugInfoRecursively(const GraphicsLayer * root)2769 static void UpdateLayerDebugInfoRecursively(const GraphicsLayer* root) {
2770   ForAllDrawableGraphicsLayers(
2771       root,
2772       [](const GraphicsLayer* layer) {
2773         PaintArtifactCompositor::UpdateLayerDebugInfo(
2774             layer->CcLayer(),
2775             PaintChunk::Id(*layer, DisplayItem::kGraphicsLayerWrapper),
2776             layer->GetCompositingReasons(),
2777             layer->GetRasterInvalidationTracking());
2778       },
2779       [](const GraphicsLayer* layer, cc::Layer* contents_layer) {
2780         PaintArtifactCompositor::UpdateLayerDebugInfo(
2781             contents_layer,
2782             PaintChunk::Id(*layer, DisplayItem::kForeignLayerContentsWrapper),
2783             layer->GetCompositingReasons(), nullptr);
2784       });
2785 }
2786 
PaintGraphicsLayerRecursively(GraphicsLayer * layer)2787 static bool PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
2788   bool painted = layer->PaintRecursively();
2789 #if DCHECK_IS_ON()
2790   VerboseLogGraphicsLayerTree(layer);
2791 #endif
2792   return painted;
2793 }
2794 
PaintTree()2795 void LocalFrameView::PaintTree() {
2796   SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
2797                            LocalFrameUkmAggregator::kPaint);
2798 
2799   DCHECK(GetFrame().IsLocalRoot());
2800 
2801   auto* layout_view = GetLayoutView();
2802   DCHECK(layout_view);
2803   paint_frame_count_++;
2804   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2805     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint);
2806   });
2807 
2808   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2809     if (!paint_controller_)
2810       paint_controller_ = std::make_unique<PaintController>();
2811 
2812     // TODO(crbug.com/917911): Painting of overlays should not force repainting
2813     // of the frame contents.
2814     auto* web_local_frame_impl = WebLocalFrameImpl::FromFrame(frame_);
2815     bool has_dev_tools_overlays =
2816         web_local_frame_impl && web_local_frame_impl->HasDevToolsOverlays();
2817     if (!GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint() &&
2818         !visual_viewport_needs_repaint_ && !has_dev_tools_overlays) {
2819       paint_controller_->UpdateUMACountsOnFullyCached();
2820     } else {
2821       GraphicsContext graphics_context(*paint_controller_);
2822       if (Settings* settings = frame_->GetSettings()) {
2823         graphics_context.SetDarkMode(
2824             BuildDarkModeSettings(*settings, *GetLayoutView()));
2825       }
2826 
2827       PaintInternal(graphics_context, kGlobalPaintNormalPhase,
2828                     CullRect::Infinite());
2829 
2830       GetPage()->GetLinkHighlight().Paint(graphics_context);
2831 
2832       GetPage()->GetValidationMessageClient().PaintOverlay(graphics_context);
2833       ForAllNonThrottledLocalFrameViews(
2834           [&graphics_context](LocalFrameView& view) {
2835             view.frame_->PaintFrameColorOverlay(graphics_context);
2836           });
2837 
2838       // Devtools overlays query the inspected page's paint data so this update
2839       // needs to be after other paintings.
2840       if (has_dev_tools_overlays)
2841         web_local_frame_impl->PaintDevToolsOverlays(graphics_context);
2842 
2843       if (frame_->IsMainFrame()) {
2844         frame_->GetPage()->GetVisualViewport().Paint(graphics_context);
2845         visual_viewport_needs_repaint_ = false;
2846       } else {
2847         DCHECK(!visual_viewport_needs_repaint_);
2848       }
2849 
2850       paint_controller_->CommitNewDisplayItems();
2851     }
2852   } else {
2853     // A null graphics layer can occur for painting of SVG images that are not
2854     // parented into the main frame tree, or when the LocalFrameView is the main
2855     // frame view of a page overlay. The page overlay is in the layer tree of
2856     // the host page and will be painted during painting of the host page.
2857     if (GraphicsLayer* root_graphics_layer =
2858             layout_view->Compositor()->PaintRootGraphicsLayer()) {
2859       bool painted = PaintGraphicsLayerRecursively(root_graphics_layer);
2860       if (painted) {
2861         // If the painted result changed, the recorded hit test data may have
2862         // changed which will affect the mapped hit test geometry.
2863         if (GetScrollingCoordinator())
2864           GetScrollingCoordinator()->NotifyGeometryChanged(this);
2865       }
2866     }
2867   }
2868 
2869   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
2870     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
2871     if (auto* layout_view = frame_view.GetLayoutView())
2872       layout_view->Layer()->ClearNeedsRepaintRecursively();
2873     frame_view.GetPaintTimingDetector().NotifyPaintFinished();
2874   });
2875 
2876   PaintController::ReportUMACounts();
2877 }
2878 
RootCcLayer() const2879 const cc::Layer* LocalFrameView::RootCcLayer() const {
2880   return paint_artifact_compositor_ ? paint_artifact_compositor_->RootLayer()
2881                                     : nullptr;
2882 }
2883 
PushPaintArtifactToCompositor()2884 void LocalFrameView::PushPaintArtifactToCompositor() {
2885   TRACE_EVENT0("blink", "LocalFrameView::pushPaintArtifactToCompositor");
2886   if (!frame_->GetSettings()->GetAcceleratedCompositingEnabled())
2887     return;
2888 
2889   Page* page = GetFrame().GetPage();
2890   if (!page)
2891     return;
2892 
2893   if (!paint_artifact_compositor_) {
2894     paint_artifact_compositor_ = std::make_unique<PaintArtifactCompositor>(
2895         page->GetScrollingCoordinator()->GetWeakPtr());
2896     page->GetChromeClient().AttachRootLayer(
2897         paint_artifact_compositor_->RootLayer(), &GetFrame());
2898   }
2899 
2900   SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
2901                            LocalFrameUkmAggregator::kCompositingCommit);
2902 
2903   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
2904       layer_debug_info_enabled_) {
2905     UpdateLayerDebugInfoRecursively(
2906         GetLayoutView()->Compositor()->PaintRootGraphicsLayer());
2907   }
2908 
2909   // Skip updating property trees, pushing cc::Layers, and issuing raster
2910   // invalidations if possible.
2911   if (!paint_artifact_compositor_->NeedsUpdate()) {
2912     DCHECK(paint_controller_);
2913     return;
2914   }
2915 
2916   paint_artifact_compositor_->SetLayerDebugInfoEnabled(
2917       layer_debug_info_enabled_);
2918 
2919   PaintArtifactCompositor::ViewportProperties viewport_properties;
2920   if (GetFrame().IsMainFrame()) {
2921     const auto& viewport = page->GetVisualViewport();
2922     viewport_properties.overscroll_elasticity_transform =
2923         viewport.GetOverscrollElasticityTransformNode();
2924     viewport_properties.page_scale = viewport.GetPageScaleNode();
2925 
2926     if (const auto* root_scroller =
2927             GetPage()->GlobalRootScrollerController().GlobalRootScroller()) {
2928       if (const auto* layout_object = root_scroller->GetLayoutObject()) {
2929         if (const auto* paint_properties =
2930                 layout_object->FirstFragment().PaintProperties()) {
2931           if (paint_properties->Scroll()) {
2932             viewport_properties.outer_clip = paint_properties->OverflowClip();
2933             viewport_properties.outer_scroll_translation =
2934                 paint_properties->ScrollTranslation();
2935             viewport_properties.inner_scroll_translation =
2936                 viewport.GetScrollTranslationNode();
2937           }
2938         }
2939       }
2940     }
2941   }
2942 
2943   PaintArtifactCompositor::Settings settings;
2944   settings.prefer_compositing_to_lcd_text =
2945       page->GetSettings().GetPreferCompositingToLCDTextEnabled();
2946 
2947   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
2948       (!paint_controller_ || visual_viewport_needs_repaint_)) {
2949     // Before CompositeAfterPaint, we need a transient PaintController to
2950     // collect the foreign layers, and this doesn't need caching. This shouldn't
2951     // affect caching status of DisplayItemClients because FinishCycle() is
2952     // not synchronized with other PaintControllers. This may live across frame
2953     // updates until SetForeignLayerListNeedsUpdate() is called.
2954     paint_controller_ =
2955         std::make_unique<PaintController>(PaintController::kTransient);
2956 
2957     GraphicsContext context(*paint_controller_);
2958     auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
2959     CollectDrawableLayersForLayerListRecursively(context, root);
2960 
2961     if (frame_->IsMainFrame()) {
2962       if (root == GetLayoutView()->Compositor()->RootGraphicsLayer())
2963         frame_->GetPage()->GetVisualViewport().Paint(context);
2964       visual_viewport_needs_repaint_ = false;
2965     } else {
2966       DCHECK(!visual_viewport_needs_repaint_);
2967     }
2968 
2969     // Link highlights paint after all other layers.
2970     page->GetLinkHighlight().Paint(context);
2971 
2972     paint_controller_->CommitNewDisplayItems();
2973   }
2974 
2975   paint_artifact_compositor_->Update(
2976       paint_controller_->GetPaintArtifactShared(), viewport_properties,
2977       settings);
2978 
2979   probe::LayerTreePainted(&GetFrame());
2980 }
2981 
CompositedLayersAsJSON(LayerTreeFlags flags)2982 std::unique_ptr<JSONObject> LocalFrameView::CompositedLayersAsJSON(
2983     LayerTreeFlags flags) {
2984   auto* root_frame_view = GetFrame().LocalFrameRoot().View();
2985   if (root_frame_view->GetPaintController()) {
2986     return root_frame_view->paint_artifact_compositor_->GetLayersAsJSON(
2987         flags, &root_frame_view->GetPaintController()->GetPaintArtifact());
2988   } else {
2989     return std::make_unique<JSONObject>();
2990   }
2991 }
2992 
UpdateStyleAndLayoutIfNeededRecursive()2993 void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() {
2994   if (ShouldThrottleRendering() || !frame_->GetDocument()->IsActive())
2995     return;
2996 
2997   ScopedFrameBlamer frame_blamer(frame_);
2998   TRACE_EVENT0("blink,benchmark",
2999                "LocalFrameView::updateStyleAndLayoutIfNeededRecursive");
3000 
3001   // We have to crawl our entire subtree looking for any FrameViews that need
3002   // layout and make sure they are up to date.
3003   // Mac actually tests for intersection with the dirty region and tries not to
3004   // update layout for frames that are outside the dirty region.  Not only does
3005   // this seem pointless (since those frames will have set a zero timer to
3006   // layout anyway), but it is also incorrect, since if two frames overlap, the
3007   // first could be excluded from the dirty region but then become included
3008   // later by the second frame adding rects to the dirty region when it lays
3009   // out.
3010 
3011   {
3012     SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
3013                              LocalFrameUkmAggregator::kStyle);
3014     frame_->GetDocument()->UpdateStyleAndLayoutTree();
3015 
3016     // Update style for all embedded SVG documents underneath this frame, so
3017     // that intrinsic size computation for any embedded objects has up-to-date
3018     // information before layout.
3019     ForAllChildLocalFrameViews([](LocalFrameView& view) {
3020       Document& document = *view.GetFrame().GetDocument();
3021       if (document.IsSVGDocument())
3022         document.UpdateStyleAndLayoutTree();
3023     });
3024   }
3025 
3026   CHECK(!ShouldThrottleRendering());
3027   CHECK(frame_->GetDocument()->IsActive());
3028   CHECK(!nested_layout_count_);
3029 
3030   if (NeedsLayout()) {
3031     SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
3032                              LocalFrameUkmAggregator::kLayout);
3033     UpdateLayout();
3034   } else {
3035     UpdateGeometriesIfNeeded();
3036   }
3037 
3038   CheckDoesNotNeedLayout();
3039 
3040   // WebView plugins need to update regardless of whether the
3041   // LayoutEmbeddedObject that owns them needed layout.
3042   // TODO(schenney): This currently runs the entire lifecycle on plugin
3043   // WebViews. We should have a way to only run these other Documents to the
3044   // same lifecycle stage as this frame.
3045   for (const auto& plugin : plugins_) {
3046     plugin->UpdateAllLifecyclePhases();
3047   }
3048   CheckDoesNotNeedLayout();
3049 
3050   // FIXME: Calling layout() shouldn't trigger script execution or have any
3051   // observable effects on the frame tree but we're not quite there yet.
3052   HeapVector<Member<LocalFrameView>> frame_views;
3053   for (Frame* child = frame_->Tree().FirstChild(); child;
3054        child = child->Tree().NextSibling()) {
3055     auto* child_local_frame = DynamicTo<LocalFrame>(child);
3056     if (!child_local_frame)
3057       continue;
3058     if (LocalFrameView* view = child_local_frame->View())
3059       frame_views.push_back(view);
3060   }
3061 
3062   for (const auto& frame_view : frame_views)
3063     frame_view->UpdateStyleAndLayoutIfNeededRecursive();
3064 
3065   // These asserts ensure that parent frames are clean, when child frames
3066   // finished updating layout and style.
3067   // TODO(szager): this is the last call to CheckDoesNotNeedLayout during the
3068   // lifecycle code, but it can happen that NeedsLayout() becomes true after
3069   // this point, even while the document lifecycle proceeds to kLayoutClean
3070   // and beyond. Figure out how this happens, and do something sensible.
3071   CheckDoesNotNeedLayout();
3072 #if DCHECK_IS_ON()
3073   frame_->GetDocument()->GetLayoutView()->AssertLaidOut();
3074 #endif
3075 
3076   if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
3077     Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
3078 
3079   // If we're restoring a scroll position from history, that takes precedence
3080   // over scrolling to the anchor in the URL.
3081   frame_->GetDocument()->ApplyScrollRestorationLogic();
3082 
3083   // Ensure that we become visually non-empty eventually.
3084   // TODO(esprehn): This should check isRenderingReady() instead.
3085   if (GetFrame().GetDocument()->HasFinishedParsing() &&
3086       GetFrame().Loader().StateMachine()->CommittedFirstRealDocumentLoad())
3087     is_visually_non_empty_ = true;
3088 
3089   GetFrame().Selection().UpdateStyleAndLayoutIfNeeded();
3090   GetFrame().GetPage()->GetDragCaret().UpdateStyleAndLayoutIfNeeded();
3091 }
3092 
EnableAutoSizeMode(const IntSize & min_size,const IntSize & max_size)3093 void LocalFrameView::EnableAutoSizeMode(const IntSize& min_size,
3094                                         const IntSize& max_size) {
3095   if (!auto_size_info_)
3096     auto_size_info_ = MakeGarbageCollected<FrameViewAutoSizeInfo>(this);
3097 
3098   auto_size_info_->ConfigureAutoSizeMode(min_size, max_size);
3099   SetLayoutSizeFixedToFrameSize(true);
3100   SetNeedsLayout();
3101   ScheduleRelayout();
3102 }
3103 
DisableAutoSizeMode()3104 void LocalFrameView::DisableAutoSizeMode() {
3105   if (!auto_size_info_)
3106     return;
3107 
3108   SetLayoutSizeFixedToFrameSize(false);
3109   SetNeedsLayout();
3110   ScheduleRelayout();
3111 
3112   // Since autosize mode forces the scrollbar mode, change them to being auto.
3113   GetLayoutView()->SetAutosizeScrollbarModes(
3114       mojom::blink::ScrollbarMode::kAuto, mojom::blink::ScrollbarMode::kAuto);
3115   auto_size_info_.Clear();
3116 }
3117 
ForceLayoutForPagination(const FloatSize & page_size,const FloatSize & original_page_size,float maximum_shrink_factor)3118 void LocalFrameView::ForceLayoutForPagination(
3119     const FloatSize& page_size,
3120     const FloatSize& original_page_size,
3121     float maximum_shrink_factor) {
3122   // Dumping externalRepresentation(m_frame->layoutObject()).ascii() is a good
3123   // trick to see the state of things before and after the layout
3124   if (LayoutView* layout_view = this->GetLayoutView()) {
3125     float page_logical_width = layout_view->StyleRef().IsHorizontalWritingMode()
3126                                    ? page_size.Width()
3127                                    : page_size.Height();
3128     float page_logical_height =
3129         layout_view->StyleRef().IsHorizontalWritingMode() ? page_size.Height()
3130                                                           : page_size.Width();
3131 
3132     LayoutUnit floored_page_logical_width =
3133         static_cast<LayoutUnit>(page_logical_width);
3134     LayoutUnit floored_page_logical_height =
3135         static_cast<LayoutUnit>(page_logical_height);
3136     layout_view->SetLogicalWidth(floored_page_logical_width);
3137     layout_view->SetPageLogicalHeight(floored_page_logical_height);
3138     layout_view->SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
3139         layout_invalidation_reason::kPrintingChanged);
3140     UpdateLayout();
3141 
3142     // If we don't fit in the given page width, we'll lay out again. If we don't
3143     // fit in the page width when shrunk, we will lay out at maximum shrink and
3144     // clip extra content.
3145     // FIXME: We are assuming a shrink-to-fit printing implementation.  A
3146     // cropping implementation should not do this!
3147     bool horizontal_writing_mode =
3148         layout_view->StyleRef().IsHorizontalWritingMode();
3149     PhysicalRect document_rect(layout_view->DocumentRect());
3150     LayoutUnit doc_logical_width = horizontal_writing_mode
3151                                        ? document_rect.Width()
3152                                        : document_rect.Height();
3153     if (doc_logical_width > page_logical_width) {
3154       // ResizePageRectsKeepingRatio would truncate the expected page size,
3155       // while we want it rounded -- so make sure it's rounded here.
3156       FloatSize expected_page_size(
3157           std::min<float>(document_rect.Width().Round(),
3158                           page_size.Width() * maximum_shrink_factor),
3159           std::min<float>(document_rect.Height().Round(),
3160                           page_size.Height() * maximum_shrink_factor));
3161       FloatSize max_page_size = frame_->ResizePageRectsKeepingRatio(
3162           FloatSize(original_page_size.Width(), original_page_size.Height()),
3163           expected_page_size);
3164       page_logical_width = horizontal_writing_mode ? max_page_size.Width()
3165                                                    : max_page_size.Height();
3166       page_logical_height = horizontal_writing_mode ? max_page_size.Height()
3167                                                     : max_page_size.Width();
3168 
3169       floored_page_logical_width = static_cast<LayoutUnit>(page_logical_width);
3170       floored_page_logical_height =
3171           static_cast<LayoutUnit>(page_logical_height);
3172       layout_view->SetLogicalWidth(floored_page_logical_width);
3173       layout_view->SetPageLogicalHeight(floored_page_logical_height);
3174       layout_view
3175           ->SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
3176               layout_invalidation_reason::kPrintingChanged);
3177       UpdateLayout();
3178 
3179       PhysicalRect updated_document_rect(layout_view->DocumentRect());
3180       LayoutUnit doc_logical_height = horizontal_writing_mode
3181                                           ? updated_document_rect.Height()
3182                                           : updated_document_rect.Width();
3183       LayoutUnit doc_logical_top = horizontal_writing_mode
3184                                        ? updated_document_rect.Y()
3185                                        : updated_document_rect.X();
3186       LayoutUnit doc_logical_right = horizontal_writing_mode
3187                                          ? updated_document_rect.Right()
3188                                          : updated_document_rect.Bottom();
3189       LayoutUnit clipped_logical_left;
3190       if (!layout_view->StyleRef().IsLeftToRightDirection()) {
3191         clipped_logical_left =
3192             LayoutUnit(doc_logical_right - page_logical_width);
3193       }
3194       LayoutRect overflow(clipped_logical_left, doc_logical_top,
3195                           LayoutUnit(page_logical_width), doc_logical_height);
3196 
3197       if (!horizontal_writing_mode)
3198         overflow = overflow.TransposedRect();
3199       AdjustViewSizeAndLayout();
3200       // This is how we clip in case we overflow again.
3201       layout_view->ClearLayoutOverflow();
3202       layout_view->AddLayoutOverflow(overflow);
3203       return;
3204     }
3205   }
3206 
3207   if (TextAutosizer* text_autosizer = frame_->GetDocument()->GetTextAutosizer())
3208     text_autosizer->UpdatePageInfo();
3209   AdjustViewSizeAndLayout();
3210 }
3211 
ConvertFromLayoutObject(const LayoutObject & layout_object,const IntRect & layout_object_rect) const3212 IntRect LocalFrameView::ConvertFromLayoutObject(
3213     const LayoutObject& layout_object,
3214     const IntRect& layout_object_rect) const {
3215   // Convert from page ("absolute") to LocalFrameView coordinates.
3216   return PixelSnappedIntRect(
3217       layout_object.LocalToAbsoluteRect(PhysicalRect(layout_object_rect)));
3218 }
3219 
ConvertToLayoutObject(const LayoutObject & layout_object,const IntRect & frame_rect) const3220 IntRect LocalFrameView::ConvertToLayoutObject(const LayoutObject& layout_object,
3221                                               const IntRect& frame_rect) const {
3222   return PixelSnappedIntRect(
3223       layout_object.AbsoluteToLocalRect(PhysicalRect(frame_rect)));
3224 }
3225 
ConvertFromLayoutObject(const LayoutObject & layout_object,const IntPoint & layout_object_point) const3226 IntPoint LocalFrameView::ConvertFromLayoutObject(
3227     const LayoutObject& layout_object,
3228     const IntPoint& layout_object_point) const {
3229   return RoundedIntPoint(ConvertFromLayoutObject(
3230       layout_object, PhysicalOffset(layout_object_point)));
3231 }
3232 
ConvertToLayoutObject(const LayoutObject & layout_object,const IntPoint & frame_point) const3233 IntPoint LocalFrameView::ConvertToLayoutObject(
3234     const LayoutObject& layout_object,
3235     const IntPoint& frame_point) const {
3236   return RoundedIntPoint(
3237       ConvertToLayoutObject(layout_object, PhysicalOffset(frame_point)));
3238 }
3239 
ConvertFromLayoutObject(const LayoutObject & layout_object,const PhysicalOffset & layout_object_offset) const3240 PhysicalOffset LocalFrameView::ConvertFromLayoutObject(
3241     const LayoutObject& layout_object,
3242     const PhysicalOffset& layout_object_offset) const {
3243   return layout_object.LocalToAbsolutePoint(layout_object_offset);
3244 }
3245 
ConvertToLayoutObject(const LayoutObject & layout_object,const PhysicalOffset & frame_offset) const3246 PhysicalOffset LocalFrameView::ConvertToLayoutObject(
3247     const LayoutObject& layout_object,
3248     const PhysicalOffset& frame_offset) const {
3249   return PhysicalOffset::FromFloatPointRound(
3250       ConvertToLayoutObject(layout_object, FloatPoint(frame_offset)));
3251 }
3252 
ConvertToLayoutObject(const LayoutObject & layout_object,const FloatPoint & frame_point) const3253 FloatPoint LocalFrameView::ConvertToLayoutObject(
3254     const LayoutObject& layout_object,
3255     const FloatPoint& frame_point) const {
3256   return layout_object.AbsoluteToLocalFloatPoint(frame_point);
3257 }
3258 
ConvertSelfToChild(const EmbeddedContentView & child,const IntPoint & point) const3259 IntPoint LocalFrameView::ConvertSelfToChild(const EmbeddedContentView& child,
3260                                             const IntPoint& point) const {
3261   IntPoint new_point(point);
3262   new_point.MoveBy(-child.Location());
3263   return new_point;
3264 }
3265 
RootFrameToDocument(const IntRect & rect_in_root_frame)3266 IntRect LocalFrameView::RootFrameToDocument(const IntRect& rect_in_root_frame) {
3267   IntPoint offset = RootFrameToDocument(rect_in_root_frame.Location());
3268   IntRect local_rect = rect_in_root_frame;
3269   local_rect.SetLocation(offset);
3270   return local_rect;
3271 }
3272 
RootFrameToDocument(const IntPoint & point_in_root_frame)3273 IntPoint LocalFrameView::RootFrameToDocument(
3274     const IntPoint& point_in_root_frame) {
3275   return FlooredIntPoint(RootFrameToDocument(FloatPoint(point_in_root_frame)));
3276 }
3277 
RootFrameToDocument(const FloatPoint & point_in_root_frame)3278 FloatPoint LocalFrameView::RootFrameToDocument(
3279     const FloatPoint& point_in_root_frame) {
3280   ScrollableArea* layout_viewport = LayoutViewport();
3281   if (!layout_viewport)
3282     return point_in_root_frame;
3283 
3284   FloatPoint local_frame = ConvertFromRootFrame(point_in_root_frame);
3285   return local_frame + layout_viewport->GetScrollOffset();
3286 }
3287 
DocumentToFrame(const IntRect & rect_in_document) const3288 IntRect LocalFrameView::DocumentToFrame(const IntRect& rect_in_document) const {
3289   IntRect rect_in_frame = rect_in_document;
3290   rect_in_frame.SetLocation(DocumentToFrame(rect_in_document.Location()));
3291   return rect_in_frame;
3292 }
3293 
DocumentToFrame(const DoublePoint & point_in_document) const3294 DoublePoint LocalFrameView::DocumentToFrame(
3295     const DoublePoint& point_in_document) const {
3296   ScrollableArea* layout_viewport = LayoutViewport();
3297   if (!layout_viewport)
3298     return point_in_document;
3299 
3300   return point_in_document - layout_viewport->GetScrollOffset();
3301 }
3302 
DocumentToFrame(const IntPoint & point_in_document) const3303 IntPoint LocalFrameView::DocumentToFrame(
3304     const IntPoint& point_in_document) const {
3305   return FlooredIntPoint(DocumentToFrame(DoublePoint(point_in_document)));
3306 }
3307 
DocumentToFrame(const FloatPoint & point_in_document) const3308 FloatPoint LocalFrameView::DocumentToFrame(
3309     const FloatPoint& point_in_document) const {
3310   return FloatPoint(DocumentToFrame(DoublePoint(point_in_document)));
3311 }
3312 
DocumentToFrame(const PhysicalOffset & offset_in_document) const3313 PhysicalOffset LocalFrameView::DocumentToFrame(
3314     const PhysicalOffset& offset_in_document) const {
3315   ScrollableArea* layout_viewport = LayoutViewport();
3316   if (!layout_viewport)
3317     return offset_in_document;
3318 
3319   return offset_in_document -
3320          PhysicalOffset::FromFloatSizeRound(layout_viewport->GetScrollOffset());
3321 }
3322 
DocumentToFrame(const PhysicalRect & rect_in_document) const3323 PhysicalRect LocalFrameView::DocumentToFrame(
3324     const PhysicalRect& rect_in_document) const {
3325   return PhysicalRect(DocumentToFrame(rect_in_document.offset),
3326                       rect_in_document.size);
3327 }
3328 
FrameToDocument(const IntPoint & point_in_frame) const3329 IntPoint LocalFrameView::FrameToDocument(const IntPoint& point_in_frame) const {
3330   return FlooredIntPoint(FrameToDocument(PhysicalOffset(point_in_frame)));
3331 }
3332 
FrameToDocument(const PhysicalOffset & offset_in_frame) const3333 PhysicalOffset LocalFrameView::FrameToDocument(
3334     const PhysicalOffset& offset_in_frame) const {
3335   ScrollableArea* layout_viewport = LayoutViewport();
3336   if (!layout_viewport)
3337     return offset_in_frame;
3338 
3339   return offset_in_frame +
3340          PhysicalOffset::FromFloatSizeRound(layout_viewport->GetScrollOffset());
3341 }
3342 
FrameToDocument(const IntRect & rect_in_frame) const3343 IntRect LocalFrameView::FrameToDocument(const IntRect& rect_in_frame) const {
3344   return IntRect(FrameToDocument(rect_in_frame.Location()),
3345                  rect_in_frame.Size());
3346 }
3347 
FrameToDocument(const PhysicalRect & rect_in_frame) const3348 PhysicalRect LocalFrameView::FrameToDocument(
3349     const PhysicalRect& rect_in_frame) const {
3350   return PhysicalRect(FrameToDocument(rect_in_frame.offset),
3351                       rect_in_frame.size);
3352 }
3353 
ConvertToContainingEmbeddedContentView(const IntRect & local_rect) const3354 IntRect LocalFrameView::ConvertToContainingEmbeddedContentView(
3355     const IntRect& local_rect) const {
3356   if (LocalFrameView* parent = ParentFrameView()) {
3357     auto* layout_object = GetLayoutEmbeddedContent();
3358     if (!layout_object)
3359       return local_rect;
3360 
3361     IntRect rect(local_rect);
3362     // Add borders and padding
3363     rect.Move(
3364         (layout_object->BorderLeft() + layout_object->PaddingLeft()).ToInt(),
3365         (layout_object->BorderTop() + layout_object->PaddingTop()).ToInt());
3366     return parent->ConvertFromLayoutObject(*layout_object, rect);
3367   }
3368 
3369   return local_rect;
3370 }
3371 
ConvertFromContainingEmbeddedContentView(const IntRect & parent_rect) const3372 IntRect LocalFrameView::ConvertFromContainingEmbeddedContentView(
3373     const IntRect& parent_rect) const {
3374   if (LocalFrameView* parent = ParentFrameView()) {
3375     IntRect local_rect = parent_rect;
3376     local_rect.SetLocation(
3377         parent->ConvertSelfToChild(*this, local_rect.Location()));
3378     return local_rect;
3379   }
3380 
3381   return parent_rect;
3382 }
3383 
ConvertToContainingEmbeddedContentView(const PhysicalOffset & local_offset) const3384 PhysicalOffset LocalFrameView::ConvertToContainingEmbeddedContentView(
3385     const PhysicalOffset& local_offset) const {
3386   if (LocalFrameView* parent = ParentFrameView()) {
3387     auto* layout_object = GetLayoutEmbeddedContent();
3388     if (!layout_object)
3389       return local_offset;
3390 
3391     PhysicalOffset point(local_offset);
3392 
3393     // Add borders and padding
3394     point += PhysicalOffset(
3395         layout_object->BorderLeft() + layout_object->PaddingLeft(),
3396         layout_object->BorderTop() + layout_object->PaddingTop());
3397     return parent->ConvertFromLayoutObject(*layout_object, point);
3398   }
3399 
3400   return local_offset;
3401 }
3402 
ConvertToContainingEmbeddedContentView(const FloatPoint & local_point) const3403 FloatPoint LocalFrameView::ConvertToContainingEmbeddedContentView(
3404     const FloatPoint& local_point) const {
3405   if (ParentFrameView()) {
3406     auto* layout_object = GetLayoutEmbeddedContent();
3407     if (!layout_object)
3408       return local_point;
3409 
3410     PhysicalOffset point = PhysicalOffset::FromFloatPointRound(local_point);
3411 
3412     // Add borders and padding
3413     point.left += layout_object->BorderLeft() + layout_object->PaddingLeft();
3414     point.top += layout_object->BorderTop() + layout_object->PaddingTop();
3415     return FloatPoint(layout_object->LocalToAbsolutePoint(point));
3416   }
3417 
3418   return local_point;
3419 }
3420 
ConvertFromContainingEmbeddedContentView(const PhysicalOffset & parent_offset) const3421 PhysicalOffset LocalFrameView::ConvertFromContainingEmbeddedContentView(
3422     const PhysicalOffset& parent_offset) const {
3423   return PhysicalOffset::FromFloatPointRound(
3424       ConvertFromContainingEmbeddedContentView(FloatPoint(parent_offset)));
3425 }
3426 
ConvertFromContainingEmbeddedContentView(const FloatPoint & parent_point) const3427 FloatPoint LocalFrameView::ConvertFromContainingEmbeddedContentView(
3428     const FloatPoint& parent_point) const {
3429   return FloatPoint(
3430       ConvertFromContainingEmbeddedContentView(DoublePoint(parent_point)));
3431 }
3432 
ConvertFromContainingEmbeddedContentView(const DoublePoint & parent_point) const3433 DoublePoint LocalFrameView::ConvertFromContainingEmbeddedContentView(
3434     const DoublePoint& parent_point) const {
3435   if (LocalFrameView* parent = ParentFrameView()) {
3436     // Get our layoutObject in the parent view
3437     auto* layout_object = GetLayoutEmbeddedContent();
3438     if (!layout_object)
3439       return parent_point;
3440 
3441     DoublePoint point = DoublePoint(parent->ConvertToLayoutObject(
3442         *layout_object, FloatPoint(parent_point)));
3443     // Subtract borders and padding
3444     point.Move(
3445         (-layout_object->BorderLeft() - layout_object->PaddingLeft())
3446             .ToDouble(),
3447         (-layout_object->BorderTop() - layout_object->PaddingTop()).ToDouble());
3448     return point;
3449   }
3450 
3451   return parent_point;
3452 }
3453 
ConvertToContainingEmbeddedContentView(const IntPoint & local_point) const3454 IntPoint LocalFrameView::ConvertToContainingEmbeddedContentView(
3455     const IntPoint& local_point) const {
3456   return RoundedIntPoint(
3457       ConvertToContainingEmbeddedContentView(PhysicalOffset(local_point)));
3458 }
3459 
SetTracksRasterInvalidations(bool track_raster_invalidations)3460 void LocalFrameView::SetTracksRasterInvalidations(
3461     bool track_raster_invalidations) {
3462   if (track_raster_invalidations == is_tracking_raster_invalidations_)
3463     return;
3464 
3465   // Ensure the document is up-to-date before tracking invalidations.
3466   UpdateAllLifecyclePhases(DocumentUpdateReason::kTest);
3467 
3468   for (Frame* frame = &frame_->Tree().Top(); frame;
3469        frame = frame->Tree().TraverseNext()) {
3470     auto* local_frame = DynamicTo<LocalFrame>(frame);
3471     if (!local_frame)
3472       continue;
3473     if (auto* layout_view = local_frame->ContentLayoutObject()) {
3474       is_tracking_raster_invalidations_ = track_raster_invalidations;
3475       if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
3476         if (paint_artifact_compositor_) {
3477           paint_artifact_compositor_->SetTracksRasterInvalidations(
3478               track_raster_invalidations);
3479         }
3480       } else {
3481         layout_view->Compositor()->UpdateTrackingRasterInvalidations();
3482       }
3483     }
3484   }
3485 
3486   TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
3487                        "LocalFrameView::setTracksPaintInvalidations",
3488                        TRACE_EVENT_SCOPE_GLOBAL, "enabled",
3489                        track_raster_invalidations);
3490 }
3491 
ScheduleAnimation(base::TimeDelta delay)3492 void LocalFrameView::ScheduleAnimation(base::TimeDelta delay) {
3493   if (auto* client = GetChromeClient())
3494     client->ScheduleAnimation(this, delay);
3495 }
3496 
ScrollableAreasDidChange()3497 void LocalFrameView::ScrollableAreasDidChange() {
3498   // Layout may update scrollable area bounding boxes. It also sets the same
3499   // dirty flag making this one redundant (See
3500   // |ScrollingCoordinator::notifyGeometryChanged|).
3501   // So if layout is expected, ignore this call allowing scrolling coordinator
3502   // to be notified post-layout to recompute gesture regions.
3503   // TODO(wjmaclean): It would be nice to move the !NeedsLayout() check from
3504   // here to SetScrollGestureRegionIsDirty(), but at present doing so breaks
3505   // web tests. This suggests that there is something that wants to set the
3506   // dirty bit when layout is needed, and won't re-try setting the bit after
3507   // layout has completed - it would be nice to find that and fix it.
3508   if (!NeedsLayout())
3509     GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
3510 }
3511 
AddScrollableArea(PaintLayerScrollableArea * scrollable_area)3512 void LocalFrameView::AddScrollableArea(
3513     PaintLayerScrollableArea* scrollable_area) {
3514   DCHECK(scrollable_area);
3515   if (!scrollable_areas_)
3516     scrollable_areas_ = MakeGarbageCollected<ScrollableAreaSet>();
3517   scrollable_areas_->insert(scrollable_area);
3518 
3519   if (GetScrollingCoordinator())
3520     ScrollableAreasDidChange();
3521 }
3522 
RemoveScrollableArea(PaintLayerScrollableArea * scrollable_area)3523 void LocalFrameView::RemoveScrollableArea(
3524     PaintLayerScrollableArea* scrollable_area) {
3525   if (!scrollable_areas_)
3526     return;
3527   scrollable_areas_->erase(scrollable_area);
3528 
3529   if (GetScrollingCoordinator())
3530     ScrollableAreasDidChange();
3531 }
3532 
AddAnimatingScrollableArea(PaintLayerScrollableArea * scrollable_area)3533 void LocalFrameView::AddAnimatingScrollableArea(
3534     PaintLayerScrollableArea* scrollable_area) {
3535   DCHECK(scrollable_area);
3536   if (!animating_scrollable_areas_)
3537     animating_scrollable_areas_ = MakeGarbageCollected<ScrollableAreaSet>();
3538   animating_scrollable_areas_->insert(scrollable_area);
3539 }
3540 
RemoveAnimatingScrollableArea(PaintLayerScrollableArea * scrollable_area)3541 void LocalFrameView::RemoveAnimatingScrollableArea(
3542     PaintLayerScrollableArea* scrollable_area) {
3543   if (!animating_scrollable_areas_)
3544     return;
3545   animating_scrollable_areas_->erase(scrollable_area);
3546 }
3547 
AttachToLayout()3548 void LocalFrameView::AttachToLayout() {
3549   CHECK(!IsAttached());
3550   if (frame_->GetDocument())
3551     CHECK_NE(Lifecycle().GetState(), DocumentLifecycle::kStopping);
3552   SetAttached(true);
3553   LocalFrameView* parent_view = ParentFrameView();
3554   CHECK(parent_view);
3555   if (parent_view->IsVisible())
3556     SetParentVisible(true);
3557   UpdateRenderThrottlingStatus(IsHiddenForThrottling(),
3558                                parent_view->CanThrottleRendering());
3559 
3560   // We may have updated paint properties in detached frame subtree for
3561   // printing (see UpdateLifecyclePhasesForPrinting()). The paint properties
3562   // may change after the frame is attached.
3563   if (auto* layout_view = GetLayoutView()) {
3564     layout_view->AddSubtreePaintPropertyUpdateReason(
3565         SubtreePaintPropertyUpdateReason::kPrinting);
3566   }
3567 }
3568 
DetachFromLayout()3569 void LocalFrameView::DetachFromLayout() {
3570   CHECK(IsAttached());
3571   SetParentVisible(false);
3572   SetAttached(false);
3573 
3574   // We may need update paint properties in detached frame subtree for printing.
3575   // See UpdateLifecyclePhasesForPrinting().
3576   if (auto* layout_view = GetLayoutView()) {
3577     layout_view->AddSubtreePaintPropertyUpdateReason(
3578         SubtreePaintPropertyUpdateReason::kPrinting);
3579   }
3580 }
3581 
AddPlugin(WebPluginContainerImpl * plugin)3582 void LocalFrameView::AddPlugin(WebPluginContainerImpl* plugin) {
3583   DCHECK(!plugins_.Contains(plugin));
3584   plugins_.insert(plugin);
3585 }
3586 
RemovePlugin(WebPluginContainerImpl * plugin)3587 void LocalFrameView::RemovePlugin(WebPluginContainerImpl* plugin) {
3588   DCHECK(plugins_.Contains(plugin));
3589   plugins_.erase(plugin);
3590 }
3591 
RemoveScrollbar(Scrollbar * scrollbar)3592 void LocalFrameView::RemoveScrollbar(Scrollbar* scrollbar) {
3593   DCHECK(scrollbars_.Contains(scrollbar));
3594   scrollbars_.erase(scrollbar);
3595 }
3596 
AddScrollbar(Scrollbar * scrollbar)3597 void LocalFrameView::AddScrollbar(Scrollbar* scrollbar) {
3598   DCHECK(!scrollbars_.Contains(scrollbar));
3599   scrollbars_.insert(scrollbar);
3600 }
3601 
VisualViewportSuppliesScrollbars()3602 bool LocalFrameView::VisualViewportSuppliesScrollbars() {
3603   // On desktop, we always use the layout viewport's scrollbars.
3604   if (!frame_->GetSettings() || !frame_->GetSettings()->GetViewportEnabled() ||
3605       !frame_->GetDocument() || !frame_->GetPage())
3606     return false;
3607 
3608   if (!LayoutViewport())
3609     return false;
3610 
3611   const TopDocumentRootScrollerController& controller =
3612       frame_->GetPage()->GlobalRootScrollerController();
3613   return controller.RootScrollerArea() == LayoutViewport();
3614 }
3615 
ExistingAXObjectCache() const3616 AXObjectCache* LocalFrameView::ExistingAXObjectCache() const {
3617   if (GetFrame().GetDocument())
3618     return GetFrame().GetDocument()->ExistingAXObjectCache();
3619   return nullptr;
3620 }
3621 
SetCursor(const ui::Cursor & cursor)3622 void LocalFrameView::SetCursor(const ui::Cursor& cursor) {
3623   Page* page = GetFrame().GetPage();
3624   if (!page || frame_->GetEventHandler().IsMousePositionUnknown())
3625     return;
3626   LogCursorSizeCounter(&GetFrame(), cursor);
3627   page->GetChromeClient().SetCursor(cursor, frame_);
3628 }
3629 
PropagateFrameRects()3630 void LocalFrameView::PropagateFrameRects() {
3631   TRACE_EVENT0("blink", "LocalFrameView::PropagateFrameRects");
3632   if (LayoutSizeFixedToFrameSize())
3633     SetLayoutSizeInternal(Size());
3634 
3635   ForAllChildViewsAndPlugins([](EmbeddedContentView& view) {
3636     auto* local_frame_view = DynamicTo<LocalFrameView>(view);
3637     if (!local_frame_view || !local_frame_view->ShouldThrottleRendering()) {
3638       view.PropagateFrameRects();
3639     }
3640   });
3641 
3642   GetFrame().Client()->FrameRectsChanged(FrameRect());
3643 
3644   // It's possible for changing the frame rect to not generate a layout
3645   // or any other event tracked by accessibility, we've seen this with
3646   // Android WebView. Ensure that the root of the accessibility tree is
3647   // invalidated so that it gets the right bounding rect.
3648   if (AXObjectCache* cache = ExistingAXObjectCache())
3649     cache->HandleFrameRectsChanged(*GetFrame().GetDocument());
3650 }
3651 
SetLayoutSizeInternal(const IntSize & size)3652 void LocalFrameView::SetLayoutSizeInternal(const IntSize& size) {
3653   if (layout_size_ == size)
3654     return;
3655   layout_size_ = size;
3656 
3657   if (frame_->IsMainFrame() && frame_->GetDocument())
3658     TextAutosizer::UpdatePageInfoInAllFrames(frame_);
3659 
3660   SetNeedsLayout();
3661 }
3662 
ClipPaintRect(FloatRect * paint_rect) const3663 void LocalFrameView::ClipPaintRect(FloatRect* paint_rect) const {
3664   // TODO(wangxianzhu): Support ChromeClient::VisibleContentRectForPainting()
3665   // with CompositeAfterPaint.
3666   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
3667 
3668   // Paint the whole rect if ClipsContent is false, meaning that the whole
3669   // document should be recorded. This occurs if:
3670   // - A paint preview is being captured.
3671   // - WebPreferences::record_whole_document is true.
3672   if (!frame_->ClipsContent())
3673     return;
3674 
3675   // By default we consider the bounds of the FrameView to be what is considered
3676   // visible for the Frame.
3677   IntRect visible_rect = IntRect(IntPoint(), Size());
3678   // Non-main frames always clip to their FrameView bounds. Main frames can
3679   // have this behaviour modified by devtools.
3680   if (frame_->IsMainFrame()) {
3681     // If devtools is overriding the viewport, then the FrameView's bounds are
3682     // not what we should paint, instead we should paint inside the bounds
3683     // specified by devtools.
3684     GetPage()->GetChromeClient().OverrideVisibleRectForMainFrame(*frame_,
3685                                                                  &visible_rect);
3686   }
3687   paint_rect->Intersect(visible_rect);
3688 }
3689 
DidChangeScrollOffset()3690 void LocalFrameView::DidChangeScrollOffset() {
3691   GetFrame().Client()->DidChangeScrollOffset();
3692   if (GetFrame().IsMainFrame()) {
3693     GetFrame().GetPage()->GetChromeClient().MainFrameScrollOffsetChanged(
3694         GetFrame());
3695   }
3696 }
3697 
ScrollableAreaWithElementId(const CompositorElementId & id)3698 ScrollableArea* LocalFrameView::ScrollableAreaWithElementId(
3699     const CompositorElementId& id) {
3700   // Check for the layout viewport, which may not be in scrollable_areas_ if it
3701   // is styled overflow: hidden.  (Other overflow: hidden elements won't have
3702   // composited scrolling layers per crbug.com/784053, so we don't have to worry
3703   // about them.)
3704   ScrollableArea* viewport = LayoutViewport();
3705   if (id == viewport->GetScrollElementId())
3706     return viewport;
3707 
3708   if (scrollable_areas_) {
3709     // This requires iterating over all scrollable areas. We may want to store a
3710     // map of ElementId to ScrollableArea if this is an issue for performance.
3711     for (ScrollableArea* scrollable_area : *scrollable_areas_) {
3712       if (id == scrollable_area->GetScrollElementId())
3713         return scrollable_area;
3714     }
3715   }
3716   return nullptr;
3717 }
3718 
ScrollRectToVisibleInRemoteParent(const PhysicalRect & rect_to_scroll,mojom::blink::ScrollIntoViewParamsPtr params)3719 void LocalFrameView::ScrollRectToVisibleInRemoteParent(
3720     const PhysicalRect& rect_to_scroll,
3721     mojom::blink::ScrollIntoViewParamsPtr params) {
3722   DCHECK(GetFrame().IsLocalRoot() && !GetFrame().IsMainFrame() &&
3723          safe_to_propagate_scroll_to_parent_);
3724   PhysicalRect new_rect = ConvertToRootFrame(rect_to_scroll);
3725   frame_->GetLocalFrameHostRemote().ScrollRectToVisibleInParentFrame(
3726       gfx::Rect(new_rect.X().ToInt(), new_rect.Y().ToInt(),
3727                 new_rect.Width().ToInt(), new_rect.Height().ToInt()),
3728       std::move(params));
3729 }
3730 
NotifyFrameRectsChangedIfNeeded()3731 void LocalFrameView::NotifyFrameRectsChangedIfNeeded() {
3732   if (root_layer_did_scroll_) {
3733     root_layer_did_scroll_ = false;
3734     PropagateFrameRects();
3735   }
3736 }
3737 
ViewportToFrame(const PhysicalOffset & point_in_viewport) const3738 PhysicalOffset LocalFrameView::ViewportToFrame(
3739     const PhysicalOffset& point_in_viewport) const {
3740   PhysicalOffset point_in_root_frame = PhysicalOffset::FromFloatPointRound(
3741       frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
3742           FloatPoint(point_in_viewport)));
3743   return ConvertFromRootFrame(point_in_root_frame);
3744 }
3745 
ViewportToFrame(const FloatPoint & point_in_viewport) const3746 FloatPoint LocalFrameView::ViewportToFrame(
3747     const FloatPoint& point_in_viewport) const {
3748   FloatPoint point_in_root_frame(
3749       frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
3750           point_in_viewport));
3751   return ConvertFromRootFrame(point_in_root_frame);
3752 }
3753 
ViewportToFrame(const IntRect & rect_in_viewport) const3754 IntRect LocalFrameView::ViewportToFrame(const IntRect& rect_in_viewport) const {
3755   IntRect rect_in_root_frame =
3756       frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
3757           rect_in_viewport);
3758   return ConvertFromRootFrame(rect_in_root_frame);
3759 }
3760 
ViewportToFrame(const IntPoint & point_in_viewport) const3761 IntPoint LocalFrameView::ViewportToFrame(
3762     const IntPoint& point_in_viewport) const {
3763   return RoundedIntPoint(ViewportToFrame(PhysicalOffset(point_in_viewport)));
3764 }
3765 
FrameToViewport(const IntRect & rect_in_frame) const3766 IntRect LocalFrameView::FrameToViewport(const IntRect& rect_in_frame) const {
3767   IntRect rect_in_root_frame = ConvertToRootFrame(rect_in_frame);
3768   return frame_->GetPage()->GetVisualViewport().RootFrameToViewport(
3769       rect_in_root_frame);
3770 }
3771 
FrameToViewport(const IntPoint & point_in_frame) const3772 IntPoint LocalFrameView::FrameToViewport(const IntPoint& point_in_frame) const {
3773   IntPoint point_in_root_frame = ConvertToRootFrame(point_in_frame);
3774   return frame_->GetPage()->GetVisualViewport().RootFrameToViewport(
3775       point_in_root_frame);
3776 }
3777 
FrameToScreen(const IntRect & rect) const3778 IntRect LocalFrameView::FrameToScreen(const IntRect& rect) const {
3779   if (auto* client = GetChromeClient())
3780     return client->ViewportToScreen(FrameToViewport(rect), this);
3781   return IntRect();
3782 }
3783 
SoonToBeRemovedUnscaledViewportToContents(const IntPoint & point_in_viewport) const3784 IntPoint LocalFrameView::SoonToBeRemovedUnscaledViewportToContents(
3785     const IntPoint& point_in_viewport) const {
3786   IntPoint point_in_root_frame = FlooredIntPoint(
3787       frame_->GetPage()->GetVisualViewport().ViewportCSSPixelsToRootFrame(
3788           FloatPoint(point_in_viewport)));
3789   return ConvertFromRootFrame(point_in_root_frame);
3790 }
3791 
Paint(GraphicsContext & context,const GlobalPaintFlags global_paint_flags,const CullRect & cull_rect,const IntSize & paint_offset) const3792 void LocalFrameView::Paint(GraphicsContext& context,
3793                            const GlobalPaintFlags global_paint_flags,
3794                            const CullRect& cull_rect,
3795                            const IntSize& paint_offset) const {
3796   // |paint_offset| is not used because paint properties of the contents will
3797   // ensure the correct location.
3798   PaintInternal(context, global_paint_flags, cull_rect);
3799 }
3800 
PaintInternal(GraphicsContext & context,const GlobalPaintFlags global_paint_flags,const CullRect & cull_rect) const3801 void LocalFrameView::PaintInternal(GraphicsContext& context,
3802                                    const GlobalPaintFlags global_paint_flags,
3803                                    const CullRect& cull_rect) const {
3804   FramePainter(*this).Paint(context, global_paint_flags, cull_rect);
3805 }
3806 
PaintOutsideOfLifecycleIsAllowed(GraphicsContext & context,const LocalFrameView & frame_view)3807 static bool PaintOutsideOfLifecycleIsAllowed(GraphicsContext& context,
3808                                              const LocalFrameView& frame_view) {
3809   // A paint outside of lifecycle should not conflict about paint controller
3810   // caching with the default painting executed during lifecycle update,
3811   // otherwise the caller should either use a transient paint controller or
3812   // explicitly skip cache.
3813   if (context.GetPaintController().IsSkippingCache())
3814     return true;
3815   // For CompositeAfterPaint, they always conflict because we always paint into
3816   // paint_controller_ during lifecycle update.
3817   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
3818     return false;
3819   // For pre-CompositeAfterPaint, they conflict if the local frame root has a
3820   // a root graphics layer.
3821   return !frame_view.GetFrame()
3822               .LocalFrameRoot()
3823               .View()
3824               ->GetLayoutView()
3825               ->Compositor()
3826               ->PaintRootGraphicsLayer();
3827 }
3828 
PaintOutsideOfLifecycle(GraphicsContext & context,const GlobalPaintFlags global_paint_flags,const CullRect & cull_rect)3829 void LocalFrameView::PaintOutsideOfLifecycle(
3830     GraphicsContext& context,
3831     const GlobalPaintFlags global_paint_flags,
3832     const CullRect& cull_rect) {
3833   DCHECK(PaintOutsideOfLifecycleIsAllowed(context, *this));
3834 
3835   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
3836     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint);
3837   });
3838 
3839   PaintInternal(context, global_paint_flags, cull_rect);
3840 
3841   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
3842     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
3843   });
3844 }
3845 
PaintContentsOutsideOfLifecycle(GraphicsContext & context,const GlobalPaintFlags global_paint_flags,const CullRect & cull_rect)3846 void LocalFrameView::PaintContentsOutsideOfLifecycle(
3847     GraphicsContext& context,
3848     const GlobalPaintFlags global_paint_flags,
3849     const CullRect& cull_rect) {
3850   DCHECK(PaintOutsideOfLifecycleIsAllowed(context, *this));
3851 
3852   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
3853     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint);
3854   });
3855 
3856   FramePainter(*this).PaintContents(context, global_paint_flags, cull_rect);
3857 
3858   ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
3859     frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
3860   });
3861 }
3862 
GetPaintRecord() const3863 sk_sp<PaintRecord> LocalFrameView::GetPaintRecord() const {
3864   DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
3865   DCHECK_EQ(DocumentLifecycle::kPaintClean, Lifecycle().GetState());
3866   DCHECK(frame_->IsLocalRoot());
3867   DCHECK(paint_controller_);
3868   return paint_controller_->GetPaintArtifact().GetPaintRecord(
3869       PropertyTreeState::Root());
3870 }
3871 
ConvertToRootFrame(const IntRect & local_rect) const3872 IntRect LocalFrameView::ConvertToRootFrame(const IntRect& local_rect) const {
3873   if (LocalFrameView* parent = ParentFrameView()) {
3874     IntRect parent_rect = ConvertToContainingEmbeddedContentView(local_rect);
3875     return parent->ConvertToRootFrame(parent_rect);
3876   }
3877   return local_rect;
3878 }
3879 
ConvertToRootFrame(const IntPoint & local_point) const3880 IntPoint LocalFrameView::ConvertToRootFrame(const IntPoint& local_point) const {
3881   return RoundedIntPoint(ConvertToRootFrame(PhysicalOffset(local_point)));
3882 }
3883 
ConvertToRootFrame(const PhysicalOffset & local_offset) const3884 PhysicalOffset LocalFrameView::ConvertToRootFrame(
3885     const PhysicalOffset& local_offset) const {
3886   if (LocalFrameView* parent = ParentFrameView()) {
3887     PhysicalOffset parent_offset =
3888         ConvertToContainingEmbeddedContentView(local_offset);
3889     return parent->ConvertToRootFrame(parent_offset);
3890   }
3891   return local_offset;
3892 }
3893 
ConvertToRootFrame(const FloatPoint & local_point) const3894 FloatPoint LocalFrameView::ConvertToRootFrame(
3895     const FloatPoint& local_point) const {
3896   if (LocalFrameView* parent = ParentFrameView()) {
3897     FloatPoint parent_point =
3898         ConvertToContainingEmbeddedContentView(local_point);
3899     return parent->ConvertToRootFrame(parent_point);
3900   }
3901   return local_point;
3902 }
3903 
ConvertToRootFrame(const PhysicalRect & local_rect) const3904 PhysicalRect LocalFrameView::ConvertToRootFrame(
3905     const PhysicalRect& local_rect) const {
3906   if (LocalFrameView* parent = ParentFrameView()) {
3907     PhysicalOffset parent_offset =
3908         ConvertToContainingEmbeddedContentView(local_rect.offset);
3909     PhysicalRect parent_rect(parent_offset, local_rect.size);
3910     return parent->ConvertToRootFrame(parent_rect);
3911   }
3912   return local_rect;
3913 }
3914 
ConvertFromRootFrame(const IntRect & rect_in_root_frame) const3915 IntRect LocalFrameView::ConvertFromRootFrame(
3916     const IntRect& rect_in_root_frame) const {
3917   if (LocalFrameView* parent = ParentFrameView()) {
3918     IntRect parent_rect = parent->ConvertFromRootFrame(rect_in_root_frame);
3919     return ConvertFromContainingEmbeddedContentView(parent_rect);
3920   }
3921   return rect_in_root_frame;
3922 }
3923 
ConvertFromRootFrame(const IntPoint & point_in_root_frame) const3924 IntPoint LocalFrameView::ConvertFromRootFrame(
3925     const IntPoint& point_in_root_frame) const {
3926   return RoundedIntPoint(
3927       ConvertFromRootFrame(PhysicalOffset(point_in_root_frame)));
3928 }
3929 
ConvertFromRootFrame(const PhysicalOffset & offset_in_root_frame) const3930 PhysicalOffset LocalFrameView::ConvertFromRootFrame(
3931     const PhysicalOffset& offset_in_root_frame) const {
3932   if (LocalFrameView* parent = ParentFrameView()) {
3933     PhysicalOffset parent_point =
3934         parent->ConvertFromRootFrame(offset_in_root_frame);
3935     return ConvertFromContainingEmbeddedContentView(parent_point);
3936   }
3937   return offset_in_root_frame;
3938 }
3939 
ConvertFromRootFrame(const FloatPoint & point_in_root_frame) const3940 FloatPoint LocalFrameView::ConvertFromRootFrame(
3941     const FloatPoint& point_in_root_frame) const {
3942   if (LocalFrameView* parent = ParentFrameView()) {
3943     FloatPoint parent_point = parent->ConvertFromRootFrame(point_in_root_frame);
3944     return ConvertFromContainingEmbeddedContentView(parent_point);
3945   }
3946   return point_in_root_frame;
3947 }
3948 
ParentVisibleChanged()3949 void LocalFrameView::ParentVisibleChanged() {
3950   // As parent visibility changes, we may need to recomposite this frame view
3951   // and potentially child frame views.
3952   SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
3953 
3954   if (!IsSelfVisible())
3955     return;
3956 
3957   bool visible = IsParentVisible();
3958   ForAllChildViewsAndPlugins(
3959       [visible](EmbeddedContentView& embedded_content_view) {
3960         embedded_content_view.SetParentVisible(visible);
3961       });
3962 }
3963 
SelfVisibleChanged()3964 void LocalFrameView::SelfVisibleChanged() {
3965   // FrameView visibility affects PLC::CanBeComposited, which in turn affects
3966   // compositing inputs.
3967   if (LayoutView* view = GetLayoutView())
3968     view->Layer()->SetNeedsCompositingInputsUpdate();
3969 }
3970 
Show()3971 void LocalFrameView::Show() {
3972   if (!IsSelfVisible()) {
3973     SetSelfVisible(true);
3974     if (GetScrollingCoordinator())
3975       GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
3976     SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
3977     if (IsParentVisible()) {
3978       ForAllChildViewsAndPlugins(
3979           [](EmbeddedContentView& embedded_content_view) {
3980             embedded_content_view.SetParentVisible(true);
3981           });
3982     }
3983   }
3984 }
3985 
Hide()3986 void LocalFrameView::Hide() {
3987   if (IsSelfVisible()) {
3988     if (IsParentVisible()) {
3989       ForAllChildViewsAndPlugins(
3990           [](EmbeddedContentView& embedded_content_view) {
3991             embedded_content_view.SetParentVisible(false);
3992           });
3993     }
3994     SetSelfVisible(false);
3995     if (GetScrollingCoordinator())
3996       GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
3997     SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
3998   }
3999 }
4000 
ViewportWidth() const4001 int LocalFrameView::ViewportWidth() const {
4002   int viewport_width = GetLayoutSize().Width();
4003   return AdjustForAbsoluteZoom::AdjustInt(viewport_width, GetLayoutView());
4004 }
4005 
GetScrollableArea()4006 ScrollableArea* LocalFrameView::GetScrollableArea() {
4007   if (viewport_scrollable_area_)
4008     return viewport_scrollable_area_.Get();
4009 
4010   return LayoutViewport();
4011 }
4012 
LayoutViewport() const4013 PaintLayerScrollableArea* LocalFrameView::LayoutViewport() const {
4014   auto* layout_view = GetLayoutView();
4015   return layout_view ? layout_view->GetScrollableArea() : nullptr;
4016 }
4017 
GetRootFrameViewport()4018 RootFrameViewport* LocalFrameView::GetRootFrameViewport() {
4019   return viewport_scrollable_area_.Get();
4020 }
4021 
CollectAnnotatedRegions(LayoutObject & layout_object,Vector<AnnotatedRegionValue> & regions) const4022 void LocalFrameView::CollectAnnotatedRegions(
4023     LayoutObject& layout_object,
4024     Vector<AnnotatedRegionValue>& regions) const {
4025   // LayoutTexts don't have their own style, they just use their parent's style,
4026   // so we don't want to include them.
4027   if (layout_object.IsText())
4028     return;
4029 
4030   layout_object.AddAnnotatedRegions(regions);
4031   for (LayoutObject* curr = layout_object.SlowFirstChild(); curr;
4032        curr = curr->NextSibling())
4033     CollectAnnotatedRegions(*curr, regions);
4034 }
4035 
UpdateViewportIntersectionsForSubtree(unsigned parent_flags)4036 bool LocalFrameView::UpdateViewportIntersectionsForSubtree(
4037     unsigned parent_flags) {
4038   // TODO(dcheng): Since LocalFrameView tree updates are deferred, FrameViews
4039   // might still be in the LocalFrameView hierarchy even though the associated
4040   // Document is already detached. Investigate if this check and a similar check
4041   // in lifecycle updates are still needed when there are no more deferred
4042   // LocalFrameView updates: https://crbug.com/561683
4043   if (!GetFrame().GetDocument()->IsActive())
4044     return false;
4045 
4046   unsigned flags = GetIntersectionObservationFlags(parent_flags);
4047   bool needs_occlusion_tracking = false;
4048 
4049   if (!NeedsLayout()) {
4050     // Notify javascript IntersectionObservers
4051     if (IntersectionObserverController* controller =
4052             GetFrame().GetDocument()->GetIntersectionObserverController()) {
4053       needs_occlusion_tracking |= controller->ComputeIntersections(flags);
4054     }
4055     intersection_observation_state_ = kNotNeeded;
4056   }
4057 
4058   if (UpdateViewportIntersection(flags, needs_occlusion_tracking))
4059     flags |= IntersectionObservation::kCanSkipStickyFrameTracking;
4060 
4061   for (Frame* child = frame_->Tree().FirstChild(); child;
4062        child = child->Tree().NextSibling()) {
4063     needs_occlusion_tracking |=
4064         child->View()->UpdateViewportIntersectionsForSubtree(flags);
4065   }
4066 
4067   for (PortalContents* portal :
4068        DocumentPortals::From(*frame_->GetDocument()).GetPortals()) {
4069     if (Frame* frame = portal->GetFrame()) {
4070       needs_occlusion_tracking |=
4071           frame->View()->UpdateViewportIntersectionsForSubtree(flags);
4072     }
4073   }
4074 
4075   return needs_occlusion_tracking;
4076 }
4077 
DeliverSynchronousIntersectionObservations()4078 void LocalFrameView::DeliverSynchronousIntersectionObservations() {
4079   if (IntersectionObserverController* controller =
4080           GetFrame().GetDocument()->GetIntersectionObserverController()) {
4081     controller->DeliverNotifications(
4082         IntersectionObserver::kDeliverDuringPostLifecycleSteps);
4083   }
4084   ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
4085     frame_view.DeliverSynchronousIntersectionObservations();
4086   });
4087 }
4088 
CrossOriginToMainFrameChanged()4089 void LocalFrameView::CrossOriginToMainFrameChanged() {
4090   // If any of these conditions hold, then a change in cross-origin status does
4091   // not affect throttling.
4092   if (lifecycle_updates_throttled_ || IsSubtreeThrottled() ||
4093       !IsHiddenForThrottling()) {
4094     return;
4095   }
4096   RenderThrottlingStatusChanged();
4097   // We need to invalidate unconditionally, so if it didn't happen during
4098   // RenderThrottlingStatusChanged, do it now.
4099   if (CanThrottleRendering())
4100     InvalidateForThrottlingChange();
4101   // Immediately propagate changes to children.
4102   UpdateRenderThrottlingStatus(IsHiddenForThrottling(), IsSubtreeThrottled(),
4103                                true);
4104 }
4105 
CrossOriginToParentFrameChanged()4106 void LocalFrameView::CrossOriginToParentFrameChanged() {
4107   if (auto* owner = frame_->DeprecatedLocalOwner())
4108     owner->FrameCrossOriginToParentFrameChanged();
4109 }
4110 
VisibilityForThrottlingChanged()4111 void LocalFrameView::VisibilityForThrottlingChanged() {
4112   if (FrameScheduler* frame_scheduler = frame_->GetFrameScheduler()) {
4113     // TODO(szager): Per crbug.com/994443, maybe this should be:
4114     //   SetFrameVisible(IsHiddenForThrottling() || IsSubtreeThrottled());
4115     frame_scheduler->SetFrameVisible(!IsHiddenForThrottling());
4116   }
4117 }
4118 
VisibilityChanged(blink::mojom::FrameVisibility visibility)4119 void LocalFrameView::VisibilityChanged(
4120     blink::mojom::FrameVisibility visibility) {
4121   frame_->GetLocalFrameHostRemote().VisibilityChanged(visibility);
4122 }
4123 
RenderThrottlingStatusChanged()4124 void LocalFrameView::RenderThrottlingStatusChanged() {
4125   TRACE_EVENT0("blink", "LocalFrameView::RenderThrottlingStatusChanged");
4126   DCHECK(!IsInPerformLayout());
4127   DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->InStyleRecalc());
4128 
4129   // We may record more/less foreign layers under the frame.
4130   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
4131     SetForeignLayerListNeedsUpdate();
4132 
4133   if (!CanThrottleRendering())
4134     InvalidateForThrottlingChange();
4135 
4136   // If we have become unthrottled, this is essentially a no-op since we're
4137   // going to paint anyway. If we have become throttled, then this will force
4138   // one lifecycle update to clear the painted output.
4139   if (GetFrame().IsLocalRoot())
4140     need_paint_phase_after_throttling_ = true;
4141 
4142 #if DCHECK_IS_ON()
4143   // Make sure we never have an unthrottled frame inside a throttled one.
4144   LocalFrameView* parent = ParentFrameView();
4145   while (parent) {
4146     DCHECK(CanThrottleRendering() || !parent->CanThrottleRendering());
4147     parent = parent->ParentFrameView();
4148   }
4149 #endif
4150 }
4151 
InvalidateForThrottlingChange()4152 void LocalFrameView::InvalidateForThrottlingChange() {
4153   // ScrollingCoordinator needs to update according to the new throttling
4154   // status.
4155   if (ScrollingCoordinator* coordinator = this->GetScrollingCoordinator())
4156     coordinator->NotifyGeometryChanged(this);
4157   // Start ticking animation frames again if necessary.
4158   if (GetPage())
4159     GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
4160   // Force a full repaint of this frame to ensure we are not left with a
4161   // partially painted version of this frame's contents if we skipped
4162   // painting them while the frame was throttled.
4163   LayoutView* layout_view = GetLayoutView();
4164   if (layout_view) {
4165     layout_view->InvalidatePaintForViewAndCompositedLayers();
4166     // Also need to update all paint properties that might be skipped while
4167     // the frame was throttled.
4168     layout_view->AddSubtreePaintPropertyUpdateReason(
4169         SubtreePaintPropertyUpdateReason::kPreviouslySkipped);
4170   }
4171 }
4172 
SetNeedsForcedCompositingUpdate()4173 void LocalFrameView::SetNeedsForcedCompositingUpdate() {
4174   needs_forced_compositing_update_ = true;
4175   if (LocalFrameView* parent = ParentFrameView())
4176     parent->SetNeedsForcedCompositingUpdate();
4177 }
4178 
SetIntersectionObservationState(IntersectionObservationState state)4179 void LocalFrameView::SetIntersectionObservationState(
4180     IntersectionObservationState state) {
4181   if (intersection_observation_state_ >= state)
4182     return;
4183   intersection_observation_state_ = state;
4184 }
4185 
SetPaintArtifactCompositorNeedsUpdate()4186 void LocalFrameView::SetPaintArtifactCompositorNeedsUpdate() {
4187   LocalFrameView* root = GetFrame().LocalFrameRoot().View();
4188   if (root && root->paint_artifact_compositor_)
4189     root->paint_artifact_compositor_->SetNeedsUpdate();
4190 }
4191 
SetForeignLayerListNeedsUpdate()4192 void LocalFrameView::SetForeignLayerListNeedsUpdate() {
4193   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
4194   DCHECK_NE(Lifecycle().GetState(), DocumentLifecycle::kInPaint);
4195 
4196   if (LocalFrameView* root = GetFrame().LocalFrameRoot().View()) {
4197     // We will re-collect foreign layers in PushPaintArtifactsToCompositor().
4198     root->paint_controller_ = nullptr;
4199     if (root->paint_artifact_compositor_)
4200       root->paint_artifact_compositor_->SetNeedsUpdate();
4201   }
4202 }
4203 
GetPaintArtifactCompositor() const4204 PaintArtifactCompositor* LocalFrameView::GetPaintArtifactCompositor() const {
4205   LocalFrameView* root = GetFrame().LocalFrameRoot().View();
4206   return root ? root->paint_artifact_compositor_.get() : nullptr;
4207 }
4208 
GetIntersectionObservationFlags(unsigned parent_flags) const4209 unsigned LocalFrameView::GetIntersectionObservationFlags(
4210     unsigned parent_flags) const {
4211   unsigned flags = 0;
4212 
4213   const LocalFrame& target_frame = GetFrame();
4214   const Frame& root_frame = target_frame.Tree().Top();
4215   if (&root_frame == &target_frame ||
4216       target_frame.GetSecurityContext()->GetSecurityOrigin()->CanAccess(
4217           root_frame.GetSecurityContext()->GetSecurityOrigin())) {
4218     flags |= IntersectionObservation::kReportImplicitRootBounds;
4219   }
4220 
4221   // Observers with explicit roots only need to be checked on the same frame,
4222   // since in this case target and root must be in the same document.
4223   if (intersection_observation_state_ != kNotNeeded) {
4224     flags |= (IntersectionObservation::kExplicitRootObserversNeedUpdate |
4225               IntersectionObservation::kImplicitRootObserversNeedUpdate);
4226   }
4227 
4228   // For observers with implicit roots, we need to check state on the whole
4229   // local frame tree, as passed down from the parent.
4230   flags |= (parent_flags &
4231             IntersectionObservation::kImplicitRootObserversNeedUpdate);
4232 
4233   // The kIgnoreDelay parameter is used to force computation in an OOPIF which
4234   // is hidden in the parent document, thus not running lifecycle updates. It
4235   // applies to the entire frame tree.
4236   flags |= (parent_flags & IntersectionObservation::kIgnoreDelay);
4237 
4238   flags |=
4239       (parent_flags & IntersectionObservation::kCanSkipStickyFrameTracking);
4240 
4241   return flags;
4242 }
4243 
ShouldThrottleRendering() const4244 bool LocalFrameView::ShouldThrottleRendering() const {
4245   bool throttled_for_global_reasons = CanThrottleRendering() &&
4246                                       frame_->GetDocument() &&
4247                                       Lifecycle().ThrottlingAllowed();
4248   if (!throttled_for_global_reasons || needs_forced_compositing_update_ ||
4249       need_paint_phase_after_throttling_) {
4250     return false;
4251   }
4252 
4253   if (intersection_observation_state_ == kRequired) {
4254     auto* local_frame_root_view = GetFrame().LocalFrameRoot().View();
4255     // When doing a lifecycle update required by intersection observer, we can
4256     // throttle lifecycle states after layout. Outside of lifecycle updates,
4257     // the frame should be considered throttled because it is not fully updating
4258     // the lifecycle.
4259     return !local_frame_root_view->in_lifecycle_update_ ||
4260            local_frame_root_view->past_layout_lifecycle_update_;
4261   }
4262 
4263   return true;
4264 }
4265 
CanThrottleRendering() const4266 bool LocalFrameView::CanThrottleRendering() const {
4267   if (lifecycle_updates_throttled_)
4268     return true;
4269   if (IsSubtreeThrottled())
4270     return true;
4271   // We only throttle hidden cross-origin frames. This is to avoid a situation
4272   // where an ancestor frame directly depends on the pipeline timing of a
4273   // descendant and breaks as a result of throttling. The rationale is that
4274   // cross-origin frames must already communicate with asynchronous messages,
4275   // so they should be able to tolerate some delay in receiving replies from a
4276   // throttled peer.
4277   return IsHiddenForThrottling() && frame_->IsCrossOriginToMainFrame();
4278 }
4279 
UpdateRenderThrottlingStatus(bool hidden_for_throttling,bool subtree_throttled,bool recurse)4280 void LocalFrameView::UpdateRenderThrottlingStatus(bool hidden_for_throttling,
4281                                                   bool subtree_throttled,
4282                                                   bool recurse) {
4283   bool was_throttled = CanThrottleRendering();
4284   FrameView::UpdateRenderThrottlingStatus(hidden_for_throttling,
4285                                           subtree_throttled, recurse);
4286   if (was_throttled != CanThrottleRendering())
4287     RenderThrottlingStatusChanged();
4288 }
4289 
BeginLifecycleUpdates()4290 void LocalFrameView::BeginLifecycleUpdates() {
4291   // Avoid pumping frames for the initially empty document.
4292   // TODO(schenney): This seems pointless because main frame updates do occur
4293   // for pages like about:blank, at least according to log messages.
4294   if (!GetFrame().Loader().StateMachine()->CommittedFirstRealDocumentLoad())
4295     return;
4296   lifecycle_updates_throttled_ = false;
4297   if (auto* owner = GetLayoutEmbeddedContent())
4298     owner->SetShouldCheckForPaintInvalidation();
4299 
4300   LayoutView* layout_view = GetLayoutView();
4301   bool layout_view_is_empty = layout_view && !layout_view->FirstChild();
4302   if (layout_view_is_empty && !DidFirstLayout() && !NeedsLayout()) {
4303     // Make sure a display:none iframe gets an initial layout pass.
4304     layout_view->SetNeedsLayout(layout_invalidation_reason::kAddedToLayout,
4305                                 kMarkOnlyThis);
4306   }
4307 
4308   ScheduleAnimation();
4309   SetIntersectionObservationState(kRequired);
4310 
4311   // Non-main-frame lifecycle and commit deferral are controlled by their
4312   // main frame.
4313   if (!GetFrame().IsMainFrame())
4314     return;
4315 
4316   Document* document = GetFrame().GetDocument();
4317   ChromeClient& chrome_client = GetFrame().GetPage()->GetChromeClient();
4318 
4319   // Determine if we want to defer commits to the compositor once lifecycle
4320   // updates start. Doing so allows us to update the page lifecycle but not
4321   // present the results to screen until we see first contentful paint is
4322   // available or until a timer expires.
4323   // This is enabled only if kAvoidFlashBetweenNavigation is enabled, and
4324   // the document loading is regular HTML served over HTTP/HTTPs.
4325   // And only defer commits once. This method gets called multiple times,
4326   // and we do not want to defer a second time if we have already done
4327   // so once and resumed commits already.
4328   if (document &&
4329       base::FeatureList::IsEnabled(blink::features::kPaintHolding) &&
4330       document->DeferredCompositorCommitIsAllowed() &&
4331       !have_deferred_commits_) {
4332     chrome_client.StartDeferringCommits(GetFrame(),
4333                                         GetCommitDelayForPaintHolding());
4334     have_deferred_commits_ = true;
4335   }
4336 
4337   chrome_client.BeginLifecycleUpdates(GetFrame());
4338 }
4339 
SetInitialViewportSize(const IntSize & viewport_size)4340 void LocalFrameView::SetInitialViewportSize(const IntSize& viewport_size) {
4341   if (viewport_size == initial_viewport_size_)
4342     return;
4343 
4344   initial_viewport_size_ = viewport_size;
4345   if (Document* document = frame_->GetDocument())
4346     document->GetStyleEngine().InitialViewportChanged();
4347 }
4348 
InitialViewportWidth() const4349 int LocalFrameView::InitialViewportWidth() const {
4350   DCHECK(frame_->IsMainFrame());
4351   return initial_viewport_size_.Width();
4352 }
4353 
InitialViewportHeight() const4354 int LocalFrameView::InitialViewportHeight() const {
4355   DCHECK(frame_->IsMainFrame());
4356   return initial_viewport_size_.Height();
4357 }
4358 
HasVisibleSlowRepaintViewportConstrainedObjects() const4359 bool LocalFrameView::HasVisibleSlowRepaintViewportConstrainedObjects() const {
4360   if (!ViewportConstrainedObjects())
4361     return false;
4362   for (const LayoutObject* layout_object : *ViewportConstrainedObjects()) {
4363     DCHECK(layout_object->IsBoxModelObject() && layout_object->HasLayer());
4364     DCHECK(layout_object->StyleRef().GetPosition() == EPosition::kFixed ||
4365            layout_object->StyleRef().GetPosition() == EPosition::kSticky);
4366     if (ToLayoutBoxModelObject(layout_object)->IsSlowRepaintConstrainedObject())
4367       return true;
4368   }
4369   return false;
4370 }
4371 
MainThreadScrollingReasonsPerFrame() const4372 MainThreadScrollingReasons LocalFrameView::MainThreadScrollingReasonsPerFrame()
4373     const {
4374   MainThreadScrollingReasons reasons =
4375       static_cast<MainThreadScrollingReasons>(0);
4376 
4377   if (ShouldThrottleRendering())
4378     return reasons;
4379 
4380   if (RequiresMainThreadScrollingForBackgroundAttachmentFixed()) {
4381     reasons |=
4382         cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
4383   }
4384 
4385   // Force main-thread scrolling if the frame has uncomposited position: fixed
4386   // elements.  Note: we care about this not only for input-scrollable frames
4387   // but also for overflow: hidden frames, because script can run composited
4388   // smooth-scroll animations.  For this reason, we use HasOverflow instead of
4389   // ScrollsOverflow (which is false for overflow: hidden).
4390   if (LayoutViewport()->HasOverflow() &&
4391       GetLayoutView()->StyleRef().VisibleToHitTesting() &&
4392       HasVisibleSlowRepaintViewportConstrainedObjects()) {
4393     reasons |=
4394         cc::MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects;
4395   }
4396   return reasons;
4397 }
4398 
GetMainThreadScrollingReasons() const4399 MainThreadScrollingReasons LocalFrameView::GetMainThreadScrollingReasons()
4400     const {
4401   MainThreadScrollingReasons reasons =
4402       static_cast<MainThreadScrollingReasons>(0);
4403 
4404   if (!GetPage()->GetSettings().GetThreadedScrollingEnabled())
4405     reasons |= cc::MainThreadScrollingReason::kThreadedScrollingDisabled;
4406 
4407   if (!GetPage()->MainFrame()->IsLocalFrame())
4408     return reasons;
4409 
4410   // TODO(alexmos,kenrb): For OOPIF, local roots that are different from
4411   // the main frame can't be used in the calculation, since they use
4412   // different compositors with unrelated state, which breaks some of the
4413   // calculations below.
4414   if (&frame_->LocalFrameRoot() != GetPage()->MainFrame())
4415     return reasons;
4416 
4417   // Walk the tree to the root. Use the gathered reasons to determine
4418   // whether the target frame should be scrolled on main thread regardless
4419   // other subframes on the same page.
4420   for (Frame* frame = frame_; frame; frame = frame->Tree().Parent()) {
4421     auto* local_frame = DynamicTo<LocalFrame>(frame);
4422     if (!local_frame)
4423       continue;
4424     reasons |= local_frame->View()->MainThreadScrollingReasonsPerFrame();
4425   }
4426 
4427   DCHECK(
4428       !cc::MainThreadScrollingReason::HasNonCompositedScrollReasons(reasons));
4429   return reasons;
4430 }
4431 
MainThreadScrollingReasonsAsText()4432 String LocalFrameView::MainThreadScrollingReasonsAsText() {
4433   MainThreadScrollingReasons reasons = 0;
4434   DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean);
4435   const auto* properties = GetLayoutView()->FirstFragment().PaintProperties();
4436   if (properties && properties->Scroll())
4437     reasons = properties->Scroll()->GetMainThreadScrollingReasons();
4438   return String(cc::MainThreadScrollingReason::AsText(reasons).c_str());
4439 }
4440 
MapToVisualRectInRemoteRootFrame(PhysicalRect & rect,bool apply_overflow_clip)4441 bool LocalFrameView::MapToVisualRectInRemoteRootFrame(
4442     PhysicalRect& rect,
4443     bool apply_overflow_clip) {
4444   DCHECK(frame_->IsLocalRoot());
4445   // This is the top-level frame, so no mapping necessary.
4446   if (frame_->IsMainFrame())
4447     return true;
4448   bool result = rect.InclusiveIntersect(PhysicalRect(
4449       apply_overflow_clip ? frame_->RemoteViewportIntersection()
4450                           : frame_->RemoteMainFrameDocumentIntersection()));
4451   if (result)
4452     rect.Move(PhysicalOffset(GetFrame().RemoteViewportOffset()));
4453   return result;
4454 }
4455 
MapLocalToRemoteRootFrame(TransformState & transform_state)4456 void LocalFrameView::MapLocalToRemoteRootFrame(
4457     TransformState& transform_state) {
4458   DCHECK(frame_->IsLocalRoot());
4459   // This is the top-level frame, so no mapping necessary.
4460   if (frame_->IsMainFrame())
4461     return;
4462   transform_state.Move(PhysicalOffset(frame_->RemoteViewportOffset()));
4463 }
4464 
CaretWidth() const4465 LayoutUnit LocalFrameView::CaretWidth() const {
4466   return LayoutUnit(std::max<float>(
4467       1.0f, GetChromeClient()->WindowToViewportScalar(&GetFrame(), 1.0f)));
4468 }
4469 
EnsureUkmAggregator()4470 LocalFrameUkmAggregator& LocalFrameView::EnsureUkmAggregator() {
4471   if (!ukm_aggregator_) {
4472     ukm_aggregator_ = base::MakeRefCounted<LocalFrameUkmAggregator>(
4473         frame_->GetDocument()->UkmSourceID(),
4474         frame_->GetDocument()->UkmRecorder());
4475   }
4476   return *ukm_aggregator_;
4477 }
4478 
OnFirstContentfulPaint()4479 void LocalFrameView::OnFirstContentfulPaint() {
4480   GetPage()->GetChromeClient().StopDeferringCommits(
4481       *frame_, cc::PaintHoldingCommitTrigger::kFirstContentfulPaint);
4482   EnsureUkmAggregator().DidReachFirstContentfulPaint(frame_->IsMainFrame());
4483 }
4484 
RegisterForLifecycleNotifications(LifecycleNotificationObserver * observer)4485 void LocalFrameView::RegisterForLifecycleNotifications(
4486     LifecycleNotificationObserver* observer) {
4487   lifecycle_observers_.insert(observer);
4488 }
4489 
UnregisterFromLifecycleNotifications(LifecycleNotificationObserver * observer)4490 void LocalFrameView::UnregisterFromLifecycleNotifications(
4491     LifecycleNotificationObserver* observer) {
4492   lifecycle_observers_.erase(observer);
4493 }
4494 
EnqueueStartOfLifecycleTask(base::OnceClosure closure)4495 void LocalFrameView::EnqueueStartOfLifecycleTask(base::OnceClosure closure) {
4496   start_of_lifecycle_tasks_.push_back(std::move(closure));
4497 }
4498 
4499 #if DCHECK_IS_ON()
4500 LocalFrameView::DisallowLayoutInvalidationScope::
DisallowLayoutInvalidationScope(LocalFrameView * view)4501     DisallowLayoutInvalidationScope(LocalFrameView* view)
4502     : local_frame_view_(view) {
4503   local_frame_view_->allows_layout_invalidation_after_layout_clean_ = false;
4504   local_frame_view_->ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
4505     if (!frame_view.ShouldThrottleRendering())
4506       frame_view.CheckDoesNotNeedLayout();
4507     frame_view.allows_layout_invalidation_after_layout_clean_ = false;
4508   });
4509 }
4510 
4511 LocalFrameView::DisallowLayoutInvalidationScope::
~DisallowLayoutInvalidationScope()4512     ~DisallowLayoutInvalidationScope() {
4513   local_frame_view_->allows_layout_invalidation_after_layout_clean_ = true;
4514   local_frame_view_->ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
4515     if (!frame_view.ShouldThrottleRendering())
4516       frame_view.CheckDoesNotNeedLayout();
4517     frame_view.allows_layout_invalidation_after_layout_clean_ = true;
4518   });
4519 }
4520 
4521 #endif
4522 
UpdateLayerDebugInfoEnabled()4523 void LocalFrameView::UpdateLayerDebugInfoEnabled() {
4524   DCHECK(frame_->IsLocalRoot());
4525 #if DCHECK_IS_ON()
4526   DCHECK(layer_debug_info_enabled_);
4527 #else
4528   bool should_enable =
4529       cc::frame_viewer_instrumentation::IsTracingLayerTreeSnapshots() ||
4530       WebTestSupport::IsRunningWebTest() ||
4531       CoreProbeSink::HasAgentsGlobal(CoreProbeSink::kInspectorLayerTreeAgent);
4532   if (should_enable != layer_debug_info_enabled_) {
4533     layer_debug_info_enabled_ = should_enable;
4534     SetPaintArtifactCompositorNeedsUpdate();
4535   }
4536 #endif
4537 }
4538 
4539 OverlayInterstitialAdDetector&
EnsureOverlayInterstitialAdDetector()4540 LocalFrameView::EnsureOverlayInterstitialAdDetector() {
4541   if (!overlay_interstitial_ad_detector_) {
4542     overlay_interstitial_ad_detector_ =
4543         std::make_unique<OverlayInterstitialAdDetector>();
4544   }
4545   return *overlay_interstitial_ad_detector_.get();
4546 }
4547 
4548 }  // namespace blink
4549