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"
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/debug/trace_event.h"
14 #include "base/i18n/rtl.h"
15 #include "base/message_loop.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram.h"
18 #include "base/string_number_conversions.h"
19 #include "base/utf_string_conversions.h"
20 #include "content/browser/gpu/gpu_process_host.h"
21 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
22 #include "content/browser/gpu/gpu_surface_tracker.h"
23 #include "content/browser/renderer_host/backing_store.h"
24 #include "content/browser/renderer_host/backing_store_manager.h"
25 #include "content/browser/renderer_host/gesture_event_filter.h"
26 #include "content/browser/renderer_host/overscroll_controller.h"
27 #include "content/browser/renderer_host/render_process_host_impl.h"
28 #include "content/browser/renderer_host/render_view_host_impl.h"
29 #include "content/browser/renderer_host/render_widget_helper.h"
30 #include "content/browser/renderer_host/render_widget_host_delegate.h"
31 #include "content/browser/renderer_host/tap_suppression_controller.h"
32 #include "content/browser/renderer_host/touch_event_queue.h"
33 #include "content/common/accessibility_messages.h"
34 #include "content/common/gpu/gpu_messages.h"
35 #include "content/common/view_messages.h"
36 #include "content/port/browser/render_widget_host_view_port.h"
37 #include "content/port/browser/smooth_scroll_gesture.h"
38 #include "content/public/browser/compositor_util.h"
39 #include "content/public/browser/native_web_keyboard_event.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/notification_types.h"
42 #include "content/public/browser/user_metrics.h"
43 #include "content/public/common/content_constants.h"
44 #include "content/public/common/content_switches.h"
45 #include "content/public/common/result_codes.h"
46 #include "skia/ext/image_operations.h"
47 #include "skia/ext/platform_canvas.h"
48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
50 #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
52 #include "ui/base/events/event.h"
53 #include "ui/base/keycodes/keyboard_codes.h"
54 #include "ui/gfx/size_conversions.h"
55 #include "ui/gfx/skbitmap_operations.h"
56 #include "webkit/glue/webcursor.h"
57 #include "webkit/glue/webpreferences.h"
58 #include "webkit/plugins/npapi/webplugin.h"
59 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
61 #if defined(TOOLKIT_GTK)
62 #include "content/browser/renderer_host/backing_store_gtk.h"
63 #elif defined(OS_MACOSX)
64 #include "content/browser/renderer_host/backing_store_mac.h"
68 using base::TimeDelta
;
69 using base::TimeTicks
;
70 using webkit::npapi::WebPluginDelegateImpl
;
71 using WebKit::WebGestureEvent
;
72 using WebKit::WebInputEvent
;
73 using WebKit::WebKeyboardEvent
;
74 using WebKit::WebMouseEvent
;
75 using WebKit::WebMouseWheelEvent
;
76 using WebKit::WebTextDirection
;
81 // How long to (synchronously) wait for the renderer to respond with a
82 // PaintRect message, when our backing-store is invalid, before giving up and
83 // returning a null or incorrectly sized backing-store from GetBackingStore.
84 // This timeout impacts the "choppiness" of our window resize perf.
85 const int kPaintMsgTimeoutMS
= 50;
87 // How long to wait before we consider a renderer hung.
88 const int kHungRendererDelayMs
= 30000;
90 // How many milliseconds apart synthetic scroll messages should be sent.
91 static const int kSyntheticScrollMessageIntervalMs
= 8;
93 // Returns |true| if the two wheel events should be coalesced.
94 bool ShouldCoalesceMouseWheelEvents(const WebMouseWheelEvent
& last_event
,
95 const WebMouseWheelEvent
& new_event
) {
96 return last_event
.modifiers
== new_event
.modifiers
&&
97 last_event
.scrollByPage
== new_event
.scrollByPage
&&
98 last_event
.hasPreciseScrollingDeltas
99 == new_event
.hasPreciseScrollingDeltas
&&
100 last_event
.phase
== new_event
.phase
&&
101 last_event
.momentumPhase
== new_event
.momentumPhase
;
108 void RenderWidgetHost::RemoveAllBackingStores() {
109 BackingStoreManager::RemoveAllBackingStores();
113 size_t RenderWidgetHost::BackingStoreMemorySize() {
114 return BackingStoreManager::MemorySize();
117 ///////////////////////////////////////////////////////////////////////////////
118 // RenderWidgetHostImpl
120 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate
* delegate
,
121 RenderProcessHost
* process
,
124 renderer_initialized_(false),
125 hung_renderer_delay_ms_(kHungRendererDelayMs
),
128 routing_id_(routing_id
),
132 is_fullscreen_(false),
133 is_accelerated_compositing_active_(false),
134 repaint_ack_pending_(false),
135 resize_ack_pending_(false),
136 should_auto_resize_(false),
137 waiting_for_screen_rects_ack_(false),
138 mouse_move_pending_(false),
139 mouse_wheel_pending_(false),
140 select_range_pending_(false),
141 needs_repainting_on_restore_(false),
142 is_unresponsive_(false),
143 in_flight_event_count_(0),
144 in_get_backing_store_(false),
145 abort_get_backing_store_(false),
146 view_being_painted_(false),
147 ignore_input_events_(false),
148 text_direction_updated_(false),
149 text_direction_(WebKit::WebTextDirectionLeftToRight
),
150 text_direction_canceled_(false),
151 suppress_next_char_events_(false),
152 pending_mouse_lock_request_(false),
153 allow_privileged_mouse_lock_(false),
154 has_touch_handler_(false),
155 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
156 tick_active_smooth_scroll_gestures_task_posted_(false),
157 touch_event_queue_(new TouchEventQueue(this)),
158 gesture_event_filter_(new GestureEventFilter(this)) {
160 if (routing_id_
== MSG_ROUTING_NONE
) {
161 routing_id_
= process_
->GetNextRoutingID();
162 surface_id_
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
166 // TODO(piman): This is a O(N) lookup, where we could forward the
167 // information from the RenderWidgetHelper. The problem is that doing so
168 // currently leaks outside of content all the way to chrome classes, and
169 // would be a layering violation. Since we don't expect more than a few
170 // hundreds of RWH, this seems acceptable. Revisit if performance become a
171 // problem, for example by tracking in the RenderWidgetHelper the routing id
172 // (and surface id) that have been created, but whose RWH haven't yet.
173 surface_id_
= GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
179 is_threaded_compositing_enabled_
= IsThreadedCompositingEnabled();
181 process_
->Attach(this, routing_id_
);
182 // Because the widget initializes as is_hidden_ == false,
183 // tell the process host that we're alive.
184 process_
->WidgetRestored();
186 #if defined(USE_AURA)
187 bool overscroll_enabled
= CommandLine::ForCurrentProcess()->
188 HasSwitch(switches::kEnableOverscrollHistoryNavigation
);
189 if (overscroll_enabled
)
190 InitializeOverscrollController();
194 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
197 // Clear our current or cached backing store if either remains.
198 BackingStoreManager::RemoveBackingStore(this);
200 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_
);
203 process_
->Release(routing_id_
);
206 delegate_
->RenderWidgetDeleted(this);
210 RenderWidgetHostImpl
* RenderWidgetHostImpl::From(RenderWidgetHost
* rwh
) {
211 return rwh
->AsRenderWidgetHostImpl();
214 void RenderWidgetHostImpl::SetView(RenderWidgetHostView
* view
) {
215 view_
= RenderWidgetHostViewPort::FromRWHV(view
);
218 GpuSurfaceTracker::Get()->SetSurfaceHandle(
219 surface_id_
, gfx::GLSurfaceHandle());
223 RenderProcessHost
* RenderWidgetHostImpl::GetProcess() const {
227 int RenderWidgetHostImpl::GetRoutingID() const {
231 RenderWidgetHostView
* RenderWidgetHostImpl::GetView() const {
235 RenderWidgetHostImpl
* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
239 gfx::NativeViewId
RenderWidgetHostImpl::GetNativeViewId() const {
241 return view_
->GetNativeViewId();
245 gfx::GLSurfaceHandle
RenderWidgetHostImpl::GetCompositingSurface() {
247 return view_
->GetCompositingSurface();
248 return gfx::GLSurfaceHandle();
251 void RenderWidgetHostImpl::CompositingSurfaceUpdated() {
252 GpuSurfaceTracker::Get()->SetSurfaceHandle(
253 surface_id_
, GetCompositingSurface());
254 process_
->SurfaceUpdated(surface_id_
);
257 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
258 resize_ack_pending_
= false;
259 repaint_ack_pending_
= false;
260 in_flight_size_
.SetSize(0, 0);
263 void RenderWidgetHostImpl::SendScreenRects() {
264 if (!renderer_initialized_
|| waiting_for_screen_rects_ack_
)
268 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
269 // happens on Win & Mac, and when the view is shown it'll call this again.
276 last_view_screen_rect_
= view_
->GetViewBounds();
277 last_window_screen_rect_
= view_
->GetBoundsInRootWindow();
278 Send(new ViewMsg_UpdateScreenRects(
279 GetRoutingID(), last_view_screen_rect_
, last_window_screen_rect_
));
280 waiting_for_screen_rects_ack_
= true;
283 void RenderWidgetHostImpl::Init() {
284 DCHECK(process_
->HasConnection());
286 renderer_initialized_
= true;
288 GpuSurfaceTracker::Get()->SetSurfaceHandle(
289 surface_id_
, GetCompositingSurface());
291 // Send the ack along with the information on placement.
292 Send(new ViewMsg_CreatingNew_ACK(routing_id_
));
293 GetProcess()->ResumeRequestsForView(routing_id_
);
298 void RenderWidgetHostImpl::Shutdown() {
299 RejectMouseLockOrUnlockIfNecessary();
301 if (process_
->HasConnection()) {
302 // Tell the renderer object to close.
303 bool rv
= Send(new ViewMsg_Close(routing_id_
));
310 bool RenderWidgetHostImpl::IsLoading() const {
314 bool RenderWidgetHostImpl::IsRenderView() const {
318 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message
&msg
) {
320 bool msg_is_ok
= true;
321 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl
, msg
, msg_is_ok
)
322 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady
, OnMsgRenderViewReady
)
323 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone
, OnMsgRenderViewGone
)
324 IPC_MESSAGE_HANDLER(ViewHostMsg_Close
, OnMsgClose
)
325 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK
,
326 OnMsgUpdateScreenRectsAck
)
327 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove
, OnMsgRequestMove
)
328 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText
, OnMsgSetTooltipText
)
329 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK
, OnMsgPaintAtSizeAck
)
330 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped
,
331 OnCompositorSurfaceBuffersSwapped
)
332 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect
, OnMsgUpdateRect
)
333 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed
, OnMsgUpdateIsDelayed
)
334 IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK
, OnMsgInputEventAck
)
335 IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll
, OnMsgBeginSmoothScroll
)
336 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK
, OnMsgSelectRangeAck
)
337 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus
, OnMsgFocus
)
338 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur
, OnMsgBlur
)
339 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers
,
340 OnMsgHasTouchEventHandlers
)
341 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor
, OnMsgSetCursor
)
342 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged
,
343 OnMsgTextInputStateChanged
)
344 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged
,
345 OnMsgImeCompositionRangeChanged
)
346 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition
,
347 OnMsgImeCancelComposition
)
348 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing
,
349 OnMsgDidActivateAcceleratedCompositing
)
350 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse
, OnMsgLockMouse
)
351 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse
, OnMsgUnlockMouse
)
352 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup
,
353 OnMsgShowDisambiguationPopup
)
354 #if defined(OS_MACOSX)
355 IPC_MESSAGE_HANDLER(ViewHostMsg_PluginFocusChanged
,
356 OnMsgPluginFocusChanged
)
357 IPC_MESSAGE_HANDLER(ViewHostMsg_StartPluginIme
,
359 IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateFakePluginWindowHandle
,
360 OnAllocateFakePluginWindowHandle
)
361 IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyFakePluginWindowHandle
,
362 OnDestroyFakePluginWindowHandle
)
363 IPC_MESSAGE_HANDLER(ViewHostMsg_AcceleratedSurfaceSetIOSurface
,
364 OnAcceleratedSurfaceSetIOSurface
)
365 IPC_MESSAGE_HANDLER(ViewHostMsg_AcceleratedSurfaceSetTransportDIB
,
366 OnAcceleratedSurfaceSetTransportDIB
)
367 IPC_MESSAGE_HANDLER(ViewHostMsg_AcceleratedSurfaceBuffersSwapped
,
368 OnAcceleratedSurfaceBuffersSwapped
)
370 #if defined(OS_ANDROID)
371 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFrameInfo
,
372 OnMsgUpdateFrameInfo
)
374 #if defined(TOOLKIT_GTK)
375 IPC_MESSAGE_HANDLER(ViewHostMsg_CreatePluginContainer
,
376 OnMsgCreatePluginContainer
)
377 IPC_MESSAGE_HANDLER(ViewHostMsg_DestroyPluginContainer
,
378 OnMsgDestroyPluginContainer
)
381 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated
,
382 OnWindowlessPluginDummyWindowCreated
)
383 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed
,
384 OnWindowlessPluginDummyWindowDestroyed
)
386 IPC_MESSAGE_UNHANDLED(handled
= false)
387 IPC_END_MESSAGE_MAP_EX()
390 // The message de-serialization failed. Kill the renderer process.
391 RecordAction(UserMetricsAction("BadMessageTerminate_RWH"));
392 GetProcess()->ReceivedBadMessage();
397 bool RenderWidgetHostImpl::Send(IPC::Message
* msg
) {
398 return process_
->Send(msg
);
401 void RenderWidgetHostImpl::WasHidden() {
404 // Don't bother reporting hung state when we aren't active.
405 StopHangMonitorTimeout();
407 // If we have a renderer, then inform it that we are being hidden so it can
408 // reduce its resource utilization.
409 Send(new ViewMsg_WasHidden(routing_id_
));
411 // Tell the RenderProcessHost we were hidden.
412 process_
->WidgetHidden();
414 bool is_visible
= false;
415 NotificationService::current()->Notify(
416 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
417 Source
<RenderWidgetHost
>(this),
418 Details
<bool>(&is_visible
));
421 void RenderWidgetHostImpl::WasShown() {
422 // When we create the widget, it is created as *not* hidden.
429 BackingStore
* backing_store
= BackingStoreManager::Lookup(this);
430 // If we already have a backing store for this widget, then we don't need to
431 // repaint on restore _unless_ we know that our backing store is invalid.
432 // When accelerated compositing is on, we must always repaint, even when
433 // the backing store exists.
434 bool needs_repainting
;
435 if (needs_repainting_on_restore_
|| !backing_store
||
436 is_accelerated_compositing_active()) {
437 needs_repainting
= true;
438 needs_repainting_on_restore_
= false;
440 needs_repainting
= false;
442 Send(new ViewMsg_WasShown(routing_id_
, needs_repainting
));
444 process_
->WidgetRestored();
446 bool is_visible
= true;
447 NotificationService::current()->Notify(
448 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
449 Source
<RenderWidgetHost
>(this),
450 Details
<bool>(&is_visible
));
452 // It's possible for our size to be out of sync with the renderer. The
453 // following is one case that leads to this:
454 // 1. WasResized -> Send ViewMsg_Resize to render
455 // 2. WasResized -> do nothing as resize_ack_pending_ is true
457 // 4. OnMsgUpdateRect from (1) processed. Does NOT invoke WasResized as view
458 // is hidden. Now renderer/browser out of sync with what they think size
460 // By invoking WasResized the renderer is updated as necessary. WasResized
461 // does nothing if the sizes are already in sync.
463 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
464 // could handle both the restore and resize at once. This isn't that big a
465 // deal as RenderWidget::WasShown delays updating, so that the resize from
466 // WasResized is usually processed before the renderer is painted.
470 void RenderWidgetHostImpl::WasResized() {
471 if (resize_ack_pending_
|| !process_
->HasConnection() || !view_
||
472 !renderer_initialized_
|| should_auto_resize_
) {
476 gfx::Rect view_bounds
= view_
->GetViewBounds();
477 gfx::Size
new_size(view_bounds
.size());
479 bool was_fullscreen
= is_fullscreen_
;
480 is_fullscreen_
= IsFullscreen();
481 bool fullscreen_changed
= was_fullscreen
!= is_fullscreen_
;
482 bool size_changed
= new_size
!= current_size_
;
484 // Avoid asking the RenderWidget to resize to its current size, since it
485 // won't send us a PaintRect message in that case.
486 if (!size_changed
&& !fullscreen_changed
)
489 if (in_flight_size_
!= gfx::Size() && new_size
== in_flight_size_
&&
493 // We don't expect to receive an ACK when the requested size is empty.
494 if (!new_size
.IsEmpty() && size_changed
)
495 resize_ack_pending_
= true;
497 if (!Send(new ViewMsg_Resize(routing_id_
, new_size
,
498 GetRootWindowResizerRect(), is_fullscreen_
))) {
499 resize_ack_pending_
= false;
501 in_flight_size_
= new_size
;
505 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect
& new_rect
) {
506 Send(new ViewMsg_ChangeResizeRect(routing_id_
, new_rect
));
509 void RenderWidgetHostImpl::GotFocus() {
513 void RenderWidgetHostImpl::Focus() {
514 Send(new ViewMsg_SetFocus(routing_id_
, true));
517 void RenderWidgetHostImpl::Blur() {
518 // If there is a pending mouse lock request, we don't want to reject it at
519 // this point. The user can switch focus back to this view and approve the
522 view_
->UnlockMouse();
524 Send(new ViewMsg_SetFocus(routing_id_
, false));
527 void RenderWidgetHostImpl::LostCapture() {
528 Send(new ViewMsg_MouseCaptureLost(routing_id_
));
531 void RenderWidgetHostImpl::SetActive(bool active
) {
532 Send(new ViewMsg_SetActive(routing_id_
, active
));
535 void RenderWidgetHostImpl::LostMouseLock() {
536 Send(new ViewMsg_MouseLockLost(routing_id_
));
539 void RenderWidgetHostImpl::ViewDestroyed() {
540 RejectMouseLockOrUnlockIfNecessary();
542 // TODO(evanm): tracking this may no longer be necessary;
543 // eliminate this function if so.
547 void RenderWidgetHostImpl::SetIsLoading(bool is_loading
) {
548 is_loading_
= is_loading
;
549 gesture_event_filter_
->FlingHasBeenHalted();
552 view_
->SetIsLoading(is_loading
);
555 void RenderWidgetHostImpl::CopyFromBackingStore(
556 const gfx::Rect
& src_subrect
,
557 const gfx::Size
& accelerated_dst_size
,
558 const base::Callback
<void(bool)>& callback
,
559 skia::PlatformBitmap
* output
) {
560 if (view_
&& is_accelerated_compositing_active_
) {
561 TRACE_EVENT0("browser",
562 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
563 gfx::Rect copy_rect
= src_subrect
.IsEmpty() ?
564 gfx::Rect(view_
->GetViewBounds().size()) : src_subrect
;
565 view_
->CopyFromCompositingSurface(copy_rect
,
566 accelerated_dst_size
,
572 BackingStore
* backing_store
= GetBackingStore(false);
573 if (!backing_store
) {
578 TRACE_EVENT0("browser",
579 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
580 gfx::Rect copy_rect
= src_subrect
.IsEmpty() ?
581 gfx::Rect(backing_store
->size()) : src_subrect
;
582 // When the result size is equal to the backing store size, copy from the
583 // backing store directly to the output canvas.
584 bool result
= backing_store
->CopyFromBackingStore(copy_rect
, output
);
585 callback
.Run(result
);
588 #if defined(TOOLKIT_GTK)
589 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
590 const gfx::Rect
& dest_rect
, GdkWindow
* target
) {
591 BackingStore
* backing_store
= GetBackingStore(false);
594 (static_cast<BackingStoreGtk
*>(backing_store
))->PaintToRect(
598 #elif defined(OS_MACOSX)
599 gfx::Size
RenderWidgetHostImpl::GetBackingStoreSize() {
600 BackingStore
* backing_store
= GetBackingStore(false);
601 return backing_store
? backing_store
->size() : gfx::Size();
604 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
605 const CGRect
& dest_rect
, CGContextRef target
) {
606 BackingStore
* backing_store
= GetBackingStore(false);
609 (static_cast<BackingStoreMac
*>(backing_store
))->
610 CopyFromBackingStoreToCGContext(dest_rect
, target
);
615 void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle
,
617 const gfx::Size
& page_size
,
618 const gfx::Size
& desired_size
) {
619 // Ask the renderer to create a bitmap regardless of whether it's
620 // hidden, being resized, redrawn, etc. It resizes the web widget
621 // to the page_size and then scales it to the desired_size.
622 Send(new ViewMsg_PaintAtSize(routing_id_
, dib_handle
, tag
,
623 page_size
, desired_size
));
626 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size
& desired_size
,
627 BackingStore
** backing_store
) {
628 // Check if the view has an accelerated surface of the desired size.
629 if (view_
->HasAcceleratedSurface(desired_size
)) {
630 *backing_store
= NULL
;
634 // Check for a software backing store of the desired size.
635 *backing_store
= BackingStoreManager::GetBackingStore(this, desired_size
);
636 return !!*backing_store
;
639 BackingStore
* RenderWidgetHostImpl::GetBackingStore(bool force_create
) {
643 // The view_size will be current_size_ for auto-sized views and otherwise the
644 // size of the view_. (For auto-sized views, current_size_ is updated during
645 // UpdateRect messages.)
646 gfx::Size view_size
= current_size_
;
647 if (!should_auto_resize_
) {
648 // Get the desired size from the current view bounds.
649 gfx::Rect view_rect
= view_
->GetViewBounds();
650 if (view_rect
.IsEmpty())
652 view_size
= view_rect
.size();
655 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
656 "width", base::IntToString(view_size
.width()),
657 "height", base::IntToString(view_size
.height()));
659 // We should not be asked to paint while we are hidden. If we are hidden,
660 // then it means that our consumer failed to call WasShown. If we're not
661 // force creating the backing store, it's OK since we can feel free to give
662 // out our cached one if we have it.
663 DCHECK(!is_hidden_
|| !force_create
) <<
664 "GetBackingStore called while hidden!";
666 // We should never be called recursively; this can theoretically lead to
667 // infinite recursion and almost certainly leads to lower performance.
668 DCHECK(!in_get_backing_store_
) << "GetBackingStore called recursively!";
669 base::AutoReset
<bool> auto_reset_in_get_backing_store(
670 &in_get_backing_store_
, true);
672 // We might have a cached backing store that we can reuse!
673 BackingStore
* backing_store
= NULL
;
674 if (TryGetBackingStore(view_size
, &backing_store
) || !force_create
)
675 return backing_store
;
677 // We do not have a suitable backing store in the cache, so send out a
678 // request to the renderer to paint the view if required.
679 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
) {
680 repaint_start_time_
= TimeTicks::Now();
681 repaint_ack_pending_
= true;
682 Send(new ViewMsg_Repaint(routing_id_
, view_size
));
685 TimeDelta max_delay
= TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS
);
686 TimeTicks end_time
= TimeTicks::Now() + max_delay
;
688 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
690 #if defined(OS_MACOSX)
691 view_
->AboutToWaitForBackingStoreMsg();
694 // When we have asked the RenderWidget to resize, and we are still waiting
695 // on a response, block for a little while to see if we can't get a response
696 // before returning the old (incorrectly sized) backing store.
698 if (process_
->WaitForBackingStoreMsg(routing_id_
, max_delay
, &msg
)) {
699 OnMessageReceived(msg
);
701 // For auto-resized views, current_size_ determines the view_size and it
702 // may have changed during the handling of an UpdateRect message.
703 if (should_auto_resize_
)
704 view_size
= current_size_
;
706 // Break now if we got a backing store or accelerated surface of the
708 if (TryGetBackingStore(view_size
, &backing_store
) ||
709 abort_get_backing_store_
) {
710 abort_get_backing_store_
= false;
711 return backing_store
;
714 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
718 // Loop if we still have time left and haven't gotten a properly sized
719 // BackingStore yet. This is necessary to support the GPU path which
720 // typically has multiple frames pipelined -- we may need to skip one or two
721 // BackingStore messages to get to the latest.
722 max_delay
= end_time
- TimeTicks::Now();
723 } while (max_delay
> TimeDelta::FromSeconds(0));
725 // We have failed to get a backing store of view_size. Fall back on
726 // current_size_ to avoid a white flash while resizing slow pages.
727 if (view_size
!= current_size_
)
728 TryGetBackingStore(current_size_
, &backing_store
);
729 return backing_store
;
732 BackingStore
* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size
& size
) {
735 return view_
->AllocBackingStore(size
);
738 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
739 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
742 void RenderWidgetHostImpl::ScheduleComposite() {
743 if (is_hidden_
|| !is_accelerated_compositing_active_
) {
747 // Send out a request to the renderer to paint the view if required.
748 if (!repaint_ack_pending_
&& !resize_ack_pending_
&& !view_being_painted_
) {
749 repaint_start_time_
= TimeTicks::Now();
750 repaint_ack_pending_
= true;
751 Send(new ViewMsg_Repaint(routing_id_
, current_size_
));
755 void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay
) {
756 if (CommandLine::ForCurrentProcess()->HasSwitch(
757 switches::kDisableHangMonitor
)) {
761 // Set time_when_considered_hung_ if it's null. Also, update
762 // time_when_considered_hung_ if the caller's request is sooner than the
763 // existing one. This will have the side effect that the existing timeout will
765 Time requested_end_time
= Time::Now() + delay
;
766 if (time_when_considered_hung_
.is_null() ||
767 time_when_considered_hung_
> requested_end_time
)
768 time_when_considered_hung_
= requested_end_time
;
770 // If we already have a timer with the same or shorter duration, then we can
771 // wait for it to finish.
772 if (hung_renderer_timer_
.IsRunning() &&
773 hung_renderer_timer_
.GetCurrentDelay() <= delay
) {
774 // If time_when_considered_hung_ was null, this timer may fire early.
775 // CheckRendererIsUnresponsive handles that by calling
776 // StartHangMonitorTimeout with the remaining time.
777 // If time_when_considered_hung_ was non-null, it means we still haven't
778 // heard from the renderer so we leave time_when_considered_hung_ as is.
782 // Either the timer is not yet running, or we need to adjust the timer to
784 time_when_considered_hung_
= requested_end_time
;
785 hung_renderer_timer_
.Stop();
786 hung_renderer_timer_
.Start(FROM_HERE
, delay
, this,
787 &RenderWidgetHostImpl::CheckRendererIsUnresponsive
);
790 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
791 // Setting to null will cause StartHangMonitorTimeout to restart the timer.
792 time_when_considered_hung_
= Time();
793 StartHangMonitorTimeout(
794 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
797 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
798 time_when_considered_hung_
= Time();
799 RendererIsResponsive();
800 // We do not bother to stop the hung_renderer_timer_ here in case it will be
801 // started again shortly, which happens to be the common use case.
804 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
805 SetAccessibilityMode(AccessibilityModeComplete
);
808 static WebGestureEvent
MakeGestureEvent(WebInputEvent::Type type
,
809 double timestamp_seconds
,
813 WebGestureEvent result
;
818 result
.timeStampSeconds
= timestamp_seconds
;
819 result
.modifiers
= modifiers
;
824 void RenderWidgetHostImpl::SimulateTouchGestureWithMouse(
825 const WebMouseEvent
& mouse_event
) {
826 int x
= mouse_event
.x
, y
= mouse_event
.y
;
827 float dx
= mouse_event
.movementX
, dy
= mouse_event
.movementY
;
828 static int startX
= 0, startY
= 0;
830 switch (mouse_event
.button
) {
831 case WebMouseEvent::ButtonLeft
:
832 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
835 ForwardGestureEvent(MakeGestureEvent(
836 WebInputEvent::GestureScrollBegin
, mouse_event
.timeStampSeconds
,
839 if (dx
!= 0 || dy
!= 0) {
840 WebGestureEvent event
= MakeGestureEvent(
841 WebInputEvent::GestureScrollUpdate
, mouse_event
.timeStampSeconds
,
843 event
.data
.scrollUpdate
.deltaX
= dx
;
844 event
.data
.scrollUpdate
.deltaY
= dy
;
845 ForwardGestureEvent(event
);
847 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
848 ForwardGestureEvent(MakeGestureEvent(
849 WebInputEvent::GestureScrollEnd
, mouse_event
.timeStampSeconds
,
853 case WebMouseEvent::ButtonMiddle
:
854 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
857 ForwardGestureEvent(MakeGestureEvent(
858 WebInputEvent::GestureTapDown
, mouse_event
.timeStampSeconds
,
861 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
862 ForwardGestureEvent(MakeGestureEvent(
863 WebInputEvent::GestureTap
, mouse_event
.timeStampSeconds
,
867 case WebMouseEvent::ButtonRight
:
868 if (mouse_event
.type
== WebInputEvent::MouseDown
) {
871 ForwardGestureEvent(MakeGestureEvent(
872 WebInputEvent::GesturePinchBegin
, mouse_event
.timeStampSeconds
,
875 if (dx
!= 0 || dy
!= 0) {
876 dx
= pow(dy
< 0 ? 0.998f
: 1.002f
, fabs(dy
));
877 WebGestureEvent event
= MakeGestureEvent(
878 WebInputEvent::GesturePinchUpdate
, mouse_event
.timeStampSeconds
,
880 event
.data
.pinchUpdate
.scale
= dx
;
881 ForwardGestureEvent(event
);
883 if (mouse_event
.type
== WebInputEvent::MouseUp
) {
884 ForwardGestureEvent(MakeGestureEvent(
885 WebInputEvent::GesturePinchEnd
, mouse_event
.timeStampSeconds
,
889 case WebMouseEvent::ButtonNone
:
894 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent
& mouse_event
) {
895 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::ForwardMouseEvent",
896 "x", mouse_event
.x
, "y", mouse_event
.y
);
897 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
900 if (CommandLine::ForCurrentProcess()->HasSwitch(
901 switches::kSimulateTouchScreenWithMouse
)) {
902 SimulateTouchGestureWithMouse(mouse_event
);
906 if (mouse_event
.type
== WebInputEvent::MouseDown
&&
907 gesture_event_filter_
->GetTapSuppressionController()->
908 ShouldDeferMouseDown(mouse_event
))
910 if (mouse_event
.type
== WebInputEvent::MouseUp
&&
911 gesture_event_filter_
->GetTapSuppressionController()->
912 ShouldSuppressMouseUp())
915 ForwardMouseEventImmediately(mouse_event
);
918 void RenderWidgetHostImpl::OnPointerEventActivate() {
921 void RenderWidgetHostImpl::ForwardWheelEvent(
922 const WebMouseWheelEvent
& wheel_event
) {
923 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::ForwardWheelEvent");
924 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
927 // If there's already a mouse wheel event waiting to be sent to the renderer,
928 // add the new deltas to that event. Not doing so (e.g., by dropping the old
929 // event, as for mouse moves) results in very slow scrolling on the Mac (on
930 // which many, very small wheel events are sent).
931 if (mouse_wheel_pending_
) {
932 if (coalesced_mouse_wheel_events_
.empty() ||
933 !ShouldCoalesceMouseWheelEvents(coalesced_mouse_wheel_events_
.back(),
935 coalesced_mouse_wheel_events_
.push_back(wheel_event
);
937 WebMouseWheelEvent
* last_wheel_event
=
938 &coalesced_mouse_wheel_events_
.back();
939 last_wheel_event
->deltaX
+= wheel_event
.deltaX
;
940 last_wheel_event
->deltaY
+= wheel_event
.deltaY
;
941 last_wheel_event
->wheelTicksX
+= wheel_event
.wheelTicksX
;
942 last_wheel_event
->wheelTicksY
+= wheel_event
.wheelTicksY
;
943 DCHECK_GE(wheel_event
.timeStampSeconds
,
944 last_wheel_event
->timeStampSeconds
);
945 last_wheel_event
->timeStampSeconds
= wheel_event
.timeStampSeconds
;
949 mouse_wheel_pending_
= true;
950 current_wheel_event_
= wheel_event
;
952 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize",
953 coalesced_mouse_wheel_events_
.size());
955 ForwardInputEvent(wheel_event
, sizeof(WebMouseWheelEvent
), false);
958 void RenderWidgetHostImpl::ForwardGestureEvent(
959 const WebKit::WebGestureEvent
& gesture_event
) {
960 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::ForwardGestureEvent");
961 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
964 if (!IsInOverscrollGesture() &&
965 !gesture_event_filter_
->ShouldForward(gesture_event
))
968 ForwardInputEvent(gesture_event
, sizeof(WebGestureEvent
), false);
971 // Forwards MouseEvent without passing it through TapSuppressionController
972 void RenderWidgetHostImpl::ForwardMouseEventImmediately(
973 const WebMouseEvent
& mouse_event
) {
974 TRACE_EVENT2("renderer_host",
975 "RenderWidgetHostImpl::ForwardMouseEventImmediately",
976 "x", mouse_event
.x
, "y", mouse_event
.y
);
977 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
980 if (CommandLine::ForCurrentProcess()->HasSwitch(
981 switches::kSimulateTouchScreenWithMouse
)) {
982 SimulateTouchGestureWithMouse(mouse_event
);
986 // Avoid spamming the renderer with mouse move events. It is important
987 // to note that WM_MOUSEMOVE events are anyways synthetic, but since our
988 // thread is able to rapidly consume WM_MOUSEMOVE events, we may get way
989 // more WM_MOUSEMOVE events than we wish to send to the renderer.
990 if (mouse_event
.type
== WebInputEvent::MouseMove
) {
991 if (mouse_move_pending_
) {
992 if (!next_mouse_move_
.get()) {
993 next_mouse_move_
.reset(new WebMouseEvent(mouse_event
));
995 // Accumulate movement deltas.
996 int x
= next_mouse_move_
->movementX
;
997 int y
= next_mouse_move_
->movementY
;
998 *next_mouse_move_
= mouse_event
;
999 next_mouse_move_
->movementX
+= x
;
1000 next_mouse_move_
->movementY
+= y
;
1004 mouse_move_pending_
= true;
1005 } else if (mouse_event
.type
== WebInputEvent::MouseDown
) {
1009 ForwardInputEvent(mouse_event
, sizeof(WebMouseEvent
), false);
1012 void RenderWidgetHostImpl::ForwardTouchEventImmediately(
1013 const WebKit::WebTouchEvent
& touch_event
) {
1014 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::ForwardTouchEvent");
1015 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1018 ForwardInputEvent(touch_event
, sizeof(WebKit::WebTouchEvent
), false);
1021 void RenderWidgetHostImpl::ForwardGestureEventImmediately(
1022 const WebKit::WebGestureEvent
& gesture_event
) {
1023 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1025 ForwardInputEvent(gesture_event
, sizeof(WebGestureEvent
), false);
1028 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1029 const NativeWebKeyboardEvent
& key_event
) {
1030 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1031 if (ignore_input_events_
|| process_
->IgnoreInputEvents())
1034 if (key_event
.type
== WebKeyboardEvent::Char
&&
1035 (key_event
.windowsKeyCode
== ui::VKEY_RETURN
||
1036 key_event
.windowsKeyCode
== ui::VKEY_SPACE
)) {
1040 // Double check the type to make sure caller hasn't sent us nonsense that
1041 // will mess up our key queue.
1042 if (WebInputEvent::isKeyboardEventType(key_event
.type
)) {
1043 if (suppress_next_char_events_
) {
1044 // If preceding RawKeyDown event was handled by the browser, then we need
1045 // suppress all Char events generated by it. Please note that, one
1046 // RawKeyDown event may generate multiple Char events, so we can't reset
1047 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1048 if (key_event
.type
== WebKeyboardEvent::Char
)
1050 // We get a KeyUp or a RawKeyDown event.
1051 suppress_next_char_events_
= false;
1054 bool is_keyboard_shortcut
= false;
1055 // Only pre-handle the key event if it's not handled by the input method.
1056 if (delegate_
&& !key_event
.skip_in_browser
) {
1057 // We need to set |suppress_next_char_events_| to true if
1058 // PreHandleKeyboardEvent() returns true, but |this| may already be
1059 // destroyed at that time. So set |suppress_next_char_events_| true here,
1060 // then revert it afterwards when necessary.
1061 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1062 suppress_next_char_events_
= true;
1064 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1065 // a hung/malicious renderer from interfering.
1066 if (delegate_
->PreHandleKeyboardEvent(key_event
, &is_keyboard_shortcut
))
1069 if (key_event
.type
== WebKeyboardEvent::RawKeyDown
)
1070 suppress_next_char_events_
= false;
1073 // Don't add this key to the queue if we have no way to send the message...
1074 if (!process_
->HasConnection())
1077 // Put all WebKeyboardEvent objects in a queue since we can't trust the
1078 // renderer and we need to give something to the HandleKeyboardEvent
1080 key_queue_
.push_back(key_event
);
1081 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_
.size());
1083 gesture_event_filter_
->FlingHasBeenHalted();
1085 // Only forward the non-native portions of our event.
1086 ForwardInputEvent(key_event
, sizeof(WebKeyboardEvent
),
1087 is_keyboard_shortcut
);
1091 void RenderWidgetHostImpl::SendInputEvent(const WebInputEvent
& input_event
,
1093 bool is_keyboard_shortcut
) {
1094 IPC::Message
* message
= new ViewMsg_HandleInputEvent(routing_id_
);
1096 reinterpret_cast<const char*>(&input_event
), event_size
);
1097 // |is_keyboard_shortcut| only makes sense for RawKeyDown events.
1098 if (input_event
.type
== WebInputEvent::RawKeyDown
)
1099 message
->WriteBool(is_keyboard_shortcut
);
1100 input_event_start_time_
= TimeTicks::Now();
1102 increment_in_flight_event_count();
1105 void RenderWidgetHostImpl::ForwardInputEvent(const WebInputEvent
& input_event
,
1107 bool is_keyboard_shortcut
) {
1108 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::ForwardInputEvent");
1110 if (!process_
->HasConnection())
1113 DCHECK(!process_
->IgnoreInputEvents());
1115 if (overscroll_controller_
.get() &&
1116 !overscroll_controller_
->WillDispatchEvent(input_event
)) {
1117 // Reset the wheel-event state when appropriate.
1118 if (input_event
.type
== WebKit::WebInputEvent::MouseWheel
) {
1119 mouse_wheel_pending_
= false;
1120 } else if (WebInputEvent::isGestureEventType(input_event
.type
) &&
1121 gesture_event_filter_
->HasQueuedGestureEvents()) {
1122 // If the gesture-event filter has queued gesture events, that implies it
1123 // is awaiting an ack for the event. Since the event is being consumed by
1124 // the over scroll here, it is never sent to the renderer, and so it won't
1125 // receive any ACKs. So send the ACK to the gesture event filter
1126 // immediately, and mark it as having been processed.
1127 gesture_event_filter_
->ProcessGestureAck(true, input_event
.type
);
1128 } else if (WebInputEvent::isTouchEventType(input_event
.type
)) {
1129 // During an overscroll gesture initiated by touch-scrolling, the
1130 // touch-events do not reset or contribute to the overscroll gesture.
1131 // However, the touch-events are not sent to the renderer. So send and ACK
1132 // to the touch-event queue immediately. Mark the event as not processed,
1133 // to make sure that the touch-scroll gesture that initiated the
1134 // overscroll is updated properly.
1135 touch_event_queue_
->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
);
1140 in_process_event_types_
.push(input_event
.type
);
1142 // Transmit any pending wheel events on a non-wheel event. This ensures that
1143 // the renderer receives the final PhaseEnded wheel event, which is necessary
1144 // to terminate rubber-banding, for example.
1145 if (input_event
.type
!= WebInputEvent::MouseWheel
) {
1146 for (size_t i
= 0; i
< coalesced_mouse_wheel_events_
.size(); ++i
) {
1147 SendInputEvent(coalesced_mouse_wheel_events_
[i
],
1148 sizeof(WebMouseWheelEvent
), false);
1150 coalesced_mouse_wheel_events_
.clear();
1153 SendInputEvent(input_event
, event_size
, is_keyboard_shortcut
);
1155 // Any input event cancels a pending mouse move event. Note that
1156 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event|
1158 next_mouse_move_
.reset();
1160 StartHangMonitorTimeout(
1161 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_
));
1164 void RenderWidgetHostImpl::ForwardTouchEvent(
1165 const WebKit::WebTouchEvent
& touch_event
) {
1166 touch_event_queue_
->QueueEvent(touch_event
);
1169 #if defined(TOOLKIT_GTK)
1170 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(GdkEventKey
* event
) {
1171 if (event
->type
!= GDK_KEY_PRESS
)
1174 for (std::list
<KeyboardListener
*>::iterator it
= keyboard_listeners_
.begin();
1175 it
!= keyboard_listeners_
.end(); ++it
) {
1176 if ((*it
)->HandleKeyPressEvent(event
))
1182 #endif // defined(TOOLKIT_GTK)
1184 #if defined(TOOLKIT_VIEWS)
1185 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(ui::KeyEvent
* event
) {
1186 if (event
->type() != ui::ET_KEY_PRESSED
)
1189 for (std::list
<KeyboardListener
*>::iterator it
= keyboard_listeners_
.begin();
1190 it
!= keyboard_listeners_
.end(); ++it
) {
1191 if ((*it
)->HandleKeyPressEvent(event
))
1197 #endif // defined(TOOLKIT_VIEWS)
1199 void RenderWidgetHostImpl::AddKeyboardListener(KeyboardListener
* listener
) {
1200 keyboard_listeners_
.push_back(listener
);
1203 void RenderWidgetHostImpl::RemoveKeyboardListener(
1204 KeyboardListener
* listener
) {
1205 keyboard_listeners_
.remove(listener
);
1208 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1209 WebKit::WebScreenInfo screen_info
;
1210 GetWebScreenInfo(&screen_info
);
1211 Send(new ViewMsg_ScreenInfoChanged(GetRoutingID(), screen_info
));
1214 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase
,
1215 base::TimeDelta interval
) {
1216 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase
, interval
));
1219 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status
,
1221 // Clearing this flag causes us to re-create the renderer when recovering
1222 // from a crashed renderer.
1223 renderer_initialized_
= false;
1225 waiting_for_screen_rects_ack_
= false;
1227 // Must reset these to ensure that mouse move/wheel events work with a new
1229 mouse_move_pending_
= false;
1230 next_mouse_move_
.reset();
1231 mouse_wheel_pending_
= false;
1232 coalesced_mouse_wheel_events_
.clear();
1234 // Must reset these to ensure that SelectRange works with a new renderer.
1235 select_range_pending_
= false;
1236 next_selection_range_
.reset();
1238 touch_event_queue_
->Reset();
1240 // Must reset these to ensure that gesture events work with a new renderer.
1241 gesture_event_filter_
->Reset();
1243 if (overscroll_controller_
.get())
1244 overscroll_controller_
->Reset();
1246 // Must reset these to ensure that keyboard events work with a new renderer.
1248 suppress_next_char_events_
= false;
1250 // Reset some fields in preparation for recovering from a crash.
1251 ResetSizeAndRepaintPendingFlags();
1252 current_size_
.SetSize(0, 0);
1254 is_accelerated_compositing_active_
= false;
1256 // Reset this to ensure the hung renderer mechanism is working properly.
1257 in_flight_event_count_
= 0;
1260 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_
,
1261 gfx::GLSurfaceHandle());
1262 view_
->RenderViewGone(status
, exit_code
);
1263 view_
= NULL
; // The View should be deleted by RenderViewGone.
1266 BackingStoreManager::RemoveBackingStore(this);
1269 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction
) {
1270 text_direction_updated_
= true;
1271 text_direction_
= direction
;
1274 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1275 if (text_direction_updated_
)
1276 text_direction_canceled_
= true;
1279 void RenderWidgetHostImpl::NotifyTextDirection() {
1280 if (text_direction_updated_
) {
1281 if (!text_direction_canceled_
)
1282 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_
));
1283 text_direction_updated_
= false;
1284 text_direction_canceled_
= false;
1288 void RenderWidgetHostImpl::SetInputMethodActive(bool activate
) {
1289 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate
));
1292 void RenderWidgetHostImpl::ImeSetComposition(
1293 const string16
& text
,
1294 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
1295 int selection_start
,
1296 int selection_end
) {
1297 Send(new ViewMsg_ImeSetComposition(
1298 GetRoutingID(), text
, underlines
, selection_start
, selection_end
));
1301 void RenderWidgetHostImpl::ImeConfirmComposition(const string16
& text
) {
1302 ImeConfirmComposition(text
, ui::Range::InvalidRange());
1305 void RenderWidgetHostImpl::ImeConfirmComposition(
1306 const string16
& text
, const ui::Range
& replacement_range
) {
1307 Send(new ViewMsg_ImeConfirmComposition(
1308 GetRoutingID(), text
, replacement_range
));
1311 void RenderWidgetHostImpl::ImeConfirmComposition() {
1312 ImeConfirmComposition(string16());
1315 void RenderWidgetHostImpl::ImeCancelComposition() {
1316 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(),
1317 std::vector
<WebKit::WebCompositionUnderline
>(), 0, 0));
1320 void RenderWidgetHostImpl::ExtendSelectionAndDelete(
1323 Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before
, after
));
1326 gfx::Rect
RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1330 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture
,
1331 bool last_unlocked_by_target
) {
1332 // Directly reject to lock the mouse. Subclass can override this method to
1333 // decide whether to allow mouse lock or not.
1334 GotResponseToLockMouseRequest(false);
1337 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1338 DCHECK(!pending_mouse_lock_request_
|| !IsMouseLocked());
1339 if (pending_mouse_lock_request_
) {
1340 pending_mouse_lock_request_
= false;
1341 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
1342 } else if (IsMouseLocked()) {
1343 view_
->UnlockMouse();
1347 bool RenderWidgetHostImpl::IsMouseLocked() const {
1348 return view_
? view_
->IsMouseLocked() : false;
1351 bool RenderWidgetHostImpl::IsFullscreen() const {
1355 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable
) {
1356 should_auto_resize_
= enable
;
1359 void RenderWidgetHostImpl::InitializeOverscrollController() {
1360 overscroll_controller_
.reset(new OverscrollController(this));
1363 bool RenderWidgetHostImpl::IsInOverscrollGesture() const {
1364 return overscroll_controller_
.get() &&
1365 overscroll_controller_
->overscroll_mode() != OVERSCROLL_NONE
;
1368 void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo
* result
) {
1369 #if defined(OS_POSIX) || defined(USE_AURA)
1371 static_cast<RenderWidgetHostViewPort
*>(GetView())->GetScreenInfo(result
);
1373 RenderWidgetHostViewPort::GetDefaultScreenInfo(result
);
1376 *result
= WebKit::WebScreenInfoFactory::screenInfo(
1377 gfx::NativeViewFromId(GetNativeViewId()));
1381 void RenderWidgetHostImpl::Destroy() {
1382 NotificationService::current()->Notify(
1383 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1384 Source
<RenderWidgetHost
>(this),
1385 NotificationService::NoDetails());
1387 // Tell the view to die.
1388 // Note that in the process of the view shutting down, it can call a ton
1389 // of other messages on us. So if you do any other deinitialization here,
1390 // do it after this call to view_->Destroy().
1397 void RenderWidgetHostImpl::CheckRendererIsUnresponsive() {
1398 // If we received a call to StopHangMonitorTimeout.
1399 if (time_when_considered_hung_
.is_null())
1402 // If we have not waited long enough, then wait some more.
1403 Time now
= Time::Now();
1404 if (now
< time_when_considered_hung_
) {
1405 StartHangMonitorTimeout(time_when_considered_hung_
- now
);
1409 // OK, looks like we have a hung renderer!
1410 NotificationService::current()->Notify(
1411 NOTIFICATION_RENDERER_PROCESS_HANG
,
1412 Source
<RenderWidgetHost
>(this),
1413 NotificationService::NoDetails());
1414 is_unresponsive_
= true;
1415 NotifyRendererUnresponsive();
1418 void RenderWidgetHostImpl::RendererIsResponsive() {
1419 if (is_unresponsive_
) {
1420 is_unresponsive_
= false;
1421 NotifyRendererResponsive();
1425 void RenderWidgetHostImpl::OnMsgRenderViewReady() {
1430 void RenderWidgetHostImpl::OnMsgRenderViewGone(int status
, int exit_code
) {
1431 // TODO(evanm): This synchronously ends up calling "delete this".
1432 // Is that really what we want in response to this message? I'm matching
1433 // previous behavior of the code here.
1437 void RenderWidgetHostImpl::OnMsgClose() {
1441 void RenderWidgetHostImpl::OnMsgSetTooltipText(
1442 const string16
& tooltip_text
,
1443 WebTextDirection text_direction_hint
) {
1444 // First, add directionality marks around tooltip text if necessary.
1445 // A naive solution would be to simply always wrap the text. However, on
1446 // windows, Unicode directional embedding characters can't be displayed on
1447 // systems that lack RTL fonts and are instead displayed as empty squares.
1449 // To get around this we only wrap the string when we deem it necessary i.e.
1450 // when the locale direction is different than the tooltip direction hint.
1452 // Currently, we use element's directionality as the tooltip direction hint.
1453 // An alternate solution would be to set the overall directionality based on
1454 // trying to detect the directionality from the tooltip text rather than the
1455 // element direction. One could argue that would be a preferable solution
1456 // but we use the current approach to match Fx & IE's behavior.
1457 string16 wrapped_tooltip_text
= tooltip_text
;
1458 if (!tooltip_text
.empty()) {
1459 if (text_direction_hint
== WebKit::WebTextDirectionLeftToRight
) {
1460 // Force the tooltip to have LTR directionality.
1461 wrapped_tooltip_text
=
1462 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text
);
1463 } else if (text_direction_hint
== WebKit::WebTextDirectionRightToLeft
&&
1464 !base::i18n::IsRTL()) {
1465 // Force the tooltip to have RTL directionality.
1466 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text
);
1470 view_
->SetTooltipText(wrapped_tooltip_text
);
1473 void RenderWidgetHostImpl::OnMsgUpdateScreenRectsAck() {
1474 waiting_for_screen_rects_ack_
= false;
1478 if (view_
->GetViewBounds() == last_view_screen_rect_
&&
1479 view_
->GetBoundsInRootWindow() == last_window_screen_rect_
) {
1486 void RenderWidgetHostImpl::OnMsgRequestMove(const gfx::Rect
& pos
) {
1487 // Note that we ignore the position.
1489 view_
->SetBounds(pos
);
1490 Send(new ViewMsg_Move_ACK(routing_id_
));
1494 void RenderWidgetHostImpl::OnMsgPaintAtSizeAck(int tag
, const gfx::Size
& size
) {
1495 std::pair
<int, gfx::Size
> details
= std::make_pair(tag
, size
);
1496 NotificationService::current()->Notify(
1497 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK
,
1498 Source
<RenderWidgetHost
>(this),
1499 Details
<std::pair
<int, gfx::Size
> >(&details
));
1502 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1504 uint64 surface_handle
,
1506 const gfx::Size
& size
,
1507 int32 gpu_process_host_id
) {
1508 TRACE_EVENT0("renderer_host",
1509 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1511 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id
,
1512 gpu_process_host_id
,
1517 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params
;
1518 gpu_params
.surface_id
= surface_id
;
1519 gpu_params
.surface_handle
= surface_handle
;
1520 gpu_params
.route_id
= route_id
;
1521 gpu_params
.size
= size
;
1522 #if defined(OS_MACOSX)
1523 // Compositor window is always gfx::kNullPluginWindow.
1524 // TODO(jbates) http://crbug.com/105344 This will be removed when there are no
1526 gpu_params
.window
= gfx::kNullPluginWindow
;
1528 view_
->AcceleratedSurfaceBuffersSwapped(gpu_params
,
1529 gpu_process_host_id
);
1532 void RenderWidgetHostImpl::OnMsgUpdateRect(
1533 const ViewHostMsg_UpdateRect_Params
& params
) {
1534 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgUpdateRect");
1535 TimeTicks paint_start
= TimeTicks::Now();
1537 // Update our knowledge of the RenderWidget's size.
1538 current_size_
= params
.view_size
;
1539 // Update our knowledge of the RenderWidget's scroll offset.
1540 last_scroll_offset_
= params
.scroll_offset
;
1542 bool is_resize_ack
=
1543 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1545 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1546 // that will end up reaching GetBackingStore.
1547 if (is_resize_ack
) {
1548 DCHECK(resize_ack_pending_
);
1549 resize_ack_pending_
= false;
1550 in_flight_size_
.SetSize(0, 0);
1553 bool is_repaint_ack
=
1554 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params
.flags
);
1555 if (is_repaint_ack
) {
1556 repaint_ack_pending_
= false;
1557 TimeDelta delta
= TimeTicks::Now() - repaint_start_time_
;
1558 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta
);
1561 DCHECK(!params
.view_size
.IsEmpty());
1563 bool was_async
= false;
1565 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1566 TransportDIB
* dib
= process_
->GetTransportDIB(params
.bitmap
);
1568 // If gpu process does painting, scroll_rect and copy_rects are always empty
1569 // and backing store is never used.
1571 DCHECK(!params
.bitmap_rect
.IsEmpty());
1572 gfx::Size pixel_size
= gfx::ToFlooredSize(
1573 gfx::ScaleSize(params
.bitmap_rect
.size(), params
.scale_factor
));
1574 const size_t size
= pixel_size
.height() * pixel_size
.width() * 4;
1575 if (dib
->size() < size
) {
1576 DLOG(WARNING
) << "Transport DIB too small for given rectangle";
1577 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
1578 GetProcess()->ReceivedBadMessage();
1580 UNSHIPPED_TRACE_EVENT_INSTANT2("test_latency", "UpdateRect",
1581 "x+y", params
.bitmap_rect
.x() + params
.bitmap_rect
.y(),
1582 "color", 0xffffff & *static_cast<uint32
*>(dib
->memory()));
1583 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectWidth",
1584 "width", params
.bitmap_rect
.width());
1586 // Scroll the backing store.
1587 if (!params
.scroll_rect
.IsEmpty()) {
1588 ScrollBackingStoreRect(params
.scroll_delta
,
1593 // Paint the backing store. This will update it with the
1594 // renderer-supplied bits. The view will read out of the backing store
1595 // later to actually draw to the screen.
1596 was_async
= PaintBackingStoreRect(
1601 params
.scale_factor
,
1602 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore
,
1603 weak_factory_
.GetWeakPtr(), params
, paint_start
));
1608 DidUpdateBackingStore(params
, paint_start
);
1611 if (should_auto_resize_
) {
1612 bool post_callback
= new_auto_size_
.IsEmpty();
1613 new_auto_size_
= params
.view_size
;
1614 if (post_callback
) {
1615 MessageLoop::current()->PostTask(
1617 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized
,
1618 weak_factory_
.GetWeakPtr()));
1622 // Log the time delta for processing a paint message. On platforms that don't
1623 // support asynchronous painting, this is equivalent to
1624 // MPArch.RWH_TotalPaintTime.
1625 TimeDelta delta
= TimeTicks::Now() - paint_start
;
1626 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta
);
1629 void RenderWidgetHostImpl::OnMsgUpdateIsDelayed() {
1630 if (in_get_backing_store_
)
1631 abort_get_backing_store_
= true;
1634 void RenderWidgetHostImpl::DidUpdateBackingStore(
1635 const ViewHostMsg_UpdateRect_Params
& params
,
1636 const TimeTicks
& paint_start
) {
1637 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1638 TimeTicks update_start
= TimeTicks::Now();
1640 if (params
.needs_ack
) {
1641 // ACK early so we can prefetch the next PaintRect if there is a next one.
1642 // This must be done AFTER we're done painting with the bitmap supplied by
1643 // the renderer. This ACK is a signal to the renderer that the backing store
1644 // can be re-used, so the bitmap may be invalid after this call.
1645 Send(new ViewMsg_UpdateRect_ACK(routing_id_
));
1648 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1649 // will not be re-issued, so must move them now, regardless of whether we
1650 // paint or not. MovePluginWindows attempts to move the plugin windows and
1651 // in the process could dispatch other window messages which could cause the
1652 // view to be destroyed.
1654 view_
->MovePluginWindows(params
.scroll_offset
, params
.plugin_window_moves
);
1656 NotificationService::current()->Notify(
1657 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE
,
1658 Source
<RenderWidgetHost
>(this),
1659 NotificationService::NoDetails());
1661 // We don't need to update the view if the view is hidden. We must do this
1662 // early return after the ACK is sent, however, or the renderer will not send
1667 // Now paint the view. Watch out: it might be destroyed already.
1668 if (view_
&& !is_accelerated_compositing_active_
) {
1669 view_being_painted_
= true;
1670 view_
->DidUpdateBackingStore(params
.scroll_rect
, params
.scroll_delta
,
1672 view_being_painted_
= false;
1675 // If we got a resize ack, then perhaps we have another resize to send?
1676 bool is_resize_ack
=
1677 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params
.flags
);
1681 // Log the time delta for processing a paint message.
1682 TimeTicks now
= TimeTicks::Now();
1683 TimeDelta delta
= now
- update_start
;
1684 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta
);
1686 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1687 // DidUpdateBackingStore() method. On platforms which have asynchronous
1688 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1689 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1690 // waiting for the paint to complete.
1692 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1693 delta
= now
- paint_start
;
1694 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta
);
1695 UNSHIPPED_TRACE_EVENT_INSTANT1("test_latency", "UpdateRectComplete",
1696 "x+y", params
.bitmap_rect
.x() + params
.bitmap_rect
.y());
1699 void RenderWidgetHostImpl::OnMsgInputEventAck(
1700 WebInputEvent::Type event_type
, InputEventAckState ack_result
) {
1701 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnMsgInputEventAck");
1702 bool processed
= (ack_result
== INPUT_EVENT_ACK_STATE_CONSUMED
);
1704 if (!in_process_event_types_
.empty() &&
1705 in_process_event_types_
.front() == event_type
)
1706 in_process_event_types_
.pop();
1708 // Log the time delta for processing an input event.
1709 TimeDelta delta
= TimeTicks::Now() - input_event_start_time_
;
1710 UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta
);
1712 // Cancel pending hung renderer checks since the renderer is responsive.
1713 if (decrement_in_flight_event_count() == 0)
1714 StopHangMonitorTimeout();
1716 // If an input ack is pending, then hold off ticking the gesture
1717 // until we get an input ack.
1718 if (in_process_event_types_
.empty() &&
1719 !active_smooth_scroll_gestures_
.empty())
1720 TickActiveSmoothScrollGesture();
1722 int type
= static_cast<int>(event_type
);
1723 if (type
< WebInputEvent::Undefined
) {
1724 RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
1725 process_
->ReceivedBadMessage();
1726 } else if (type
== WebInputEvent::MouseMove
) {
1727 mouse_move_pending_
= false;
1729 // now, we can send the next mouse move event
1730 if (next_mouse_move_
.get()) {
1731 DCHECK(next_mouse_move_
->type
== WebInputEvent::MouseMove
);
1732 ForwardMouseEvent(*next_mouse_move_
);
1734 } else if (WebInputEvent::isKeyboardEventType(type
)) {
1735 ProcessKeyboardEventAck(type
, processed
);
1736 } else if (type
== WebInputEvent::MouseWheel
) {
1737 ProcessWheelAck(processed
);
1738 } else if (WebInputEvent::isTouchEventType(type
)) {
1739 ProcessTouchAck(ack_result
);
1740 } else if (WebInputEvent::isGestureEventType(type
)) {
1741 ProcessGestureAck(processed
, type
);
1744 // WARNING: |this| may be deleted at this point.
1746 // This is used only for testing, and the other end does not use the
1747 // source object. On linux, specifying
1748 // Source<RenderWidgetHost> results in a very strange
1749 // runtime error in the epilogue of the enclosing
1750 // (OnMsgInputEventAck) method, but not on other platforms; using
1751 // 'void' instead is just as safe (since NotificationSource
1752 // is not actually typesafe) and avoids this error.
1753 NotificationService::current()->Notify(
1754 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK
,
1756 Details
<int>(&type
));
1759 void RenderWidgetHostImpl::OnMsgBeginSmoothScroll(
1760 int gesture_id
, const ViewHostMsg_BeginSmoothScroll_Params
¶ms
) {
1763 active_smooth_scroll_gestures_
.insert(
1764 std::make_pair(gesture_id
,
1765 view_
->CreateSmoothScrollGesture(
1766 params
.scroll_down
, params
.pixels_to_scroll
,
1767 params
.mouse_event_x
, params
.mouse_event_y
)));
1769 // If an input ack is pending, then hold off ticking the gesture
1770 // until we get an input ack.
1771 if (!in_process_event_types_
.empty())
1773 if (tick_active_smooth_scroll_gestures_task_posted_
)
1775 TickActiveSmoothScrollGesture();
1778 void RenderWidgetHostImpl::TickActiveSmoothScrollGesture() {
1779 TRACE_EVENT0("input", "RenderWidgetHostImpl::TickActiveSmoothScrollGesture");
1780 tick_active_smooth_scroll_gestures_task_posted_
= false;
1781 if (active_smooth_scroll_gestures_
.empty()) {
1782 TRACE_EVENT_INSTANT0("input", "EarlyOut_NoActiveScrollGesture");
1786 base::TimeTicks now
= TimeTicks::HighResNow();
1787 base::TimeDelta preferred_interval
=
1788 base::TimeDelta::FromMilliseconds(kSyntheticScrollMessageIntervalMs
);
1789 base::TimeDelta time_until_next_ideal_interval
=
1790 (last_smooth_scroll_gestures_tick_time_
+ preferred_interval
) -
1792 if (time_until_next_ideal_interval
.InMilliseconds() > 0) {
1793 TRACE_EVENT_INSTANT1(
1794 "input", "EarlyOut_TickedTooRecently",
1795 "delay", time_until_next_ideal_interval
.InMilliseconds());
1797 tick_active_smooth_scroll_gestures_task_posted_
= true;
1798 MessageLoop::current()->PostDelayedTask(
1800 base::Bind(&RenderWidgetHostImpl::TickActiveSmoothScrollGesture
,
1801 weak_factory_
.GetWeakPtr()),
1802 time_until_next_ideal_interval
);
1806 last_smooth_scroll_gestures_tick_time_
= now
;
1808 // Separate ticking of gestures from sending their completion messages.
1809 std::vector
<int> ids_that_are_done
;
1810 for (SmoothScrollGestureMap::iterator it
=
1811 active_smooth_scroll_gestures_
.begin();
1812 it
!= active_smooth_scroll_gestures_
.end();
1815 bool active
= it
->second
->ForwardInputEvents(now
, this);
1817 ids_that_are_done
.push_back(it
->first
);
1820 // Delete completed gestures and send their completion event.
1821 for(size_t i
= 0; i
< ids_that_are_done
.size(); i
++) {
1822 int id
= ids_that_are_done
[i
];
1823 SmoothScrollGestureMap::iterator it
=
1824 active_smooth_scroll_gestures_
.find(id
);
1825 DCHECK(it
!= active_smooth_scroll_gestures_
.end());
1826 active_smooth_scroll_gestures_
.erase(it
);
1828 Send(new ViewMsg_SmoothScrollCompleted(routing_id_
, id
));
1831 // No need to post the next tick if an input is in flight.
1832 if (!in_process_event_types_
.empty())
1835 TRACE_EVENT_INSTANT1("input", "PostTickTask",
1836 "delay", preferred_interval
.InMilliseconds());
1837 tick_active_smooth_scroll_gestures_task_posted_
= true;
1838 MessageLoop::current()->PostDelayedTask(
1840 base::Bind(&RenderWidgetHostImpl::TickActiveSmoothScrollGesture
,
1841 weak_factory_
.GetWeakPtr()),
1842 preferred_interval
);
1845 void RenderWidgetHostImpl::OnMsgSelectRangeAck() {
1846 select_range_pending_
= false;
1847 if (next_selection_range_
.get()) {
1848 scoped_ptr
<SelectionRange
> next(next_selection_range_
.Pass());
1849 SelectRange(next
->start
, next
->end
);
1853 void RenderWidgetHostImpl::ProcessWheelAck(bool processed
) {
1854 mouse_wheel_pending_
= false;
1856 if (overscroll_controller_
.get())
1857 overscroll_controller_
->ReceivedEventACK(current_wheel_event_
, processed
);
1859 // Now send the next (coalesced) mouse wheel event.
1860 if (!coalesced_mouse_wheel_events_
.empty()) {
1861 WebMouseWheelEvent next_wheel_event
=
1862 coalesced_mouse_wheel_events_
.front();
1863 coalesced_mouse_wheel_events_
.pop_front();
1864 ForwardWheelEvent(next_wheel_event
);
1867 if (!processed
&& !is_hidden_
&& view_
)
1868 view_
->UnhandledWheelEvent(current_wheel_event_
);
1871 void RenderWidgetHostImpl::ProcessGestureAck(bool processed
, int type
) {
1872 if (overscroll_controller_
.get()) {
1873 overscroll_controller_
->ReceivedEventACK(
1874 gesture_event_filter_
->GetGestureEventAwaitingAck(), processed
);
1876 gesture_event_filter_
->ProcessGestureAck(processed
, type
);
1879 void RenderWidgetHostImpl::ProcessTouchAck(InputEventAckState ack_result
) {
1880 touch_event_queue_
->ProcessTouchAck(ack_result
);
1883 void RenderWidgetHostImpl::OnMsgFocus() {
1884 // Only RenderViewHost can deal with that message.
1885 RecordAction(UserMetricsAction("BadMessageTerminate_RWH4"));
1886 GetProcess()->ReceivedBadMessage();
1889 void RenderWidgetHostImpl::OnMsgBlur() {
1890 // Only RenderViewHost can deal with that message.
1891 RecordAction(UserMetricsAction("BadMessageTerminate_RWH5"));
1892 GetProcess()->ReceivedBadMessage();
1895 void RenderWidgetHostImpl::OnMsgHasTouchEventHandlers(bool has_handlers
) {
1896 if (has_touch_handler_
== has_handlers
)
1898 has_touch_handler_
= has_handlers
;
1899 if (!has_touch_handler_
)
1900 touch_event_queue_
->FlushQueue();
1901 #if defined(OS_ANDROID)
1903 view_
->HasTouchEventHandlers(has_touch_handler_
);
1907 void RenderWidgetHostImpl::OnMsgSetCursor(const WebCursor
& cursor
) {
1911 view_
->UpdateCursor(cursor
);
1914 void RenderWidgetHostImpl::OnMsgTextInputStateChanged(
1915 const ViewHostMsg_TextInputState_Params
& params
) {
1917 view_
->TextInputStateChanged(params
);
1920 void RenderWidgetHostImpl::OnMsgImeCompositionRangeChanged(
1921 const ui::Range
& range
,
1922 const std::vector
<gfx::Rect
>& character_bounds
) {
1924 view_
->ImeCompositionRangeChanged(range
, character_bounds
);
1927 void RenderWidgetHostImpl::OnMsgImeCancelComposition() {
1929 view_
->ImeCancelComposition();
1932 void RenderWidgetHostImpl::OnMsgDidActivateAcceleratedCompositing(
1934 TRACE_EVENT1("renderer_host",
1935 "RenderWidgetHostImpl::OnMsgDidActivateAcceleratedCompositing",
1936 "activated", activated
);
1937 is_accelerated_compositing_active_
= activated
;
1939 view_
->OnAcceleratedCompositingStateChange();
1942 void RenderWidgetHostImpl::OnMsgLockMouse(bool user_gesture
,
1943 bool last_unlocked_by_target
,
1946 if (pending_mouse_lock_request_
) {
1947 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
1949 } else if (IsMouseLocked()) {
1950 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
1954 pending_mouse_lock_request_
= true;
1955 if (privileged
&& allow_privileged_mouse_lock_
) {
1956 // Directly approve to lock the mouse.
1957 GotResponseToLockMouseRequest(true);
1959 RequestToLockMouse(user_gesture
, last_unlocked_by_target
);
1963 void RenderWidgetHostImpl::OnMsgUnlockMouse() {
1964 RejectMouseLockOrUnlockIfNecessary();
1967 void RenderWidgetHostImpl::OnMsgShowDisambiguationPopup(
1968 const gfx::Rect
& rect
,
1969 const gfx::Size
& size
,
1970 const TransportDIB::Id
& id
) {
1971 DCHECK(!rect
.IsEmpty());
1972 DCHECK(!size
.IsEmpty());
1974 TransportDIB
* dib
= process_
->GetTransportDIB(id
);
1975 DCHECK(dib
->memory());
1976 DCHECK(dib
->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config
,
1977 size
.width(), size
.height()));
1979 SkBitmap zoomed_bitmap
;
1980 zoomed_bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
1981 size
.width(), size
.height());
1982 zoomed_bitmap
.setPixels(dib
->memory());
1984 #if defined(OS_ANDROID)
1986 view_
->ShowDisambiguationPopup(rect
, zoomed_bitmap
);
1991 zoomed_bitmap
.setPixels(0);
1992 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
1997 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
1998 gfx::NativeViewId dummy_activation_window
) {
1999 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
2000 if (!IsWindow(hwnd
) ||
2001 !WebPluginDelegateImpl::IsDummyActivationWindow(hwnd
)) {
2002 // This may happen as a result of a race condition when the plugin is going
2007 SetParent(hwnd
, reinterpret_cast<HWND
>(GetNativeViewId()));
2008 dummy_windows_for_activation_
.push_back(hwnd
);
2011 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
2012 gfx::NativeViewId dummy_activation_window
) {
2013 HWND hwnd
= reinterpret_cast<HWND
>(dummy_activation_window
);
2014 std::list
<HWND
>::iterator i
= dummy_windows_for_activation_
.begin();
2015 for (; i
!= dummy_windows_for_activation_
.end(); ++i
) {
2017 dummy_windows_for_activation_
.erase(i
);
2021 NOTREACHED() << "Unknown dummy window";
2025 bool RenderWidgetHostImpl::PaintBackingStoreRect(
2026 TransportDIB::Id bitmap
,
2027 const gfx::Rect
& bitmap_rect
,
2028 const std::vector
<gfx::Rect
>& copy_rects
,
2029 const gfx::Size
& view_size
,
2031 const base::Closure
& completion_callback
) {
2032 // The view may be destroyed already.
2037 // Don't bother updating the backing store when we're hidden. Just mark it
2038 // as being totally invalid. This will cause a complete repaint when the
2039 // view is restored.
2040 needs_repainting_on_restore_
= true;
2044 bool needs_full_paint
= false;
2045 bool scheduled_completion_callback
= false;
2046 BackingStoreManager::PrepareBackingStore(this, view_size
, bitmap
, bitmap_rect
,
2047 copy_rects
, scale_factor
,
2048 completion_callback
,
2050 &scheduled_completion_callback
);
2051 if (needs_full_paint
) {
2052 repaint_start_time_
= TimeTicks::Now();
2053 repaint_ack_pending_
= true;
2054 Send(new ViewMsg_Repaint(routing_id_
, view_size
));
2057 return scheduled_completion_callback
;
2060 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d
& delta
,
2061 const gfx::Rect
& clip_rect
,
2062 const gfx::Size
& view_size
) {
2064 // Don't bother updating the backing store when we're hidden. Just mark it
2065 // as being totally invalid. This will cause a complete repaint when the
2066 // view is restored.
2067 needs_repainting_on_restore_
= true;
2071 // TODO(darin): do we need to do something else if our backing store is not
2072 // the same size as the advertised view? maybe we just assume there is a
2073 // full paint on its way?
2074 BackingStore
* backing_store
= BackingStoreManager::Lookup(this);
2075 if (!backing_store
|| (backing_store
->size() != view_size
))
2077 backing_store
->ScrollBackingStore(delta
, clip_rect
, view_size
);
2080 void RenderWidgetHostImpl::Replace(const string16
& word
) {
2081 Send(new ViewMsg_Replace(routing_id_
, word
));
2084 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events
) {
2085 ignore_input_events_
= ignore_input_events
;
2088 void RenderWidgetHostImpl::ProcessKeyboardEventAck(int type
, bool processed
) {
2089 if (key_queue_
.empty()) {
2090 LOG(ERROR
) << "Got a KeyEvent back from the renderer but we "
2091 << "don't seem to have sent it to the renderer!";
2092 } else if (key_queue_
.front().type
!= type
) {
2093 LOG(ERROR
) << "We seem to have a different key type sent from "
2094 << "the renderer. (" << key_queue_
.front().type
<< " vs. "
2095 << type
<< "). Ignoring event.";
2097 // Something must be wrong. Clear the |key_queue_| and
2098 // |suppress_next_char_events_| so that we can resume from the error.
2100 suppress_next_char_events_
= false;
2102 NativeWebKeyboardEvent front_item
= key_queue_
.front();
2103 key_queue_
.pop_front();
2105 #if defined(OS_MACOSX)
2106 if (!is_hidden_
&& view_
->PostProcessEventForPluginIme(front_item
))
2110 // We only send unprocessed key event upwards if we are not hidden,
2111 // because the user has moved away from us and no longer expect any effect
2112 // of this key event.
2113 if (delegate_
&& !processed
&& !is_hidden_
&& !front_item
.skip_in_browser
) {
2114 delegate_
->HandleKeyboardEvent(front_item
);
2116 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2117 // (i.e. in the case of Ctrl+W, where the call to
2118 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2123 void RenderWidgetHostImpl::ActivateDeferredPluginHandles() {
2124 #if !defined(USE_AURA)
2128 for (int i
= 0; i
< static_cast<int>(deferred_plugin_handles_
.size()); i
++) {
2129 #if defined(TOOLKIT_GTK)
2130 view_
->CreatePluginContainer(deferred_plugin_handles_
[i
]);
2134 deferred_plugin_handles_
.clear();
2138 const gfx::Vector2d
& RenderWidgetHostImpl::GetLastScrollOffset() const {
2139 return last_scroll_offset_
;
2142 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2143 // Always send a touch event if the renderer has a touch-event handler. It is
2144 // possible that a renderer stops listening to touch-events while there are
2145 // still events in the touch-queue. In such cases, the new events should still
2146 // get into the queue.
2147 return has_touch_handler_
|| !touch_event_queue_
->empty();
2150 void RenderWidgetHostImpl::StartUserGesture() {
2154 void RenderWidgetHostImpl::Stop() {
2155 Send(new ViewMsg_Stop(GetRoutingID()));
2158 void RenderWidgetHostImpl::SetBackground(const SkBitmap
& background
) {
2159 Send(new ViewMsg_SetBackground(GetRoutingID(), background
));
2162 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2163 const std::vector
<EditCommand
>& commands
) {
2164 Send(new ViewMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands
));
2167 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode
) {
2168 Send(new ViewMsg_SetAccessibilityMode(routing_id_
, mode
));
2171 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id
) {
2172 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id
));
2175 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id
) {
2176 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id
));
2179 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2180 int acc_obj_id
, gfx::Rect subfocus
) {
2181 Send(new AccessibilityMsg_ScrollToMakeVisible(
2182 GetRoutingID(), acc_obj_id
, subfocus
));
2185 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2186 int acc_obj_id
, gfx::Point point
) {
2187 Send(new AccessibilityMsg_ScrollToPoint(
2188 GetRoutingID(), acc_obj_id
, point
));
2191 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2192 int object_id
, int start_offset
, int end_offset
) {
2193 Send(new AccessibilityMsg_SetTextSelection(
2194 GetRoutingID(), object_id
, start_offset
, end_offset
));
2197 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string
& command
,
2198 const std::string
& value
) {
2199 Send(new ViewMsg_ExecuteEditCommand(GetRoutingID(), command
, value
));
2202 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2203 const gfx::Rect
& rect
) {
2204 Send(new ViewMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect
));
2207 void RenderWidgetHostImpl::SelectRange(const gfx::Point
& start
,
2208 const gfx::Point
& end
) {
2209 if (select_range_pending_
) {
2210 if (!next_selection_range_
.get()) {
2211 next_selection_range_
.reset(new SelectionRange());
2213 next_selection_range_
->start
= start
;
2214 next_selection_range_
->end
= end
;
2218 select_range_pending_
= true;
2219 Send(new ViewMsg_SelectRange(GetRoutingID(), start
, end
));
2222 void RenderWidgetHostImpl::Undo() {
2223 Send(new ViewMsg_Undo(GetRoutingID()));
2224 RecordAction(UserMetricsAction("Undo"));
2227 void RenderWidgetHostImpl::Redo() {
2228 Send(new ViewMsg_Redo(GetRoutingID()));
2229 RecordAction(UserMetricsAction("Redo"));
2232 void RenderWidgetHostImpl::Cut() {
2233 Send(new ViewMsg_Cut(GetRoutingID()));
2234 RecordAction(UserMetricsAction("Cut"));
2237 void RenderWidgetHostImpl::Copy() {
2238 Send(new ViewMsg_Copy(GetRoutingID()));
2239 RecordAction(UserMetricsAction("Copy"));
2242 void RenderWidgetHostImpl::CopyToFindPboard() {
2243 #if defined(OS_MACOSX)
2244 // Windows/Linux don't have the concept of a find pasteboard.
2245 Send(new ViewMsg_CopyToFindPboard(GetRoutingID()));
2246 RecordAction(UserMetricsAction("CopyToFindPboard"));
2250 void RenderWidgetHostImpl::Paste() {
2251 Send(new ViewMsg_Paste(GetRoutingID()));
2252 RecordAction(UserMetricsAction("Paste"));
2255 void RenderWidgetHostImpl::PasteAndMatchStyle() {
2256 Send(new ViewMsg_PasteAndMatchStyle(GetRoutingID()));
2257 RecordAction(UserMetricsAction("PasteAndMatchStyle"));
2260 void RenderWidgetHostImpl::Delete() {
2261 Send(new ViewMsg_Delete(GetRoutingID()));
2262 RecordAction(UserMetricsAction("DeleteSelection"));
2265 void RenderWidgetHostImpl::SelectAll() {
2266 Send(new ViewMsg_SelectAll(GetRoutingID()));
2267 RecordAction(UserMetricsAction("SelectAll"));
2269 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed
) {
2271 RejectMouseLockOrUnlockIfNecessary();
2274 if (!pending_mouse_lock_request_
) {
2275 // This is possible, e.g., the plugin sends us an unlock request before
2276 // the user allows to lock to mouse.
2280 pending_mouse_lock_request_
= false;
2281 if (!view_
|| !view_
->HasFocus()|| !view_
->LockMouse()) {
2282 Send(new ViewMsg_LockMouse_ACK(routing_id_
, false));
2285 Send(new ViewMsg_LockMouse_ACK(routing_id_
, true));
2292 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2293 int32 route_id
, int gpu_host_id
, bool presented
, uint32 sync_point
) {
2294 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(gpu_host_id
);
2296 ui_shim
->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id
,
2301 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2302 if (!is_threaded_compositing_enabled_
)
2303 Send(new ViewMsg_SwapBuffers_ACK(routing_id_
));
2306 #if defined(USE_AURA)
2308 void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent
) {
2310 HWND hwnd
= reinterpret_cast<HWND
>(new_parent
);
2312 hwnd
= WebPluginDelegateImpl::GetDefaultWindowParent();
2313 for (std::list
<HWND
>::iterator i
= dummy_windows_for_activation_
.begin();
2314 i
!= dummy_windows_for_activation_
.end(); ++i
) {
2315 SetParent(*i
, hwnd
);
2321 void RenderWidgetHostImpl::SendFrontSurfaceIsProtected(
2323 uint32 protection_state_id
,
2326 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(gpu_host_id
);
2328 ui_shim
->Send(new AcceleratedSurfaceMsg_SetFrontSurfaceIsProtected(
2329 route_id
, is_protected
, protection_state_id
));
2334 void RenderWidgetHostImpl::DelayedAutoResized() {
2335 gfx::Size new_size
= new_auto_size_
;
2336 // Clear the new_auto_size_ since the empty value is used as a flag to
2337 // indicate that no callback is in progress (i.e. without this line
2338 // DelayedAutoResized will not get called again).
2339 new_auto_size_
.SetSize(0, 0);
2340 if (!should_auto_resize_
)
2343 OnRenderAutoResized(new_size
);
2346 void RenderWidgetHostImpl::DetachDelegate() {
2350 } // namespace content