Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_impl.cc
blobf37ec19ffa63c05d5d0d9437495f846648e3396b
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 <utility>
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/containers/hash_tables.h"
14 #include "base/debug/trace_event.h"
15 #include "base/i18n/rtl.h"
16 #include "base/lazy_instance.h"
17 #include "base/message_loop.h"
18 #include "base/metrics/field_trial.h"
19 #include "base/metrics/histogram.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "cc/output/compositor_frame.h"
23 #include "cc/output/compositor_frame_ack.h"
24 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
25 #include "content/browser/gpu/gpu_process_host.h"
26 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
27 #include "content/browser/gpu/gpu_surface_tracker.h"
28 #include "content/browser/renderer_host/backing_store.h"
29 #include "content/browser/renderer_host/backing_store_manager.h"
30 #include "content/browser/renderer_host/dip_util.h"
31 #include "content/browser/renderer_host/gesture_event_filter.h"
32 #include "content/browser/renderer_host/overscroll_controller.h"
33 #include "content/browser/renderer_host/render_process_host_impl.h"
34 #include "content/browser/renderer_host/render_view_host_impl.h"
35 #include "content/browser/renderer_host/render_widget_helper.h"
36 #include "content/browser/renderer_host/render_widget_host_delegate.h"
37 #include "content/browser/renderer_host/touch_event_queue.h"
38 #include "content/browser/renderer_host/touchpad_tap_suppression_controller.h"
39 #include "content/common/accessibility_messages.h"
40 #include "content/common/content_constants_internal.h"
41 #include "content/common/gpu/gpu_messages.h"
42 #include "content/common/input_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/port/browser/render_widget_host_view_port.h"
45 #include "content/public/browser/compositor_util.h"
46 #include "content/public/browser/native_web_keyboard_event.h"
47 #include "content/public/browser/notification_service.h"
48 #include "content/public/browser/notification_types.h"
49 #include "content/public/browser/user_metrics.h"
50 #include "content/public/common/content_constants.h"
51 #include "content/public/common/content_switches.h"
52 #include "content/public/common/result_codes.h"
53 #include "skia/ext/image_operations.h"
54 #include "skia/ext/platform_canvas.h"
55 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
56 #include "ui/base/events/event.h"
57 #include "ui/base/keycodes/keyboard_codes.h"
58 #include "ui/gfx/size_conversions.h"
59 #include "ui/gfx/skbitmap_operations.h"
60 #include "ui/gfx/vector2d_conversions.h"
61 #include "webkit/common/cursors/webcursor.h"
62 #include "webkit/common/webpreferences.h"
63 #include "webkit/plugins/npapi/webplugin.h"
64 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
66 #if defined(TOOLKIT_GTK)
67 #include "content/browser/renderer_host/backing_store_gtk.h"
68 #elif defined(OS_MACOSX)
69 #include "content/browser/renderer_host/backing_store_mac.h"
70 #endif
72 using base::Time;
73 using base::TimeDelta;
74 using base::TimeTicks;
75 using webkit::npapi::WebPluginDelegateImpl;
76 using WebKit::WebGestureEvent;
77 using WebKit::WebInputEvent;
78 using WebKit::WebKeyboardEvent;
79 using WebKit::WebMouseEvent;
80 using WebKit::WebMouseWheelEvent;
81 using WebKit::WebTextDirection;
83 namespace content {
84 namespace {
86 bool g_check_for_pending_resize_ack = true;
88 // How long to (synchronously) wait for the renderer to respond with a
89 // PaintRect message, when our backing-store is invalid, before giving up and
90 // returning a null or incorrectly sized backing-store from GetBackingStore.
91 // This timeout impacts the "choppiness" of our window resize perf.
92 const int kPaintMsgTimeoutMS = 50;
94 // Returns |true| if the two wheel events should be coalesced.
95 bool ShouldCoalesceMouseWheelEvents(const WebMouseWheelEvent& last_event,
96 const WebMouseWheelEvent& new_event) {
97 return last_event.modifiers == new_event.modifiers &&
98 last_event.scrollByPage == new_event.scrollByPage &&
99 last_event.hasPreciseScrollingDeltas
100 == new_event.hasPreciseScrollingDeltas &&
101 last_event.phase == new_event.phase &&
102 last_event.momentumPhase == new_event.momentumPhase;
105 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
106 return accelerated_delta * acceleration_ratio;
109 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) {
110 if (unaccelerated_delta == 0.f || accelerated_delta == 0.f)
111 return 1.f;
112 return unaccelerated_delta / accelerated_delta;
115 base::LazyInstance<std::vector<RenderWidgetHost::CreatedCallback> >
116 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
118 } // namespace
121 typedef std::pair<int32, int32> RenderWidgetHostID;
122 typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
123 RoutingIDWidgetMap;
124 static base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
125 LAZY_INSTANCE_INITIALIZER;
127 // static
128 void RenderWidgetHost::RemoveAllBackingStores() {
129 BackingStoreManager::RemoveAllBackingStores();
132 // static
133 size_t RenderWidgetHost::BackingStoreMemorySize() {
134 return BackingStoreManager::MemorySize();
137 ///////////////////////////////////////////////////////////////////////////////
138 // RenderWidgetHostImpl
140 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
141 RenderProcessHost* process,
142 int routing_id)
143 : view_(NULL),
144 renderer_initialized_(false),
145 hung_renderer_delay_ms_(kHungRendererDelayMs),
146 delegate_(delegate),
147 process_(process),
148 routing_id_(routing_id),
149 surface_id_(0),
150 is_loading_(false),
151 is_hidden_(false),
152 is_fullscreen_(false),
153 is_accelerated_compositing_active_(false),
154 repaint_ack_pending_(false),
155 resize_ack_pending_(false),
156 screen_info_out_of_date_(false),
157 overdraw_bottom_height_(0.f),
158 should_auto_resize_(false),
159 waiting_for_screen_rects_ack_(false),
160 mouse_move_pending_(false),
161 mouse_wheel_pending_(false),
162 accessibility_mode_(AccessibilityModeOff),
163 select_range_pending_(false),
164 move_caret_pending_(false),
165 needs_repainting_on_restore_(false),
166 is_unresponsive_(false),
167 in_flight_event_count_(0),
168 in_get_backing_store_(false),
169 abort_get_backing_store_(false),
170 view_being_painted_(false),
171 ignore_input_events_(false),
172 input_method_active_(false),
173 text_direction_updated_(false),
174 text_direction_(WebKit::WebTextDirectionLeftToRight),
175 text_direction_canceled_(false),
176 suppress_next_char_events_(false),
177 pending_mouse_lock_request_(false),
178 allow_privileged_mouse_lock_(false),
179 has_touch_handler_(false),
180 weak_factory_(this),
181 touch_event_queue_(new TouchEventQueue(this)),
182 gesture_event_filter_(new GestureEventFilter(this)),
183 last_input_number_(0) {
184 CHECK(delegate_);
185 if (routing_id_ == MSG_ROUTING_NONE) {
186 routing_id_ = process_->GetNextRoutingID();
187 surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
188 process_->GetID(),
189 routing_id_);
190 } else {
191 // TODO(piman): This is a O(N) lookup, where we could forward the
192 // information from the RenderWidgetHelper. The problem is that doing so
193 // currently leaks outside of content all the way to chrome classes, and
194 // would be a layering violation. Since we don't expect more than a few
195 // hundreds of RWH, this seems acceptable. Revisit if performance become a
196 // problem, for example by tracking in the RenderWidgetHelper the routing id
197 // (and surface id) that have been created, but whose RWH haven't yet.
198 surface_id_ = GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
199 process_->GetID(),
200 routing_id_);
201 DCHECK(surface_id_);
204 is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled();
206 g_routing_id_widget_map.Get().insert(std::make_pair(
207 RenderWidgetHostID(process->GetID(), routing_id_), this));
208 process_->AddRoute(routing_id_, this);
209 // Because the widget initializes as is_hidden_ == false,
210 // tell the process host that we're alive.
211 process_->WidgetRestored();
213 accessibility_mode_ =
214 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
216 for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
217 g_created_callbacks.Get().at(i).Run(this);
219 #if defined(USE_AURA)
220 bool overscroll_enabled = CommandLine::ForCurrentProcess()->
221 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
222 SetOverscrollControllerEnabled(overscroll_enabled);
223 #endif
226 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
227 SetView(NULL);
229 // Clear our current or cached backing store if either remains.
230 BackingStoreManager::RemoveBackingStore(this);
232 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
233 surface_id_ = 0;
235 process_->RemoveRoute(routing_id_);
236 g_routing_id_widget_map.Get().erase(
237 RenderWidgetHostID(process_->GetID(), routing_id_));
239 if (delegate_)
240 delegate_->RenderWidgetDeleted(this);
243 // static
244 RenderWidgetHost* RenderWidgetHost::FromID(
245 int32 process_id,
246 int32 routing_id) {
247 return RenderWidgetHostImpl::FromID(process_id, routing_id);
250 // static
251 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
252 int32 process_id,
253 int32 routing_id) {
254 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
255 RoutingIDWidgetMap::iterator it = widgets->find(
256 RenderWidgetHostID(process_id, routing_id));
257 return it == widgets->end() ? NULL : it->second;
260 // static
261 std::vector<RenderWidgetHost*> RenderWidgetHost::GetRenderWidgetHosts() {
262 std::vector<RenderWidgetHost*> hosts;
263 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
264 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
265 it != widgets->end();
266 ++it) {
267 hosts.push_back(it->second);
269 return hosts;
272 // static
273 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
274 return rwh->AsRenderWidgetHostImpl();
277 // static
278 void RenderWidgetHost::AddCreatedCallback(const CreatedCallback& callback) {
279 g_created_callbacks.Get().push_back(callback);
282 // static
283 void RenderWidgetHost::RemoveCreatedCallback(const CreatedCallback& callback) {
284 for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
285 if (g_created_callbacks.Get().at(i).Equals(callback)) {
286 g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
287 return;
292 void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
293 view_ = RenderWidgetHostViewPort::FromRWHV(view);
295 if (!view_) {
296 GpuSurfaceTracker::Get()->SetSurfaceHandle(
297 surface_id_, gfx::GLSurfaceHandle());
301 RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
302 return process_;
305 int RenderWidgetHostImpl::GetRoutingID() const {
306 return routing_id_;
309 RenderWidgetHostView* RenderWidgetHostImpl::GetView() const {
310 return view_;
313 RenderWidgetHostImpl* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
314 return this;
317 gfx::NativeViewId RenderWidgetHostImpl::GetNativeViewId() const {
318 if (view_)
319 return view_->GetNativeViewId();
320 return 0;
323 gfx::GLSurfaceHandle RenderWidgetHostImpl::GetCompositingSurface() {
324 if (view_)
325 return view_->GetCompositingSurface();
326 return gfx::GLSurfaceHandle();
329 void RenderWidgetHostImpl::CompositingSurfaceUpdated() {
330 GpuSurfaceTracker::Get()->SetSurfaceHandle(
331 surface_id_, GetCompositingSurface());
332 process_->SurfaceUpdated(surface_id_);
335 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
336 resize_ack_pending_ = false;
337 if (repaint_ack_pending_) {
338 TRACE_EVENT_ASYNC_END0(
339 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
341 repaint_ack_pending_ = false;
342 in_flight_size_.SetSize(0, 0);
345 void RenderWidgetHostImpl::SendScreenRects() {
346 if (!renderer_initialized_ || waiting_for_screen_rects_ack_)
347 return;
349 if (is_hidden_) {
350 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
351 // happens on Win & Mac, and when the view is shown it'll call this again.
352 return;
355 if (!view_)
356 return;
358 last_view_screen_rect_ = view_->GetViewBounds();
359 last_window_screen_rect_ = view_->GetBoundsInRootWindow();
360 Send(new ViewMsg_UpdateScreenRects(
361 GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
362 if (delegate_)
363 delegate_->DidSendScreenRects(this);
364 waiting_for_screen_rects_ack_ = true;
367 base::TimeDelta
368 RenderWidgetHostImpl::GetSyntheticScrollMessageInterval() const {
369 return smooth_scroll_gesture_controller_.GetSyntheticScrollMessageInterval();
372 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
373 if (!enabled)
374 overscroll_controller_.reset();
375 else if (!overscroll_controller_)
376 overscroll_controller_.reset(new OverscrollController(this));
379 void RenderWidgetHostImpl::SuppressNextCharEvents() {
380 suppress_next_char_events_ = true;
383 void RenderWidgetHostImpl::Init() {
384 DCHECK(process_->HasConnection());
386 renderer_initialized_ = true;
388 GpuSurfaceTracker::Get()->SetSurfaceHandle(
389 surface_id_, GetCompositingSurface());
391 // Send the ack along with the information on placement.
392 Send(new ViewMsg_CreatingNew_ACK(routing_id_));
393 GetProcess()->ResumeRequestsForView(routing_id_);
395 WasResized();
398 void RenderWidgetHostImpl::Shutdown() {
399 RejectMouseLockOrUnlockIfNecessary();
401 if (process_->HasConnection()) {
402 // Tell the renderer object to close.
403 bool rv = Send(new ViewMsg_Close(routing_id_));
404 DCHECK(rv);
407 Destroy();
410 bool RenderWidgetHostImpl::IsLoading() const {
411 return is_loading_;
414 bool RenderWidgetHostImpl::IsRenderView() const {
415 return false;
418 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
419 bool handled = true;
420 bool msg_is_ok = true;
421 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl, msg, msg_is_ok)
422 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
423 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnRenderViewGone)
424 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
425 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
426 OnUpdateScreenRectsAck)
427 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
428 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
429 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK, OnPaintAtSizeAck)
430 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
431 OnCompositorSurfaceBuffersSwapped)
432 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
433 msg_is_ok = OnSwapCompositorFrame(msg))
434 IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
435 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
436 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
437 IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
438 IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll, OnBeginSmoothScroll)
439 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
440 IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
441 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
442 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
443 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
444 OnHasTouchEventHandlers)
445 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
446 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
447 OnTextInputTypeChanged)
448 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
449 OnImeCompositionRangeChanged)
450 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
451 OnImeCancelComposition)
452 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing,
453 OnDidActivateAcceleratedCompositing)
454 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
455 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
456 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
457 OnShowDisambiguationPopup)
458 #if defined(OS_WIN)
459 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
460 OnWindowlessPluginDummyWindowCreated)
461 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
462 OnWindowlessPluginDummyWindowDestroyed)
463 #endif
464 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
465 IPC_MESSAGE_UNHANDLED(handled = false)
466 IPC_END_MESSAGE_MAP_EX()
468 if (!handled && view_ && view_->OnMessageReceived(msg))
469 return true;
471 if (!msg_is_ok) {
472 // The message de-serialization failed. Kill the renderer process.
473 RecordAction(UserMetricsAction("BadMessageTerminate_RWH"));
474 GetProcess()->ReceivedBadMessage();
476 return handled;
479 bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
480 return process_->Send(msg);
483 void RenderWidgetHostImpl::WasHidden() {
484 is_hidden_ = true;
486 // Don't bother reporting hung state when we aren't active.
487 StopHangMonitorTimeout();
489 // If we have a renderer, then inform it that we are being hidden so it can
490 // reduce its resource utilization.
491 Send(new ViewMsg_WasHidden(routing_id_));
493 // Tell the RenderProcessHost we were hidden.
494 process_->WidgetHidden();
496 bool is_visible = false;
497 NotificationService::current()->Notify(
498 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
499 Source<RenderWidgetHost>(this),
500 Details<bool>(&is_visible));
503 void RenderWidgetHostImpl::WasShown() {
504 // When we create the widget, it is created as *not* hidden.
505 if (!is_hidden_)
506 return;
507 is_hidden_ = false;
509 SendScreenRects();
511 BackingStore* backing_store = BackingStoreManager::Lookup(this);
512 // If we already have a backing store for this widget, then we don't need to
513 // repaint on restore _unless_ we know that our backing store is invalid.
514 // When accelerated compositing is on, we must always repaint, even when
515 // the backing store exists.
516 bool needs_repainting;
517 if (needs_repainting_on_restore_ || !backing_store ||
518 is_accelerated_compositing_active()) {
519 needs_repainting = true;
520 needs_repainting_on_restore_ = false;
521 } else {
522 needs_repainting = false;
524 Send(new ViewMsg_WasShown(routing_id_, needs_repainting));
526 process_->WidgetRestored();
528 bool is_visible = true;
529 NotificationService::current()->Notify(
530 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
531 Source<RenderWidgetHost>(this),
532 Details<bool>(&is_visible));
534 // It's possible for our size to be out of sync with the renderer. The
535 // following is one case that leads to this:
536 // 1. WasResized -> Send ViewMsg_Resize to render
537 // 2. WasResized -> do nothing as resize_ack_pending_ is true
538 // 3. WasHidden
539 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
540 // is hidden. Now renderer/browser out of sync with what they think size
541 // is.
542 // By invoking WasResized the renderer is updated as necessary. WasResized
543 // does nothing if the sizes are already in sync.
545 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
546 // could handle both the restore and resize at once. This isn't that big a
547 // deal as RenderWidget::WasShown delays updating, so that the resize from
548 // WasResized is usually processed before the renderer is painted.
549 WasResized();
552 void RenderWidgetHostImpl::WasResized() {
553 if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
554 !renderer_initialized_ || should_auto_resize_) {
555 return;
558 gfx::Rect view_bounds = view_->GetViewBounds();
559 gfx::Size new_size(view_bounds.size());
561 gfx::Size old_physical_backing_size = physical_backing_size_;
562 physical_backing_size_ = view_->GetPhysicalBackingSize();
563 bool was_fullscreen = is_fullscreen_;
564 is_fullscreen_ = IsFullscreen();
565 float old_overdraw_bottom_height = overdraw_bottom_height_;
566 overdraw_bottom_height_ = view_->GetOverdrawBottomHeight();
568 bool size_changed = new_size != current_size_;
569 bool side_payload_changed =
570 screen_info_out_of_date_ ||
571 old_physical_backing_size != physical_backing_size_ ||
572 was_fullscreen != is_fullscreen_ ||
573 old_overdraw_bottom_height != overdraw_bottom_height_;
575 if (!size_changed && !side_payload_changed)
576 return;
578 if (in_flight_size_ != gfx::Size() && new_size == in_flight_size_ &&
579 !side_payload_changed)
580 return;
582 if (!screen_info_) {
583 screen_info_.reset(new WebKit::WebScreenInfo);
584 GetWebScreenInfo(screen_info_.get());
587 // We don't expect to receive an ACK when the requested size or the physical
588 // backing size is empty, or when the main viewport size didn't change.
589 if (!new_size.IsEmpty() && !physical_backing_size_.IsEmpty() && size_changed)
590 resize_ack_pending_ = g_check_for_pending_resize_ack;
592 ViewMsg_Resize_Params params;
593 params.screen_info = *screen_info_;
594 params.new_size = new_size;
595 params.physical_backing_size = physical_backing_size_;
596 params.overdraw_bottom_height = overdraw_bottom_height_;
597 params.resizer_rect = GetRootWindowResizerRect();
598 params.is_fullscreen = is_fullscreen_;
599 if (!Send(new ViewMsg_Resize(routing_id_, params))) {
600 resize_ack_pending_ = false;
601 } else {
602 in_flight_size_ = new_size;
606 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
607 Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
610 void RenderWidgetHostImpl::GotFocus() {
611 Focus();
614 void RenderWidgetHostImpl::Focus() {
615 Send(new InputMsg_SetFocus(routing_id_, true));
618 void RenderWidgetHostImpl::Blur() {
619 // If there is a pending mouse lock request, we don't want to reject it at
620 // this point. The user can switch focus back to this view and approve the
621 // request later.
622 if (IsMouseLocked())
623 view_->UnlockMouse();
625 // If there is a pending overscroll, then that should be cancelled.
626 if (overscroll_controller_)
627 overscroll_controller_->Cancel();
629 Send(new InputMsg_SetFocus(routing_id_, false));
632 void RenderWidgetHostImpl::LostCapture() {
633 Send(new InputMsg_MouseCaptureLost(routing_id_));
636 void RenderWidgetHostImpl::SetActive(bool active) {
637 Send(new ViewMsg_SetActive(routing_id_, active));
640 void RenderWidgetHostImpl::LostMouseLock() {
641 Send(new ViewMsg_MouseLockLost(routing_id_));
644 void RenderWidgetHostImpl::ViewDestroyed() {
645 RejectMouseLockOrUnlockIfNecessary();
647 // TODO(evanm): tracking this may no longer be necessary;
648 // eliminate this function if so.
649 SetView(NULL);
652 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
653 is_loading_ = is_loading;
654 if (!view_)
655 return;
656 view_->SetIsLoading(is_loading);
659 void RenderWidgetHostImpl::CopyFromBackingStore(
660 const gfx::Rect& src_subrect,
661 const gfx::Size& accelerated_dst_size,
662 const base::Callback<void(bool, const SkBitmap&)>& callback) {
663 if (view_ && is_accelerated_compositing_active_) {
664 TRACE_EVENT0("browser",
665 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
666 gfx::Rect accelerated_copy_rect = src_subrect.IsEmpty() ?
667 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
668 view_->CopyFromCompositingSurface(accelerated_copy_rect,
669 accelerated_dst_size,
670 callback);
671 return;
674 BackingStore* backing_store = GetBackingStore(false);
675 if (!backing_store) {
676 callback.Run(false, SkBitmap());
677 return;
680 TRACE_EVENT0("browser",
681 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
682 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
683 gfx::Rect(backing_store->size()) : src_subrect;
684 // When the result size is equal to the backing store size, copy from the
685 // backing store directly to the output canvas.
686 skia::PlatformBitmap output;
687 bool result = backing_store->CopyFromBackingStore(copy_rect, &output);
688 callback.Run(result, output.GetBitmap());
691 #if defined(TOOLKIT_GTK)
692 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
693 const gfx::Rect& dest_rect, GdkWindow* target) {
694 BackingStore* backing_store = GetBackingStore(false);
695 if (!backing_store)
696 return false;
697 (static_cast<BackingStoreGtk*>(backing_store))->PaintToRect(
698 dest_rect, target);
699 return true;
701 #elif defined(OS_MACOSX)
702 gfx::Size RenderWidgetHostImpl::GetBackingStoreSize() {
703 BackingStore* backing_store = GetBackingStore(false);
704 return backing_store ? backing_store->size() : gfx::Size();
707 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
708 const CGRect& dest_rect, CGContextRef target) {
709 BackingStore* backing_store = GetBackingStore(false);
710 if (!backing_store)
711 return false;
712 (static_cast<BackingStoreMac*>(backing_store))->
713 CopyFromBackingStoreToCGContext(dest_rect, target);
714 return true;
716 #endif
718 void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle,
719 int tag,
720 const gfx::Size& page_size,
721 const gfx::Size& desired_size) {
722 // Ask the renderer to create a bitmap regardless of whether it's
723 // hidden, being resized, redrawn, etc. It resizes the web widget
724 // to the page_size and then scales it to the desired_size.
725 Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, tag,
726 page_size, desired_size));
729 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
730 BackingStore** backing_store) {
731 // Check if the view has an accelerated surface of the desired size.
732 if (view_->HasAcceleratedSurface(desired_size)) {
733 *backing_store = NULL;
734 return true;
737 // Check for a software backing store of the desired size.
738 *backing_store = BackingStoreManager::GetBackingStore(this, desired_size);
739 return !!*backing_store;
742 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
743 if (!view_)
744 return NULL;
746 // The view_size will be current_size_ for auto-sized views and otherwise the
747 // size of the view_. (For auto-sized views, current_size_ is updated during
748 // UpdateRect messages.)
749 gfx::Size view_size = current_size_;
750 if (!should_auto_resize_) {
751 // Get the desired size from the current view bounds.
752 gfx::Rect view_rect = view_->GetViewBounds();
753 if (view_rect.IsEmpty())
754 return NULL;
755 view_size = view_rect.size();
758 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
759 "width", base::IntToString(view_size.width()),
760 "height", base::IntToString(view_size.height()));
762 // We should not be asked to paint while we are hidden. If we are hidden,
763 // then it means that our consumer failed to call WasShown. If we're not
764 // force creating the backing store, it's OK since we can feel free to give
765 // out our cached one if we have it.
766 DCHECK(!is_hidden_ || !force_create) <<
767 "GetBackingStore called while hidden!";
769 // We should never be called recursively; this can theoretically lead to
770 // infinite recursion and almost certainly leads to lower performance.
771 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!";
772 base::AutoReset<bool> auto_reset_in_get_backing_store(
773 &in_get_backing_store_, true);
775 // We might have a cached backing store that we can reuse!
776 BackingStore* backing_store = NULL;
777 if (TryGetBackingStore(view_size, &backing_store) || !force_create)
778 return backing_store;
780 // We do not have a suitable backing store in the cache, so send out a
781 // request to the renderer to paint the view if required.
782 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
783 repaint_start_time_ = TimeTicks::Now();
784 repaint_ack_pending_ = true;
785 TRACE_EVENT_ASYNC_BEGIN0(
786 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
787 Send(new ViewMsg_Repaint(routing_id_, view_size));
790 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
791 TimeTicks end_time = TimeTicks::Now() + max_delay;
792 do {
793 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
795 #if defined(OS_MACOSX)
796 view_->AboutToWaitForBackingStoreMsg();
797 #endif
799 // When we have asked the RenderWidget to resize, and we are still waiting
800 // on a response, block for a little while to see if we can't get a response
801 // before returning the old (incorrectly sized) backing store.
802 IPC::Message msg;
803 if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
804 OnMessageReceived(msg);
806 // For auto-resized views, current_size_ determines the view_size and it
807 // may have changed during the handling of an UpdateRect message.
808 if (should_auto_resize_)
809 view_size = current_size_;
811 // Break now if we got a backing store or accelerated surface of the
812 // correct size.
813 if (TryGetBackingStore(view_size, &backing_store) ||
814 abort_get_backing_store_) {
815 abort_get_backing_store_ = false;
816 return backing_store;
818 } else {
819 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
820 break;
823 // Loop if we still have time left and haven't gotten a properly sized
824 // BackingStore yet. This is necessary to support the GPU path which
825 // typically has multiple frames pipelined -- we may need to skip one or two
826 // BackingStore messages to get to the latest.
827 max_delay = end_time - TimeTicks::Now();
828 } while (max_delay > TimeDelta::FromSeconds(0));
830 // We have failed to get a backing store of view_size. Fall back on
831 // current_size_ to avoid a white flash while resizing slow pages.
832 if (view_size != current_size_)
833 TryGetBackingStore(current_size_, &backing_store);
834 return backing_store;
837 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) {
838 if (!view_)
839 return NULL;
840 return view_->AllocBackingStore(size);
843 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
844 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
847 void RenderWidgetHostImpl::ScheduleComposite() {
848 if (is_hidden_ || !is_accelerated_compositing_active_ ||
849 current_size_.IsEmpty()) {
850 return;
853 // Send out a request to the renderer to paint the view if required.
854 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
855 repaint_start_time_ = TimeTicks::Now();
856 repaint_ack_pending_ = true;
857 TRACE_EVENT_ASYNC_BEGIN0(
858 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
859 Send(new ViewMsg_Repaint(routing_id_, current_size_));
863 void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
864 if (!GetProcess()->IsGuest() && CommandLine::ForCurrentProcess()->HasSwitch(
865 switches::kDisableHangMonitor)) {
866 return;
869 // Set time_when_considered_hung_ if it's null. Also, update
870 // time_when_considered_hung_ if the caller's request is sooner than the
871 // existing one. This will have the side effect that the existing timeout will
872 // be forgotten.
873 Time requested_end_time = Time::Now() + delay;
874 if (time_when_considered_hung_.is_null() ||
875 time_when_considered_hung_ > requested_end_time)
876 time_when_considered_hung_ = requested_end_time;
878 // If we already have a timer with the same or shorter duration, then we can
879 // wait for it to finish.
880 if (hung_renderer_timer_.IsRunning() &&
881 hung_renderer_timer_.GetCurrentDelay() <= delay) {
882 // If time_when_considered_hung_ was null, this timer may fire early.
883 // CheckRendererIsUnresponsive handles that by calling
884 // StartHangMonitorTimeout with the remaining time.
885 // If time_when_considered_hung_ was non-null, it means we still haven't
886 // heard from the renderer so we leave time_when_considered_hung_ as is.
887 return;
890 // Either the timer is not yet running, or we need to adjust the timer to
891 // fire sooner.
892 time_when_considered_hung_ = requested_end_time;
893 hung_renderer_timer_.Stop();
894 hung_renderer_timer_.Start(FROM_HERE, delay, this,
895 &RenderWidgetHostImpl::CheckRendererIsUnresponsive);
898 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
899 // Setting to null will cause StartHangMonitorTimeout to restart the timer.
900 time_when_considered_hung_ = Time();
901 StartHangMonitorTimeout(
902 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
905 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
906 time_when_considered_hung_ = Time();
907 RendererIsResponsive();
908 // We do not bother to stop the hung_renderer_timer_ here in case it will be
909 // started again shortly, which happens to be the common use case.
912 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
913 SetAccessibilityMode(AccessibilityModeComplete);
916 static WebGestureEvent MakeGestureEvent(WebInputEvent::Type type,
917 double timestamp_seconds,
918 int x,
919 int y,
920 int modifiers) {
921 WebGestureEvent result;
923 result.type = type;
924 result.x = x;
925 result.y = y;
926 result.sourceDevice = WebGestureEvent::Touchscreen;
927 result.timeStampSeconds = timestamp_seconds;
928 result.modifiers = modifiers;
930 return result;
933 void RenderWidgetHostImpl::SimulateTouchGestureWithMouse(
934 const WebMouseEvent& mouse_event) {
935 int x = mouse_event.x, y = mouse_event.y;
936 float dx = mouse_event.movementX, dy = mouse_event.movementY;
937 static int startX = 0, startY = 0;
939 switch (mouse_event.button) {
940 case WebMouseEvent::ButtonLeft:
941 if (mouse_event.type == WebInputEvent::MouseDown) {
942 startX = x;
943 startY = y;
944 ForwardGestureEvent(MakeGestureEvent(
945 WebInputEvent::GestureScrollBegin, mouse_event.timeStampSeconds,
946 x, y, 0));
948 if (dx != 0 || dy != 0) {
949 WebGestureEvent event = MakeGestureEvent(
950 WebInputEvent::GestureScrollUpdate, mouse_event.timeStampSeconds,
951 x, y, 0);
952 event.data.scrollUpdate.deltaX = dx;
953 event.data.scrollUpdate.deltaY = dy;
954 ForwardGestureEvent(event);
956 if (mouse_event.type == WebInputEvent::MouseUp) {
957 ForwardGestureEvent(MakeGestureEvent(
958 WebInputEvent::GestureScrollEnd, mouse_event.timeStampSeconds,
959 x, y, 0));
961 break;
962 case WebMouseEvent::ButtonMiddle:
963 if (mouse_event.type == WebInputEvent::MouseDown) {
964 startX = x;
965 startY = y;
966 ForwardGestureEvent(MakeGestureEvent(
967 WebInputEvent::GestureTapDown, mouse_event.timeStampSeconds,
968 x, y, 0));
970 if (mouse_event.type == WebInputEvent::MouseUp) {
971 ForwardGestureEvent(MakeGestureEvent(
972 WebInputEvent::GestureTap, mouse_event.timeStampSeconds,
973 x, y, 0));
975 break;
976 case WebMouseEvent::ButtonRight:
977 if (mouse_event.type == WebInputEvent::MouseDown) {
978 startX = x;
979 startY = y;
980 ForwardGestureEvent(MakeGestureEvent(
981 WebInputEvent::GesturePinchBegin, mouse_event.timeStampSeconds,
982 x, y, 0));
984 if (dx != 0 || dy != 0) {
985 dx = pow(dy < 0 ? 0.998f : 1.002f, fabs(dy));
986 WebGestureEvent event = MakeGestureEvent(
987 WebInputEvent::GesturePinchUpdate, mouse_event.timeStampSeconds,
988 startX, startY, 0);
989 event.data.pinchUpdate.scale = dx;
990 ForwardGestureEvent(event);
992 if (mouse_event.type == WebInputEvent::MouseUp) {
993 ForwardGestureEvent(MakeGestureEvent(
994 WebInputEvent::GesturePinchEnd, mouse_event.timeStampSeconds,
995 x, y, 0));
997 break;
998 case WebMouseEvent::ButtonNone:
999 break;
1003 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
1004 ForwardMouseEventWithLatencyInfo(
1005 MouseEventWithLatencyInfo(mouse_event, NewInputLatencyInfo()));
1008 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
1009 const MouseEventWithLatencyInfo& mouse_event) {
1010 TRACE_EVENT2("input",
1011 "RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo",
1012 "x", mouse_event.event.x, "y", mouse_event.event.y);
1013 if (ignore_input_events_ || process_->IgnoreInputEvents())
1014 return;
1016 if (CommandLine::ForCurrentProcess()->HasSwitch(
1017 switches::kSimulateTouchScreenWithMouse)) {
1018 SimulateTouchGestureWithMouse(mouse_event.event);
1019 return;
1022 if (mouse_event.event.type == WebInputEvent::MouseDown &&
1023 gesture_event_filter_->GetTouchpadTapSuppressionController()->
1024 ShouldDeferMouseDown(mouse_event))
1025 return;
1026 if (mouse_event.event.type == WebInputEvent::MouseUp &&
1027 gesture_event_filter_->GetTouchpadTapSuppressionController()->
1028 ShouldSuppressMouseUp())
1029 return;
1031 ForwardMouseEventImmediately(mouse_event);
1034 void RenderWidgetHostImpl::OnPointerEventActivate() {
1037 void RenderWidgetHostImpl::ForwardWheelEvent(
1038 const WebMouseWheelEvent& wheel_event) {
1039 ForwardWheelEventWithLatencyInfo(wheel_event, NewInputLatencyInfo());
1042 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
1043 const WebMouseWheelEvent& wheel_event,
1044 const ui::LatencyInfo& latency_info) {
1045 TRACE_EVENT0("input",
1046 "RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo");
1047 if (ignore_input_events_ || process_->IgnoreInputEvents())
1048 return;
1050 if (delegate_->PreHandleWheelEvent(wheel_event))
1051 return;
1053 // If there's already a mouse wheel event waiting to be sent to the renderer,
1054 // add the new deltas to that event. Not doing so (e.g., by dropping the old
1055 // event, as for mouse moves) results in very slow scrolling on the Mac (on
1056 // which many, very small wheel events are sent).
1057 if (mouse_wheel_pending_) {
1058 if (coalesced_mouse_wheel_events_.empty() ||
1059 !ShouldCoalesceMouseWheelEvents(
1060 coalesced_mouse_wheel_events_.back().event, wheel_event)) {
1061 coalesced_mouse_wheel_events_.push_back(
1062 MouseWheelEventWithLatencyInfo(wheel_event, latency_info));
1063 } else {
1064 MouseWheelEventWithLatencyInfo* last_wheel_event =
1065 &coalesced_mouse_wheel_events_.back();
1066 float unaccelerated_x =
1067 GetUnacceleratedDelta(last_wheel_event->event.deltaX,
1068 last_wheel_event->event.accelerationRatioX) +
1069 GetUnacceleratedDelta(wheel_event.deltaX,
1070 wheel_event.accelerationRatioX);
1071 float unaccelerated_y =
1072 GetUnacceleratedDelta(last_wheel_event->event.deltaY,
1073 last_wheel_event->event.accelerationRatioY) +
1074 GetUnacceleratedDelta(wheel_event.deltaY,
1075 wheel_event.accelerationRatioY);
1076 last_wheel_event->event.deltaX += wheel_event.deltaX;
1077 last_wheel_event->event.deltaY += wheel_event.deltaY;
1078 last_wheel_event->event.wheelTicksX += wheel_event.wheelTicksX;
1079 last_wheel_event->event.wheelTicksY += wheel_event.wheelTicksY;
1080 last_wheel_event->event.accelerationRatioX =
1081 GetAccelerationRatio(last_wheel_event->event.deltaX, unaccelerated_x);
1082 last_wheel_event->event.accelerationRatioY =
1083 GetAccelerationRatio(last_wheel_event->event.deltaY, unaccelerated_y);
1084 DCHECK_GE(wheel_event.timeStampSeconds,
1085 last_wheel_event->event.timeStampSeconds);
1086 last_wheel_event->event.timeStampSeconds = wheel_event.timeStampSeconds;
1087 last_wheel_event->latency.MergeWith(latency_info);
1089 return;
1091 mouse_wheel_pending_ = true;
1092 current_wheel_event_ = wheel_event;
1094 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize",
1095 coalesced_mouse_wheel_events_.size());
1097 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent), latency_info,
1098 false);
1101 void RenderWidgetHostImpl::ForwardGestureEvent(
1102 const WebKit::WebGestureEvent& gesture_event) {
1103 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
1104 if (ignore_input_events_ || process_->IgnoreInputEvents())
1105 return;
1107 ui::LatencyInfo latency_info = NewInputLatencyInfo();
1109 if (!IsInOverscrollGesture() &&
1110 !gesture_event_filter_->ShouldForward(
1111 GestureEventWithLatencyInfo(gesture_event, latency_info))) {
1112 if (overscroll_controller_.get())
1113 overscroll_controller_->DiscardingGestureEvent(gesture_event);
1114 return;
1117 ForwardInputEvent(gesture_event, sizeof(WebGestureEvent),
1118 latency_info, false);
1121 // Forwards MouseEvent without passing it through
1122 // TouchpadTapSuppressionController.
1123 void RenderWidgetHostImpl::ForwardMouseEventImmediately(
1124 const MouseEventWithLatencyInfo& mouse_event) {
1125 TRACE_EVENT2("input",
1126 "RenderWidgetHostImpl::ForwardMouseEventImmediately",
1127 "x", mouse_event.event.x, "y", mouse_event.event.y);
1128 if (ignore_input_events_ || process_->IgnoreInputEvents())
1129 return;
1131 if (CommandLine::ForCurrentProcess()->HasSwitch(
1132 switches::kSimulateTouchScreenWithMouse)) {
1133 SimulateTouchGestureWithMouse(mouse_event.event);
1134 return;
1137 // Avoid spamming the renderer with mouse move events. It is important
1138 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
1139 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
1140 // more WM_MOUSEMOVE events than we wish to send to the renderer.
1141 if (mouse_event.event.type == WebInputEvent::MouseMove) {
1142 if (mouse_move_pending_) {
1143 if (!next_mouse_move_) {
1144 next_mouse_move_.reset(new MouseEventWithLatencyInfo(mouse_event));
1145 } else {
1146 // Accumulate movement deltas.
1147 int x = next_mouse_move_->event.movementX;
1148 int y = next_mouse_move_->event.movementY;
1149 next_mouse_move_->event = mouse_event.event;
1150 next_mouse_move_->event.movementX += x;
1151 next_mouse_move_->event.movementY += y;
1152 next_mouse_move_->latency.MergeWith(mouse_event.latency);
1154 return;
1156 mouse_move_pending_ = true;
1157 } else if (mouse_event.event.type == WebInputEvent::MouseDown) {
1158 OnUserGesture();
1161 ForwardInputEvent(mouse_event.event, sizeof(WebMouseEvent),
1162 mouse_event.latency, false);
1165 void RenderWidgetHostImpl::ForwardTouchEventImmediately(
1166 const TouchEventWithLatencyInfo& touch_event) {
1167 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1168 if (ignore_input_events_ || process_->IgnoreInputEvents())
1169 return;
1171 ForwardInputEvent(touch_event.event, sizeof(WebKit::WebTouchEvent),
1172 touch_event.latency, false);
1175 void RenderWidgetHostImpl::ForwardGestureEventImmediately(
1176 const GestureEventWithLatencyInfo& gesture_event) {
1177 if (ignore_input_events_ || process_->IgnoreInputEvents())
1178 return;
1179 ForwardInputEvent(gesture_event.event, sizeof(WebGestureEvent),
1180 gesture_event.latency, false);
1183 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1184 const NativeWebKeyboardEvent& key_event) {
1185 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1186 if (ignore_input_events_ || process_->IgnoreInputEvents())
1187 return;
1189 // First, let keypress listeners take a shot at handling the event. If a
1190 // listener handles the event, it should not be propagated to the renderer.
1191 if (KeyPressListenersHandleEvent(key_event)) {
1192 // Some keypresses that are accepted by the listener might have follow up
1193 // char events, which should be ignored.
1194 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1195 suppress_next_char_events_ = true;
1196 return;
1199 if (key_event.type == WebKeyboardEvent::Char &&
1200 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
1201 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
1202 OnUserGesture();
1205 // Double check the type to make sure caller hasn't sent us nonsense that
1206 // will mess up our key queue.
1207 if (WebInputEvent::isKeyboardEventType(key_event.type)) {
1208 if (suppress_next_char_events_) {
1209 // If preceding RawKeyDown event was handled by the browser, then we need
1210 // suppress all Char events generated by it. Please note that, one
1211 // RawKeyDown event may generate multiple Char events, so we can't reset
1212 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1213 if (key_event.type == WebKeyboardEvent::Char)
1214 return;
1215 // We get a KeyUp or a RawKeyDown event.
1216 suppress_next_char_events_ = false;
1219 bool is_keyboard_shortcut = false;
1220 // Only pre-handle the key event if it's not handled by the input method.
1221 if (delegate_ && !key_event.skip_in_browser) {
1222 // We need to set |suppress_next_char_events_| to true if
1223 // PreHandleKeyboardEvent() returns true, but |this| may already be
1224 // destroyed at that time. So set |suppress_next_char_events_| true here,
1225 // then revert it afterwards when necessary.
1226 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1227 suppress_next_char_events_ = true;
1229 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1230 // a hung/malicious renderer from interfering.
1231 if (delegate_->PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut))
1232 return;
1234 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1235 suppress_next_char_events_ = false;
1238 // Don't add this key to the queue if we have no way to send the message...
1239 if (!process_->HasConnection())
1240 return;
1242 // Put all WebKeyboardEvent objects in a queue since we can't trust the
1243 // renderer and we need to give something to the HandleKeyboardEvent
1244 // handler.
1245 key_queue_.push_back(key_event);
1246 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
1248 gesture_event_filter_->FlingHasBeenHalted();
1250 // Only forward the non-native portions of our event.
1251 ForwardInputEvent(key_event, sizeof(WebKeyboardEvent),
1252 NewInputLatencyInfo(),
1253 is_keyboard_shortcut);
1257 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
1258 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
1261 int64 RenderWidgetHostImpl::GetLatencyComponentId() {
1262 return GetRoutingID() | (static_cast<int64>(GetProcess()->GetID()) << 32);
1265 // static
1266 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1267 g_check_for_pending_resize_ack = false;
1270 ui::LatencyInfo RenderWidgetHostImpl::NewInputLatencyInfo() {
1271 ui::LatencyInfo info;
1272 info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT,
1273 GetLatencyComponentId(),
1274 ++last_input_number_);
1275 return info;
1278 void RenderWidgetHostImpl::SendInputEvent(const WebInputEvent& input_event,
1279 int event_size,
1280 const ui::LatencyInfo& latency_info,
1281 bool is_keyboard_shortcut) {
1282 input_event_start_time_ = TimeTicks::Now();
1283 Send(new InputMsg_HandleInputEvent(
1284 routing_id_, &input_event, latency_info, is_keyboard_shortcut));
1285 increment_in_flight_event_count();
1288 void RenderWidgetHostImpl::ForwardInputEvent(
1289 const WebInputEvent& input_event, int event_size,
1290 const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut) {
1291 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardInputEvent");
1293 if (!process_->HasConnection())
1294 return;
1296 DCHECK(!process_->IgnoreInputEvents());
1298 if (overscroll_controller_.get() &&
1299 !overscroll_controller_->WillDispatchEvent(input_event, latency_info)) {
1300 if (input_event.type == WebKit::WebInputEvent::MouseMove) {
1301 // Since this mouse-move event has been consumed, there will be no ACKs.
1302 // So reset the state here so that future mouse-move events do reach the
1303 // renderer.
1304 mouse_move_pending_ = false;
1305 } else if (input_event.type == WebKit::WebInputEvent::MouseWheel) {
1306 // Reset the wheel-event state when appropriate.
1307 mouse_wheel_pending_ = false;
1308 } else if (WebInputEvent::isGestureEventType(input_event.type) &&
1309 gesture_event_filter_->HasQueuedGestureEvents()) {
1310 // If the gesture-event filter has queued gesture events, that implies it
1311 // is awaiting an ack for the event. Since the event is being consumed by
1312 // the over scroll here, it is never sent to the renderer, and so it won't
1313 // receive any ACKs. So send the ACK to the gesture event filter
1314 // immediately, and mark it as having been processed.
1315 gesture_event_filter_->ProcessGestureAck(true, input_event.type);
1316 } else if (WebInputEvent::isTouchEventType(input_event.type)) {
1317 // During an overscroll gesture initiated by touch-scrolling, the
1318 // touch-events do not reset or contribute to the overscroll gesture.
1319 // However, the touch-events are not sent to the renderer. So send and ACK
1320 // to the touch-event queue immediately. Mark the event as not processed,
1321 // to make sure that the touch-scroll gesture that initiated the
1322 // overscroll is updated properly.
1323 touch_event_queue_->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
1325 return;
1328 // Transmit any pending wheel events on a non-wheel event. This ensures that
1329 // the renderer receives the final PhaseEnded wheel event, which is necessary
1330 // to terminate rubber-banding, for example.
1331 if (input_event.type != WebInputEvent::MouseWheel) {
1332 for (size_t i = 0; i < coalesced_mouse_wheel_events_.size(); ++i) {
1333 SendInputEvent(coalesced_mouse_wheel_events_[i].event,
1334 sizeof(WebMouseWheelEvent),
1335 coalesced_mouse_wheel_events_[i].latency,
1336 false);
1338 coalesced_mouse_wheel_events_.clear();
1341 if (view_) {
1342 // Perform optional, synchronous event handling, sending ACK messages for
1343 // processed events, or proceeding as usual.
1344 InputEventAckState filter_ack = view_->FilterInputEvent(input_event);
1345 switch (filter_ack) {
1346 // Send the ACK and early exit.
1347 case INPUT_EVENT_ACK_STATE_CONSUMED:
1348 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
1349 next_mouse_move_.reset();
1350 OnInputEventAck(input_event.type, filter_ack);
1351 // WARNING: |this| may be deleted at this point.
1352 return;
1354 // Proceed as normal.
1355 case INPUT_EVENT_ACK_STATE_UNKNOWN:
1356 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
1357 default:
1358 break;
1362 SendInputEvent(input_event, event_size, latency_info, is_keyboard_shortcut);
1364 // Any input event cancels a pending mouse move event. Note that
1365 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event|
1366 // after this line.
1367 next_mouse_move_.reset();
1369 StartHangMonitorTimeout(
1370 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
1373 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1374 const WebKit::WebTouchEvent& touch_event,
1375 const ui::LatencyInfo& ui_latency) {
1376 ui::LatencyInfo latency_info = NewInputLatencyInfo();
1377 latency_info.MergeWith(ui_latency);
1378 TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
1379 touch_event_queue_->QueueEvent(touch_with_latency);
1382 void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener* listener) {
1383 keyboard_listeners_.AddObserver(listener);
1386 void RenderWidgetHostImpl::RemoveKeyboardListener(
1387 KeyboardListener* listener) {
1388 // Ensure that the element is actually an observer.
1389 DCHECK(keyboard_listeners_.HasObserver(listener));
1390 keyboard_listeners_.RemoveObserver(listener);
1393 void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
1394 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1395 if (GetView())
1396 static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
1397 else
1398 RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
1401 const NativeWebKeyboardEvent*
1402 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1403 if (key_queue_.empty())
1404 return NULL;
1405 return &key_queue_.front();
1408 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1409 // The resize message (which may not happen immediately) will carry with it
1410 // the screen info as well as the new size (if the screen has changed scale
1411 // factor).
1412 screen_info_.reset();
1413 screen_info_out_of_date_ = true;
1414 WasResized();
1417 void RenderWidgetHostImpl::GetSnapshotFromRenderer(
1418 const gfx::Rect& src_subrect,
1419 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1420 TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
1421 pending_snapshots_.push(callback);
1423 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
1424 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
1426 gfx::Rect copy_rect_in_pixel = ConvertViewRectToPixel(view_, copy_rect);
1427 Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel));
1430 void RenderWidgetHostImpl::OnSnapshot(bool success,
1431 const SkBitmap& bitmap) {
1432 if (pending_snapshots_.size() == 0) {
1433 LOG(ERROR) << "RenderWidgetHostImpl::OnSnapshot: "
1434 "Received a snapshot that was not requested.";
1435 return;
1438 base::Callback<void(bool, const SkBitmap&)> callback =
1439 pending_snapshots_.front();
1440 pending_snapshots_.pop();
1442 if (!success) {
1443 callback.Run(success, SkBitmap());
1444 return;
1447 callback.Run(success, bitmap);
1450 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase,
1451 base::TimeDelta interval) {
1452 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase, interval));
1455 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
1456 int exit_code) {
1457 // Clearing this flag causes us to re-create the renderer when recovering
1458 // from a crashed renderer.
1459 renderer_initialized_ = false;
1461 waiting_for_screen_rects_ack_ = false;
1463 // Must reset these to ensure that mouse move/wheel events work with a new
1464 // renderer.
1465 mouse_move_pending_ = false;
1466 next_mouse_move_.reset();
1467 mouse_wheel_pending_ = false;
1468 coalesced_mouse_wheel_events_.clear();
1470 // Must reset these to ensure that SelectRange works with a new renderer.
1471 select_range_pending_ = false;
1472 next_selection_range_.reset();
1474 // Must reset these to ensure that MoveCaret works with a new renderer.
1475 move_caret_pending_ = false;
1476 next_move_caret_.reset();
1478 touch_event_queue_->Reset();
1480 // Must reset these to ensure that gesture events work with a new renderer.
1481 gesture_event_filter_->Reset();
1483 if (overscroll_controller_)
1484 overscroll_controller_->Reset();
1486 // Must reset these to ensure that keyboard events work with a new renderer.
1487 key_queue_.clear();
1488 suppress_next_char_events_ = false;
1490 // Reset some fields in preparation for recovering from a crash.
1491 ResetSizeAndRepaintPendingFlags();
1492 current_size_.SetSize(0, 0);
1493 is_hidden_ = false;
1494 is_accelerated_compositing_active_ = false;
1496 // Reset this to ensure the hung renderer mechanism is working properly.
1497 in_flight_event_count_ = 0;
1499 if (view_) {
1500 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_,
1501 gfx::GLSurfaceHandle());
1502 view_->RenderViewGone(status, exit_code);
1503 view_ = NULL; // The View should be deleted by RenderViewGone.
1506 BackingStoreManager::RemoveBackingStore(this);
1509 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction) {
1510 text_direction_updated_ = true;
1511 text_direction_ = direction;
1514 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1515 if (text_direction_updated_)
1516 text_direction_canceled_ = true;
1519 void RenderWidgetHostImpl::NotifyTextDirection() {
1520 if (text_direction_updated_) {
1521 if (!text_direction_canceled_)
1522 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_));
1523 text_direction_updated_ = false;
1524 text_direction_canceled_ = false;
1528 void RenderWidgetHostImpl::SetInputMethodActive(bool activate) {
1529 input_method_active_ = activate;
1530 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate));
1533 void RenderWidgetHostImpl::ImeSetComposition(
1534 const string16& text,
1535 const std::vector<WebKit::WebCompositionUnderline>& underlines,
1536 int selection_start,
1537 int selection_end) {
1538 Send(new ViewMsg_ImeSetComposition(
1539 GetRoutingID(), text, underlines, selection_start, selection_end));
1542 void RenderWidgetHostImpl::ImeConfirmComposition(const string16& text) {
1543 ImeConfirmComposition(text, ui::Range::InvalidRange());
1546 void RenderWidgetHostImpl::ImeConfirmComposition(
1547 const string16& text, const ui::Range& replacement_range) {
1548 Send(new ViewMsg_ImeConfirmComposition(
1549 GetRoutingID(), text, replacement_range));
1552 void RenderWidgetHostImpl::ImeConfirmComposition() {
1553 ImeConfirmComposition(string16());
1556 void RenderWidgetHostImpl::ImeCancelComposition() {
1557 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(),
1558 std::vector<WebKit::WebCompositionUnderline>(), 0, 0));
1561 void RenderWidgetHostImpl::ExtendSelectionAndDelete(
1562 size_t before,
1563 size_t after) {
1564 Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before, after));
1567 gfx::Rect RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1568 return gfx::Rect();
1571 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture,
1572 bool last_unlocked_by_target) {
1573 // Directly reject to lock the mouse. Subclass can override this method to
1574 // decide whether to allow mouse lock or not.
1575 GotResponseToLockMouseRequest(false);
1578 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1579 DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
1580 if (pending_mouse_lock_request_) {
1581 pending_mouse_lock_request_ = false;
1582 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1583 } else if (IsMouseLocked()) {
1584 view_->UnlockMouse();
1588 bool RenderWidgetHostImpl::IsMouseLocked() const {
1589 return view_ ? view_->IsMouseLocked() : false;
1592 bool RenderWidgetHostImpl::IsFullscreen() const {
1593 return false;
1596 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
1597 should_auto_resize_ = enable;
1600 bool RenderWidgetHostImpl::IsInOverscrollGesture() const {
1601 return overscroll_controller_.get() &&
1602 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE;
1605 void RenderWidgetHostImpl::Destroy() {
1606 NotificationService::current()->Notify(
1607 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1608 Source<RenderWidgetHost>(this),
1609 NotificationService::NoDetails());
1611 // Tell the view to die.
1612 // Note that in the process of the view shutting down, it can call a ton
1613 // of other messages on us. So if you do any other deinitialization here,
1614 // do it after this call to view_->Destroy().
1615 if (view_)
1616 view_->Destroy();
1618 delete this;
1621 void RenderWidgetHostImpl::CheckRendererIsUnresponsive() {
1622 // If we received a call to StopHangMonitorTimeout.
1623 if (time_when_considered_hung_.is_null())
1624 return;
1626 // If we have not waited long enough, then wait some more.
1627 Time now = Time::Now();
1628 if (now < time_when_considered_hung_) {
1629 StartHangMonitorTimeout(time_when_considered_hung_ - now);
1630 return;
1633 // OK, looks like we have a hung renderer!
1634 NotificationService::current()->Notify(
1635 NOTIFICATION_RENDERER_PROCESS_HANG,
1636 Source<RenderWidgetHost>(this),
1637 NotificationService::NoDetails());
1638 is_unresponsive_ = true;
1639 NotifyRendererUnresponsive();
1642 void RenderWidgetHostImpl::RendererIsResponsive() {
1643 if (is_unresponsive_) {
1644 is_unresponsive_ = false;
1645 NotifyRendererResponsive();
1649 void RenderWidgetHostImpl::OnRenderViewReady() {
1650 SendScreenRects();
1651 WasResized();
1654 void RenderWidgetHostImpl::OnRenderViewGone(int status, int exit_code) {
1655 // TODO(evanm): This synchronously ends up calling "delete this".
1656 // Is that really what we want in response to this message? I'm matching
1657 // previous behavior of the code here.
1658 Destroy();
1661 void RenderWidgetHostImpl::OnClose() {
1662 Shutdown();
1665 void RenderWidgetHostImpl::OnSetTooltipText(
1666 const string16& tooltip_text,
1667 WebTextDirection text_direction_hint) {
1668 // First, add directionality marks around tooltip text if necessary.
1669 // A naive solution would be to simply always wrap the text. However, on
1670 // windows, Unicode directional embedding characters can't be displayed on
1671 // systems that lack RTL fonts and are instead displayed as empty squares.
1673 // To get around this we only wrap the string when we deem it necessary i.e.
1674 // when the locale direction is different than the tooltip direction hint.
1676 // Currently, we use element's directionality as the tooltip direction hint.
1677 // An alternate solution would be to set the overall directionality based on
1678 // trying to detect the directionality from the tooltip text rather than the
1679 // element direction. One could argue that would be a preferable solution
1680 // but we use the current approach to match Fx & IE's behavior.
1681 string16 wrapped_tooltip_text = tooltip_text;
1682 if (!tooltip_text.empty()) {
1683 if (text_direction_hint == WebKit::WebTextDirectionLeftToRight) {
1684 // Force the tooltip to have LTR directionality.
1685 wrapped_tooltip_text =
1686 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
1687 } else if (text_direction_hint == WebKit::WebTextDirectionRightToLeft &&
1688 !base::i18n::IsRTL()) {
1689 // Force the tooltip to have RTL directionality.
1690 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
1693 if (GetView())
1694 view_->SetTooltipText(wrapped_tooltip_text);
1697 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1698 waiting_for_screen_rects_ack_ = false;
1699 if (!view_)
1700 return;
1702 if (view_->GetViewBounds() == last_view_screen_rect_ &&
1703 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
1704 return;
1707 SendScreenRects();
1710 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
1711 // Note that we ignore the position.
1712 if (view_) {
1713 view_->SetBounds(pos);
1714 Send(new ViewMsg_Move_ACK(routing_id_));
1718 void RenderWidgetHostImpl::OnPaintAtSizeAck(int tag, const gfx::Size& size) {
1719 std::pair<int, gfx::Size> details = std::make_pair(tag, size);
1720 NotificationService::current()->Notify(
1721 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
1722 Source<RenderWidgetHost>(this),
1723 Details<std::pair<int, gfx::Size> >(&details));
1726 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1727 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1728 TRACE_EVENT0("renderer_host",
1729 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1730 if (!view_) {
1731 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1732 ack_params.sync_point = 0;
1733 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1734 params.gpu_process_host_id,
1735 ack_params);
1736 return;
1738 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
1739 gpu_params.surface_id = params.surface_id;
1740 gpu_params.surface_handle = params.surface_handle;
1741 gpu_params.route_id = params.route_id;
1742 gpu_params.size = params.size;
1743 gpu_params.scale_factor = params.scale_factor;
1744 gpu_params.latency_info = params.latency_info;
1745 view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
1746 params.gpu_process_host_id);
1749 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1750 const IPC::Message& message) {
1751 ViewHostMsg_SwapCompositorFrame::Param param;
1752 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
1753 return false;
1754 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
1755 param.a.AssignTo(frame.get());
1757 if (view_) {
1758 view_->OnSwapCompositorFrame(frame.Pass());
1759 } else {
1760 cc::CompositorFrameAck ack;
1761 if (frame->gl_frame_data) {
1762 ack.gl_frame_data = frame->gl_frame_data.Pass();
1763 ack.gl_frame_data->sync_point = 0;
1764 } else if (frame->delegated_frame_data) {
1765 ack.resources.swap(frame->delegated_frame_data->resource_list);
1766 } else if (frame->software_frame_data) {
1767 ack.last_software_frame_id = frame->software_frame_data->id;
1769 SendSwapCompositorFrameAck(routing_id_, process_->GetID(), ack);
1771 return true;
1774 void RenderWidgetHostImpl::OnOverscrolled(
1775 gfx::Vector2dF accumulated_overscroll,
1776 gfx::Vector2dF current_fling_velocity) {
1777 if (view_)
1778 view_->OnOverscrolled(accumulated_overscroll, current_fling_velocity);
1781 void RenderWidgetHostImpl::OnUpdateRect(
1782 const ViewHostMsg_UpdateRect_Params& params) {
1783 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1784 TimeTicks paint_start = TimeTicks::Now();
1786 // Update our knowledge of the RenderWidget's size.
1787 current_size_ = params.view_size;
1788 // Update our knowledge of the RenderWidget's scroll offset.
1789 last_scroll_offset_ = params.scroll_offset;
1791 bool is_resize_ack =
1792 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1794 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1795 // that will end up reaching GetBackingStore.
1796 if (is_resize_ack) {
1797 DCHECK(!g_check_for_pending_resize_ack || resize_ack_pending_);
1798 resize_ack_pending_ = false;
1799 in_flight_size_.SetSize(0, 0);
1802 bool is_repaint_ack =
1803 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
1804 if (is_repaint_ack) {
1805 DCHECK(repaint_ack_pending_);
1806 TRACE_EVENT_ASYNC_END0(
1807 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1808 repaint_ack_pending_ = false;
1809 TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
1810 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
1813 DCHECK(!params.view_size.IsEmpty());
1815 bool was_async = false;
1817 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1818 TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
1820 // If gpu process does painting, scroll_rect and copy_rects are always empty
1821 // and backing store is never used.
1822 if (dib) {
1823 DCHECK(!params.bitmap_rect.IsEmpty());
1824 gfx::Size pixel_size = gfx::ToFlooredSize(
1825 gfx::ScaleSize(params.bitmap_rect.size(), params.scale_factor));
1826 const size_t size = pixel_size.height() * pixel_size.width() * 4;
1827 if (dib->size() < size) {
1828 DLOG(WARNING) << "Transport DIB too small for given rectangle";
1829 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
1830 GetProcess()->ReceivedBadMessage();
1831 } else {
1832 UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
1833 TRACE_EVENT_SCOPE_THREAD,
1834 "x+y", params.bitmap_rect.x() + params.bitmap_rect.y(),
1835 "color", 0xffffff & *static_cast<uint32*>(dib->memory()));
1836 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
1837 TRACE_EVENT_SCOPE_THREAD,
1838 "width", params.bitmap_rect.width());
1840 // Scroll the backing store.
1841 if (!params.scroll_rect.IsEmpty()) {
1842 ScrollBackingStoreRect(params.scroll_delta,
1843 params.scroll_rect,
1844 params.view_size);
1847 // Paint the backing store. This will update it with the
1848 // renderer-supplied bits. The view will read out of the backing store
1849 // later to actually draw to the screen.
1850 was_async = PaintBackingStoreRect(
1851 params.bitmap,
1852 params.bitmap_rect,
1853 params.copy_rects,
1854 params.view_size,
1855 params.scale_factor,
1856 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
1857 weak_factory_.GetWeakPtr(), params, paint_start));
1861 if (!was_async) {
1862 DidUpdateBackingStore(params, paint_start);
1865 if (should_auto_resize_) {
1866 bool post_callback = new_auto_size_.IsEmpty();
1867 new_auto_size_ = params.view_size;
1868 if (post_callback) {
1869 base::MessageLoop::current()->PostTask(
1870 FROM_HERE,
1871 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
1872 weak_factory_.GetWeakPtr()));
1876 // Log the time delta for processing a paint message. On platforms that don't
1877 // support asynchronous painting, this is equivalent to
1878 // MPArch.RWH_TotalPaintTime.
1879 TimeDelta delta = TimeTicks::Now() - paint_start;
1880 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
1883 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1884 if (in_get_backing_store_)
1885 abort_get_backing_store_ = true;
1888 void RenderWidgetHostImpl::DidUpdateBackingStore(
1889 const ViewHostMsg_UpdateRect_Params& params,
1890 const TimeTicks& paint_start) {
1891 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1892 TimeTicks update_start = TimeTicks::Now();
1894 if (params.needs_ack) {
1895 // ACK early so we can prefetch the next PaintRect if there is a next one.
1896 // This must be done AFTER we're done painting with the bitmap supplied by
1897 // the renderer. This ACK is a signal to the renderer that the backing store
1898 // can be re-used, so the bitmap may be invalid after this call.
1899 Send(new ViewMsg_UpdateRect_ACK(routing_id_));
1902 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1903 // will not be re-issued, so must move them now, regardless of whether we
1904 // paint or not. MovePluginWindows attempts to move the plugin windows and
1905 // in the process could dispatch other window messages which could cause the
1906 // view to be destroyed.
1907 if (view_)
1908 view_->MovePluginWindows(params.scroll_offset, params.plugin_window_moves);
1910 NotificationService::current()->Notify(
1911 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
1912 Source<RenderWidgetHost>(this),
1913 NotificationService::NoDetails());
1915 // We don't need to update the view if the view is hidden. We must do this
1916 // early return after the ACK is sent, however, or the renderer will not send
1917 // us more data.
1918 if (is_hidden_)
1919 return;
1921 // Now paint the view. Watch out: it might be destroyed already.
1922 if (view_ && !is_accelerated_compositing_active_) {
1923 view_being_painted_ = true;
1924 view_->DidUpdateBackingStore(params.scroll_rect, params.scroll_delta,
1925 params.copy_rects, params.latency_info);
1926 view_being_painted_ = false;
1929 // If we got a resize ack, then perhaps we have another resize to send?
1930 bool is_resize_ack =
1931 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1932 if (is_resize_ack)
1933 WasResized();
1935 // Log the time delta for processing a paint message.
1936 TimeTicks now = TimeTicks::Now();
1937 TimeDelta delta = now - update_start;
1938 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta);
1940 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1941 // DidUpdateBackingStore() method. On platforms which have asynchronous
1942 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1943 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1944 // waiting for the paint to complete.
1946 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1947 delta = now - paint_start;
1948 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
1949 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectComplete",
1950 TRACE_EVENT_SCOPE_THREAD,
1951 "x+y", params.bitmap_rect.x() + params.bitmap_rect.y());
1954 void RenderWidgetHostImpl::OnInputEventAck(
1955 WebInputEvent::Type event_type, InputEventAckState ack_result) {
1956 TRACE_EVENT0("input", "RenderWidgetHostImpl::OnInputEventAck");
1957 bool processed = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
1959 // Log the time delta for processing an input event.
1960 TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
1961 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta);
1963 // Cancel pending hung renderer checks since the renderer is responsive.
1964 if (decrement_in_flight_event_count() == 0)
1965 StopHangMonitorTimeout();
1967 int type = static_cast<int>(event_type);
1968 if (type < WebInputEvent::Undefined) {
1969 RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
1970 process_->ReceivedBadMessage();
1971 } else if (type == WebInputEvent::MouseMove) {
1972 mouse_move_pending_ = false;
1974 // now, we can send the next mouse move event
1975 if (next_mouse_move_) {
1976 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove);
1977 ForwardMouseEventWithLatencyInfo(*next_mouse_move_);
1979 } else if (WebInputEvent::isKeyboardEventType(type)) {
1980 ProcessKeyboardEventAck(type, processed);
1981 } else if (type == WebInputEvent::MouseWheel) {
1982 ProcessWheelAck(processed);
1983 } else if (WebInputEvent::isTouchEventType(type)) {
1984 ProcessTouchAck(ack_result);
1985 } else if (WebInputEvent::isGestureEventType(type)) {
1986 ProcessGestureAck(processed, type);
1989 // WARNING: |this| may be deleted at this point.
1991 // This is used only for testing, and the other end does not use the
1992 // source object. On linux, specifying
1993 // Source<RenderWidgetHost> results in a very strange
1994 // runtime error in the epilogue of the enclosing
1995 // (OnInputEventAck) method, but not on other platforms; using
1996 // 'void' instead is just as safe (since NotificationSource
1997 // is not actually typesafe) and avoids this error.
1998 NotificationService::current()->Notify(
1999 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
2000 Source<void>(this),
2001 Details<int>(&type));
2004 void RenderWidgetHostImpl::OnBeginSmoothScroll(
2005 const ViewHostMsg_BeginSmoothScroll_Params& params) {
2006 if (!view_)
2007 return;
2008 smooth_scroll_gesture_controller_.BeginSmoothScroll(view_, params);
2011 void RenderWidgetHostImpl::OnSelectRangeAck() {
2012 select_range_pending_ = false;
2013 if (next_selection_range_) {
2014 scoped_ptr<SelectionRange> next(next_selection_range_.Pass());
2015 SelectRange(next->start, next->end);
2019 void RenderWidgetHostImpl::OnMsgMoveCaretAck() {
2020 move_caret_pending_ = false;
2021 if (next_move_caret_) {
2022 scoped_ptr<gfx::Point> next(next_move_caret_.Pass());
2023 MoveCaret(*next);
2027 void RenderWidgetHostImpl::ProcessWheelAck(bool processed) {
2028 mouse_wheel_pending_ = false;
2030 if (overscroll_controller_)
2031 overscroll_controller_->ReceivedEventACK(current_wheel_event_, processed);
2033 // Process the unhandled wheel event here before calling
2034 // ForwardWheelEventWithLatencyInfo() since it will mutate
2035 // current_wheel_event_.
2036 if (!processed && !is_hidden_ && view_)
2037 view_->UnhandledWheelEvent(current_wheel_event_);
2039 // Now send the next (coalesced) mouse wheel event.
2040 if (!coalesced_mouse_wheel_events_.empty()) {
2041 MouseWheelEventWithLatencyInfo next_wheel_event =
2042 coalesced_mouse_wheel_events_.front();
2043 coalesced_mouse_wheel_events_.pop_front();
2044 ForwardWheelEventWithLatencyInfo(next_wheel_event.event,
2045 next_wheel_event.latency);
2049 void RenderWidgetHostImpl::ProcessGestureAck(bool processed, int type) {
2050 if (overscroll_controller_) {
2051 overscroll_controller_->ReceivedEventACK(
2052 gesture_event_filter_->GetGestureEventAwaitingAck(), processed);
2054 gesture_event_filter_->ProcessGestureAck(processed, type);
2056 if (view_)
2057 view_->GestureEventAck(type);
2060 void RenderWidgetHostImpl::ProcessTouchAck(InputEventAckState ack_result) {
2061 touch_event_queue_->ProcessTouchAck(ack_result);
2064 void RenderWidgetHostImpl::OnFocus() {
2065 // Only RenderViewHost can deal with that message.
2066 RecordAction(UserMetricsAction("BadMessageTerminate_RWH4"));
2067 GetProcess()->ReceivedBadMessage();
2070 void RenderWidgetHostImpl::OnBlur() {
2071 // Only RenderViewHost can deal with that message.
2072 RecordAction(UserMetricsAction("BadMessageTerminate_RWH5"));
2073 GetProcess()->ReceivedBadMessage();
2076 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
2077 if (has_touch_handler_ == has_handlers)
2078 return;
2079 has_touch_handler_ = has_handlers;
2080 if (!has_touch_handler_)
2081 touch_event_queue_->FlushQueue();
2082 #if defined(OS_ANDROID)
2083 if (view_)
2084 view_->HasTouchEventHandlers(has_touch_handler_);
2085 #endif
2088 void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
2089 if (!view_) {
2090 return;
2092 view_->UpdateCursor(cursor);
2095 void RenderWidgetHostImpl::OnTextInputTypeChanged(ui::TextInputType type,
2096 bool can_compose_inline) {
2097 if (view_)
2098 view_->TextInputTypeChanged(type, can_compose_inline);
2101 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
2102 const ui::Range& range,
2103 const std::vector<gfx::Rect>& character_bounds) {
2104 if (view_)
2105 view_->ImeCompositionRangeChanged(range, character_bounds);
2108 void RenderWidgetHostImpl::OnImeCancelComposition() {
2109 if (view_)
2110 view_->ImeCancelComposition();
2113 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated) {
2114 TRACE_EVENT1("renderer_host",
2115 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
2116 "activated", activated);
2117 is_accelerated_compositing_active_ = activated;
2118 if (view_)
2119 view_->OnAcceleratedCompositingStateChange();
2122 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
2123 bool last_unlocked_by_target,
2124 bool privileged) {
2126 if (pending_mouse_lock_request_) {
2127 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2128 return;
2129 } else if (IsMouseLocked()) {
2130 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2131 return;
2134 pending_mouse_lock_request_ = true;
2135 if (privileged && allow_privileged_mouse_lock_) {
2136 // Directly approve to lock the mouse.
2137 GotResponseToLockMouseRequest(true);
2138 } else {
2139 RequestToLockMouse(user_gesture, last_unlocked_by_target);
2143 void RenderWidgetHostImpl::OnUnlockMouse() {
2144 RejectMouseLockOrUnlockIfNecessary();
2147 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
2148 const gfx::Rect& rect,
2149 const gfx::Size& size,
2150 const TransportDIB::Id& id) {
2151 DCHECK(!rect.IsEmpty());
2152 DCHECK(!size.IsEmpty());
2154 TransportDIB* dib = process_->GetTransportDIB(id);
2155 DCHECK(dib->memory());
2156 DCHECK(dib->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config,
2157 size.width(), size.height()));
2159 SkBitmap zoomed_bitmap;
2160 zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
2161 size.width(), size.height());
2162 zoomed_bitmap.setPixels(dib->memory());
2164 #if defined(OS_ANDROID)
2165 if (view_)
2166 view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
2167 #else
2168 NOTIMPLEMENTED();
2169 #endif
2171 zoomed_bitmap.setPixels(0);
2172 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
2173 dib->handle()));
2176 #if defined(OS_WIN)
2177 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
2178 gfx::NativeViewId dummy_activation_window) {
2179 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
2180 if (!IsWindow(hwnd) ||
2181 !WebPluginDelegateImpl::IsDummyActivationWindow(hwnd)) {
2182 // This may happen as a result of a race condition when the plugin is going
2183 // away.
2184 return;
2187 SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
2188 dummy_windows_for_activation_.push_back(hwnd);
2191 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
2192 gfx::NativeViewId dummy_activation_window) {
2193 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
2194 std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
2195 for (; i != dummy_windows_for_activation_.end(); ++i) {
2196 if ((*i) == hwnd) {
2197 dummy_windows_for_activation_.erase(i);
2198 return;
2201 NOTREACHED() << "Unknown dummy window";
2203 #endif
2205 bool RenderWidgetHostImpl::PaintBackingStoreRect(
2206 TransportDIB::Id bitmap,
2207 const gfx::Rect& bitmap_rect,
2208 const std::vector<gfx::Rect>& copy_rects,
2209 const gfx::Size& view_size,
2210 float scale_factor,
2211 const base::Closure& completion_callback) {
2212 // The view may be destroyed already.
2213 if (!view_)
2214 return false;
2216 if (is_hidden_) {
2217 // Don't bother updating the backing store when we're hidden. Just mark it
2218 // as being totally invalid. This will cause a complete repaint when the
2219 // view is restored.
2220 needs_repainting_on_restore_ = true;
2221 return false;
2224 bool needs_full_paint = false;
2225 bool scheduled_completion_callback = false;
2226 BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
2227 copy_rects, scale_factor,
2228 completion_callback,
2229 &needs_full_paint,
2230 &scheduled_completion_callback);
2231 if (needs_full_paint) {
2232 repaint_start_time_ = TimeTicks::Now();
2233 DCHECK(!repaint_ack_pending_);
2234 repaint_ack_pending_ = true;
2235 TRACE_EVENT_ASYNC_BEGIN0(
2236 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
2237 Send(new ViewMsg_Repaint(routing_id_, view_size));
2240 return scheduled_completion_callback;
2243 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta,
2244 const gfx::Rect& clip_rect,
2245 const gfx::Size& view_size) {
2246 if (is_hidden_) {
2247 // Don't bother updating the backing store when we're hidden. Just mark it
2248 // as being totally invalid. This will cause a complete repaint when the
2249 // view is restored.
2250 needs_repainting_on_restore_ = true;
2251 return;
2254 // TODO(darin): do we need to do something else if our backing store is not
2255 // the same size as the advertised view? maybe we just assume there is a
2256 // full paint on its way?
2257 BackingStore* backing_store = BackingStoreManager::Lookup(this);
2258 if (!backing_store || (backing_store->size() != view_size))
2259 return;
2260 backing_store->ScrollBackingStore(delta, clip_rect, view_size);
2263 void RenderWidgetHostImpl::Replace(const string16& word) {
2264 Send(new InputMsg_Replace(routing_id_, word));
2267 void RenderWidgetHostImpl::ReplaceMisspelling(const string16& word) {
2268 Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
2271 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
2272 ignore_input_events_ = ignore_input_events;
2275 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
2276 const NativeWebKeyboardEvent& event) {
2277 if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
2278 return false;
2280 ObserverList<KeyboardListener>::Iterator it(keyboard_listeners_);
2281 KeyboardListener* listener;
2282 while ((listener = it.GetNext()) != NULL) {
2283 if (listener->HandleKeyPressEvent(event))
2284 return true;
2287 return false;
2290 void RenderWidgetHostImpl::ProcessKeyboardEventAck(int type, bool processed) {
2291 if (key_queue_.empty()) {
2292 LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
2293 << "don't seem to have sent it to the renderer!";
2294 } else if (key_queue_.front().type != type) {
2295 LOG(ERROR) << "We seem to have a different key type sent from "
2296 << "the renderer. (" << key_queue_.front().type << " vs. "
2297 << type << "). Ignoring event.";
2299 // Something must be wrong. Clear the |key_queue_| and
2300 // |suppress_next_char_events_| so that we can resume from the error.
2301 key_queue_.clear();
2302 suppress_next_char_events_ = false;
2303 } else {
2304 NativeWebKeyboardEvent front_item = key_queue_.front();
2305 key_queue_.pop_front();
2307 #if defined(OS_MACOSX)
2308 if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item))
2309 return;
2310 #endif
2312 // We only send unprocessed key event upwards if we are not hidden,
2313 // because the user has moved away from us and no longer expect any effect
2314 // of this key event.
2315 if (delegate_ && !processed && !is_hidden_ && !front_item.skip_in_browser) {
2316 delegate_->HandleKeyboardEvent(front_item);
2318 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2319 // (i.e. in the case of Ctrl+W, where the call to
2320 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2325 const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
2326 return last_scroll_offset_;
2329 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2330 // Always send a touch event if the renderer has a touch-event handler. It is
2331 // possible that a renderer stops listening to touch-events while there are
2332 // still events in the touch-queue. In such cases, the new events should still
2333 // get into the queue.
2334 return has_touch_handler_ || !touch_event_queue_->empty();
2337 void RenderWidgetHostImpl::StartUserGesture() {
2338 OnUserGesture();
2341 void RenderWidgetHostImpl::Stop() {
2342 Send(new ViewMsg_Stop(GetRoutingID()));
2345 void RenderWidgetHostImpl::SetBackground(const SkBitmap& background) {
2346 Send(new ViewMsg_SetBackground(GetRoutingID(), background));
2349 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2350 const std::vector<EditCommand>& commands) {
2351 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
2354 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
2355 accessibility_mode_ = mode;
2356 Send(new ViewMsg_SetAccessibilityMode(routing_id_, mode));
2359 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
2360 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
2363 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id) {
2364 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id));
2367 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2368 int acc_obj_id, gfx::Rect subfocus) {
2369 Send(new AccessibilityMsg_ScrollToMakeVisible(
2370 GetRoutingID(), acc_obj_id, subfocus));
2373 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2374 int acc_obj_id, gfx::Point point) {
2375 Send(new AccessibilityMsg_ScrollToPoint(
2376 GetRoutingID(), acc_obj_id, point));
2379 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2380 int object_id, int start_offset, int end_offset) {
2381 Send(new AccessibilityMsg_SetTextSelection(
2382 GetRoutingID(), object_id, start_offset, end_offset));
2385 void RenderWidgetHostImpl::FatalAccessibilityTreeError() {
2386 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2389 #if defined(OS_WIN) && defined(USE_AURA)
2390 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2391 gfx::NativeViewAccessible accessible_parent) {
2392 if (view_)
2393 view_->SetParentNativeViewAccessible(accessible_parent);
2396 gfx::NativeViewAccessible
2397 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2398 return delegate_->GetParentNativeViewAccessible();
2400 #endif
2402 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
2403 const std::string& value) {
2404 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
2407 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2408 const gfx::Rect& rect) {
2409 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
2412 void RenderWidgetHostImpl::SelectRange(const gfx::Point& start,
2413 const gfx::Point& end) {
2414 if (select_range_pending_) {
2415 if (!next_selection_range_) {
2416 next_selection_range_.reset(new SelectionRange());
2418 next_selection_range_->start = start;
2419 next_selection_range_->end = end;
2420 return;
2423 select_range_pending_ = true;
2424 Send(new InputMsg_SelectRange(GetRoutingID(), start, end));
2427 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
2428 if (move_caret_pending_) {
2429 next_move_caret_.reset(new gfx::Point(point));
2430 return;
2433 move_caret_pending_ = true;
2434 Send(new InputMsg_MoveCaret(GetRoutingID(), point));
2437 void RenderWidgetHostImpl::Undo() {
2438 Send(new InputMsg_Undo(GetRoutingID()));
2439 RecordAction(UserMetricsAction("Undo"));
2442 void RenderWidgetHostImpl::Redo() {
2443 Send(new InputMsg_Redo(GetRoutingID()));
2444 RecordAction(UserMetricsAction("Redo"));
2447 void RenderWidgetHostImpl::Cut() {
2448 Send(new InputMsg_Cut(GetRoutingID()));
2449 RecordAction(UserMetricsAction("Cut"));
2452 void RenderWidgetHostImpl::Copy() {
2453 Send(new InputMsg_Copy(GetRoutingID()));
2454 RecordAction(UserMetricsAction("Copy"));
2457 void RenderWidgetHostImpl::CopyToFindPboard() {
2458 #if defined(OS_MACOSX)
2459 // Windows/Linux don't have the concept of a find pasteboard.
2460 Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
2461 RecordAction(UserMetricsAction("CopyToFindPboard"));
2462 #endif
2465 void RenderWidgetHostImpl::Paste() {
2466 Send(new InputMsg_Paste(GetRoutingID()));
2467 RecordAction(UserMetricsAction("Paste"));
2470 void RenderWidgetHostImpl::PasteAndMatchStyle() {
2471 Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
2472 RecordAction(UserMetricsAction("PasteAndMatchStyle"));
2475 void RenderWidgetHostImpl::Delete() {
2476 Send(new InputMsg_Delete(GetRoutingID()));
2477 RecordAction(UserMetricsAction("DeleteSelection"));
2480 void RenderWidgetHostImpl::SelectAll() {
2481 Send(new InputMsg_SelectAll(GetRoutingID()));
2482 RecordAction(UserMetricsAction("SelectAll"));
2485 void RenderWidgetHostImpl::Unselect() {
2486 Send(new InputMsg_Unselect(GetRoutingID()));
2487 RecordAction(UserMetricsAction("Unselect"));
2490 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
2491 if (!allowed) {
2492 RejectMouseLockOrUnlockIfNecessary();
2493 return false;
2494 } else {
2495 if (!pending_mouse_lock_request_) {
2496 // This is possible, e.g., the plugin sends us an unlock request before
2497 // the user allows to lock to mouse.
2498 return false;
2501 pending_mouse_lock_request_ = false;
2502 if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
2503 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2504 return false;
2505 } else {
2506 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2507 return true;
2512 // static
2513 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2514 int32 route_id, int gpu_host_id,
2515 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
2516 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
2517 if (ui_shim) {
2518 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
2519 params));
2523 // static
2524 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2525 int32 route_id, int renderer_host_id, const cc::CompositorFrameAck& ack) {
2526 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2527 if (host)
2528 host->Send(new ViewMsg_SwapCompositorFrameAck(route_id, ack));
2531 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2532 if (!is_threaded_compositing_enabled_)
2533 Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
2536 #if defined(USE_AURA)
2538 void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent) {
2539 #if defined(OS_WIN)
2540 HWND hwnd = reinterpret_cast<HWND>(new_parent);
2541 if (!hwnd)
2542 hwnd = WebPluginDelegateImpl::GetDefaultWindowParent();
2543 for (std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
2544 i != dummy_windows_for_activation_.end(); ++i) {
2545 SetParent(*i, hwnd);
2547 #endif
2550 #endif
2552 void RenderWidgetHostImpl::DelayedAutoResized() {
2553 gfx::Size new_size = new_auto_size_;
2554 // Clear the new_auto_size_ since the empty value is used as a flag to
2555 // indicate that no callback is in progress (i.e. without this line
2556 // DelayedAutoResized will not get called again).
2557 new_auto_size_.SetSize(0, 0);
2558 if (!should_auto_resize_)
2559 return;
2561 OnRenderAutoResized(new_size);
2564 void RenderWidgetHostImpl::DetachDelegate() {
2565 delegate_ = NULL;
2568 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
2569 ui::LatencyInfo::LatencyMap::const_iterator l =
2570 latency_info.latency_components.find(std::make_pair(
2571 ui::INPUT_EVENT_LATENCY_RWH_COMPONENT, GetLatencyComponentId()));
2572 if (l == latency_info.latency_components.end())
2573 return;
2575 rendering_stats_.input_event_count += l->second.event_count;
2576 rendering_stats_.total_input_latency +=
2577 l->second.event_count *
2578 (latency_info.swap_timestamp - l->second.event_time);
2580 if (CommandLine::ForCurrentProcess()->HasSwitch(
2581 switches::kEnableGpuBenchmarking))
2582 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_, rendering_stats_));
2585 // static
2586 void RenderWidgetHostImpl::CompositorFrameDrawn(
2587 const ui::LatencyInfo& latency_info) {
2588 for (ui::LatencyInfo::LatencyMap::const_iterator b =
2589 latency_info.latency_components.begin();
2590 b != latency_info.latency_components.end();
2591 ++b) {
2592 if (b->first.first != ui::INPUT_EVENT_LATENCY_RWH_COMPONENT)
2593 continue;
2594 // Matches with GetLatencyComponentId
2595 int routing_id = b->first.second & 0xffffffff;
2596 int process_id = (b->first.second >> 32) & 0xffffffff;
2597 RenderWidgetHost* rwh =
2598 RenderWidgetHost::FromID(process_id, routing_id);
2599 if (!rwh)
2600 continue;
2601 RenderWidgetHostImpl::From(rwh)->FrameSwapped(latency_info);
2605 } // namespace content