1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_impl.h"
12 #include <unordered_map>
16 #include "base/auto_reset.h"
17 #include "base/check.h"
18 #include "base/command_line.h"
19 #include "base/containers/contains.h"
20 #include "base/containers/cxx20_erase.h"
21 #include "base/debug/alias.h"
22 #include "base/debug/dump_without_crashing.h"
23 #include "base/feature_list.h"
24 #include "base/files/file_path.h"
25 #include "base/functional/bind.h"
26 #include "base/functional/callback_helpers.h"
27 #include "base/hash/hash.h"
28 #include "base/i18n/rtl.h"
29 #include "base/lazy_instance.h"
30 #include "base/location.h"
31 #include "base/memory/ptr_util.h"
32 #include "base/metrics/field_trial.h"
33 #include "base/metrics/histogram_macros.h"
34 #include "base/observer_list.h"
35 #include "base/strings/string_number_conversions.h"
36 #include "base/strings/utf_string_conversions.h"
37 #include "base/task/current_thread.h"
38 #include "base/task/single_thread_task_runner.h"
39 #include "base/time/default_tick_clock.h"
40 #include "base/trace_event/optional_trace_event.h"
41 #include "base/trace_event/trace_event.h"
42 #include "build/build_config.h"
43 #include "cc/base/switches.h"
44 #include "cc/trees/browser_controls_params.h"
45 #include "cc/trees/render_frame_metadata.h"
46 #include "components/viz/common/features.h"
47 #include "components/viz/host/host_frame_sink_manager.h"
48 #include "content/browser/accessibility/browser_accessibility_manager.h"
49 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
50 #include "content/browser/bad_message.h"
51 #include "content/browser/browser_main_loop.h"
52 #include "content/browser/child_process_security_policy_impl.h"
53 #include "content/browser/compositor/surface_utils.h"
54 #include "content/browser/devtools/devtools_instrumentation.h"
55 #include "content/browser/file_system/browser_file_system_helper.h"
56 #include "content/browser/file_system_access/file_system_access_manager_impl.h"
57 #include "content/browser/gpu/compositor_util.h"
58 #include "content/browser/renderer_host/agent_scheduling_group_host.h"
59 #include "content/browser/renderer_host/data_transfer_util.h"
60 #include "content/browser/renderer_host/dip_util.h"
61 #include "content/browser/renderer_host/display_feature.h"
62 #include "content/browser/renderer_host/frame_token_message_queue.h"
63 #include "content/browser/renderer_host/frame_tree.h"
64 #include "content/browser/renderer_host/input/fling_scheduler.h"
65 #include "content/browser/renderer_host/input/input_router_config_helper.h"
66 #include "content/browser/renderer_host/input/input_router_impl.h"
67 #include "content/browser/renderer_host/input/synthetic_gesture.h"
68 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
69 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
70 #include "content/browser/renderer_host/input/timeout_monitor.h"
71 #include "content/browser/renderer_host/input/touch_emulator.h"
72 #include "content/browser/renderer_host/render_process_host_impl.h"
73 #include "content/browser/renderer_host/render_view_host_delegate.h"
74 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
75 #include "content/browser/renderer_host/render_view_host_impl.h"
76 #include "content/browser/renderer_host/render_widget_helper.h"
77 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
78 #include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
79 #include "content/browser/renderer_host/render_widget_host_view_base.h"
80 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
81 #include "content/browser/renderer_host/visible_time_request_trigger.h"
82 #include "content/browser/scheduler/browser_task_executor.h"
83 #include "content/browser/scheduler/browser_ui_thread_scheduler.h"
84 #include "content/browser/storage_partition_impl.h"
85 #include "content/common/content_constants_internal.h"
86 #include "content/common/frame.mojom.h"
87 #include "content/public/browser/browser_context.h"
88 #include "content/public/browser/browser_thread.h"
89 #include "content/public/browser/device_service.h"
90 #include "content/public/browser/keyboard_event_processing_result.h"
91 #include "content/public/browser/notification_service.h"
92 #include "content/public/browser/notification_types.h"
93 #include "content/public/browser/peak_gpu_memory_tracker.h"
94 #include "content/public/browser/render_frame_metadata_provider.h"
95 #include "content/public/browser/render_process_host_priority_client.h"
96 #include "content/public/browser/render_widget_host_iterator.h"
97 #include "content/public/browser/render_widget_host_observer.h"
98 #include "content/public/browser/storage_partition.h"
99 #include "content/public/common/content_constants.h"
100 #include "content/public/common/content_features.h"
101 #include "content/public/common/content_switches.h"
102 #include "content/public/common/drop_data.h"
103 #include "content/public/common/input/native_web_keyboard_event.h"
104 #include "content/public/common/result_codes.h"
105 #include "gpu/GLES2/gl2extchromium.h"
106 #include "gpu/command_buffer/service/gpu_switches.h"
107 #include "mojo/public/cpp/bindings/callback_helpers.h"
108 #include "mojo/public/cpp/bindings/pending_receiver.h"
109 #include "mojo/public/cpp/system/platform_handle.h"
110 #include "net/base/filename_util.h"
111 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
112 #include "skia/ext/image_operations.h"
113 #include "skia/ext/platform_canvas.h"
114 #include "skia/ext/skia_utils_base.h"
115 #include "storage/browser/file_system/isolated_context.h"
116 #include "third_party/abseil-cpp/absl/types/optional.h"
117 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
118 #include "third_party/blink/public/common/storage_key/storage_key.h"
119 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
120 #include "third_party/blink/public/common/widget/visual_properties.h"
121 #include "third_party/blink/public/mojom/drag/drag.mojom.h"
122 #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom.h"
123 #include "third_party/blink/public/mojom/input/input_handler.mojom-forward.h"
124 #include "third_party/blink/public/mojom/input/touch_event.mojom.h"
125 #include "ui/base/clipboard/clipboard_constants.h"
126 #include "ui/base/cursor/cursor.h"
127 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
128 #include "ui/base/ime/mojom/text_input_state.mojom.h"
129 #include "ui/base/ui_base_features.h"
130 #include "ui/base/ui_base_switches.h"
131 #include "ui/display/display_switches.h"
132 #include "ui/display/display_util.h"
133 #include "ui/display/screen.h"
134 #include "ui/events/blink/web_input_event_traits.h"
135 #include "ui/events/event.h"
136 #include "ui/events/keycodes/dom/dom_code.h"
137 #include "ui/gfx/color_space.h"
138 #include "ui/gfx/geometry/size_conversions.h"
139 #include "ui/gfx/geometry/vector2d_conversions.h"
140 #include "ui/gfx/geometry/vector2d_f.h"
141 #include "ui/gfx/image/image.h"
142 #include "ui/gfx/image/image_skia.h"
143 #include "ui/gfx/skbitmap_operations.h"
144 #include "ui/snapshot/snapshot.h"
146 #if BUILDFLAG(IS_ANDROID)
147 #include "content/browser/renderer_host/input/fling_scheduler_android.h"
148 #include "ui/android/view_android.h"
151 #if BUILDFLAG(IS_MAC)
152 #include "content/browser/renderer_host/input/fling_scheduler_mac.h"
153 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
154 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
155 #include "ui/base/cocoa/cursor_utils.h"
158 using blink::DragOperationsMask;
159 using blink::WebGestureEvent;
160 using blink::WebInputEvent;
161 using blink::WebKeyboardEvent;
162 using blink::WebMouseEvent;
163 using blink::WebMouseWheelEvent;
168 // How long to wait for newly loaded content to send a compositor frame
169 // before clearing previously displayed graphics.
170 constexpr base::TimeDelta kNewContentRenderingDelay = base::Seconds(4);
172 constexpr gfx::Rect kInvalidScreenRect(std::numeric_limits<int>::max(),
173 std::numeric_limits<int>::max(),
177 bool g_check_for_pending_visual_properties_ack = true;
179 // <process id, routing id>
180 using RenderWidgetHostID = std::pair<int32_t, int32_t>;
181 using RoutingIDWidgetMap =
182 std::unordered_map<RenderWidgetHostID,
183 RenderWidgetHostImpl*,
184 base::IntPairHash<RenderWidgetHostID>>;
185 base::LazyInstance<RoutingIDWidgetMap>::DestructorAtExit
186 g_routing_id_widget_map = LAZY_INSTANCE_INITIALIZER;
188 // Implements the RenderWidgetHostIterator interface. It keeps a list of
189 // RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
190 // iteration (or NULL if there isn't any left).
191 class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
193 RenderWidgetHostIteratorImpl() = default;
195 RenderWidgetHostIteratorImpl(const RenderWidgetHostIteratorImpl&) = delete;
196 RenderWidgetHostIteratorImpl& operator=(const RenderWidgetHostIteratorImpl&) =
199 ~RenderWidgetHostIteratorImpl() override = default;
201 void Add(RenderWidgetHost* host) {
202 hosts_.emplace_back(host->GetProcess()->GetID(), host->GetRoutingID());
205 // RenderWidgetHostIterator:
206 RenderWidgetHost* GetNextHost() override {
207 RenderWidgetHost* host = nullptr;
208 while (current_index_ < hosts_.size() && !host) {
209 RenderWidgetHostID id = hosts_[current_index_];
210 host = RenderWidgetHost::FromID(id.first, id.second);
217 std::vector<RenderWidgetHostID> hosts_;
218 size_t current_index_ = 0;
221 std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
222 std::vector<DropData::Metadata> metadata;
223 if (drop_data.text) {
224 metadata.push_back(DropData::Metadata::CreateForMimeType(
225 DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeText)));
228 if (drop_data.url.is_valid()) {
229 metadata.push_back(DropData::Metadata::CreateForMimeType(
230 DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeURIList)));
233 if (drop_data.html) {
234 metadata.push_back(DropData::Metadata::CreateForMimeType(
235 DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeHTML)));
238 // On Aura, filenames are available before drop.
239 for (const auto& file_info : drop_data.filenames) {
240 if (!file_info.path.empty()) {
241 metadata.push_back(DropData::Metadata::CreateForFilePath(file_info.path));
245 // On Android, only files' mime types are available before drop.
246 for (const auto& mime_type : drop_data.file_mime_types) {
247 if (!mime_type.empty()) {
248 metadata.push_back(DropData::Metadata::CreateForMimeType(
249 DropData::Kind::FILENAME, mime_type));
253 for (const auto& file_system_file : drop_data.file_system_files) {
254 if (!file_system_file.url.is_empty()) {
256 DropData::Metadata::CreateForFileSystemUrl(file_system_file.url));
260 if (drop_data.file_contents_source_url.is_valid()) {
261 metadata.push_back(DropData::Metadata::CreateForBinary(
262 drop_data.file_contents_source_url));
265 for (const auto& custom_data_item : drop_data.custom_data) {
266 metadata.push_back(DropData::Metadata::CreateForMimeType(
267 DropData::Kind::STRING, custom_data_item.first));
273 class UnboundWidgetInputHandler : public blink::mojom::WidgetInputHandler {
275 void SetFocus(blink::mojom::FocusState focus_state) override {
276 DLOG(WARNING) << "Input request on unbound interface";
278 void MouseCaptureLost() override {
279 DLOG(WARNING) << "Input request on unbound interface";
281 void SetEditCommandsForNextKeyEvent(
282 std::vector<blink::mojom::EditCommandPtr> commands) override {
283 DLOG(WARNING) << "Input request on unbound interface";
285 void CursorVisibilityChanged(bool visible) override {
286 DLOG(WARNING) << "Input request on unbound interface";
288 void ImeSetComposition(const std::u16string& text,
289 const std::vector<ui::ImeTextSpan>& ime_text_spans,
290 const gfx::Range& range,
293 ImeSetCompositionCallback callback) override {
294 DLOG(WARNING) << "Input request on unbound interface";
296 void ImeCommitText(const std::u16string& text,
297 const std::vector<ui::ImeTextSpan>& ime_text_spans,
298 const gfx::Range& range,
299 int32_t relative_cursor_position,
300 ImeCommitTextCallback callback) override {
301 DLOG(WARNING) << "Input request on unbound interface";
303 void ImeFinishComposingText(bool keep_selection) override {
304 DLOG(WARNING) << "Input request on unbound interface";
306 void RequestTextInputStateUpdate() override {
307 DLOG(WARNING) << "Input request on unbound interface";
309 void RequestCompositionUpdates(bool immediate_request,
310 bool monitor_request) override {
311 DLOG(WARNING) << "Input request on unbound interface";
313 void DispatchEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event,
314 DispatchEventCallback callback) override {
315 DLOG(WARNING) << "Input request on unbound interface";
317 void DispatchNonBlockingEvent(
318 std::unique_ptr<blink::WebCoalescedInputEvent> event) override {
319 DLOG(WARNING) << "Input request on unbound interface";
321 void WaitForInputProcessed(WaitForInputProcessedCallback callback) override {
322 DLOG(WARNING) << "Input request on unbound interface";
324 #if BUILDFLAG(IS_ANDROID)
325 void AttachSynchronousCompositor(
326 mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost>
328 mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost>
330 mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor>
331 compositor_request) override {
332 NOTREACHED() << "Input request on unbound interface";
335 void GetFrameWidgetInputHandler(
336 mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
338 NOTREACHED() << "Input request on unbound interface";
340 void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
341 cc::BrowserControlsState current,
342 bool animate) override {
343 NOTREACHED() << "Input request on unbound interface";
347 std::u16string GetWrappedTooltipText(
348 const std::u16string& tooltip_text,
349 base::i18n::TextDirection text_direction_hint) {
350 // First, add directionality marks around tooltip text if necessary.
351 // A naive solution would be to simply always wrap the text. However, on
352 // windows, Unicode directional embedding characters can't be displayed on
353 // systems that lack RTL fonts and are instead displayed as empty squares.
355 // To get around this we only wrap the string when we deem it necessary i.e.
356 // when the locale direction is different than the tooltip direction hint.
358 // Currently, we use element's directionality as the tooltip direction hint.
359 // An alternate solution would be to set the overall directionality based on
360 // trying to detect the directionality from the tooltip text rather than the
361 // element direction. One could argue that would be a preferable solution
362 // but we use the current approach to match Fx & IE's behavior.
363 std::u16string wrapped_tooltip_text = tooltip_text;
364 if (!tooltip_text.empty()) {
365 if (text_direction_hint == base::i18n::LEFT_TO_RIGHT) {
366 // Force the tooltip to have LTR directionality.
367 wrapped_tooltip_text =
368 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
369 } else if (text_direction_hint == base::i18n::RIGHT_TO_LEFT &&
370 !base::i18n::IsRTL()) {
371 // Force the tooltip to have RTL directionality.
372 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
375 return wrapped_tooltip_text;
378 base::LazyInstance<UnboundWidgetInputHandler>::Leaky g_unbound_input_handler =
379 LAZY_INSTANCE_INITIALIZER;
383 ///////////////////////////////////////////////////////////////////////////////
384 // RenderWidgetHostImpl
387 std::unique_ptr<RenderWidgetHostImpl> RenderWidgetHostImpl::Create(
388 FrameTree* frame_tree,
389 RenderWidgetHostDelegate* delegate,
390 viz::FrameSinkId frame_sink_id,
391 base::SafeRef<SiteInstanceGroup> site_instance_group,
394 bool renderer_initiated_creation,
395 std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue) {
396 return base::WrapUnique(new RenderWidgetHostImpl(
398 /*self_owned=*/false, frame_sink_id, delegate,
399 std::move(site_instance_group), routing_id, hidden,
400 renderer_initiated_creation, std::move(frame_token_message_queue)));
404 RenderWidgetHostImpl* RenderWidgetHostImpl::CreateSelfOwned(
405 FrameTree* frame_tree,
406 RenderWidgetHostDelegate* delegate,
407 base::SafeRef<SiteInstanceGroup> site_instance_group,
410 std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue) {
411 auto* host = new RenderWidgetHostImpl(
412 frame_tree, /*self_owned=*/true,
413 DefaultFrameSinkId(*site_instance_group, routing_id), delegate,
414 site_instance_group, routing_id, hidden,
415 /*renderer_initiated_creation=*/true,
416 std::move(frame_token_message_queue));
417 host->SetViewIsFrameSinkIdOwner(true);
421 RenderWidgetHostImpl::RenderWidgetHostImpl(
422 FrameTree* frame_tree,
424 viz::FrameSinkId frame_sink_id,
425 RenderWidgetHostDelegate* delegate,
426 base::SafeRef<SiteInstanceGroup> site_instance_group,
429 bool renderer_initiated_creation,
430 std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue)
431 : frame_tree_(frame_tree),
432 self_owned_(self_owned),
433 waiting_for_init_(renderer_initiated_creation),
435 agent_scheduling_group_(site_instance_group->agent_scheduling_group()),
436 site_instance_group_(site_instance_group->GetWeakPtrToAllowDangling()),
437 routing_id_(routing_id),
439 last_view_screen_rect_(kInvalidScreenRect),
440 last_window_screen_rect_(kInvalidScreenRect),
441 should_disable_hang_monitor_(
442 base::CommandLine::ForCurrentProcess()->HasSwitch(
443 switches::kDisableHangMonitor)),
444 latency_tracker_(delegate_),
445 hung_renderer_delay_(kHungRendererDelay),
446 new_content_rendering_delay_(kNewContentRenderingDelay),
447 frame_token_message_queue_(std::move(frame_token_message_queue)),
448 render_frame_metadata_provider_(
449 #if BUILDFLAG(IS_MAC)
450 ui::WindowResizeHelperMac::Get()->task_runner(),
452 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}),
454 frame_token_message_queue_.get()),
455 frame_sink_id_(frame_sink_id) {
456 DCHECK(frame_token_message_queue_);
457 frame_token_message_queue_->Init(this);
459 #if BUILDFLAG(IS_MAC)
460 fling_scheduler_ = std::make_unique<FlingSchedulerMac>(this);
461 #elif BUILDFLAG(IS_ANDROID)
462 fling_scheduler_ = std::make_unique<FlingSchedulerAndroid>(this);
464 fling_scheduler_ = std::make_unique<FlingScheduler>(this);
467 CHECK_NE(MSG_ROUTING_NONE, routing_id_);
468 DCHECK(base::ThreadPoolInstance::Get());
470 std::pair<RoutingIDWidgetMap::iterator, bool> result =
471 g_routing_id_widget_map.Get().insert(std::make_pair(
472 RenderWidgetHostID(agent_scheduling_group_->GetProcess()->GetID(),
475 CHECK(result.second) << "Inserting a duplicate item!";
477 // Self-owned RenderWidgetHost lifetime is managed by the renderer process.
478 // To avoid leaking any instance. They self-delete when their renderer process
481 agent_scheduling_group_->GetProcess()->AddObserver(this);
484 render_process_blocked_state_changed_subscription_ =
485 agent_scheduling_group_->GetProcess()->RegisterBlockStateChangedCallback(
487 &RenderWidgetHostImpl::RenderProcessBlockedStateChanged,
488 base::Unretained(this)));
489 agent_scheduling_group_->GetProcess()->AddPriorityClient(this);
493 const auto* command_line = base::CommandLine::ForCurrentProcess();
494 if (!command_line->HasSwitch(switches::kDisableNewContentRenderingTimeout)) {
495 new_content_rendering_timeout_ = std::make_unique<TimeoutMonitor>(
496 base::BindRepeating(&RenderWidgetHostImpl::ClearDisplayedGraphics,
497 weak_factory_.GetWeakPtr()));
499 input_event_ack_timeout_.SetTaskRunner(
500 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
502 delegate_->RenderWidgetCreated(this);
503 render_frame_metadata_provider_.AddObserver(this);
506 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
508 render_frame_metadata_provider_.RemoveObserver(this);
515 RenderWidgetHost* RenderWidgetHost::FromID(int32_t process_id,
516 int32_t routing_id) {
517 return RenderWidgetHostImpl::FromID(process_id, routing_id);
521 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(int32_t process_id,
522 int32_t routing_id) {
523 DCHECK_CURRENTLY_ON(BrowserThread::UI);
524 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
525 auto it = widgets->find(RenderWidgetHostID(process_id, routing_id));
526 return it != widgets->end() ? it->second : nullptr;
530 std::unique_ptr<RenderWidgetHostIterator>
531 RenderWidgetHost::GetRenderWidgetHosts() {
532 auto hosts = std::make_unique<RenderWidgetHostIteratorImpl>();
533 for (auto& it : g_routing_id_widget_map.Get()) {
534 RenderWidgetHostImpl* widget = it.second;
535 RenderWidgetHostOwnerDelegate* owner_delegate = widget->owner_delegate();
536 // If the widget is not for a main frame, add to |hosts|.
537 if (!owner_delegate) {
542 // If the widget is for a main frame, only add if there is a RenderWidget in
543 // the renderer process. When this is false, there is no main RenderFrame
544 // and so no RenderWidget for this RenderWidgetHost.
545 if (owner_delegate->IsMainFrameActive()) {
550 return std::move(hosts);
554 std::unique_ptr<RenderWidgetHostIterator>
555 RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
556 auto hosts = std::make_unique<RenderWidgetHostIteratorImpl>();
557 for (auto& it : g_routing_id_widget_map.Get()) {
558 hosts->Add(it.second);
561 return std::move(hosts);
565 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
566 return static_cast<RenderWidgetHostImpl*>(rwh);
570 viz::FrameSinkId RenderWidgetHostImpl::DefaultFrameSinkId(
571 const SiteInstanceGroup& group,
573 return viz::FrameSinkId(
574 base::checked_cast<uint32_t>(group.process()->GetID()),
575 base::checked_cast<uint32_t>(routing_id));
578 void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
579 synthetic_gesture_controller_.reset();
582 view_ = view->GetWeakPtr();
583 view_->SetIsFrameSinkIdOwner(view_is_frame_sink_id_owner_);
584 MaybeDispatchBufferedFrameSinkRequest();
586 // SendScreenRects() and SynchronizeVisualProperties() delay until a view
587 // is set, however we come here with a newly created `view` that is not
588 // initialized and ready to be used.
589 // The portal codepath comes here because it replaces the view while the
590 // renderer-side widget is already created. In that case the renderer will
591 // hear about geometry changes from the view being moved/resized as a result
593 // Speculative RenderViews also end up setting a `view` after creating the
594 // renderer-side widget, as per https://crbug.com/1161585. That path must
595 // be responsible for updating the renderer geometry itself, which it does
596 // because it will start hidden, and will send them when shown.
597 // TODO(crbug.com/1161585): Once RendererWidgetCreated() is always called
598 // with a non-null `view` then this comment can go away. :)
604 #if BUILDFLAG(IS_TIZEN)
605 void RenderWidgetHostImpl::PauseScheduledTasks() {
606 blink_widget_->PauseScheduledTasks();
609 void RenderWidgetHostImpl::UnPauseScheduledTasks() {
610 blink_widget_->UnPauseScheduledTasks();
614 #if BUILDFLAG(IS_TIZEN_TV)
615 void RenderWidgetHostImpl::RequestVideoPlaying(int callback_id) {
617 LOG(ERROR) << "blink_widget_ is null";
620 blink_widget_->IsVideoPlaying(
621 base::BindOnce(&RenderWidgetHostImpl::OnGetVideoPlayingStatus,
622 weak_factory_.GetWeakPtr(), callback_id));
625 void RenderWidgetHostImpl::OnGetVideoPlayingStatus(int callback_id,
628 LOG(ERROR) << "view_ is null";
631 view_->VideoPlayingStatusReceived(is_playing, callback_id);
634 void RenderWidgetHostImpl::SetParentalRatingResult(const std::string& url,
637 LOG(ERROR) << "blink_widget_ is null";
640 blink_widget_->SetParentalRatingResult(url, is_pass);
643 void RenderWidgetHostImpl::SetPreferSubtitleLang(std::string lang_list) {
644 if (!blink_widget_) {
645 LOG(ERROR) << "blink_widget_ is null";
648 blink_widget_->SetPreferSubtitleLang(lang_list);
653 const base::TimeDelta RenderWidgetHostImpl::kActivationNotificationExpireTime =
654 base::Milliseconds(300);
656 RenderProcessHost* RenderWidgetHostImpl::GetProcess() {
657 return agent_scheduling_group_->GetProcess();
660 int RenderWidgetHostImpl::GetRoutingID() {
664 RenderWidgetHostViewBase* RenderWidgetHostImpl::GetView() {
668 VisibleTimeRequestTrigger&
669 RenderWidgetHostImpl::GetVisibleTimeRequestTrigger() {
670 return delegate()->GetVisibleTimeRequestTrigger();
673 const viz::FrameSinkId& RenderWidgetHostImpl::GetFrameSinkId() {
674 return frame_sink_id_;
677 void RenderWidgetHostImpl::SendScreenRects() {
678 // Sending screen rects are deferred until we have a connection to a
679 // renderer-side Widget to send them to. Further, if we're waiting for the
680 // renderer to show (aka Init()) the widget then we defer sending updates
681 // until the renderer is ready.
682 if (!renderer_widget_created_ || waiting_for_init_) {
685 // TODO(danakj): The `renderer_widget_created_` flag is set to true for
686 // widgets owned by inactive RenderViewHosts, even though there is no widget
687 // created. In that case the `view_` will not be created.
691 // Throttle to one update at a time.
692 if (waiting_for_screen_rects_ack_) {
696 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
697 // happens on Win & Mac, and when the view is shown it'll call this again.
701 if (last_view_screen_rect_ == view_->GetViewBounds() &&
702 last_window_screen_rect_ == view_->GetBoundsInRootWindow()) {
706 last_view_screen_rect_ = view_->GetViewBounds();
707 last_window_screen_rect_ = view_->GetBoundsInRootWindow();
708 blink_widget_->UpdateScreenRects(
709 last_view_screen_rect_, last_window_screen_rect_,
710 base::BindOnce(&RenderWidgetHostImpl::OnUpdateScreenRectsAck,
711 weak_factory_.GetWeakPtr()));
712 waiting_for_screen_rects_ack_ = true;
715 void RenderWidgetHostImpl::SetFrameDepth(unsigned int depth) {
716 if (frame_depth_ == depth) {
720 frame_depth_ = depth;
724 void RenderWidgetHostImpl::SetIntersectsViewport(bool intersects) {
725 if (intersects_viewport_ == intersects) {
729 intersects_viewport_ = intersects;
733 void RenderWidgetHostImpl::UpdatePriority() {
735 GetProcess()->UpdateClientPriority(this);
739 void RenderWidgetHostImpl::BindWidgetInterfaces(
740 mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> widget_host,
741 mojo::PendingAssociatedRemote<blink::mojom::Widget> widget) {
742 // This API may get called on a RenderWidgetHostImpl from a
743 // reused RenderViewHostImpl so we need to ensure old channels are dropped.
744 // TODO(dcheng): Rather than resetting here, reset when the process goes away.
745 blink_widget_host_receiver_.reset();
746 blink_widget_.reset();
747 widget_input_handler_.reset();
748 blink_widget_host_receiver_.Bind(
749 std::move(widget_host),
750 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
751 blink_widget_.Bind(std::move(widget), content::GetUIThreadTaskRunner(
752 {BrowserTaskType::kUserInput}));
755 void RenderWidgetHostImpl::BindPopupWidgetInterface(
756 mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
758 blink_popup_widget_host_receiver_.reset();
759 blink_popup_widget_host_receiver_.Bind(
760 std::move(popup_widget_host),
761 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
764 void RenderWidgetHostImpl::BindFrameWidgetInterfaces(
765 mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost>
767 mojo::PendingAssociatedRemote<blink::mojom::FrameWidget> frame_widget) {
768 // This API may get called on a RenderWidgetHostImpl from a
769 // reused RenderViewHostImpl so we need to ensure old channels are dropped.
770 // TODO(dcheng): Rather than resetting here, reset when the process goes away.
771 blink_frame_widget_host_receiver_.reset();
772 blink_frame_widget_.reset();
773 frame_widget_input_handler_.reset();
774 input_target_client_.reset();
775 widget_compositor_.reset();
776 blink_frame_widget_host_receiver_.Bind(
777 std::move(frame_widget_host),
778 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
779 blink_frame_widget_.Bind(
780 std::move(frame_widget),
781 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
784 void RenderWidgetHostImpl::RendererWidgetCreated(bool for_frame_widget) {
785 DCHECK(GetProcess()->IsInitializedAndNotDead());
787 renderer_widget_created_ = true;
789 blink_widget_->GetWidgetInputHandler(
790 widget_input_handler_.BindNewPipeAndPassReceiver(
791 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})),
792 input_router_->BindNewHost(
793 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})));
794 if (for_frame_widget) {
795 widget_input_handler_->GetFrameWidgetInputHandler(
796 frame_widget_input_handler_.BindNewEndpointAndPassReceiver(
797 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})));
798 blink_frame_widget_->BindInputTargetClient(
799 input_target_client_.BindNewPipeAndPassReceiver(
800 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})));
803 // TODO(crbug.com/1161585): The `view_` can be null. :( Speculative
804 // RenderViews along with the main frame and its widget before the
805 // RenderWidgetHostView is created. Normally the RenderWidgetHostView should
806 // come first. Historically, unit tests also set things up in the wrong order
807 // and could get here with a null, but that is no longer the case (hopefully
808 // that remains true).
810 view_->OnRendererWidgetCreated();
813 // These two methods avoid running until `renderer_widget_created_` is true,
814 // so we run them here after we set it.
816 SynchronizeVisualProperties();
819 void RenderWidgetHostImpl::Init() {
820 // Note that this may be called after a renderer crash. In this case, we can
821 // just exit early, as there is nothing else to do. Note that
822 // `waiting_for_init_` should've already been reset to false in that case.
823 if (!renderer_widget_created_) {
824 DCHECK(!waiting_for_init_);
828 DCHECK(waiting_for_init_);
829 waiting_for_init_ = false;
831 // These two methods avoid running while we are `waiting_for_init_`, so we
832 // run them here after we clear it.
834 SynchronizeVisualProperties();
835 #if BUILDFLAG(IS_TIZEN_TV)
836 if (pending_suspend_network_loading_closure_)
837 std::move(pending_suspend_network_loading_closure_).Run();
839 if (pending_resume_network_loading_closure_)
840 std::move(pending_resume_network_loading_closure_).Run();
842 if (pending_set_active_closure_)
843 std::move(pending_set_active_closure_).Run();
845 if (pending_set_page_focus_closure_)
846 std::move(pending_set_page_focus_closure_).Run();
849 // Show/Hide state is not given to the renderer while we are
850 // `waiting_for_init_`, but Init() signals that the renderer is ready to
851 // receive them. This call will inform the renderer that the widget is shown.
852 if (pending_show_params_) {
853 DCHECK(blink_widget_.is_bound());
854 blink_widget_->WasShown(
855 pending_show_params_->is_evicted,
856 std::move(pending_show_params_->visible_time_request));
857 pending_show_params_.reset();
861 bool RenderWidgetHostImpl::ShouldShowStaleContentOnEviction() {
862 return delegate_ && delegate_->ShouldShowStaleContentOnEviction();
865 void RenderWidgetHostImpl::ShutdownAndDestroyWidget(bool also_delete) {
866 CancelKeyboardLock();
867 RejectMouseLockOrUnlockIfNecessary(
868 blink::mojom::PointerLockResult::kElementDestroyed);
869 Destroy(also_delete);
872 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
874 view_->SetIsLoading(is_loading);
878 void RenderWidgetHostImpl::WasHidden() {
883 RejectMouseLockOrUnlockIfNecessary(
884 blink::mojom::PointerLockResult::kWrongDocument);
886 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::WasHidden");
889 // Unthrottle SynchronizeVisualProperties IPCs so that the first call after
890 // show goes through immediately.
891 visual_properties_ack_pending_ = false;
893 // Don't bother reporting hung state when we aren't active.
894 StopInputEventAckTimeout();
896 // Show/Hide state is not sent to the renderer when it has requested for us to
897 // wait until it requests them via Init().
898 if (pending_show_params_) {
899 pending_show_params_.reset();
901 // Widgets start out hidden, so we must have previously been shown to get
902 // here, and we'd have a `pending_show_params_` if we are
903 // `waiting_for_init_`.
904 DCHECK(!waiting_for_init_);
905 blink_widget_->WasHidden();
908 // Tell the RenderProcessHost we were hidden.
909 GetProcess()->UpdateClientPriority(this);
911 bool is_visible = false;
912 NotificationService::current()->Notify(
913 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
914 Source<RenderWidgetHost>(this), Details<bool>(&is_visible));
915 for (auto& observer : observers_) {
916 observer.RenderWidgetHostVisibilityChanged(this, false);
920 void RenderWidgetHostImpl::WasShown(
921 blink::mojom::RecordContentToVisibleTimeRequestPtr
922 record_tab_switch_time_request) {
927 TRACE_EVENT_WITH_FLOW0("renderer_host", "RenderWidgetHostImpl::WasShown",
928 routing_id_, TRACE_EVENT_FLAG_FLOW_OUT);
931 // If we navigated in background, clear the displayed graphics of the
932 // previous page before going visible.
933 // TODO(crbug.com/1396336): Checking if there is a content rendering timeout
934 // running isn't ideal for seeing if the tab navigated in the background.
935 ForceFirstFrameAfterNavigationTimeout();
936 RestartInputEventAckTimeoutIfNecessary();
938 // This methods avoids running when the widget is hidden, so we run it here
939 // once it is no longer hidden.
941 // SendScreenRects() and SynchronizeVisualProperties() should happen
942 // together as one message, but we send them back-to-back for now so that
943 // all state gets to the renderer as close together as possible.
944 SynchronizeVisualProperties();
946 DCHECK(!pending_show_params_);
947 if (!waiting_for_init_) {
948 if (!blink_widget_) {
949 LOG(ERROR) << "Bind WidgetInterfaces still not finish";
952 blink_widget_->WasShown(view_->is_evicted(),
953 std::move(record_tab_switch_time_request));
955 // Delay the WasShown message until Init is called.
956 pending_show_params_.emplace(view_->is_evicted(),
957 std::move(record_tab_switch_time_request));
959 view_->reset_is_evicted();
961 GetProcess()->UpdateClientPriority(this);
963 bool is_visible = true;
964 NotificationService::current()->Notify(
965 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
966 Source<RenderWidgetHost>(this), Details<bool>(&is_visible));
967 for (auto& observer : observers_) {
968 observer.RenderWidgetHostVisibilityChanged(this, true);
971 // It's possible for our size to be out of sync with the renderer. The
972 // following is one case that leads to this:
973 // 1. SynchronizeVisualProperties -> Send
974 // WidgetMsg_SynchronizeVisualProperties
976 // 2. SynchronizeVisualProperties -> do nothing as
977 // sync_visual_props_ack_pending_ is true
979 // By invoking SynchronizeVisualProperties the renderer is updated as
980 // necessary. SynchronizeVisualProperties does nothing if the sizes are
983 // TODO: ideally blink::mojom::Widget's WasShown would take a size. This way,
984 // the renderer could handle both the restore and resize at once. This isn't
985 // that big a deal as RenderWidget::WasShown delays updating, so that the
986 // resize from SynchronizeVisualProperties is usually processed before the
987 // renderer is painted.
988 SynchronizeVisualProperties();
990 if (synthetic_gesture_controller_) {
991 // Synthetic gestures queued while hidden are deferred until the widget
993 synthetic_gesture_controller_->StartIfNeeded();
997 void RenderWidgetHostImpl::RequestSuccessfulPresentationTimeForNextFrame(
998 blink::mojom::RecordContentToVisibleTimeRequestPtr visible_time_request) {
1000 DCHECK(visible_time_request);
1001 if (waiting_for_init_) {
1002 // This method should only be called if the RWHI is already visible, meaning
1003 // there will be a WasShown call that's queued until init. Update that with
1005 DCHECK(pending_show_params_);
1006 pending_show_params_->visible_time_request =
1007 std::move(visible_time_request);
1010 DCHECK(!pending_show_params_);
1011 blink_widget_->RequestSuccessfulPresentationTimeForNextFrame(
1012 std::move(visible_time_request));
1015 void RenderWidgetHostImpl::CancelSuccessfulPresentationTimeRequest() {
1016 DCHECK(!is_hidden_);
1017 if (waiting_for_init_) {
1018 // This method should only be called if the RWHI is already visible, meaning
1019 // there will be a WasShown call that's queued until init. Update that to
1020 // clear any request that was set.
1021 DCHECK(pending_show_params_);
1022 pending_show_params_->visible_time_request = nullptr;
1025 DCHECK(!pending_show_params_);
1026 blink_widget_->CancelSuccessfulPresentationTimeRequest();
1029 #if BUILDFLAG(IS_ANDROID)
1030 void RenderWidgetHostImpl::SetImportance(ChildProcessImportance importance) {
1031 if (importance_ == importance) {
1034 importance_ = importance;
1035 GetProcess()->UpdateClientPriority(this);
1038 void RenderWidgetHostImpl::AddImeInputEventObserver(
1039 RenderWidgetHost::InputEventObserver* observer) {
1040 if (!ime_input_event_observers_.HasObserver(observer)) {
1041 ime_input_event_observers_.AddObserver(observer);
1045 void RenderWidgetHostImpl::RemoveImeInputEventObserver(
1046 RenderWidgetHost::InputEventObserver* observer) {
1047 ime_input_event_observers_.RemoveObserver(observer);
1051 #if BUILDFLAG(IS_EFL)
1052 void RenderWidgetHostImpl::RequestBackgroundColor(int callback_id) {
1053 blink_widget_->GetBackgroundColor(
1054 base::BindOnce(&RenderWidgetHostImpl::OnGetBackgroundColor,
1055 weak_factory_.GetWeakPtr(), callback_id));
1058 void RenderWidgetHostImpl::OnGetBackgroundColor(int callback_id,
1062 view_->BackgroundColorReceived(callback_id, bg_color);
1065 void RenderWidgetHostImpl::RequestContentSnapshot(
1066 const gfx::Rect& snapshot_rect,
1067 float page_scale_factor,
1069 blink_widget_->GetContentSnapshot(
1070 snapshot_rect, page_scale_factor,
1071 base::BindOnce(&RenderWidgetHostImpl::OnGetContentSnapshot,
1072 weak_factory_.GetWeakPtr(), request_id));
1075 void RenderWidgetHostImpl::OnGetContentSnapshot(int request_id,
1076 const SkBitmap& bitmap) {
1079 view_->DidGetContentSnapshot(bitmap, request_id);
1082 void RenderWidgetHostImpl::UpdateFocusedNodeBounds() {
1083 blink_widget_->UpdateFocusedNodeBounds(
1084 base::BindOnce(&RenderWidgetHostImpl::OnGetFocusedNodeBounds,
1085 weak_factory_.GetWeakPtr()));
1088 void RenderWidgetHostImpl::OnGetFocusedNodeBounds(const gfx::RectF& rect) {
1091 view_->OnGetFocusedNodeBounds(rect);
1094 void RenderWidgetHostImpl::SetLongPollingGlobalTimeout(uint64_t timeout) {
1095 blink_widget_->SetLongPollingGlobalTimeout(timeout);
1098 void RenderWidgetHostImpl::PrintToPdf(int width,
1100 const base::FilePath& filename) {
1101 blink_widget_->PrintToPdf(width, height, filename);
1104 void RenderWidgetHostImpl::SetMainFrameScrollbarVisible(bool visible) {
1105 blink_widget_->SetMainFrameScrollbarVisible(visible);
1108 void RenderWidgetHostImpl::RequestMainFrameScrollbarVisible(int callback_id) {
1109 blink_widget_->RequestMainFrameScrollbarVisible(
1110 base::BindOnce(&RenderWidgetHostImpl::OnGetMainFrameScrollbarVisible,
1111 weak_factory_.GetWeakPtr(), callback_id));
1114 void RenderWidgetHostImpl::OnGetMainFrameScrollbarVisible(int callback_id,
1118 view_->OnGetMainFrameScrollbarVisible(callback_id, visible);
1121 void RenderWidgetHostImpl::QueryInputType() {
1122 blink_widget_->QueryInputType(base::BindOnce(
1123 &RenderWidgetHostImpl::OnChangeInputType, weak_factory_.GetWeakPtr()));
1126 void RenderWidgetHostImpl::OnChangeInputType(bool is_password_field) {
1129 view_->DidChangeInputType(is_password_field);
1132 void RenderWidgetHostImpl::SelectClosestWord(int x, int y) {
1133 blink_widget_->SelectClosestWord(x, y);
1136 void RenderWidgetHostImpl::SelectFocusedLink() {
1137 blink_widget_->SelectFocusedLink();
1140 void RenderWidgetHostImpl::RequestSelectionRect() {
1141 blink_widget_->RequestSelectionRect(base::BindOnce(
1142 &RenderWidgetHostImpl::OnGetSelectionRect, weak_factory_.GetWeakPtr()));
1145 void RenderWidgetHostImpl::OnGetSelectionRect(const gfx::Rect& rect) {
1148 view_->OnSelectionRectReceived(rect);
1151 void RenderWidgetHostImpl::ResetLastInteractedElements() {
1152 blink_widget_->ResetLastInteractedElements();
1155 #if BUILDFLAG(IS_TIZEN_TV)
1156 void RenderWidgetHostImpl::SetFloatVideoWindowState(bool enabled) {
1157 blink_widget_->SetFloatVideoWindowState(enabled);
1160 void RenderWidgetHostImpl::SuspendNetworkLoading() {
1161 if (!waiting_for_init_) {
1162 if (!blink_widget_) {
1163 LOG(ERROR) << "Bind WidgetInterfaces still not finish";
1166 blink_widget_->SuspendNetworkLoading();
1168 if (pending_suspend_network_loading_closure_)
1169 pending_suspend_network_loading_closure_.Reset();
1171 LOG(INFO) << "set pending SuspendNetworkLoading";
1172 pending_suspend_network_loading_closure_ =
1173 base::BindOnce(&RenderWidgetHostImpl::RunPendingSuspendNetworkLoading,
1174 base::Unretained(this));
1178 void RenderWidgetHostImpl::RunPendingSuspendNetworkLoading() {
1179 if (!blink_widget_) {
1180 LOG(ERROR) << "Bind WidgetInterfaces still not finish";
1183 blink_widget_->SuspendNetworkLoading();
1186 void RenderWidgetHostImpl::ResumeNetworkLoading() {
1187 if (!waiting_for_init_) {
1188 if (!blink_widget_) {
1189 LOG(ERROR) << "Bind WidgetInterfaces still not finish";
1192 blink_widget_->ResumeNetworkLoading();
1194 if (pending_resume_network_loading_closure_)
1195 pending_resume_network_loading_closure_.Reset();
1197 LOG(INFO) << "set pending ResumeNetworkLoading";
1198 pending_resume_network_loading_closure_ =
1199 base::BindOnce(&RenderWidgetHostImpl::RunPendingResumeNetworkLoading,
1200 base::Unretained(this));
1204 void RenderWidgetHostImpl::RunPendingResumeNetworkLoading() {
1205 if (!blink_widget_) {
1206 LOG(ERROR) << "Bind WidgetInterfaces still not finish";
1209 blink_widget_->ResumeNetworkLoading();
1211 #endif // IS_TIZEN_TV
1214 blink::VisualProperties RenderWidgetHostImpl::GetInitialVisualProperties() {
1215 blink::VisualProperties initial_props = GetVisualProperties();
1217 // A RenderWidget being created in the renderer means the browser should
1218 // reset any state that may be set for the previous RenderWidget but which
1219 // will be incorrect with a fresh RenderWidget.
1220 ResetStateForCreatedRenderWidget(initial_props);
1222 return initial_props;
1225 blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
1226 // This is only called while the RenderWidgetHost is attached to a delegate
1229 // When the renderer process is gone, there's no need for VisualProperties
1230 // which are to be sent to the renderer process.
1233 // Differentiate between widgets for frames vs widgets for popups/pepper.
1234 // Historically this was done by finding the RenderViewHost for the widget,
1235 // but a child local root would not convert to a RenderViewHost but is for a
1237 const bool is_frame_widget = !self_owned_;
1239 blink::VisualProperties visual_properties;
1240 visual_properties.screen_infos = GetScreenInfos();
1241 auto& current_screen_info = visual_properties.screen_infos.mutable_current();
1243 // For testing, override the raster color profile.
1244 // Note: this needs to be done here and not earlier in the pipeline because
1245 // Mac uses the display color space to update an NSSurface and this setting
1246 // is only for "raster" color space.
1247 if (display::Display::HasForceRasterColorProfile()) {
1248 for (auto& screen_info : visual_properties.screen_infos.screen_infos) {
1249 screen_info.display_color_spaces = gfx::DisplayColorSpaces(
1250 display::Display::GetForcedRasterColorProfile());
1254 visual_properties.is_fullscreen_granted = delegate_->IsFullscreen();
1256 if (is_frame_widget) {
1257 visual_properties.display_mode = delegate_->GetDisplayMode();
1259 visual_properties.display_mode = blink::mojom::DisplayMode::kBrowser;
1261 visual_properties.zoom_level = delegate_->GetPendingPageZoomLevel();
1263 RenderViewHostDelegateView* rvh_delegate_view = delegate_->GetDelegateView();
1264 DCHECK(rvh_delegate_view);
1266 visual_properties.browser_controls_params.browser_controls_shrink_blink_size =
1267 rvh_delegate_view->DoBrowserControlsShrinkRendererSize();
1268 visual_properties.browser_controls_params
1269 .animate_browser_controls_height_changes =
1270 rvh_delegate_view->ShouldAnimateBrowserControlsHeightChanges();
1271 visual_properties.browser_controls_params
1272 .only_expand_top_controls_at_page_top =
1273 rvh_delegate_view->OnlyExpandTopControlsAtPageTop();
1275 visual_properties.browser_controls_params.top_controls_height =
1276 rvh_delegate_view->GetTopControlsHeight();
1277 visual_properties.browser_controls_params.top_controls_min_height =
1278 rvh_delegate_view->GetTopControlsMinHeight();
1279 visual_properties.browser_controls_params.bottom_controls_height =
1280 rvh_delegate_view->GetBottomControlsHeight();
1281 visual_properties.browser_controls_params.bottom_controls_min_height =
1282 rvh_delegate_view->GetBottomControlsMinHeight();
1284 visual_properties.auto_resize_enabled = auto_resize_enabled_;
1285 visual_properties.min_size_for_auto_resize = min_size_for_auto_resize_;
1286 visual_properties.max_size_for_auto_resize = max_size_for_auto_resize_;
1288 visual_properties.new_size = view_->GetRequestedRendererSize();
1290 // This widget is for a frame that is the main frame of the outermost frame
1291 // tree. That makes it the top-most frame. OR this is a non-frame widget.
1292 const bool is_top_most_widget = !view_->IsRenderWidgetHostViewChildFrame();
1293 // This widget is for a frame, but not the main frame of its frame tree.
1294 const bool is_child_frame_widget =
1295 view_->IsRenderWidgetHostViewChildFrame() && !owner_delegate_;
1297 // These properties come from the main frame RenderWidget and flow down the
1298 // tree of RenderWidgets. Some properties are global across all nested
1299 // WebContents/frame trees. Some properties are global only within their
1300 // WebContents/frame tree.
1302 // Each child frame RenderWidgetHost that inherits values gets them from their
1303 // parent RenderWidget in the renderer process. It then passes them along to
1304 // its own RenderWidget, and the process repeats down the tree.
1306 // The plumbing goes:
1307 // 1. Browser: parent RenderWidgetHost
1308 // 2. IPC -> blink::mojom::Widget::UpdateVisualProperties
1309 // 3. Renderer A: parent RenderWidget
1310 // (sometimes blink involved)
1311 // 4. Renderer A: child blink::RemoteFrame
1312 // 5. IPC -> FrameHostMsg_SynchronizeVisualProperties
1313 // 6. Browser: child CrossProcessFrameConnector
1314 // 7. Browser: parent RenderWidgetHost (We're here if |is_child_frame|.)
1315 // 8. IPC -> blink::mojom::Widget::UpdateVisualProperties
1316 // 9. Renderer B: child RenderWidget
1318 // This property comes from the top-level main frame.
1319 if (is_top_most_widget) {
1320 visual_properties.compositor_viewport_pixel_rect =
1321 gfx::Rect(view_->GetCompositorViewportPixelSize());
1322 visual_properties.window_controls_overlay_rect =
1323 delegate_->GetWindowsControlsOverlayRect();
1324 visual_properties.virtual_keyboard_resize_height_physical_px =
1325 delegate_->GetVirtualKeyboardResizeHeight();
1326 visual_properties.window_show_state = delegate_->GetWindowShowState();
1327 visual_properties.resizable = delegate_->GetResizable();
1329 visual_properties.compositor_viewport_pixel_rect =
1330 properties_from_parent_local_root_.compositor_viewport;
1331 visual_properties.window_show_state = ui::SHOW_STATE_DEFAULT;
1333 // These properties come from the top-level main frame's renderer. The
1334 // top-level main frame in the browser doesn't specify a value.
1335 visual_properties.page_scale_factor =
1336 properties_from_parent_local_root_.page_scale_factor;
1337 visual_properties.is_pinch_gesture_active =
1338 properties_from_parent_local_root_.is_pinch_gesture_active;
1341 visual_properties.compositing_scale_factor =
1342 properties_from_parent_local_root_.compositing_scale_factor;
1344 #if BUILDFLAG(IS_MAC)
1345 // Only macOS cursor scaling affects CSS custom cursor images for now.
1346 visual_properties.cursor_accessibility_scale_factor =
1347 ui::GetCursorAccessibilityScaleFactor();
1350 // The |visible_viewport_size| is affected by auto-resize which is magical and
1353 // For the top-level main frame, auto resize ends up asynchronously resizing
1354 // the widget's RenderWidgetHostView and the size will show up there, so
1355 // nothing needs to be written in here.
1357 // For nested main frames, auto resize happens in the renderer so we need to
1358 // store the size on this class and use that. When auto-resize is not enabled
1359 // we use the size of the nested main frame's RenderWidgetHostView.
1361 // For child frames, we always use the value provided from the parent.
1363 // For non-frame widgets, there is no auto-resize and we behave like the top-
1364 // level main frame.
1366 if (is_child_frame_widget) {
1367 viewport = properties_from_parent_local_root_.visible_viewport_size;
1369 viewport = view_->GetVisibleViewportSize();
1371 visual_properties.visible_viewport_size = viewport;
1373 // The root widget's window segments are computed here - child frames just
1374 // use the value provided from the parent.
1375 if (is_top_most_widget) {
1376 absl::optional<DisplayFeature> display_feature = view_->GetDisplayFeature();
1377 if (display_feature) {
1378 visual_properties.root_widget_window_segments =
1379 display_feature->ComputeWindowSegments(
1380 visual_properties.visible_viewport_size);
1382 visual_properties.root_widget_window_segments = {
1383 gfx::Rect(visual_properties.visible_viewport_size)};
1386 visual_properties.root_widget_window_segments =
1387 properties_from_parent_local_root_.root_widget_window_segments;
1390 visual_properties.capture_sequence_number = view_->GetCaptureSequenceNumber();
1392 // TODO(ccameron): GetLocalSurfaceId is not synchronized with the device
1393 // scale factor of the surface. Fix this.
1394 viz::LocalSurfaceId local_surface_id = view_->GetLocalSurfaceId();
1395 if (local_surface_id.is_valid()) {
1396 visual_properties.local_surface_id = local_surface_id;
1399 if (screen_orientation_type_for_testing_) {
1400 current_screen_info.orientation_type =
1401 *screen_orientation_type_for_testing_;
1404 if (screen_orientation_angle_for_testing_) {
1405 current_screen_info.orientation_angle =
1406 *screen_orientation_angle_for_testing_;
1409 return visual_properties;
1412 bool RenderWidgetHostImpl::UpdateVisualProperties(bool propagate) {
1413 return SynchronizeVisualProperties(false, propagate);
1416 bool RenderWidgetHostImpl::SynchronizeVisualProperties() {
1417 return SynchronizeVisualProperties(false, true);
1420 bool RenderWidgetHostImpl::SynchronizeVisualPropertiesIgnoringPendingAck() {
1421 visual_properties_ack_pending_ = false;
1422 return SynchronizeVisualProperties();
1425 bool RenderWidgetHostImpl::SynchronizeVisualProperties(
1426 bool scroll_focused_node_into_view,
1428 // If the RenderViewHost is inactive, then there is no RenderWidget that can
1429 // receive visual properties yet, even though we are setting them on the
1430 // browser side. Wait until there is a local main frame with a RenderWidget
1431 // to receive these before sending the visual properties.
1433 // When the RenderViewHost becomes active, a SynchronizeVisualProperties()
1434 // call does not explicitly get made. That is because RenderWidgets for frames
1435 // are created and initialized with a valid VisualProperties already, and once
1436 // their initial navigation completes (and they are in the foreground) the
1437 // RenderWidget will be shown, which means a VisualProperties update happens
1438 // at the time where compositing begins.
1440 // Note that this drops |scroll_focused_node_into_view| but this value does
1441 // not make sense for an inactive RenderViewHost's top level RenderWidgetHost,
1442 // because there is no frames associated with the RenderWidget when it is
1443 // inactive, so there is no focused node, or anything to scroll and display.
1444 if (owner_delegate_ && !owner_delegate_->IsMainFrameActive()) {
1447 // Sending VisualProperties are deferred until we have a connection to a
1448 // renderer-side Widget to send them to. Further, if we're waiting for the
1449 // renderer to show (aka Init()) the widget then we defer sending updates
1450 // until the renderer is ready.
1451 if (!renderer_widget_created_ || waiting_for_init_) {
1454 // TODO(danakj): The `renderer_widget_created_` flag is set to true for
1455 // widgets owned by inactive RenderViewHosts, even though there is no widget
1456 // created. In that case the `view_` will not be created.
1460 // Throttle to one update at a time.
1461 if (visual_properties_ack_pending_) {
1465 // Skip if the |delegate_| has already been detached because it's web contents
1466 // is being deleted, or if LocalSurfaceId is suppressed, as we are
1467 // first updating our internal state from a child's request, before
1468 // subsequently merging ids to send.
1469 if (!GetProcess()->IsInitializedAndNotDead() || !view_->HasSize() ||
1470 !delegate_ || surface_id_allocation_suppressed_ ||
1471 !view_->CanSynchronizeVisualProperties()) {
1475 auto visual_properties = std::make_unique<blink::VisualProperties>();
1476 *visual_properties = GetVisualProperties();
1477 if (!StoredVisualPropertiesNeedsUpdate(old_visual_properties_,
1478 *visual_properties)) {
1482 visual_properties->scroll_focused_node_into_view =
1483 scroll_focused_node_into_view;
1486 blink_widget_->UpdateVisualProperties(*visual_properties);
1489 bool width_changed =
1490 !old_visual_properties_ || old_visual_properties_->new_size.width() !=
1491 visual_properties->new_size.width();
1493 // WidgetBase::UpdateSurfaceAndScreenInfo uses similar logic to detect
1494 // orientation changes on the display currently showing the widget.
1495 // TODO(lanwei): clean the duplicate code.
1496 if (visual_properties && old_visual_properties_) {
1497 const auto& old_screen_info =
1498 old_visual_properties_->screen_infos.current();
1499 const auto& screen_info = visual_properties->screen_infos.current();
1500 bool orientation_changed =
1501 old_screen_info.orientation_angle != screen_info.orientation_angle ||
1502 old_screen_info.orientation_type != screen_info.orientation_type;
1503 if (orientation_changed) {
1504 delegate_->DidChangeScreenOrientation();
1508 input_router_->SetDeviceScaleFactor(
1509 visual_properties->screen_infos.current().device_scale_factor);
1511 // If we do not have a valid viz::LocalSurfaceId then we are a child frame
1512 // waiting on the id to be propagated from our parent. We cannot create a hash
1513 // for tracing of an invalid id.
1515 // TODO(jonross): Untangle startup so that we don't have this invalid partial
1516 // state. (https://crbug.com/1185286) (https://crbug.com/419087)
1517 if (visual_properties->local_surface_id.has_value()) {
1518 TRACE_EVENT_WITH_FLOW2(
1519 TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
1520 "RenderWidgetHostImpl::SynchronizeVisualProperties send message",
1521 visual_properties->local_surface_id->submission_trace_id(),
1522 TRACE_EVENT_FLAG_FLOW_OUT, "message",
1523 "WidgetMsg_SynchronizeVisualProperties", "local_surface_id",
1524 visual_properties->local_surface_id->ToString());
1526 visual_properties_ack_pending_ =
1527 DoesVisualPropertiesNeedAck(old_visual_properties_, *visual_properties);
1528 old_visual_properties_ = std::move(visual_properties);
1530 // Warning: |visual_properties| invalid after this point.
1533 delegate_->RenderWidgetWasResized(this, width_changed);
1539 void RenderWidgetHostImpl::GotFocus() {
1541 if (owner_delegate_) {
1542 owner_delegate_->RenderWidgetGotFocus();
1546 void RenderWidgetHostImpl::LostFocus() {
1548 if (owner_delegate_) {
1549 owner_delegate_->RenderWidgetLostFocus();
1551 has_lost_focus_ = true;
1554 void RenderWidgetHostImpl::Focus() {
1555 // TODO(crbug.com/689777): This sends it to the main frame RenderWidgetHost
1556 // should it be going to the local root instead?
1557 RenderWidgetHostImpl* focused_widget =
1558 delegate_ ? delegate_->GetRenderWidgetHostWithPageFocus() : nullptr;
1560 if (!focused_widget) {
1561 focused_widget = this;
1563 focused_widget->SetPageFocus(true);
1566 void RenderWidgetHostImpl::Blur() {
1567 // TODO(crbug.com/689777): This sends it to the main frame RenderWidgetHost
1568 // should it be going to the local root instead?
1569 RenderWidgetHostImpl* focused_widget =
1570 delegate_ ? delegate_->GetRenderWidgetHostWithPageFocus() : nullptr;
1572 if (!focused_widget) {
1573 focused_widget = this;
1575 focused_widget->SetPageFocus(false);
1578 void RenderWidgetHostImpl::FlushForTesting() {
1579 if (widget_input_handler_) {
1580 return widget_input_handler_.FlushForTesting();
1584 void RenderWidgetHostImpl::SetFocusInternal(bool focused) {
1585 blink::mojom::FocusState focus_state =
1586 blink::mojom::FocusState::kNotFocusedAndNotActive;
1588 focus_state = blink::mojom::FocusState::kFocused;
1589 else if (is_active_)
1590 focus_state = blink::mojom::FocusState::kNotFocusedAndActive;
1592 GetWidgetInputHandler()->SetFocus(focus_state);
1595 void RenderWidgetHostImpl::SetPageFocus(bool focused) {
1596 OPTIONAL_TRACE_EVENT1("content", "RenderWidgetHostImpl::SetPageFocus",
1597 "is_focused", focused);
1598 is_focused_ = focused;
1600 // If focused state is being set is_active must be true. Android does
1601 // not call SetActive so if we are trying to focus ensure `is_active`
1607 // Portals should never get page focus.
1608 DCHECK(!delegate_ || !delegate_->IsPortal() || !focused);
1611 // If there is a pending mouse lock request, we don't want to reject it at
1612 // this point. The user can switch focus back to this view and approve the
1614 if (IsMouseLocked()) {
1615 view_->UnlockMouse();
1618 if (IsKeyboardLocked()) {
1622 if (auto* touch_emulator = GetExistingTouchEmulator()) {
1623 touch_emulator->CancelTouch();
1625 } else if (keyboard_lock_allowed_) {
1629 #if BUILDFLAG(IS_TIZEN_TV)
1630 if (!waiting_for_init_) {
1631 SetFocusInternal(focused);
1633 if (pending_set_page_focus_closure_)
1634 pending_set_page_focus_closure_.Reset();
1637 LOG(INFO) << "set Pending SetPageFocus";
1638 pending_set_page_focus_closure_ =
1639 base::BindOnce(&RenderWidgetHostImpl::RunPendingSetPageFocus,
1640 base::Unretained(this), focused);
1643 SetFocusInternal(focused);
1646 // Also send page-level focus state to other SiteInstances involved in
1647 // rendering the current FrameTree, if this widget is for a main frame.
1648 // TODO(crbug.com/689777): We should be telling `frame_tree_` which
1649 // RenderWidgetHost was focused (if we send it to the focused one instead
1650 // of the main frame in order to order it correctly with other input events),
1651 // so that `frame_tree_` can propagate it to all other WebViews based on
1652 // where this RenderWidgetHost lives.
1653 if (owner_delegate_ && frame_tree_) {
1654 frame_tree_->ReplicatePageFocus(focused);
1658 #if BUILDFLAG(IS_TIZEN_TV)
1659 void RenderWidgetHostImpl::RunPendingSetPageFocus(bool focused) {
1660 SetFocusInternal(focused);
1664 void RenderWidgetHostImpl::LostCapture() {
1665 if (auto* touch_emulator = GetExistingTouchEmulator()) {
1666 touch_emulator->CancelTouch();
1669 GetWidgetInputHandler()->MouseCaptureLost();
1672 #if BUILDFLAG(IS_TIZEN_TV)
1673 void RenderWidgetHostImpl::RunPendingSetActive(bool active) {
1674 SetActiveInternal(active);
1678 void RenderWidgetHostImpl::SetActive(bool active) {
1679 #if BUILDFLAG(IS_TIZEN_TV)
1680 if (!waiting_for_init_) {
1681 SetActiveInternal(active);
1683 if (pending_set_active_closure_)
1684 pending_set_active_closure_.Reset();
1686 LOG(INFO) << "set pending setActive";
1687 pending_set_active_closure_ =
1688 base::BindOnce(&RenderWidgetHostImpl::RunPendingSetActive,
1689 base::Unretained(this), active);
1692 SetActiveInternal(active);
1696 void RenderWidgetHostImpl::SetActiveInternal(bool active) {
1697 is_active_ = active;
1698 if (blink_frame_widget_) {
1699 blink_frame_widget_->SetActive(active);
1703 void RenderWidgetHostImpl::LostMouseLock() {
1705 delegate_->LostMouseLock(this);
1709 void RenderWidgetHostImpl::SendMouseLockLost() {
1710 mouse_lock_context_.reset();
1713 void RenderWidgetHostImpl::ViewDestroyed() {
1714 CancelKeyboardLock();
1715 RejectMouseLockOrUnlockIfNecessary(
1716 blink::mojom::PointerLockResult::kElementDestroyed);
1718 // TODO(evanm): tracking this may no longer be necessary;
1719 // eliminate this function if so.
1723 bool RenderWidgetHostImpl::RequestRepaintForTesting() {
1728 return view_->RequestRepaintForTesting();
1731 void RenderWidgetHostImpl::RenderProcessBlockedStateChanged(bool blocked) {
1733 StopInputEventAckTimeout();
1735 RestartInputEventAckTimeoutIfNecessary();
1739 void RenderWidgetHostImpl::StartInputEventAckTimeout() {
1740 if (should_disable_hang_monitor_) {
1744 if (!input_event_ack_timeout_.IsRunning()) {
1745 input_event_ack_timeout_.Start(
1746 FROM_HERE, hung_renderer_delay_,
1747 base::BindOnce(&RenderWidgetHostImpl::OnInputEventAckTimeout,
1748 weak_factory_.GetWeakPtr()));
1752 void RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary() {
1753 if (!GetProcess()->IsBlocked() && !should_disable_hang_monitor_ &&
1754 in_flight_event_count_ > 0 && !is_hidden_) {
1755 input_event_ack_timeout_.Start(
1756 FROM_HERE, hung_renderer_delay_,
1757 base::BindOnce(&RenderWidgetHostImpl::OnInputEventAckTimeout,
1758 weak_factory_.GetWeakPtr()));
1762 bool RenderWidgetHostImpl::IsCurrentlyUnresponsive() {
1763 return is_unresponsive_;
1766 void RenderWidgetHostImpl::StopInputEventAckTimeout() {
1767 input_event_ack_timeout_.Stop();
1768 RendererIsResponsive();
1771 void RenderWidgetHostImpl::DidNavigate() {
1772 // Stop the flinging after navigating to a new page.
1775 // Resize messages before navigation are not acked, so reset
1776 // |visual_properties_ack_pending_| and make sure the next resize will be
1777 // acked if the last resize before navigation was supposed to be acked.
1778 visual_properties_ack_pending_ = false;
1780 view_->DidNavigate();
1783 ClearPendingUserActivation();
1786 void RenderWidgetHostImpl::StartNewContentRenderingTimeout() {
1787 if (!new_content_rendering_timeout_) {
1790 new_content_rendering_timeout_->Start(new_content_rendering_delay_);
1793 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
1794 ForwardMouseEventWithLatencyInfo(mouse_event,
1795 ui::LatencyInfo(ui::SourceEventType::MOUSE));
1796 if (owner_delegate_) {
1797 owner_delegate_->RenderWidgetDidForwardMouseEvent(mouse_event);
1801 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
1802 const WebMouseEvent& mouse_event,
1803 const ui::LatencyInfo& latency) {
1804 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent", "x",
1805 mouse_event.PositionInWidget().x(), "y",
1806 mouse_event.PositionInWidget().y());
1808 DCHECK_GE(mouse_event.GetType(), WebInputEvent::Type::kMouseTypeFirst);
1809 DCHECK_LE(mouse_event.GetType(), WebInputEvent::Type::kMouseTypeLast);
1811 // This is used to auto-disable accessibility if we detect user input
1812 // but no accessibility API usage.
1813 if (mouse_event.GetType() == WebInputEvent::Type::kMouseDown) {
1814 BrowserAccessibilityStateImpl::GetInstance()->OnUserInputEvent();
1817 for (auto& mouse_event_callback : mouse_event_callbacks_) {
1818 if (mouse_event_callback.Run(mouse_event)) {
1823 if (IsIgnoringInputEvents()) {
1827 auto* touch_emulator = GetExistingTouchEmulator();
1828 if (touch_emulator &&
1829 touch_emulator->HandleMouseEvent(mouse_event, GetView())) {
1833 MouseEventWithLatencyInfo mouse_with_latency(mouse_event, latency);
1834 DispatchInputEventWithLatencyInfo(
1835 mouse_with_latency.event, &mouse_with_latency.latency,
1836 &mouse_with_latency.event.GetModifiableEventLatencyMetadata());
1837 input_router_->SendMouseEvent(
1838 mouse_with_latency, base::BindOnce(&RenderWidgetHostImpl::OnMouseEventAck,
1839 weak_factory_.GetWeakPtr()));
1842 void RenderWidgetHostImpl::ForwardWheelEvent(
1843 const WebMouseWheelEvent& wheel_event) {
1844 ForwardWheelEventWithLatencyInfo(wheel_event,
1845 ui::LatencyInfo(ui::SourceEventType::WHEEL));
1848 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
1849 const WebMouseWheelEvent& wheel_event,
1850 const ui::LatencyInfo& latency) {
1851 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardWheelEvent", "dx",
1852 wheel_event.delta_x, "dy", wheel_event.delta_y);
1854 if (IsIgnoringInputEvents()) {
1858 auto* touch_emulator = GetExistingTouchEmulator();
1859 if (touch_emulator && touch_emulator->HandleMouseWheelEvent(wheel_event)) {
1863 MouseWheelEventWithLatencyInfo wheel_with_latency(wheel_event, latency);
1864 DispatchInputEventWithLatencyInfo(
1865 wheel_with_latency.event, &wheel_with_latency.latency,
1866 &wheel_with_latency.event.GetModifiableEventLatencyMetadata());
1867 input_router_->SendWheelEvent(wheel_with_latency);
1870 void RenderWidgetHostImpl::WaitForInputProcessed(
1871 SyntheticGestureParams::GestureType type,
1872 content::mojom::GestureSourceType source,
1873 base::OnceClosure callback) {
1874 // TODO(bokan): Input can be queued and delayed in InputRouterImpl based on
1875 // the kind of events we're getting. To be truly robust, we should wait until
1876 // those queues are flushed before issuing this message. This will be done in
1877 // a follow-up and is the reason for the currently unused type and source
1878 // params. https://crbug.com/902446.
1879 WaitForInputProcessed(std::move(callback));
1882 void RenderWidgetHostImpl::WaitForInputProcessed(base::OnceClosure callback) {
1883 // TODO(bokan): The RequestPresentationCallback mechanism doesn't seem to
1884 // work in OOPIFs. For now, just callback immediately. Remove when fixed.
1885 // https://crbug.com/924646.
1886 if (GetView()->IsRenderWidgetHostViewChildFrame()) {
1887 std::move(callback).Run();
1891 input_router_->WaitForInputProcessed(std::move(callback));
1894 void RenderWidgetHostImpl::ForwardGestureEvent(
1895 const WebGestureEvent& gesture_event) {
1896 ForwardGestureEventWithLatencyInfo(
1898 ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
1902 void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
1903 const WebGestureEvent& gesture_event,
1904 const ui::LatencyInfo& latency) {
1905 TRACE_EVENT1("input", "RenderWidgetHostImpl::ForwardGestureEvent", "type",
1906 WebInputEvent::GetName(gesture_event.GetType()));
1908 // This is used to auto-disable accessibility if we detect user input
1909 // but no accessibility API usage.
1910 if (gesture_event.GetType() == WebInputEvent::Type::kGestureTapDown) {
1911 BrowserAccessibilityStateImpl::GetInstance()->OnUserInputEvent();
1914 // Early out if necessary, prior to performing latency logic.
1915 if (IsIgnoringInputEvents()) {
1919 // The gesture events must have a known source.
1920 DCHECK_NE(gesture_event.SourceDevice(),
1921 blink::WebGestureDevice::kUninitialized);
1923 if (gesture_event.GetType() ==
1924 WebInputEvent::Type::kGestureScrollBegin) {
1926 !is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())]);
1927 is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())] =
1929 NotifyUISchedulerOfScrollStateUpdate(
1930 BrowserUIThreadScheduler::ScrollState::kGestureScrollActive);
1931 scroll_peak_gpu_mem_tracker_ =
1932 PeakGpuMemoryTracker::Create(PeakGpuMemoryTracker::Usage::SCROLL);
1933 } else if (gesture_event.GetType() ==
1934 WebInputEvent::Type::kGestureScrollEnd) {
1936 is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())]);
1937 is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())] =
1939 NotifyUISchedulerOfScrollStateUpdate(
1940 BrowserUIThreadScheduler::ScrollState::kNone);
1941 is_in_touchpad_gesture_fling_ = false;
1943 if (scroll_peak_gpu_mem_tracker_ &&
1944 !view_->is_currently_scrolling_viewport()) {
1945 // We start tracking peak gpu-memory usage when the initial scroll-begin
1946 // is dispatched. However, it is possible that the scroll-begin did not
1947 // trigger any scrolls (e.g. the page is not scrollable). In such cases,
1948 // we do not want to report the peak-memory usage metric. So it is
1950 scroll_peak_gpu_mem_tracker_->Cancel();
1953 view_->set_is_currently_scrolling_viewport(false);
1955 scroll_peak_gpu_mem_tracker_ = nullptr;
1956 } else if (gesture_event.GetType() ==
1957 WebInputEvent::Type::kGestureFlingStart) {
1958 NotifyUISchedulerOfScrollStateUpdate(
1959 BrowserUIThreadScheduler::ScrollState::kFlingActive);
1960 if (gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchpad) {
1961 // a GSB event is generated from the first wheel event in a sequence after
1962 // the event is acked as not consumed by the renderer. Sometimes when the
1963 // main thread is busy/slow (e.g ChromeOS debug builds) a GFS arrives
1964 // before the first wheel is acked. In these cases no GSB will arrive
1965 // before the GFS. With browser side fling the out of order GFS arrival
1966 // does not need a DCHECK since the fling controller will process the GFS
1967 // and start queuing wheel events which will follow the one currently
1968 // awaiting ACK and the renderer receives the events in order.
1970 is_in_touchpad_gesture_fling_ = true;
1972 DCHECK(is_in_gesture_scroll_[static_cast<int>(
1973 gesture_event.SourceDevice())]);
1975 // The FlingController handles GFS with touchscreen source and sends GSU
1976 // events with inertial state to the renderer to progress the fling.
1977 // is_in_gesture_scroll must stay true till the fling progress is
1978 // finished. Then the FlingController will generate and send a GSE which
1979 // shows the end of a scroll sequence and resets is_in_gesture_scroll_.
1983 // Delegate must be non-null, due to |IsIgnoringInputEvents()| test.
1984 if (delegate_->PreHandleGestureEvent(gesture_event)) {
1988 GestureEventWithLatencyInfo gesture_with_latency(gesture_event, latency);
1989 DispatchInputEventWithLatencyInfo(
1990 gesture_with_latency.event, &gesture_with_latency.latency,
1991 &gesture_with_latency.event.GetModifiableEventLatencyMetadata());
1992 input_router_->SendGestureEvent(gesture_with_latency);
1995 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1996 const blink::WebTouchEvent& touch_event,
1997 const ui::LatencyInfo& latency) {
1998 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
2000 // This is used to auto-disable accessibility if we detect user input
2001 // but no accessibility API usage.
2002 if (touch_event.GetType() == WebInputEvent::Type::kTouchStart) {
2003 BrowserAccessibilityStateImpl::GetInstance()->OnUserInputEvent();
2006 // Always forward TouchEvents for touch stream consistency. They will be
2007 // ignored if appropriate in FilterInputEvent().
2009 TouchEventWithLatencyInfo touch_with_latency(touch_event, latency);
2010 DispatchInputEventWithLatencyInfo(
2011 touch_with_latency.event, &touch_with_latency.latency,
2012 &touch_with_latency.event.GetModifiableEventLatencyMetadata());
2013 input_router_->SendTouchEvent(touch_with_latency);
2016 void RenderWidgetHostImpl::ForwardKeyboardEvent(
2017 const NativeWebKeyboardEvent& key_event) {
2018 ui::LatencyInfo latency_info;
2020 if (key_event.GetType() == WebInputEvent::Type::kRawKeyDown ||
2021 key_event.GetType() == WebInputEvent::Type::kChar) {
2022 latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
2024 ForwardKeyboardEventWithLatencyInfo(key_event, latency_info);
2027 void RenderWidgetHostImpl::ForwardKeyboardEventWithLatencyInfo(
2028 const NativeWebKeyboardEvent& key_event,
2029 const ui::LatencyInfo& latency) {
2030 ForwardKeyboardEventWithCommands(
2031 key_event, latency, std::vector<blink::mojom::EditCommandPtr>(), nullptr);
2034 void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
2035 const NativeWebKeyboardEvent& key_event,
2036 const ui::LatencyInfo& latency,
2037 std::vector<blink::mojom::EditCommandPtr> commands,
2038 bool* update_event) {
2039 DCHECK(WebInputEvent::IsKeyboardEventType(key_event.GetType()));
2041 // This is used to auto-disable accessibility if we detect user input
2042 // but no accessibility API usage.
2043 if (key_event.GetType() == WebInputEvent::Type::kRawKeyDown ||
2044 key_event.GetType() == WebInputEvent::Type::kKeyDown) {
2045 BrowserAccessibilityStateImpl::GetInstance()->OnUserInputEvent();
2048 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
2049 if (owner_delegate_ &&
2050 !owner_delegate_->MayRenderWidgetForwardKeyboardEvent(key_event)) {
2054 if (IsIgnoringInputEvents()) {
2058 if (!GetProcess()->IsInitializedAndNotDead()) {
2062 // First, let keypress listeners take a shot at handling the event. If a
2063 // listener handles the event, it should not be propagated to the renderer.
2064 if (KeyPressListenersHandleEvent(key_event)) {
2065 // Some keypresses that are accepted by the listener may be followed by Char
2066 // and KeyUp events, which should be ignored.
2067 if (key_event.GetType() == WebKeyboardEvent::Type::kRawKeyDown) {
2068 suppress_events_until_keydown_ = true;
2073 if (suppress_events_until_keydown_) {
2074 // If the preceding RawKeyDown event was handled by the browser, then we
2075 // need to suppress all events generated by it until the next RawKeyDown or
2077 if (key_event.GetType() == WebKeyboardEvent::Type::kKeyUp ||
2078 key_event.GetType() == WebKeyboardEvent::Type::kChar) {
2081 DCHECK(key_event.GetType() == WebKeyboardEvent::Type::kRawKeyDown ||
2082 key_event.GetType() == WebKeyboardEvent::Type::kKeyDown);
2083 suppress_events_until_keydown_ = false;
2086 bool is_shortcut = false;
2088 // Only pre-handle the key event if it's not handled by the input method.
2089 if (delegate_ && !key_event.skip_if_unhandled) {
2090 // We need to set |suppress_events_until_keydown_| to true if
2091 // PreHandleKeyboardEvent() handles the event, but |this| may already be
2092 // destroyed at that time. So set |suppress_events_until_keydown_| true
2093 // here, then revert it afterwards when necessary.
2094 if (key_event.GetType() == WebKeyboardEvent::Type::kRawKeyDown) {
2095 suppress_events_until_keydown_ = true;
2098 // Tab switching/closing accelerators aren't sent to the renderer to avoid
2099 // a hung/malicious renderer from interfering.
2100 switch (delegate_->PreHandleKeyboardEvent(key_event)) {
2101 case KeyboardEventProcessingResult::HANDLED:
2103 #if defined(USE_AURA)
2104 case KeyboardEventProcessingResult::HANDLED_DONT_UPDATE_EVENT:
2106 *update_event = false;
2110 case KeyboardEventProcessingResult::NOT_HANDLED:
2112 case KeyboardEventProcessingResult::NOT_HANDLED_IS_SHORTCUT:
2117 if (key_event.GetType() == WebKeyboardEvent::Type::kRawKeyDown) {
2118 suppress_events_until_keydown_ = false;
2122 auto* touch_emulator = GetExistingTouchEmulator();
2123 if (touch_emulator && touch_emulator->HandleKeyboardEvent(key_event)) {
2126 NativeWebKeyboardEventWithLatencyInfo key_event_with_latency(key_event,
2128 key_event_with_latency.event.is_browser_shortcut = is_shortcut;
2129 DispatchInputEventWithLatencyInfo(
2130 key_event_with_latency.event, &key_event_with_latency.latency,
2131 &key_event_with_latency.event.GetModifiableEventLatencyMetadata());
2132 // TODO(foolip): |InputRouter::SendKeyboardEvent()| may filter events, in
2133 // which the commands will be treated as belonging to the next key event.
2134 // WidgetInputHandler::SetEditCommandsForNextKeyEvent should only be sent if
2135 // WidgetInputHandler::DispatchEvent is, but has to be sent first.
2136 // https://crbug.com/684298
2137 if (!commands.empty()) {
2138 GetWidgetInputHandler()->SetEditCommandsForNextKeyEvent(
2139 std::move(commands));
2142 input_router_->SendKeyboardEvent(
2143 key_event_with_latency,
2144 base::BindOnce(&RenderWidgetHostImpl::OnKeyboardEventAck,
2145 weak_factory_.GetWeakPtr()));
2148 void RenderWidgetHostImpl::CreateSyntheticGestureControllerIfNecessary() {
2149 if (!synthetic_gesture_controller_ && view_) {
2150 synthetic_gesture_controller_ =
2151 std::make_unique<SyntheticGestureController>(
2152 this, view_->CreateSyntheticGestureTarget());
2156 void RenderWidgetHostImpl::QueueSyntheticGesture(
2157 std::unique_ptr<SyntheticGesture> synthetic_gesture,
2158 base::OnceCallback<void(SyntheticGesture::Result)> on_complete) {
2159 CreateSyntheticGestureControllerIfNecessary();
2160 if (synthetic_gesture_controller_) {
2161 synthetic_gesture_controller_->QueueSyntheticGesture(
2162 std::move(synthetic_gesture), std::move(on_complete));
2166 void RenderWidgetHostImpl::QueueSyntheticGestureCompleteImmediately(
2167 std::unique_ptr<SyntheticGesture> synthetic_gesture) {
2168 CreateSyntheticGestureControllerIfNecessary();
2169 if (synthetic_gesture_controller_) {
2170 synthetic_gesture_controller_->QueueSyntheticGestureCompleteImmediately(
2171 std::move(synthetic_gesture));
2175 void RenderWidgetHostImpl::EnsureReadyForSyntheticGestures(
2176 base::OnceClosure on_ready) {
2177 CreateSyntheticGestureControllerIfNecessary();
2178 if (synthetic_gesture_controller_) {
2179 synthetic_gesture_controller_->EnsureRendererInitialized(
2180 std::move(on_ready));
2182 // If we couldn't create a SyntheticGestureController then we won't ever be
2183 // ready. Invoke the callback to unblock the calling code.
2184 std::move(on_ready).Run();
2188 void RenderWidgetHostImpl::TakeSyntheticGestureController(
2189 RenderWidgetHostImpl* host) {
2190 DCHECK(!synthetic_gesture_controller_);
2191 if (host->synthetic_gesture_controller_) {
2192 synthetic_gesture_controller_ =
2193 std::move(host->synthetic_gesture_controller_);
2194 synthetic_gesture_controller_->UpdateSyntheticGestureTarget(
2195 view_->CreateSyntheticGestureTarget(), this);
2199 void RenderWidgetHostImpl::OnCursorVisibilityStateChanged(bool is_visible) {
2200 GetWidgetInputHandler()->CursorVisibilityChanged(is_visible);
2204 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
2205 g_check_for_pending_visual_properties_ack = false;
2208 void RenderWidgetHostImpl::AddKeyPressEventCallback(
2209 const KeyPressEventCallback& callback) {
2210 DCHECK(!base::Contains(key_press_event_callbacks_, callback));
2211 key_press_event_callbacks_.push_back(callback);
2214 void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
2215 const KeyPressEventCallback& callback) {
2216 base::Erase(key_press_event_callbacks_, callback);
2219 void RenderWidgetHostImpl::AddMouseEventCallback(
2220 const MouseEventCallback& callback) {
2221 DCHECK(!base::Contains(mouse_event_callbacks_, callback));
2222 mouse_event_callbacks_.push_back(callback);
2225 void RenderWidgetHostImpl::RemoveMouseEventCallback(
2226 const MouseEventCallback& callback) {
2227 base::Erase(mouse_event_callbacks_, callback);
2230 void RenderWidgetHostImpl::AddSuppressShowingImeCallback(
2231 const SuppressShowingImeCallback& callback) {
2232 DCHECK(!base::Contains(suppress_showing_ime_callbacks_, callback));
2233 suppress_showing_ime_callbacks_.push_back(callback);
2236 void RenderWidgetHostImpl::RemoveSuppressShowingImeCallback(
2237 const SuppressShowingImeCallback& callback) {
2238 base::Erase(suppress_showing_ime_callbacks_, callback);
2241 void RenderWidgetHostImpl::AddInputEventObserver(
2242 RenderWidgetHost::InputEventObserver* observer) {
2243 if (!input_event_observers_.HasObserver(observer)) {
2244 input_event_observers_.AddObserver(observer);
2248 void RenderWidgetHostImpl::RemoveInputEventObserver(
2249 RenderWidgetHost::InputEventObserver* observer) {
2250 input_event_observers_.RemoveObserver(observer);
2253 void RenderWidgetHostImpl::AddObserver(RenderWidgetHostObserver* observer) {
2254 observers_.AddObserver(observer);
2257 void RenderWidgetHostImpl::RemoveObserver(RenderWidgetHostObserver* observer) {
2258 observers_.RemoveObserver(observer);
2261 display::ScreenInfo RenderWidgetHostImpl::GetScreenInfo() const {
2262 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetScreenInfo");
2265 return view_->GetScreenInfo();
2268 // If this widget has not been connected to a view yet (or has been
2269 // disconnected), the display code may be using a fake primary display.
2270 display::ScreenInfo screen_info;
2271 display::DisplayUtil::GetDefaultScreenInfo(&screen_info);
2275 display::ScreenInfos RenderWidgetHostImpl::GetScreenInfos() const {
2276 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetScreenInfos");
2278 return view_ ? view_->GetScreenInfos()
2279 : display::ScreenInfos(GetScreenInfo());
2282 float RenderWidgetHostImpl::GetDeviceScaleFactor() {
2283 return GetScaleFactorForView(view_.get());
2286 absl::optional<cc::TouchAction> RenderWidgetHostImpl::GetAllowedTouchAction() {
2287 return input_router_->AllowedTouchAction();
2290 void RenderWidgetHostImpl::WriteIntoTrace(perfetto::TracedValue context) {
2291 auto dict = std::move(context).WriteDictionary();
2292 dict.Add("routing_id", GetRoutingID());
2295 void RenderWidgetHostImpl::DragTargetDragEnter(
2296 const DropData& drop_data,
2297 const gfx::PointF& client_pt,
2298 const gfx::PointF& screen_pt,
2299 DragOperationsMask operations_allowed,
2301 DragOperationCallback callback) {
2302 DragTargetDragEnterWithMetaData(DropDataToMetaData(drop_data), client_pt,
2303 screen_pt, operations_allowed, key_modifiers,
2304 std::move(callback));
2307 void RenderWidgetHostImpl::DragTargetDragEnterWithMetaData(
2308 const std::vector<DropData::Metadata>& metadata,
2309 const gfx::PointF& client_pt,
2310 const gfx::PointF& screen_pt,
2311 DragOperationsMask operations_allowed,
2313 DragOperationCallback callback) {
2314 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2315 if (blink_frame_widget_) {
2316 DragOperationCallback callback_wrapper =
2317 base::BindOnce(&RenderWidgetHostImpl::OnUpdateDragOperation,
2318 base::Unretained(this), std::move(callback));
2319 blink_frame_widget_->DragTargetDragEnter(
2320 DropMetaDataToDragData(metadata),
2321 ConvertWindowPointToViewport(client_pt), screen_pt, operations_allowed,
2322 key_modifiers, std::move(callback_wrapper));
2326 void RenderWidgetHostImpl::DragTargetDragOver(
2327 const gfx::PointF& client_point,
2328 const gfx::PointF& screen_point,
2329 DragOperationsMask operations_allowed,
2331 DragOperationCallback callback) {
2332 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2333 if (blink_frame_widget_) {
2334 blink_frame_widget_->DragTargetDragOver(
2335 ConvertWindowPointToViewport(client_point), screen_point,
2336 operations_allowed, key_modifiers,
2337 base::BindOnce(&RenderWidgetHostImpl::OnUpdateDragOperation,
2338 base::Unretained(this), std::move(callback)));
2342 void RenderWidgetHostImpl::DragTargetDragLeave(
2343 const gfx::PointF& client_point,
2344 const gfx::PointF& screen_point) {
2345 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2346 if (blink_frame_widget_) {
2347 blink_frame_widget_->DragTargetDragLeave(
2348 ConvertWindowPointToViewport(client_point), screen_point);
2352 void RenderWidgetHostImpl::DragTargetDrop(const DropData& drop_data,
2353 const gfx::PointF& client_point,
2354 const gfx::PointF& screen_point,
2356 base::OnceClosure callback) {
2357 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2358 if (blink_frame_widget_) {
2359 DropData drop_data_with_permissions(drop_data);
2360 GrantFileAccessFromDropData(&drop_data_with_permissions);
2361 StoragePartitionImpl* storage_partition =
2362 static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition());
2363 blink_frame_widget_->DragTargetDrop(
2364 DropDataToDragData(drop_data_with_permissions,
2365 storage_partition->GetFileSystemAccessManager(),
2366 GetProcess()->GetID(),
2367 ChromeBlobStorageContext::GetFor(
2368 GetProcess()->GetBrowserContext())),
2369 ConvertWindowPointToViewport(client_point), screen_point, key_modifiers,
2370 std::move(callback));
2374 void RenderWidgetHostImpl::DragSourceEndedAt(const gfx::PointF& client_point,
2375 const gfx::PointF& screen_point,
2376 ui::mojom::DragOperation operation,
2377 base::OnceClosure callback) {
2378 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2379 if (!blink_frame_widget_) {
2382 blink_frame_widget_->DragSourceEndedAt(
2383 ConvertWindowPointToViewport(client_point), screen_point, operation,
2384 std::move(callback));
2386 devtools_instrumentation::DragEnded(*frame_tree_->root());
2390 void RenderWidgetHostImpl::DragSourceSystemDragEnded() {
2391 // TODO(https://crbug.com/1102769): Replace with a for_frame() check.
2392 if (!blink_frame_widget_) {
2395 blink_frame_widget_->DragSourceSystemDragEnded();
2397 devtools_instrumentation::DragEnded(*frame_tree_->root());
2401 void RenderWidgetHostImpl::FilterDropData(DropData* drop_data) {
2403 drop_data->view_id = GetRoutingID();
2404 #endif // DCHECK_IS_ON()
2406 GetProcess()->FilterURL(true, &drop_data->url);
2407 if (drop_data->did_originate_from_renderer) {
2408 drop_data->filenames.clear();
2412 void RenderWidgetHostImpl::SetCursor(const ui::Cursor& cursor) {
2414 view_->UpdateCursor(cursor);
2418 void RenderWidgetHostImpl::ShowContextMenuAtPoint(
2419 const gfx::Point& point,
2420 const ui::MenuSourceType source_type) {
2421 if (blink_frame_widget_) {
2422 blink_frame_widget_->ShowContextMenu(source_type, point);
2426 void RenderWidgetHostImpl::InsertVisualStateCallback(
2427 VisualStateCallback callback) {
2428 if (!blink_frame_widget_) {
2429 std::move(callback).Run(false);
2433 if (!widget_compositor_) {
2434 blink_frame_widget_->BindWidgetCompositor(
2435 widget_compositor_.BindNewPipeAndPassReceiver(
2436 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput})));
2439 widget_compositor_->VisualStateRequest(base::BindOnce(
2440 [](VisualStateCallback callback) { std::move(callback).Run(true); },
2441 mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), false)));
2444 RenderProcessHostPriorityClient::Priority RenderWidgetHostImpl::GetPriority() {
2445 RenderProcessHostPriorityClient::Priority priority = {
2448 intersects_viewport_,
2449 #if BUILDFLAG(IS_ANDROID)
2453 if (owner_delegate_ &&
2454 !owner_delegate_->ShouldContributePriorityToProcess()) {
2455 priority.is_hidden = true;
2456 priority.frame_depth = RenderProcessHostImpl::kMaxFrameDepthForPriority;
2457 #if BUILDFLAG(IS_ANDROID)
2458 priority.importance = ChildProcessImportance::NORMAL;
2464 void RenderWidgetHostImpl::RenderProcessExited(
2465 RenderProcessHost* host,
2466 const ChildProcessTerminationInfo& info) {
2468 Destroy(/*also_delete=*/true); // Delete |this|.
2471 blink::mojom::WidgetInputHandler*
2472 RenderWidgetHostImpl::GetWidgetInputHandler() {
2473 if (widget_input_handler_) {
2474 return widget_input_handler_.get();
2476 // TODO(dtapuska): Remove the need for the unbound interface. It is
2477 // possible that a RVHI may make calls to a WidgetInputHandler when
2478 // the main frame is remote. This is because of ordering issues during
2479 // widget shutdown, so we present an UnboundWidgetInputHandler had
2480 // DLOGS the message calls.
2481 return g_unbound_input_handler.Pointer();
2484 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
2485 // The resize message (which may not happen immediately) will carry with it
2486 // the screen info as well as the new size (if the screen has changed scale
2487 // factor). Force sending the new visual properties even if there is one in
2488 // flight to ensure proper IPC ordering for features like the Fullscreen API.
2489 SynchronizeVisualPropertiesIgnoringPendingAck();
2491 // The device scale factor will be same for all the views contained by the
2492 // primary main frame, so just set it once.
2493 if (delegate_ && !delegate_->IsWidgetForPrimaryMainFrame(this)) {
2497 // The delegate may not have an input event router in tests.
2498 if (auto* touch_emulator = GetExistingTouchEmulator()) {
2499 touch_emulator->SetDeviceScaleFactor(GetScaleFactorForView(view_.get()));
2503 void RenderWidgetHostImpl::GetSnapshotFromBrowser(
2504 GetSnapshotFromBrowserCallback callback,
2505 bool from_surface) {
2506 int snapshot_id = next_browser_snapshot_id_++;
2508 pending_surface_browser_snapshots_.insert(
2509 std::make_pair(snapshot_id, std::move(callback)));
2510 RequestForceRedraw(snapshot_id);
2514 #if BUILDFLAG(IS_MAC)
2515 // MacOS version of underlying GrabViewSnapshot() blocks while
2516 // display/GPU are in a power-saving mode, so make sure display
2517 // does not go to sleep for the duration of reading a snapshot.
2518 if (pending_browser_snapshots_.empty()) {
2519 GetWakeLock()->RequestWakeLock();
2522 // TODO(nzolghadr): Remove the duplication here and the if block just above.
2523 pending_browser_snapshots_.insert(
2524 std::make_pair(snapshot_id, std::move(callback)));
2525 RequestForceRedraw(snapshot_id);
2528 void RenderWidgetHostImpl::SelectionChanged(const std::u16string& text,
2530 const gfx::Range& range) {
2532 view_->SelectionChanged(text, static_cast<size_t>(offset), range);
2536 void RenderWidgetHostImpl::SelectionBoundsChanged(
2537 const gfx::Rect& anchor_rect,
2538 base::i18n::TextDirection anchor_dir,
2539 const gfx::Rect& focus_rect,
2540 base::i18n::TextDirection focus_dir,
2541 const gfx::Rect& bounding_box,
2542 bool is_anchor_first) {
2544 view_->SelectionBoundsChanged(anchor_rect, anchor_dir, focus_rect,
2545 focus_dir, bounding_box, is_anchor_first);
2549 void RenderWidgetHostImpl::OnUpdateDragOperation(
2550 DragOperationCallback callback,
2551 ui::mojom::DragOperation current_op,
2552 bool document_is_handling_drag) {
2553 RenderViewHostDelegateView* view = delegate_->GetDelegateView();
2555 view->UpdateDragOperation(current_op, document_is_handling_drag);
2557 std::move(callback).Run(current_op, document_is_handling_drag);
2560 void RenderWidgetHostImpl::RendererExited() {
2561 if (!renderer_widget_created_) {
2565 // Clearing this flag causes us to re-create the renderer when recovering
2566 // from a crashed renderer.
2567 renderer_widget_created_ = false;
2568 // This flag is set when creating the renderer widget.
2569 waiting_for_init_ = false;
2571 blink_widget_.reset();
2573 // No need to perform a deferred show after the renderer crashes, and this
2574 // wouldn't work anyway as it requires a valid `blink_widget_`.
2575 pending_show_params_.reset();
2577 // After the renderer crashes, the view is destroyed and so the
2578 // RenderWidgetHost cannot track its visibility anymore. We assume such
2579 // RenderWidgetHost to be invisible for the sake of internal accounting - be
2580 // careful about changing this - see http://crbug.com/401859 and
2581 // http://crbug.com/522795.
2583 // We need to at least make sure that the RenderProcessHost is notified about
2584 // the |is_hidden_| change, so that the renderer will have correct visibility
2585 // set when respawned.
2589 GetProcess()->UpdateClientPriority(this);
2594 view_->RenderProcessGone();
2595 SetView(nullptr); // The View should be deleted by RenderProcessGone.
2599 void RenderWidgetHostImpl::ResetStateForCreatedRenderWidget(
2600 const blink::VisualProperties& initial_props) {
2601 // When the RenderWidget was destroyed, the ack may never come back. Don't
2602 // let that prevent us from speaking to the next RenderWidget.
2603 waiting_for_screen_rects_ack_ = false;
2604 last_view_screen_rect_ = last_window_screen_rect_ = kInvalidScreenRect;
2606 visual_properties_ack_pending_ =
2607 DoesVisualPropertiesNeedAck(nullptr, initial_props);
2608 old_visual_properties_ =
2609 std::make_unique<blink::VisualProperties>(initial_props);
2611 // Reconstruct the input router to ensure that it has fresh state for a new
2612 // RenderWidget. Otherwise it may be stuck waiting for the old renderer to ack
2613 // an event. (In particular, the above call to view_->RenderProcessGone() will
2614 // destroy the aura window, which may dispatch a synthetic mouse move.)
2616 // This also stops the event ack timeout to ensure the hung renderer mechanism
2617 // is working properly.
2620 frame_token_message_queue_->Reset();
2623 void RenderWidgetHostImpl::UpdateTextDirection(
2624 base::i18n::TextDirection direction) {
2625 text_direction_updated_ = true;
2626 text_direction_ = direction;
2629 void RenderWidgetHostImpl::NotifyTextDirection() {
2630 if (!text_direction_updated_) {
2633 blink_frame_widget_->SetTextDirection(text_direction_);
2634 text_direction_updated_ = false;
2637 void RenderWidgetHostImpl::ImeSetComposition(
2638 const std::u16string& text,
2639 const std::vector<ui::ImeTextSpan>& ime_text_spans,
2640 const gfx::Range& replacement_range,
2641 int selection_start,
2642 int selection_end) {
2643 // Passing null callback since it is only needed for Devtools
2644 GetWidgetInputHandler()->ImeSetComposition(
2645 text, ime_text_spans, replacement_range, selection_start, selection_end,
2646 base::OnceClosure());
2647 #if BUILDFLAG(IS_ANDROID)
2648 for (auto& observer : ime_input_event_observers_) {
2649 observer.OnImeSetComposingTextEvent(text);
2654 void RenderWidgetHostImpl::ImeCommitText(
2655 const std::u16string& text,
2656 const std::vector<ui::ImeTextSpan>& ime_text_spans,
2657 const gfx::Range& replacement_range,
2658 int relative_cursor_pos) {
2659 // Passing null callback since it is only needed for Devtools
2660 GetWidgetInputHandler()->ImeCommitText(text, ime_text_spans,
2661 replacement_range, relative_cursor_pos,
2662 base::OnceClosure());
2663 #if BUILDFLAG(IS_ANDROID)
2664 for (auto& observer : ime_input_event_observers_) {
2665 observer.OnImeTextCommittedEvent(text);
2670 void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) {
2671 GetWidgetInputHandler()->ImeFinishComposingText(keep_selection);
2672 #if BUILDFLAG(IS_ANDROID)
2673 for (auto& observer : ime_input_event_observers_) {
2674 observer.OnImeFinishComposingTextEvent();
2679 void RenderWidgetHostImpl::ImeCancelComposition() {
2680 // Passing null callback since it is only needed for Devtools
2681 GetWidgetInputHandler()->ImeSetComposition(
2682 std::u16string(), std::vector<ui::ImeTextSpan>(),
2683 gfx::Range::InvalidRange(), 0, 0, base::OnceClosure());
2686 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary(
2687 blink::mojom::PointerLockResult reason) {
2688 DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
2689 DCHECK(reason != blink::mojom::PointerLockResult::kSuccess);
2690 if (pending_mouse_lock_request_) {
2691 DCHECK(request_mouse_callback_);
2692 pending_mouse_lock_request_ = false;
2693 mouse_lock_raw_movement_ = false;
2694 std::move(request_mouse_callback_)
2695 .Run(reason, /*context=*/mojo::NullRemote());
2697 } else if (IsMouseLocked()) {
2698 view_->UnlockMouse();
2702 bool RenderWidgetHostImpl::IsKeyboardLocked() const {
2703 return view_ ? view_->IsKeyboardLocked() : false;
2706 bool RenderWidgetHostImpl::IsContentRenderingTimeoutRunning() const {
2707 return new_content_rendering_timeout_ &&
2708 new_content_rendering_timeout_->IsRunning();
2711 void RenderWidgetHostImpl::OnMouseEventAck(
2712 const MouseEventWithLatencyInfo& mouse_event,
2713 blink::mojom::InputEventResultSource ack_source,
2714 blink::mojom::InputEventResultState ack_result) {
2715 latency_tracker_.OnInputEventAck(mouse_event.event, &mouse_event.latency,
2717 for (auto& input_event_observer : input_event_observers_) {
2718 input_event_observer.OnInputEventAck(ack_source, ack_result,
2722 // Give the delegate the ability to handle a mouse event that wasn't consumed
2723 // by the renderer. eg. Back/Forward mouse buttons.
2725 ack_result != blink::mojom::InputEventResultState::kConsumed &&
2727 delegate_->HandleMouseEvent(mouse_event.event);
2731 bool RenderWidgetHostImpl::IsMouseLocked() const {
2732 return view_ ? view_->IsMouseLocked() : false;
2735 void RenderWidgetHostImpl::SetVisualPropertiesFromParentFrame(
2736 float page_scale_factor,
2737 float compositing_scale_factor,
2738 bool is_pinch_gesture_active,
2739 const gfx::Size& visible_viewport_size,
2740 const gfx::Rect& compositor_viewport,
2741 std::vector<gfx::Rect> root_widget_window_segments) {
2742 properties_from_parent_local_root_.page_scale_factor = page_scale_factor;
2743 properties_from_parent_local_root_.compositing_scale_factor =
2744 compositing_scale_factor;
2745 properties_from_parent_local_root_.is_pinch_gesture_active =
2746 is_pinch_gesture_active;
2747 properties_from_parent_local_root_.visible_viewport_size =
2748 visible_viewport_size;
2749 properties_from_parent_local_root_.compositor_viewport = compositor_viewport;
2750 properties_from_parent_local_root_.root_widget_window_segments =
2751 std::move(root_widget_window_segments);
2754 void RenderWidgetHostImpl::SetAutoResize(bool enable,
2755 const gfx::Size& min_size,
2756 const gfx::Size& max_size) {
2757 auto_resize_enabled_ = enable;
2758 min_size_for_auto_resize_ = min_size;
2759 max_size_for_auto_resize_ = max_size;
2762 void RenderWidgetHostImpl::Destroy(bool also_delete) {
2763 DCHECK(!destroyed_);
2766 for (auto& observer : observers_) {
2767 observer.RenderWidgetHostDestroyed(this);
2770 // Tell the view to die.
2771 // Note that in the process of the view shutting down, it can call a ton
2772 // of other messages on us. So if you do any other deinitialization here,
2773 // do it after this call to view_->Destroy().
2779 // Reset the popup host receiver, this will cause a disconnection notification
2780 // on the renderer to delete Popup widgets.
2781 blink_popup_widget_host_receiver_.reset();
2783 render_process_blocked_state_changed_subscription_ = {};
2784 GetProcess()->RemovePriorityClient(this);
2785 GetProcess()->RemoveObserver(this);
2786 g_routing_id_widget_map.Get().erase(
2787 RenderWidgetHostID(GetProcess()->GetID(), routing_id_));
2789 // The |delegate_| may have been destroyed (or is in the process of being
2790 // destroyed) and detached first.
2792 delegate_->RenderWidgetDeleted(this);
2797 // The destructor CHECKs self-owned RenderWidgetHostImpl aren't destroyed
2798 // externally. This bit needs to be reset to allow internal deletion.
2799 self_owned_ = false;
2804 void RenderWidgetHostImpl::OnInputEventAckTimeout() {
2805 // Since input has timed out, let the BrowserUiThreadScheduler know we are
2806 // done with input currently.
2807 user_input_active_handle_.reset();
2808 RendererIsUnresponsive(base::BindRepeating(
2809 &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
2810 weak_factory_.GetWeakPtr()));
2813 void RenderWidgetHostImpl::RendererIsUnresponsive(
2814 base::RepeatingClosure restart_hang_monitor_timeout) {
2815 NotificationService::current()->Notify(NOTIFICATION_RENDER_WIDGET_HOST_HANG,
2816 Source<RenderWidgetHost>(this),
2817 NotificationService::NoDetails());
2818 is_unresponsive_ = true;
2821 delegate_->RendererUnresponsive(this,
2822 std::move(restart_hang_monitor_timeout));
2825 // Do not add code after this since the Delegate may delete this
2826 // RenderWidgetHostImpl in RendererUnresponsive.
2829 void RenderWidgetHostImpl::RendererIsResponsive() {
2830 if (is_unresponsive_) {
2831 is_unresponsive_ = false;
2833 delegate_->RendererResponsive(this);
2838 void RenderWidgetHostImpl::ClearDisplayedGraphics() {
2839 NotifyNewContentRenderingTimeoutForTesting();
2841 view_->ResetFallbackToFirstNavigationSurface();
2845 void RenderWidgetHostImpl::OnKeyboardEventAck(
2846 const NativeWebKeyboardEventWithLatencyInfo& event,
2847 blink::mojom::InputEventResultSource ack_source,
2848 blink::mojom::InputEventResultState ack_result) {
2849 latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
2850 for (auto& input_event_observer : input_event_observers_) {
2851 input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
2855 (blink::mojom::InputEventResultState::kConsumed == ack_result);
2857 // We only send unprocessed key event upwards if we are not hidden,
2858 // because the user has moved away from us and no longer expect any effect
2859 // of this key event.
2860 if (delegate_ && !processed && !is_hidden() &&
2861 !event.event.skip_if_unhandled) {
2862 delegate_->HandleKeyboardEvent(event.event);
2864 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2865 // (i.e. in the case of Ctrl+W, where the call to
2866 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2869 void RenderWidgetHostImpl::RequestClosePopup() {
2870 DCHECK(!owner_delegate_);
2871 ShutdownAndDestroyWidget(true);
2874 void RenderWidgetHostImpl::SetPopupBounds(const gfx::Rect& bounds,
2875 SetPopupBoundsCallback callback) {
2876 // If the browser changes bounds, do not allow renderer changing bounds at the
2877 // same time until it acked the changes. Otherwise, if they simultaneously
2878 // change bounds, browser's bounds can be clobbered.
2879 if (view_ && !waiting_for_screen_rects_ack_) {
2880 view_->SetBounds(bounds);
2882 std::move(callback).Run();
2885 void RenderWidgetHostImpl::ShowPopup(const gfx::Rect& initial_screen_rect,
2886 const gfx::Rect& anchor_screen_rect,
2887 ShowPopupCallback callback) {
2888 // `delegate_` may be null since this message may be received from when
2889 // the delegate shutdown but this widget is not yet destroyed.
2891 delegate_->ShowCreatedWidget(GetProcess()->GetID(), GetRoutingID(),
2892 initial_screen_rect, anchor_screen_rect);
2894 std::move(callback).Run();
2897 #if BUILDFLAG(IS_TIZEN_TV)
2898 void RenderWidgetHostImpl::DidEdgeScrollBy(const gfx::Point& offset, bool handled) {
2902 view_->DidEdgeScrollBy(offset, handled);
2905 void RenderWidgetHostImpl::SetTranslatedURL(const std::string& url) {
2908 blink_widget_->SetTranslatedURL(url);
2911 void RenderWidgetHostImpl::NotifyTrackInfoToBrowser(int active_track_id,
2912 const std::string& url,
2913 const std::string& lang) {
2914 LOG(INFO) << __func__;
2916 LOG(ERROR) << __func__ << ", GetView return null";
2920 view_->NotifyTrackInfoToBrowser(active_track_id, url, lang);
2924 void RenderWidgetHostImpl::UpdateTooltipUnderCursor(
2925 const std::u16string& tooltip_text,
2926 base::i18n::TextDirection text_direction_hint) {
2931 view_->UpdateTooltipUnderCursor(
2932 GetWrappedTooltipText(tooltip_text, text_direction_hint));
2935 void RenderWidgetHostImpl::UpdateTooltipFromKeyboard(
2936 const std::u16string& tooltip_text,
2937 base::i18n::TextDirection text_direction_hint,
2938 const gfx::Rect& bounds) {
2943 view_->UpdateTooltipFromKeyboard(
2944 GetWrappedTooltipText(tooltip_text, text_direction_hint), bounds);
2947 void RenderWidgetHostImpl::ClearKeyboardTriggeredTooltip() {
2952 view_->ClearKeyboardTriggeredTooltip();
2955 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
2956 waiting_for_screen_rects_ack_ = false;
2961 view_->SendInitialPropertiesIfNeeded();
2963 if (view_->GetViewBounds() == last_view_screen_rect_ &&
2964 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
2971 void RenderWidgetHostImpl::OnRenderFrameSubmission() {}
2973 void RenderWidgetHostImpl::OnLocalSurfaceIdChanged(
2974 const cc::RenderFrameMetadata& metadata) {
2975 TRACE_EVENT_WITH_FLOW1(
2976 "renderer_host," TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
2977 "RenderWidgetHostImpl::OnLocalSurfaceIdChanged",
2978 metadata.local_surface_id && metadata.local_surface_id->is_valid()
2979 ? metadata.local_surface_id->submission_trace_id() +
2980 metadata.local_surface_id->embed_trace_id()
2982 TRACE_EVENT_FLAG_FLOW_IN, "local_surface_id",
2983 metadata.local_surface_id ? metadata.local_surface_id->ToString()
2986 // Update our knowledge of the RenderWidget's size.
2987 DCHECK(!metadata.viewport_size_in_pixels.IsEmpty());
2989 visual_properties_ack_pending_ = false;
2991 for (auto& observer : observers_) {
2992 observer.RenderWidgetHostDidUpdateVisualProperties(this);
2999 viz::ScopedSurfaceIdAllocator scoped_allocator =
3000 view_->DidUpdateVisualProperties(metadata);
3001 base::AutoReset<bool> auto_reset(&surface_id_allocation_suppressed_, true);
3003 if (auto_resize_enabled_ && delegate_) {
3004 // TODO(fsamuel): The fact that we translate the viewport_size from pixels
3005 // to DIP is concerning. This could result in invariants violations.
3006 gfx::Size viewport_size_in_dip = gfx::ScaleToCeiledSize(
3007 metadata.viewport_size_in_pixels, 1.f / metadata.device_scale_factor);
3008 delegate_->ResizeDueToAutoResize(this, viewport_size_in_dip);
3012 SiteInstanceGroup* RenderWidgetHostImpl::GetSiteInstanceGroup() {
3013 return site_instance_group_.get();
3016 void RenderWidgetHostImpl::UpdateBrowserControlsState(
3017 cc::BrowserControlsState constraints,
3018 cc::BrowserControlsState current,
3020 GetWidgetInputHandler()->UpdateBrowserControlsState(constraints, current,
3024 void RenderWidgetHostImpl::StartDragging(
3025 blink::mojom::DragDataPtr drag_data,
3026 const url::Origin& source_origin,
3027 DragOperationsMask drag_operations_mask,
3028 const SkBitmap& bitmap,
3029 const gfx::Vector2d& cursor_offset_in_dip,
3030 const gfx::Rect& drag_obj_rect_in_dip,
3031 blink::mojom::DragEventSourceInfoPtr event_info) {
3032 DropData drop_data = DragDataToDropData(*drag_data);
3033 DropData filtered_data(drop_data);
3034 RenderProcessHost* process = GetProcess();
3035 ChildProcessSecurityPolicyImpl* policy =
3036 ChildProcessSecurityPolicyImpl::GetInstance();
3038 // Allow drag of Javascript URLs to enable bookmarklet drag to bookmark bar.
3039 if (!filtered_data.url.SchemeIs(url::kJavaScriptScheme)) {
3040 process->FilterURL(true, &filtered_data.url);
3042 process->FilterURL(false, &filtered_data.html_base_url);
3043 // Filter out any paths that the renderer didn't have access to. This prevents
3044 // the following attack on a malicious renderer:
3045 // 1. StartDragging IPC sent with renderer-specified filesystem paths that it
3046 // doesn't have read permissions for.
3047 // 2. We initiate a native DnD operation.
3048 // 3. DnD operation immediately ends since mouse is not held down. DnD events
3049 // still fire though, which causes read permissions to be granted to the
3050 // renderer for any file paths in the drop.
3051 filtered_data.filenames.clear();
3052 for (const auto& file_info : drop_data.filenames) {
3053 if (policy->CanReadFile(GetProcess()->GetID(), file_info.path)) {
3054 filtered_data.filenames.push_back(file_info);
3058 storage::FileSystemContext* file_system_context =
3059 GetProcess()->GetStoragePartition()->GetFileSystemContext();
3060 filtered_data.file_system_files.clear();
3062 for (const auto& file_system_file : drop_data.file_system_files) {
3063 storage::FileSystemURL file_system_url =
3064 file_system_context->CrackURLInFirstPartyContext(file_system_file.url);
3066 // Sandboxed filesystem files should never be handled via this path, so
3067 // skip any that are sent from the renderer. In all other cases, it should
3068 // be safe to use the FileSystemURL returned from calling
3069 // CrackURLInFirstPartyContext as long as CanReadFileSystemFile only
3070 // performs checks on the origin and doesn't use more of the StorageKey.
3071 if (file_system_url.type() == storage::kFileSystemTypePersistent ||
3072 file_system_url.type() == storage::kFileSystemTypeTemporary) {
3076 if (policy->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url)) {
3077 filtered_data.file_system_files.push_back(file_system_file);
3082 bool intercepted = false;
3083 devtools_instrumentation::WillStartDragging(
3084 frame_tree_->root(), filtered_data, std::move(drag_data),
3085 drag_operations_mask, &intercepted);
3091 RenderViewHostDelegateView* view = delegate_->GetDelegateView();
3092 if (!view || !GetView()) {
3093 // Need to clear drag and drop state in blink.
3094 DragSourceSystemDragEnded();
3097 float scale = GetScaleFactorForView(GetView());
3098 gfx::ImageSkia image = gfx::ImageSkia::CreateFromBitmap(bitmap, scale);
3099 gfx::Vector2d offset = cursor_offset_in_dip;
3100 gfx::Rect rect = drag_obj_rect_in_dip;
3101 #if BUILDFLAG(IS_WIN)
3102 // Scale the offset by device scale factor, otherwise the drag
3103 // image location doesn't line up with the drop location (drag destination).
3104 // TODO(crbug.com/1354831): this conversion should not be necessary.
3105 gfx::Vector2dF scaled_offset = static_cast<gfx::Vector2dF>(offset);
3106 scaled_offset.Scale(scale);
3107 offset = gfx::ToRoundedVector2d(scaled_offset);
3108 gfx::RectF scaled_rect = static_cast<gfx::RectF>(rect);
3109 scaled_rect.Scale(scale);
3110 rect = gfx::ToRoundedRect(scaled_rect);
3112 view->StartDragging(filtered_data, source_origin, drag_operations_mask, image,
3113 offset, rect, *event_info, this);
3117 bool RenderWidgetHostImpl::DidVisualPropertiesSizeChange(
3118 const blink::VisualProperties& old_visual_properties,
3119 const blink::VisualProperties& new_visual_properties) {
3120 return old_visual_properties.auto_resize_enabled !=
3121 new_visual_properties.auto_resize_enabled ||
3122 (old_visual_properties.auto_resize_enabled &&
3123 (old_visual_properties.min_size_for_auto_resize !=
3124 new_visual_properties.min_size_for_auto_resize ||
3125 old_visual_properties.max_size_for_auto_resize !=
3126 new_visual_properties.max_size_for_auto_resize)) ||
3127 (!old_visual_properties.auto_resize_enabled &&
3128 (old_visual_properties.new_size != new_visual_properties.new_size ||
3129 (old_visual_properties.compositor_viewport_pixel_rect.IsEmpty() &&
3130 !new_visual_properties.compositor_viewport_pixel_rect.IsEmpty())));
3134 bool RenderWidgetHostImpl::DoesVisualPropertiesNeedAck(
3135 const std::unique_ptr<blink::VisualProperties>& old_visual_properties,
3136 const blink::VisualProperties& new_visual_properties) {
3137 // We should throttle sending updated VisualProperties to the renderer to
3138 // the rate of commit. This ensures we don't overwhelm the renderer with
3139 // visual updates faster than it can keep up. |needs_ack| corresponds to
3140 // cases where a commit is expected.
3141 bool is_acking_applicable =
3142 g_check_for_pending_visual_properties_ack &&
3143 !new_visual_properties.auto_resize_enabled &&
3144 !new_visual_properties.new_size.IsEmpty() &&
3145 !new_visual_properties.compositor_viewport_pixel_rect.IsEmpty() &&
3146 new_visual_properties.local_surface_id;
3148 // If acking is applicable, then check if there has been an
3149 // |old_visual_properties| stored which would indicate an update has been
3150 // sent. If so, then acking is defined by size changing.
3151 return is_acking_applicable &&
3152 (!old_visual_properties ||
3153 DidVisualPropertiesSizeChange(*old_visual_properties,
3154 new_visual_properties));
3158 bool RenderWidgetHostImpl::StoredVisualPropertiesNeedsUpdate(
3159 const std::unique_ptr<blink::VisualProperties>& old_visual_properties,
3160 const blink::VisualProperties& new_visual_properties) {
3161 if (!old_visual_properties) {
3165 const bool size_changed = DidVisualPropertiesSizeChange(
3166 *old_visual_properties, new_visual_properties);
3168 // Hold on the the LocalSurfaceId in a local variable otherwise the
3169 // LocalSurfaceId may become invalid when used later.
3170 const viz::LocalSurfaceId old_parent_local_surface_id =
3171 old_visual_properties->local_surface_id.value_or(viz::LocalSurfaceId());
3172 const viz::LocalSurfaceId new_parent_local_surface_id =
3173 new_visual_properties.local_surface_id.value_or(viz::LocalSurfaceId());
3175 const bool parent_local_surface_id_changed =
3176 old_parent_local_surface_id.parent_sequence_number() !=
3177 new_parent_local_surface_id.parent_sequence_number() ||
3178 old_parent_local_surface_id.embed_token() !=
3179 new_parent_local_surface_id.embed_token();
3181 const bool zoom_changed =
3182 old_visual_properties->zoom_level != new_visual_properties.zoom_level;
3184 return zoom_changed || size_changed || parent_local_surface_id_changed ||
3185 old_visual_properties->screen_infos !=
3186 new_visual_properties.screen_infos ||
3187 old_visual_properties->compositor_viewport_pixel_rect !=
3188 new_visual_properties.compositor_viewport_pixel_rect ||
3189 old_visual_properties->is_fullscreen_granted !=
3190 new_visual_properties.is_fullscreen_granted ||
3191 old_visual_properties->display_mode !=
3192 new_visual_properties.display_mode ||
3193 old_visual_properties->window_show_state !=
3194 new_visual_properties.window_show_state ||
3195 old_visual_properties->resizable != new_visual_properties.resizable ||
3196 old_visual_properties->browser_controls_params !=
3197 new_visual_properties.browser_controls_params ||
3198 old_visual_properties->visible_viewport_size !=
3199 new_visual_properties.visible_viewport_size ||
3200 old_visual_properties->capture_sequence_number !=
3201 new_visual_properties.capture_sequence_number ||
3202 old_visual_properties->page_scale_factor !=
3203 new_visual_properties.page_scale_factor ||
3204 old_visual_properties->compositing_scale_factor !=
3205 new_visual_properties.compositing_scale_factor ||
3206 old_visual_properties->cursor_accessibility_scale_factor !=
3207 new_visual_properties.cursor_accessibility_scale_factor ||
3208 old_visual_properties->is_pinch_gesture_active !=
3209 new_visual_properties.is_pinch_gesture_active ||
3210 old_visual_properties->root_widget_window_segments !=
3211 new_visual_properties.root_widget_window_segments ||
3212 old_visual_properties->window_controls_overlay_rect !=
3213 new_visual_properties.window_controls_overlay_rect;
3216 void RenderWidgetHostImpl::AutoscrollStart(const gfx::PointF& position) {
3217 GetView()->OnAutoscrollStart();
3218 sent_autoscroll_scroll_begin_ = false;
3219 autoscroll_in_progress_ = true;
3220 delegate()->GetInputEventRouter()->SetAutoScrollInProgress(
3221 autoscroll_in_progress_);
3222 autoscroll_start_position_ = position;
3225 void RenderWidgetHostImpl::AutoscrollFling(const gfx::Vector2dF& velocity) {
3226 DCHECK(autoscroll_in_progress_);
3227 if (!sent_autoscroll_scroll_begin_ && velocity != gfx::Vector2dF()) {
3228 // Send a GSB event with valid delta hints.
3229 WebGestureEvent scroll_begin =
3230 blink::SyntheticWebGestureEventBuilder::Build(
3231 WebInputEvent::Type::kGestureScrollBegin,
3232 blink::WebGestureDevice::kSyntheticAutoscroll);
3233 scroll_begin.SetPositionInWidget(autoscroll_start_position_);
3234 scroll_begin.data.scroll_begin.delta_x_hint = velocity.x();
3235 scroll_begin.data.scroll_begin.delta_y_hint = velocity.y();
3237 ForwardGestureEventWithLatencyInfo(
3238 scroll_begin, ui::LatencyInfo(ui::SourceEventType::OTHER));
3239 sent_autoscroll_scroll_begin_ = true;
3242 WebGestureEvent event = blink::SyntheticWebGestureEventBuilder::Build(
3243 WebInputEvent::Type::kGestureFlingStart,
3244 blink::WebGestureDevice::kSyntheticAutoscroll);
3245 event.SetPositionInWidget(autoscroll_start_position_);
3246 event.data.fling_start.velocity_x = velocity.x();
3247 event.data.fling_start.velocity_y = velocity.y();
3249 ForwardGestureEventWithLatencyInfo(
3250 event, ui::LatencyInfo(ui::SourceEventType::OTHER));
3253 void RenderWidgetHostImpl::AutoscrollEnd() {
3254 autoscroll_in_progress_ = false;
3256 delegate()->GetInputEventRouter()->SetAutoScrollInProgress(
3257 autoscroll_in_progress_);
3258 // Don't send a GFC if no GSB is sent.
3259 if (!sent_autoscroll_scroll_begin_) {
3263 sent_autoscroll_scroll_begin_ = false;
3264 WebGestureEvent cancel_event = blink::SyntheticWebGestureEventBuilder::Build(
3265 WebInputEvent::Type::kGestureFlingCancel,
3266 blink::WebGestureDevice::kSyntheticAutoscroll);
3267 cancel_event.data.fling_cancel.prevent_boosting = true;
3268 cancel_event.SetPositionInWidget(autoscroll_start_position_);
3270 ForwardGestureEventWithLatencyInfo(
3271 cancel_event, ui::LatencyInfo(ui::SourceEventType::OTHER));
3274 bool RenderWidgetHostImpl::IsAutoscrollInProgress() {
3275 return autoscroll_in_progress_;
3278 TouchEmulator* RenderWidgetHostImpl::GetTouchEmulator() {
3279 if (!delegate_ || !delegate_->GetInputEventRouter()) {
3283 return delegate_->GetInputEventRouter()->GetTouchEmulator();
3286 TouchEmulator* RenderWidgetHostImpl::GetExistingTouchEmulator() {
3287 if (!delegate_ || !delegate_->GetInputEventRouter() ||
3288 !delegate_->GetInputEventRouter()->has_touch_emulator()) {
3292 return delegate_->GetInputEventRouter()->GetTouchEmulator();
3295 void RenderWidgetHostImpl::TextInputStateChanged(
3296 ui::mojom::TextInputStatePtr state) {
3300 for (auto& callback : suppress_showing_ime_callbacks_) {
3301 if (callback.Run()) {
3302 state->always_hide_ime = true;
3306 view_->TextInputStateChanged(*state);
3309 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
3310 const gfx::Range& range,
3311 const absl::optional<std::vector<gfx::Rect>>& character_bounds,
3312 const absl::optional<std::vector<gfx::Rect>>& line_bounds) {
3314 view_->ImeCompositionRangeChanged(range, character_bounds, line_bounds);
3318 void RenderWidgetHostImpl::OnImeCancelComposition() {
3320 view_->ImeCancelComposition();
3324 RenderWidgetHostViewBase* RenderWidgetHostImpl::GetRenderWidgetHostViewBase() {
3328 void RenderWidgetHostImpl::OnStartStylusWriting() {
3329 if (blink_frame_widget_) {
3330 auto callback = base::BindOnce(
3331 &RenderWidgetHostImpl::OnEditElementFocusedForStylusWriting,
3332 weak_factory_.GetWeakPtr());
3333 blink_frame_widget_->OnStartStylusWriting(std::move(callback));
3337 void RenderWidgetHostImpl::OnEditElementFocusedForStylusWriting(
3338 const absl::optional<gfx::Rect>& focused_edit_bounds,
3339 const absl::optional<gfx::Rect>& caret_bounds) {
3341 view_->OnEditElementFocusedForStylusWriting(
3342 focused_edit_bounds.value_or(gfx::Rect()),
3343 caret_bounds.value_or(gfx::Rect()));
3347 bool RenderWidgetHostImpl::IsWheelScrollInProgress() {
3348 return is_in_gesture_scroll_[static_cast<int>(
3349 blink::WebGestureDevice::kTouchpad)];
3352 void RenderWidgetHostImpl::SetMouseCapture(bool capture) {
3353 if (!delegate_ || !delegate_->GetInputEventRouter()) {
3357 delegate_->GetInputEventRouter()->SetMouseCaptureTarget(GetView(), capture);
3360 void RenderWidgetHostImpl::RequestMouseLock(
3361 bool from_user_gesture,
3362 bool unadjusted_movement,
3363 InputRouterImpl::RequestMouseLockCallback response) {
3364 if (pending_mouse_lock_request_ || IsMouseLocked()) {
3365 std::move(response).Run(blink::mojom::PointerLockResult::kAlreadyLocked,
3366 /*context=*/mojo::NullRemote());
3370 if (!view_ || !view_->CanBeMouseLocked()) {
3371 std::move(response).Run(blink::mojom::PointerLockResult::kWrongDocument,
3372 /*context=*/mojo::NullRemote());
3376 request_mouse_callback_ = std::move(response);
3378 pending_mouse_lock_request_ = true;
3379 mouse_lock_raw_movement_ = unadjusted_movement;
3381 // No delegate, reject message.
3382 GotResponseToLockMouseRequest(
3383 blink::mojom::PointerLockResult::kPermissionDenied);
3387 delegate_->RequestToLockMouse(this, from_user_gesture,
3388 is_last_unlocked_by_target_, false);
3389 // We need to reset |is_last_unlocked_by_target_| here as we don't know
3390 // request source in |LostMouseLock()|.
3391 is_last_unlocked_by_target_ = false;
3394 void RenderWidgetHostImpl::RequestMouseLockChange(
3395 bool unadjusted_movement,
3396 PointerLockContext::RequestMouseLockChangeCallback response) {
3397 if (pending_mouse_lock_request_) {
3398 std::move(response).Run(blink::mojom::PointerLockResult::kAlreadyLocked);
3402 if (!view_ || !view_->HasFocus()) {
3403 std::move(response).Run(blink::mojom::PointerLockResult::kWrongDocument);
3407 std::move(response).Run(view_->ChangeMouseLock(unadjusted_movement));
3410 void RenderWidgetHostImpl::UnlockMouse() {
3411 // Got unlock request from renderer. Will update |is_last_unlocked_by_target_|
3412 // for silent re-lock.
3413 const bool was_mouse_locked = !pending_mouse_lock_request_ && IsMouseLocked();
3414 RejectMouseLockOrUnlockIfNecessary(
3415 blink::mojom::PointerLockResult::kUserRejected);
3416 if (was_mouse_locked) {
3417 is_last_unlocked_by_target_ = true;
3421 void RenderWidgetHostImpl::OnInvalidFrameToken(uint32_t frame_token) {
3422 bad_message::ReceivedBadMessage(GetProcess(),
3423 bad_message::RWH_INVALID_FRAME_TOKEN);
3426 bool RenderWidgetHostImpl::RequestKeyboardLock(
3427 absl::optional<base::flat_set<ui::DomCode>> codes) {
3429 CancelKeyboardLock();
3433 DCHECK(!codes.has_value() || !codes.value().empty());
3434 keyboard_keys_to_lock_ = std::move(codes);
3435 keyboard_lock_requested_ = true;
3437 const bool esc_requested =
3438 !keyboard_keys_to_lock_.has_value() ||
3439 base::Contains(keyboard_keys_to_lock_.value(), ui::DomCode::ESCAPE);
3441 if (!delegate_->RequestKeyboardLock(this, esc_requested)) {
3442 CancelKeyboardLock();
3449 void RenderWidgetHostImpl::CancelKeyboardLock() {
3451 delegate_->CancelKeyboardLock(this);
3456 keyboard_lock_allowed_ = false;
3457 keyboard_lock_requested_ = false;
3458 keyboard_keys_to_lock_.reset();
3461 base::flat_map<std::string, std::string>
3462 RenderWidgetHostImpl::GetKeyboardLayoutMap() {
3466 return view_->GetKeyboardLayoutMap();
3469 void RenderWidgetHostImpl::RequestForceRedraw(int snapshot_id) {
3470 if (!blink_widget_) {
3474 blink_widget_->ForceRedraw(
3475 base::BindOnce(&RenderWidgetHostImpl::GotResponseToForceRedraw,
3476 base::Unretained(this), snapshot_id));
3479 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
3480 const NativeWebKeyboardEvent& event) {
3481 if (event.skip_if_unhandled ||
3482 event.GetType() != WebKeyboardEvent::Type::kRawKeyDown) {
3486 for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
3487 size_t original_size = key_press_event_callbacks_.size();
3488 if (key_press_event_callbacks_[i].Run(event)) {
3492 // Check whether the callback that just ran removed itself, in which case
3493 // the iterator needs to be decremented to properly account for the removal.
3494 size_t current_size = key_press_event_callbacks_.size();
3495 if (current_size != original_size) {
3496 DCHECK_EQ(original_size - 1, current_size);
3504 blink::mojom::InputEventResultState RenderWidgetHostImpl::FilterInputEvent(
3505 const WebInputEvent& event,
3506 const ui::LatencyInfo& latency_info) {
3507 // Don't ignore touch cancel events, since they may be sent while input
3508 // events are being ignored in order to keep the renderer from getting
3509 // confused about how many touches are active.
3510 if (IsIgnoringInputEvents() &&
3511 event.GetType() != WebInputEvent::Type::kTouchCancel) {
3512 return blink::mojom::InputEventResultState::kNoConsumerExists;
3515 if (!GetProcess()->IsInitializedAndNotDead()) {
3516 return blink::mojom::InputEventResultState::kUnknown;
3520 if (event.GetType() == WebInputEvent::Type::kMouseDown ||
3521 event.GetType() == WebInputEvent::Type::kTouchStart ||
3522 event.GetType() == WebInputEvent::Type::kGestureTap) {
3523 delegate_->FocusOwningWebContents(this);
3525 delegate_->DidReceiveInputEvent(this, event);
3528 return view_ ? view_->FilterInputEvent(event)
3529 : blink::mojom::InputEventResultState::kNotConsumed;
3532 void RenderWidgetHostImpl::IncrementInFlightEventCount() {
3533 ++in_flight_event_count_;
3534 if (in_flight_event_count_ == 1) {
3535 user_input_active_handle_ = BrowserTaskExecutor::OnUserInputStart();
3539 StartInputEventAckTimeout();
3543 void RenderWidgetHostImpl::NotifyUISchedulerOfScrollStateUpdate(
3544 BrowserUIThreadScheduler::ScrollState scroll_state) {
3545 DCHECK_CURRENTLY_ON(BrowserThread::UI);
3546 BrowserUIThreadScheduler::Get()->OnScrollStateUpdate(scroll_state);
3548 void RenderWidgetHostImpl::DecrementInFlightEventCount(
3549 blink::mojom::InputEventResultSource ack_source) {
3550 --in_flight_event_count_;
3551 if (in_flight_event_count_ <= 0) {
3552 // Cancel pending hung renderer checks since the renderer is responsive.
3553 StopInputEventAckTimeout();
3554 user_input_active_handle_.reset();
3556 // Only restart the hang monitor timer if we got a response from the
3558 if (ack_source == blink::mojom::InputEventResultSource::kMainThread) {
3559 RestartInputEventAckTimeoutIfNecessary();
3564 void RenderWidgetHostImpl::DidOverscroll(
3565 const ui::DidOverscrollParams& params) {
3567 view_->DidOverscroll(params);
3571 void RenderWidgetHostImpl::DidStopFlinging() {
3572 is_in_touchpad_gesture_fling_ = false;
3574 view_->DidStopFlinging();
3578 void RenderWidgetHostImpl::DidStartScrollingViewport() {
3580 view_->set_is_currently_scrolling_viewport(true);
3584 void RenderWidgetHostImpl::OnInvalidInputEventSource() {
3585 bad_message::ReceivedBadMessage(
3586 GetProcess(), bad_message::INPUT_ROUTER_INVALID_EVENT_SOURCE);
3589 void RenderWidgetHostImpl::AddPendingUserActivation(
3590 const WebInputEvent& event) {
3591 if ((base::FeatureList::IsEnabled(
3592 features::kBrowserVerifiedUserActivationMouse) &&
3593 event.GetType() == WebInputEvent::Type::kMouseDown) ||
3594 (base::FeatureList::IsEnabled(
3595 features::kBrowserVerifiedUserActivationKeyboard) &&
3596 (event.GetType() == WebInputEvent::Type::kKeyDown ||
3597 event.GetType() == WebInputEvent::Type::kRawKeyDown))) {
3598 pending_user_activation_timer_.Start(
3599 FROM_HERE, kActivationNotificationExpireTime,
3600 base::BindOnce(&RenderWidgetHostImpl::ClearPendingUserActivation,
3601 base::Unretained(this)));
3602 pending_user_activation_counter_++;
3606 void RenderWidgetHostImpl::ClearPendingUserActivation() {
3607 pending_user_activation_counter_ = 0;
3608 pending_user_activation_timer_.Stop();
3611 bool RenderWidgetHostImpl::RemovePendingUserActivationIfAvailable() {
3612 if (pending_user_activation_counter_ > 0) {
3613 pending_user_activation_counter_--;
3619 const mojo::AssociatedRemote<blink::mojom::FrameWidget>&
3620 RenderWidgetHostImpl::GetAssociatedFrameWidget() {
3621 return blink_frame_widget_;
3624 blink::mojom::FrameWidgetInputHandler*
3625 RenderWidgetHostImpl::GetFrameWidgetInputHandler() {
3626 if (!frame_widget_input_handler_) {
3629 return frame_widget_input_handler_.get();
3632 absl::optional<blink::VisualProperties>
3633 RenderWidgetHostImpl::LastComputedVisualProperties() const {
3634 if (!old_visual_properties_) {
3635 return absl::nullopt;
3637 return *old_visual_properties_;
3640 mojom::CreateFrameWidgetParamsPtr
3641 RenderWidgetHostImpl::BindAndGenerateCreateFrameWidgetParams() {
3642 auto params = mojom::CreateFrameWidgetParams::New();
3644 params->routing_id = GetRoutingID();
3646 mojo::PendingAssociatedRemote<blink::mojom::Widget> widget_remote;
3647 params->widget = widget_remote.InitWithNewEndpointAndPassReceiver();
3648 BindWidgetInterfaces(params->widget_host.InitWithNewEndpointAndPassReceiver(),
3649 std::move(widget_remote));
3650 mojo::PendingAssociatedRemote<blink::mojom::FrameWidget> frame_widget_remote;
3651 params->frame_widget =
3652 frame_widget_remote.InitWithNewEndpointAndPassReceiver();
3653 BindFrameWidgetInterfaces(
3654 params->frame_widget_host.InitWithNewEndpointAndPassReceiver(),
3655 std::move(frame_widget_remote));
3657 params->visual_properties = GetInitialVisualProperties();
3662 mojom::CreateFrameWidgetParamsPtr
3663 RenderWidgetHostImpl::BindAndGenerateCreateFrameWidgetParamsForNewWindow() {
3664 auto params = mojom::CreateFrameWidgetParams::New();
3665 params->routing_id = GetRoutingID();
3666 mojo::PendingAssociatedRemote<blink::mojom::Widget> widget_remote;
3667 params->widget = widget_remote.InitWithNewEndpointAndPassReceiver();
3668 BindWidgetInterfaces(params->widget_host.InitWithNewEndpointAndPassReceiver(),
3669 std::move(widget_remote));
3670 mojo::PendingAssociatedRemote<blink::mojom::FrameWidget> frame_widget_remote;
3671 params->frame_widget =
3672 frame_widget_remote.InitWithNewEndpointAndPassReceiver();
3673 BindFrameWidgetInterfaces(
3674 params->frame_widget_host.InitWithNewEndpointAndPassReceiver(),
3675 std::move(frame_widget_remote));
3676 // TODO(danakj): For some reason, there is no RenderWidgetHostView here, but
3677 // it seems like there should be one? In the meantime we send some nonsense
3678 // with semi-valid but incorrect screen info (it needs a RenderWidgetHostView
3679 // to be correct). An updated VisualProperties will get to the RenderWidget
3681 params->visual_properties.screen_infos = GetScreenInfos();
3685 void RenderWidgetHostImpl::DispatchInputEventWithLatencyInfo(
3686 const WebInputEvent& event,
3687 ui::LatencyInfo* latency,
3688 ui::EventLatencyMetadata* event_latency_metadata) {
3689 latency_tracker_.OnInputEvent(event, latency, event_latency_metadata);
3690 AddPendingUserActivation(event);
3691 for (auto& observer : input_event_observers_) {
3692 observer.OnInputEvent(event);
3696 void RenderWidgetHostImpl::OnWheelEventAck(
3697 const MouseWheelEventWithLatencyInfo& wheel_event,
3698 blink::mojom::InputEventResultSource ack_source,
3699 blink::mojom::InputEventResultState ack_result) {
3700 latency_tracker_.OnInputEventAck(wheel_event.event, &wheel_event.latency,
3702 for (auto& input_event_observer : input_event_observers_) {
3703 input_event_observer.OnInputEventAck(ack_source, ack_result,
3707 if (!is_hidden() && view_) {
3708 if (ack_result != blink::mojom::InputEventResultState::kConsumed &&
3709 delegate_ && delegate_->HandleWheelEvent(wheel_event.event)) {
3710 ack_result = blink::mojom::InputEventResultState::kConsumed;
3712 view_->WheelEventAck(wheel_event.event, ack_result);
3716 void RenderWidgetHostImpl::OnGestureEventAck(
3717 const GestureEventWithLatencyInfo& event,
3718 blink::mojom::InputEventResultSource ack_source,
3719 blink::mojom::InputEventResultState ack_result,
3720 blink::mojom::ScrollResultDataPtr scroll_result_data) {
3721 latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
3722 for (auto& input_event_observer : input_event_observers_) {
3723 input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
3726 // If the TouchEmulator didn't exist when this GestureEvent was sent, we
3727 // shouldn't create it here.
3728 if (auto* touch_emulator = GetExistingTouchEmulator()) {
3729 touch_emulator->OnGestureEventAck(event.event, GetView());
3733 view_->GestureEventAck(event.event, ack_result,
3734 std::move(scroll_result_data));
3738 void RenderWidgetHostImpl::OnTouchEventAck(
3739 const TouchEventWithLatencyInfo& event,
3740 blink::mojom::InputEventResultSource ack_source,
3741 blink::mojom::InputEventResultState ack_result) {
3742 latency_tracker_.OnInputEventAck(event.event, &event.latency, ack_result);
3743 for (auto& input_event_observer : input_event_observers_) {
3744 input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
3747 auto* input_event_router =
3748 delegate() ? delegate()->GetInputEventRouter() : nullptr;
3750 // At present interstitial pages might not have an input event router, so we
3751 // just have the view process the ack directly in that case; the view is
3752 // guaranteed to be a top-level view with an appropriate implementation of
3753 // ProcessAckedTouchEvent().
3754 if (input_event_router) {
3755 input_event_router->ProcessAckedTouchEvent(event, ack_result, view_.get());
3757 view_->ProcessAckedTouchEvent(event, ack_result);
3761 bool RenderWidgetHostImpl::IsIgnoringInputEvents() const {
3762 return agent_scheduling_group_->GetProcess()->IsBlocked() || !delegate_ ||
3763 delegate_->ShouldIgnoreInputEvents();
3766 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(
3767 blink::mojom::PointerLockResult response) {
3768 if (response != blink::mojom::PointerLockResult::kSuccess) {
3769 RejectMouseLockOrUnlockIfNecessary(response);
3771 if (!pending_mouse_lock_request_) {
3772 // This is possible, e.g., the plugin sends us an unlock request before
3773 // the user allows to lock to mouse.
3777 DCHECK(request_mouse_callback_);
3778 pending_mouse_lock_request_ = false;
3779 if (!view_ || !view_->HasFocus()) {
3780 std::move(request_mouse_callback_)
3781 .Run(blink::mojom::PointerLockResult::kWrongDocument,
3782 /*context=*/mojo::NullRemote());
3786 blink::mojom::PointerLockResult result =
3787 view_->LockMouse(mouse_lock_raw_movement_);
3789 if (result != blink::mojom::PointerLockResult::kSuccess) {
3790 std::move(request_mouse_callback_)
3791 .Run(result, /*context=*/mojo::NullRemote());
3795 mojo::PendingRemote<blink::mojom::PointerLockContext> context =
3796 mouse_lock_context_.BindNewPipeAndPassRemote(
3797 content::GetUIThreadTaskRunner({BrowserTaskType::kUserInput}));
3799 std::move(request_mouse_callback_)
3800 .Run(blink::mojom::PointerLockResult::kSuccess, std::move(context));
3801 mouse_lock_context_.set_disconnect_handler(base::BindOnce(
3802 &RenderWidgetHostImpl::UnlockMouse, weak_factory_.GetWeakPtr()));
3806 void RenderWidgetHostImpl::GotResponseToKeyboardLockRequest(bool allowed) {
3807 DCHECK(keyboard_lock_requested_);
3808 keyboard_lock_allowed_ = allowed;
3810 if (keyboard_lock_allowed_) {
3817 void RenderWidgetHostImpl::GotResponseToForceRedraw(int snapshot_id) {
3818 // Snapshots from surface do not need to wait for the screen update.
3819 if (!pending_surface_browser_snapshots_.empty()) {
3820 GetView()->CopyFromSurface(
3821 gfx::Rect(), gfx::Size(),
3822 base::BindOnce(&RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived,
3823 weak_factory_.GetWeakPtr(), snapshot_id, 0));
3826 if (pending_browser_snapshots_.empty()) {
3829 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
3830 // On Mac, when using CoreAnimation, or Win32 when using GDI, there is a
3831 // delay between when content is drawn to the screen, and when the
3832 // snapshot will actually pick up that content. Insert a manual delay of
3833 // 1/6th of a second (to simulate 10 frames at 60 fps) before actually
3834 // taking the snapshot.
3835 base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
3837 base::BindOnce(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
3838 weak_factory_.GetWeakPtr(), snapshot_id),
3839 base::Seconds(1. / 6));
3841 WindowSnapshotReachedScreen(snapshot_id);
3845 void RenderWidgetHostImpl::DetachDelegate() {
3846 delegate_ = nullptr;
3847 latency_tracker_.reset_delegate();
3850 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
3851 DCHECK(base::CurrentUIThread::IsSet());
3853 if (!pending_browser_snapshots_.empty()) {
3854 #if BUILDFLAG(IS_ANDROID)
3855 // On Android, call sites should pass in the bounds with correct offset
3856 // to capture the intended content area.
3857 gfx::Rect snapshot_bounds(GetView()->GetViewBounds());
3858 snapshot_bounds.Offset(0, GetView()->GetNativeView()->content_offset());
3860 gfx::Rect snapshot_bounds(GetView()->GetViewBounds().size());
3864 if (ui::GrabViewSnapshot(GetView()->GetNativeView(), snapshot_bounds,
3866 OnSnapshotReceived(snapshot_id, image);
3870 ui::GrabViewSnapshotAsync(
3871 GetView()->GetNativeView(), snapshot_bounds,
3872 base::BindOnce(&RenderWidgetHostImpl::OnSnapshotReceived,
3873 weak_factory_.GetWeakPtr(), snapshot_id));
3877 void RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived(
3880 const SkBitmap& bitmap) {
3881 static constexpr int kMaxRetries = 5;
3882 if (bitmap.drawsNothing() && retry_count < kMaxRetries) {
3883 GetView()->CopyFromSurface(
3884 gfx::Rect(), gfx::Size(),
3885 base::BindOnce(&RenderWidgetHostImpl::OnSnapshotFromSurfaceReceived,
3886 weak_factory_.GetWeakPtr(), snapshot_id,
3890 // If all retries have failed, we return an empty image.
3892 if (!bitmap.drawsNothing()) {
3893 image = gfx::Image::CreateFrom1xBitmap(bitmap);
3895 // Any pending snapshots with a lower ID than the one received are considered
3896 // to be implicitly complete, and returned the same snapshot data.
3897 auto it = pending_surface_browser_snapshots_.begin();
3898 while (it != pending_surface_browser_snapshots_.end()) {
3899 if (it->first <= snapshot_id) {
3900 std::move(it->second).Run(image);
3901 pending_surface_browser_snapshots_.erase(it++);
3908 void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id,
3910 // Any pending snapshots with a lower ID than the one received are considered
3911 // to be implicitly complete, and returned the same snapshot data.
3912 auto it = pending_browser_snapshots_.begin();
3913 while (it != pending_browser_snapshots_.end()) {
3914 if (it->first <= snapshot_id) {
3915 std::move(it->second).Run(image);
3916 pending_browser_snapshots_.erase(it++);
3921 #if BUILDFLAG(IS_MAC)
3922 if (pending_browser_snapshots_.empty()) {
3923 GetWakeLock()->CancelWakeLock();
3928 BrowserAccessibilityManager*
3929 RenderWidgetHostImpl::GetRootBrowserAccessibilityManager() {
3930 return delegate_ ? delegate_->GetRootBrowserAccessibilityManager() : nullptr;
3933 BrowserAccessibilityManager*
3934 RenderWidgetHostImpl::GetOrCreateRootBrowserAccessibilityManager() {
3935 return delegate_ ? delegate_->GetOrCreateRootBrowserAccessibilityManager()
3939 void RenderWidgetHostImpl::GrantFileAccessFromDropData(DropData* drop_data) {
3940 DCHECK_EQ(GetRoutingID(), drop_data->view_id);
3941 RenderProcessHost* process = GetProcess();
3942 PrepareDropDataForChildProcess(
3943 drop_data, ChildProcessSecurityPolicyImpl::GetInstance(),
3944 process->GetID(), process->GetStoragePartition()->GetFileSystemContext());
3947 void RenderWidgetHostImpl::RequestCompositionUpdates(bool immediate_request,
3948 bool monitor_updates) {
3949 if (!immediate_request && monitor_updates == monitoring_composition_info_) {
3952 monitoring_composition_info_ = monitor_updates;
3953 GetWidgetInputHandler()->RequestCompositionUpdates(immediate_request,
3957 void RenderWidgetHostImpl::CreateFrameSink(
3958 mojo::PendingReceiver<viz::mojom::CompositorFrameSink>
3959 compositor_frame_sink_receiver,
3960 mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient>
3961 compositor_frame_sink_client) {
3962 // Connects the viz process end of CompositorFrameSink message pipes. The
3963 // renderer compositor may request a new CompositorFrameSink on context
3964 // loss, which will destroy the existing CompositorFrameSink.
3965 create_frame_sink_callback_ = base::BindOnce(
3966 [](mojo::PendingReceiver<viz::mojom::CompositorFrameSink> receiver,
3967 mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient> client,
3968 const viz::FrameSinkId& frame_sink_id) {
3969 GetHostFrameSinkManager()->CreateCompositorFrameSink(
3970 frame_sink_id, std::move(receiver), std::move(client));
3972 std::move(compositor_frame_sink_receiver),
3973 std::move(compositor_frame_sink_client));
3975 MaybeDispatchBufferedFrameSinkRequest();
3978 void RenderWidgetHostImpl::MaybeDispatchBufferedFrameSinkRequest() {
3979 if (!view_ || !view_is_frame_sink_id_owner_) {
3983 if (!create_frame_sink_callback_) {
3987 std::move(create_frame_sink_callback_).Run(view_->GetFrameSinkId());
3990 void RenderWidgetHostImpl::RegisterRenderFrameMetadataObserver(
3991 mojo::PendingReceiver<cc::mojom::RenderFrameMetadataObserverClient>
3992 render_frame_metadata_observer_client_receiver,
3993 mojo::PendingRemote<cc::mojom::RenderFrameMetadataObserver>
3994 render_frame_metadata_observer) {
3995 render_frame_metadata_provider_.Bind(
3996 std::move(render_frame_metadata_observer_client_receiver),
3997 std::move(render_frame_metadata_observer));
4000 bool RenderWidgetHostImpl::HasGestureStopped() {
4001 if (delegate_ && delegate_->GetInputEventRouter() &&
4002 delegate_->GetInputEventRouter()->HasEventsPendingDispatch()) {
4006 if (input_router_->HasPendingEvents()) {
4010 std::unique_ptr<RenderWidgetHostIterator> child_widgets(
4011 GetEmbeddedRenderWidgetHosts());
4012 while (RenderWidgetHost* child = child_widgets->GetNextHost()) {
4013 auto* child_impl = static_cast<RenderWidgetHostImpl*>(child);
4014 if (!child_impl->HasGestureStopped()) {
4022 bool RenderWidgetHostImpl::IsHidden() const {
4026 void RenderWidgetHostImpl::DidProcessFrame(uint32_t frame_token,
4027 base::TimeTicks activation_time) {
4028 frame_token_message_queue_->DidProcessFrame(frame_token, activation_time);
4031 #if BUILDFLAG(IS_MAC)
4032 device::mojom::WakeLock* RenderWidgetHostImpl::GetWakeLock() {
4033 // Here is a lazy binding, and will not reconnect after connection error.
4035 mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
4036 GetDeviceService().BindWakeLockProvider(
4037 wake_lock_provider.BindNewPipeAndPassReceiver());
4038 wake_lock_provider->GetWakeLockWithoutContext(
4039 device::mojom::WakeLockType::kPreventDisplaySleep,
4040 device::mojom::WakeLockReason::kOther, "GetSnapshot",
4041 wake_lock_.BindNewPipeAndPassReceiver());
4043 return wake_lock_.get();
4047 void RenderWidgetHostImpl::SetupInputRouter() {
4048 in_flight_event_count_ = 0;
4049 // We are resetting in_flight_event_count_ so also inform the
4050 // BrowserUIThreadScheduler that we are no longer processing input.
4051 user_input_active_handle_.reset();
4052 suppress_events_until_keydown_ = false;
4053 monitoring_composition_info_ = false;
4054 StopInputEventAckTimeout();
4056 input_router_ = std::make_unique<InputRouterImpl>(
4057 this, this, fling_scheduler_.get(), GetInputRouterConfigForPlatform());
4059 // input_router_ recreated, need to update the force_enable_zoom_ state.
4060 input_router_->SetForceEnableZoom(force_enable_zoom_);
4061 input_router_->SetDeviceScaleFactor(GetScaleFactorForView(view_.get()));
4064 void RenderWidgetHostImpl::SetForceEnableZoom(bool enabled) {
4065 force_enable_zoom_ = enabled;
4066 input_router_->SetForceEnableZoom(enabled);
4069 void RenderWidgetHostImpl::SetInputTargetClientForTesting(
4070 mojo::Remote<viz::mojom::InputTargetClient> input_target_client) {
4071 input_target_client_ = std::move(input_target_client);
4074 void RenderWidgetHostImpl::ProgressFlingIfNeeded(base::TimeTicks current_time) {
4075 fling_scheduler_->ProgressFlingOnBeginFrameIfneeded(current_time);
4078 void RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout() {
4079 if (!IsContentRenderingTimeoutRunning()) {
4082 new_content_rendering_timeout_->Stop();
4083 ClearDisplayedGraphics();
4086 void RenderWidgetHostImpl::StopFling() {
4087 input_router_->StopFling();
4090 void RenderWidgetHostImpl::SetScreenOrientationForTesting(
4092 display::mojom::ScreenOrientation type) {
4093 screen_orientation_angle_for_testing_ = angle;
4094 screen_orientation_type_for_testing_ = type;
4095 SynchronizeVisualProperties();
4098 bool RenderWidgetHostImpl::LockKeyboard() {
4099 if (!keyboard_lock_allowed_ || !is_focused_ || !view_) {
4103 // KeyboardLock can be activated and deactivated several times per request,
4104 // for example when a fullscreen tab loses and gains focus multiple times,
4105 // so we need to retain a copy of the keys requested.
4106 absl::optional<base::flat_set<ui::DomCode>> copy = keyboard_keys_to_lock_;
4107 return view_->LockKeyboard(std::move(copy));
4110 void RenderWidgetHostImpl::UnlockKeyboard() {
4111 if (IsKeyboardLocked()) {
4112 view_->UnlockKeyboard();
4116 void RenderWidgetHostImpl::OnRenderFrameMetadataChangedBeforeActivation(
4117 const cc::RenderFrameMetadata& metadata) {}
4119 void RenderWidgetHostImpl::OnRenderFrameMetadataChangedAfterActivation(
4120 base::TimeTicks activation_time) {
4121 const auto& metadata =
4122 render_frame_metadata_provider_.LastRenderFrameMetadata();
4124 bool is_mobile_optimized = metadata.is_mobile_optimized;
4125 input_router_->NotifySiteIsMobileOptimized(is_mobile_optimized);
4126 if (auto* touch_emulator = GetExistingTouchEmulator()) {
4127 touch_emulator->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
4130 // TODO(danakj): Can this method be called during WebContents destruction?
4135 // The root BrowserAccessibilityManager only is reachable if there's a
4136 // delegate() still, ie we're not in shutdown. This can be null in tests.
4137 BrowserAccessibilityManager* accessibility_manager =
4138 GetRootBrowserAccessibilityManager();
4139 if (accessibility_manager) {
4140 accessibility_manager->SetPageScaleFactor(metadata.page_scale_factor);
4143 // The value |kNull| is only used to indicate an absence of vertical scroll
4144 // direction and should therefore be ignored.
4145 // Also, changes in vertical scroll direction are only propagated for main
4146 // frames. If there is no |owner_delegate|, this is not a main frame.
4147 if (metadata.new_vertical_scroll_direction !=
4148 viz::VerticalScrollDirection::kNull &&
4150 delegate()->OnVerticalScrollDirectionChanged(
4151 metadata.new_vertical_scroll_direction);
4155 std::vector<viz::SurfaceId>
4156 RenderWidgetHostImpl::CollectSurfaceIdsForEviction() {
4157 RenderViewHostImpl* rvh = RenderViewHostImpl::From(this);
4158 // A corresponding RenderViewHostImpl may not exist in unit tests.
4162 return rvh->CollectSurfaceIdsForEviction();
4165 std::unique_ptr<RenderWidgetHostIterator>
4166 RenderWidgetHostImpl::GetEmbeddedRenderWidgetHosts() {
4167 // This iterates over all RenderWidgetHosts and returns those whose Views
4168 // are children of this host's View.
4169 auto hosts = std::make_unique<RenderWidgetHostIteratorImpl>();
4170 auto* parent_view = static_cast<RenderWidgetHostViewBase*>(GetView());
4171 for (auto& it : g_routing_id_widget_map.Get()) {
4172 RenderWidgetHost* widget = it.second;
4174 auto* view = static_cast<RenderWidgetHostViewBase*>(widget->GetView());
4175 if (view && view->IsRenderWidgetHostViewChildFrame() &&
4176 static_cast<RenderWidgetHostViewChildFrame*>(view)->GetParentView() ==
4182 return std::move(hosts);
4187 bool TransformPointAndRectToRootView(RenderWidgetHostViewBase* view,
4188 RenderWidgetHostViewBase* root_view,
4189 gfx::Point* transformed_point,
4190 gfx::Rect* transformed_rect) {
4191 gfx::Transform transform_to_main_frame;
4192 if (!view->GetTransformToViewCoordSpace(root_view,
4193 &transform_to_main_frame)) {
4197 if (transformed_point) {
4198 *transformed_point = transform_to_main_frame.MapPoint(*transformed_point);
4201 if (transformed_rect) {
4202 *transformed_rect = transform_to_main_frame.MapRect(*transformed_rect);
4210 void RenderWidgetHostImpl::AnimateDoubleTapZoomInMainFrame(
4211 const gfx::Point& point,
4212 const gfx::Rect& rect_to_zoom) {
4217 auto* root_view = view_->GetRootView();
4218 gfx::Point transformed_point(point);
4219 gfx::Rect transformed_rect_to_zoom(rect_to_zoom);
4220 if (!TransformPointAndRectToRootView(view_.get(), root_view,
4222 &transformed_rect_to_zoom)) {
4226 auto* root_rvhi = RenderViewHostImpl::From(root_view->GetRenderWidgetHost());
4227 root_rvhi->AnimateDoubleTapZoom(transformed_point, transformed_rect_to_zoom);
4230 void RenderWidgetHostImpl::ZoomToFindInPageRectInMainFrame(
4231 const gfx::Rect& rect_to_zoom) {
4236 auto* root_view = view_->GetRootView();
4237 gfx::Rect transformed_rect_to_zoom(rect_to_zoom);
4238 if (!TransformPointAndRectToRootView(view_.get(), root_view, nullptr,
4239 &transformed_rect_to_zoom)) {
4243 auto* root_rvhi = RenderViewHostImpl::From(root_view->GetRenderWidgetHost());
4244 root_rvhi->ZoomToFindInPageRect(transformed_rect_to_zoom);
4247 void RenderWidgetHostImpl::SetHasTouchEventConsumers(
4248 blink::mojom::TouchEventConsumersPtr consumers) {
4249 input_router_->OnHasTouchEventConsumers(std::move(consumers));
4252 void RenderWidgetHostImpl::IntrinsicSizingInfoChanged(
4253 blink::mojom::IntrinsicSizingInfoPtr sizing_info) {
4255 view_->UpdateIntrinsicSizingInfo(std::move(sizing_info));
4259 gfx::Size RenderWidgetHostImpl::GetRootWidgetViewportSize() {
4264 // if |view_| is RWHVCF and |frame_connector_| is destroyed, then call to
4265 // GetRootView will return null pointer.
4266 auto* root_view = view_->GetRootView();
4271 return root_view->GetVisibleViewportSize();
4274 #if BUILDFLAG(IS_EFL)
4275 void RenderWidgetHostImpl::HandleKeyEvent(blink::WebInputEvent::Type type,
4279 view_->DidHandleKeyEvent(type, processed);
4283 // This method was copied from RenderWidget::ConvertWindowToViewport() when
4284 // porting drag-and-drop calls to Mojo, so that RenderWidgetHostImpl bypasses
4285 // RenderWidget to talk the the WebFrameWidget and needs to perform the scale
4286 // operation itself.
4287 gfx::PointF RenderWidgetHostImpl::ConvertWindowPointToViewport(
4288 const gfx::PointF& window_point) {
4289 gfx::PointF viewport_point = window_point;
4290 viewport_point.Scale(GetScaleFactorForView(GetView()));
4291 return viewport_point;
4294 void RenderWidgetHostImpl::SetViewIsFrameSinkIdOwner(bool is_owner) {
4295 if (view_is_frame_sink_id_owner_ == is_owner) {
4299 view_is_frame_sink_id_owner_ = is_owner;
4301 view_->SetIsFrameSinkIdOwner(view_is_frame_sink_id_owner_);
4302 MaybeDispatchBufferedFrameSinkRequest();
4306 RenderWidgetHostImpl::MainFramePropagationProperties::
4307 MainFramePropagationProperties() = default;
4309 RenderWidgetHostImpl::MainFramePropagationProperties::
4310 ~MainFramePropagationProperties() = default;
4312 RenderWidgetHostImpl::PendingShowParams::PendingShowParams(
4314 blink::mojom::RecordContentToVisibleTimeRequestPtr visible_time_request)
4315 : is_evicted(is_evicted),
4316 visible_time_request(std::move(visible_time_request)) {}
4318 RenderWidgetHostImpl::PendingShowParams::~PendingShowParams() = default;
4320 } // namespace content