1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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"
11 #include "base/auto_reset.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/debug/trace_event.h"
16 #include "base/i18n/rtl.h"
17 #include "base/lazy_instance.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/histogram.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "cc/base/switches.h"
25 #include "cc/output/compositor_frame.h"
26 #include "cc/output/compositor_frame_ack.h"
27 #include "content/browser/accessibility/accessibility_mode_helper.h"
28 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
29 #include "content/browser/gpu/compositor_util.h"
30 #include "content/browser/gpu/gpu_process_host.h"
31 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
32 #include "content/browser/gpu/gpu_surface_tracker.h"
33 #include "content/browser/renderer_host/dip_util.h"
34 #include "content/browser/renderer_host/input/input_router_config_helper.h"
35 #include "content/browser/renderer_host/input/input_router_impl.h"
36 #include "content/browser/renderer_host/input/synthetic_gesture.h"
37 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
38 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
39 #include "content/browser/renderer_host/input/timeout_monitor.h"
40 #include "content/browser/renderer_host/input/touch_emulator.h"
41 #include "content/browser/renderer_host/overscroll_controller.h"
42 #include "content/browser/renderer_host/render_process_host_impl.h"
43 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/renderer_host/render_widget_helper.h"
45 #include "content/browser/renderer_host/render_widget_host_delegate.h"
46 #include "content/browser/renderer_host/render_widget_host_view_base.h"
47 #include "content/common/accessibility_messages.h"
48 #include "content/common/content_constants_internal.h"
49 #include "content/common/cursors/webcursor.h"
50 #include "content/common/gpu/gpu_messages.h"
51 #include "content/common/host_shared_bitmap_manager.h"
52 #include "content/common/input_messages.h"
53 #include "content/common/view_messages.h"
54 #include "content/public/browser/native_web_keyboard_event.h"
55 #include "content/public/browser/notification_service.h"
56 #include "content/public/browser/notification_types.h"
57 #include "content/public/browser/render_widget_host_iterator.h"
58 #include "content/public/browser/user_metrics.h"
59 #include "content/public/common/content_constants.h"
60 #include "content/public/common/content_switches.h"
61 #include "content/public/common/result_codes.h"
62 #include "skia/ext/image_operations.h"
63 #include "skia/ext/platform_canvas.h"
64 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
65 #include "ui/events/event.h"
66 #include "ui/events/keycodes/keyboard_codes.h"
67 #include "ui/gfx/size_conversions.h"
68 #include "ui/gfx/skbitmap_operations.h"
69 #include "ui/gfx/vector2d_conversions.h"
70 #include "ui/snapshot/snapshot.h"
71 #include "webkit/common/webpreferences.h"
74 #include "content/common/plugin_constants_win.h"
78 using base::TimeDelta
;
79 using base::TimeTicks
;
80 using blink::WebGestureEvent
;
81 using blink::WebInputEvent
;
82 using blink::WebKeyboardEvent
;
83 using blink::WebMouseEvent
;
84 using blink::WebMouseWheelEvent
;
85 using blink::WebTextDirection
;
90 bool g_check_for_pending_resize_ack
= true;
92 // How long to (synchronously) wait for the renderer to respond with a
93 // PaintRect message, when our backing-store is invalid, before giving up and
94 // returning a null or incorrectly sized backing-store from GetBackingStore.
95 // This timeout impacts the "choppiness" of our window resize perf.
96 const int kPaintMsgTimeoutMS
= 50;
98 typedef std::pair
<int32
, int32
> RenderWidgetHostID
;
99 typedef base::hash_map
<RenderWidgetHostID
, RenderWidgetHostImpl
*>
101 base::LazyInstance
<RoutingIDWidgetMap
> g_routing_id_widget_map
=
102 LAZY_INSTANCE_INITIALIZER
;
104 int GetInputRouterViewFlagsFromCompositorFrameMetadata(
105 const cc::CompositorFrameMetadata metadata
) {
106 int view_flags
= InputRouter::VIEW_FLAGS_NONE
;
108 if (metadata
.min_page_scale_factor
== metadata
.max_page_scale_factor
)
109 view_flags
|= InputRouter::FIXED_PAGE_SCALE
;
111 const float window_width_dip
=
112 std::ceil(metadata
.page_scale_factor
* metadata
.viewport_size
.width());
113 const float content_width_css
= metadata
.root_layer_size
.width();
114 if (content_width_css
<= window_width_dip
)
115 view_flags
|= InputRouter::MOBILE_VIEWPORT
;
120 // Implements the RenderWidgetHostIterator interface. It keeps a list of
121 // RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
122 // iteration (or NULL if there isn't any left).
123 class RenderWidgetHostIteratorImpl
: public RenderWidgetHostIterator
{
125 RenderWidgetHostIteratorImpl()
126 : current_index_(0) {
129 virtual ~RenderWidgetHostIteratorImpl() {
132 void Add(RenderWidgetHost
* host
) {
133 hosts_
.push_back(RenderWidgetHostID(host
->GetProcess()->GetID(),
134 host
->GetRoutingID()));
137 // RenderWidgetHostIterator:
138 virtual RenderWidgetHost
* GetNextHost() OVERRIDE
{
139 RenderWidgetHost
* host
= NULL
;
140 while (current_index_
< hosts_
.size() && !host
) {
141 RenderWidgetHostID id
= hosts_
[current_index_
];
142 host
= RenderWidgetHost::FromID(id
.first
, id
.second
);
149 std::vector
<RenderWidgetHostID
> hosts_
;
150 size_t current_index_
;
152 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl
);
157 ///////////////////////////////////////////////////////////////////////////////
158 // RenderWidgetHostImpl
160 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate
* delegate
,
161 RenderProcessHost
* process
,
165 renderer_initialized_(false),
166 hung_renderer_delay_ms_(kHungRendererDelayMs
),
169 routing_id_(routing_id
),
173 is_fullscreen_(false),
174 is_accelerated_compositing_active_(false),
175 repaint_ack_pending_(false),
176 resize_ack_pending_(false),
177 screen_info_out_of_date_(false),
178 overdraw_bottom_height_(0.f
),
179 should_auto_resize_(false),
180 waiting_for_screen_rects_ack_(false),
181 accessibility_mode_(AccessibilityModeOff
),
182 needs_repainting_on_restore_(false),
183 is_unresponsive_(false),
184 in_flight_event_count_(0),
185 in_get_backing_store_(false),
186 abort_get_backing_store_(false),
187 view_being_painted_(false),
188 ignore_input_events_(false),
189 input_method_active_(false),
190 text_direction_updated_(false),
191 text_direction_(blink::WebTextDirectionLeftToRight
),
192 text_direction_canceled_(false),
193 suppress_next_char_events_(false),
194 pending_mouse_lock_request_(false),
195 allow_privileged_mouse_lock_(false),
196 has_touch_handler_(false),
198 last_input_number_(static_cast<int64
>(GetProcess()->GetID()) << 32) {
200 if (routing_id_
== MSG_ROUTING_NONE
) {
201 routing_id_
= process_
->GetNextRoutingID();
202 surface_id_
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
206 // TODO(piman): This is a O(N) lookup, where we could forward the
207 // information from the RenderWidgetHelper. The problem is that doing so
208 // currently leaks outside of content all the way to chrome classes, and
209 // would be a layering violation. Since we don't expect more than a few
210 // hundreds of RWH, this seems acceptable. Revisit if performance become a
211 // problem, for example by tracking in the RenderWidgetHelper the routing id
212 // (and surface id) that have been created, but whose RWH haven't yet.
213 surface_id_
= GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
219 std::pair
<RoutingIDWidgetMap::iterator
, bool> result
=
220 g_routing_id_widget_map
.Get().insert(std::make_pair(
221 RenderWidgetHostID(process
->GetID(), routing_id_
), this));
222 CHECK(result
.second
) << "Inserting a duplicate item!";
223 process_
->AddRoute(routing_id_
, this);
225 // If we're initially visible, tell the process host that we're alive.
226 // Otherwise we'll notify the process host when we are first shown.
228 process_
->WidgetRestored();
230 accessibility_mode_
=
231 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
233 input_router_
.reset(new InputRouterImpl(
234 process_
, this, this, routing_id_
, GetInputRouterConfigForPlatform()));
236 touch_emulator_
.reset();
238 #if defined(USE_AURA)
239 bool overscroll_enabled
= CommandLine::ForCurrentProcess()->
240 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation
) != "0";
241 SetOverscrollControllerEnabled(overscroll_enabled
);
244 if (GetProcess()->IsGuest() || !CommandLine::ForCurrentProcess()->HasSwitch(
245 switches::kDisableHangMonitor
)) {
246 hang_monitor_timeout_
.reset(new TimeoutMonitor(
247 base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive
,
248 weak_factory_
.GetWeakPtr())));
252 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
255 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_
);
258 process_
->RemoveRoute(routing_id_
);
259 g_routing_id_widget_map
.Get().erase(
260 RenderWidgetHostID(process_
->GetID(), routing_id_
));
263 delegate_
->RenderWidgetDeleted(this);
267 RenderWidgetHost
* RenderWidgetHost::FromID(
270 return RenderWidgetHostImpl::FromID(process_id
, routing_id
);
274 RenderWidgetHostImpl
* RenderWidgetHostImpl::FromID(
277 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
278 RoutingIDWidgetMap
* widgets
= g_routing_id_widget_map
.Pointer();
279 RoutingIDWidgetMap::iterator it
= widgets
->find(
280 RenderWidgetHostID(process_id
, routing_id
));
281 return it
== widgets
->end() ? NULL
: it
->second
;
285 scoped_ptr
<RenderWidgetHostIterator
> RenderWidgetHost::GetRenderWidgetHosts() {
286 RenderWidgetHostIteratorImpl
* hosts
= new RenderWidgetHostIteratorImpl();
287 RoutingIDWidgetMap
* widgets
= g_routing_id_widget_map
.Pointer();
288 for (RoutingIDWidgetMap::const_iterator it
= widgets
->begin();
289 it
!= widgets
->end();
291 RenderWidgetHost
* widget
= it
->second
;
293 if (!widget
->IsRenderView()) {
298 // Add only active RenderViewHosts.
299 RenderViewHost
* rvh
= RenderViewHost::From(widget
);
300 if (RenderViewHostImpl::IsRVHStateActive(
301 static_cast<RenderViewHostImpl
*>(rvh
)->rvh_state()))
305 return scoped_ptr
<RenderWidgetHostIterator
>(hosts
);
309 scoped_ptr
<RenderWidgetHostIterator
>
310 RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
311 RenderWidgetHostIteratorImpl
* hosts
= new RenderWidgetHostIteratorImpl();
312 RoutingIDWidgetMap
* widgets
= g_routing_id_widget_map
.Pointer();
313 for (RoutingIDWidgetMap::const_iterator it
= widgets
->begin();
314 it
!= widgets
->end();
316 hosts
->Add(it
->second
);
319 return scoped_ptr
<RenderWidgetHostIterator
>(hosts
);
323 RenderWidgetHostImpl
* RenderWidgetHostImpl::From(RenderWidgetHost
* rwh
) {
324 return rwh
->AsRenderWidgetHostImpl();
327 void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase
* view
) {
330 GpuSurfaceTracker::Get()->SetSurfaceHandle(
331 surface_id_
, GetCompositingSurface());
333 synthetic_gesture_controller_
.reset();
336 RenderProcessHost
* RenderWidgetHostImpl::GetProcess() const {
340 int RenderWidgetHostImpl::GetRoutingID() const {
344 RenderWidgetHostView
* RenderWidgetHostImpl::GetView() const {
348 RenderWidgetHostImpl
* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
352 gfx::NativeViewId
RenderWidgetHostImpl::GetNativeViewId() const {
354 return view_
->GetNativeViewId();
358 gfx::GLSurfaceHandle
RenderWidgetHostImpl::GetCompositingSurface() {
360 return view_
->GetCompositingSurface();
361 return gfx::GLSurfaceHandle();
364 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
365 resize_ack_pending_
= false;
366 if (repaint_ack_pending_
) {
367 TRACE_EVENT_ASYNC_END0(
368 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
370 repaint_ack_pending_
= false;
371 last_requested_size_
.SetSize(0, 0);
374 void RenderWidgetHostImpl::SendScreenRects() {
375 if (!renderer_initialized_
|| waiting_for_screen_rects_ack_
)
379 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
380 // happens on Win & Mac, and when the view is shown it'll call this again.
387 last_view_screen_rect_
= view_
->GetViewBounds();
388 last_window_screen_rect_
= view_
->GetBoundsInRootWindow();
389 Send(new ViewMsg_UpdateScreenRects(
390 GetRoutingID(), last_view_screen_rect_
, last_window_screen_rect_
));
392 delegate_
->DidSendScreenRects(this);
393 waiting_for_screen_rects_ack_
= true;
396 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled
) {
398 overscroll_controller_
.reset();
399 else if (!overscroll_controller_
)
400 overscroll_controller_
.reset(new OverscrollController());
403 void RenderWidgetHostImpl::SuppressNextCharEvents() {
404 suppress_next_char_events_
= true;
407 void RenderWidgetHostImpl::FlushInput() {
408 input_router_
->Flush();
409 if (synthetic_gesture_controller_
)
410 synthetic_gesture_controller_
->Flush(base::TimeTicks::Now());
413 void RenderWidgetHostImpl::SetNeedsFlush() {
415 view_
->OnSetNeedsFlushInput();
418 void RenderWidgetHostImpl::Init() {
419 DCHECK(process_
->HasConnection());
421 renderer_initialized_
= true;
423 GpuSurfaceTracker::Get()->SetSurfaceHandle(
424 surface_id_
, GetCompositingSurface());
426 // Send the ack along with the information on placement.
427 Send(new ViewMsg_CreatingNew_ACK(routing_id_
));
428 GetProcess()->ResumeRequestsForView(routing_id_
);
433 void RenderWidgetHostImpl::Shutdown() {
434 RejectMouseLockOrUnlockIfNecessary();
436 if (process_
->HasConnection()) {
437 // Tell the renderer object to close.
438 bool rv
= Send(new ViewMsg_Close(routing_id_
));
445 bool RenderWidgetHostImpl::IsLoading() const {
449 bool RenderWidgetHostImpl::IsRenderView() const {
453 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message
&msg
) {
455 bool msg_is_ok
= true;
456 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl
, msg
, msg_is_ok
)
457 IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture
,
458 OnQueueSyntheticGesture
)
459 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady
, OnRenderViewReady
)
460 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone
, OnRenderProcessGone
)
461 IPC_MESSAGE_HANDLER(ViewHostMsg_Close
, OnClose
)
462 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK
,
463 OnUpdateScreenRectsAck
)
464 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove
, OnRequestMove
)
465 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText
, OnSetTooltipText
)
466 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame
,
467 msg_is_ok
= OnSwapCompositorFrame(msg
))
468 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopFlinging
, OnFlingingStopped
)
469 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnUpdateRect
)
470 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed
, OnUpdateIsDelayed
)
471 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus
, OnFocus
)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur
, OnBlur
)
473 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnSetCursor
)
474 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTouchEventEmulationEnabled
,
475 OnSetTouchEventEmulationEnabled
)
476 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged
,
477 OnTextInputTypeChanged
)
478 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition
,
479 OnImeCancelComposition
)
480 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing
,
481 OnDidActivateAcceleratedCompositing
)
482 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnLockMouse
)
483 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnUnlockMouse
)
484 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup
,
485 OnShowDisambiguationPopup
)
486 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged
, OnSelectionChanged
)
487 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged
,
488 OnSelectionBoundsChanged
)
490 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated
,
491 OnWindowlessPluginDummyWindowCreated
)
492 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed
,
493 OnWindowlessPluginDummyWindowDestroyed
)
495 #if defined(OS_MACOSX)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped
,
497 OnCompositorSurfaceBuffersSwapped
)
499 #if defined(OS_MACOSX) || defined(USE_AURA)
500 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged
,
501 OnImeCompositionRangeChanged
)
503 IPC_MESSAGE_UNHANDLED(handled
= false)
504 IPC_END_MESSAGE_MAP_EX()
506 if (!handled
&& input_router_
&& input_router_
->OnMessageReceived(msg
))
509 if (!handled
&& view_
&& view_
->OnMessageReceived(msg
))
513 // The message de-serialization failed. Kill the renderer process.
514 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH"));
515 GetProcess()->ReceivedBadMessage();
520 bool RenderWidgetHostImpl::Send(IPC::Message
* msg
) {
521 if (IPC_MESSAGE_ID_CLASS(msg
->type()) == InputMsgStart
)
522 return input_router_
->SendInput(make_scoped_ptr(msg
));
524 return process_
->Send(msg
);
527 void RenderWidgetHostImpl::WasHidden() {
533 // Don't bother reporting hung state when we aren't active.
534 StopHangMonitorTimeout();
536 // If we have a renderer, then inform it that we are being hidden so it can
537 // reduce its resource utilization.
538 Send(new ViewMsg_WasHidden(routing_id_
));
540 // Tell the RenderProcessHost we were hidden.
541 process_
->WidgetHidden();
543 bool is_visible
= false;
544 NotificationService::current()->Notify(
545 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
546 Source
<RenderWidgetHost
>(this),
547 Details
<bool>(&is_visible
));
550 void RenderWidgetHostImpl::WasShown() {
557 // Always repaint on restore.
558 bool needs_repainting
= true;
559 needs_repainting_on_restore_
= false;
560 Send(new ViewMsg_WasShown(routing_id_
, needs_repainting
));
562 process_
->WidgetRestored();
564 bool is_visible
= true;
565 NotificationService::current()->Notify(
566 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
567 Source
<RenderWidgetHost
>(this),
568 Details
<bool>(&is_visible
));
570 // It's possible for our size to be out of sync with the renderer. The
571 // following is one case that leads to this:
572 // 1. WasResized -> Send ViewMsg_Resize to render
573 // 2. WasResized -> do nothing as resize_ack_pending_ is true
575 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
576 // is hidden. Now renderer/browser out of sync with what they think size
578 // By invoking WasResized the renderer is updated as necessary. WasResized
579 // does nothing if the sizes are already in sync.
581 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
582 // could handle both the restore and resize at once. This isn't that big a
583 // deal as RenderWidget::WasShown delays updating, so that the resize from
584 // WasResized is usually processed before the renderer is painted.
588 void RenderWidgetHostImpl::WasResized() {
589 // Skip if the |delegate_| has already been detached because
590 // it's web contents is being deleted.
591 if (resize_ack_pending_
|| !process_
->HasConnection() || !view_
||
592 !renderer_initialized_
|| should_auto_resize_
|| !delegate_
) {
596 gfx::Rect view_bounds
= view_
->GetViewBounds();
597 gfx::Size
new_size(view_bounds
.size());
599 gfx::Size old_physical_backing_size
= physical_backing_size_
;
600 physical_backing_size_
= view_
->GetPhysicalBackingSize();
601 bool was_fullscreen
= is_fullscreen_
;
602 is_fullscreen_
= IsFullscreen();
603 float old_overdraw_bottom_height
= overdraw_bottom_height_
;
604 overdraw_bottom_height_
= view_
->GetOverdrawBottomHeight();
605 gfx::Size old_visible_viewport_size
= visible_viewport_size_
;
606 visible_viewport_size_
= view_
->GetVisibleViewportSize();
608 bool size_changed
= new_size
!= last_requested_size_
;
609 bool side_payload_changed
=
610 screen_info_out_of_date_
||
611 old_physical_backing_size
!= physical_backing_size_
||
612 was_fullscreen
!= is_fullscreen_
||
613 old_overdraw_bottom_height
!= overdraw_bottom_height_
||
614 old_visible_viewport_size
!= visible_viewport_size_
;
616 if (!size_changed
&& !side_payload_changed
)
620 screen_info_
.reset(new blink::WebScreenInfo
);
621 GetWebScreenInfo(screen_info_
.get());
624 // We don't expect to receive an ACK when the requested size or the physical
625 // backing size is empty, or when the main viewport size didn't change.
626 if (!new_size
.IsEmpty() && !physical_backing_size_
.IsEmpty() && size_changed
)
627 resize_ack_pending_
= g_check_for_pending_resize_ack
;
629 ViewMsg_Resize_Params params
;
630 params
.screen_info
= *screen_info_
;
631 params
.new_size
= new_size
;
632 params
.physical_backing_size
= physical_backing_size_
;
633 params
.overdraw_bottom_height
= overdraw_bottom_height_
;
634 params
.visible_viewport_size
= visible_viewport_size_
;
635 params
.resizer_rect
= GetRootWindowResizerRect();
636 params
.is_fullscreen
= is_fullscreen_
;
637 if (!Send(new ViewMsg_Resize(routing_id_
, params
))) {
638 resize_ack_pending_
= false;
640 last_requested_size_
= new_size
;
644 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect
& new_rect
) {
645 Send(new ViewMsg_ChangeResizeRect(routing_id_
, new_rect
));
648 void RenderWidgetHostImpl::GotFocus() {
652 void RenderWidgetHostImpl::Focus() {
653 Send(new InputMsg_SetFocus(routing_id_
, true));
656 void RenderWidgetHostImpl::Blur() {
657 // If there is a pending mouse lock request, we don't want to reject it at
658 // this point. The user can switch focus back to this view and approve the
661 view_
->UnlockMouse();
663 // If there is a pending overscroll, then that should be cancelled.
664 if (overscroll_controller_
)
665 overscroll_controller_
->Cancel();
668 touch_emulator_
->CancelTouch();
670 Send(new InputMsg_SetFocus(routing_id_
, false));
673 void RenderWidgetHostImpl::LostCapture() {
675 touch_emulator_
->CancelTouch();
677 Send(new InputMsg_MouseCaptureLost(routing_id_
));
680 void RenderWidgetHostImpl::SetActive(bool active
) {
681 Send(new ViewMsg_SetActive(routing_id_
, active
));
684 void RenderWidgetHostImpl::LostMouseLock() {
685 Send(new ViewMsg_MouseLockLost(routing_id_
));
688 void RenderWidgetHostImpl::ViewDestroyed() {
689 RejectMouseLockOrUnlockIfNecessary();
691 // TODO(evanm): tracking this may no longer be necessary;
692 // eliminate this function if so.
696 void RenderWidgetHostImpl::SetIsLoading(bool is_loading
) {
697 is_loading_
= is_loading
;
700 view_
->SetIsLoading(is_loading
);
703 void RenderWidgetHostImpl::CopyFromBackingStore(
704 const gfx::Rect
& src_subrect
,
705 const gfx::Size
& accelerated_dst_size
,
706 const base::Callback
<void(bool, const SkBitmap
&)>& callback
,
707 const SkBitmap::Config
& bitmap_config
) {
708 if (view_
&& is_accelerated_compositing_active_
) {
709 TRACE_EVENT0("browser",
710 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
711 gfx::Rect accelerated_copy_rect
= src_subrect
.IsEmpty() ?
712 gfx::Rect(view_
->GetViewBounds().size()) : src_subrect
;
713 view_
->CopyFromCompositingSurface(
714 accelerated_copy_rect
, accelerated_dst_size
, callback
, bitmap_config
);
718 callback
.Run(false, SkBitmap());
721 bool RenderWidgetHostImpl::CanCopyFromBackingStore() {
723 return view_
->IsSurfaceAvailableForCopy();
727 #if defined(OS_ANDROID)
728 void RenderWidgetHostImpl::LockBackingStore() {
730 view_
->LockCompositingSurface();
733 void RenderWidgetHostImpl::UnlockBackingStore() {
735 view_
->UnlockCompositingSurface();
739 void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
740 TRACE_EVENT0("browser",
741 "RenderWidgetHostImpl::PauseForPendingResizeOrRepaints");
743 if (!CanPauseForPendingResizeOrRepaints())
749 bool RenderWidgetHostImpl::CanPauseForPendingResizeOrRepaints() {
750 // Do not pause if the view is hidden.
754 // Do not pause if there is not a paint or resize already coming.
755 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
)
761 void RenderWidgetHostImpl::WaitForSurface() {
762 TRACE_EVENT0("browser", "RenderWidgetHostImpl::WaitForSurface");
767 // The view_size will be current_size_ for auto-sized views and otherwise the
768 // size of the view_. (For auto-sized views, current_size_ is updated during
769 // UpdateRect messages.)
770 gfx::Size view_size
= current_size_
;
771 if (!should_auto_resize_
) {
772 // Get the desired size from the current view bounds.
773 gfx::Rect view_rect
= view_
->GetViewBounds();
774 if (view_rect
.IsEmpty())
776 view_size
= view_rect
.size();
779 TRACE_EVENT2("renderer_host",
780 "RenderWidgetHostImpl::WaitForBackingStore",
782 base::IntToString(view_size
.width()),
784 base::IntToString(view_size
.height()));
786 // We should not be asked to paint while we are hidden. If we are hidden,
787 // then it means that our consumer failed to call WasShown. If we're not
788 // force creating the backing store, it's OK since we can feel free to give
789 // out our cached one if we have it.
790 DCHECK(!is_hidden_
) << "WaitForSurface called while hidden!";
792 // We should never be called recursively; this can theoretically lead to
793 // infinite recursion and almost certainly leads to lower performance.
794 DCHECK(!in_get_backing_store_
) << "WaitForSurface called recursively!";
795 base::AutoReset
<bool> auto_reset_in_get_backing_store(
796 &in_get_backing_store_
, true);
798 // We might have a surface that we can use!
799 if (view_
->HasAcceleratedSurface(view_size
))
802 // We do not have a suitable backing store in the cache, so send out a
803 // request to the renderer to paint the view if required.
804 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
) {
805 repaint_start_time_
= TimeTicks::Now();
806 repaint_ack_pending_
= true;
807 TRACE_EVENT_ASYNC_BEGIN0(
808 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
809 Send(new ViewMsg_Repaint(routing_id_
, view_size
));
812 TimeDelta max_delay
= TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS
);
813 TimeTicks end_time
= TimeTicks::Now() + max_delay
;
815 TRACE_EVENT0("renderer_host", "WaitForSurface::WaitForUpdate");
817 // When we have asked the RenderWidget to resize, and we are still waiting
818 // on a response, block for a little while to see if we can't get a response
819 // before returning the old (incorrectly sized) backing store.
821 if (process_
->WaitForBackingStoreMsg(routing_id_
, max_delay
, &msg
)) {
822 OnMessageReceived(msg
);
824 // For auto-resized views, current_size_ determines the view_size and it
825 // may have changed during the handling of an UpdateRect message.
826 if (should_auto_resize_
)
827 view_size
= current_size_
;
829 // Break now if we got a backing store or accelerated surface of the
831 if (view_
->HasAcceleratedSurface(view_size
) || abort_get_backing_store_
) {
832 abort_get_backing_store_
= false;
836 TRACE_EVENT0("renderer_host", "WaitForSurface::Timeout");
840 // Loop if we still have time left and haven't gotten a properly sized
841 // BackingStore yet. This is necessary to support the GPU path which
842 // typically has multiple frames pipelined -- we may need to skip one or two
843 // BackingStore messages to get to the latest.
844 max_delay
= end_time
- TimeTicks::Now();
845 } while (max_delay
> TimeDelta::FromSeconds(0));
848 bool RenderWidgetHostImpl::ScheduleComposite() {
849 if (is_hidden_
|| !is_accelerated_compositing_active_
||
850 current_size_
.IsEmpty() || repaint_ack_pending_
||
851 resize_ack_pending_
|| view_being_painted_
) {
855 // Send out a request to the renderer to paint the view if required.
856 repaint_start_time_
= TimeTicks::Now();
857 repaint_ack_pending_
= true;
858 TRACE_EVENT_ASYNC_BEGIN0(
859 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
860 Send(new ViewMsg_Repaint(routing_id_
, current_size_
));
864 void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay
) {
865 if (hang_monitor_timeout_
)
866 hang_monitor_timeout_
->Start(delay
);
869 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
870 if (hang_monitor_timeout_
)
871 hang_monitor_timeout_
->Restart(
872 base::TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
875 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
876 if (hang_monitor_timeout_
)
877 hang_monitor_timeout_
->Stop();
878 RendererIsResponsive();
881 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
882 AddAccessibilityMode(AccessibilityModeComplete
);
885 bool RenderWidgetHostImpl::IsFullAccessibilityModeForTesting() {
886 return accessibility_mode() == AccessibilityModeComplete
;
889 void RenderWidgetHostImpl::EnableTreeOnlyAccessibilityMode() {
890 AddAccessibilityMode(AccessibilityModeTreeOnly
);
893 bool RenderWidgetHostImpl::IsTreeOnlyAccessibilityModeForTesting() {
894 return accessibility_mode() == AccessibilityModeTreeOnly
;
897 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent
& mouse_event
) {
898 ForwardMouseEventWithLatencyInfo(mouse_event
, ui::LatencyInfo());
901 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
902 const blink::WebMouseEvent
& mouse_event
,
903 const ui::LatencyInfo
& ui_latency
) {
904 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
905 "x", mouse_event
.x
, "y", mouse_event
.y
);
907 ui::LatencyInfo latency_info
=
908 CreateRWHLatencyInfoIfNotExist(&ui_latency
, mouse_event
.type
);
910 for (size_t i
= 0; i
< mouse_event_callbacks_
.size(); ++i
) {
911 if (mouse_event_callbacks_
[i
].Run(mouse_event
))
915 if (IgnoreInputEvents())
918 if (touch_emulator_
&& touch_emulator_
->HandleMouseEvent(mouse_event
))
921 input_router_
->SendMouseEvent(MouseEventWithLatencyInfo(mouse_event
,
925 void RenderWidgetHostImpl::OnPointerEventActivate() {
928 void RenderWidgetHostImpl::ForwardWheelEvent(
929 const WebMouseWheelEvent
& wheel_event
) {
930 ForwardWheelEventWithLatencyInfo(wheel_event
, ui::LatencyInfo());
933 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
934 const blink::WebMouseWheelEvent
& wheel_event
,
935 const ui::LatencyInfo
& ui_latency
) {
936 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
938 ui::LatencyInfo latency_info
=
939 CreateRWHLatencyInfoIfNotExist(&ui_latency
, wheel_event
.type
);
941 if (IgnoreInputEvents())
944 if (touch_emulator_
&& touch_emulator_
->HandleMouseWheelEvent(wheel_event
))
947 input_router_
->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event
,
951 void RenderWidgetHostImpl::ForwardGestureEvent(
952 const blink::WebGestureEvent
& gesture_event
) {
953 ForwardGestureEventWithLatencyInfo(gesture_event
, ui::LatencyInfo());
956 void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
957 const blink::WebGestureEvent
& gesture_event
,
958 const ui::LatencyInfo
& ui_latency
) {
959 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
960 // Early out if necessary, prior to performing latency logic.
961 if (IgnoreInputEvents())
964 if (delegate_
->PreHandleGestureEvent(gesture_event
))
967 ui::LatencyInfo latency_info
=
968 CreateRWHLatencyInfoIfNotExist(&ui_latency
, gesture_event
.type
);
970 if (gesture_event
.type
== blink::WebInputEvent::GestureScrollUpdate
) {
971 latency_info
.AddLatencyNumber(
972 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT
,
973 GetLatencyComponentId(),
974 ++last_input_number_
);
976 // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
977 // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
978 // So we can track the latency specifically for scroll update events.
979 ui::LatencyInfo::LatencyComponent original_component
;
980 if (latency_info
.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT
,
982 &original_component
)) {
983 latency_info
.AddLatencyNumberWithTimestamp(
984 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT
,
985 GetLatencyComponentId(),
986 original_component
.sequence_number
,
987 original_component
.event_time
,
988 original_component
.event_count
);
992 GestureEventWithLatencyInfo
gesture_with_latency(gesture_event
, latency_info
);
993 input_router_
->SendGestureEvent(gesture_with_latency
);
996 void RenderWidgetHostImpl::ForwardTouchEvent(
997 const blink::WebTouchEvent
& touch_event
) {
998 ForwardTouchEventWithLatencyInfo(touch_event
, ui::LatencyInfo());
1001 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1002 const blink::WebTouchEvent
& touch_event
,
1003 const ui::LatencyInfo
& ui_latency
) {
1004 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1006 // Always forward TouchEvents for touch stream consistency. They will be
1007 // ignored if appropriate in FilterInputEvent().
1009 ui::LatencyInfo latency_info
=
1010 CreateRWHLatencyInfoIfNotExist(&ui_latency
, touch_event
.type
);
1011 TouchEventWithLatencyInfo
touch_with_latency(touch_event
, latency_info
);
1012 input_router_
->SendTouchEvent(touch_with_latency
);
1015 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1016 const NativeWebKeyboardEvent
& key_event
) {
1017 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1018 if (IgnoreInputEvents())
1021 if (!process_
->HasConnection())
1024 // First, let keypress listeners take a shot at handling the event. If a
1025 // listener handles the event, it should not be propagated to the renderer.
1026 if (KeyPressListenersHandleEvent(key_event
)) {
1027 // Some keypresses that are accepted by the listener might have follow up
1028 // char events, which should be ignored.
1029 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1030 suppress_next_char_events_
= true;
1034 if (key_event
.type
== WebKeyboardEvent::Char
&&
1035 (key_event
.windowsKeyCode
== ui::VKEY_RETURN
||
1036 key_event
.windowsKeyCode
== ui::VKEY_SPACE
)) {
1040 // Double check the type to make sure caller hasn't sent us nonsense that
1041 // will mess up our key queue.
1042 if (!WebInputEvent::isKeyboardEventType(key_event
.type
))
1045 if (suppress_next_char_events_
) {
1046 // If preceding RawKeyDown event was handled by the browser, then we need
1047 // suppress all Char events generated by it. Please note that, one
1048 // RawKeyDown event may generate multiple Char events, so we can't reset
1049 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1050 if (key_event
.type
== WebKeyboardEvent::Char
)
1052 // We get a KeyUp or a RawKeyDown event.
1053 suppress_next_char_events_
= false;
1056 bool is_shortcut
= false;
1058 // Only pre-handle the key event if it's not handled by the input method.
1059 if (delegate_
&& !key_event
.skip_in_browser
) {
1060 // We need to set |suppress_next_char_events_| to true if
1061 // PreHandleKeyboardEvent() returns true, but |this| may already be
1062 // destroyed at that time. So set |suppress_next_char_events_| true here,
1063 // then revert it afterwards when necessary.
1064 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1065 suppress_next_char_events_
= true;
1067 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1068 // a hung/malicious renderer from interfering.
1069 if (delegate_
->PreHandleKeyboardEvent(key_event
, &is_shortcut
))
1072 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1073 suppress_next_char_events_
= false;
1076 if (touch_emulator_
&& touch_emulator_
->HandleKeyboardEvent(key_event
))
1079 input_router_
->SendKeyboardEvent(
1081 CreateRWHLatencyInfoIfNotExist(NULL
, key_event
.type
),
1085 void RenderWidgetHostImpl::QueueSyntheticGesture(
1086 scoped_ptr
<SyntheticGesture
> synthetic_gesture
,
1087 const base::Callback
<void(SyntheticGesture::Result
)>& on_complete
) {
1088 if (!synthetic_gesture_controller_
&& view_
) {
1089 synthetic_gesture_controller_
.reset(
1090 new SyntheticGestureController(
1091 view_
->CreateSyntheticGestureTarget().Pass()));
1093 if (synthetic_gesture_controller_
) {
1094 synthetic_gesture_controller_
->QueueSyntheticGesture(
1095 synthetic_gesture
.Pass(), on_complete
);
1099 void RenderWidgetHostImpl::SetCursor(const WebCursor
& cursor
) {
1102 view_
->UpdateCursor(cursor
);
1105 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible
) {
1106 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible
));
1109 int64
RenderWidgetHostImpl::GetLatencyComponentId() {
1110 return GetRoutingID() | (static_cast<int64
>(GetProcess()->GetID()) << 32);
1114 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1115 g_check_for_pending_resize_ack
= false;
1118 ui::LatencyInfo
RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
1119 const ui::LatencyInfo
* original
, WebInputEvent::Type type
) {
1120 ui::LatencyInfo info
;
1123 // In Aura, gesture event will already carry its original touch event's
1124 // INPUT_EVENT_LATENCY_RWH_COMPONENT.
1125 if (!info
.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
,
1126 GetLatencyComponentId(),
1128 info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
,
1129 GetLatencyComponentId(),
1130 ++last_input_number_
);
1131 info
.TraceEventType(WebInputEventTraits::GetName(type
));
1137 void RenderWidgetHostImpl::AddKeyPressEventCallback(
1138 const KeyPressEventCallback
& callback
) {
1139 key_press_event_callbacks_
.push_back(callback
);
1142 void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
1143 const KeyPressEventCallback
& callback
) {
1144 for (size_t i
= 0; i
< key_press_event_callbacks_
.size(); ++i
) {
1145 if (key_press_event_callbacks_
[i
].Equals(callback
)) {
1146 key_press_event_callbacks_
.erase(
1147 key_press_event_callbacks_
.begin() + i
);
1153 void RenderWidgetHostImpl::AddMouseEventCallback(
1154 const MouseEventCallback
& callback
) {
1155 mouse_event_callbacks_
.push_back(callback
);
1158 void RenderWidgetHostImpl::RemoveMouseEventCallback(
1159 const MouseEventCallback
& callback
) {
1160 for (size_t i
= 0; i
< mouse_event_callbacks_
.size(); ++i
) {
1161 if (mouse_event_callbacks_
[i
].Equals(callback
)) {
1162 mouse_event_callbacks_
.erase(mouse_event_callbacks_
.begin() + i
);
1168 void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo
* result
) {
1169 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1171 view_
->GetScreenInfo(result
);
1173 RenderWidgetHostViewBase::GetDefaultScreenInfo(result
);
1174 screen_info_out_of_date_
= false;
1177 const NativeWebKeyboardEvent
*
1178 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1179 return input_router_
->GetLastKeyboardEvent();
1182 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1183 // The resize message (which may not happen immediately) will carry with it
1184 // the screen info as well as the new size (if the screen has changed scale
1186 InvalidateScreenInfo();
1190 void RenderWidgetHostImpl::InvalidateScreenInfo() {
1191 screen_info_out_of_date_
= true;
1192 screen_info_
.reset();
1195 void RenderWidgetHostImpl::OnSelectionChanged(const base::string16
& text
,
1197 const gfx::Range
& range
) {
1199 view_
->SelectionChanged(text
, offset
, range
);
1202 void RenderWidgetHostImpl::OnSelectionBoundsChanged(
1203 const ViewHostMsg_SelectionBounds_Params
& params
) {
1205 view_
->SelectionBoundsChanged(params
);
1209 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase
,
1210 base::TimeDelta interval
) {
1211 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase
, interval
));
1214 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status
,
1216 // Clearing this flag causes us to re-create the renderer when recovering
1217 // from a crashed renderer.
1218 renderer_initialized_
= false;
1220 waiting_for_screen_rects_ack_
= false;
1222 // Reset to ensure that input routing works with a new renderer.
1223 input_router_
.reset(new InputRouterImpl(
1224 process_
, this, this, routing_id_
, GetInputRouterConfigForPlatform()));
1226 if (overscroll_controller_
)
1227 overscroll_controller_
->Reset();
1229 // Must reset these to ensure that keyboard events work with a new renderer.
1230 suppress_next_char_events_
= false;
1232 // Reset some fields in preparation for recovering from a crash.
1233 ResetSizeAndRepaintPendingFlags();
1234 current_size_
.SetSize(0, 0);
1236 is_accelerated_compositing_active_
= false;
1238 // Reset this to ensure the hung renderer mechanism is working properly.
1239 in_flight_event_count_
= 0;
1242 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_
,
1243 gfx::GLSurfaceHandle());
1244 view_
->RenderProcessGone(status
, exit_code
);
1245 view_
= NULL
; // The View should be deleted by RenderProcessGone.
1248 synthetic_gesture_controller_
.reset();
1251 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction
) {
1252 text_direction_updated_
= true;
1253 text_direction_
= direction
;
1256 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1257 if (text_direction_updated_
)
1258 text_direction_canceled_
= true;
1261 void RenderWidgetHostImpl::NotifyTextDirection() {
1262 if (text_direction_updated_
) {
1263 if (!text_direction_canceled_
)
1264 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_
));
1265 text_direction_updated_
= false;
1266 text_direction_canceled_
= false;
1270 void RenderWidgetHostImpl::SetInputMethodActive(bool activate
) {
1271 input_method_active_
= activate
;
1272 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate
));
1275 void RenderWidgetHostImpl::CandidateWindowShown() {
1276 Send(new ViewMsg_CandidateWindowShown(GetRoutingID()));
1279 void RenderWidgetHostImpl::CandidateWindowUpdated() {
1280 Send(new ViewMsg_CandidateWindowUpdated(GetRoutingID()));
1283 void RenderWidgetHostImpl::CandidateWindowHidden() {
1284 Send(new ViewMsg_CandidateWindowHidden(GetRoutingID()));
1287 void RenderWidgetHostImpl::ImeSetComposition(
1288 const base::string16
& text
,
1289 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
1290 int selection_start
,
1291 int selection_end
) {
1292 Send(new ViewMsg_ImeSetComposition(
1293 GetRoutingID(), text
, underlines
, selection_start
, selection_end
));
1296 void RenderWidgetHostImpl::ImeConfirmComposition(
1297 const base::string16
& text
,
1298 const gfx::Range
& replacement_range
,
1299 bool keep_selection
) {
1300 Send(new ViewMsg_ImeConfirmComposition(
1301 GetRoutingID(), text
, replacement_range
, keep_selection
));
1304 void RenderWidgetHostImpl::ImeCancelComposition() {
1305 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(),
1306 std::vector
<blink::WebCompositionUnderline
>(), 0, 0));
1309 gfx::Rect
RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1313 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture
,
1314 bool last_unlocked_by_target
) {
1315 // Directly reject to lock the mouse. Subclass can override this method to
1316 // decide whether to allow mouse lock or not.
1317 GotResponseToLockMouseRequest(false);
1320 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1321 DCHECK(!pending_mouse_lock_request_
|| !IsMouseLocked());
1322 if (pending_mouse_lock_request_
) {
1323 pending_mouse_lock_request_
= false;
1324 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
1325 } else if (IsMouseLocked()) {
1326 view_
->UnlockMouse();
1330 bool RenderWidgetHostImpl::IsMouseLocked() const {
1331 return view_
? view_
->IsMouseLocked() : false;
1334 bool RenderWidgetHostImpl::IsFullscreen() const {
1338 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable
) {
1339 should_auto_resize_
= enable
;
1342 void RenderWidgetHostImpl::Destroy() {
1343 NotificationService::current()->Notify(
1344 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1345 Source
<RenderWidgetHost
>(this),
1346 NotificationService::NoDetails());
1348 // Tell the view to die.
1349 // Note that in the process of the view shutting down, it can call a ton
1350 // of other messages on us. So if you do any other deinitialization here,
1351 // do it after this call to view_->Destroy().
1358 void RenderWidgetHostImpl::RendererIsUnresponsive() {
1359 NotificationService::current()->Notify(
1360 NOTIFICATION_RENDER_WIDGET_HOST_HANG
,
1361 Source
<RenderWidgetHost
>(this),
1362 NotificationService::NoDetails());
1363 is_unresponsive_
= true;
1364 NotifyRendererUnresponsive();
1367 void RenderWidgetHostImpl::RendererIsResponsive() {
1368 if (is_unresponsive_
) {
1369 is_unresponsive_
= false;
1370 NotifyRendererResponsive();
1374 void RenderWidgetHostImpl::OnRenderViewReady() {
1379 void RenderWidgetHostImpl::OnRenderProcessGone(int status
, int exit_code
) {
1380 // TODO(evanm): This synchronously ends up calling "delete this".
1381 // Is that really what we want in response to this message? I'm matching
1382 // previous behavior of the code here.
1386 void RenderWidgetHostImpl::OnClose() {
1390 void RenderWidgetHostImpl::OnSetTooltipText(
1391 const base::string16
& tooltip_text
,
1392 WebTextDirection text_direction_hint
) {
1393 // First, add directionality marks around tooltip text if necessary.
1394 // A naive solution would be to simply always wrap the text. However, on
1395 // windows, Unicode directional embedding characters can't be displayed on
1396 // systems that lack RTL fonts and are instead displayed as empty squares.
1398 // To get around this we only wrap the string when we deem it necessary i.e.
1399 // when the locale direction is different than the tooltip direction hint.
1401 // Currently, we use element's directionality as the tooltip direction hint.
1402 // An alternate solution would be to set the overall directionality based on
1403 // trying to detect the directionality from the tooltip text rather than the
1404 // element direction. One could argue that would be a preferable solution
1405 // but we use the current approach to match Fx & IE's behavior.
1406 base::string16 wrapped_tooltip_text
= tooltip_text
;
1407 if (!tooltip_text
.empty()) {
1408 if (text_direction_hint
== blink::WebTextDirectionLeftToRight
) {
1409 // Force the tooltip to have LTR directionality.
1410 wrapped_tooltip_text
=
1411 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text
);
1412 } else if (text_direction_hint
== blink::WebTextDirectionRightToLeft
&&
1413 !base::i18n::IsRTL()) {
1414 // Force the tooltip to have RTL directionality.
1415 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text
);
1419 view_
->SetTooltipText(wrapped_tooltip_text
);
1422 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1423 waiting_for_screen_rects_ack_
= false;
1427 if (view_
->GetViewBounds() == last_view_screen_rect_
&&
1428 view_
->GetBoundsInRootWindow() == last_window_screen_rect_
) {
1435 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect
& pos
) {
1437 view_
->SetBounds(pos
);
1438 Send(new ViewMsg_Move_ACK(routing_id_
));
1442 #if defined(OS_MACOSX)
1443 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1444 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params
& params
) {
1445 // This trace event is used in
1446 // chrome/browser/extensions/api/cast_streaming/performance_test.cc
1447 TRACE_EVENT0("renderer_host",
1448 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1449 // This trace event is used in
1450 // chrome/browser/extensions/api/cast_streaming/performance_test.cc
1451 UNSHIPPED_TRACE_EVENT0("test_fps",
1452 TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame"));
1453 if (!ui::LatencyInfo::Verify(params
.latency_info
,
1454 "ViewHostMsg_CompositorSurfaceBuffersSwapped"))
1457 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
1458 ack_params
.sync_point
= 0;
1459 RenderWidgetHostImpl::AcknowledgeBufferPresent(params
.route_id
,
1460 params
.gpu_process_host_id
,
1464 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params
;
1465 gpu_params
.surface_id
= params
.surface_id
;
1466 gpu_params
.surface_handle
= params
.surface_handle
;
1467 gpu_params
.route_id
= params
.route_id
;
1468 gpu_params
.size
= params
.size
;
1469 gpu_params
.scale_factor
= params
.scale_factor
;
1470 gpu_params
.latency_info
= params
.latency_info
;
1471 for (size_t i
= 0; i
< gpu_params
.latency_info
.size(); i
++)
1472 AddLatencyInfoComponentIds(&gpu_params
.latency_info
[i
]);
1473 view_
->AcceleratedSurfaceBuffersSwapped(gpu_params
,
1474 params
.gpu_process_host_id
);
1475 view_
->DidReceiveRendererFrame();
1479 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1480 const IPC::Message
& message
) {
1481 // This trace event is used in
1482 // chrome/browser/extensions/api/cast_streaming/performance_test.cc
1483 UNSHIPPED_TRACE_EVENT0("test_fps",
1484 TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame"));
1485 ViewHostMsg_SwapCompositorFrame::Param param
;
1486 if (!ViewHostMsg_SwapCompositorFrame::Read(&message
, ¶m
))
1488 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
1489 uint32 output_surface_id
= param
.a
;
1490 param
.b
.AssignTo(frame
.get());
1492 for (size_t i
= 0; i
< frame
->metadata
.latency_info
.size(); i
++)
1493 AddLatencyInfoComponentIds(&frame
->metadata
.latency_info
[i
]);
1495 input_router_
->OnViewUpdated(
1496 GetInputRouterViewFlagsFromCompositorFrameMetadata(frame
->metadata
));
1499 view_
->OnSwapCompositorFrame(output_surface_id
, frame
.Pass());
1500 view_
->DidReceiveRendererFrame();
1502 cc::CompositorFrameAck ack
;
1503 if (frame
->gl_frame_data
) {
1504 ack
.gl_frame_data
= frame
->gl_frame_data
.Pass();
1505 ack
.gl_frame_data
->sync_point
= 0;
1506 } else if (frame
->delegated_frame_data
) {
1507 cc::TransferableResource::ReturnResources(
1508 frame
->delegated_frame_data
->resource_list
,
1510 } else if (frame
->software_frame_data
) {
1511 ack
.last_software_frame_id
= frame
->software_frame_data
->id
;
1513 SendSwapCompositorFrameAck(routing_id_
, output_surface_id
,
1514 process_
->GetID(), ack
);
1519 void RenderWidgetHostImpl::OnFlingingStopped() {
1521 view_
->DidStopFlinging();
1524 void RenderWidgetHostImpl::OnUpdateRect(
1525 const ViewHostMsg_UpdateRect_Params
& params
) {
1526 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1527 TimeTicks paint_start
= TimeTicks::Now();
1529 // Update our knowledge of the RenderWidget's size.
1530 current_size_
= params
.view_size
;
1531 // Update our knowledge of the RenderWidget's scroll offset.
1532 last_scroll_offset_
= params
.scroll_offset
;
1534 bool is_resize_ack
=
1535 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1537 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1538 // that will end up reaching GetBackingStore.
1539 if (is_resize_ack
) {
1540 DCHECK(!g_check_for_pending_resize_ack
|| resize_ack_pending_
);
1541 resize_ack_pending_
= false;
1544 bool is_repaint_ack
=
1545 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params
.flags
);
1546 if (is_repaint_ack
) {
1547 DCHECK(repaint_ack_pending_
);
1548 TRACE_EVENT_ASYNC_END0(
1549 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1550 repaint_ack_pending_
= false;
1551 TimeDelta delta
= TimeTicks::Now() - repaint_start_time_
;
1552 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta
);
1555 DCHECK(!params
.view_size
.IsEmpty());
1557 DidUpdateBackingStore(params
, paint_start
);
1559 if (should_auto_resize_
) {
1560 bool post_callback
= new_auto_size_
.IsEmpty();
1561 new_auto_size_
= params
.view_size
;
1562 if (post_callback
) {
1563 base::MessageLoop::current()->PostTask(
1565 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized
,
1566 weak_factory_
.GetWeakPtr()));
1570 // Log the time delta for processing a paint message. On platforms that don't
1571 // support asynchronous painting, this is equivalent to
1572 // MPArch.RWH_TotalPaintTime.
1573 TimeDelta delta
= TimeTicks::Now() - paint_start
;
1574 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta
);
1577 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1578 if (in_get_backing_store_
)
1579 abort_get_backing_store_
= true;
1582 void RenderWidgetHostImpl::DidUpdateBackingStore(
1583 const ViewHostMsg_UpdateRect_Params
& params
,
1584 const TimeTicks
& paint_start
) {
1585 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1586 TimeTicks update_start
= TimeTicks::Now();
1588 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1589 // will not be re-issued, so must move them now, regardless of whether we
1590 // paint or not. MovePluginWindows attempts to move the plugin windows and
1591 // in the process could dispatch other window messages which could cause the
1592 // view to be destroyed.
1594 view_
->MovePluginWindows(params
.plugin_window_moves
);
1596 NotificationService::current()->Notify(
1597 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE
,
1598 Source
<RenderWidgetHost
>(this),
1599 NotificationService::NoDetails());
1601 // We don't need to update the view if the view is hidden. We must do this
1602 // early return after the ACK is sent, however, or the renderer will not send
1607 // If we got a resize ack, then perhaps we have another resize to send?
1608 bool is_resize_ack
=
1609 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1613 // Log the time delta for processing a paint message.
1614 TimeTicks now
= TimeTicks::Now();
1615 TimeDelta delta
= now
- update_start
;
1616 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta
);
1619 void RenderWidgetHostImpl::OnQueueSyntheticGesture(
1620 const SyntheticGesturePacket
& gesture_packet
) {
1621 // Only allow untrustworthy gestures if explicitly enabled.
1622 if (!CommandLine::ForCurrentProcess()->HasSwitch(
1623 cc::switches::kEnableGpuBenchmarking
)) {
1624 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH7"));
1625 GetProcess()->ReceivedBadMessage();
1629 QueueSyntheticGesture(
1630 SyntheticGesture::Create(*gesture_packet
.gesture_params()),
1631 base::Bind(&RenderWidgetHostImpl::OnSyntheticGestureCompleted
,
1632 weak_factory_
.GetWeakPtr()));
1635 void RenderWidgetHostImpl::OnFocus() {
1636 // Only RenderViewHost can deal with that message.
1637 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH4"));
1638 GetProcess()->ReceivedBadMessage();
1641 void RenderWidgetHostImpl::OnBlur() {
1642 // Only RenderViewHost can deal with that message.
1643 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH5"));
1644 GetProcess()->ReceivedBadMessage();
1647 void RenderWidgetHostImpl::OnSetCursor(const WebCursor
& cursor
) {
1651 void RenderWidgetHostImpl::OnSetTouchEventEmulationEnabled(
1652 bool enabled
, bool allow_pinch
) {
1654 if (!touch_emulator_
)
1655 touch_emulator_
.reset(new TouchEmulator(this));
1656 touch_emulator_
->Enable(allow_pinch
);
1658 if (touch_emulator_
)
1659 touch_emulator_
->Disable();
1663 void RenderWidgetHostImpl::OnTextInputTypeChanged(
1664 ui::TextInputType type
,
1665 ui::TextInputMode input_mode
,
1666 bool can_compose_inline
) {
1668 view_
->TextInputTypeChanged(type
, input_mode
, can_compose_inline
);
1671 #if defined(OS_MACOSX) || defined(USE_AURA)
1672 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
1673 const gfx::Range
& range
,
1674 const std::vector
<gfx::Rect
>& character_bounds
) {
1676 view_
->ImeCompositionRangeChanged(range
, character_bounds
);
1680 void RenderWidgetHostImpl::OnImeCancelComposition() {
1682 view_
->ImeCancelComposition();
1685 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated
) {
1686 TRACE_EVENT1("renderer_host",
1687 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
1688 "activated", activated
);
1689 is_accelerated_compositing_active_
= activated
;
1691 view_
->OnAcceleratedCompositingStateChange();
1694 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture
,
1695 bool last_unlocked_by_target
,
1698 if (pending_mouse_lock_request_
) {
1699 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
1701 } else if (IsMouseLocked()) {
1702 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
1706 pending_mouse_lock_request_
= true;
1707 if (privileged
&& allow_privileged_mouse_lock_
) {
1708 // Directly approve to lock the mouse.
1709 GotResponseToLockMouseRequest(true);
1711 RequestToLockMouse(user_gesture
, last_unlocked_by_target
);
1715 void RenderWidgetHostImpl::OnUnlockMouse() {
1716 RejectMouseLockOrUnlockIfNecessary();
1719 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
1720 const gfx::Rect
& rect
,
1721 const gfx::Size
& size
,
1722 const cc::SharedBitmapId
& id
) {
1723 DCHECK(!rect
.IsEmpty());
1724 DCHECK(!size
.IsEmpty());
1726 scoped_ptr
<cc::SharedBitmap
> bitmap
=
1727 HostSharedBitmapManager::current()->GetSharedBitmapFromId(size
, id
);
1729 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH6"));
1730 GetProcess()->ReceivedBadMessage();
1734 DCHECK(bitmap
->pixels());
1736 SkBitmap zoomed_bitmap
;
1737 zoomed_bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
1738 size
.width(), size
.height());
1739 zoomed_bitmap
.setPixels(bitmap
->pixels());
1741 #if defined(OS_ANDROID)
1743 view_
->ShowDisambiguationPopup(rect
, zoomed_bitmap
);
1748 zoomed_bitmap
.setPixels(0);
1749 Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id
));
1753 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
1754 gfx::NativeViewId dummy_activation_window
) {
1755 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
1757 // This may happen as a result of a race condition when the plugin is going
1759 wchar_t window_title
[MAX_PATH
+ 1] = {0};
1760 if (!IsWindow(hwnd
) ||
1761 !GetWindowText(hwnd
, window_title
, arraysize(window_title
)) ||
1762 lstrcmpiW(window_title
, kDummyActivationWindowName
) != 0) {
1766 #if defined(USE_AURA)
1768 reinterpret_cast<HWND
>(view_
->GetParentForWindowlessPlugin()));
1770 SetParent(hwnd
, reinterpret_cast<HWND
>(GetNativeViewId()));
1772 dummy_windows_for_activation_
.push_back(hwnd
);
1775 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
1776 gfx::NativeViewId dummy_activation_window
) {
1777 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
1778 std::list
<HWND
>::iterator i
= dummy_windows_for_activation_
.begin();
1779 for (; i
!= dummy_windows_for_activation_
.end(); ++i
) {
1781 dummy_windows_for_activation_
.erase(i
);
1785 NOTREACHED() << "Unknown dummy window";
1789 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events
) {
1790 ignore_input_events_
= ignore_input_events
;
1793 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
1794 const NativeWebKeyboardEvent
& event
) {
1795 if (event
.skip_in_browser
|| event
.type
!= WebKeyboardEvent::RawKeyDown
)
1798 for (size_t i
= 0; i
< key_press_event_callbacks_
.size(); i
++) {
1799 size_t original_size
= key_press_event_callbacks_
.size();
1800 if (key_press_event_callbacks_
[i
].Run(event
))
1803 // Check whether the callback that just ran removed itself, in which case
1804 // the iterator needs to be decremented to properly account for the removal.
1805 size_t current_size
= key_press_event_callbacks_
.size();
1806 if (current_size
!= original_size
) {
1807 DCHECK_EQ(original_size
- 1, current_size
);
1815 InputEventAckState
RenderWidgetHostImpl::FilterInputEvent(
1816 const blink::WebInputEvent
& event
, const ui::LatencyInfo
& latency_info
) {
1817 // Don't ignore touch cancel events, since they may be sent while input
1818 // events are being ignored in order to keep the renderer from getting
1819 // confused about how many touches are active.
1820 if (IgnoreInputEvents() && event
.type
!= WebInputEvent::TouchCancel
)
1821 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
;
1823 if (!process_
->HasConnection())
1824 return INPUT_EVENT_ACK_STATE_UNKNOWN
;
1826 if (event
.type
== WebInputEvent::MouseDown
)
1829 return view_
? view_
->FilterInputEvent(event
)
1830 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
1833 void RenderWidgetHostImpl::IncrementInFlightEventCount() {
1834 StartHangMonitorTimeout(
1835 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
1836 increment_in_flight_event_count();
1839 void RenderWidgetHostImpl::DecrementInFlightEventCount() {
1840 DCHECK(in_flight_event_count_
>= 0);
1841 // Cancel pending hung renderer checks since the renderer is responsive.
1842 if (decrement_in_flight_event_count() <= 0)
1843 StopHangMonitorTimeout();
1846 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers
) {
1847 has_touch_handler_
= has_handlers
;
1850 OverscrollController
* RenderWidgetHostImpl::GetOverscrollController() const {
1851 return overscroll_controller_
.get();
1854 void RenderWidgetHostImpl::DidFlush() {
1855 if (synthetic_gesture_controller_
)
1856 synthetic_gesture_controller_
->OnDidFlushInput();
1858 view_
->OnDidFlushInput();
1861 void RenderWidgetHostImpl::OnKeyboardEventAck(
1862 const NativeWebKeyboardEvent
& event
,
1863 InputEventAckState ack_result
) {
1864 #if defined(OS_MACOSX)
1865 if (!is_hidden() && view_
&& view_
->PostProcessEventForPluginIme(event
))
1869 // We only send unprocessed key event upwards if we are not hidden,
1870 // because the user has moved away from us and no longer expect any effect
1871 // of this key event.
1872 const bool processed
= (INPUT_EVENT_ACK_STATE_CONSUMED
== ack_result
);
1873 if (delegate_
&& !processed
&& !is_hidden() && !event
.skip_in_browser
) {
1874 delegate_
->HandleKeyboardEvent(event
);
1876 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
1877 // (i.e. in the case of Ctrl+W, where the call to
1878 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
1882 void RenderWidgetHostImpl::OnWheelEventAck(
1883 const MouseWheelEventWithLatencyInfo
& wheel_event
,
1884 InputEventAckState ack_result
) {
1885 if (!wheel_event
.latency
.FindLatency(
1886 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT
, 0, NULL
)) {
1887 // MouseWheelEvent latency ends when it is acked but does not cause any
1888 // rendering scheduled.
1889 ui::LatencyInfo latency
= wheel_event
.latency
;
1890 latency
.AddLatencyNumber(
1891 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT
, 0, 0);
1894 const bool processed
= (INPUT_EVENT_ACK_STATE_CONSUMED
== ack_result
);
1895 if (!processed
&& !is_hidden() && view_
) {
1896 if (!delegate_
->HandleWheelEvent(wheel_event
.event
))
1897 view_
->UnhandledWheelEvent(wheel_event
.event
);
1901 void RenderWidgetHostImpl::OnGestureEventAck(
1902 const GestureEventWithLatencyInfo
& event
,
1903 InputEventAckState ack_result
) {
1904 if (!event
.latency
.FindLatency(
1905 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT
, 0, NULL
)) {
1906 // GestureEvent latency ends when it is acked but does not cause any
1907 // rendering scheduled.
1908 ui::LatencyInfo latency
= event
.latency
;
1909 latency
.AddLatencyNumber(
1910 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT
, 0 ,0);
1913 if (ack_result
!= INPUT_EVENT_ACK_STATE_CONSUMED
) {
1914 if (delegate_
->HandleGestureEvent(event
.event
))
1915 ack_result
= INPUT_EVENT_ACK_STATE_CONSUMED
;
1919 view_
->GestureEventAck(event
.event
, ack_result
);
1922 void RenderWidgetHostImpl::OnTouchEventAck(
1923 const TouchEventWithLatencyInfo
& event
,
1924 InputEventAckState ack_result
) {
1925 TouchEventWithLatencyInfo touch_event
= event
;
1926 touch_event
.latency
.AddLatencyNumber(
1927 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT
, 0, 0);
1928 // TouchEvent latency ends at ack if it didn't cause any rendering.
1929 if (!touch_event
.latency
.FindLatency(
1930 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT
, 0, NULL
)) {
1931 touch_event
.latency
.AddLatencyNumber(
1932 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT
, 0, 0);
1934 ComputeTouchLatency(touch_event
.latency
);
1936 if (touch_emulator_
&& touch_emulator_
->HandleTouchEventAck(ack_result
))
1940 view_
->ProcessAckedTouchEvent(touch_event
, ack_result
);
1943 void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type
) {
1944 if (type
== BAD_ACK_MESSAGE
) {
1945 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH2"));
1946 process_
->ReceivedBadMessage();
1947 } else if (type
== UNEXPECTED_EVENT_TYPE
) {
1948 suppress_next_char_events_
= false;
1952 void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
1953 SyntheticGesture::Result result
) {
1954 Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
1957 const gfx::Vector2d
& RenderWidgetHostImpl::GetLastScrollOffset() const {
1958 return last_scroll_offset_
;
1961 bool RenderWidgetHostImpl::IgnoreInputEvents() const {
1962 return ignore_input_events_
|| process_
->IgnoreInputEvents();
1965 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
1966 return input_router_
->ShouldForwardTouchEvent();
1969 void RenderWidgetHostImpl::StartUserGesture() {
1973 void RenderWidgetHostImpl::Stop() {
1974 Send(new ViewMsg_Stop(GetRoutingID()));
1977 void RenderWidgetHostImpl::SetBackground(const SkBitmap
& background
) {
1978 Send(new ViewMsg_SetBackground(GetRoutingID(), background
));
1981 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
1982 const std::vector
<EditCommand
>& commands
) {
1983 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands
));
1986 void RenderWidgetHostImpl::AddAccessibilityMode(AccessibilityMode mode
) {
1987 SetAccessibilityMode(
1988 content::AddAccessibilityModeTo(accessibility_mode_
, mode
));
1991 void RenderWidgetHostImpl::RemoveAccessibilityMode(AccessibilityMode mode
) {
1992 SetAccessibilityMode(
1993 content::RemoveAccessibilityModeFrom(accessibility_mode_
, mode
));
1996 void RenderWidgetHostImpl::ResetAccessibilityMode() {
1997 SetAccessibilityMode(
1998 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
2001 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode
) {
2002 accessibility_mode_
= mode
;
2003 Send(new ViewMsg_SetAccessibilityMode(GetRoutingID(), mode
));
2006 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id
) {
2007 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id
));
2008 view_
->OnAccessibilitySetFocus(object_id
);
2011 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id
) {
2012 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id
));
2015 void RenderWidgetHostImpl::AccessibilityShowMenu(int object_id
) {
2016 view_
->AccessibilityShowMenu(object_id
);
2019 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2020 int acc_obj_id
, gfx::Rect subfocus
) {
2021 Send(new AccessibilityMsg_ScrollToMakeVisible(
2022 GetRoutingID(), acc_obj_id
, subfocus
));
2025 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2026 int acc_obj_id
, gfx::Point point
) {
2027 Send(new AccessibilityMsg_ScrollToPoint(
2028 GetRoutingID(), acc_obj_id
, point
));
2031 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2032 int object_id
, int start_offset
, int end_offset
) {
2033 Send(new AccessibilityMsg_SetTextSelection(
2034 GetRoutingID(), object_id
, start_offset
, end_offset
));
2037 bool RenderWidgetHostImpl::AccessibilityViewHasFocus() const {
2038 return view_
->HasFocus();
2041 gfx::Rect
RenderWidgetHostImpl::AccessibilityGetViewBounds() const {
2042 return view_
->GetViewBounds();
2045 gfx::Point
RenderWidgetHostImpl::AccessibilityOriginInScreen(
2046 const gfx::Rect
& bounds
) const {
2047 return view_
->AccessibilityOriginInScreen(bounds
);
2050 void RenderWidgetHostImpl::AccessibilityFatalError() {
2051 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2052 view_
->SetBrowserAccessibilityManager(NULL
);
2056 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2057 gfx::NativeViewAccessible accessible_parent
) {
2059 view_
->SetParentNativeViewAccessible(accessible_parent
);
2062 gfx::NativeViewAccessible
2063 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2064 return delegate_
->GetParentNativeViewAccessible();
2068 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string
& command
,
2069 const std::string
& value
) {
2070 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command
, value
));
2073 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2074 const gfx::Rect
& rect
) {
2075 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect
));
2078 void RenderWidgetHostImpl::MoveCaret(const gfx::Point
& point
) {
2079 Send(new InputMsg_MoveCaret(GetRoutingID(), point
));
2082 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed
) {
2084 RejectMouseLockOrUnlockIfNecessary();
2087 if (!pending_mouse_lock_request_
) {
2088 // This is possible, e.g., the plugin sends us an unlock request before
2089 // the user allows to lock to mouse.
2093 pending_mouse_lock_request_
= false;
2094 if (!view_
|| !view_
->HasFocus()|| !view_
->LockMouse()) {
2095 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
2098 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
2105 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2106 int32 route_id
, int gpu_host_id
,
2107 const AcceleratedSurfaceMsg_BufferPresented_Params
& params
) {
2108 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(gpu_host_id
);
2110 ui_shim
->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id
,
2116 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2118 uint32 output_surface_id
,
2119 int renderer_host_id
,
2120 const cc::CompositorFrameAck
& ack
) {
2121 RenderProcessHost
* host
= RenderProcessHost::FromID(renderer_host_id
);
2124 host
->Send(new ViewMsg_SwapCompositorFrameAck(
2125 route_id
, output_surface_id
, ack
));
2129 void RenderWidgetHostImpl::SendReclaimCompositorResources(
2131 uint32 output_surface_id
,
2132 int renderer_host_id
,
2133 const cc::CompositorFrameAck
& ack
) {
2134 RenderProcessHost
* host
= RenderProcessHost::FromID(renderer_host_id
);
2138 new ViewMsg_ReclaimCompositorResources(route_id
, output_surface_id
, ack
));
2141 void RenderWidgetHostImpl::DelayedAutoResized() {
2142 gfx::Size new_size
= new_auto_size_
;
2143 // Clear the new_auto_size_ since the empty value is used as a flag to
2144 // indicate that no callback is in progress (i.e. without this line
2145 // DelayedAutoResized will not get called again).
2146 new_auto_size_
.SetSize(0, 0);
2147 if (!should_auto_resize_
)
2150 OnRenderAutoResized(new_size
);
2153 void RenderWidgetHostImpl::DetachDelegate() {
2157 void RenderWidgetHostImpl::ComputeTouchLatency(
2158 const ui::LatencyInfo
& latency_info
) {
2159 ui::LatencyInfo::LatencyComponent ui_component
;
2160 ui::LatencyInfo::LatencyComponent rwh_component
;
2161 ui::LatencyInfo::LatencyComponent acked_component
;
2163 if (!latency_info
.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT
,
2166 !latency_info
.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
,
2167 GetLatencyComponentId(),
2171 DCHECK(ui_component
.event_count
== 1);
2172 DCHECK(rwh_component
.event_count
== 1);
2174 base::TimeDelta ui_delta
=
2175 rwh_component
.event_time
- ui_component
.event_time
;
2176 UMA_HISTOGRAM_CUSTOM_COUNTS(
2177 "Event.Latency.Browser.TouchUI",
2178 ui_delta
.InMicroseconds(),
2183 if (latency_info
.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT
,
2185 &acked_component
)) {
2186 DCHECK(acked_component
.event_count
== 1);
2187 base::TimeDelta acked_delta
=
2188 acked_component
.event_time
- rwh_component
.event_time
;
2189 UMA_HISTOGRAM_CUSTOM_COUNTS(
2190 "Event.Latency.Browser.TouchAcked",
2191 acked_delta
.InMicroseconds(),
2198 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo
& latency_info
) {
2199 ui::LatencyInfo::LatencyComponent window_snapshot_component
;
2200 if (latency_info
.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT
,
2201 GetLatencyComponentId(),
2202 &window_snapshot_component
)) {
2203 WindowSnapshotReachedScreen(
2204 static_cast<int>(window_snapshot_component
.sequence_number
));
2207 ui::LatencyInfo::LatencyComponent rwh_component
;
2208 ui::LatencyInfo::LatencyComponent swap_component
;
2209 if (!latency_info
.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
,
2210 GetLatencyComponentId(),
2212 !latency_info
.FindLatency(
2213 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT
,
2214 0, &swap_component
)) {
2218 ui::LatencyInfo::LatencyComponent original_component
;
2219 if (latency_info
.FindLatency(
2220 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT
,
2221 GetLatencyComponentId(),
2222 &original_component
)) {
2223 // This UMA metric tracks the time from when the original touch event is
2224 // created (averaged if there are multiple) to when the scroll gesture
2225 // results in final frame swap.
2226 base::TimeDelta delta
=
2227 swap_component
.event_time
- original_component
.event_time
;
2228 for (size_t i
= 0; i
< original_component
.event_count
; i
++) {
2229 UMA_HISTOGRAM_CUSTOM_COUNTS(
2230 "Event.Latency.TouchToScrollUpdateSwap",
2231 delta
.InMicroseconds(),
2239 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
2240 view_
->DidReceiveRendererFrame();
2243 void RenderWidgetHostImpl::WindowSnapshotAsyncCallback(
2246 gfx::Size snapshot_size
,
2247 scoped_refptr
<base::RefCountedBytes
> png_data
) {
2249 std::vector
<unsigned char> png_vector
;
2250 Send(new ViewMsg_WindowSnapshotCompleted(
2251 routing_id
, snapshot_id
, gfx::Size(), png_vector
));
2255 Send(new ViewMsg_WindowSnapshotCompleted(
2256 routing_id
, snapshot_id
, snapshot_size
, png_data
->data()));
2259 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id
) {
2260 DCHECK(base::MessageLoopForUI::IsCurrent());
2262 std::vector
<unsigned char> png
;
2264 // This feature is behind the kEnableGpuBenchmarking command line switch
2265 // because it poses security concerns and should only be used for testing.
2266 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
2267 if (!command_line
.HasSwitch(cc::switches::kEnableGpuBenchmarking
)) {
2268 Send(new ViewMsg_WindowSnapshotCompleted(
2269 GetRoutingID(), snapshot_id
, gfx::Size(), png
));
2273 gfx::Rect view_bounds
= GetView()->GetViewBounds();
2274 gfx::Rect
snapshot_bounds(view_bounds
.size());
2275 gfx::Size snapshot_size
= snapshot_bounds
.size();
2277 if (ui::GrabViewSnapshot(
2278 GetView()->GetNativeView(), &png
, snapshot_bounds
)) {
2279 Send(new ViewMsg_WindowSnapshotCompleted(
2280 GetRoutingID(), snapshot_id
, snapshot_size
, png
));
2284 ui::GrabViewSnapshotAsync(
2285 GetView()->GetNativeView(),
2287 base::ThreadTaskRunnerHandle::Get(),
2288 base::Bind(&RenderWidgetHostImpl::WindowSnapshotAsyncCallback
,
2289 weak_factory_
.GetWeakPtr(),
2296 void RenderWidgetHostImpl::CompositorFrameDrawn(
2297 const std::vector
<ui::LatencyInfo
>& latency_info
) {
2298 for (size_t i
= 0; i
< latency_info
.size(); i
++) {
2299 std::set
<RenderWidgetHostImpl
*> rwhi_set
;
2300 for (ui::LatencyInfo::LatencyMap::const_iterator b
=
2301 latency_info
[i
].latency_components
.begin();
2302 b
!= latency_info
[i
].latency_components
.end();
2304 if (b
->first
.first
== ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
||
2305 b
->first
.first
== ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT
) {
2306 // Matches with GetLatencyComponentId
2307 int routing_id
= b
->first
.second
& 0xffffffff;
2308 int process_id
= (b
->first
.second
>> 32) & 0xffffffff;
2309 RenderWidgetHost
* rwh
=
2310 RenderWidgetHost::FromID(process_id
, routing_id
);
2314 RenderWidgetHostImpl
* rwhi
= RenderWidgetHostImpl::From(rwh
);
2315 if (rwhi_set
.insert(rwhi
).second
)
2316 rwhi
->FrameSwapped(latency_info
[i
]);
2322 void RenderWidgetHostImpl::AddLatencyInfoComponentIds(
2323 ui::LatencyInfo
* latency_info
) {
2324 ui::LatencyInfo::LatencyMap new_components
;
2325 ui::LatencyInfo::LatencyMap::iterator lc
=
2326 latency_info
->latency_components
.begin();
2327 while (lc
!= latency_info
->latency_components
.end()) {
2328 ui::LatencyComponentType component_type
= lc
->first
.first
;
2329 if (component_type
== ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT
) {
2330 // Generate a new component entry with the correct component ID
2331 ui::LatencyInfo::LatencyMap::key_type key
=
2332 std::make_pair(component_type
, GetLatencyComponentId());
2333 new_components
[key
] = lc
->second
;
2335 // Remove the old entry
2336 latency_info
->latency_components
.erase(lc
++);
2342 // Add newly generated components into the latency info
2343 for (lc
= new_components
.begin(); lc
!= new_components
.end(); ++lc
) {
2344 latency_info
->latency_components
[lc
->first
] = lc
->second
;
2348 SkBitmap::Config
RenderWidgetHostImpl::PreferredReadbackFormat() {
2350 return view_
->PreferredReadbackFormat();
2351 return SkBitmap::kARGB_8888_Config
;
2354 } // namespace content