Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_impl.cc
blobf01a2e75e141b978c5d83a2f8d135a895ba2ba98
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"
7 #include <math.h>
8 #include <set>
9 #include <utility>
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"
73 #if defined(OS_WIN)
74 #include "content/common/plugin_constants_win.h"
75 #endif
77 using base::Time;
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;
87 namespace content {
88 namespace {
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*>
100 RoutingIDWidgetMap;
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;
117 return view_flags;
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 {
124 public:
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);
143 ++current_index_;
145 return host;
148 private:
149 std::vector<RenderWidgetHostID> hosts_;
150 size_t current_index_;
152 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
155 } // namespace
157 ///////////////////////////////////////////////////////////////////////////////
158 // RenderWidgetHostImpl
160 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
161 RenderProcessHost* process,
162 int routing_id,
163 bool hidden)
164 : view_(NULL),
165 renderer_initialized_(false),
166 hung_renderer_delay_ms_(kHungRendererDelayMs),
167 delegate_(delegate),
168 process_(process),
169 routing_id_(routing_id),
170 surface_id_(0),
171 is_loading_(false),
172 is_hidden_(hidden),
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),
197 weak_factory_(this),
198 last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32) {
199 CHECK(delegate_);
200 if (routing_id_ == MSG_ROUTING_NONE) {
201 routing_id_ = process_->GetNextRoutingID();
202 surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
203 process_->GetID(),
204 routing_id_);
205 } else {
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(
214 process_->GetID(),
215 routing_id_);
216 DCHECK(surface_id_);
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.
227 if (!hidden)
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);
242 #endif
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() {
253 SetView(NULL);
255 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
256 surface_id_ = 0;
258 process_->RemoveRoute(routing_id_);
259 g_routing_id_widget_map.Get().erase(
260 RenderWidgetHostID(process_->GetID(), routing_id_));
262 if (delegate_)
263 delegate_->RenderWidgetDeleted(this);
266 // static
267 RenderWidgetHost* RenderWidgetHost::FromID(
268 int32 process_id,
269 int32 routing_id) {
270 return RenderWidgetHostImpl::FromID(process_id, routing_id);
273 // static
274 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
275 int32 process_id,
276 int32 routing_id) {
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;
284 // static
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();
290 ++it) {
291 RenderWidgetHost* widget = it->second;
293 if (!widget->IsRenderView()) {
294 hosts->Add(widget);
295 continue;
298 // Add only active RenderViewHosts.
299 RenderViewHost* rvh = RenderViewHost::From(widget);
300 if (RenderViewHostImpl::IsRVHStateActive(
301 static_cast<RenderViewHostImpl*>(rvh)->rvh_state()))
302 hosts->Add(widget);
305 return scoped_ptr<RenderWidgetHostIterator>(hosts);
308 // static
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();
315 ++it) {
316 hosts->Add(it->second);
319 return scoped_ptr<RenderWidgetHostIterator>(hosts);
322 // static
323 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
324 return rwh->AsRenderWidgetHostImpl();
327 void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
328 view_ = view;
330 GpuSurfaceTracker::Get()->SetSurfaceHandle(
331 surface_id_, GetCompositingSurface());
333 synthetic_gesture_controller_.reset();
336 RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
337 return process_;
340 int RenderWidgetHostImpl::GetRoutingID() const {
341 return routing_id_;
344 RenderWidgetHostView* RenderWidgetHostImpl::GetView() const {
345 return view_;
348 RenderWidgetHostImpl* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
349 return this;
352 gfx::NativeViewId RenderWidgetHostImpl::GetNativeViewId() const {
353 if (view_)
354 return view_->GetNativeViewId();
355 return 0;
358 gfx::GLSurfaceHandle RenderWidgetHostImpl::GetCompositingSurface() {
359 if (view_)
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_)
376 return;
378 if (is_hidden_) {
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.
381 return;
384 if (!view_)
385 return;
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_));
391 if (delegate_)
392 delegate_->DidSendScreenRects(this);
393 waiting_for_screen_rects_ack_ = true;
396 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
397 if (!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() {
414 if (view_)
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_);
430 WasResized();
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_));
439 DCHECK(rv);
442 Destroy();
445 bool RenderWidgetHostImpl::IsLoading() const {
446 return is_loading_;
449 bool RenderWidgetHostImpl::IsRenderView() const {
450 return false;
453 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
454 bool handled = true;
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)
489 #if defined(OS_WIN)
490 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
491 OnWindowlessPluginDummyWindowCreated)
492 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
493 OnWindowlessPluginDummyWindowDestroyed)
494 #endif
495 #if defined(OS_MACOSX)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
497 OnCompositorSurfaceBuffersSwapped)
498 #endif
499 #if defined(OS_MACOSX) || defined(USE_AURA)
500 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
501 OnImeCompositionRangeChanged)
502 #endif
503 IPC_MESSAGE_UNHANDLED(handled = false)
504 IPC_END_MESSAGE_MAP_EX()
506 if (!handled && input_router_ && input_router_->OnMessageReceived(msg))
507 return true;
509 if (!handled && view_ && view_->OnMessageReceived(msg))
510 return true;
512 if (!msg_is_ok) {
513 // The message de-serialization failed. Kill the renderer process.
514 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH"));
515 GetProcess()->ReceivedBadMessage();
517 return handled;
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() {
528 if (is_hidden_)
529 return;
531 is_hidden_ = true;
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() {
551 if (!is_hidden_)
552 return;
553 is_hidden_ = false;
555 SendScreenRects();
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
574 // 3. WasHidden
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
577 // is.
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.
585 WasResized();
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_) {
593 return;
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)
617 return;
619 if (!screen_info_) {
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;
639 } else {
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() {
649 Focus();
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
659 // request later.
660 if (IsMouseLocked())
661 view_->UnlockMouse();
663 // If there is a pending overscroll, then that should be cancelled.
664 if (overscroll_controller_)
665 overscroll_controller_->Cancel();
667 if (touch_emulator_)
668 touch_emulator_->CancelTouch();
670 Send(new InputMsg_SetFocus(routing_id_, false));
673 void RenderWidgetHostImpl::LostCapture() {
674 if (touch_emulator_)
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.
693 SetView(NULL);
696 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
697 is_loading_ = is_loading;
698 if (!view_)
699 return;
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);
715 return;
718 callback.Run(false, SkBitmap());
721 bool RenderWidgetHostImpl::CanCopyFromBackingStore() {
722 if (view_)
723 return view_->IsSurfaceAvailableForCopy();
724 return false;
727 #if defined(OS_ANDROID)
728 void RenderWidgetHostImpl::LockBackingStore() {
729 if (view_)
730 view_->LockCompositingSurface();
733 void RenderWidgetHostImpl::UnlockBackingStore() {
734 if (view_)
735 view_->UnlockCompositingSurface();
737 #endif
739 void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
740 TRACE_EVENT0("browser",
741 "RenderWidgetHostImpl::PauseForPendingResizeOrRepaints");
743 if (!CanPauseForPendingResizeOrRepaints())
744 return;
746 WaitForSurface();
749 bool RenderWidgetHostImpl::CanPauseForPendingResizeOrRepaints() {
750 // Do not pause if the view is hidden.
751 if (is_hidden())
752 return false;
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_)
756 return false;
758 return true;
761 void RenderWidgetHostImpl::WaitForSurface() {
762 TRACE_EVENT0("browser", "RenderWidgetHostImpl::WaitForSurface");
764 if (!view_)
765 return;
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())
775 return;
776 view_size = view_rect.size();
779 TRACE_EVENT2("renderer_host",
780 "RenderWidgetHostImpl::WaitForBackingStore",
781 "width",
782 base::IntToString(view_size.width()),
783 "height",
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))
800 return;
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;
814 do {
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.
820 IPC::Message msg;
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
830 // correct size.
831 if (view_->HasAcceleratedSurface(view_size) || abort_get_backing_store_) {
832 abort_get_backing_store_ = false;
833 return;
835 } else {
836 TRACE_EVENT0("renderer_host", "WaitForSurface::Timeout");
837 break;
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_) {
852 return false;
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_));
861 return true;
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))
912 return;
915 if (IgnoreInputEvents())
916 return;
918 if (touch_emulator_ && touch_emulator_->HandleMouseEvent(mouse_event))
919 return;
921 input_router_->SendMouseEvent(MouseEventWithLatencyInfo(mouse_event,
922 latency_info));
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())
942 return;
944 if (touch_emulator_ && touch_emulator_->HandleMouseWheelEvent(wheel_event))
945 return;
947 input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event,
948 latency_info));
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())
962 return;
964 if (delegate_->PreHandleGestureEvent(gesture_event))
965 return;
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())
1019 return;
1021 if (!process_->HasConnection())
1022 return;
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;
1031 return;
1034 if (key_event.type == WebKeyboardEvent::Char &&
1035 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
1036 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
1037 OnUserGesture();
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))
1043 return;
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)
1051 return;
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))
1070 return;
1072 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1073 suppress_next_char_events_ = false;
1076 if (touch_emulator_ && touch_emulator_->HandleKeyboardEvent(key_event))
1077 return;
1079 input_router_->SendKeyboardEvent(
1080 key_event,
1081 CreateRWHLatencyInfoIfNotExist(NULL, key_event.type),
1082 is_shortcut);
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) {
1100 if (!view_)
1101 return;
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);
1113 // static
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;
1121 if (original)
1122 info = *original;
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(),
1127 NULL)) {
1128 info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1129 GetLatencyComponentId(),
1130 ++last_input_number_);
1131 info.TraceEventType(WebInputEventTraits::GetName(type));
1133 return info;
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);
1148 return;
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);
1163 return;
1168 void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
1169 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1170 if (view_)
1171 view_->GetScreenInfo(result);
1172 else
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
1185 // factor).
1186 InvalidateScreenInfo();
1187 WasResized();
1190 void RenderWidgetHostImpl::InvalidateScreenInfo() {
1191 screen_info_out_of_date_ = true;
1192 screen_info_.reset();
1195 void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
1196 size_t offset,
1197 const gfx::Range& range) {
1198 if (view_)
1199 view_->SelectionChanged(text, offset, range);
1202 void RenderWidgetHostImpl::OnSelectionBoundsChanged(
1203 const ViewHostMsg_SelectionBounds_Params& params) {
1204 if (view_) {
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,
1215 int exit_code) {
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);
1235 is_hidden_ = false;
1236 is_accelerated_compositing_active_ = false;
1238 // Reset this to ensure the hung renderer mechanism is working properly.
1239 in_flight_event_count_ = 0;
1241 if (view_) {
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 {
1310 return gfx::Rect();
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 {
1335 return false;
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().
1352 if (view_)
1353 view_->Destroy();
1355 delete this;
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() {
1375 SendScreenRects();
1376 WasResized();
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.
1383 Destroy();
1386 void RenderWidgetHostImpl::OnClose() {
1387 Shutdown();
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);
1418 if (GetView())
1419 view_->SetTooltipText(wrapped_tooltip_text);
1422 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1423 waiting_for_screen_rects_ack_ = false;
1424 if (!view_)
1425 return;
1427 if (view_->GetViewBounds() == last_view_screen_rect_ &&
1428 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
1429 return;
1432 SendScreenRects();
1435 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
1436 if (view_) {
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"))
1455 return;
1456 if (!view_) {
1457 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1458 ack_params.sync_point = 0;
1459 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1460 params.gpu_process_host_id,
1461 ack_params);
1462 return;
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();
1477 #endif // OS_MACOSX
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, &param))
1487 return false;
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));
1498 if (view_) {
1499 view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
1500 view_->DidReceiveRendererFrame();
1501 } else {
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,
1509 &ack.resources);
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);
1516 return true;
1519 void RenderWidgetHostImpl::OnFlingingStopped() {
1520 if (view_)
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(
1564 FROM_HERE,
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.
1593 if (view_)
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
1603 // us more data.
1604 if (is_hidden_)
1605 return;
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);
1610 if (is_resize_ack)
1611 WasResized();
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();
1626 return;
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) {
1648 SetCursor(cursor);
1651 void RenderWidgetHostImpl::OnSetTouchEventEmulationEnabled(
1652 bool enabled, bool allow_pinch) {
1653 if (enabled) {
1654 if (!touch_emulator_)
1655 touch_emulator_.reset(new TouchEmulator(this));
1656 touch_emulator_->Enable(allow_pinch);
1657 } else {
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) {
1667 if (view_)
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) {
1675 if (view_)
1676 view_->ImeCompositionRangeChanged(range, character_bounds);
1678 #endif
1680 void RenderWidgetHostImpl::OnImeCancelComposition() {
1681 if (view_)
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;
1690 if (view_)
1691 view_->OnAcceleratedCompositingStateChange();
1694 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
1695 bool last_unlocked_by_target,
1696 bool privileged) {
1698 if (pending_mouse_lock_request_) {
1699 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1700 return;
1701 } else if (IsMouseLocked()) {
1702 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
1703 return;
1706 pending_mouse_lock_request_ = true;
1707 if (privileged && allow_privileged_mouse_lock_) {
1708 // Directly approve to lock the mouse.
1709 GotResponseToLockMouseRequest(true);
1710 } else {
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);
1728 if (!bitmap) {
1729 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH6"));
1730 GetProcess()->ReceivedBadMessage();
1731 return;
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)
1742 if (view_)
1743 view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
1744 #else
1745 NOTIMPLEMENTED();
1746 #endif
1748 zoomed_bitmap.setPixels(0);
1749 Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id));
1752 #if defined(OS_WIN)
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
1758 // away.
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) {
1763 return;
1766 #if defined(USE_AURA)
1767 SetParent(hwnd,
1768 reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
1769 #else
1770 SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
1771 #endif
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) {
1780 if ((*i) == hwnd) {
1781 dummy_windows_for_activation_.erase(i);
1782 return;
1785 NOTREACHED() << "Unknown dummy window";
1787 #endif
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)
1796 return false;
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))
1801 return true;
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);
1808 --i;
1812 return false;
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)
1827 OnUserGesture();
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();
1857 if (view_)
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))
1866 return;
1867 #endif
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;
1918 if (view_)
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))
1937 return;
1939 if (view_)
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() {
1970 OnUserGesture();
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);
2055 #if defined(OS_WIN)
2056 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2057 gfx::NativeViewAccessible accessible_parent) {
2058 if (view_)
2059 view_->SetParentNativeViewAccessible(accessible_parent);
2062 gfx::NativeViewAccessible
2063 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2064 return delegate_->GetParentNativeViewAccessible();
2066 #endif
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) {
2083 if (!allowed) {
2084 RejectMouseLockOrUnlockIfNecessary();
2085 return false;
2086 } else {
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.
2090 return false;
2093 pending_mouse_lock_request_ = false;
2094 if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
2095 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2096 return false;
2097 } else {
2098 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2099 return true;
2104 // static
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);
2109 if (ui_shim) {
2110 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
2111 params));
2115 // static
2116 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2117 int32 route_id,
2118 uint32 output_surface_id,
2119 int renderer_host_id,
2120 const cc::CompositorFrameAck& ack) {
2121 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2122 if (!host)
2123 return;
2124 host->Send(new ViewMsg_SwapCompositorFrameAck(
2125 route_id, output_surface_id, ack));
2128 // static
2129 void RenderWidgetHostImpl::SendReclaimCompositorResources(
2130 int32 route_id,
2131 uint32 output_surface_id,
2132 int renderer_host_id,
2133 const cc::CompositorFrameAck& ack) {
2134 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2135 if (!host)
2136 return;
2137 host->Send(
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_)
2148 return;
2150 OnRenderAutoResized(new_size);
2153 void RenderWidgetHostImpl::DetachDelegate() {
2154 delegate_ = NULL;
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,
2165 &ui_component) ||
2166 !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2167 GetLatencyComponentId(),
2168 &rwh_component))
2169 return;
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(),
2180 20000,
2181 100);
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(),
2193 1000000,
2194 100);
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(),
2211 &rwh_component) ||
2212 !latency_info.FindLatency(
2213 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
2214 0, &swap_component)) {
2215 return;
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(),
2233 1000000,
2234 100);
2239 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
2240 view_->DidReceiveRendererFrame();
2243 void RenderWidgetHostImpl::WindowSnapshotAsyncCallback(
2244 int routing_id,
2245 int snapshot_id,
2246 gfx::Size snapshot_size,
2247 scoped_refptr<base::RefCountedBytes> png_data) {
2248 if (!png_data) {
2249 std::vector<unsigned char> png_vector;
2250 Send(new ViewMsg_WindowSnapshotCompleted(
2251 routing_id, snapshot_id, gfx::Size(), png_vector));
2252 return;
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));
2270 return;
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));
2281 return;
2284 ui::GrabViewSnapshotAsync(
2285 GetView()->GetNativeView(),
2286 snapshot_bounds,
2287 base::ThreadTaskRunnerHandle::Get(),
2288 base::Bind(&RenderWidgetHostImpl::WindowSnapshotAsyncCallback,
2289 weak_factory_.GetWeakPtr(),
2290 GetRoutingID(),
2291 snapshot_id,
2292 snapshot_size));
2295 // static
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();
2303 ++b) {
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);
2311 if (!rwh) {
2312 continue;
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++);
2337 } else {
2338 ++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() {
2349 if (view_)
2350 return view_->PreferredReadbackFormat();
2351 return SkBitmap::kARGB_8888_Config;
2354 } // namespace content