[M120 Migration] Fix show IME
[platform/framework/web/chromium-efl.git] / third_party / blink / renderer / core / frame / web_frame_widget_impl.cc
1 /*
2  * Copyright (C) 2014 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
32
33 #include <memory>
34 #include <utility>
35
36 #include "base/auto_reset.h"
37 #include "base/debug/crash_logging.h"
38 #include "base/debug/dump_without_crashing.h"
39 #include "base/functional/callback_helpers.h"
40 #include "base/functional/function_ref.h"
41 #include "base/metrics/histogram_macros.h"
42 #include "base/numerics/safe_conversions.h"
43 #include "base/task/single_thread_task_runner.h"
44 #include "base/time/time.h"
45 #include "build/build_config.h"
46 #include "cc/animation/animation_host.h"
47 #include "cc/base/features.h"
48 #include "cc/trees/compositor_commit_data.h"
49 #include "cc/trees/layer_tree_host.h"
50 #include "cc/trees/swap_promise.h"
51 #include "cc/trees/ukm_manager.h"
52 #include "third_party/blink/public/common/features.h"
53 #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
54 #include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
55 #include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
56 #include "third_party/blink/public/platform/platform.h"
57 #include "third_party/blink/public/web/web_autofill_client.h"
58 #include "third_party/blink/public/web/web_local_frame.h"
59 #include "third_party/blink/public/web/web_local_frame_client.h"
60 #include "third_party/blink/public/web/web_non_composited_widget_client.h"
61 #include "third_party/blink/public/web/web_performance_metrics_for_reporting.h"
62 #include "third_party/blink/public/web/web_plugin.h"
63 #include "third_party/blink/public/web/web_settings.h"
64 #include "third_party/blink/public/web/web_view_client.h"
65 #include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
66 #include "third_party/blink/renderer/core/core_initializer.h"
67 #include "third_party/blink/renderer/core/dom/element.h"
68 #include "third_party/blink/renderer/core/dom/focus_params.h"
69 #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
70 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
71 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
72 #include "third_party/blink/renderer/core/editing/frame_selection.h"
73 #include "third_party/blink/renderer/core/editing/ime/edit_context.h"
74 #include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
75 #include "third_party/blink/renderer/core/editing/ime/stylus_writing_gesture.h"
76 #include "third_party/blink/renderer/core/editing/selection_template.h"
77 #include "third_party/blink/renderer/core/events/current_input_event.h"
78 #include "third_party/blink/renderer/core/events/pointer_event_factory.h"
79 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
80 #include "third_party/blink/renderer/core/events/wheel_event.h"
81 #include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
82 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
83 #include "third_party/blink/renderer/core/exported/web_settings_impl.h"
84 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
85 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
86 #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
87 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
88 #include "third_party/blink/renderer/core/frame/remote_frame_client.h"
89 #include "third_party/blink/renderer/core/frame/screen.h"
90 #include "third_party/blink/renderer/core/frame/screen_metrics_emulator.h"
91 #include "third_party/blink/renderer/core/frame/settings.h"
92 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
93 #include "third_party/blink/renderer/core/frame/web_feature.h"
94 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
95 #include "third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h"
96 #include "third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h"
97 #include "third_party/blink/renderer/core/html/forms/text_control_element.h"
98 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
99 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
100 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
101 #include "third_party/blink/renderer/core/html/portal/portal_contents.h"
102 #include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
103 #include "third_party/blink/renderer/core/input/event_handler.h"
104 #include "third_party/blink/renderer/core/input/touch_action_util.h"
105 #include "third_party/blink/renderer/core/layout/hit_test_location.h"
106 #include "third_party/blink/renderer/core/layout/hit_test_request.h"
107 #include "third_party/blink/renderer/core/layout/layout_box.h"
108 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
109 #include "third_party/blink/renderer/core/layout/layout_object.h"
110 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
111 #include "third_party/blink/renderer/core/layout/layout_text.h"
112 #include "third_party/blink/renderer/core/loader/document_loader.h"
113 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
114 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
115 #include "third_party/blink/renderer/core/page/drag_actions.h"
116 #include "third_party/blink/renderer/core/page/drag_data.h"
117 #include "third_party/blink/renderer/core/page/focus_controller.h"
118 #include "third_party/blink/renderer/core/page/link_highlight.h"
119 #include "third_party/blink/renderer/core/page/page.h"
120 #include "third_party/blink/renderer/core/page/page_animator.h"
121 #include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
122 #include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
123 #include "third_party/blink/renderer/core/page/validation_message_client.h"
124 #include "third_party/blink/renderer/core/page/viewport_description.h"
125 #include "third_party/blink/renderer/core/paint/timing/first_meaningful_paint_detector.h"
126 #include "third_party/blink/renderer/core/paint/timing/paint_timing_detector.h"
127 #include "third_party/blink/renderer/core/probe/core_probes.h"
128 #include "third_party/blink/renderer/core/scroll/scroll_into_view_util.h"
129 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
130 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
131 #include "third_party/blink/renderer/core/timing/window_performance.h"
132 #include "third_party/blink/renderer/core/view_transition/view_transition.h"
133 #include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
134 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
135 #include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
136 #include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h"
137 #include "third_party/blink/renderer/platform/heap/cross_thread_handle.h"
138 #include "third_party/blink/renderer/platform/heap/persistent.h"
139 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
140 #include "third_party/blink/renderer/platform/keyboard_codes.h"
141 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
142 #include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h"
143 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
144 #include "third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h"
145 #include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
146 #include "third_party/blink/renderer/platform/widget/widget_base.h"
147 #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
148 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
149 #include "third_party/blink/renderer/platform/wtf/functional.h"
150 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
151 #include "ui/base/ui_base_types.h"
152 #include "ui/gfx/geometry/point_conversions.h"
153
154 #if BUILDFLAG(IS_MAC)
155 #include "third_party/blink/renderer/core/editing/substring_util.h"
156 #include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
157 #include "ui/base/mojom/attributed_string.mojom-blink.h"
158 #include "ui/gfx/geometry/point.h"
159 #endif
160
161 #if BUILDFLAG(IS_EFL)
162 #include "skia/ext/image_operations.h"
163 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
164 #include "third_party/blink/renderer/core/input_type_names.h"
165 #endif
166
167 namespace WTF {
168
169 template <>
170 struct CrossThreadCopier<blink::WebFrameWidgetImpl::PromiseCallbacks>
171     : public CrossThreadCopierByValuePassThrough<
172           blink::WebFrameWidgetImpl::PromiseCallbacks> {
173   STATIC_ONLY(CrossThreadCopier);
174 };
175
176 }  // namespace WTF
177
178 namespace blink {
179
180 namespace {
181
182 using ::ui::mojom::blink::DragOperation;
183
184 void ForEachLocalFrameControlledByWidget(
185     LocalFrame* frame,
186     base::FunctionRef<void(WebLocalFrameImpl*)> callback) {
187   callback(WebLocalFrameImpl::FromFrame(frame));
188   for (Frame* child = frame->FirstChild(); child;
189        child = child->NextSibling()) {
190     if (auto* local_child = DynamicTo<LocalFrame>(child)) {
191       ForEachLocalFrameControlledByWidget(local_child, callback);
192     }
193   }
194 }
195
196 // Iterate the remote children that will be controlled by the widget. Skip over
197 // any RemoteFrames have have another LocalFrame root as their parent.
198 void ForEachRemoteFrameChildrenControlledByWidget(
199     Frame* frame,
200     base::FunctionRef<void(RemoteFrame*)> callback) {
201   for (Frame* child = frame->Tree().FirstChild(); child;
202        child = child->Tree().NextSibling()) {
203     if (auto* remote_frame = DynamicTo<RemoteFrame>(child)) {
204       callback(remote_frame);
205       ForEachRemoteFrameChildrenControlledByWidget(remote_frame, callback);
206     } else if (auto* local_frame = DynamicTo<LocalFrame>(child)) {
207       // If iteration arrives at a local root then don't descend as it will be
208       // controlled by another widget.
209       if (!local_frame->IsLocalRoot()) {
210         ForEachRemoteFrameChildrenControlledByWidget(local_frame, callback);
211       }
212     }
213   }
214
215   if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
216     if (Document* document = local_frame->GetDocument()) {
217       // Iterate on any portals owned by a local frame.
218       if (auto* portals = DocumentPortals::Get(*document)) {
219         for (PortalContents* portal : portals->GetPortals()) {
220           if (RemoteFrame* remote_frame = portal->GetFrame())
221             callback(remote_frame);
222         }
223       }
224       // Iterate on any fenced frames owned by a local frame.
225       if (auto* fenced_frames = DocumentFencedFrames::Get(*document)) {
226         for (HTMLFencedFrameElement* fenced_frame :
227              fenced_frames->GetFencedFrames()) {
228           callback(To<RemoteFrame>(fenced_frame->ContentFrame()));
229         }
230       }
231     }
232   }
233 }
234
235 viz::FrameSinkId GetRemoteFrameSinkId(const HitTestResult& result) {
236   Node* node = result.InnerNode();
237   auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node);
238   if (!frame_owner || !frame_owner->ContentFrame() ||
239       !frame_owner->ContentFrame()->IsRemoteFrame())
240     return viz::FrameSinkId();
241
242   RemoteFrame* remote_frame = To<RemoteFrame>(frame_owner->ContentFrame());
243   if (remote_frame->IsIgnoredForHitTest())
244     return viz::FrameSinkId();
245   LayoutObject* object = node->GetLayoutObject();
246   DCHECK(object);
247   if (!object->IsBox())
248     return viz::FrameSinkId();
249
250   PhysicalOffset local_point(ToRoundedPoint(result.LocalPoint()));
251   if (!To<LayoutBox>(object)->ComputedCSSContentBoxRect().Contains(local_point))
252     return viz::FrameSinkId();
253
254   return remote_frame->GetFrameSinkId();
255 }
256
257 bool IsElementNotNullAndEditable(Element* element) {
258   if (!element)
259     return false;
260
261   if (IsEditable(*element))
262     return true;
263
264   auto* text_control = ToTextControlOrNull(element);
265   if (text_control && !text_control->IsDisabledOrReadOnly())
266     return true;
267
268   if (EqualIgnoringASCIICase(element->FastGetAttribute(html_names::kRoleAttr),
269                              "textbox")) {
270     return true;
271   }
272
273   return false;
274 }
275
276 bool& InputDisabledPerBrowsingContextGroup(
277     const base::UnguessableToken& token) {
278   using BrowsingContextGroupMap = std::map<base::UnguessableToken, bool>;
279   DEFINE_STATIC_LOCAL(BrowsingContextGroupMap, values, ());
280   return values[token];
281 }
282
283 }  // namespace
284
285 // WebFrameWidget ------------------------------------------------------------
286
287 bool WebFrameWidgetImpl::ignore_input_events_ = false;
288
289 // static
290 void WebFrameWidgetImpl::SetIgnoreInputEvents(
291     const base::UnguessableToken& browsing_context_group_token,
292     bool value) {
293   if (base::FeatureList::IsEnabled(
294           features::kPausePagesPerBrowsingContextGroup)) {
295     CHECK_NE(InputDisabledPerBrowsingContextGroup(browsing_context_group_token),
296              value);
297     InputDisabledPerBrowsingContextGroup(browsing_context_group_token) = value;
298   } else {
299     CHECK_NE(ignore_input_events_, value);
300     ignore_input_events_ = value;
301   }
302 }
303
304 // static
305 bool WebFrameWidgetImpl::IgnoreInputEvents(
306     const base::UnguessableToken& browsing_context_group_token) {
307   if (base::FeatureList::IsEnabled(
308           features::kPausePagesPerBrowsingContextGroup)) {
309     return InputDisabledPerBrowsingContextGroup(browsing_context_group_token);
310   } else {
311     return ignore_input_events_;
312   }
313 }
314
315 WebFrameWidgetImpl::WebFrameWidgetImpl(
316     base::PassKey<WebLocalFrame>,
317     CrossVariantMojoAssociatedRemote<mojom::blink::FrameWidgetHostInterfaceBase>
318         frame_widget_host,
319     CrossVariantMojoAssociatedReceiver<mojom::blink::FrameWidgetInterfaceBase>
320         frame_widget,
321     CrossVariantMojoAssociatedRemote<mojom::blink::WidgetHostInterfaceBase>
322         widget_host,
323     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
324         widget,
325     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
326     const viz::FrameSinkId& frame_sink_id,
327     bool hidden,
328     bool never_composited,
329     bool is_for_child_local_root,
330     bool is_for_nested_main_frame,
331     bool is_for_scalable_page)
332     : widget_base_(std::make_unique<WidgetBase>(
333           /*widget_base_client=*/this,
334           std::move(widget_host),
335           std::move(widget),
336           task_runner,
337           hidden,
338           never_composited,
339           /*is_embedded=*/is_for_child_local_root || is_for_nested_main_frame,
340           is_for_scalable_page)),
341       frame_sink_id_(frame_sink_id),
342       is_for_child_local_root_(is_for_child_local_root),
343       is_for_scalable_page_(is_for_scalable_page) {
344   DCHECK(task_runner);
345   if (is_for_nested_main_frame)
346     main_data().is_for_nested_main_frame = is_for_nested_main_frame;
347   frame_widget_host_.Bind(std::move(frame_widget_host), task_runner);
348   receiver_.Bind(std::move(frame_widget), task_runner);
349 }
350
351 WebFrameWidgetImpl::~WebFrameWidgetImpl() {
352   // Ensure that Close is called and we aren't releasing |widget_base_| in the
353   // destructor.
354   // TODO(crbug.com/1139104): This CHECK can be changed to a DCHECK once
355   // the issue is solved.
356   CHECK(!widget_base_);
357 }
358
359 void WebFrameWidgetImpl::BindLocalRoot(WebLocalFrame& local_root) {
360   local_root_ = To<WebLocalFrameImpl>(local_root);
361   CHECK(local_root_ && local_root_->GetFrame());
362   if (RuntimeEnabledFeatures::LongAnimationFrameMonitoringEnabled(
363           local_root_->GetFrame()->DomWindow()) &&
364       !IsHidden()) {
365     animation_frame_timing_monitor_ =
366         MakeGarbageCollected<AnimationFrameTimingMonitor>(
367             *this, local_root_->GetFrame()->GetProbeSink());
368   }
369 }
370
371 bool WebFrameWidgetImpl::ForTopMostMainFrame() const {
372   return ForMainFrame() && !main_data().is_for_nested_main_frame;
373 }
374
375 void WebFrameWidgetImpl::SetIsNestedMainFrameWidget(bool is_nested) {
376   main_data().is_for_nested_main_frame = is_nested;
377 }
378
379 void WebFrameWidgetImpl::Close() {
380   // TODO(bokan): This seems wrong since the page may have other still-active
381   // frame widgets. See also: https://crbug.com/1344531.
382   GetPage()->WillStopCompositing();
383
384   if (ForMainFrame()) {
385     // Closing the WebFrameWidgetImpl happens in response to the local main
386     // frame being detached from the Page/WebViewImpl.
387     View()->SetMainFrameViewWidget(nullptr);
388   }
389
390   if (animation_frame_timing_monitor_) {
391     animation_frame_timing_monitor_->Shutdown();
392     animation_frame_timing_monitor_.Clear();
393   }
394
395   mutator_dispatcher_ = nullptr;
396   local_root_ = nullptr;
397   widget_base_->Shutdown();
398   widget_base_.reset();
399   // These WeakPtrs must be invalidated for WidgetInputHandlerManager at the
400   // same time as the WidgetBase is.
401   input_handler_weak_ptr_factory_.InvalidateWeakPtrs();
402   receiver_.reset();
403   input_target_receiver_.reset();
404 }
405
406 WebLocalFrame* WebFrameWidgetImpl::LocalRoot() const {
407   return local_root_.Get();
408 }
409
410 bool WebFrameWidgetImpl::RequestedMainFramePending() {
411   return View() && View()->does_composite() && LayerTreeHost() &&
412          LayerTreeHost()->RequestedMainFramePending();
413 }
414
415 ukm::UkmRecorder* WebFrameWidgetImpl::MainFrameUkmRecorder() {
416   DCHECK(local_root_);
417   if (!local_root_->IsOutermostMainFrame()) {
418     return nullptr;
419   }
420
421   if (!local_root_->GetFrame() || !local_root_->GetFrame()->DomWindow()) {
422     return nullptr;
423   }
424
425   return local_root_->GetFrame()->DomWindow()->UkmRecorder();
426 }
427 ukm::SourceId WebFrameWidgetImpl::MainFrameUkmSourceId() {
428   DCHECK(local_root_);
429   if (!local_root_->IsOutermostMainFrame()) {
430     return ukm::kInvalidSourceId;
431   }
432
433   if (!local_root_->GetFrame() || !local_root_->GetFrame()->DomWindow()) {
434     return ukm::kInvalidSourceId;
435   }
436
437   return local_root_->GetFrame()->DomWindow()->UkmSourceID();
438 }
439
440 bool WebFrameWidgetImpl::IsMainFrameFullyLoaded() const {
441   DCHECK(local_root_);
442   if (!local_root_->IsOutermostMainFrame()) {
443     return false;
444   }
445
446   return local_root_->GetFrame() &&
447          local_root_->GetFrame()->Loader().GetDocumentLoader() &&
448          !local_root_->GetFrame()
449               ->Loader()
450               .GetDocumentLoader()
451               ->GetTiming()
452               .LoadEventEnd()
453               .is_null();
454 }
455
456 gfx::Rect WebFrameWidgetImpl::ComputeBlockBound(
457     const gfx::Point& point_in_root_frame,
458     bool ignore_clipping) const {
459   HitTestLocation location(local_root_->GetFrameView()->ConvertFromRootFrame(
460       PhysicalOffset(point_in_root_frame)));
461   HitTestRequest::HitTestRequestType hit_type =
462       HitTestRequest::kReadOnly | HitTestRequest::kActive |
463       (ignore_clipping ? HitTestRequest::kIgnoreClipping : 0);
464   HitTestResult result =
465       local_root_->GetFrame()->GetEventHandler().HitTestResultAtLocation(
466           location, hit_type);
467   result.SetToShadowHostIfInUAShadowRoot();
468
469   Node* node = result.InnerNodeOrImageMapImage();
470   if (!node)
471     return gfx::Rect();
472
473   // Find the block type node based on the hit node.
474   // FIXME: This wants to walk flat tree with
475   // LayoutTreeBuilderTraversal::parent().
476   while (node &&
477          (!node->GetLayoutObject() || node->GetLayoutObject()->IsInline()))
478     node = LayoutTreeBuilderTraversal::Parent(*node);
479
480   // Return the bounding box in the root frame's coordinate space.
481   if (node) {
482     gfx::Rect absolute_rect =
483         node->GetLayoutObject()->AbsoluteBoundingBoxRect();
484     LocalFrame* frame = node->GetDocument().GetFrame();
485     return frame->View()->ConvertToRootFrame(absolute_rect);
486   }
487   return gfx::Rect();
488 }
489
490 void WebFrameWidgetImpl::DragTargetDragEnter(
491     const WebDragData& web_drag_data,
492     const gfx::PointF& point_in_viewport,
493     const gfx::PointF& screen_point,
494     DragOperationsMask operations_allowed,
495     uint32_t key_modifiers,
496     DragTargetDragEnterCallback callback) {
497   auto* target = local_root_->GetFrame()->DocumentAtPoint(
498       PhysicalOffset::FromPointFRound(ViewportToRootFrame(point_in_viewport)));
499
500   // Any execution context should do the work since no file should ever be
501   // created during drag events.
502   current_drag_data_ = DataObject::Create(
503       target ? target->GetExecutionContext() : nullptr, web_drag_data);
504   operations_allowed_ = operations_allowed;
505
506   DragTargetDragEnterOrOver(point_in_viewport, screen_point, kDragEnter,
507                             key_modifiers);
508
509   std::move(callback).Run(drag_operation_.operation,
510                           drag_operation_.document_is_handling_drag);
511 }
512
513 void WebFrameWidgetImpl::DragTargetDragOver(
514     const gfx::PointF& point_in_viewport,
515     const gfx::PointF& screen_point,
516     DragOperationsMask operations_allowed,
517     uint32_t key_modifiers,
518     DragTargetDragOverCallback callback) {
519   operations_allowed_ = operations_allowed;
520
521   DragTargetDragEnterOrOver(point_in_viewport, screen_point, kDragOver,
522                             key_modifiers);
523
524   std::move(callback).Run(drag_operation_.operation,
525                           drag_operation_.document_is_handling_drag);
526 }
527
528 void WebFrameWidgetImpl::DragTargetDragLeave(
529     const gfx::PointF& point_in_viewport,
530     const gfx::PointF& screen_point) {
531   base::ScopedClosureRunner runner(
532       WTF::BindOnce(&WebFrameWidgetImpl::CancelDrag, WrapWeakPersistent(this)));
533   if (ShouldIgnoreInputEvents() || !current_drag_data_) {
534     return;
535   }
536
537   gfx::PointF point_in_root_frame(ViewportToRootFrame(point_in_viewport));
538   DragData drag_data(current_drag_data_.Get(), point_in_root_frame,
539                      screen_point, operations_allowed_,
540                      /*force_default_action=*/false);
541
542   GetPage()->GetDragController().DragExited(&drag_data,
543                                             *local_root_->GetFrame());
544
545   // FIXME: why is the drag scroll timer not stopped here?
546 }
547
548 void WebFrameWidgetImpl::DragTargetDrop(const WebDragData& web_drag_data,
549                                         const gfx::PointF& point_in_viewport,
550                                         const gfx::PointF& screen_point,
551                                         uint32_t key_modifiers,
552                                         base::OnceClosure callback) {
553   base::ScopedClosureRunner callback_runner(std::move(callback));
554   base::ScopedClosureRunner runner(
555       WTF::BindOnce(&WebFrameWidgetImpl::CancelDrag, WrapWeakPersistent(this)));
556
557   if (ShouldIgnoreInputEvents() || !current_drag_data_) {
558     return;
559   }
560
561   auto* target = local_root_->GetFrame()->DocumentAtPoint(
562       PhysicalOffset::FromPointFRound(ViewportToRootFrame(point_in_viewport)));
563
564   current_drag_data_ = DataObject::Create(
565       target ? target->GetExecutionContext() : nullptr, web_drag_data);
566
567   // If this webview transitions from the "drop accepting" state to the "not
568   // accepting" state, then our IPC message reply indicating that may be in-
569   // flight, or else delayed by javascript processing in this webview.  If a
570   // drop happens before our IPC reply has reached the browser process, then
571   // the browser forwards the drop to this webview.  So only allow a drop to
572   // proceed if our webview drag operation state is not DragOperation::kNone.
573
574   if (drag_operation_.operation == DragOperation::kNone) {
575     // IPC RACE CONDITION: do not allow this drop.
576     DragTargetDragLeave(point_in_viewport, screen_point);
577     return;
578   }
579
580   current_drag_data_->SetModifiers(key_modifiers);
581   DragData drag_data(current_drag_data_.Get(),
582                      ViewportToRootFrame(point_in_viewport), screen_point,
583                      operations_allowed_, web_drag_data.ForceDefaultAction());
584   GetPage()->GetDragController().PerformDrag(&drag_data,
585                                              *local_root_->GetFrame());
586 }
587
588 void WebFrameWidgetImpl::DragSourceEndedAt(const gfx::PointF& point_in_viewport,
589                                            const gfx::PointF& screen_point,
590                                            DragOperation operation,
591                                            base::OnceClosure callback) {
592   base::ScopedClosureRunner callback_runner(std::move(callback));
593   base::ScopedClosureRunner runner(
594       WTF::BindOnce(&WebFrameWidgetImpl::DragSourceSystemDragEnded,
595                     WrapWeakPersistent(this)));
596
597   if (ShouldIgnoreInputEvents()) {
598     return;
599   }
600
601   WebMouseEvent fake_mouse_move(
602       WebInputEvent::Type::kMouseMove,
603       GetPage()->GetVisualViewport().ViewportToRootFrame(point_in_viewport),
604       screen_point, WebPointerProperties::Button::kLeft, 0,
605       WebInputEvent::kNoModifiers, base::TimeTicks::Now());
606   fake_mouse_move.SetFrameScale(1);
607   local_root_->GetFrame()->GetEventHandler().DragSourceEndedAt(fake_mouse_move,
608                                                                operation);
609 }
610
611 void WebFrameWidgetImpl::DragSourceSystemDragEnded() {
612   CancelDrag();
613
614   // It's possible for this to be false if the source stopped dragging at a
615   // previous page.
616   if (!doing_drag_and_drop_) {
617     return;
618   }
619   GetPage()->GetDragController().DragEnded();
620   doing_drag_and_drop_ = false;
621 }
622
623 gfx::Rect WebFrameWidgetImpl::GetAbsoluteCaretBounds() {
624   LocalFrame* local_frame = GetPage()->GetFocusController().FocusedFrame();
625   if (local_frame) {
626     auto& selection = local_frame->Selection();
627     if (selection.GetSelectionInDOMTree().IsCaret())
628       return selection.AbsoluteCaretBounds();
629   }
630   return gfx::Rect();
631 }
632
633 void WebFrameWidgetImpl::OnStartStylusWriting(
634     OnStartStylusWritingCallback callback) {
635   // Focus the stylus writable element for current touch sequence as we have
636   // detected writing has started.
637   LocalFrame* frame = LocalRootImpl()->GetFrame();
638   if (!frame) {
639     std::move(callback).Run(absl::nullopt, absl::nullopt);
640     return;
641   }
642
643   Element* stylus_writable_element =
644       frame->GetEventHandler().CurrentTouchDownElement();
645   if (!stylus_writable_element) {
646     std::move(callback).Run(absl::nullopt, absl::nullopt);
647     return;
648   }
649
650   if (auto* text_control = EnclosingTextControl(stylus_writable_element)) {
651     text_control->Focus(FocusParams(FocusTrigger::kUserGesture));
652   } else if (auto* html_element =
653                  DynamicTo<HTMLElement>(stylus_writable_element)) {
654     html_element->Focus(FocusParams(FocusTrigger::kUserGesture));
655   }
656   Element* focused_element = FocusedElement();
657   // Since the element can change after it gets focused, we just verify if
658   // the focused element is editable to continue writing.
659   if (IsElementNotNullAndEditable(focused_element)) {
660     std::move(callback).Run(
661         focused_element->BoundsInWidget(),
662         frame->View()->FrameToViewport(GetAbsoluteCaretBounds()));
663     return;
664   }
665
666   std::move(callback).Run(absl::nullopt, absl::nullopt);
667 }
668
669 void WebFrameWidgetImpl::HandleStylusWritingGestureAction(
670     mojom::blink::StylusWritingGestureDataPtr gesture_data,
671     HandleStylusWritingGestureActionCallback callback) {
672   LocalFrame* focused_frame = FocusedLocalFrameInWidget();
673   if (!focused_frame) {
674     std::move(callback).Run(mojom::blink::HandwritingGestureResult::kFailed);
675     return;
676   }
677   mojom::blink::HandwritingGestureResult result =
678       StylusWritingGesture::ApplyGesture(focused_frame,
679                                          std::move(gesture_data));
680   std::move(callback).Run(result);
681 }
682
683 void WebFrameWidgetImpl::SetBackgroundOpaque(bool opaque) {
684   View()->SetBaseBackgroundColorOverrideTransparent(!opaque);
685 }
686
687 void WebFrameWidgetImpl::SetTextDirection(base::i18n::TextDirection direction) {
688   LocalFrame* focusedFrame = FocusedLocalFrameInWidget();
689   if (focusedFrame)
690     focusedFrame->SetTextDirection(direction);
691 }
692
693 void WebFrameWidgetImpl::SetInheritedEffectiveTouchActionForSubFrame(
694     TouchAction touch_action) {
695   DCHECK(ForSubframe());
696   LocalRootImpl()->GetFrame()->SetInheritedEffectiveTouchAction(touch_action);
697 }
698
699 void WebFrameWidgetImpl::UpdateRenderThrottlingStatusForSubFrame(
700     bool is_throttled,
701     bool subtree_throttled,
702     bool display_locked) {
703   DCHECK(ForSubframe());
704   // TODO(szager,vmpstr): The parent render process currently rolls up
705   // display_locked into the value of subtree throttled here; display_locked
706   // should be maintained as a separate bit and transmitted between render
707   // processes.
708   LocalRootImpl()->GetFrameView()->UpdateRenderThrottlingStatus(
709       is_throttled, subtree_throttled, display_locked, /*recurse=*/true);
710 }
711
712 #if BUILDFLAG(IS_MAC)
713 void WebFrameWidgetImpl::GetStringAtPoint(const gfx::Point& point_in_local_root,
714                                           GetStringAtPointCallback callback) {
715   gfx::Point baseline_point;
716   ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
717   base::apple::ScopedCFTypeRef<CFAttributedStringRef> string =
718       SubstringUtil::AttributedWordAtPoint(this, point_in_local_root,
719                                            baseline_point);
720   if (string) {
721     attributed_string = ui::mojom::blink::AttributedString::From(string.get());
722   }
723
724   std::move(callback).Run(std::move(attributed_string), baseline_point);
725 }
726 #endif
727
728 void WebFrameWidgetImpl::BindWidgetCompositor(
729     mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
730   widget_base_->BindWidgetCompositor(std::move(receiver));
731 }
732
733 void WebFrameWidgetImpl::BindInputTargetClient(
734     mojo::PendingReceiver<viz::mojom::blink::InputTargetClient> receiver) {
735   DCHECK(!input_target_receiver_.is_bound());
736   input_target_receiver_.Bind(
737       std::move(receiver),
738       local_root_->GetTaskRunner(TaskType::kInternalInputBlocking));
739 }
740
741 void WebFrameWidgetImpl::FrameSinkIdAt(const gfx::PointF& point,
742                                        const uint64_t trace_id,
743                                        FrameSinkIdAtCallback callback) {
744   TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Event.Pipeline",
745                          TRACE_ID_GLOBAL(trace_id),
746                          TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
747                          "step", "FrameSinkIdAt");
748
749   gfx::PointF local_point;
750   viz::FrameSinkId id = GetFrameSinkIdAtPoint(point, &local_point);
751   std::move(callback).Run(id, local_point);
752 }
753
754 viz::FrameSinkId WebFrameWidgetImpl::GetFrameSinkIdAtPoint(
755     const gfx::PointF& point_in_dips,
756     gfx::PointF* local_point_in_dips) {
757   HitTestResult result =
758       CoreHitTestResultAt(widget_base_->DIPsToBlinkSpace(point_in_dips));
759
760   Node* result_node = result.InnerNode();
761   *local_point_in_dips = gfx::PointF(point_in_dips);
762
763   // TODO(crbug.com/797828): When the node is null the caller may
764   // need to do extra checks. Like maybe update the layout and then
765   // call the hit-testing API. Either way it might be better to have
766   // a DCHECK for the node rather than a null check here.
767   if (!result_node) {
768     return frame_sink_id_;
769   }
770
771   viz::FrameSinkId remote_frame_sink_id = GetRemoteFrameSinkId(result);
772   if (remote_frame_sink_id.is_valid()) {
773     gfx::PointF local_point(result.LocalPoint());
774     LayoutObject* object = result_node->GetLayoutObject();
775     if (auto* box = DynamicTo<LayoutBox>(object))
776       local_point -= gfx::Vector2dF(box->PhysicalContentBoxOffset());
777
778     *local_point_in_dips = widget_base_->BlinkSpaceToDIPs(local_point);
779     return remote_frame_sink_id;
780   }
781
782   // Return the FrameSinkId for the current widget if the point did not hit
783   // test to a remote frame, or the point is outside of the remote frame's
784   // content box, or the remote frame doesn't have a valid FrameSinkId yet.
785   return frame_sink_id_;
786 }
787
788 gfx::RectF WebFrameWidgetImpl::BlinkSpaceToDIPs(const gfx::RectF& rect) {
789   return widget_base_->BlinkSpaceToDIPs(rect);
790 }
791
792 gfx::Rect WebFrameWidgetImpl::BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) {
793   return widget_base_->BlinkSpaceToEnclosedDIPs(rect);
794 }
795
796 gfx::Size WebFrameWidgetImpl::BlinkSpaceToFlooredDIPs(const gfx::Size& size) {
797   return widget_base_->BlinkSpaceToFlooredDIPs(size);
798 }
799
800 gfx::RectF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::RectF& rect) {
801   return widget_base_->DIPsToBlinkSpace(rect);
802 }
803
804 gfx::PointF WebFrameWidgetImpl::DIPsToBlinkSpace(const gfx::PointF& point) {
805   return widget_base_->DIPsToBlinkSpace(point);
806 }
807
808 gfx::Point WebFrameWidgetImpl::DIPsToRoundedBlinkSpace(
809     const gfx::Point& point) {
810   return widget_base_->DIPsToRoundedBlinkSpace(point);
811 }
812
813 float WebFrameWidgetImpl::DIPsToBlinkSpace(float scalar) {
814   return widget_base_->DIPsToBlinkSpace(scalar);
815 }
816
817 gfx::Size WebFrameWidgetImpl::DIPsToCeiledBlinkSpace(const gfx::Size& size) {
818   return widget_base_->DIPsToCeiledBlinkSpace(size);
819 }
820
821 void WebFrameWidgetImpl::SetActive(bool active) {
822   View()->SetIsActive(active);
823 }
824
825 WebInputEventResult WebFrameWidgetImpl::HandleKeyEvent(
826     const WebKeyboardEvent& event) {
827   DCHECK((event.GetType() == WebInputEvent::Type::kRawKeyDown) ||
828          (event.GetType() == WebInputEvent::Type::kKeyDown) ||
829          (event.GetType() == WebInputEvent::Type::kKeyUp));
830
831   // Please refer to the comments explaining the m_suppressNextKeypressEvent
832   // member.
833   // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
834   // Webkit. A keyDown event is typically associated with a keyPress(char)
835   // event and a keyUp event. We reset this flag here as this is a new keyDown
836   // event.
837   suppress_next_keypress_event_ = false;
838
839   // If there is a popup open, it should be the one processing the event,
840   // not the page.
841   scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
842   if (page_popup) {
843     page_popup->HandleKeyEvent(event);
844     if (event.GetType() == WebInputEvent::Type::kRawKeyDown) {
845       suppress_next_keypress_event_ = true;
846     }
847     return WebInputEventResult::kHandledSystem;
848   }
849
850   auto* frame = DynamicTo<LocalFrame>(FocusedCoreFrame());
851   if (!frame)
852     return WebInputEventResult::kNotHandled;
853
854   WebInputEventResult result = frame->GetEventHandler().KeyEvent(event);
855   // EventHandler may have detached the frame.
856   if (!LocalRootImpl())
857     return result;
858
859   if (result != WebInputEventResult::kNotHandled) {
860     if (WebInputEvent::Type::kRawKeyDown == event.GetType()) {
861       // Suppress the next keypress event unless the focused node is a plugin
862       // node.  (Flash needs these keypress events to handle non-US keyboards.)
863       Element* element = FocusedElement();
864       if (element && element->GetLayoutObject() &&
865           element->GetLayoutObject()->IsEmbeddedObject()) {
866         if (event.windows_key_code == VKEY_TAB) {
867           // If the plugin supports keyboard focus then we should not send a tab
868           // keypress event.
869           WebPluginContainerImpl* plugin_view =
870               To<LayoutEmbeddedContent>(element->GetLayoutObject())->Plugin();
871           if (plugin_view && plugin_view->SupportsKeyboardFocus()) {
872             suppress_next_keypress_event_ = true;
873           }
874         }
875       } else {
876         suppress_next_keypress_event_ = true;
877       }
878     }
879     return result;
880   }
881
882 #if !BUILDFLAG(IS_MAC)
883   const WebInputEvent::Type kContextMenuKeyTriggeringEventType =
884 #if BUILDFLAG(IS_WIN)
885       WebInputEvent::Type::kKeyUp;
886 #else
887       WebInputEvent::Type::kRawKeyDown;
888 #endif
889   const WebInputEvent::Type kShiftF10TriggeringEventType =
890       WebInputEvent::Type::kRawKeyDown;
891
892   bool is_unmodified_menu_key =
893       !(event.GetModifiers() & WebInputEvent::kInputModifiers) &&
894       event.windows_key_code == VKEY_APPS;
895   bool is_shift_f10 = (event.GetModifiers() & WebInputEvent::kInputModifiers) ==
896                           WebInputEvent::kShiftKey &&
897                       event.windows_key_code == VKEY_F10;
898   if ((is_unmodified_menu_key &&
899        event.GetType() == kContextMenuKeyTriggeringEventType) ||
900       (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) {
901     View()->SendContextMenuEvent();
902     return WebInputEventResult::kHandledSystem;
903   }
904 #endif  // !BUILDFLAG(IS_MAC)
905
906   return WebInputEventResult::kNotHandled;
907 }
908
909 void WebFrameWidgetImpl::HandleMouseDown(LocalFrame& local_root,
910                                          const WebMouseEvent& event) {
911   WebViewImpl* view_impl = View();
912   // If there is a popup open, close it as the user is clicking on the page
913   // (outside of the popup). We also save it so we can prevent a click on an
914   // element from immediately reopening the same popup.
915   scoped_refptr<WebPagePopupImpl> page_popup;
916   if (event.button == WebMouseEvent::Button::kLeft) {
917     page_popup = view_impl->GetPagePopup();
918     view_impl->CancelPagePopup();
919   }
920
921   // Take capture on a mouse down on a plugin so we can send it mouse events.
922   // If the hit node is a plugin but a scrollbar is over it don't start mouse
923   // capture because it will interfere with the scrollbar receiving events.
924   PhysicalOffset point(LayoutUnit(event.PositionInWidget().x()),
925                        LayoutUnit(event.PositionInWidget().y()));
926   if (event.button == WebMouseEvent::Button::kLeft) {
927     HitTestLocation location(
928         LocalRootImpl()->GetFrameView()->ConvertFromRootFrame(point));
929     HitTestResult result(
930         LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
931             location));
932     result.SetToShadowHostIfInUAShadowRoot();
933     Node* hit_node = result.InnerNode();
934     auto* html_element = DynamicTo<HTMLElement>(hit_node);
935     if (!result.GetScrollbar() && hit_node && hit_node->GetLayoutObject() &&
936         hit_node->GetLayoutObject()->IsEmbeddedObject() && html_element &&
937         html_element->IsPluginElement()) {
938       mouse_capture_element_ = To<HTMLPlugInElement>(hit_node);
939       SetMouseCapture(true);
940       TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("input", "capturing mouse",
941                                         TRACE_ID_LOCAL(this));
942     }
943   }
944
945   WidgetEventHandler::HandleMouseDown(local_root, event);
946   // WidgetEventHandler may have detached the frame.
947   if (!LocalRootImpl())
948     return;
949
950   if (view_impl->GetPagePopup() && page_popup &&
951       view_impl->GetPagePopup()->HasSamePopupClient(page_popup.get())) {
952     // That click triggered a page popup that is the same as the one we just
953     // closed.  It needs to be closed.
954     view_impl->CancelPagePopup();
955   }
956
957   // Dispatch the contextmenu event regardless of if the click was swallowed.
958   if (!GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
959 #if BUILDFLAG(IS_MAC)
960     if (event.button == WebMouseEvent::Button::kRight ||
961         (event.button == WebMouseEvent::Button::kLeft &&
962          event.GetModifiers() & WebMouseEvent::kControlKey))
963       MouseContextMenu(event);
964 #else
965     if (event.button == WebMouseEvent::Button::kRight)
966       MouseContextMenu(event);
967 #endif
968   }
969 }
970
971 void WebFrameWidgetImpl::HandleMouseLeave(LocalFrame& local_root,
972                                           const WebMouseEvent& event) {
973   View()->SetMouseOverURL(WebURL());
974   WidgetEventHandler::HandleMouseLeave(local_root, event);
975   // WidgetEventHandler may have detached the frame.
976 }
977
978 void WebFrameWidgetImpl::MouseContextMenu(const WebMouseEvent& event) {
979   GetPage()->GetContextMenuController().ClearContextMenu();
980
981   WebMouseEvent transformed_event =
982       TransformWebMouseEvent(LocalRootImpl()->GetFrameView(), event);
983   transformed_event.menu_source_type = kMenuSourceMouse;
984   transformed_event.id = PointerEventFactory::kMouseId;
985
986   // Find the right target frame. See issue 1186900.
987   HitTestResult result =
988       HitTestResultForRootFramePos(transformed_event.PositionInRootFrame());
989   Frame* target_frame;
990   if (result.InnerNodeOrImageMapImage())
991     target_frame = result.InnerNodeOrImageMapImage()->GetDocument().GetFrame();
992   else
993     target_frame = GetPage()->GetFocusController().FocusedOrMainFrame();
994
995   // This will need to be changed to a nullptr check when focus control
996   // is refactored, at which point focusedOrMainFrame will never return a
997   // RemoteFrame.
998   // See https://crbug.com/341918.
999   LocalFrame* target_local_frame = DynamicTo<LocalFrame>(target_frame);
1000   if (!target_local_frame)
1001     return;
1002
1003   {
1004     ContextMenuAllowedScope scope;
1005     target_local_frame->GetEventHandler().SendContextMenuEvent(
1006         transformed_event);
1007   }
1008   // Actually showing the context menu is handled by the ContextMenuClient
1009   // implementation...
1010 }
1011
1012 WebInputEventResult WebFrameWidgetImpl::HandleMouseUp(
1013     LocalFrame& local_root,
1014     const WebMouseEvent& event) {
1015   WebInputEventResult result =
1016       WidgetEventHandler::HandleMouseUp(local_root, event);
1017   // WidgetEventHandler may have detached the frame.
1018   if (!LocalRootImpl())
1019     return result;
1020
1021   if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
1022     // Dispatch the contextmenu event regardless of if the click was swallowed.
1023     // On Mac/Linux, we handle it on mouse down, not up.
1024     if (event.button == WebMouseEvent::Button::kRight)
1025       MouseContextMenu(event);
1026   }
1027   return result;
1028 }
1029
1030 WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
1031     const WebGestureEvent& event) {
1032   WebInputEventResult event_result = WebInputEventResult::kNotHandled;
1033
1034   // Fling events are not sent to the renderer.
1035   CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingStart);
1036   CHECK(event.GetType() != WebInputEvent::Type::kGestureFlingCancel);
1037
1038   WebViewImpl* web_view = View();
1039
1040   LocalFrame* frame = LocalRootImpl()->GetFrame();
1041   WebGestureEvent scaled_event = TransformWebGestureEvent(frame->View(), event);
1042
1043   // Special handling for double tap and scroll events as we don't want to
1044   // hit test for them.
1045   switch (event.GetType()) {
1046     case WebInputEvent::Type::kGestureDoubleTap:
1047       if (web_view->SettingsImpl()->DoubleTapToZoomEnabled() &&
1048           web_view->MinimumPageScaleFactor() !=
1049               web_view->MaximumPageScaleFactor()) {
1050         gfx::Point pos_in_local_frame_root =
1051             gfx::ToFlooredPoint(scaled_event.PositionInRootFrame());
1052         auto block_bounds = ComputeBlockBound(pos_in_local_frame_root, false);
1053
1054         if (ForMainFrame()) {
1055           web_view->AnimateDoubleTapZoom(pos_in_local_frame_root, block_bounds);
1056         } else {
1057           // This sends the tap point and bounds to the main frame renderer via
1058           // the browser, where their coordinates will be transformed into the
1059           // main frame's coordinate space.
1060           GetAssociatedFrameWidgetHost()->AnimateDoubleTapZoomInMainFrame(
1061               pos_in_local_frame_root, block_bounds);
1062         }
1063       }
1064       event_result = WebInputEventResult::kHandledSystem;
1065       DidHandleGestureEvent(event);
1066       return event_result;
1067     case WebInputEvent::Type::kGestureScrollBegin:
1068     case WebInputEvent::Type::kGestureScrollEnd:
1069     case WebInputEvent::Type::kGestureScrollUpdate:
1070       // If we are getting any scroll toss close any page popup that is open.
1071       web_view->CancelPagePopup();
1072
1073       // Scrolling-related gesture events invoke EventHandler recursively for
1074       // each frame down the chain, doing a single-frame hit-test per frame.
1075       // This matches handleWheelEvent.  Perhaps we could simplify things by
1076       // rewriting scroll handling to work inner frame out, and then unify with
1077       // other gesture events.
1078       event_result =
1079           frame->GetEventHandler().HandleGestureScrollEvent(scaled_event);
1080       DidHandleGestureEvent(event);
1081       return event_result;
1082     default:
1083       break;
1084   }
1085
1086   // Hit test across all frames and do touch adjustment as necessary for the
1087   // event type.
1088   GestureEventWithHitTestResults targeted_event =
1089       frame->GetEventHandler().TargetGestureEvent(scaled_event);
1090
1091   // Link highlight animations are only for the main frame.
1092   // TODO(bokan): This isn't intentional, see https://crbug.com/1344531.
1093   if (ForMainFrame()) {
1094     // Handle link highlighting outside the main switch to avoid getting lost in
1095     // the complicated set of cases handled below.
1096     switch (scaled_event.GetType()) {
1097       case WebInputEvent::Type::kGestureShowPress:
1098         // Queue a highlight animation, then hand off to regular handler.
1099         web_view->EnableTapHighlightAtPoint(targeted_event);
1100         break;
1101       case WebInputEvent::Type::kGestureShortPress:
1102       case WebInputEvent::Type::kGestureLongPress:
1103       case WebInputEvent::Type::kGestureTapCancel:
1104       case WebInputEvent::Type::kGestureTap:
1105         GetPage()->GetLinkHighlight().UpdateOpacityAndRequestAnimation();
1106         break;
1107       default:
1108         break;
1109     }
1110   }
1111
1112   switch (scaled_event.GetType()) {
1113     case WebInputEvent::Type::kGestureTap: {
1114 #if BUILDFLAG(IS_EFL)
1115       if (web_view->SettingsImpl()->LinkEffectEnabled()) {
1116         HitTestResult result = targeted_event.GetHitTestResult();
1117         result.SetToShadowHostIfInUAShadowRoot();
1118         if (result.CanPlayLinkEffect()) {
1119           auto focused_frame = FocusedWebLocalFrameInWidget();
1120           if (focused_frame) {
1121             focused_frame->Client()->PlayLinkEffect();
1122           }
1123         }
1124       }
1125 #endif
1126       {
1127         ContextMenuAllowedScope scope;
1128         event_result =
1129             frame->GetEventHandler().HandleGestureEvent(targeted_event);
1130       }
1131
1132       if (web_view->GetPagePopup() && last_hidden_page_popup_ &&
1133           web_view->GetPagePopup()->HasSamePopupClient(
1134               last_hidden_page_popup_.get())) {
1135         // The tap triggered a page popup that is the same as the one we just
1136         // closed. It needs to be closed.
1137         web_view->CancelPagePopup();
1138       }
1139       // Don't have this value persist outside of a single tap gesture, plus
1140       // we're done with it now.
1141       last_hidden_page_popup_ = nullptr;
1142       break;
1143     }
1144     case WebInputEvent::Type::kGestureTwoFingerTap:
1145     case WebInputEvent::Type::kGestureLongPress:
1146     case WebInputEvent::Type::kGestureLongTap:
1147       if (scaled_event.GetType() == WebInputEvent::Type::kGestureLongTap) {
1148         if (LocalFrame* inner_frame =
1149                 targeted_event.GetHitTestResult().InnerNodeFrame()) {
1150           if (!inner_frame->GetEventHandler().LongTapShouldInvokeContextMenu())
1151             break;
1152         } else if (!frame->GetEventHandler().LongTapShouldInvokeContextMenu()) {
1153           break;
1154         }
1155       }
1156
1157       GetPage()->GetContextMenuController().ClearContextMenu();
1158       {
1159         ContextMenuAllowedScope scope;
1160         event_result =
1161             frame->GetEventHandler().HandleGestureEvent(targeted_event);
1162       }
1163
1164       break;
1165     case WebInputEvent::Type::kGestureTapDown:
1166       // Touch pinch zoom and scroll on the page (outside of a popup) must hide
1167       // the popup. In case of a touch scroll or pinch zoom, this function is
1168       // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
1169       // When we close a popup because of a GestureTapDown, we also save it so
1170       // we can prevent the following GestureTap from immediately reopening the
1171       // same popup.
1172       // This value should not persist outside of a gesture, so is cleared by
1173       // GestureTap (where it is used) and by GestureCancel.
1174       last_hidden_page_popup_ = web_view->GetPagePopup();
1175       web_view->CancelPagePopup();
1176       event_result =
1177           frame->GetEventHandler().HandleGestureEvent(targeted_event);
1178       break;
1179     case WebInputEvent::Type::kGestureTapCancel:
1180       // Don't have this value persist outside of a single tap gesture.
1181       last_hidden_page_popup_ = nullptr;
1182       event_result =
1183           frame->GetEventHandler().HandleGestureEvent(targeted_event);
1184       break;
1185     case WebInputEvent::Type::kGestureShowPress:
1186     case WebInputEvent::Type::kGestureTapUnconfirmed:
1187     case WebInputEvent::Type::kGestureShortPress:
1188       event_result =
1189           frame->GetEventHandler().HandleGestureEvent(targeted_event);
1190       break;
1191     default:
1192       NOTREACHED();
1193   }
1194   DidHandleGestureEvent(event);
1195   return event_result;
1196 }
1197
1198 WebInputEventResult WebFrameWidgetImpl::HandleMouseWheel(
1199     LocalFrame& frame,
1200     const WebMouseWheelEvent& event) {
1201   View()->CancelPagePopup();
1202   return WidgetEventHandler::HandleMouseWheel(frame, event);
1203   // WidgetEventHandler may have detached the frame.
1204 }
1205
1206 WebInputEventResult WebFrameWidgetImpl::HandleCharEvent(
1207     const WebKeyboardEvent& event) {
1208   DCHECK_EQ(event.GetType(), WebInputEvent::Type::kChar);
1209
1210   // Please refer to the comments explaining the m_suppressNextKeypressEvent
1211   // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
1212   // handled by Webkit. A keyDown event is typically associated with a
1213   // keyPress(char) event and a keyUp event. We reset this flag here as it
1214   // only applies to the current keyPress event.
1215   bool suppress = suppress_next_keypress_event_;
1216   suppress_next_keypress_event_ = false;
1217
1218   // If there is a popup open, it should be the one processing the event,
1219   // not the page.
1220   scoped_refptr<WebPagePopupImpl> page_popup = View()->GetPagePopup();
1221   if (page_popup)
1222     return page_popup->HandleKeyEvent(event);
1223
1224   LocalFrame* frame = To<LocalFrame>(FocusedCoreFrame());
1225   if (!frame) {
1226     return suppress ? WebInputEventResult::kHandledSuppressed
1227                     : WebInputEventResult::kNotHandled;
1228   }
1229
1230   EventHandler& handler = frame->GetEventHandler();
1231
1232   if (!event.IsCharacterKey())
1233     return WebInputEventResult::kHandledSuppressed;
1234
1235   // Accesskeys are triggered by char events and can't be suppressed.
1236   // It is unclear whether a keypress should be dispatched as well
1237   // crbug.com/563507
1238   if (handler.HandleAccessKey(event))
1239     return WebInputEventResult::kHandledSystem;
1240
1241   // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
1242   // the eventHandler::keyEvent. We mimic this behavior on all platforms since
1243   // for now we are converting other platform's key events to windows key
1244   // events.
1245   if (event.is_system_key)
1246     return WebInputEventResult::kNotHandled;
1247
1248   if (suppress)
1249     return WebInputEventResult::kHandledSuppressed;
1250
1251   WebInputEventResult result = handler.KeyEvent(event);
1252   if (result != WebInputEventResult::kNotHandled)
1253     return result;
1254
1255   return WebInputEventResult::kNotHandled;
1256 }
1257
1258 void WebFrameWidgetImpl::CancelDrag() {
1259   drag_operation_ = DragController::Operation();
1260   current_drag_data_ = nullptr;
1261 }
1262
1263 void WebFrameWidgetImpl::StartDragging(LocalFrame* source_frame,
1264                                        const WebDragData& drag_data,
1265                                        DragOperationsMask operations_allowed,
1266                                        const SkBitmap& drag_image,
1267                                        const gfx::Vector2d& cursor_offset,
1268                                        const gfx::Rect& drag_obj_rect) {
1269   doing_drag_and_drop_ = true;
1270   if (drag_and_drop_disabled_) {
1271     DragSourceSystemDragEnded();
1272     return;
1273   }
1274
1275   gfx::Vector2d offset_in_dips =
1276       widget_base_->BlinkSpaceToFlooredDIPs(gfx::Point() + cursor_offset)
1277           .OffsetFromOrigin();
1278   gfx::Rect drag_obj_rect_in_dips =
1279       gfx::Rect(widget_base_->BlinkSpaceToFlooredDIPs(drag_obj_rect.origin()),
1280                 widget_base_->BlinkSpaceToFlooredDIPs(drag_obj_rect.size()));
1281   source_frame->GetLocalFrameHostRemote().StartDragging(
1282       drag_data, operations_allowed, drag_image, offset_in_dips,
1283       drag_obj_rect_in_dips, possible_drag_event_info_.Clone());
1284 }
1285
1286 void WebFrameWidgetImpl::DragTargetDragEnterOrOver(
1287     const gfx::PointF& point_in_viewport,
1288     const gfx::PointF& screen_point,
1289     DragAction drag_action,
1290     uint32_t key_modifiers) {
1291   if (ShouldIgnoreInputEvents() || !current_drag_data_) {
1292     CancelDrag();
1293     return;
1294   }
1295
1296   gfx::PointF point_in_root_frame = ViewportToRootFrame(point_in_viewport);
1297
1298   current_drag_data_->SetModifiers(key_modifiers);
1299   DragData drag_data(current_drag_data_.Get(), point_in_root_frame,
1300                      screen_point, operations_allowed_,
1301                      /*force_default_action=*/false);
1302
1303   drag_operation_ = GetPage()->GetDragController().DragEnteredOrUpdated(
1304       &drag_data, *local_root_->GetFrame());
1305
1306   // Mask the drag operation against the drag source's allowed
1307   // operations.
1308   if (!(static_cast<int>(drag_operation_.operation) &
1309         drag_data.DraggingSourceOperationMask())) {
1310     drag_operation_ = DragController::Operation();
1311   }
1312 }
1313
1314 void WebFrameWidgetImpl::SendOverscrollEventFromImplSide(
1315     const gfx::Vector2dF& overscroll_delta,
1316     cc::ElementId scroll_latched_element_id) {
1317   if (!RuntimeEnabledFeatures::OverscrollCustomizationEnabled())
1318     return;
1319
1320   Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
1321       scroll_latched_element_id);
1322   if (target_node) {
1323     target_node->GetDocument().EnqueueOverscrollEventForNode(
1324         target_node, overscroll_delta.x(), overscroll_delta.y());
1325   }
1326 }
1327
1328 void WebFrameWidgetImpl::SendScrollEndEventFromImplSide(
1329     bool affects_outer_viewport,
1330     cc::ElementId scroll_latched_element_id) {
1331   if (!RuntimeEnabledFeatures::ScrollEndEventsEnabled())
1332     return;
1333
1334   Node* target_node = View()->FindNodeFromScrollableCompositorElementId(
1335       scroll_latched_element_id);
1336   bool target_is_root_scroller = false;
1337   if (View()->MainFrameImpl()) {
1338     Node* document_node = View()->MainFrameImpl()->GetDocument();
1339     if (target_node == document_node) {
1340       target_is_root_scroller = true;
1341     }
1342   }
1343   if (target_node) {
1344     // Scrolls consumed entirely by the VisualViewport and not the
1345     // LayoutViewport should not trigger scrollends on the document. The
1346     // VisualViewport currently handles scroll but not scrollends. If that
1347     // changes, we should consider firing scrollend at the visualviewport
1348     // instead of simply bailing.
1349     if (affects_outer_viewport || !target_is_root_scroller) {
1350       target_node->GetDocument().EnqueueScrollEndEventForNode(target_node);
1351     }
1352   }
1353 }
1354
1355 void WebFrameWidgetImpl::UpdateCompositorScrollState(
1356     const cc::CompositorCommitData& commit_data) {
1357   if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
1358     devtools->SetPageIsScrolling(commit_data.is_scroll_active);
1359
1360   RecordManipulationTypeCounts(commit_data.manipulation_info);
1361
1362   if (commit_data.scroll_latched_element_id == cc::ElementId())
1363     return;
1364
1365   if (!commit_data.overscroll_delta.IsZero()) {
1366     SendOverscrollEventFromImplSide(commit_data.overscroll_delta,
1367                                     commit_data.scroll_latched_element_id);
1368   }
1369
1370   // TODO(bokan): If a scroll ended and a new one began in the same Blink frame
1371   // (e.g. during a long running main thread task), this will erroneously
1372   // dispatch the scroll end to the latter (still-scrolling) element.
1373   // https://crbug.com/1116780.
1374   if (commit_data.scroll_end_data.scroll_gesture_did_end) {
1375     SendScrollEndEventFromImplSide(
1376         commit_data.scroll_end_data.gesture_affects_outer_viewport_scroll,
1377         commit_data.scroll_latched_element_id);
1378   }
1379 }
1380
1381 WebInputMethodController*
1382 WebFrameWidgetImpl::GetActiveWebInputMethodController() const {
1383   WebLocalFrameImpl* local_frame =
1384       WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
1385   return local_frame ? local_frame->GetInputMethodController() : nullptr;
1386 }
1387
1388 void WebFrameWidgetImpl::DisableDragAndDrop() {
1389   drag_and_drop_disabled_ = true;
1390 }
1391
1392 gfx::PointF WebFrameWidgetImpl::ViewportToRootFrame(
1393     const gfx::PointF& point_in_viewport) const {
1394   return GetPage()->GetVisualViewport().ViewportToRootFrame(point_in_viewport);
1395 }
1396
1397 WebViewImpl* WebFrameWidgetImpl::View() const {
1398   return local_root_->ViewImpl();
1399 }
1400
1401 Page* WebFrameWidgetImpl::GetPage() const {
1402   return View()->GetPage();
1403 }
1404
1405 mojom::blink::FrameWidgetHost*
1406 WebFrameWidgetImpl::GetAssociatedFrameWidgetHost() const {
1407   return frame_widget_host_.get();
1408 }
1409
1410 void WebFrameWidgetImpl::RequestDecode(
1411     const PaintImage& image,
1412     base::OnceCallback<void(bool)> callback) {
1413   widget_base_->LayerTreeHost()->QueueImageDecode(image, std::move(callback));
1414 }
1415
1416 void WebFrameWidgetImpl::Trace(Visitor* visitor) const {
1417   visitor->Trace(local_root_);
1418   visitor->Trace(current_drag_data_);
1419   visitor->Trace(frame_widget_host_);
1420   visitor->Trace(receiver_);
1421   visitor->Trace(input_target_receiver_);
1422   visitor->Trace(mouse_capture_element_);
1423   visitor->Trace(device_emulator_);
1424   visitor->Trace(animation_frame_timing_monitor_);
1425 }
1426
1427 #if BUILDFLAG(IS_TIZEN_TV)
1428 void WebFrameWidgetImpl::EdgeScrollBy(const gfx::Point& offset, const gfx::Point& mouse_position) {
1429   bool handled = false;
1430   WebViewImpl* webview = View();
1431   if (webview)
1432     handled = webview->EdgeScrollBy(
1433             blink::ScrollOffset(offset.x(), offset.y()),
1434             gfx::Point(mouse_position.x(), mouse_position.y()));
1435   widget_base_->DidEdgeScrollBy(offset, handled);
1436 }
1437
1438 void WebFrameWidgetImpl::SetTranslatedURL(const WTF::String& url) {
1439   WebViewImpl* webview = View();
1440   if (!webview)
1441     return;
1442   webview->SetTranslatedURL(blink::WebString::FromUTF8(url.Ascii()));
1443 }
1444
1445 void WebFrameWidgetImpl::SetParentalRatingResult(const WTF::String& url,
1446                                                  bool is_pass) {
1447   WebViewImpl* webview = View();
1448   if (!webview){
1449     LOG(ERROR) << "no webview.";
1450     return;
1451   }
1452   webview->SetParentalRatingResult(blink::WebString::FromUTF8(url.Ascii()),
1453                                    is_pass);
1454 }
1455
1456 bool WebFrameWidgetImpl::IsVideoPlaying() {
1457   WebViewImpl* webview = View();
1458   if (!webview){
1459     LOG(ERROR) << "no webview.";
1460     return false;
1461   }
1462   return webview->IsVideoPlaying();
1463 }
1464
1465 void WebFrameWidgetImpl::SetPreferSubtitleLang(const WTF::String lang_list) {
1466   WebViewImpl* webview = View();
1467   if (!webview) {
1468     LOG(ERROR) << "no webview.";
1469     return;
1470   }
1471   webview->SetPreferTextLang(lang_list);
1472 }
1473 #endif
1474
1475 void WebFrameWidgetImpl::SetNeedsRecalculateRasterScales() {
1476   if (!View()->does_composite())
1477     return;
1478   widget_base_->LayerTreeHost()->SetNeedsRecalculateRasterScales();
1479 }
1480
1481 void WebFrameWidgetImpl::SetBackgroundColor(SkColor color) {
1482   if (!View()->does_composite())
1483     return;
1484   // TODO(crbug/1308932): Remove FromColor and make all SkColor4f.
1485   widget_base_->LayerTreeHost()->set_background_color(
1486       SkColor4f::FromColor(color));
1487 }
1488
1489 void WebFrameWidgetImpl::SetOverscrollBehavior(
1490     const cc::OverscrollBehavior& overscroll_behavior) {
1491   if (!View()->does_composite())
1492     return;
1493   widget_base_->LayerTreeHost()->SetOverscrollBehavior(overscroll_behavior);
1494 }
1495
1496 void WebFrameWidgetImpl::SetPrefersReducedMotion(bool prefers_reduced_motion) {
1497   if (!View()->does_composite())
1498     return;
1499   widget_base_->LayerTreeHost()->SetPrefersReducedMotion(
1500       prefers_reduced_motion);
1501 }
1502
1503 void WebFrameWidgetImpl::StartPageScaleAnimation(const gfx::Point& destination,
1504                                                  bool use_anchor,
1505                                                  float new_page_scale,
1506                                                  base::TimeDelta duration) {
1507   widget_base_->LayerTreeHost()->StartPageScaleAnimation(
1508       destination, use_anchor, new_page_scale, duration);
1509 }
1510
1511 void WebFrameWidgetImpl::RequestBeginMainFrameNotExpected(bool request) {
1512   if (!View()->does_composite())
1513     return;
1514   widget_base_->LayerTreeHost()->RequestBeginMainFrameNotExpected(request);
1515 }
1516
1517 void WebFrameWidgetImpl::DidCommitAndDrawCompositorFrame() {
1518   ForEachLocalFrameControlledByWidget(
1519       local_root_->GetFrame(), [](WebLocalFrameImpl* local_frame) {
1520         local_frame->Client()->DidCommitAndDrawCompositorFrame();
1521       });
1522 }
1523
1524 void WebFrameWidgetImpl::DidObserveFirstScrollDelay(
1525     base::TimeDelta first_scroll_delay,
1526     base::TimeTicks first_scroll_timestamp) {
1527   if (!local_root_ || !(local_root_->GetFrame()) ||
1528       !(local_root_->GetFrame()->GetDocument())) {
1529     return;
1530   }
1531   InteractiveDetector* interactive_detector =
1532       InteractiveDetector::From(*(local_root_->GetFrame()->GetDocument()));
1533   if (interactive_detector) {
1534     interactive_detector->DidObserveFirstScrollDelay(first_scroll_delay,
1535                                                      first_scroll_timestamp);
1536   }
1537 }
1538
1539 void WebFrameWidgetImpl::WillBeginMainFrame() {
1540   if (animation_frame_timing_monitor_) {
1541     animation_frame_timing_monitor_->WillBeginMainFrame();
1542   }
1543 }
1544
1545 bool WebFrameWidgetImpl::ShouldIgnoreInputEvents() {
1546   CHECK(GetPage());
1547   return IgnoreInputEvents(GetPage()->BrowsingContextGroupToken());
1548 }
1549
1550 std::unique_ptr<cc::LayerTreeFrameSink>
1551 WebFrameWidgetImpl::AllocateNewLayerTreeFrameSink() {
1552   return nullptr;
1553 }
1554
1555 void WebFrameWidgetImpl::ReportLongAnimationFrameTiming(
1556     AnimationFrameTimingInfo* timing_info) {
1557   WebSecurityOrigin root_origin = local_root_->GetSecurityOrigin();
1558   ForEachLocalFrameControlledByWidget(
1559       local_root_->GetFrame(), [&](WebLocalFrameImpl* local_frame) {
1560         if (local_frame == local_root_ ||
1561             !local_frame->GetSecurityOrigin().IsSameOriginWith(root_origin)) {
1562           DOMWindowPerformance::performance(
1563               *local_frame->GetFrame()->DomWindow())
1564               ->ReportLongAnimationFrameTiming(timing_info);
1565         }
1566       });
1567 }
1568
1569 void WebFrameWidgetImpl::ReportLongTaskTiming(base::TimeTicks start_time,
1570                                               base::TimeTicks end_time,
1571                                               ExecutionContext* task_context) {
1572   CHECK(local_root_);
1573   CHECK(local_root_->GetFrame());
1574   ForEachLocalFrameControlledByWidget(
1575       local_root_->GetFrame(), [&](WebLocalFrameImpl* local_frame) {
1576         CHECK(local_frame->GetFrame());
1577         CHECK(local_frame->GetFrame()->DomWindow());
1578         // Note: |task_context| could be the execution context of any same-agent
1579         // frame.
1580         DOMWindowPerformance::performance(*local_frame->GetFrame()->DomWindow())
1581             ->ReportLongTask(start_time, end_time, task_context,
1582                              /*has_multiple_contexts=*/false);
1583       });
1584 }
1585
1586 bool WebFrameWidgetImpl::ShouldReportLongAnimationFrameTiming() const {
1587   return widget_base_ && !IsHidden();
1588 }
1589 void WebFrameWidgetImpl::OnTaskCompletedForFrame(
1590     base::TimeTicks start_time,
1591     base::TimeTicks end_time,
1592     base::TimeTicks desired_execution_time,
1593     LocalFrame* frame) {
1594   if (animation_frame_timing_monitor_) {
1595     animation_frame_timing_monitor_->OnTaskCompleted(
1596         start_time, end_time, desired_execution_time, frame);
1597   }
1598 }
1599
1600 void WebFrameWidgetImpl::DidBeginMainFrame() {
1601   LocalFrame* root_frame = LocalRootImpl()->GetFrame();
1602   DCHECK(root_frame);
1603
1604   if (LocalFrameView* frame_view = root_frame->View())
1605     frame_view->RunPostLifecycleSteps();
1606
1607   if (animation_frame_timing_monitor_) {
1608     animation_frame_timing_monitor_->DidBeginMainFrame();
1609   }
1610
1611   if (Page* page = root_frame->GetPage())
1612     page->Animator().PostAnimate();
1613 }
1614
1615 void WebFrameWidgetImpl::UpdateLifecycle(WebLifecycleUpdate requested_update,
1616                                          DocumentUpdateReason reason) {
1617   TRACE_EVENT0("blink", "WebFrameWidgetImpl::UpdateLifecycle");
1618   if (!LocalRootImpl())
1619     return;
1620
1621   if (requested_update == WebLifecycleUpdate::kAll &&
1622       animation_frame_timing_monitor_) {
1623     animation_frame_timing_monitor_->WillPerformStyleAndLayoutCalculation();
1624   }
1625
1626   GetPage()->UpdateLifecycle(*LocalRootImpl()->GetFrame(), requested_update,
1627                              reason);
1628   if (requested_update != WebLifecycleUpdate::kAll)
1629     return;
1630
1631   View()->UpdatePagePopup();
1632
1633   // Meaningful layout events and background colors only apply to main frames.
1634   if (ForMainFrame()) {
1635     MainFrameData& data = main_data();
1636
1637     // There is no background color for non-composited WebViews (eg
1638     // printing).
1639     if (View()->does_composite()) {
1640       SkColor background_color = View()->BackgroundColor();
1641       SetBackgroundColor(background_color);
1642       if (background_color != data.last_background_color) {
1643         LocalRootImpl()->GetFrame()->DidChangeBackgroundColor(
1644             SkColor4f::FromColor(background_color), false /* color_adjust */);
1645         data.last_background_color = background_color;
1646       }
1647     }
1648
1649     if (LocalFrameView* view = LocalRootImpl()->GetFrameView()) {
1650       LocalFrame* frame = LocalRootImpl()->GetFrame();
1651
1652       if (data.should_dispatch_first_visually_non_empty_layout &&
1653           view->IsVisuallyNonEmpty()) {
1654         data.should_dispatch_first_visually_non_empty_layout = false;
1655         // TODO(esprehn): Move users of this callback to something
1656         // better, the heuristic for "visually non-empty" is bad.
1657         DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
1658       }
1659
1660       if (data.should_dispatch_first_layout_after_finished_parsing &&
1661           frame->GetDocument()->HasFinishedParsing()) {
1662         data.should_dispatch_first_layout_after_finished_parsing = false;
1663         DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
1664       }
1665
1666       if (data.should_dispatch_first_layout_after_finished_loading &&
1667           frame->GetDocument()->IsLoadCompleted()) {
1668         data.should_dispatch_first_layout_after_finished_loading = false;
1669         DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
1670       }
1671     }
1672   }
1673 }
1674
1675 void WebFrameWidgetImpl::DidCompletePageScaleAnimation() {
1676   // Page scale animations only happen on the main frame.
1677   DCHECK(ForMainFrame());
1678   if (auto* focused_frame = View()->FocusedFrame()) {
1679     if (focused_frame->AutofillClient())
1680       focused_frame->AutofillClient()->DidCompleteFocusChangeInFrame();
1681   }
1682
1683   if (page_scale_animation_for_testing_callback_)
1684     std::move(page_scale_animation_for_testing_callback_).Run();
1685 }
1686
1687 void WebFrameWidgetImpl::ScheduleAnimation() {
1688   if (!View()->does_composite()) {
1689     non_composited_client_->ScheduleNonCompositedAnimation();
1690     return;
1691   }
1692
1693   if (widget_base_->WillBeDestroyed()) {
1694     return;
1695   }
1696
1697   widget_base_->LayerTreeHost()->SetNeedsAnimate();
1698 }
1699
1700 void WebFrameWidgetImpl::FocusChanged(mojom::blink::FocusState focus_state) {
1701   // TODO(crbug.com/689777): FocusChange events are only sent to the MainFrame
1702   // these maybe should goto the local root so that the rest of input messages
1703   // sent to those are preserved in order.
1704   DCHECK(ForMainFrame());
1705   View()->SetIsActive(focus_state == mojom::blink::FocusState::kFocused ||
1706                       focus_state ==
1707                           mojom::blink::FocusState::kNotFocusedAndActive);
1708   View()->SetPageFocus(focus_state == mojom::blink::FocusState::kFocused);
1709 }
1710
1711 bool WebFrameWidgetImpl::ShouldAckSyntheticInputImmediately() {
1712   // TODO(bokan): The RequestPresentation API appears not to function in VR. As
1713   // a short term workaround for https://crbug.com/940063, ACK input
1714   // immediately rather than using RequestPresentation.
1715   if (GetPage()->GetSettings().GetImmersiveModeEnabled())
1716     return true;
1717   return false;
1718 }
1719
1720 void WebFrameWidgetImpl::UpdateVisualProperties(
1721     const VisualProperties& visual_properties) {
1722   SetZoomLevel(visual_properties.zoom_level);
1723
1724   // TODO(danakj): In order to synchronize updates between local roots, the
1725   // display mode should be propagated to RenderFrameProxies and down through
1726   // their RenderWidgetHosts to child WebFrameWidgetImpl via the
1727   // VisualProperties waterfall, instead of coming to each WebFrameWidgetImpl
1728   // independently.
1729   // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode
1730   SetDisplayMode(visual_properties.display_mode);
1731   SetWindowShowState(visual_properties.window_show_state);
1732   SetResizable(visual_properties.resizable);
1733
1734   if (ForMainFrame()) {
1735     SetAutoResizeMode(
1736         visual_properties.auto_resize_enabled,
1737         visual_properties.min_size_for_auto_resize,
1738         visual_properties.max_size_for_auto_resize,
1739         visual_properties.screen_infos.current().device_scale_factor);
1740   }
1741
1742   bool capture_sequence_number_changed =
1743       visual_properties.capture_sequence_number !=
1744       last_capture_sequence_number_;
1745   if (capture_sequence_number_changed) {
1746     last_capture_sequence_number_ = visual_properties.capture_sequence_number;
1747
1748     // Send the capture sequence number to RemoteFrames that are below the
1749     // local root for this widget.
1750     ForEachRemoteFrameControlledByWidget(
1751         [capture_sequence_number = visual_properties.capture_sequence_number](
1752             RemoteFrame* remote_frame) {
1753           remote_frame->UpdateCaptureSequenceNumber(capture_sequence_number);
1754         });
1755   }
1756
1757   if (!View()->AutoResizeMode()) {
1758     // This needs to run before ApplyVisualPropertiesSizing below,
1759     // which updates the current set of screen_infos from visual properties.
1760     if (DidChangeFullscreenState(visual_properties)) {
1761       is_fullscreen_granted_ = visual_properties.is_fullscreen_granted;
1762       if (is_fullscreen_granted_)
1763         View()->DidEnterFullscreen();
1764       else
1765         View()->DidExitFullscreen();
1766     }
1767   }
1768
1769   gfx::Size old_visible_viewport_size_in_dips =
1770       widget_base_->VisibleViewportSizeInDIPs();
1771   ApplyVisualPropertiesSizing(visual_properties);
1772
1773   if (old_visible_viewport_size_in_dips !=
1774       widget_base_->VisibleViewportSizeInDIPs()) {
1775     ForEachLocalFrameControlledByWidget(
1776         local_root_->GetFrame(),
1777         &WebLocalFrameImpl::ResetHasScrolledFocusedEditableIntoView);
1778
1779     // Propagate changes down to child local root RenderWidgets and
1780     // BrowserPlugins in other frame trees/processes.
1781     ForEachRemoteFrameControlledByWidget(
1782         [visible_viewport_size = widget_base_->VisibleViewportSizeInDIPs()](
1783             RemoteFrame* remote_frame) {
1784           remote_frame->DidChangeVisibleViewportSize(visible_viewport_size);
1785         });
1786   }
1787
1788   // All non-top-level Widgets (child local-root frames, Portals, GuestViews,
1789   // etc.) propagate and consume the page scale factor as "external", meaning
1790   // that it comes from the top level widget's page scale.
1791   if (!ForTopMostMainFrame()) {
1792     // The main frame controls the page scale factor, from blink. For other
1793     // frame widgets, the page scale from pinch zoom and compositing scale is
1794     // received from its parent as part of the visual properties here. While
1795     // blink doesn't need to know this page scale factor outside the main frame,
1796     // the compositor does in order to produce its output at the correct scale.
1797     float combined_scale_factor = visual_properties.page_scale_factor *
1798                                   visual_properties.compositing_scale_factor;
1799     widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
1800         combined_scale_factor, visual_properties.is_pinch_gesture_active);
1801
1802     NotifyPageScaleFactorChanged(visual_properties.page_scale_factor,
1803                                  visual_properties.is_pinch_gesture_active);
1804
1805     NotifyCompositingScaleFactorChanged(
1806         visual_properties.compositing_scale_factor);
1807   } else {
1808     // Ensure the external scale factor in top-level widgets is reset as it may
1809     // be leftover from when a widget was nested and was promoted to top level
1810     // (e.g. portal activation).
1811     widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
1812         1.f,
1813         /*is_pinch_gesture_active=*/false);
1814   }
1815
1816   EventHandler& event_handler = local_root_->GetFrame()->GetEventHandler();
1817   if (event_handler.cursor_accessibility_scale_factor() !=
1818       visual_properties.cursor_accessibility_scale_factor) {
1819     ForEachLocalFrameControlledByWidget(
1820         local_root_->GetFrame(), [&](WebLocalFrameImpl* local_frame) {
1821           local_frame->GetFrame()
1822               ->GetEventHandler()
1823               .set_cursor_accessibility_scale_factor(
1824                   visual_properties.cursor_accessibility_scale_factor);
1825         });
1826     // Propagate changes down to any child RemoteFrames.
1827     ForEachRemoteFrameControlledByWidget(
1828         [scale_factor = visual_properties.cursor_accessibility_scale_factor](
1829             RemoteFrame* remote_frame) {
1830           remote_frame->CursorAccessibilityScaleFactorChanged(scale_factor);
1831         });
1832   }
1833
1834   // TODO(crbug.com/939118): This code path where scroll_focused_node_into_view
1835   // is set is used only for WebView, crbug 939118 tracks fixing webviews to
1836   // not use scroll_focused_node_into_view.
1837   if (visual_properties.scroll_focused_node_into_view)
1838     ScrollFocusedEditableElementIntoView();
1839 }
1840
1841 void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
1842     const VisualProperties& visual_properties) {
1843   gfx::Rect new_compositor_viewport_pixel_rect =
1844       visual_properties.compositor_viewport_pixel_rect;
1845   if (ForMainFrame()) {
1846     if (size_ !=
1847         widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size)) {
1848       // Only hide popups when the size changes. Eg https://crbug.com/761908.
1849       View()->CancelPagePopup();
1850     }
1851
1852     if (auto* device_emulator = DeviceEmulator()) {
1853       device_emulator->UpdateVisualProperties(visual_properties);
1854       return;
1855     }
1856
1857     if (AutoResizeMode()) {
1858       new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize(
1859           widget_base_->BlinkSpaceToFlooredDIPs(size_.value_or(gfx::Size())),
1860           visual_properties.screen_infos.current().device_scale_factor));
1861     }
1862   }
1863
1864   SetWindowSegments(visual_properties.root_widget_window_segments);
1865
1866   widget_base_->UpdateSurfaceAndScreenInfo(
1867       visual_properties.local_surface_id.value_or(viz::LocalSurfaceId()),
1868       new_compositor_viewport_pixel_rect, visual_properties.screen_infos);
1869
1870   // Store this even when auto-resizing, it is the size of the full viewport
1871   // used for clipping, and this value is propagated down the Widget
1872   // hierarchy via the VisualProperties waterfall.
1873   widget_base_->SetVisibleViewportSizeInDIPs(
1874       visual_properties.visible_viewport_size);
1875
1876   virtual_keyboard_resize_height_physical_px_ =
1877       visual_properties.virtual_keyboard_resize_height_physical_px;
1878   DCHECK(!virtual_keyboard_resize_height_physical_px_ || ForTopMostMainFrame());
1879
1880   if (ForMainFrame()) {
1881     if (!AutoResizeMode()) {
1882       size_ = widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size);
1883
1884       View()->ResizeWithBrowserControls(
1885           size_.value(),
1886           widget_base_->DIPsToCeiledBlinkSpace(
1887               widget_base_->VisibleViewportSizeInDIPs()),
1888           visual_properties.browser_controls_params);
1889     }
1890
1891 #if !BUILDFLAG(IS_ANDROID)
1892     LocalRootImpl()->GetFrame()->UpdateWindowControlsOverlay(
1893         visual_properties.window_controls_overlay_rect);
1894 #endif
1895
1896   } else {
1897     // Widgets in a WebView's frame tree without a local main frame
1898     // set the size of the WebView to be the |visible_viewport_size|, in order
1899     // to limit compositing in (out of process) child frames to what is visible.
1900     //
1901     // Note that child frames in the same process/WebView frame tree as the
1902     // main frame do not do this in order to not clobber the source of truth in
1903     // the main frame.
1904     if (!View()->MainFrameImpl()) {
1905       View()->Resize(widget_base_->DIPsToCeiledBlinkSpace(
1906           widget_base_->VisibleViewportSizeInDIPs()));
1907     }
1908
1909     Resize(widget_base_->DIPsToCeiledBlinkSpace(visual_properties.new_size));
1910   }
1911 }
1912
1913 bool WebFrameWidgetImpl::DidChangeFullscreenState(
1914     const VisualProperties& visual_properties) const {
1915   if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_)
1916     return true;
1917   // If changing fullscreen from one display to another, the fullscreen
1918   // granted state will not change, but we still need to resolve promises
1919   // by considering this a change.
1920   return visual_properties.is_fullscreen_granted &&
1921          widget_base_->screen_infos().current().display_id !=
1922              visual_properties.screen_infos.current().display_id;
1923 }
1924
1925 int WebFrameWidgetImpl::GetLayerTreeId() {
1926   if (!View()->does_composite())
1927     return 0;
1928   return widget_base_->LayerTreeHost()->GetId();
1929 }
1930
1931 const cc::LayerTreeSettings* WebFrameWidgetImpl::GetLayerTreeSettings() {
1932   if (!View()->does_composite()) {
1933     return nullptr;
1934   }
1935   return &widget_base_->LayerTreeHost()->GetSettings();
1936 }
1937
1938 void WebFrameWidgetImpl::UpdateBrowserControlsState(
1939     cc::BrowserControlsState constraints,
1940     cc::BrowserControlsState current,
1941     bool animate) {
1942   DCHECK(View()->does_composite());
1943   widget_base_->LayerTreeHost()->UpdateBrowserControlsState(constraints,
1944                                                             current, animate);
1945 }
1946
1947 void WebFrameWidgetImpl::SetHaveScrollEventHandlers(bool has_handlers) {
1948   widget_base_->LayerTreeHost()->SetHaveScrollEventHandlers(has_handlers);
1949 }
1950
1951 void WebFrameWidgetImpl::SetEventListenerProperties(
1952     cc::EventListenerClass listener_class,
1953     cc::EventListenerProperties listener_properties) {
1954   widget_base_->LayerTreeHost()->SetEventListenerProperties(
1955       listener_class, listener_properties);
1956
1957   if (listener_class == cc::EventListenerClass::kTouchStartOrMove ||
1958       listener_class == cc::EventListenerClass::kTouchEndOrCancel) {
1959     bool has_touch_handlers =
1960         EventListenerProperties(cc::EventListenerClass::kTouchStartOrMove) !=
1961             cc::EventListenerProperties::kNone ||
1962         EventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel) !=
1963             cc::EventListenerProperties::kNone;
1964     if (!has_touch_handlers_ || *has_touch_handlers_ != has_touch_handlers) {
1965       has_touch_handlers_ = has_touch_handlers;
1966
1967       widget_base_->WidgetScheduler()->SetHasTouchHandler(has_touch_handlers);
1968       // Set touch event consumers based on whether there are touch event
1969       // handlers or the page has hit testable scrollbars.
1970       auto touch_event_consumers = mojom::blink::TouchEventConsumers::New(
1971           has_touch_handlers, GetPage()->GetScrollbarTheme().AllowsHitTest());
1972       frame_widget_host_->SetHasTouchEventConsumers(
1973           std::move(touch_event_consumers));
1974     }
1975   } else if (listener_class == cc::EventListenerClass::kPointerRawUpdate) {
1976     SetHasPointerRawUpdateEventHandlers(listener_properties !=
1977                                         cc::EventListenerProperties::kNone);
1978   }
1979 }
1980
1981 cc::EventListenerProperties WebFrameWidgetImpl::EventListenerProperties(
1982     cc::EventListenerClass listener_class) const {
1983   return widget_base_->LayerTreeHost()->event_listener_properties(
1984       listener_class);
1985 }
1986
1987 mojom::blink::DisplayMode WebFrameWidgetImpl::DisplayMode() const {
1988   return display_mode_;
1989 }
1990
1991 ui::WindowShowState WebFrameWidgetImpl::WindowShowState() const {
1992   return window_show_state_;
1993 }
1994
1995 bool WebFrameWidgetImpl::Resizable() const {
1996   return resizable_;
1997 }
1998
1999 const WebVector<gfx::Rect>& WebFrameWidgetImpl::WindowSegments() const {
2000   return window_segments_;
2001 }
2002
2003 bool WebFrameWidgetImpl::StartDeferringCommits(base::TimeDelta timeout,
2004                                                cc::PaintHoldingReason reason) {
2005   if (!View()->does_composite())
2006     return false;
2007   return widget_base_->LayerTreeHost()->StartDeferringCommits(timeout, reason);
2008 }
2009
2010 void WebFrameWidgetImpl::StopDeferringCommits(
2011     cc::PaintHoldingCommitTrigger triggger) {
2012   if (!View()->does_composite())
2013     return;
2014   widget_base_->LayerTreeHost()->StopDeferringCommits(triggger);
2015 }
2016
2017 std::unique_ptr<cc::ScopedPauseRendering> WebFrameWidgetImpl::PauseRendering() {
2018   if (!View()->does_composite())
2019     return nullptr;
2020   return widget_base_->LayerTreeHost()->PauseRendering();
2021 }
2022
2023 absl::optional<int> WebFrameWidgetImpl::GetMaxRenderBufferBounds() const {
2024   if (!View()->does_composite()) {
2025     return absl::nullopt;
2026   }
2027   return widget_base_->GetMaxRenderBufferBounds();
2028 }
2029
2030 std::unique_ptr<cc::ScopedDeferMainFrameUpdate>
2031 WebFrameWidgetImpl::DeferMainFrameUpdate() {
2032   return widget_base_->LayerTreeHost()->DeferMainFrameUpdate();
2033 }
2034
2035 void WebFrameWidgetImpl::SetBrowserControlsShownRatio(float top_ratio,
2036                                                       float bottom_ratio) {
2037   widget_base_->LayerTreeHost()->SetBrowserControlsShownRatio(top_ratio,
2038                                                               bottom_ratio);
2039 }
2040
2041 void WebFrameWidgetImpl::SetBrowserControlsParams(
2042     cc::BrowserControlsParams params) {
2043   widget_base_->LayerTreeHost()->SetBrowserControlsParams(params);
2044 }
2045
2046 void WebFrameWidgetImpl::SynchronouslyCompositeForTesting(
2047     base::TimeTicks frame_time) {
2048   widget_base_->LayerTreeHost()->CompositeForTest(frame_time, false,
2049                                                   base::OnceClosure());
2050 }
2051
2052 void WebFrameWidgetImpl::SetDeviceColorSpaceForTesting(
2053     const gfx::ColorSpace& color_space) {
2054   DCHECK(ForMainFrame());
2055   // We are changing the device color space from the renderer, so allocate a
2056   // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
2057   widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
2058
2059   display::ScreenInfos screen_infos = widget_base_->screen_infos();
2060   for (display::ScreenInfo& screen_info : screen_infos.screen_infos)
2061     screen_info.display_color_spaces = gfx::DisplayColorSpaces(color_space);
2062   widget_base_->UpdateScreenInfo(screen_infos);
2063 }
2064
2065 // TODO(665924): Remove direct dispatches of mouse events from
2066 // PointerLockController, instead passing them through EventHandler.
2067 void WebFrameWidgetImpl::PointerLockMouseEvent(
2068     const WebCoalescedInputEvent& coalesced_event) {
2069   const WebInputEvent& input_event = coalesced_event.Event();
2070   const WebMouseEvent& mouse_event =
2071       static_cast<const WebMouseEvent&>(input_event);
2072   WebMouseEvent transformed_event =
2073       TransformWebMouseEvent(local_root_->GetFrameView(), mouse_event);
2074
2075   AtomicString event_type;
2076   switch (input_event.GetType()) {
2077     case WebInputEvent::Type::kMouseDown:
2078       event_type = event_type_names::kMousedown;
2079       if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
2080         break;
2081       LocalFrame::NotifyUserActivation(
2082           GetPage()
2083               ->GetPointerLockController()
2084               .GetElement()
2085               ->GetDocument()
2086               .GetFrame(),
2087           mojom::blink::UserActivationNotificationType::kInteraction);
2088       break;
2089     case WebInputEvent::Type::kMouseUp:
2090       event_type = event_type_names::kMouseup;
2091       break;
2092     case WebInputEvent::Type::kMouseMove:
2093       event_type = event_type_names::kMousemove;
2094       break;
2095     case WebInputEvent::Type::kMouseEnter:
2096     case WebInputEvent::Type::kMouseLeave:
2097     case WebInputEvent::Type::kContextMenu:
2098       // These should not be normally dispatched but may be due to timing
2099       // because pointer lost messaging happens on separate mojo channel.
2100       return;
2101     default:
2102       NOTREACHED() << input_event.GetType();
2103   }
2104
2105   if (GetPage()) {
2106     GetPage()->GetPointerLockController().DispatchLockedMouseEvent(
2107         transformed_event,
2108         TransformWebMouseEventVector(
2109             local_root_->GetFrameView(),
2110             coalesced_event.GetCoalescedEventsPointers()),
2111         TransformWebMouseEventVector(
2112             local_root_->GetFrameView(),
2113             coalesced_event.GetPredictedEventsPointers()),
2114         event_type);
2115   }
2116 }
2117 bool WebFrameWidgetImpl::IsPointerLocked() {
2118   if (GetPage()) {
2119     return GetPage()->GetPointerLockController().IsPointerLocked();
2120   }
2121   return false;
2122 }
2123
2124 void WebFrameWidgetImpl::ShowContextMenu(
2125     ui::mojom::blink::MenuSourceType source_type,
2126     const gfx::Point& location) {
2127   host_context_menu_location_ = location;
2128
2129   if (!GetPage())
2130     return;
2131   GetPage()->GetContextMenuController().ClearContextMenu();
2132   {
2133     ContextMenuAllowedScope scope;
2134     if (LocalFrame* focused_frame =
2135             GetPage()->GetFocusController().FocusedFrame()) {
2136       focused_frame->GetEventHandler().ShowNonLocatedContextMenu(
2137           nullptr, static_cast<blink::WebMenuSourceType>(source_type));
2138     }
2139   }
2140   host_context_menu_location_.reset();
2141 }
2142
2143 void WebFrameWidgetImpl::SetViewportIntersection(
2144     mojom::blink::ViewportIntersectionStatePtr intersection_state,
2145     const absl::optional<VisualProperties>& visual_properties) {
2146   // Remote viewports are only applicable to local frames with remote ancestors.
2147   // TODO(https://crbug.com/1148960): Should this deal with portals?
2148   DCHECK(ForSubframe() || !LocalRootImpl()->GetFrame()->IsOutermostMainFrame());
2149
2150   if (visual_properties.has_value())
2151     UpdateVisualProperties(visual_properties.value());
2152   ApplyViewportIntersection(std::move(intersection_state));
2153 }
2154
2155 void WebFrameWidgetImpl::ApplyViewportIntersectionForTesting(
2156     mojom::blink::ViewportIntersectionStatePtr intersection_state) {
2157   ApplyViewportIntersection(std::move(intersection_state));
2158 }
2159
2160 void WebFrameWidgetImpl::ApplyViewportIntersection(
2161     mojom::blink::ViewportIntersectionStatePtr intersection_state) {
2162   if (ForSubframe()) {
2163     // This information is propagated to LTH to define the region for filling
2164     // the on-screen text content.
2165     // TODO(khushalsagar) : This needs to also be done for main frames which are
2166     // embedded pages (see Frame::IsOutermostMainFrame()).
2167     child_data().compositor_visible_rect =
2168         intersection_state->compositor_visible_rect;
2169     widget_base_->LayerTreeHost()->SetVisualDeviceViewportIntersectionRect(
2170         intersection_state->compositor_visible_rect);
2171   }
2172   LocalRootImpl()->GetFrame()->SetViewportIntersectionFromParent(
2173       *intersection_state);
2174 }
2175
2176 void WebFrameWidgetImpl::EnableDeviceEmulation(
2177     const DeviceEmulationParams& parameters) {
2178   // Device Emaulation is only supported for the main frame.
2179   DCHECK(ForMainFrame());
2180   if (!device_emulator_) {
2181     gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
2182
2183     device_emulator_ = MakeGarbageCollected<ScreenMetricsEmulator>(
2184         this, widget_base_->screen_infos(), size_in_dips,
2185         widget_base_->VisibleViewportSizeInDIPs(),
2186         widget_base_->WidgetScreenRect(), widget_base_->WindowScreenRect());
2187   }
2188   device_emulator_->ChangeEmulationParams(parameters);
2189 }
2190
2191 void WebFrameWidgetImpl::DisableDeviceEmulation() {
2192   if (!device_emulator_)
2193     return;
2194   device_emulator_->DisableAndApply();
2195   device_emulator_ = nullptr;
2196 }
2197
2198 void WebFrameWidgetImpl::SetIsInertForSubFrame(bool inert) {
2199   DCHECK(ForSubframe());
2200   LocalRootImpl()->GetFrame()->SetIsInert(inert);
2201 }
2202
2203 absl::optional<gfx::Point>
2204 WebFrameWidgetImpl::GetAndResetContextMenuLocation() {
2205   return std::move(host_context_menu_location_);
2206 }
2207
2208 void WebFrameWidgetImpl::SetZoomLevel(double zoom_level) {
2209   // Override the zoom level with the testing one if necessary.
2210   if (zoom_level_for_testing_ != -INFINITY)
2211     zoom_level = zoom_level_for_testing_;
2212
2213   // Set the layout shift exclusion window for the zoom level change.
2214   if (View()->ZoomLevel() != zoom_level)
2215     NotifyZoomLevelChanged(LocalRootImpl()->GetFrame());
2216
2217   View()->SetZoomLevel(zoom_level);
2218
2219   // Part of the UpdateVisualProperties dance we send the zoom level to
2220   // RemoteFrames that are below the local root for this widget.
2221   ForEachRemoteFrameControlledByWidget([zoom_level](RemoteFrame* remote_frame) {
2222     remote_frame->ZoomLevelChanged(zoom_level);
2223   });
2224 }
2225
2226 void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize,
2227                                            const gfx::Size& min_window_size,
2228                                            const gfx::Size& max_window_size,
2229                                            float device_scale_factor) {
2230   // Auto resize only applies to main frames.
2231   DCHECK(ForMainFrame());
2232
2233   if (auto_resize) {
2234     View()->EnableAutoResizeMode(
2235         gfx::ScaleToCeiledSize(min_window_size, device_scale_factor),
2236         gfx::ScaleToCeiledSize(max_window_size, device_scale_factor));
2237   } else if (AutoResizeMode()) {
2238     View()->DisableAutoResizeMode();
2239   }
2240 }
2241
2242 void WebFrameWidgetImpl::DidAutoResize(const gfx::Size& size) {
2243   DCHECK(ForMainFrame());
2244   gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(size);
2245   size_ = size;
2246
2247   // TODO(ccameron): Note that this destroys any information differentiating
2248   // |size| from the compositor's viewport size.
2249   gfx::Rect size_with_dsf = gfx::Rect(gfx::ScaleToCeiledSize(
2250       gfx::Rect(size_in_dips).size(),
2251       widget_base_->GetScreenInfo().device_scale_factor));
2252   widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
2253   widget_base_->UpdateCompositorViewportRect(size_with_dsf);
2254 }
2255
2256 LocalFrame* WebFrameWidgetImpl::FocusedLocalFrameInWidget() const {
2257   if (!local_root_) {
2258     // WebFrameWidget is created in the call to CreateFrame. The corresponding
2259     // RenderWidget, however, might not swap in right away (InstallNewDocument()
2260     // will lead to it swapping in). During this interval local_root_ is nullptr
2261     // (see https://crbug.com/792345).
2262     return nullptr;
2263   }
2264
2265   LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
2266   return (frame && frame->LocalFrameRoot() == local_root_->GetFrame())
2267              ? frame
2268              : nullptr;
2269 }
2270
2271 WebLocalFrameImpl* WebFrameWidgetImpl::FocusedWebLocalFrameInWidget() const {
2272   return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
2273 }
2274
2275 bool WebFrameWidgetImpl::ScrollFocusedEditableElementIntoView() {
2276   Element* element = FocusedElement();
2277   if (!element)
2278     return false;
2279
2280   EditContext* edit_context = element->GetDocument()
2281                                   .GetFrame()
2282                                   ->GetInputMethodController()
2283                                   .GetActiveEditContext();
2284
2285   if (!WebElement(element).IsEditable() && !edit_context)
2286     return false;
2287
2288   element->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
2289
2290   if (!element->GetLayoutObject())
2291     return false;
2292
2293   // The page scale animation started by ZoomAndScrollToFocusedEditableRect
2294   // will scroll only the visual and layout viewports. Call ScrollRectToVisible
2295   // first to ensure the editable is visible within the document (i.e. scroll
2296   // it into view in any subscrollers). By setting `for_focused_editable`,
2297   // ScrollRectToVisible will stop bubbling when it reaches the layout viewport
2298   // so that can be animated by the PageScaleAnimation.
2299   mojom::blink::ScrollIntoViewParamsPtr params =
2300       ScrollAlignment::CreateScrollIntoViewParams(
2301           ScrollAlignment::CenterIfNeeded(), ScrollAlignment::CenterIfNeeded(),
2302           mojom::blink::ScrollType::kProgrammatic,
2303           /*make_visible_in_visual_viewport=*/false,
2304           mojom::blink::ScrollBehavior::kInstant);
2305   params->for_focused_editable = mojom::blink::FocusedEditableParams::New();
2306
2307   // When deciding whether to zoom in on a focused text box, we should
2308   // decide not to zoom in if the user won't be able to zoom out. e.g if the
2309   // textbox is within a touch-action: none container the user can't zoom
2310   // back out.
2311   TouchAction action = touch_action_util::ComputeEffectiveTouchAction(*element);
2312   params->for_focused_editable->can_zoom =
2313       static_cast<int>(action) & static_cast<int>(TouchAction::kPinchZoom);
2314
2315   PhysicalRect absolute_element_bounds;
2316   PhysicalRect absolute_caret_bounds;
2317
2318   if (edit_context) {
2319     gfx::Rect control_bounds_in_physical_pixels;
2320     gfx::Rect selection_bounds_in_physical_pixels;
2321     edit_context->GetLayoutBounds(&control_bounds_in_physical_pixels,
2322                                   &selection_bounds_in_physical_pixels);
2323
2324     absolute_element_bounds = PhysicalRect(control_bounds_in_physical_pixels);
2325     absolute_caret_bounds = PhysicalRect(selection_bounds_in_physical_pixels);
2326   } else {
2327     absolute_element_bounds =
2328         PhysicalRect(element->GetLayoutObject()->AbsoluteBoundingBoxRect());
2329     absolute_caret_bounds = PhysicalRect(
2330         element->GetDocument().GetFrame()->Selection().ComputeRectToScroll(
2331             kRevealExtent));
2332   }
2333
2334   gfx::Vector2dF editable_offset_from_caret(absolute_element_bounds.offset -
2335                                             absolute_caret_bounds.offset);
2336   gfx::SizeF editable_size(absolute_element_bounds.size);
2337
2338   if (editable_size.IsEmpty()) {
2339     return false;
2340   }
2341
2342   params->for_focused_editable->relative_location = editable_offset_from_caret;
2343   params->for_focused_editable->size = editable_size;
2344
2345   scroll_into_view_util::ScrollRectToVisible(
2346       *element->GetLayoutObject(), absolute_caret_bounds, std::move(params));
2347
2348   return true;
2349 }
2350
2351 void WebFrameWidgetImpl::ResetMeaningfulLayoutStateForMainFrame() {
2352   MainFrameData& data = main_data();
2353   data.should_dispatch_first_visually_non_empty_layout = true;
2354   data.should_dispatch_first_layout_after_finished_parsing = true;
2355   data.should_dispatch_first_layout_after_finished_loading = true;
2356   data.last_background_color.reset();
2357
2358 #if BUILDFLAG(IS_EFL)
2359   if (widget_base_ && widget_base_->LayerTreeHost())
2360     widget_base_->LayerTreeHost()->ResetMeaningfulLayoutStateForMainFrame();
2361 #endif
2362 }
2363
2364 void WebFrameWidgetImpl::InitializeCompositing(
2365     const display::ScreenInfos& screen_infos,
2366     const cc::LayerTreeSettings* settings) {
2367   InitializeCompositingInternal(screen_infos, settings, nullptr);
2368 }
2369
2370 void WebFrameWidgetImpl::InitializeCompositingFromPreviousWidget(
2371     const display::ScreenInfos& screen_infos,
2372     const cc::LayerTreeSettings* settings,
2373     WebFrameWidget& previous_widget) {
2374   InitializeCompositingInternal(screen_infos, settings, &previous_widget);
2375 }
2376
2377 void WebFrameWidgetImpl::InitializeCompositingInternal(
2378     const display::ScreenInfos& screen_infos,
2379     const cc::LayerTreeSettings* settings,
2380     WebFrameWidget* previous_widget) {
2381   DCHECK(View()->does_composite());
2382   DCHECK(!non_composited_client_);  // Assure only one initialize is called.
2383   widget_base_->InitializeCompositing(
2384       *GetPage()->GetPageScheduler(), screen_infos, settings,
2385       input_handler_weak_ptr_factory_.GetWeakPtr(),
2386       previous_widget ? static_cast<WebFrameWidgetImpl*>(previous_widget)
2387                             ->widget_base_.get()
2388                       : nullptr);
2389
2390   probe::DidInitializeFrameWidget(local_root_->GetFrame());
2391
2392   // TODO(bokan): This seems wrong. Page may host multiple FrameWidgets so this
2393   // will call DidInitializeCompositing once per FrameWidget. It probably makes
2394   // sense to move LinkHighlight from Page to WidgetBase so initialization is
2395   // per-widget. See also: https://crbug.com/1344531.
2396   GetPage()->DidInitializeCompositing(*AnimationHost());
2397 }
2398
2399 void WebFrameWidgetImpl::InitializeNonCompositing(
2400     WebNonCompositedWidgetClient* client) {
2401   DCHECK(!non_composited_client_);
2402   DCHECK(client);
2403   DCHECK(!View()->does_composite());
2404   widget_base_->InitializeNonCompositing();
2405   non_composited_client_ = client;
2406 }
2407
2408 void WebFrameWidgetImpl::SetCompositorVisible(bool visible) {
2409   widget_base_->SetCompositorVisible(visible);
2410 }
2411
2412 gfx::Size WebFrameWidgetImpl::Size() {
2413   return size_.value_or(gfx::Size());
2414 }
2415
2416 void WebFrameWidgetImpl::Resize(const gfx::Size& new_size) {
2417   if (size_ && *size_ == new_size)
2418     return;
2419
2420   if (ForMainFrame()) {
2421     size_ = new_size;
2422     View()->Resize(new_size);
2423     return;
2424   }
2425
2426   if (child_data().did_suspend_parsing) {
2427     child_data().did_suspend_parsing = false;
2428     LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->ResumeParser();
2429   }
2430
2431   LocalFrameView* view = LocalRootImpl()->GetFrameView();
2432   DCHECK(view);
2433
2434   size_ = new_size;
2435
2436   view->SetLayoutSize(*size_);
2437   view->Resize(*size_);
2438 }
2439
2440 void WebFrameWidgetImpl::OnCommitRequested() {
2441   // This can be called during shutdown, in which case local_root_ will be
2442   // nullptr.
2443   if (!LocalRootImpl() || !LocalRootImpl()->GetFrame()) {
2444     return;
2445   }
2446   if (auto* view = LocalRootImpl()->GetFrame()->View())
2447     view->OnCommitRequested();
2448 }
2449
2450 void WebFrameWidgetImpl::BeginMainFrame(base::TimeTicks last_frame_time) {
2451   TRACE_EVENT1("blink", "WebFrameWidgetImpl::BeginMainFrame", "frameTime",
2452                last_frame_time);
2453   DCHECK(!last_frame_time.is_null());
2454   CHECK(LocalRootImpl());
2455
2456   // The last_frame_time is created in the compositor thread, it's the time when
2457   // the compositor is ready for a new frame and starts preparing it. For the
2458   // purpose of animation frame timing, this is the desired time to start
2459   // rendering, equivalent to the time when a work task is posted.
2460   if (animation_frame_timing_monitor_) {
2461     animation_frame_timing_monitor_->SetDesiredRenderStartTime(last_frame_time);
2462   }
2463
2464   // Dirty bit on MouseEventManager is not cleared in OOPIFs after scroll
2465   // or layout changes. Ensure the hover state is recomputed if necessary.
2466   LocalRootImpl()
2467       ->GetFrame()
2468       ->GetEventHandler()
2469       .RecomputeMouseHoverStateIfNeeded();
2470
2471   absl::optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer;
2472   if (WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
2473     ukm_timer.emplace(
2474         LocalRootImpl()->GetFrame()->View()->GetUkmAggregator()->GetScopedTimer(
2475             LocalFrameUkmAggregator::kAnimate));
2476   }
2477
2478   GetPage()->Animate(last_frame_time);
2479   // Animate can cause the local frame to detach.
2480   if (!LocalRootImpl())
2481     return;
2482
2483   GetPage()->GetValidationMessageClient().LayoutOverlay();
2484 }
2485
2486 void WebFrameWidgetImpl::BeginCommitCompositorFrame() {
2487   if (commit_compositor_frame_start_time_.has_value()) {
2488     next_commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
2489   } else {
2490     commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
2491   }
2492   GetPage()->GetChromeClient().WillCommitCompositorFrame();
2493   probe::LayerTreePainted(LocalRootImpl()->GetFrame());
2494   if (ForTopMostMainFrame()) {
2495     Document* doc = local_root_->GetFrame()->GetDocument();
2496     if (doc->GetSettings()->GetViewportMetaEnabled() &&
2497         !LayerTreeHost()->IsMobileOptimized()) {
2498       UseCounter::Count(doc, WebFeature::kTapDelayEnabled);
2499     }
2500   }
2501   if (ForMainFrame()) {
2502     View()->DidCommitCompositorFrameForLocalMainFrame();
2503     View()->UpdatePreferredSize();
2504     if (!View()->MainFrameImpl()) {
2505       // Trying to track down why the view's idea of the main frame varies
2506       // from LocalRootImpl's.
2507       // TODO(https://crbug.com/1139104): Remove this.
2508       std::string reason = View()->GetNullFrameReasonForBug1139104();
2509       DCHECK(false) << reason;
2510       SCOPED_CRASH_KEY_STRING32("Crbug1139104", "NullFrameReason", reason);
2511       base::debug::DumpWithoutCrashing();
2512     }
2513   }
2514 }
2515
2516 void WebFrameWidgetImpl::EndCommitCompositorFrame(
2517     base::TimeTicks commit_start_time,
2518     base::TimeTicks commit_finish_time) {
2519   DCHECK(commit_compositor_frame_start_time_.has_value());
2520   LocalRootImpl()
2521       ->GetFrame()
2522       ->View()
2523       ->GetUkmAggregator()
2524       ->RecordImplCompositorSample(commit_compositor_frame_start_time_.value(),
2525                                    commit_start_time, commit_finish_time);
2526   commit_compositor_frame_start_time_ =
2527       next_commit_compositor_frame_start_time_;
2528   next_commit_compositor_frame_start_time_.reset();
2529 }
2530
2531 void WebFrameWidgetImpl::ApplyViewportChanges(
2532     const ApplyViewportChangesArgs& args) {
2533   // Viewport changes only change the outermost main frame. Technically a
2534   // portal has a viewport but it cannot produce changes from the compositor
2535   // until activated so this should be correct for portals too.
2536   if (!LocalRootImpl()->GetFrame()->IsOutermostMainFrame())
2537     return;
2538
2539   WebViewImpl* web_view = View();
2540   // TODO(https://crbug.com/1160652): Figure out if View is null.
2541   CHECK(widget_base_);
2542   CHECK(web_view);
2543   web_view->ApplyViewportChanges(args);
2544 }
2545
2546 void WebFrameWidgetImpl::RecordManipulationTypeCounts(
2547     cc::ManipulationInfo info) {
2548   // Manipulation counts are only recorded for the main frame.
2549   if (!ForMainFrame())
2550     return;
2551
2552   if ((info & cc::kManipulationInfoWheel) == cc::kManipulationInfoWheel) {
2553     UseCounter::Count(LocalRootImpl()->GetDocument(),
2554                       WebFeature::kScrollByWheel);
2555   }
2556   if ((info & cc::kManipulationInfoTouch) == cc::kManipulationInfoTouch) {
2557     UseCounter::Count(LocalRootImpl()->GetDocument(),
2558                       WebFeature::kScrollByTouch);
2559   }
2560   if ((info & cc::kManipulationInfoPinchZoom) ==
2561       cc::kManipulationInfoPinchZoom) {
2562     UseCounter::Count(LocalRootImpl()->GetDocument(), WebFeature::kPinchZoom);
2563   }
2564   if ((info & cc::kManipulationInfoPrecisionTouchPad) ==
2565       cc::kManipulationInfoPrecisionTouchPad) {
2566     UseCounter::Count(LocalRootImpl()->GetDocument(),
2567                       WebFeature::kScrollByPrecisionTouchPad);
2568   }
2569 }
2570
2571 void WebFrameWidgetImpl::RecordDispatchRafAlignedInputTime(
2572     base::TimeTicks raf_aligned_input_start_time) {
2573   if (LocalRootImpl()) {
2574     LocalRootImpl()->GetFrame()->View()->GetUkmAggregator()->RecordTimerSample(
2575         LocalFrameUkmAggregator::kHandleInputEvents,
2576         raf_aligned_input_start_time, base::TimeTicks::Now());
2577   }
2578 }
2579
2580 void WebFrameWidgetImpl::SetSuppressFrameRequestsWorkaroundFor704763Only(
2581     bool suppress_frame_requests) {
2582   GetPage()->Animator().SetSuppressFrameRequestsWorkaroundFor704763Only(
2583       suppress_frame_requests);
2584 }
2585
2586 void WebFrameWidgetImpl::CountDroppedPointerDownForEventTiming(unsigned count) {
2587   if (!local_root_ || !(local_root_->GetFrame()) ||
2588       !(local_root_->GetFrame()->DomWindow())) {
2589     return;
2590   }
2591   WindowPerformance* performance = DOMWindowPerformance::performance(
2592       *(local_root_->GetFrame()->DomWindow()));
2593
2594   performance->eventCounts()->AddMultipleEvents(event_type_names::kPointerdown,
2595                                                 count);
2596   // We only count dropped touchstart that can trigger pointerdown.
2597   performance->eventCounts()->AddMultipleEvents(event_type_names::kTouchstart,
2598                                                 count);
2599   // TouchEnd will not be dropped. But in touch event model only touch starts
2600   // can set the target and after that the touch event always goes to that
2601   // target. So if a touchstart has been dropped, the following touchend will
2602   // not be dispatched. Meanwhile, the pointerup can be captured in the
2603   // pointer_event_manager.
2604   performance->eventCounts()->AddMultipleEvents(event_type_names::kTouchend,
2605                                                 count);
2606 }
2607
2608 std::unique_ptr<cc::BeginMainFrameMetrics>
2609 WebFrameWidgetImpl::GetBeginMainFrameMetrics() {
2610   if (!LocalRootImpl())
2611     return nullptr;
2612
2613   return LocalRootImpl()
2614       ->GetFrame()
2615       ->View()
2616       ->GetUkmAggregator()
2617       ->GetBeginMainFrameMetrics();
2618 }
2619
2620 std::unique_ptr<cc::WebVitalMetrics> WebFrameWidgetImpl::GetWebVitalMetrics() {
2621   if (!LocalRootImpl())
2622     return nullptr;
2623
2624   // This class should be called at most once per commit.
2625   WebPerformanceMetricsForReporting perf =
2626       LocalRootImpl()->PerformanceMetricsForReporting();
2627   auto metrics = std::make_unique<cc::WebVitalMetrics>();
2628   if (perf.FirstInputDelay().has_value()) {
2629     metrics->first_input_delay = perf.FirstInputDelay().value();
2630     metrics->has_fid = true;
2631   }
2632
2633   base::TimeTicks start = perf.NavigationStartAsMonotonicTime();
2634   base::TimeTicks largest_contentful_paint =
2635       perf.LargestContentfulDetailsForMetrics().paint_time;
2636   if (largest_contentful_paint >= start) {
2637     metrics->largest_contentful_paint = largest_contentful_paint - start;
2638     metrics->has_lcp = true;
2639   }
2640
2641   double layout_shift = LocalRootImpl()
2642                             ->GetFrame()
2643                             ->View()
2644                             ->GetLayoutShiftTracker()
2645                             .WeightedScore();
2646   if (layout_shift > 0.f) {
2647     metrics->layout_shift = layout_shift;
2648     metrics->has_cls = true;
2649   }
2650
2651   if (!metrics->HasValue())
2652     return nullptr;
2653
2654   return metrics;
2655 }
2656
2657 void WebFrameWidgetImpl::BeginUpdateLayers() {
2658   if (LocalRootImpl())
2659     update_layers_start_time_.emplace(base::TimeTicks::Now());
2660 }
2661
2662 void WebFrameWidgetImpl::EndUpdateLayers() {
2663   if (LocalRootImpl()) {
2664     DCHECK(update_layers_start_time_);
2665     LocalRootImpl()->GetFrame()->View()->GetUkmAggregator()->RecordTimerSample(
2666         LocalFrameUkmAggregator::kUpdateLayers,
2667         update_layers_start_time_.value(), base::TimeTicks::Now());
2668     probe::LayerTreeDidChange(LocalRootImpl()->GetFrame());
2669   }
2670   update_layers_start_time_.reset();
2671 }
2672
2673 void WebFrameWidgetImpl::RecordStartOfFrameMetrics() {
2674   if (!LocalRootImpl())
2675     return;
2676
2677   LocalRootImpl()->GetFrame()->View()->GetUkmAggregator()->BeginMainFrame();
2678 }
2679
2680 void WebFrameWidgetImpl::RecordEndOfFrameMetrics(
2681     base::TimeTicks frame_begin_time,
2682     cc::ActiveFrameSequenceTrackers trackers) {
2683   if (!LocalRootImpl())
2684     return;
2685   Document* document = LocalRootImpl()->GetFrame()->GetDocument();
2686   DCHECK(document);
2687   LocalRootImpl()
2688       ->GetFrame()
2689       ->View()
2690       ->GetUkmAggregator()
2691       ->RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now(),
2692                                 trackers, document->UkmSourceID(),
2693                                 document->UkmRecorder());
2694 }
2695
2696 void WebFrameWidgetImpl::WillHandleGestureEvent(const WebGestureEvent& event,
2697                                                 bool* suppress) {
2698   possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kTouch;
2699   possible_drag_event_info_.location =
2700       gfx::ToFlooredPoint(event.PositionInScreen());
2701
2702   bool handle_as_cursor_control = false;
2703   switch (event.GetType()) {
2704     case WebInputEvent::Type::kGestureScrollBegin: {
2705       if (event.data.scroll_begin.cursor_control) {
2706         swipe_to_move_cursor_activated_ = true;
2707         handle_as_cursor_control = true;
2708       }
2709       break;
2710     }
2711     case WebInputEvent::Type::kGestureScrollUpdate: {
2712       if (swipe_to_move_cursor_activated_)
2713         handle_as_cursor_control = true;
2714       break;
2715     }
2716     case WebInputEvent::Type::kGestureScrollEnd: {
2717       if (swipe_to_move_cursor_activated_) {
2718         swipe_to_move_cursor_activated_ = false;
2719         handle_as_cursor_control = true;
2720       }
2721       break;
2722     }
2723     default:
2724       break;
2725   }
2726   // TODO(crbug.com/1140106): Place cursor for scroll begin other than just move
2727   // cursor.
2728   if (handle_as_cursor_control) {
2729     WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
2730     if (focused_frame) {
2731       gfx::Point base(event.PositionInWidget().x(),
2732                       event.PositionInWidget().y());
2733       focused_frame->MoveCaretSelection(base);
2734     }
2735     *suppress = true;
2736   }
2737 }
2738
2739 void WebFrameWidgetImpl::WillHandleMouseEvent(const WebMouseEvent& event) {
2740   possible_drag_event_info_.source = ui::mojom::blink::DragEventSource::kMouse;
2741   possible_drag_event_info_.location =
2742       gfx::Point(event.PositionInScreen().x(), event.PositionInScreen().y());
2743 }
2744
2745 void WebFrameWidgetImpl::ObserveGestureEventAndResult(
2746     const WebGestureEvent& gesture_event,
2747     const gfx::Vector2dF& unused_delta,
2748     const cc::OverscrollBehavior& overscroll_behavior,
2749     bool event_processed) {
2750   if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
2751     return;
2752
2753   cc::InputHandlerScrollResult scroll_result;
2754   scroll_result.did_scroll = event_processed;
2755   scroll_result.did_overscroll_root = !unused_delta.IsZero();
2756   scroll_result.unused_scroll_delta = unused_delta;
2757   scroll_result.overscroll_behavior = overscroll_behavior;
2758
2759   widget_base_->widget_input_handler_manager()->ObserveGestureEventOnMainThread(
2760       gesture_event, scroll_result);
2761 }
2762
2763 void WebFrameWidgetImpl::DidHandleKeyEvent() {
2764   ClearEditCommands();
2765 }
2766
2767 WebTextInputType WebFrameWidgetImpl::GetTextInputType() {
2768   if (ShouldDispatchImeEventsToPlugin()) {
2769     return GetFocusedPluginContainer()->GetPluginTextInputType();
2770   }
2771
2772   WebInputMethodController* controller = GetActiveWebInputMethodController();
2773   if (!controller)
2774     return WebTextInputType::kWebTextInputTypeNone;
2775   return controller->TextInputType();
2776 }
2777
2778 void WebFrameWidgetImpl::SetCursorVisibilityState(bool is_visible) {
2779   GetPage()->SetIsCursorVisible(is_visible);
2780 }
2781
2782 void WebFrameWidgetImpl::ApplyViewportChangesForTesting(
2783     const ApplyViewportChangesArgs& args) {
2784   widget_base_->ApplyViewportChanges(args);
2785 }
2786
2787 void WebFrameWidgetImpl::SetDisplayMode(mojom::blink::DisplayMode mode) {
2788   if (mode != display_mode_) {
2789     display_mode_ = mode;
2790     LocalFrame* frame = LocalRootImpl()->GetFrame();
2791     frame->MediaQueryAffectingValueChangedForLocalSubtree(
2792         MediaValueChange::kOther);
2793   }
2794 }
2795
2796 void WebFrameWidgetImpl::SetWindowShowState(ui::WindowShowState state) {
2797   if (state == window_show_state_) {
2798     return;
2799   }
2800
2801   window_show_state_ = state;
2802   LocalFrame* frame = LocalRootImpl()->GetFrame();
2803   frame->MediaQueryAffectingValueChangedForLocalSubtree(
2804       MediaValueChange::kOther);
2805 }
2806
2807 void WebFrameWidgetImpl::SetResizable(bool resizable) {
2808   if (resizable_ == resizable) {
2809     return;
2810   }
2811
2812   resizable_ = resizable;
2813   LocalFrame* frame = LocalRootImpl()->GetFrame();
2814   frame->MediaQueryAffectingValueChangedForLocalSubtree(
2815       MediaValueChange::kOther);
2816 }
2817
2818 void WebFrameWidgetImpl::SetWindowSegments(
2819     const std::vector<gfx::Rect>& window_segments_param) {
2820   WebVector<gfx::Rect> window_segments(window_segments_param);
2821   if (!window_segments_.Equals(window_segments)) {
2822     window_segments_ = window_segments;
2823     LocalFrame* frame = LocalRootImpl()->GetFrame();
2824     frame->WindowSegmentsChanged(window_segments_);
2825
2826     ForEachRemoteFrameControlledByWidget(
2827         [&window_segments = window_segments_param](RemoteFrame* remote_frame) {
2828           remote_frame->DidChangeRootWindowSegments(window_segments);
2829         });
2830   }
2831 }
2832
2833 void WebFrameWidgetImpl::SetCursor(const ui::Cursor& cursor) {
2834   widget_base_->SetCursor(cursor);
2835 }
2836
2837 bool WebFrameWidgetImpl::HandlingInputEvent() {
2838   return widget_base_->input_handler().handling_input_event();
2839 }
2840
2841 void WebFrameWidgetImpl::SetHandlingInputEvent(bool handling) {
2842   widget_base_->input_handler().set_handling_input_event(handling);
2843 }
2844
2845 void WebFrameWidgetImpl::ProcessInputEventSynchronouslyForTesting(
2846     const WebCoalescedInputEvent& event,
2847     WidgetBaseInputHandler::HandledEventCallback callback) {
2848   widget_base_->input_handler().HandleInputEvent(event, nullptr,
2849                                                  std::move(callback));
2850 }
2851
2852 void WebFrameWidgetImpl::ProcessInputEventSynchronouslyForTesting(
2853     const WebCoalescedInputEvent& event) {
2854   ProcessInputEventSynchronouslyForTesting(event, base::DoNothing());
2855 }
2856
2857 WebInputEventResult WebFrameWidgetImpl::DispatchBufferedTouchEvents() {
2858   CHECK(LocalRootImpl());
2859
2860   if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl())
2861     devtools->DispatchBufferedTouchEvents();
2862
2863   return LocalRootImpl()
2864       ->GetFrame()
2865       ->GetEventHandler()
2866       .DispatchBufferedTouchEvents();
2867 }
2868
2869 WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
2870     const WebCoalescedInputEvent& coalesced_event) {
2871   const WebInputEvent& input_event = coalesced_event.Event();
2872   TRACE_EVENT1("input,rail", "WebFrameWidgetImpl::HandleInputEvent", "type",
2873                WebInputEvent::GetName(input_event.GetType()));
2874   DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
2875   CHECK(LocalRootImpl());
2876
2877   // Clients shouldn't be dispatching events to a provisional frame but this
2878   // can happen. Ensure that event handling can assume we're in a committed
2879   // frame.
2880   if (IsProvisional())
2881     return WebInputEventResult::kHandledSuppressed;
2882
2883   // If a drag-and-drop operation is in progress, ignore input events except
2884   // PointerCancel and GestureLongPress.
2885   if (doing_drag_and_drop_ &&
2886       input_event.GetType() != WebInputEvent::Type::kPointerCancel &&
2887       input_event.GetType() != WebInputEvent::Type::kGestureLongPress) {
2888     return WebInputEventResult::kHandledSuppressed;
2889   }
2890
2891   // Don't handle events once we've started shutting down or when the page is in
2892   // bfcache.
2893   if (!GetPage() ||
2894       GetPage()->GetPageLifecycleState()->is_in_back_forward_cache) {
2895     return WebInputEventResult::kNotHandled;
2896   }
2897
2898   if (WebDevToolsAgentImpl* devtools = LocalRootImpl()->DevToolsAgentImpl()) {
2899     auto result = devtools->HandleInputEvent(input_event);
2900     if (result != WebInputEventResult::kNotHandled)
2901       return result;
2902   }
2903
2904   // Report the event to be NOT processed by WebKit, so that the browser can
2905   // handle it appropriately.
2906   if (ShouldIgnoreInputEvents()) {
2907     return WebInputEventResult::kNotHandled;
2908   }
2909
2910   base::AutoReset<const WebInputEvent*> current_event_change(
2911       &CurrentInputEvent::current_input_event_, &input_event);
2912   UIEventWithKeyState::ClearNewTabModifierSetFromIsolatedWorld();
2913
2914   if (GetPage()->GetPointerLockController().IsPointerLocked() &&
2915       WebInputEvent::IsMouseEventType(input_event.GetType())) {
2916     PointerLockMouseEvent(coalesced_event);
2917     return WebInputEventResult::kHandledSystem;
2918   }
2919
2920   /// These metrics are only captured for the main frame.
2921   if (ForMainFrame()) {
2922     Document& main_frame_document = *LocalRootImpl()->GetFrame()->GetDocument();
2923
2924     if (input_event.GetType() != WebInputEvent::Type::kMouseMove) {
2925       FirstMeaningfulPaintDetector::From(main_frame_document)
2926           .NotifyInputEvent();
2927     }
2928
2929     if (input_event.GetType() != WebInputEvent::Type::kMouseMove &&
2930         input_event.GetType() != WebInputEvent::Type::kMouseEnter &&
2931         input_event.GetType() != WebInputEvent::Type::kMouseLeave) {
2932       InteractiveDetector* interactive_detector(
2933           InteractiveDetector::From(main_frame_document));
2934       if (interactive_detector) {
2935         interactive_detector->OnInvalidatingInputEvent(input_event.TimeStamp());
2936       }
2937     }
2938   }
2939
2940   NotifyInputObservers(coalesced_event);
2941
2942   // Notify the focus frame of the input. Note that the other frames are not
2943   // notified as input is only handled by the focused frame.
2944   Frame* frame = FocusedCoreFrame();
2945   if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
2946     if (auto* content_capture_manager =
2947             local_frame->LocalFrameRoot().GetOrResetContentCaptureManager()) {
2948       content_capture_manager->NotifyInputEvent(input_event.GetType(),
2949                                                 *local_frame);
2950     }
2951   }
2952
2953   // Skip the pointerrawupdate for mouse capture case.
2954   if (mouse_capture_element_ &&
2955       input_event.GetType() == WebInputEvent::Type::kPointerRawUpdate)
2956     return WebInputEventResult::kHandledSystem;
2957
2958   if (mouse_capture_element_ &&
2959       WebInputEvent::IsMouseEventType(input_event.GetType()))
2960     return HandleCapturedMouseEvent(coalesced_event);
2961
2962   // FIXME: This should take in the intended frame, not the local frame
2963   // root.
2964   return WidgetEventHandler::HandleInputEvent(coalesced_event,
2965                                               LocalRootImpl()->GetFrame());
2966 }
2967
2968 WebInputEventResult WebFrameWidgetImpl::HandleCapturedMouseEvent(
2969     const WebCoalescedInputEvent& coalesced_event) {
2970   const WebInputEvent& input_event = coalesced_event.Event();
2971   TRACE_EVENT1("input", "captured mouse event", "type", input_event.GetType());
2972   // Save |mouse_capture_element_| since |MouseCaptureLost()| will clear it.
2973   HTMLPlugInElement* element = mouse_capture_element_;
2974
2975   // Not all platforms call mouseCaptureLost() directly.
2976   if (input_event.GetType() == WebInputEvent::Type::kMouseUp) {
2977     SetMouseCapture(false);
2978     MouseCaptureLost();
2979   }
2980
2981   AtomicString event_type;
2982   switch (input_event.GetType()) {
2983     case WebInputEvent::Type::kMouseEnter:
2984       event_type = event_type_names::kMouseover;
2985       break;
2986     case WebInputEvent::Type::kMouseMove:
2987       event_type = event_type_names::kMousemove;
2988       break;
2989     case WebInputEvent::Type::kPointerRawUpdate:
2990       // There will be no mouse event for rawupdate events.
2991       event_type = event_type_names::kPointerrawupdate;
2992       break;
2993     case WebInputEvent::Type::kMouseLeave:
2994       event_type = event_type_names::kMouseout;
2995       break;
2996     case WebInputEvent::Type::kMouseDown:
2997       event_type = event_type_names::kMousedown;
2998       LocalFrame::NotifyUserActivation(
2999           element->GetDocument().GetFrame(),
3000           mojom::blink::UserActivationNotificationType::kInteraction);
3001       break;
3002     case WebInputEvent::Type::kMouseUp:
3003       event_type = event_type_names::kMouseup;
3004       break;
3005     default:
3006       NOTREACHED();
3007   }
3008
3009   WebMouseEvent transformed_event =
3010       TransformWebMouseEvent(LocalRootImpl()->GetFrameView(),
3011                              static_cast<const WebMouseEvent&>(input_event));
3012   if (LocalFrame* frame = element->GetDocument().GetFrame()) {
3013     frame->GetEventHandler().HandleTargetedMouseEvent(
3014         element, transformed_event, event_type,
3015         TransformWebMouseEventVector(
3016             LocalRootImpl()->GetFrameView(),
3017             coalesced_event.GetCoalescedEventsPointers()),
3018         TransformWebMouseEventVector(
3019             LocalRootImpl()->GetFrameView(),
3020             coalesced_event.GetPredictedEventsPointers()));
3021   }
3022   return WebInputEventResult::kHandledSystem;
3023 }
3024
3025 void WebFrameWidgetImpl::UpdateTextInputState() {
3026   widget_base_->UpdateTextInputState();
3027 }
3028
3029 void WebFrameWidgetImpl::UpdateSelectionBounds() {
3030   widget_base_->UpdateSelectionBounds();
3031 }
3032
3033 void WebFrameWidgetImpl::ShowVirtualKeyboard() {
3034   widget_base_->ShowVirtualKeyboard();
3035 }
3036
3037 void WebFrameWidgetImpl::FlushInputProcessedCallback() {
3038   widget_base_->FlushInputProcessedCallback();
3039 }
3040
3041 void WebFrameWidgetImpl::CancelCompositionForPepper() {
3042   widget_base_->CancelCompositionForPepper();
3043 }
3044
3045 void WebFrameWidgetImpl::RequestMouseLock(
3046     bool has_transient_user_activation,
3047     bool request_unadjusted_movement,
3048     mojom::blink::WidgetInputHandlerHost::RequestMouseLockCallback callback) {
3049   mojom::blink::WidgetInputHandlerHost* host =
3050       widget_base_->widget_input_handler_manager()->GetWidgetInputHandlerHost();
3051
3052   // If we don't have a host just leave the callback uncalled. This simulates
3053   // the browser indefinitely postponing the mouse request which is valid.
3054   // Note that |callback| is not a mojo bound callback (until it is passed
3055   // into the mojo interface) and can be destructed without invoking the
3056   // callback. It does share the same signature as the mojo definition
3057   // for simplicity.
3058   if (host) {
3059     host->RequestMouseLock(has_transient_user_activation,
3060                            request_unadjusted_movement, std::move(callback));
3061   }
3062 }
3063
3064 void WebFrameWidgetImpl::MouseCaptureLost() {
3065   TRACE_EVENT_NESTABLE_ASYNC_END0("input", "capturing mouse",
3066                                   TRACE_ID_LOCAL(this));
3067   mouse_capture_element_ = nullptr;
3068 }
3069
3070 void WebFrameWidgetImpl::ApplyVisualProperties(
3071     const VisualProperties& visual_properties) {
3072   widget_base_->UpdateVisualProperties(visual_properties);
3073 }
3074
3075 bool WebFrameWidgetImpl::IsFullscreenGranted() {
3076   return is_fullscreen_granted_;
3077 }
3078
3079 bool WebFrameWidgetImpl::PinchGestureActiveInMainFrame() {
3080   return is_pinch_gesture_active_in_mainframe_;
3081 }
3082
3083 float WebFrameWidgetImpl::PageScaleInMainFrame() {
3084   return page_scale_factor_in_mainframe_;
3085 }
3086
3087 void WebFrameWidgetImpl::UpdateSurfaceAndScreenInfo(
3088     const viz::LocalSurfaceId& new_local_surface_id,
3089     const gfx::Rect& compositor_viewport_pixel_rect,
3090     const display::ScreenInfos& new_screen_infos) {
3091   widget_base_->UpdateSurfaceAndScreenInfo(
3092       new_local_surface_id, compositor_viewport_pixel_rect, new_screen_infos);
3093 }
3094
3095 void WebFrameWidgetImpl::UpdateScreenInfo(
3096     const display::ScreenInfos& new_screen_infos) {
3097   widget_base_->UpdateScreenInfo(new_screen_infos);
3098 }
3099
3100 void WebFrameWidgetImpl::UpdateSurfaceAndCompositorRect(
3101     const viz::LocalSurfaceId& new_local_surface_id,
3102     const gfx::Rect& compositor_viewport_pixel_rect) {
3103   widget_base_->UpdateSurfaceAndCompositorRect(new_local_surface_id,
3104                                                compositor_viewport_pixel_rect);
3105 }
3106
3107 void WebFrameWidgetImpl::UpdateCompositorViewportRect(
3108     const gfx::Rect& compositor_viewport_pixel_rect) {
3109   widget_base_->UpdateCompositorViewportRect(compositor_viewport_pixel_rect);
3110 }
3111
3112 const display::ScreenInfo& WebFrameWidgetImpl::GetScreenInfo() {
3113   return widget_base_->GetScreenInfo();
3114 }
3115
3116 const display::ScreenInfos& WebFrameWidgetImpl::GetScreenInfos() {
3117   return widget_base_->screen_infos();
3118 }
3119
3120 const display::ScreenInfo& WebFrameWidgetImpl::GetOriginalScreenInfo() {
3121   if (device_emulator_)
3122     return device_emulator_->GetOriginalScreenInfo();
3123   return widget_base_->GetScreenInfo();
3124 }
3125
3126 const display::ScreenInfos& WebFrameWidgetImpl::GetOriginalScreenInfos() {
3127   if (device_emulator_)
3128     return device_emulator_->original_screen_infos();
3129   return widget_base_->screen_infos();
3130 }
3131
3132 gfx::Rect WebFrameWidgetImpl::WindowRect() {
3133   return widget_base_->WindowRect();
3134 }
3135
3136 gfx::Rect WebFrameWidgetImpl::ViewRect() {
3137   return widget_base_->ViewRect();
3138 }
3139
3140 void WebFrameWidgetImpl::SetScreenRects(const gfx::Rect& widget_screen_rect,
3141                                         const gfx::Rect& window_screen_rect) {
3142   widget_base_->SetScreenRects(widget_screen_rect, window_screen_rect);
3143 }
3144
3145 gfx::Size WebFrameWidgetImpl::VisibleViewportSizeInDIPs() {
3146   return widget_base_->VisibleViewportSizeInDIPs();
3147 }
3148
3149 void WebFrameWidgetImpl::SetPendingWindowRect(
3150     const gfx::Rect& window_screen_rect) {
3151   widget_base_->SetPendingWindowRect(window_screen_rect);
3152 }
3153
3154 void WebFrameWidgetImpl::AckPendingWindowRect() {
3155   widget_base_->AckPendingWindowRect();
3156 }
3157
3158 bool WebFrameWidgetImpl::IsHidden() const {
3159   return widget_base_->is_hidden();
3160 }
3161
3162 WebString WebFrameWidgetImpl::GetLastToolTipTextForTesting() const {
3163   return GetPage()->GetChromeClient().GetLastToolTipTextForTesting();
3164 }
3165
3166 float WebFrameWidgetImpl::GetEmulatorScale() {
3167   if (device_emulator_)
3168     return device_emulator_->scale();
3169   return 1.0f;
3170 }
3171
3172 void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
3173     mojom::blink::IntrinsicSizingInfoPtr sizing_info) {
3174   DCHECK(ForSubframe());
3175   GetAssociatedFrameWidgetHost()->IntrinsicSizingInfoChanged(
3176       std::move(sizing_info));
3177 }
3178
3179 void WebFrameWidgetImpl::AutoscrollStart(const gfx::PointF& position) {
3180   GetAssociatedFrameWidgetHost()->AutoscrollStart(std::move(position));
3181 }
3182
3183 void WebFrameWidgetImpl::AutoscrollFling(const gfx::Vector2dF& velocity) {
3184   GetAssociatedFrameWidgetHost()->AutoscrollFling(std::move(velocity));
3185 }
3186
3187 void WebFrameWidgetImpl::AutoscrollEnd() {
3188   GetAssociatedFrameWidgetHost()->AutoscrollEnd();
3189 }
3190
3191 void WebFrameWidgetImpl::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
3192   if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
3193     NotifyPresentationTime(WTF::BindOnce(
3194         &WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout,
3195         WrapWeakPersistent(this)));
3196   }
3197
3198 #if BUILDFLAG(IS_EFL)
3199   if (widget_base_ && widget_base_->LayerTreeHost()) {
3200     if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty)
3201       widget_base_->LayerTreeHost()->SetDidFirstNonEmptyLayout();
3202     else if (layout_type == blink::WebMeaningfulLayout::kFinishedParsing)
3203       widget_base_->LayerTreeHost()->SetDidFinishDocumentParsing();
3204   }
3205 #endif
3206
3207   ForEachLocalFrameControlledByWidget(
3208       local_root_->GetFrame(), [layout_type](WebLocalFrameImpl* local_frame) {
3209         local_frame->Client()->DidMeaningfulLayout(layout_type);
3210       });
3211 }
3212
3213 void WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout(
3214     base::TimeTicks first_paint_time) {
3215   // |local_root_| may be null if the widget has shut down between when this
3216   // callback was requested and when it was resolved by the compositor.
3217   if (local_root_)
3218     local_root_->ViewImpl()->DidFirstVisuallyNonEmptyPaint();
3219
3220   if (widget_base_)
3221     widget_base_->DidFirstVisuallyNonEmptyPaint(first_paint_time);
3222
3223 #if BUILDFLAG(IS_EFL)
3224   if (widget_base_ && widget_base_->LayerTreeHost())
3225     widget_base_->LayerTreeHost()->SetDidTriggerFirstNonEmptyLayoutPaint();
3226 #endif
3227 }
3228
3229 void WebFrameWidgetImpl::RequestAnimationAfterDelay(
3230     const base::TimeDelta& delay) {
3231   widget_base_->RequestAnimationAfterDelay(delay);
3232 }
3233
3234 void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
3235   if (!View()->does_composite()) {
3236     DCHECK(ForMainFrame());
3237     DCHECK(!layer);
3238     return;
3239   }
3240
3241   // Set up some initial state before we are setting the layer.
3242   if (ForSubframe() && layer) {
3243     // Child local roots will always have a transparent background color.
3244     widget_base_->LayerTreeHost()->set_background_color(SkColors::kTransparent);
3245     // Pass the limits even though this is for subframes, as the limits will
3246     // be needed in setting the raster scale.
3247     SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
3248                                View()->MinimumPageScaleFactor(),
3249                                View()->MaximumPageScaleFactor());
3250   }
3251
3252   bool root_layer_exists = !!layer;
3253   if (widget_base_->WillBeDestroyed()) {
3254     CHECK(!layer);
3255   } else {
3256     widget_base_->LayerTreeHost()->SetRootLayer(std::move(layer));
3257   }
3258
3259   // Notify the WebView that we did set a layer.
3260   if (ForMainFrame()) {
3261     View()->DidChangeRootLayer(root_layer_exists);
3262   }
3263 }
3264
3265 base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
3266 WebFrameWidgetImpl::EnsureCompositorMutatorDispatcher(
3267     scoped_refptr<base::SingleThreadTaskRunner> mutator_task_runner) {
3268   if (!mutator_task_runner_) {
3269     mutator_task_runner_ = std::move(mutator_task_runner);
3270     widget_base_->LayerTreeHost()->SetLayerTreeMutator(
3271         AnimationWorkletMutatorDispatcherImpl::CreateCompositorThreadClient(
3272             mutator_dispatcher_, mutator_task_runner_));
3273   }
3274
3275   DCHECK(mutator_task_runner_);
3276   return mutator_dispatcher_;
3277 }
3278
3279 HitTestResult WebFrameWidgetImpl::CoreHitTestResultAt(
3280     const gfx::PointF& point_in_viewport) {
3281   LocalFrameView* view = LocalRootImpl()->GetFrameView();
3282   gfx::PointF point_in_root_frame(view->ViewportToFrame(point_in_viewport));
3283   return HitTestResultForRootFramePos(point_in_root_frame);
3284 }
3285
3286 cc::AnimationHost* WebFrameWidgetImpl::AnimationHost() const {
3287   return widget_base_->AnimationHost();
3288 }
3289
3290 cc::AnimationTimeline* WebFrameWidgetImpl::ScrollAnimationTimeline() const {
3291   return widget_base_->ScrollAnimationTimeline();
3292 }
3293
3294 base::WeakPtr<PaintWorkletPaintDispatcher>
3295 WebFrameWidgetImpl::EnsureCompositorPaintDispatcher(
3296     scoped_refptr<base::SingleThreadTaskRunner>* paint_task_runner) {
3297   // We check paint_task_runner_ not paint_dispatcher_ because the dispatcher is
3298   // a base::WeakPtr that should only be used on the compositor thread.
3299   if (!paint_task_runner_) {
3300     widget_base_->LayerTreeHost()->SetPaintWorkletLayerPainter(
3301         PaintWorkletPaintDispatcher::CreateCompositorThreadPainter(
3302             &paint_dispatcher_));
3303     paint_task_runner_ = Thread::CompositorThread()->GetTaskRunner();
3304   }
3305   DCHECK(paint_task_runner_);
3306   *paint_task_runner = paint_task_runner_;
3307   return paint_dispatcher_;
3308 }
3309
3310 void WebFrameWidgetImpl::SetDelegatedInkMetadata(
3311     std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
3312   widget_base_->LayerTreeHost()->SetDelegatedInkMetadata(std::move(metadata));
3313 }
3314
3315 // Enables measuring and reporting both presentation times and swap times in
3316 // swap promises.
3317 class ReportTimeSwapPromise : public cc::SwapPromise {
3318  public:
3319   ReportTimeSwapPromise(WebFrameWidgetImpl::PromiseCallbacks callbacks,
3320                         scoped_refptr<base::SingleThreadTaskRunner> task_runner,
3321                         WebFrameWidgetImpl* widget)
3322       : promise_callbacks_(std::move(callbacks)),
3323         task_runner_(std::move(task_runner)),
3324         widget_(MakeCrossThreadWeakHandle(widget)) {}
3325
3326   ReportTimeSwapPromise(const ReportTimeSwapPromise&) = delete;
3327   ReportTimeSwapPromise& operator=(const ReportTimeSwapPromise&) = delete;
3328
3329   ~ReportTimeSwapPromise() override = default;
3330
3331   void DidActivate() override {}
3332
3333   void WillSwap(viz::CompositorFrameMetadata* metadata) override {
3334     DCHECK_GT(metadata->frame_token, 0u);
3335     // The interval between the current swap and its presentation time is
3336     // reported in UMA (see corresponding code in DidSwap() below).
3337     frame_token_ = metadata->frame_token;
3338   }
3339
3340   void DidSwap() override {
3341     DCHECK_GT(frame_token_, 0u);
3342     PostCrossThreadTask(
3343         *task_runner_, FROM_HERE,
3344         CrossThreadBindOnce(&RunCallbackAfterSwap,
3345                             MakeUnwrappingCrossThreadWeakHandle(widget_),
3346                             base::TimeTicks::Now(),
3347                             std::move(promise_callbacks_), frame_token_));
3348   }
3349
3350   DidNotSwapAction DidNotSwap(DidNotSwapReason reason,
3351                               base::TimeTicks timestamp) override {
3352     if (reason != DidNotSwapReason::SWAP_FAILS &&
3353         reason != DidNotSwapReason::COMMIT_NO_UPDATE) {
3354       return DidNotSwapAction::KEEP_ACTIVE;
3355     }
3356
3357     DidNotSwapAction action = DidNotSwapAction::BREAK_PROMISE;
3358     WebFrameWidgetImpl::PromiseCallbacks promise_callbacks_on_failure = {
3359         .swap_time_callback = std::move(promise_callbacks_.swap_time_callback),
3360         .presentation_time_callback =
3361             std::move(promise_callbacks_.presentation_time_callback)};
3362
3363 #if BUILDFLAG(IS_APPLE)
3364     if (reason == DidNotSwapReason::COMMIT_FAILS &&
3365         promise_callbacks_.core_animation_error_code_callback) {
3366       action = DidNotSwapAction::KEEP_ACTIVE;
3367     } else {
3368       promise_callbacks_on_failure.core_animation_error_code_callback =
3369           std::move(promise_callbacks_.core_animation_error_code_callback);
3370     }
3371 #endif
3372
3373     if (!promise_callbacks_on_failure.IsEmpty()) {
3374       ReportSwapAndPresentationFailureOnTaskRunner(
3375           task_runner_, std::move(promise_callbacks_on_failure), timestamp);
3376     }
3377     return action;
3378   }
3379
3380   int64_t GetTraceId() const override { return 0; }
3381
3382  private:
3383   static void RunCallbackAfterSwap(
3384       WebFrameWidgetImpl* widget,
3385       base::TimeTicks swap_time,
3386       WebFrameWidgetImpl::PromiseCallbacks callbacks,
3387       int frame_token) {
3388     // If the widget was collected or the widget wasn't collected yet, but
3389     // it was closed don't schedule a presentation callback.
3390     if (widget && widget->widget_base_) {
3391       widget->widget_base_->AddPresentationCallback(
3392           frame_token,
3393           WTF::BindOnce(&RunCallbackAfterPresentation,
3394                         std::move(callbacks.presentation_time_callback),
3395                         swap_time));
3396       ReportTime(std::move(callbacks.swap_time_callback), swap_time);
3397
3398 #if BUILDFLAG(IS_APPLE)
3399       if (callbacks.core_animation_error_code_callback) {
3400         widget->widget_base_->AddCoreAnimationErrorCodeCallback(
3401             frame_token,
3402             std::move(callbacks.core_animation_error_code_callback));
3403       }
3404 #endif
3405     } else {
3406       ReportTime(std::move(callbacks.swap_time_callback), swap_time);
3407       ReportTime(std::move(callbacks.presentation_time_callback), swap_time);
3408 #if BUILDFLAG(IS_APPLE)
3409       ReportErrorCode(std::move(callbacks.core_animation_error_code_callback),
3410                       gfx::kCALayerUnknownNoWidget);
3411 #endif
3412     }
3413   }
3414
3415   static void RunCallbackAfterPresentation(
3416       base::OnceCallback<void(base::TimeTicks)> presentation_time_callback,
3417       base::TimeTicks swap_time,
3418       base::TimeTicks presentation_time) {
3419     DCHECK(!swap_time.is_null());
3420     bool presentation_time_is_valid =
3421         !presentation_time.is_null() && (presentation_time > swap_time);
3422     UMA_HISTOGRAM_BOOLEAN("PageLoad.Internal.Renderer.PresentationTime.Valid",
3423                           presentation_time_is_valid);
3424     ReportTime(std::move(presentation_time_callback),
3425                presentation_time_is_valid ? presentation_time : swap_time);
3426   }
3427
3428   static void ReportTime(base::OnceCallback<void(base::TimeTicks)> callback,
3429                          base::TimeTicks time) {
3430     if (callback)
3431       std::move(callback).Run(time);
3432   }
3433
3434 #if BUILDFLAG(IS_APPLE)
3435   static void ReportErrorCode(
3436       base::OnceCallback<void(gfx::CALayerResult)> callback,
3437       gfx::CALayerResult error_code) {
3438     if (callback)
3439       std::move(callback).Run(error_code);
3440   }
3441 #endif
3442
3443   static void ReportSwapAndPresentationFailureOnTaskRunner(
3444       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
3445       WebFrameWidgetImpl::PromiseCallbacks callbacks,
3446       base::TimeTicks failure_time) {
3447     if (!task_runner->BelongsToCurrentThread()) {
3448       PostCrossThreadTask(
3449           *task_runner, FROM_HERE,
3450           CrossThreadBindOnce(&ReportSwapAndPresentationFailureOnTaskRunner,
3451                               task_runner, std::move(callbacks), failure_time));
3452       return;
3453     }
3454
3455     ReportTime(std::move(callbacks.swap_time_callback), failure_time);
3456     ReportTime(std::move(callbacks.presentation_time_callback), failure_time);
3457 #if BUILDFLAG(IS_APPLE)
3458     ReportErrorCode(std::move(callbacks.core_animation_error_code_callback),
3459                     gfx::kCALayerUnknownDidNotSwap);
3460 #endif
3461   }
3462
3463   WebFrameWidgetImpl::PromiseCallbacks promise_callbacks_;
3464
3465   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
3466   CrossThreadWeakHandle<WebFrameWidgetImpl> widget_;
3467   uint32_t frame_token_ = 0;
3468 };
3469
3470 void WebFrameWidgetImpl::NotifySwapAndPresentationTimeForTesting(
3471     PromiseCallbacks callbacks) {
3472   NotifySwapAndPresentationTime(std::move(callbacks));
3473 }
3474
3475 void WebFrameWidgetImpl::NotifyPresentationTimeInBlink(
3476     base::OnceCallback<void(base::TimeTicks)> presentation_callback) {
3477   NotifySwapAndPresentationTime(
3478       {.presentation_time_callback = std::move(presentation_callback)});
3479 }
3480
3481 void WebFrameWidgetImpl::NotifyPresentationTime(
3482     base::OnceCallback<void(base::TimeTicks)> presentation_callback) {
3483   NotifySwapAndPresentationTime(
3484       {.presentation_time_callback = std::move(presentation_callback)});
3485 }
3486
3487 #if BUILDFLAG(IS_APPLE)
3488 void WebFrameWidgetImpl::NotifyCoreAnimationErrorCode(
3489     base::OnceCallback<void(gfx::CALayerResult)>
3490         core_animation_error_code_callback) {
3491   NotifySwapAndPresentationTime(
3492       {.core_animation_error_code_callback =
3493            std::move(core_animation_error_code_callback)});
3494 }
3495 #endif
3496
3497 void WebFrameWidgetImpl::NotifySwapAndPresentationTime(
3498     PromiseCallbacks callbacks) {
3499   if (!View()->does_composite())
3500     return;
3501
3502   widget_base_->LayerTreeHost()->QueueSwapPromise(
3503       std::make_unique<ReportTimeSwapPromise>(std::move(callbacks),
3504                                               widget_base_->LayerTreeHost()
3505                                                   ->GetTaskRunnerProvider()
3506                                                   ->MainThreadTaskRunner(),
3507                                               this));
3508 }
3509
3510 void WebFrameWidgetImpl::WaitForDebuggerWhenShown() {
3511   local_root_->WaitForDebuggerWhenShown();
3512 }
3513
3514 void WebFrameWidgetImpl::SetTextZoomFactor(float text_zoom_factor) {
3515   local_root_->GetFrame()->SetTextZoomFactor(text_zoom_factor);
3516 }
3517
3518 float WebFrameWidgetImpl::TextZoomFactor() {
3519   return local_root_->GetFrame()->TextZoomFactor();
3520 }
3521
3522 void WebFrameWidgetImpl::SetMainFrameOverlayColor(SkColor color) {
3523   DCHECK(!local_root_->Parent());
3524   local_root_->GetFrame()->SetMainFrameColorOverlay(color);
3525 }
3526
3527 void WebFrameWidgetImpl::AddEditCommandForNextKeyEvent(const WebString& name,
3528                                                        const WebString& value) {
3529   edit_commands_.push_back(mojom::blink::EditCommand::New(name, value));
3530 }
3531
3532 bool WebFrameWidgetImpl::HandleCurrentKeyboardEvent() {
3533   if (edit_commands_.empty()) {
3534     return false;
3535   }
3536   WebLocalFrame* frame = FocusedWebLocalFrameInWidget();
3537   if (!frame)
3538     frame = local_root_;
3539   bool did_execute_command = false;
3540   // Executing an edit command can run JS and we can end up reassigning
3541   // `edit_commands_` so move it to a stack variable before iterating on it.
3542   Vector<mojom::blink::EditCommandPtr> edit_commands =
3543       std::move(edit_commands_);
3544   for (const auto& command : edit_commands) {
3545     // In gtk and cocoa, it's possible to bind multiple edit commands to one
3546     // key (but it's the exception). Once one edit command is not executed, it
3547     // seems safest to not execute the rest.
3548     if (!frame->ExecuteCommand(command->name, command->value))
3549       break;
3550     did_execute_command = true;
3551   }
3552
3553   return did_execute_command;
3554 }
3555
3556 void WebFrameWidgetImpl::ClearEditCommands() {
3557   edit_commands_ = Vector<mojom::blink::EditCommandPtr>();
3558 }
3559
3560 WebTextInputInfo WebFrameWidgetImpl::TextInputInfo() {
3561   WebInputMethodController* controller = GetActiveWebInputMethodController();
3562   if (!controller)
3563     return WebTextInputInfo();
3564   return controller->TextInputInfo();
3565 }
3566
3567 ui::mojom::blink::VirtualKeyboardVisibilityRequest
3568 WebFrameWidgetImpl::GetLastVirtualKeyboardVisibilityRequest() {
3569   WebInputMethodController* controller = GetActiveWebInputMethodController();
3570   if (!controller)
3571     return ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE;
3572   return controller->GetLastVirtualKeyboardVisibilityRequest();
3573 }
3574
3575 bool WebFrameWidgetImpl::ShouldSuppressKeyboardForFocusedElement() {
3576   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
3577   if (!focused_frame)
3578     return false;
3579   return focused_frame->ShouldSuppressKeyboardForFocusedElement();
3580 }
3581
3582 void WebFrameWidgetImpl::GetEditContextBoundsInWindow(
3583     absl::optional<gfx::Rect>* edit_context_control_bounds,
3584     absl::optional<gfx::Rect>* edit_context_selection_bounds) {
3585   WebInputMethodController* controller = GetActiveWebInputMethodController();
3586   if (!controller)
3587     return;
3588   gfx::Rect control_bounds;
3589   gfx::Rect selection_bounds;
3590   controller->GetLayoutBounds(&control_bounds, &selection_bounds);
3591   *edit_context_control_bounds =
3592       widget_base_->BlinkSpaceToEnclosedDIPs(control_bounds);
3593   if (controller->IsEditContextActive()) {
3594     *edit_context_selection_bounds =
3595         widget_base_->BlinkSpaceToEnclosedDIPs(selection_bounds);
3596   }
3597 }
3598
3599 int32_t WebFrameWidgetImpl::ComputeWebTextInputNextPreviousFlags() {
3600   WebInputMethodController* controller = GetActiveWebInputMethodController();
3601   if (!controller)
3602     return 0;
3603   return controller->ComputeWebTextInputNextPreviousFlags();
3604 }
3605
3606 void WebFrameWidgetImpl::ResetVirtualKeyboardVisibilityRequest() {
3607   WebInputMethodController* controller = GetActiveWebInputMethodController();
3608   if (!controller)
3609     return;
3610   controller->SetVirtualKeyboardVisibilityRequest(
3611       ui::mojom::blink::VirtualKeyboardVisibilityRequest::NONE);
3612   ;
3613 }
3614
3615 bool WebFrameWidgetImpl::GetSelectionBoundsInWindow(
3616     gfx::Rect* focus,
3617     gfx::Rect* anchor,
3618     gfx::Rect* bounding_box,
3619     base::i18n::TextDirection* focus_dir,
3620     base::i18n::TextDirection* anchor_dir,
3621     bool* is_anchor_first) {
3622   if (ShouldDispatchImeEventsToPlugin()) {
3623     // TODO(kinaba) http://crbug.com/101101
3624     // Current Pepper IME API does not handle selection bounds. So we simply
3625     // use the caret position as an empty range for now. It will be updated
3626     // after Pepper API equips features related to surrounding text retrieval.
3627     gfx::Rect pepper_caret_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
3628         GetFocusedPluginContainer()->GetPluginCaretBounds());
3629     if (pepper_caret_in_dips == *focus && pepper_caret_in_dips == *anchor)
3630       return false;
3631     *focus = pepper_caret_in_dips;
3632     *anchor = *focus;
3633     return true;
3634   }
3635   gfx::Rect focus_root_frame;
3636   gfx::Rect anchor_root_frame;
3637   gfx::Rect bounding_box_root_frame;
3638   CalculateSelectionBounds(focus_root_frame, anchor_root_frame,
3639                            &bounding_box_root_frame);
3640   gfx::Rect focus_rect_in_dips =
3641       widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(focus_root_frame));
3642   gfx::Rect anchor_rect_in_dips =
3643       widget_base_->BlinkSpaceToEnclosedDIPs(gfx::Rect(anchor_root_frame));
3644   gfx::Rect bounding_box_in_dips = widget_base_->BlinkSpaceToEnclosedDIPs(
3645       gfx::Rect(bounding_box_root_frame));
3646
3647   // if the bounds are the same return false.
3648   if (focus_rect_in_dips == *focus && anchor_rect_in_dips == *anchor)
3649     return false;
3650   *focus = focus_rect_in_dips;
3651   *anchor = anchor_rect_in_dips;
3652   *bounding_box = bounding_box_in_dips;
3653
3654   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
3655   if (!focused_frame)
3656     return true;
3657   focused_frame->SelectionTextDirection(*focus_dir, *anchor_dir);
3658   *is_anchor_first = focused_frame->IsSelectionAnchorFirst();
3659   return true;
3660 }
3661
3662 void WebFrameWidgetImpl::ClearTextInputState() {
3663   widget_base_->ClearTextInputState();
3664 }
3665
3666 bool WebFrameWidgetImpl::IsPasting() {
3667   return widget_base_->is_pasting();
3668 }
3669
3670 bool WebFrameWidgetImpl::HandlingSelectRange() {
3671   return widget_base_->handling_select_range();
3672 }
3673
3674 void WebFrameWidgetImpl::SetFocus(bool focus) {
3675   widget_base_->SetFocus(
3676       focus ? mojom::blink::FocusState::kFocused
3677             : View()->IsActive()
3678                   ? mojom::blink::FocusState::kNotFocusedAndActive
3679                   : mojom::blink::FocusState::kNotFocusedAndNotActive);
3680 }
3681
3682 bool WebFrameWidgetImpl::HasFocus() {
3683   return widget_base_->has_focus();
3684 }
3685
3686 void WebFrameWidgetImpl::UpdateTooltipUnderCursor(const String& tooltip_text,
3687                                                   TextDirection dir) {
3688   widget_base_->UpdateTooltipUnderCursor(tooltip_text, dir);
3689 }
3690
3691 void WebFrameWidgetImpl::UpdateTooltipFromKeyboard(const String& tooltip_text,
3692                                                    TextDirection dir,
3693                                                    const gfx::Rect& bounds) {
3694   widget_base_->UpdateTooltipFromKeyboard(tooltip_text, dir, bounds);
3695 }
3696
3697 void WebFrameWidgetImpl::ClearKeyboardTriggeredTooltip() {
3698   widget_base_->ClearKeyboardTriggeredTooltip();
3699 }
3700
3701 void WebFrameWidgetImpl::DidOverscroll(
3702     const gfx::Vector2dF& overscroll_delta,
3703     const gfx::Vector2dF& accumulated_overscroll,
3704     const gfx::PointF& position,
3705     const gfx::Vector2dF& velocity) {
3706 #if BUILDFLAG(IS_MAC)
3707   // On OSX the user can disable the elastic overscroll effect. If that's the
3708   // case, don't forward the overscroll notification.
3709   if (!widget_base_->LayerTreeHost()->GetSettings().enable_elastic_overscroll)
3710     return;
3711 #endif
3712
3713   cc::OverscrollBehavior overscroll_behavior =
3714       widget_base_->LayerTreeHost()->overscroll_behavior();
3715   if (!widget_base_->input_handler().DidOverscrollFromBlink(
3716           overscroll_delta, accumulated_overscroll, position, velocity,
3717           overscroll_behavior))
3718     return;
3719
3720   // If we're currently handling an event, stash the overscroll data such that
3721   // it can be bundled in the event ack.
3722   if (mojom::blink::WidgetInputHandlerHost* host =
3723           widget_base_->widget_input_handler_manager()
3724               ->GetWidgetInputHandlerHost()) {
3725     host->DidOverscroll(mojom::blink::DidOverscrollParams::New(
3726         accumulated_overscroll, overscroll_delta, velocity, position,
3727         overscroll_behavior));
3728   }
3729 }
3730
3731 void WebFrameWidgetImpl::InjectScrollbarGestureScroll(
3732     const gfx::Vector2dF& delta,
3733     ui::ScrollGranularity granularity,
3734     cc::ElementId scrollable_area_element_id,
3735     blink::WebInputEvent::Type injected_type) {
3736   // create a GestureScroll Event and post it to the compositor thread
3737   // TODO(crbug.com/1126098) use original input event's timestamp.
3738   // TODO(crbug.com/1082590) ensure continuity in scroll metrics collection
3739   base::TimeTicks now = base::TimeTicks::Now();
3740   std::unique_ptr<WebGestureEvent> gesture_event =
3741       WebGestureEvent::GenerateInjectedScrollbarGestureScroll(
3742           injected_type, now, gfx::PointF(0, 0), delta, granularity);
3743   if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
3744     gesture_event->data.scroll_begin.scrollable_area_element_id =
3745         scrollable_area_element_id.GetInternalValue();
3746     gesture_event->data.scroll_begin.main_thread_hit_tested_reasons =
3747         cc::MainThreadScrollingReason::kScrollbarScrolling;
3748   }
3749
3750   // Notifies TestWebFrameWidget of the injected event. Does nothing outside
3751   // of unit tests. This would happen in WidgetBase::QueueSyntheticEvent if
3752   // scroll unification were not enabled.
3753   WillQueueSyntheticEvent(
3754       WebCoalescedInputEvent(*gesture_event, ui::LatencyInfo()));
3755
3756   widget_base_->widget_input_handler_manager()
3757       ->DispatchScrollGestureToCompositor(std::move(gesture_event));
3758 }
3759
3760 void WebFrameWidgetImpl::DidChangeCursor(const ui::Cursor& cursor) {
3761   widget_base_->SetCursor(cursor);
3762 }
3763
3764 bool WebFrameWidgetImpl::SetComposition(
3765     const String& text,
3766     const Vector<ui::ImeTextSpan>& ime_text_spans,
3767     const gfx::Range& replacement_range,
3768     int selection_start,
3769     int selection_end) {
3770   WebInputMethodController* controller = GetActiveWebInputMethodController();
3771   if (!controller)
3772     return false;
3773
3774   return controller->SetComposition(
3775       text, ime_text_spans,
3776       replacement_range.IsValid()
3777           ? WebRange(base::checked_cast<int>(replacement_range.start()),
3778                      base::checked_cast<int>(replacement_range.length()))
3779           : WebRange(),
3780       selection_start, selection_end);
3781 }
3782
3783 void WebFrameWidgetImpl::CommitText(
3784     const String& text,
3785     const Vector<ui::ImeTextSpan>& ime_text_spans,
3786     const gfx::Range& replacement_range,
3787     int relative_cursor_pos) {
3788   WebInputMethodController* controller = GetActiveWebInputMethodController();
3789   if (!controller)
3790     return;
3791   controller->CommitText(
3792       text, ime_text_spans,
3793       replacement_range.IsValid()
3794           ? WebRange(base::checked_cast<int>(replacement_range.start()),
3795                      base::checked_cast<int>(replacement_range.length()))
3796           : WebRange(),
3797       relative_cursor_pos);
3798 }
3799
3800 void WebFrameWidgetImpl::FinishComposingText(bool keep_selection) {
3801   WebInputMethodController* controller = GetActiveWebInputMethodController();
3802   if (!controller)
3803     return;
3804   controller->FinishComposingText(
3805       keep_selection ? WebInputMethodController::kKeepSelection
3806                      : WebInputMethodController::kDoNotKeepSelection);
3807 }
3808
3809 bool WebFrameWidgetImpl::IsProvisional() {
3810   return LocalRoot()->IsProvisional();
3811 }
3812
3813 cc::ElementId WebFrameWidgetImpl::GetScrollableContainerIdAt(
3814     const gfx::PointF& point) {
3815   gfx::PointF hit_test_point = point;
3816   LocalFrameView* view = LocalRootImpl()->GetFrameView();
3817   hit_test_point.Scale(1 / view->InputEventsScaleFactor());
3818   return HitTestResultForRootFramePos(hit_test_point).GetScrollableContainer();
3819 }
3820
3821 bool WebFrameWidgetImpl::ShouldHandleImeEvents() {
3822   if (ForMainFrame()) {
3823     return HasFocus();
3824   } else {
3825     // TODO(ekaramad): main frame widget returns true only if it has focus.
3826     // We track page focus in all WebViews on the page but the WebFrameWidgets
3827     // corresponding to child local roots do not get the update. For now, this
3828     // method returns true when the WebFrameWidget is for a child local frame,
3829     // i.e., IME events will be processed regardless of page focus. We should
3830     // revisit this after page focus for OOPIFs has been fully resolved
3831     // (https://crbug.com/689777).
3832     return LocalRootImpl();
3833   }
3834 }
3835
3836 void WebFrameWidgetImpl::SetEditCommandsForNextKeyEvent(
3837     Vector<mojom::blink::EditCommandPtr> edit_commands) {
3838   edit_commands_ = std::move(edit_commands);
3839 }
3840
3841 void WebFrameWidgetImpl::FocusChangeComplete() {
3842   blink::WebLocalFrame* focused = LocalRoot()->View()->FocusedFrame();
3843
3844   if (focused && focused->AutofillClient())
3845     focused->AutofillClient()->DidCompleteFocusChangeInFrame();
3846 }
3847
3848 void WebFrameWidgetImpl::ShowVirtualKeyboardOnElementFocus() {
3849   widget_base_->ShowVirtualKeyboardOnElementFocus();
3850 }
3851
3852 #if BUILDFLAG(IS_EFL)
3853 void WebFrameWidgetImpl::DidUpdateTextOfFocusedElementByNonUserInput() {
3854   widget_base_->DidUpdateTextOfFocusedElementByNonUserInput();
3855 }
3856 #endif
3857 void WebFrameWidgetImpl::ProcessTouchAction(WebTouchAction touch_action) {
3858   widget_base_->ProcessTouchAction(touch_action);
3859 }
3860
3861 void WebFrameWidgetImpl::SetPanAction(mojom::blink::PanAction pan_action) {
3862   if (!widget_base_->widget_input_handler_manager())
3863     return;
3864   mojom::blink::WidgetInputHandlerHost* host =
3865       widget_base_->widget_input_handler_manager()->GetWidgetInputHandlerHost();
3866   if (!host)
3867     return;
3868   host->SetPanAction(pan_action);
3869 }
3870
3871 void WebFrameWidgetImpl::DidHandleGestureEvent(const WebGestureEvent& event) {
3872 #if BUILDFLAG(IS_ANDROID) || defined(USE_AURA) || BUILDFLAG(IS_IOS)
3873   if (event.GetType() == WebInputEvent::Type::kGestureTap) {
3874     widget_base_->ShowVirtualKeyboard();
3875   } else if (event.GetType() == WebInputEvent::Type::kGestureLongPress) {
3876     WebInputMethodController* controller = GetActiveWebInputMethodController();
3877     if (!controller || controller->TextInputInfo().value.IsEmpty())
3878       widget_base_->UpdateTextInputState();
3879     else
3880       widget_base_->ShowVirtualKeyboard();
3881   }
3882 #elif BUILDFLAG(IS_EFL)
3883   if (!HasFocus())
3884     return;
3885
3886   if ((event.GetType() == WebInputEvent::Type::kGestureTap) ||
3887       (event.GetType() == WebInputEvent::Type::kGestureLongPress)) {
3888     widget_base_->ShowVirtualKeyboard();
3889   }
3890 #endif
3891 }
3892
3893 void WebFrameWidgetImpl::SetHasPointerRawUpdateEventHandlers(
3894     bool has_handlers) {
3895   widget_base_->widget_input_handler_manager()
3896       ->input_event_queue()
3897       ->HasPointerRawUpdateEventHandlers(has_handlers);
3898 }
3899
3900 void WebFrameWidgetImpl::SetNeedsLowLatencyInput(bool needs_low_latency) {
3901   widget_base_->widget_input_handler_manager()
3902       ->input_event_queue()
3903       ->SetNeedsLowLatency(needs_low_latency);
3904 }
3905
3906 void WebFrameWidgetImpl::RequestUnbufferedInputEvents() {
3907   widget_base_->widget_input_handler_manager()
3908       ->input_event_queue()
3909       ->RequestUnbufferedInputEvents();
3910 }
3911
3912 void WebFrameWidgetImpl::SetNeedsUnbufferedInputForDebugger(bool unbuffered) {
3913   widget_base_->widget_input_handler_manager()
3914       ->input_event_queue()
3915       ->SetNeedsUnbufferedInputForDebugger(unbuffered);
3916 }
3917
3918 void WebFrameWidgetImpl::DidNavigate() {
3919   // The input handler wants to know about navigation so that it can
3920   // suppress input until the newly navigated page has a committed frame.
3921   // It also resets the state for UMA reporting of input arrival with respect
3922   // to document lifecycle.
3923   if (!widget_base_->widget_input_handler_manager())
3924     return;
3925   widget_base_->widget_input_handler_manager()->DidNavigate();
3926 }
3927
3928 void WebFrameWidgetImpl::FlushInputForTesting(base::OnceClosure done_callback) {
3929   widget_base_->widget_input_handler_manager()->FlushEventQueuesForTesting(
3930       std::move(done_callback));
3931 }
3932
3933 void WebFrameWidgetImpl::SetMouseCapture(bool capture) {
3934   if (mojom::blink::WidgetInputHandlerHost* host =
3935           widget_base_->widget_input_handler_manager()
3936               ->GetWidgetInputHandlerHost()) {
3937     host->SetMouseCapture(capture);
3938   }
3939 }
3940
3941 gfx::Range WebFrameWidgetImpl::CompositionRange() {
3942   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
3943   if (!focused_frame || ShouldDispatchImeEventsToPlugin())
3944     return gfx::Range::InvalidRange();
3945
3946   blink::WebInputMethodController* controller =
3947       focused_frame->GetInputMethodController();
3948   WebRange web_range = controller->CompositionRange();
3949   if (web_range.IsNull())
3950     return gfx::Range::InvalidRange();
3951   return gfx::Range(web_range.StartOffset(), web_range.EndOffset());
3952 }
3953
3954 void WebFrameWidgetImpl::GetCompositionCharacterBoundsInWindow(
3955     Vector<gfx::Rect>* bounds_in_dips) {
3956   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
3957   if (!focused_frame || ShouldDispatchImeEventsToPlugin())
3958     return;
3959   blink::WebInputMethodController* controller =
3960       focused_frame->GetInputMethodController();
3961   blink::WebVector<gfx::Rect> bounds_from_blink;
3962   if (!controller->GetCompositionCharacterBounds(bounds_from_blink))
3963     return;
3964
3965   for (auto& rect : bounds_from_blink) {
3966     bounds_in_dips->push_back(widget_base_->BlinkSpaceToEnclosedDIPs(rect));
3967   }
3968 }
3969
3970 namespace {
3971
3972 void GetLineBounds(Vector<gfx::QuadF>& line_quads,
3973                    TextControlInnerEditorElement* inner_editor) {
3974   for (const Node& node : NodeTraversal::DescendantsOf(*inner_editor)) {
3975     if (!node.GetLayoutObject() || !node.GetLayoutObject()->IsText()) {
3976       continue;
3977     }
3978     node.GetLayoutObject()->AbsoluteQuads(line_quads,
3979                                           kApplyRemoteMainFrameTransform);
3980   }
3981 }
3982
3983 }  // namespace
3984
3985 Vector<gfx::Rect> WebFrameWidgetImpl::CalculateVisibleLineBoundsOnScreen() {
3986   Vector<gfx::Rect> bounds_in_dips;
3987   Element* focused_element = FocusedElement();
3988   if (!focused_element) {
3989     return bounds_in_dips;
3990   }
3991   TextControlElement* text_control = ToTextControlOrNull(focused_element);
3992   if (!text_control || text_control->IsDisabledOrReadOnly() ||
3993       text_control->Value().empty() || !text_control->GetLayoutObject()) {
3994     return bounds_in_dips;
3995   }
3996
3997   Vector<gfx::QuadF> bounds_from_blink;
3998   GetLineBounds(bounds_from_blink, text_control->InnerEditorElement());
3999
4000   gfx::Rect screen = GetPage()->GetVisualViewport().VisibleContentRect();
4001   for (auto& quad : bounds_from_blink) {
4002     gfx::Rect bounding_box = gfx::ToRoundedRect(quad.BoundingBox());
4003     bounding_box.Intersect(screen);
4004     if (bounding_box.IsEmpty()) {
4005       continue;
4006     }
4007
4008     bounds_in_dips.push_back(
4009         focused_element->GetLayoutObject()->GetFrameView()->FrameToScreen(
4010             bounding_box));
4011   }
4012   return bounds_in_dips;
4013 }
4014
4015 Vector<gfx::Rect>& WebFrameWidgetImpl::GetVisibleLineBoundsOnScreen() {
4016   return input_visible_line_bounds_;
4017 }
4018
4019 void WebFrameWidgetImpl::UpdateLineBounds() {
4020   Vector<gfx::Rect> line_bounds = CalculateVisibleLineBoundsOnScreen();
4021   if (line_bounds == input_visible_line_bounds_) {
4022     return;
4023   }
4024   input_visible_line_bounds_.swap(line_bounds);
4025   if (mojom::blink::WidgetInputHandlerHost* host =
4026           widget_base_->widget_input_handler_manager()
4027               ->GetWidgetInputHandlerHost()) {
4028     host->ImeCompositionRangeChanged(gfx::Range::InvalidRange(), absl::nullopt,
4029                                      input_visible_line_bounds_);
4030   }
4031 }
4032
4033 void WebFrameWidgetImpl::AddImeTextSpansToExistingText(
4034     uint32_t start,
4035     uint32_t end,
4036     const Vector<ui::ImeTextSpan>& ime_text_spans) {
4037   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4038   if (!focused_frame)
4039     return;
4040   focused_frame->AddImeTextSpansToExistingText(ime_text_spans, start, end);
4041 }
4042
4043 Vector<ui::mojom::blink::ImeTextSpanInfoPtr>
4044 WebFrameWidgetImpl::GetImeTextSpansInfo(
4045     const WebVector<ui::ImeTextSpan>& ime_text_spans) {
4046   auto* focused_frame = FocusedWebLocalFrameInWidget();
4047   if (!focused_frame)
4048     return Vector<ui::mojom::blink::ImeTextSpanInfoPtr>();
4049
4050   Vector<ui::mojom::blink::ImeTextSpanInfoPtr> ime_text_spans_info;
4051
4052   for (const auto& ime_text_span : ime_text_spans) {
4053     gfx::Rect rect;
4054     auto length = base::checked_cast<wtf_size_t>(ime_text_span.end_offset -
4055                                                  ime_text_span.start_offset);
4056     focused_frame->FirstRectForCharacterRange(
4057         base::checked_cast<wtf_size_t>(ime_text_span.start_offset), length,
4058         rect);
4059
4060     ime_text_spans_info.push_back(ui::mojom::blink::ImeTextSpanInfo::New(
4061         ime_text_span, widget_base_->BlinkSpaceToEnclosedDIPs(rect)));
4062   }
4063   return ime_text_spans_info;
4064 }
4065
4066 void WebFrameWidgetImpl::ClearImeTextSpansByType(uint32_t start,
4067                                                  uint32_t end,
4068                                                  ui::ImeTextSpan::Type type) {
4069   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4070   if (!focused_frame)
4071     return;
4072   focused_frame->ClearImeTextSpansByType(type, start, end);
4073 }
4074
4075 void WebFrameWidgetImpl::SetCompositionFromExistingText(
4076     int32_t start,
4077     int32_t end,
4078     const Vector<ui::ImeTextSpan>& ime_text_spans) {
4079   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4080   if (!focused_frame)
4081     return;
4082   focused_frame->SetCompositionFromExistingText(start, end, ime_text_spans);
4083 }
4084
4085 void WebFrameWidgetImpl::ExtendSelectionAndDelete(int32_t before,
4086                                                   int32_t after) {
4087   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4088   if (!focused_frame)
4089     return;
4090   focused_frame->ExtendSelectionAndDelete(before, after);
4091 }
4092
4093 void WebFrameWidgetImpl::ExtendSelectionAndReplace(
4094     uint32_t before,
4095     uint32_t after,
4096     const String& replacement_text) {
4097   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4098   if (!focused_frame) {
4099     return;
4100   }
4101   focused_frame->ExtendSelectionAndReplace(base::checked_cast<int>(before),
4102                                            base::checked_cast<int>(after),
4103                                            replacement_text);
4104 }
4105
4106 void WebFrameWidgetImpl::DeleteSurroundingText(int32_t before, int32_t after) {
4107   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4108   if (!focused_frame)
4109     return;
4110   focused_frame->DeleteSurroundingText(before, after);
4111 }
4112
4113 void WebFrameWidgetImpl::DeleteSurroundingTextInCodePoints(int32_t before,
4114                                                            int32_t after) {
4115   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4116   if (!focused_frame)
4117     return;
4118   focused_frame->DeleteSurroundingTextInCodePoints(before, after);
4119 }
4120
4121 void WebFrameWidgetImpl::SetEditableSelectionOffsets(int32_t start,
4122                                                      int32_t end) {
4123   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4124   if (!focused_frame)
4125     return;
4126   focused_frame->SetEditableSelectionOffsets(start, end);
4127 }
4128
4129 void WebFrameWidgetImpl::ExecuteEditCommand(const String& command,
4130                                             const String& value) {
4131   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4132   if (!focused_frame)
4133     return;
4134   focused_frame->ExecuteCommand(command, value);
4135 }
4136
4137 void WebFrameWidgetImpl::Undo() {
4138   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4139   if (!focused_frame)
4140     return;
4141   focused_frame->ExecuteCommand(WebString::FromLatin1("Undo"));
4142 }
4143
4144 void WebFrameWidgetImpl::Redo() {
4145   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4146   if (!focused_frame)
4147     return;
4148   focused_frame->ExecuteCommand(WebString::FromLatin1("Redo"));
4149 }
4150
4151 void WebFrameWidgetImpl::Cut() {
4152   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4153   if (!focused_frame)
4154     return;
4155   focused_frame->ExecuteCommand(WebString::FromLatin1("Cut"));
4156 }
4157
4158 void WebFrameWidgetImpl::Copy() {
4159   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4160   if (!focused_frame)
4161     return;
4162   focused_frame->ExecuteCommand(WebString::FromLatin1("Copy"));
4163 }
4164
4165 void WebFrameWidgetImpl::CopyToFindPboard() {
4166 #if BUILDFLAG(IS_MAC)
4167   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4168   if (!focused_frame)
4169     return;
4170   To<WebLocalFrameImpl>(focused_frame)->CopyToFindPboard();
4171 #endif
4172 }
4173
4174 void WebFrameWidgetImpl::CenterSelection() {
4175   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4176   if (!focused_frame) {
4177     return;
4178   }
4179   To<WebLocalFrameImpl>(focused_frame)->CenterSelection();
4180 }
4181
4182 void WebFrameWidgetImpl::Paste() {
4183   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4184   if (!focused_frame)
4185     return;
4186   focused_frame->ExecuteCommand(WebString::FromLatin1("Paste"));
4187 }
4188
4189 void WebFrameWidgetImpl::PasteAndMatchStyle() {
4190   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4191   if (!focused_frame)
4192     return;
4193   focused_frame->ExecuteCommand(WebString::FromLatin1("PasteAndMatchStyle"));
4194 }
4195
4196 void WebFrameWidgetImpl::Delete() {
4197   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4198   if (!focused_frame)
4199     return;
4200   focused_frame->ExecuteCommand(WebString::FromLatin1("Delete"));
4201 }
4202
4203 void WebFrameWidgetImpl::SelectAll() {
4204   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4205   if (!focused_frame)
4206     return;
4207   focused_frame->ExecuteCommand(WebString::FromLatin1("SelectAll"));
4208 }
4209
4210 void WebFrameWidgetImpl::CollapseSelection() {
4211   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4212   if (!focused_frame)
4213     return;
4214   const blink::WebRange& range =
4215       focused_frame->GetInputMethodController()->GetSelectionOffsets();
4216   if (range.IsNull())
4217     return;
4218
4219   focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0),
4220                              blink::WebLocalFrame::kHideSelectionHandle,
4221                              mojom::blink::SelectionMenuBehavior::kHide,
4222                              blink::WebLocalFrame::kSelectionDoNotSetFocus);
4223 }
4224
4225 void WebFrameWidgetImpl::Replace(const String& word) {
4226   auto* focused_frame = FocusedWebLocalFrameInWidget();
4227   if (!focused_frame)
4228     return;
4229   if (!focused_frame->HasSelection()) {
4230     focused_frame->SelectAroundCaret(mojom::blink::SelectionGranularity::kWord,
4231                                      /*should_show_handle=*/false,
4232                                      /*should_show_context_menu=*/false);
4233   }
4234   focused_frame->ReplaceSelection(word);
4235   // If the resulting selection is not actually a change in selection, we do not
4236   // need to explicitly notify about the selection change.
4237   focused_frame->Client()->SyncSelectionIfRequired(
4238       blink::SyncCondition::kNotForced);
4239 }
4240
4241 void WebFrameWidgetImpl::ReplaceMisspelling(const String& word) {
4242   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4243   if (!focused_frame)
4244     return;
4245   if (!focused_frame->HasSelection())
4246     return;
4247   focused_frame->ReplaceMisspelledRange(word);
4248 }
4249
4250 void WebFrameWidgetImpl::SelectRange(const gfx::Point& base_in_dips,
4251                                      const gfx::Point& extent_in_dips) {
4252   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4253   if (!focused_frame)
4254     return;
4255   focused_frame->SelectRange(
4256       widget_base_->DIPsToRoundedBlinkSpace(base_in_dips),
4257       widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
4258 }
4259
4260 void WebFrameWidgetImpl::AdjustSelectionByCharacterOffset(
4261     int32_t start,
4262     int32_t end,
4263     mojom::blink::SelectionMenuBehavior selection_menu_behavior) {
4264   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4265   if (!focused_frame)
4266     return;
4267   blink::WebRange range =
4268       focused_frame->GetInputMethodController()->GetSelectionOffsets();
4269   if (range.IsNull())
4270     return;
4271
4272   // Sanity checks to disallow empty and out of range selections.
4273   if (start - end > range.length() || range.StartOffset() + start < 0)
4274     return;
4275
4276   // A negative adjust amount moves the selection towards the beginning of
4277   // the document, a positive amount moves the selection towards the end of
4278   // the document.
4279   focused_frame->SelectRange(blink::WebRange(range.StartOffset() + start,
4280                                              range.length() + end - start),
4281                              blink::WebLocalFrame::kPreserveHandleVisibility,
4282                              selection_menu_behavior,
4283                              blink::WebLocalFrame::kSelectionSetFocus);
4284 }
4285
4286 void WebFrameWidgetImpl::MoveRangeSelectionExtent(
4287     const gfx::Point& extent_in_dips) {
4288   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4289   if (!focused_frame)
4290     return;
4291   focused_frame->MoveRangeSelectionExtent(
4292       widget_base_->DIPsToRoundedBlinkSpace(extent_in_dips));
4293 }
4294
4295 void WebFrameWidgetImpl::ScrollFocusedEditableNodeIntoView() {
4296   WebLocalFrameImpl* local_frame = FocusedWebLocalFrameInWidget();
4297   if (!local_frame)
4298     return;
4299
4300   // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
4301   // on OOPIFs. Since we are starting a new scroll operation now, call
4302   // DidChangeVisibleViewport to ensure that we don't assume the element
4303   // is already in view and ignore the scroll.
4304   local_frame->ResetHasScrolledFocusedEditableIntoView();
4305   local_frame->ScrollFocusedEditableElementIntoView();
4306 }
4307
4308 void WebFrameWidgetImpl::WaitForPageScaleAnimationForTesting(
4309     WaitForPageScaleAnimationForTestingCallback callback) {
4310   DCHECK(ForMainFrame());
4311   DCHECK(LocalRootImpl()->GetFrame()->IsOutermostMainFrame());
4312   page_scale_animation_for_testing_callback_ = std::move(callback);
4313 }
4314
4315 void WebFrameWidgetImpl::ZoomToFindInPageRect(
4316     const gfx::Rect& rect_in_root_frame) {
4317   if (ForMainFrame()) {
4318     View()->ZoomToFindInPageRect(rect_in_root_frame);
4319   } else {
4320     GetAssociatedFrameWidgetHost()->ZoomToFindInPageRectInMainFrame(
4321         rect_in_root_frame);
4322   }
4323 }
4324
4325 void WebFrameWidgetImpl::MoveCaret(const gfx::Point& point_in_dips) {
4326   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4327   if (!focused_frame)
4328     return;
4329   focused_frame->MoveCaretSelection(
4330       widget_base_->DIPsToRoundedBlinkSpace(point_in_dips));
4331 }
4332
4333 void WebFrameWidgetImpl::SelectAroundCaret(
4334     mojom::blink::SelectionGranularity granularity,
4335     bool should_show_handle,
4336     bool should_show_context_menu,
4337     SelectAroundCaretCallback callback) {
4338   auto* focused_frame = FocusedWebLocalFrameInWidget();
4339   if (!focused_frame) {
4340     std::move(callback).Run(std::move(nullptr));
4341     return;
4342   }
4343
4344   int extended_start_adjust = 0;
4345   int extended_end_adjust = 0;
4346   int word_start_adjust = 0;
4347   int word_end_adjust = 0;
4348   blink::WebRange initial_range = focused_frame->SelectionRange();
4349   SetHandlingInputEvent(true);
4350
4351   if (initial_range.IsNull()) {
4352     std::move(callback).Run(std::move(nullptr));
4353     return;
4354   }
4355
4356   // If the requested granularity is not word, still calculate the hypothetical
4357   // word selection offsets. This is needed for contextual search to support
4358   // legacy semantics for the word that was tapped.
4359   blink::WebRange word_range;
4360   if (granularity != mojom::blink::SelectionGranularity::kWord) {
4361     word_range = focused_frame->GetWordSelectionRangeAroundCaret();
4362   }
4363
4364   // Select around the caret at the specified |granularity|.
4365   if (!focused_frame->SelectAroundCaret(granularity, should_show_handle,
4366                                         should_show_context_menu)) {
4367     std::move(callback).Run(std::move(nullptr));
4368     return;
4369   }
4370
4371   blink::WebRange extended_range = focused_frame->SelectionRange();
4372   DCHECK(!extended_range.IsNull());
4373   extended_start_adjust =
4374       extended_range.StartOffset() - initial_range.StartOffset();
4375   extended_end_adjust = extended_range.EndOffset() - initial_range.EndOffset();
4376
4377   if (granularity == mojom::blink::SelectionGranularity::kWord) {
4378     // Since the requested granularity was word, simply set the word offset
4379     // to be the same as the extended offset values.
4380     word_start_adjust = extended_start_adjust;
4381     word_end_adjust = extended_end_adjust;
4382   } else {
4383     // Calculate the word offset compared to the initial selection (caret).
4384     DCHECK(!word_range.IsNull());
4385     word_start_adjust = word_range.StartOffset() - initial_range.StartOffset();
4386     word_end_adjust = word_range.EndOffset() - initial_range.EndOffset();
4387   }
4388
4389   SetHandlingInputEvent(false);
4390   auto result = mojom::blink::SelectAroundCaretResult::New();
4391   result->extended_start_adjust = extended_start_adjust;
4392   result->extended_end_adjust = extended_end_adjust;
4393   result->word_start_adjust = word_start_adjust;
4394   result->word_end_adjust = word_end_adjust;
4395   std::move(callback).Run(std::move(result));
4396 }
4397
4398 void WebFrameWidgetImpl::ForEachRemoteFrameControlledByWidget(
4399     base::FunctionRef<void(RemoteFrame*)> callback) {
4400   ForEachRemoteFrameChildrenControlledByWidget(local_root_->GetFrame(),
4401                                                callback);
4402 }
4403
4404 void WebFrameWidgetImpl::CalculateSelectionBounds(
4405     gfx::Rect& anchor_root_frame,
4406     gfx::Rect& focus_root_frame,
4407     gfx::Rect* bounding_box_in_root_frame) {
4408   const LocalFrame* local_frame = FocusedLocalFrameInWidget();
4409   if (!local_frame)
4410     return;
4411
4412   gfx::Rect anchor;
4413   gfx::Rect focus;
4414   auto& selection = local_frame->Selection();
4415   if (!selection.ComputeAbsoluteBounds(anchor, focus))
4416     return;
4417
4418   // Apply the visual viewport for main frames this will apply the page scale.
4419   // For subframes it will just be a 1:1 transformation and the browser
4420   // will then apply later transformations to these rects.
4421   VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
4422   anchor_root_frame = visual_viewport.RootFrameToViewport(
4423       local_frame->View()->ConvertToRootFrame(anchor));
4424   focus_root_frame = visual_viewport.RootFrameToViewport(
4425       local_frame->View()->ConvertToRootFrame(focus));
4426
4427   // Calculate the bounding box of the selection area.
4428   if (bounding_box_in_root_frame) {
4429     Range* range =
4430         CreateRange(selection.GetSelectionInDOMTree().ComputeRange());
4431     const gfx::Rect bounding_box = ToEnclosingRect(range->BoundingRect());
4432     range->Dispose();
4433     *bounding_box_in_root_frame = visual_viewport.RootFrameToViewport(
4434         local_frame->View()->ConvertToRootFrame(bounding_box));
4435   }
4436 }
4437
4438 const viz::LocalSurfaceId& WebFrameWidgetImpl::LocalSurfaceIdFromParent() {
4439   return widget_base_->local_surface_id_from_parent();
4440 }
4441
4442 cc::LayerTreeHost* WebFrameWidgetImpl::LayerTreeHost() {
4443   return widget_base_->LayerTreeHost();
4444 }
4445
4446 cc::LayerTreeHost* WebFrameWidgetImpl::LayerTreeHostForTesting() const {
4447   return widget_base_->LayerTreeHost();
4448 }
4449
4450 ScreenMetricsEmulator* WebFrameWidgetImpl::DeviceEmulator() {
4451   return device_emulator_.Get();
4452 }
4453
4454 bool WebFrameWidgetImpl::AutoResizeMode() {
4455   return View()->AutoResizeMode();
4456 }
4457
4458 void WebFrameWidgetImpl::SetScreenMetricsEmulationParameters(
4459     bool enabled,
4460     const DeviceEmulationParams& params) {
4461   if (enabled)
4462     View()->ActivateDevToolsTransform(params);
4463   else
4464     View()->DeactivateDevToolsTransform();
4465 }
4466
4467 void WebFrameWidgetImpl::SetScreenInfoAndSize(
4468     const display::ScreenInfos& screen_infos,
4469     const gfx::Size& widget_size_in_dips,
4470     const gfx::Size& visible_viewport_size_in_dips) {
4471   // Emulation happens on regular main frames which don't use auto-resize mode.
4472   DCHECK(!AutoResizeMode());
4473
4474   UpdateScreenInfo(screen_infos);
4475   widget_base_->SetVisibleViewportSizeInDIPs(visible_viewport_size_in_dips);
4476   Resize(widget_base_->DIPsToCeiledBlinkSpace(widget_size_in_dips));
4477 }
4478
4479 float WebFrameWidgetImpl::GetCompositingScaleFactor() {
4480   return compositing_scale_factor_;
4481 }
4482
4483 const cc::LayerTreeDebugState& WebFrameWidgetImpl::GetLayerTreeDebugState() {
4484   return widget_base_->LayerTreeHost()->GetDebugState();
4485 }
4486
4487 void WebFrameWidgetImpl::SetLayerTreeDebugState(
4488     const cc::LayerTreeDebugState& state) {
4489   widget_base_->LayerTreeHost()->SetDebugState(state);
4490 }
4491
4492 void WebFrameWidgetImpl::NotifyCompositingScaleFactorChanged(
4493     float compositing_scale_factor) {
4494   compositing_scale_factor_ = compositing_scale_factor;
4495
4496   // Update the scale factor for remote frames which in turn depends on the
4497   // compositing scale factor set in the widget.
4498   ForEachRemoteFrameControlledByWidget([](RemoteFrame* remote_frame) {
4499     // Only RemoteFrames with a local parent frame participate in compositing
4500     // (and thus have a view).
4501     if (remote_frame->View())
4502       remote_frame->View()->UpdateCompositingScaleFactor();
4503   });
4504 }
4505
4506 void WebFrameWidgetImpl::NotifyPageScaleFactorChanged(
4507     float page_scale_factor,
4508     bool is_pinch_gesture_active) {
4509   // Store the value to give to any new RemoteFrame that will be created as a
4510   // descendant of this widget.
4511   page_scale_factor_in_mainframe_ = page_scale_factor;
4512   is_pinch_gesture_active_in_mainframe_ = is_pinch_gesture_active;
4513   // Push the page scale factor down to any child RemoteFrames.
4514   // TODO(danakj): This ends up setting the page scale factor in the
4515   // RenderWidgetHost of the child WebFrameWidgetImpl, so that it can bounce
4516   // the value down to its WebFrameWidgetImpl. Since this is essentially a
4517   // global value per-page, we could instead store it once in the browser
4518   // (such as in RenderViewHost) and distribute it to each WebFrameWidgetImpl
4519   // from there.
4520   ForEachRemoteFrameControlledByWidget(
4521       [page_scale_factor, is_pinch_gesture_active](RemoteFrame* remote_frame) {
4522         remote_frame->PageScaleFactorChanged(page_scale_factor,
4523                                              is_pinch_gesture_active);
4524       });
4525 }
4526
4527 void WebFrameWidgetImpl::SetPageScaleStateAndLimits(
4528     float page_scale_factor,
4529     bool is_pinch_gesture_active,
4530     float minimum,
4531     float maximum) {
4532   widget_base_->LayerTreeHost()->SetPageScaleFactorAndLimits(page_scale_factor,
4533                                                              minimum, maximum);
4534
4535   // Only propagate page scale from the main frame.
4536   if (ForMainFrame()) {
4537     // If page scale hasn't changed, then just return without notifying
4538     // the remote frames.
4539     if (page_scale_factor == page_scale_factor_in_mainframe_ &&
4540         is_pinch_gesture_active == is_pinch_gesture_active_in_mainframe_) {
4541       return;
4542     }
4543
4544     NotifyPageScaleFactorChanged(page_scale_factor, is_pinch_gesture_active);
4545   }
4546 }
4547
4548 void WebFrameWidgetImpl::UpdateViewportDescription(
4549     const ViewportDescription& viewport) {
4550   bool is_device_width = viewport.max_width.IsDeviceWidth();
4551   bool is_zoom_at_least_one = viewport.zoom >= 1.0 || viewport.min_zoom >= 1;
4552   widget_base_->LayerTreeHost()->UpdateViewportIsMobileOptimized(
4553       (is_device_width && is_zoom_at_least_one) ||
4554       (is_device_width && !viewport.zoom_is_explicit) ||
4555       (viewport.max_width.IsAuto() && is_zoom_at_least_one));
4556 }
4557
4558 bool WebFrameWidgetImpl::UpdateScreenRects(
4559     const gfx::Rect& widget_screen_rect,
4560     const gfx::Rect& window_screen_rect) {
4561   if (!device_emulator_)
4562     return false;
4563   device_emulator_->OnUpdateScreenRects(widget_screen_rect, window_screen_rect);
4564   return true;
4565 }
4566
4567 #if BUILDFLAG(IS_EFL)
4568 void WebFrameWidgetImpl::GetContentSnapshot(const gfx::Rect& snapshot_rect,
4569                                             float page_scale_factor,
4570                                             SkBitmap* snapshot) {
4571   WebView* view = View();
4572   if (!view || !view->MainFrame()) {
4573     LOG(ERROR) << "SoftBitmap:Capture Invalid view";
4574     return;
4575   }
4576
4577   if (view->HasAcceleratedCanvasWithinViewport()) {
4578     LOG(ERROR)
4579         << "SoftBitmap:Capture avoided for WebGl/Cavas2D content on viewport";
4580     return;
4581   }
4582
4583   if (view->MainFrameWidget()->Size().IsEmpty()) {
4584     LOG(ERROR) << "SoftBitmap:Capture Invalid size";
4585     return;
4586   }
4587
4588   snapshot->allocPixels(SkImageInfo::MakeN32Premul(snapshot_rect.width(),
4589                                                    snapshot_rect.height()));
4590   SkCanvas canvas(*snapshot);
4591   if (!view->PaintSoftBitmap(&canvas, snapshot_rect)) {
4592     LOG(ERROR) << "SoftBitmap:Capture PaintSoftBitmap failed";
4593     return;
4594   }
4595
4596   *snapshot = skia::ImageOperations::Resize(
4597       *snapshot, skia::ImageOperations::RESIZE_GOOD,
4598       page_scale_factor * snapshot->width(),
4599       page_scale_factor * snapshot->height());
4600 }
4601
4602 SkColor WebFrameWidgetImpl::GetBackgroundColor() {
4603   SkColor bg_color = View()->BackgroundColor();
4604   return bg_color;
4605 }
4606
4607 gfx::RectF WebFrameWidgetImpl::UpdateFocusedNodeBounds() {
4608   Element* element = FocusedElement();
4609   if (!element)
4610     return gfx::RectF();
4611
4612   WebElement web_element = WebElement(element);
4613
4614   if (!web_element.IsNull() && web_element.IsElementNode()) {
4615     gfx::RectF focused_node_bounds_scaled = gfx::ScaleRect(
4616         gfx::RectF(web_element.BoundsInWidget()), View()->PageScaleFactor());
4617     return focused_node_bounds_scaled;
4618   }
4619   return gfx::RectF();
4620 }
4621
4622 void WebFrameWidgetImpl::SetLongPollingGlobalTimeout(uint64_t timeout) {
4623   WebView* view = View();
4624   if (view)
4625     view->SetLongPollingGlobalTimeout(timeout);
4626 }
4627
4628 bool WebFrameWidgetImpl::QueryInputType() {
4629   Element* element = FocusedElement();
4630   if (!element)
4631     return false;
4632
4633   auto* input_element = DynamicTo<HTMLInputElement>(element);
4634   if (input_element && input_element->type() == input_type_names::kPassword)
4635     return true;
4636
4637   return false;
4638 }
4639
4640 void WebFrameWidgetImpl::SelectClosestWord(uint32_t x, uint32_t y) {
4641   if (!View())
4642     return;
4643
4644   blink::WebFrame* main_frame = View()->MainFrame();
4645   if (!main_frame)
4646     return;
4647
4648   SetHandlingInputEvent(true);
4649   main_frame->SelectClosestWord(x, y);
4650   SetHandlingInputEvent(false);
4651 }
4652
4653 void WebFrameWidgetImpl::SelectFocusedLink() {
4654   Element* element = FocusedElement();
4655   if (!element)
4656     return;
4657
4658   WebElement web_element = WebElement(element);
4659   if (web_element.IsNull() || web_element.IsEditable() ||
4660       web_element.HasHTMLTagName("select")) {
4661     return;
4662   }
4663
4664   gfx::Rect box_rect = web_element.BoundsInWidget();
4665   if (box_rect.IsEmpty())
4666     return;
4667
4668   if (!View())
4669     return;
4670
4671   float page_scale = View()->PageScaleFactor();
4672   int focused_x = (box_rect.x() + box_rect.width() / 2) / page_scale;
4673   int focused_y = (box_rect.y() + box_rect.height() / 2) / page_scale;
4674
4675   SelectClosestWord(focused_x, focused_y);
4676 }
4677
4678 gfx::Rect WebFrameWidgetImpl::RequestSelectionRect() {
4679   if (!View())
4680     return gfx::Rect();
4681
4682   return gfx::Rect(View()->CurrentSelectionRect());
4683 }
4684
4685 void WebFrameWidgetImpl::ResetLastInteractedElements() {
4686 #if defined(TIZEN_AUTOFILL_FW)
4687   if (!View())
4688     return;
4689
4690   if (auto* frame = View()->FocusedFrame())
4691     frame->ResetLastInteractedElements();
4692 #endif
4693 }
4694
4695 void WebFrameWidgetImpl::PrintToPdf(uint32_t width,
4696                                     uint32_t height,
4697                                     const base::FilePath& filename) {
4698   WebLocalFrame* focused_frame = FocusedWebLocalFrameInWidget();
4699   if (!focused_frame || !focused_frame->Client())
4700     return;
4701
4702   focused_frame->Client()->PrintToPdf(
4703       width, height, filename,
4704       content::RenderFrame::FromWebFrame(focused_frame));
4705 }
4706
4707 void WebFrameWidgetImpl::SetMainFrameScrollbarVisible(bool visible) {
4708   blink::WebView* view = View();
4709   if (!view || !view->MainFrame() || !view->MainFrame()->ToWebLocalFrame())
4710     return;
4711
4712   view->MainFrame()->ToWebLocalFrame()->ChangeScrollbarVisibility(visible);
4713 }
4714
4715 bool WebFrameWidgetImpl::RequestMainFrameScrollbarVisible(bool& visible) {
4716   blink::WebView* view = View();
4717   if (!view || !view->MainFrame() || !view->MainFrame()->ToWebLocalFrame())
4718     return false;
4719
4720   auto local_frame = view->MainFrame()->ToWebLocalFrame();
4721   visible = local_frame->HasHorizontalScrollbar() ||
4722             local_frame->HasVerticalScrollbar();
4723   return true;
4724 }
4725
4726 #if BUILDFLAG(IS_TIZEN_TV)
4727 bool WebFrameWidgetImpl::IsHitScrollbar() {
4728   return View()->IsHitScrollbar();
4729 }
4730
4731 bool WebFrameWidgetImpl::IsMouseDownEventSwallowed() {
4732   return View()->IsMouseDownEventSwallowed();
4733 }
4734
4735 void WebFrameWidgetImpl::SetFloatVideoWindowState(bool enabled) {
4736   View()->SetFloatVideoWindowState(enabled);
4737 }
4738
4739 void WebFrameWidgetImpl::SuspendNetworkLoading() {
4740   View()->SuspendNetworkLoading();
4741 }
4742
4743 void WebFrameWidgetImpl::ResumeNetworkLoading() {
4744   View()->ResumeNetworkLoading();
4745 }
4746 #endif  // IS_TIZEN_TV
4747 #endif  // IS_EFL
4748
4749 #if BUILDFLAG(IS_TIZEN)
4750 void WebFrameWidgetImpl::SetMaxRefreshRate(uint32_t max_refresh_rate) {
4751   widget_base_->SetMaxRefreshRate(max_refresh_rate);
4752 }
4753 #endif
4754
4755 #if BUILDFLAG(IS_TIZEN)
4756 void WebFrameWidgetImpl::DidChangeLoadState(bool is_loading) {
4757   widget_base_->LayerTreeHost()->DidChangeLoadState(is_loading);
4758 }
4759 #endif
4760
4761 void WebFrameWidgetImpl::OrientationChanged() {
4762   local_root_->SendOrientationChangeEvent();
4763 }
4764
4765 #if BUILDFLAG(IS_TIZEN)
4766 void WebFrameWidgetImpl::PauseScheduledTasks() {
4767   View()->PauseScheduledTasks();
4768 }
4769
4770 void WebFrameWidgetImpl::UnPauseScheduledTasks() {
4771   View()->UnpauseScheduledTasks();
4772 }
4773 #endif
4774
4775 void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
4776     const display::ScreenInfos& previous_original_screen_infos) {
4777   display::ScreenInfo screen_info = widget_base_->GetScreenInfo();
4778   View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
4779
4780   if (ShouldAutoDetermineCompositingToLCDTextSetting()) {
4781     // This causes compositing state to be modified which dirties the
4782     // document lifecycle. Android Webview relies on the document
4783     // lifecycle being clean after the RenderWidget is initialized, in
4784     // order to send IPCs that query and change compositing state. So
4785     // WebFrameWidgetImpl::Resize() must come after this call, as it runs the
4786     // entire document lifecycle.
4787     View()->GetSettings()->SetLCDTextPreference(
4788         widget_base_->ComputeLCDTextPreference());
4789   }
4790
4791   // When the device scale changes, the size and position of the popup would
4792   // need to be adjusted, which we can't do. Just close the popup, which is
4793   // also consistent with page zoom and resize behavior.
4794   display::ScreenInfos original_screen_infos = GetOriginalScreenInfos();
4795   if (previous_original_screen_infos.current().device_scale_factor !=
4796       original_screen_infos.current().device_scale_factor) {
4797     View()->CancelPagePopup();
4798   }
4799
4800   const bool window_screen_has_changed =
4801       !Screen::AreWebExposedScreenPropertiesEqual(
4802           previous_original_screen_infos.current(),
4803           original_screen_infos.current());
4804
4805   // Update Screens interface data before firing any events. The API is designed
4806   // to offer synchronous access to the most up-to-date cached screen
4807   // information when a change event is fired.  It is not required but it
4808   // is convenient to have all ScreenDetailed objects be up to date when any
4809   // window.screen events are fired as well.
4810   ForEachLocalFrameControlledByWidget(
4811       LocalRootImpl()->GetFrame(),
4812       [&original_screen_infos,
4813        window_screen_has_changed](WebLocalFrameImpl* local_frame) {
4814         auto* screen = local_frame->GetFrame()->DomWindow()->screen();
4815         screen->UpdateDisplayId(original_screen_infos.current().display_id);
4816         CoreInitializer::GetInstance().DidUpdateScreens(
4817             *local_frame->GetFrame(), original_screen_infos);
4818         if (window_screen_has_changed)
4819           screen->DispatchEvent(*Event::Create(event_type_names::kChange));
4820       });
4821
4822   if (previous_original_screen_infos != original_screen_infos) {
4823     // Propagate changes down to child local root RenderWidgets and
4824     // BrowserPlugins in other frame trees/processes.
4825     ForEachRemoteFrameControlledByWidget(
4826         [&original_screen_infos](RemoteFrame* remote_frame) {
4827           remote_frame->DidChangeScreenInfos(original_screen_infos);
4828         });
4829   }
4830 }
4831
4832 gfx::Rect WebFrameWidgetImpl::ViewportVisibleRect() {
4833   if (ForMainFrame()) {
4834     return widget_base_->CompositorViewportRect();
4835   } else {
4836     return child_data().compositor_visible_rect;
4837   }
4838 }
4839
4840 absl::optional<display::mojom::blink::ScreenOrientation>
4841 WebFrameWidgetImpl::ScreenOrientationOverride() {
4842   return View()->ScreenOrientationOverride();
4843 }
4844
4845 void WebFrameWidgetImpl::WasHidden() {
4846   ForEachLocalFrameControlledByWidget(local_root_->GetFrame(),
4847                                       [](WebLocalFrameImpl* local_frame) {
4848                                         local_frame->Client()->WasHidden();
4849                                       });
4850
4851   if (animation_frame_timing_monitor_) {
4852     animation_frame_timing_monitor_->Shutdown();
4853     animation_frame_timing_monitor_.Clear();
4854   }
4855 }
4856
4857 void WebFrameWidgetImpl::WasShown(bool was_evicted) {
4858   ForEachLocalFrameControlledByWidget(local_root_->GetFrame(),
4859                                       [](WebLocalFrameImpl* local_frame) {
4860                                         local_frame->Client()->WasShown();
4861                                       });
4862   if (was_evicted) {
4863     ForEachRemoteFrameControlledByWidget(
4864         // On eviction, the last SurfaceId is invalidated. We need to
4865         // allocate a new id.
4866         &RemoteFrame::ResendVisualProperties);
4867   }
4868
4869   CHECK(local_root_ && local_root_->GetFrame());
4870   if (!animation_frame_timing_monitor_ &&
4871       RuntimeEnabledFeatures::LongAnimationFrameMonitoringEnabled(
4872           local_root_->GetFrame()->DomWindow())) {
4873     animation_frame_timing_monitor_ =
4874         MakeGarbageCollected<AnimationFrameTimingMonitor>(
4875             *this, local_root_->GetFrame()->GetProbeSink());
4876   }
4877 }
4878
4879 void WebFrameWidgetImpl::RunPaintBenchmark(int repeat_count,
4880                                            cc::PaintBenchmarkResult& result) {
4881   if (!ForMainFrame())
4882     return;
4883   if (auto* frame_view = LocalRootImpl()->GetFrameView())
4884     frame_view->RunPaintBenchmark(repeat_count, result);
4885 }
4886
4887 void WebFrameWidgetImpl::NotifyInputObservers(
4888     const WebCoalescedInputEvent& coalesced_event) {
4889   LocalFrame* frame = FocusedLocalFrameInWidget();
4890   if (!frame)
4891     return;
4892
4893   LocalFrameView* frame_view = frame->View();
4894   if (!frame_view)
4895     return;
4896
4897   const WebInputEvent& input_event = coalesced_event.Event();
4898   auto& paint_timing_detector = frame_view->GetPaintTimingDetector();
4899
4900   if (paint_timing_detector.NeedToNotifyInputOrScroll())
4901     paint_timing_detector.NotifyInputEvent(input_event.GetType());
4902 }
4903
4904 Frame* WebFrameWidgetImpl::FocusedCoreFrame() const {
4905   return GetPage() ? GetPage()->GetFocusController().FocusedOrMainFrame()
4906                    : nullptr;
4907 }
4908
4909 Element* WebFrameWidgetImpl::FocusedElement() const {
4910   LocalFrame* frame = GetPage()->GetFocusController().FocusedFrame();
4911   if (!frame)
4912     return nullptr;
4913
4914   Document* document = frame->GetDocument();
4915   if (!document)
4916     return nullptr;
4917
4918   return document->FocusedElement();
4919 }
4920
4921 HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
4922     const gfx::PointF& pos_in_root_frame) {
4923   gfx::PointF doc_point =
4924       LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
4925           pos_in_root_frame);
4926   HitTestLocation location(doc_point);
4927   HitTestResult result =
4928       LocalRootImpl()->GetFrame()->View()->HitTestWithThrottlingAllowed(
4929           location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
4930   return result;
4931 }
4932
4933 KURL WebFrameWidgetImpl::GetURLForDebugTrace() {
4934   WebFrame* main_frame = View()->MainFrame();
4935   if (main_frame->IsWebLocalFrame())
4936     return main_frame->ToWebLocalFrame()->GetDocument().Url();
4937   return {};
4938 }
4939
4940 float WebFrameWidgetImpl::GetTestingDeviceScaleFactorOverride() {
4941   return device_scale_factor_for_testing_;
4942 }
4943
4944 void WebFrameWidgetImpl::ReleaseMouseLockAndPointerCaptureForTesting() {
4945   GetPage()->GetPointerLockController().ExitPointerLock();
4946   MouseCaptureLost();
4947 }
4948
4949 const viz::FrameSinkId& WebFrameWidgetImpl::GetFrameSinkId() {
4950   // It is valid to create a WebFrameWidget with an invalid frame sink id for
4951   // printing and placeholders. But if we go to use it, it should be valid.
4952   DCHECK(frame_sink_id_.is_valid());
4953   return frame_sink_id_;
4954 }
4955
4956 WebHitTestResult WebFrameWidgetImpl::HitTestResultAt(const gfx::PointF& point) {
4957   return CoreHitTestResultAt(point);
4958 }
4959
4960 void WebFrameWidgetImpl::SetZoomLevelForTesting(double zoom_level) {
4961   DCHECK(ForMainFrame());
4962   DCHECK_NE(zoom_level, -INFINITY);
4963   zoom_level_for_testing_ = zoom_level;
4964   SetZoomLevel(zoom_level);
4965 }
4966
4967 void WebFrameWidgetImpl::ResetZoomLevelForTesting() {
4968   DCHECK(ForMainFrame());
4969   zoom_level_for_testing_ = -INFINITY;
4970   SetZoomLevel(0);
4971 }
4972
4973 void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
4974   DCHECK(ForMainFrame());
4975   DCHECK_GE(factor, 0.f);
4976
4977   // Stash the window size before we adjust the scale factor, as subsequent
4978   // calls to convert will use the new scale factor.
4979   gfx::Size size_in_dips = widget_base_->BlinkSpaceToFlooredDIPs(Size());
4980   device_scale_factor_for_testing_ = factor;
4981
4982   // Receiving a 0 is used to reset between tests, it removes the override in
4983   // order to listen to the browser for the next test.
4984   if (!factor)
4985     return;
4986
4987   // We are changing the device scale factor from the renderer, so allocate a
4988   // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
4989   widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
4990
4991   display::ScreenInfos screen_infos = widget_base_->screen_infos();
4992   screen_infos.mutable_current().device_scale_factor = factor;
4993   gfx::Size size_with_dsf = gfx::ScaleToCeiledSize(size_in_dips, factor);
4994   widget_base_->UpdateCompositorViewportAndScreenInfo(gfx::Rect(size_with_dsf),
4995                                                       screen_infos);
4996   if (!AutoResizeMode()) {
4997     // This picks up the new device scale factor as
4998     // `UpdateCompositorViewportAndScreenInfo()` has applied a new value.
4999     Resize(widget_base_->DIPsToCeiledBlinkSpace(size_in_dips));
5000   }
5001 }
5002
5003 FrameWidgetTestHelper*
5004 WebFrameWidgetImpl::GetFrameWidgetTestHelperForTesting() {
5005   return nullptr;
5006 }
5007
5008 void WebFrameWidgetImpl::PrepareForFinalLifecyclUpdateForTesting() {
5009   ForEachLocalFrameControlledByWidget(
5010       LocalRootImpl()->GetFrame(), [](WebLocalFrameImpl* local_frame) {
5011         LocalFrame* core_frame = local_frame->GetFrame();
5012         // A frame in the frame tree is fully attached and must always have a
5013         // core frame.
5014         DCHECK(core_frame);
5015         Document* document = core_frame->GetDocument();
5016         // Similarly, a fully attached frame must always have a document.
5017         DCHECK(document);
5018
5019         // In a web test, a rendering update may not have occurred before the
5020         // test finishes so ensure the transition moves out of rendering
5021         // blocked state.
5022         if (RuntimeEnabledFeatures::ViewTransitionOnNavigationEnabled()) {
5023           if (auto* transition =
5024                   ViewTransitionUtils::GetTransition(*document)) {
5025             transition->ActivateFromSnapshot();
5026           }
5027         }
5028       });
5029 }
5030
5031 void WebFrameWidgetImpl::SetMayThrottleIfUndrawnFrames(
5032     bool may_throttle_if_undrawn_frames) {
5033   if (!View()->does_composite())
5034     return;
5035   widget_base_->LayerTreeHost()->SetMayThrottleIfUndrawnFrames(
5036       may_throttle_if_undrawn_frames);
5037 }
5038
5039 int WebFrameWidgetImpl::GetVirtualKeyboardResizeHeight() const {
5040   DCHECK(!virtual_keyboard_resize_height_physical_px_ || ForTopMostMainFrame());
5041   return virtual_keyboard_resize_height_physical_px_;
5042 }
5043
5044 void WebFrameWidgetImpl::SetVirtualKeyboardResizeHeightForTesting(int height) {
5045   virtual_keyboard_resize_height_physical_px_ = height;
5046 }
5047
5048 bool WebFrameWidgetImpl::GetMayThrottleIfUndrawnFramesForTesting() {
5049   return widget_base_->LayerTreeHost()
5050       ->GetMayThrottleIfUndrawnFramesForTesting();
5051 }
5052
5053 WebPlugin* WebFrameWidgetImpl::GetFocusedPluginContainer() {
5054   LocalFrame* focused_frame = FocusedLocalFrameInWidget();
5055   if (!focused_frame)
5056     return nullptr;
5057   if (auto* container = focused_frame->GetWebPluginContainer())
5058     return container->Plugin();
5059   return nullptr;
5060 }
5061
5062 bool WebFrameWidgetImpl::HasPendingPageScaleAnimation() {
5063   return LayerTreeHost()->HasPendingPageScaleAnimation();
5064 }
5065
5066 void WebFrameWidgetImpl::SetSourceURLForCompositor(ukm::SourceId source_id,
5067                                                    const KURL& url) {
5068   LayerTreeHost()->SetSourceURL(source_id, GURL(url));
5069 }
5070
5071 base::ReadOnlySharedMemoryRegion
5072 WebFrameWidgetImpl::CreateSharedMemoryForSmoothnessUkm() {
5073   return LayerTreeHost()->CreateSharedMemoryForSmoothnessUkm();
5074 }
5075
5076 bool WebFrameWidgetImpl::CanComposeInline() {
5077   if (auto* plugin = GetFocusedPluginContainer())
5078     return plugin->CanComposeInline();
5079   return true;
5080 }
5081
5082 bool WebFrameWidgetImpl::ShouldDispatchImeEventsToPlugin() {
5083   if (auto* plugin = GetFocusedPluginContainer())
5084     return plugin->ShouldDispatchImeEventsToPlugin();
5085   return false;
5086 }
5087
5088 void WebFrameWidgetImpl::ImeSetCompositionForPlugin(
5089     const String& text,
5090     const Vector<ui::ImeTextSpan>& ime_text_spans,
5091     const gfx::Range& replacement_range,
5092     int selection_start,
5093     int selection_end) {
5094   if (auto* plugin = GetFocusedPluginContainer()) {
5095     plugin->ImeSetCompositionForPlugin(
5096         text,
5097         std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
5098                                      ime_text_spans.end()),
5099         replacement_range, selection_start, selection_end);
5100   }
5101 }
5102
5103 void WebFrameWidgetImpl::ImeCommitTextForPlugin(
5104     const String& text,
5105     const Vector<ui::ImeTextSpan>& ime_text_spans,
5106     const gfx::Range& replacement_range,
5107     int relative_cursor_pos) {
5108   if (auto* plugin = GetFocusedPluginContainer()) {
5109     plugin->ImeCommitTextForPlugin(
5110         text,
5111         std::vector<ui::ImeTextSpan>(ime_text_spans.begin(),
5112                                      ime_text_spans.end()),
5113         replacement_range, relative_cursor_pos);
5114   }
5115 }
5116
5117 void WebFrameWidgetImpl::ImeFinishComposingTextForPlugin(bool keep_selection) {
5118   if (auto* plugin = GetFocusedPluginContainer())
5119     plugin->ImeFinishComposingTextForPlugin(keep_selection);
5120 }
5121
5122 void WebFrameWidgetImpl::SetWindowRect(const gfx::Rect& requested_rect,
5123                                        const gfx::Rect& adjusted_rect) {
5124   DCHECK(ForMainFrame());
5125   SetPendingWindowRect(adjusted_rect);
5126   View()->SendWindowRectToMainFrameHost(
5127       requested_rect, WTF::BindOnce(&WebFrameWidgetImpl::AckPendingWindowRect,
5128                                     WrapWeakPersistent(this)));
5129 }
5130
5131 void WebFrameWidgetImpl::SetWindowRectSynchronouslyForTesting(
5132     const gfx::Rect& new_window_rect) {
5133   DCHECK(ForMainFrame());
5134   SetWindowRectSynchronously(new_window_rect);
5135 }
5136
5137 void WebFrameWidgetImpl::SetWindowRectSynchronously(
5138     const gfx::Rect& new_window_rect) {
5139   // This method is only call in tests, and it applies the |new_window_rect| to
5140   // all three of:
5141   // a) widget size (in |size_|)
5142   // b) blink viewport (in |visible_viewport_size_|)
5143   // c) compositor viewport (in cc::LayerTreeHost)
5144   // Normally the browser controls these three things independently, but this is
5145   // used in tests to control the size from the renderer.
5146
5147   // We are resizing the window from the renderer, so allocate a new
5148   // viz::LocalSurfaceId to avoid surface invariants violations in tests.
5149   widget_base_->LayerTreeHost()->RequestNewLocalSurfaceId();
5150
5151   gfx::Rect compositor_viewport_pixel_rect(gfx::ScaleToCeiledSize(
5152       new_window_rect.size(),
5153       widget_base_->GetScreenInfo().device_scale_factor));
5154   widget_base_->UpdateSurfaceAndScreenInfo(
5155       widget_base_->local_surface_id_from_parent(),
5156       compositor_viewport_pixel_rect, widget_base_->screen_infos());
5157
5158   Resize(new_window_rect.size());
5159   widget_base_->SetScreenRects(new_window_rect, new_window_rect);
5160 }
5161
5162 void WebFrameWidgetImpl::DidCreateLocalRootView() {
5163   // If this WebWidget still hasn't received its size from the embedder, block
5164   // the parser. This is necessary, because the parser can cause layout to
5165   // happen, which needs to be done with the correct size.
5166   if (ForSubframe() && !size_) {
5167     child_data().did_suspend_parsing = true;
5168     LocalRootImpl()->GetFrame()->Loader().GetDocumentLoader()->BlockParser();
5169   }
5170 }
5171
5172 bool WebFrameWidgetImpl::ShouldAutoDetermineCompositingToLCDTextSetting() {
5173   return true;
5174 }
5175
5176 void WebFrameWidgetImpl::NotifyZoomLevelChanged(LocalFrame* root) {
5177   if (root) {
5178     Document* document = root->GetDocument();
5179     DCHECK(document);
5180     if (LocalFrameView* view = document->View())
5181       view->GetLayoutShiftTracker().NotifyZoomLevelChanged();
5182   }
5183 }
5184
5185 #if BUILDFLAG(IS_EFL)
5186 void WebFrameWidgetImpl::NotifyKeyEvent(WebInputEvent::Type type,
5187                                         bool processed) {
5188   GetAssociatedFrameWidgetHost()->HandleKeyEvent(type, processed);
5189 }
5190 #endif
5191
5192 #if BUILDFLAG(IS_TIZEN_TV)
5193 void WebFrameWidgetImpl::NotifyTrackInfoToBrowser(int active_track_id,
5194                                                   const std::string& url,
5195                                                   const std::string& lang) {
5196   LOG(INFO) << __func__ << " active_track_id:" << active_track_id
5197             << " url:" << url << " lang:" << lang;
5198   widget_base_->NotifyTrackInfoToBrowser(active_track_id, url, lang);
5199 }
5200
5201 void WebFrameWidgetImpl::MoveFocusToBrowser(int direction) {
5202   widget_base_->MoveFocusToBrowser(direction);
5203 }
5204 #endif
5205
5206 #if BUILDFLAG(IS_TIZEN)
5207 void WebFrameWidgetImpl::SetDrawsTransparentBackground(
5208     bool draws_transparent_background) {
5209   WebViewImpl* webview = View();
5210   if (!webview)
5211     return;
5212
5213   SkColor backgroundColor = draws_transparent_background
5214                                 ? static_cast<SkColor>(0x00000000)
5215                                 : static_cast<SkColor>(0xFFFFFFFF);
5216
5217   webview->SetPageBaseBackgroundColor(absl::make_optional(backgroundColor));
5218   // set transparent bg for Render process
5219   if (draws_transparent_background) {
5220     widget_base_->LayerTreeHost()->set_background_color(SkColors::kTransparent);
5221   }
5222 }
5223
5224 void WebFrameWidgetImpl::SetBackgroundColor(int32_t red,
5225                                             int32_t green,
5226                                             int32_t blue,
5227                                             int32_t alpha) {
5228   WebViewImpl* webview = View();
5229   if (!webview)
5230     return;
5231
5232   SkColor backgroundColor = SkColorSetARGB(alpha, red, green, blue);
5233   webview->SetPageBaseBackgroundColor(absl::make_optional(backgroundColor));
5234 }
5235 #endif
5236
5237 }  // namespace blink