1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_impl.h"
11 #include "base/auto_reset.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/debug/trace_event.h"
16 #include "base/i18n/rtl.h"
17 #include "base/lazy_instance.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/histogram.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "cc/output/compositor_frame.h"
24 #include "cc/output/compositor_frame_ack.h"
25 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
26 #include "content/browser/gpu/compositor_util.h"
27 #include "content/browser/gpu/gpu_process_host.h"
28 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
29 #include "content/browser/gpu/gpu_surface_tracker.h"
30 #include "content/browser/renderer_host/backing_store.h"
31 #include "content/browser/renderer_host/backing_store_manager.h"
32 #include "content/browser/renderer_host/dip_util.h"
33 #include "content/browser/renderer_host/input/immediate_input_router.h"
34 #include "content/browser/renderer_host/overscroll_controller.h"
35 #include "content/browser/renderer_host/render_process_host_impl.h"
36 #include "content/browser/renderer_host/render_view_host_impl.h"
37 #include "content/browser/renderer_host/render_widget_helper.h"
38 #include "content/browser/renderer_host/render_widget_host_delegate.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/native_web_keyboard_event.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/render_widget_host_iterator.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/events/event.h"
57 #include "ui/events/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 "ui/snapshot/snapshot.h"
62 #include "webkit/common/cursors/webcursor.h"
63 #include "webkit/common/webpreferences.h"
65 #if defined(TOOLKIT_GTK)
66 #include "content/browser/renderer_host/backing_store_gtk.h"
67 #elif defined(OS_MACOSX)
68 #include "content/browser/renderer_host/backing_store_mac.h"
70 #include "content/common/plugin_constants_win.h"
74 using base::TimeDelta;
75 using base::TimeTicks;
76 using WebKit::WebGestureEvent;
77 using WebKit::WebInputEvent;
78 using WebKit::WebKeyboardEvent;
79 using WebKit::WebMouseEvent;
80 using WebKit::WebMouseWheelEvent;
81 using WebKit::WebTextDirection;
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 base::LazyInstance<std::vector<RenderWidgetHost::CreatedCallback> >
95 g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
97 typedef std::pair<int32, int32> RenderWidgetHostID;
98 typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
100 base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
101 LAZY_INSTANCE_INITIALIZER;
103 // Implements the RenderWidgetHostIterator interface. It keeps a list of
104 // RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
105 // iteration (or NULL if there isn't any left).
106 class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
108 RenderWidgetHostIteratorImpl()
109 : current_index_(0) {
112 virtual ~RenderWidgetHostIteratorImpl() {
115 void Add(RenderWidgetHost* host) {
116 hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
117 host->GetRoutingID()));
120 // RenderWidgetHostIterator:
121 virtual RenderWidgetHost* GetNextHost() OVERRIDE {
122 RenderWidgetHost* host = NULL;
123 while (current_index_ < hosts_.size() && !host) {
124 RenderWidgetHostID id = hosts_[current_index_];
125 host = RenderWidgetHost::FromID(id.first, id.second);
132 std::vector<RenderWidgetHostID> hosts_;
133 size_t current_index_;
135 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
142 void RenderWidgetHost::RemoveAllBackingStores() {
143 BackingStoreManager::RemoveAllBackingStores();
147 size_t RenderWidgetHost::BackingStoreMemorySize() {
148 return BackingStoreManager::MemorySize();
151 ///////////////////////////////////////////////////////////////////////////////
152 // RenderWidgetHostImpl
154 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
155 RenderProcessHost* process,
159 renderer_initialized_(false),
160 hung_renderer_delay_ms_(kHungRendererDelayMs),
163 routing_id_(routing_id),
167 is_fullscreen_(false),
168 is_accelerated_compositing_active_(false),
169 repaint_ack_pending_(false),
170 resize_ack_pending_(false),
171 screen_info_out_of_date_(false),
172 overdraw_bottom_height_(0.f),
173 should_auto_resize_(false),
174 waiting_for_screen_rects_ack_(false),
175 accessibility_mode_(AccessibilityModeOff),
176 needs_repainting_on_restore_(false),
177 is_unresponsive_(false),
178 in_flight_event_count_(0),
179 in_get_backing_store_(false),
180 abort_get_backing_store_(false),
181 view_being_painted_(false),
182 ignore_input_events_(false),
183 input_method_active_(false),
184 text_direction_updated_(false),
185 text_direction_(WebKit::WebTextDirectionLeftToRight),
186 text_direction_canceled_(false),
187 suppress_next_char_events_(false),
188 pending_mouse_lock_request_(false),
189 allow_privileged_mouse_lock_(false),
190 has_touch_handler_(false),
192 last_input_number_(0) {
194 if (routing_id_ == MSG_ROUTING_NONE) {
195 routing_id_ = process_->GetNextRoutingID();
196 surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
200 // TODO(piman): This is a O(N) lookup, where we could forward the
201 // information from the RenderWidgetHelper. The problem is that doing so
202 // currently leaks outside of content all the way to chrome classes, and
203 // would be a layering violation. Since we don't expect more than a few
204 // hundreds of RWH, this seems acceptable. Revisit if performance become a
205 // problem, for example by tracking in the RenderWidgetHelper the routing id
206 // (and surface id) that have been created, but whose RWH haven't yet.
207 surface_id_ = GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
213 is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled();
216 g_routing_id_widget_map.Get().insert(std::make_pair(
217 RenderWidgetHostID(process->GetID(), routing_id_), this));
218 process_->AddRoute(routing_id_, this);
220 // If we're initially visible, tell the process host that we're alive.
221 // Otherwise we'll notify the process host when we are first shown.
223 process_->WidgetRestored();
225 accessibility_mode_ =
226 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
228 for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
229 g_created_callbacks.Get().at(i).Run(this);
232 new ImmediateInputRouter(process_, this, this, routing_id_));
234 #if defined(USE_AURA)
235 bool overscroll_enabled = CommandLine::ForCurrentProcess()->
236 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
237 SetOverscrollControllerEnabled(overscroll_enabled);
241 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
244 // Clear our current or cached backing store if either remains.
245 BackingStoreManager::RemoveBackingStore(this);
247 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
250 process_->RemoveRoute(routing_id_);
251 g_routing_id_widget_map.Get().erase(
252 RenderWidgetHostID(process_->GetID(), routing_id_));
255 delegate_->RenderWidgetDeleted(this);
259 RenderWidgetHost* RenderWidgetHost::FromID(
262 return RenderWidgetHostImpl::FromID(process_id, routing_id);
266 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
270 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
271 RoutingIDWidgetMap::iterator it = widgets->find(
272 RenderWidgetHostID(process_id, routing_id));
273 return it == widgets->end() ? NULL : it->second;
277 scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
278 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
279 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
280 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
281 it != widgets->end();
283 RenderWidgetHost* widget = it->second;
285 if (!widget->IsRenderView()) {
290 // Add only active RenderViewHosts.
291 RenderViewHost* rvh = RenderViewHost::From(widget);
292 if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
296 return scoped_ptr<RenderWidgetHostIterator>(hosts);
300 scoped_ptr<RenderWidgetHostIterator>
301 RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
302 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
303 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
304 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
305 it != widgets->end();
307 hosts->Add(it->second);
310 return scoped_ptr<RenderWidgetHostIterator>(hosts);
314 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
315 return rwh->AsRenderWidgetHostImpl();
319 void RenderWidgetHost::AddCreatedCallback(const CreatedCallback& callback) {
320 g_created_callbacks.Get().push_back(callback);
324 void RenderWidgetHost::RemoveCreatedCallback(const CreatedCallback& callback) {
325 for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
326 if (g_created_callbacks.Get().at(i).Equals(callback)) {
327 g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
333 void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
334 view_ = RenderWidgetHostViewPort::FromRWHV(view);
337 GpuSurfaceTracker::Get()->SetSurfaceHandle(
338 surface_id_, gfx::GLSurfaceHandle());
342 RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
346 int RenderWidgetHostImpl::GetRoutingID() const {
350 RenderWidgetHostView* RenderWidgetHostImpl::GetView() const {
354 RenderWidgetHostImpl* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
358 gfx::NativeViewId RenderWidgetHostImpl::GetNativeViewId() const {
360 return view_->GetNativeViewId();
364 gfx::GLSurfaceHandle RenderWidgetHostImpl::GetCompositingSurface() {
366 return view_->GetCompositingSurface();
367 return gfx::GLSurfaceHandle();
370 void RenderWidgetHostImpl::CompositingSurfaceUpdated() {
371 GpuSurfaceTracker::Get()->SetSurfaceHandle(
372 surface_id_, GetCompositingSurface());
373 process_->SurfaceUpdated(surface_id_);
376 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
377 resize_ack_pending_ = false;
378 if (repaint_ack_pending_) {
379 TRACE_EVENT_ASYNC_END0(
380 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
382 repaint_ack_pending_ = false;
383 last_requested_size_.SetSize(0, 0);
386 void RenderWidgetHostImpl::SendScreenRects() {
387 if (!renderer_initialized_ || waiting_for_screen_rects_ack_)
391 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
392 // happens on Win & Mac, and when the view is shown it'll call this again.
399 last_view_screen_rect_ = view_->GetViewBounds();
400 last_window_screen_rect_ = view_->GetBoundsInRootWindow();
401 Send(new ViewMsg_UpdateScreenRects(
402 GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
404 delegate_->DidSendScreenRects(this);
405 waiting_for_screen_rects_ack_ = true;
409 RenderWidgetHostImpl::GetSyntheticGestureMessageInterval() const {
410 return synthetic_gesture_controller_.GetSyntheticGestureMessageInterval();
413 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
415 overscroll_controller_.reset();
416 else if (!overscroll_controller_)
417 overscroll_controller_.reset(new OverscrollController());
420 void RenderWidgetHostImpl::SuppressNextCharEvents() {
421 suppress_next_char_events_ = true;
424 void RenderWidgetHostImpl::FlushInput() {
425 input_router_->Flush();
428 void RenderWidgetHostImpl::Init() {
429 DCHECK(process_->HasConnection());
431 renderer_initialized_ = true;
433 GpuSurfaceTracker::Get()->SetSurfaceHandle(
434 surface_id_, GetCompositingSurface());
436 // Send the ack along with the information on placement.
437 Send(new ViewMsg_CreatingNew_ACK(routing_id_));
438 GetProcess()->ResumeRequestsForView(routing_id_);
443 void RenderWidgetHostImpl::Shutdown() {
444 RejectMouseLockOrUnlockIfNecessary();
446 if (process_->HasConnection()) {
447 // Tell the renderer object to close.
448 bool rv = Send(new ViewMsg_Close(routing_id_));
455 bool RenderWidgetHostImpl::IsLoading() const {
459 bool RenderWidgetHostImpl::IsRenderView() const {
463 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
465 bool msg_is_ok = true;
466 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl, msg, msg_is_ok)
467 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
468 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
469 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
470 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
471 OnUpdateScreenRectsAck)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
473 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
474 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK, OnPaintAtSizeAck)
475 #if defined(OS_MACOSX)
476 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
477 OnCompositorSurfaceBuffersSwapped)
479 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
480 msg_is_ok = OnSwapCompositorFrame(msg))
481 IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
482 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
483 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
484 IPC_MESSAGE_HANDLER(ViewHostMsg_BeginSmoothScroll, OnBeginSmoothScroll)
485 IPC_MESSAGE_HANDLER(ViewHostMsg_BeginPinch, OnBeginPinch)
486 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
487 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
488 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
489 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
490 OnTextInputTypeChanged)
491 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
492 OnImeCancelComposition)
493 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing,
494 OnDidActivateAcceleratedCompositing)
495 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
497 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
498 OnShowDisambiguationPopup)
500 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
501 OnWindowlessPluginDummyWindowCreated)
502 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
503 OnWindowlessPluginDummyWindowDestroyed)
505 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
506 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
507 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
508 OnImeCompositionRangeChanged)
510 IPC_MESSAGE_UNHANDLED(handled = false)
511 IPC_END_MESSAGE_MAP_EX()
513 if (!handled && input_router_ && input_router_->OnMessageReceived(msg))
516 if (!handled && view_ && view_->OnMessageReceived(msg))
520 // The message de-serialization failed. Kill the renderer process.
521 RecordAction(UserMetricsAction("BadMessageTerminate_RWH"));
522 GetProcess()->ReceivedBadMessage();
527 bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
528 if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
529 return input_router_->SendInput(make_scoped_ptr(msg));
531 return process_->Send(msg);
534 void RenderWidgetHostImpl::WasHidden() {
540 // Don't bother reporting hung state when we aren't active.
541 StopHangMonitorTimeout();
543 // If we have a renderer, then inform it that we are being hidden so it can
544 // reduce its resource utilization.
545 Send(new ViewMsg_WasHidden(routing_id_));
547 // Tell the RenderProcessHost we were hidden.
548 process_->WidgetHidden();
550 bool is_visible = false;
551 NotificationService::current()->Notify(
552 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
553 Source<RenderWidgetHost>(this),
554 Details<bool>(&is_visible));
557 void RenderWidgetHostImpl::WasShown() {
564 BackingStore* backing_store = BackingStoreManager::Lookup(this);
565 // If we already have a backing store for this widget, then we don't need to
566 // repaint on restore _unless_ we know that our backing store is invalid.
567 // When accelerated compositing is on, we must always repaint, even when
568 // the backing store exists.
569 bool needs_repainting;
570 if (needs_repainting_on_restore_ || !backing_store ||
571 is_accelerated_compositing_active()) {
572 needs_repainting = true;
573 needs_repainting_on_restore_ = false;
575 needs_repainting = false;
577 Send(new ViewMsg_WasShown(routing_id_, needs_repainting));
579 process_->WidgetRestored();
581 bool is_visible = true;
582 NotificationService::current()->Notify(
583 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
584 Source<RenderWidgetHost>(this),
585 Details<bool>(&is_visible));
587 // It's possible for our size to be out of sync with the renderer. The
588 // following is one case that leads to this:
589 // 1. WasResized -> Send ViewMsg_Resize to render
590 // 2. WasResized -> do nothing as resize_ack_pending_ is true
592 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
593 // is hidden. Now renderer/browser out of sync with what they think size
595 // By invoking WasResized the renderer is updated as necessary. WasResized
596 // does nothing if the sizes are already in sync.
598 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
599 // could handle both the restore and resize at once. This isn't that big a
600 // deal as RenderWidget::WasShown delays updating, so that the resize from
601 // WasResized is usually processed before the renderer is painted.
605 void RenderWidgetHostImpl::WasResized() {
606 // Skip if the |delegate_| has already been detached because
607 // it's web contents is being deleted.
608 if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
609 !renderer_initialized_ || should_auto_resize_ || !delegate_) {
613 gfx::Rect view_bounds = view_->GetViewBounds();
614 gfx::Size new_size(view_bounds.size());
616 gfx::Size old_physical_backing_size = physical_backing_size_;
617 physical_backing_size_ = view_->GetPhysicalBackingSize();
618 bool was_fullscreen = is_fullscreen_;
619 is_fullscreen_ = IsFullscreen();
620 float old_overdraw_bottom_height = overdraw_bottom_height_;
621 overdraw_bottom_height_ = view_->GetOverdrawBottomHeight();
623 bool size_changed = new_size != last_requested_size_;
624 bool side_payload_changed =
625 screen_info_out_of_date_ ||
626 old_physical_backing_size != physical_backing_size_ ||
627 was_fullscreen != is_fullscreen_ ||
628 old_overdraw_bottom_height != overdraw_bottom_height_;
630 if (!size_changed && !side_payload_changed)
634 screen_info_.reset(new WebKit::WebScreenInfo);
635 GetWebScreenInfo(screen_info_.get());
638 // We don't expect to receive an ACK when the requested size or the physical
639 // backing size is empty, or when the main viewport size didn't change.
640 if (!new_size.IsEmpty() && !physical_backing_size_.IsEmpty() && size_changed)
641 resize_ack_pending_ = g_check_for_pending_resize_ack;
643 ViewMsg_Resize_Params params;
644 params.screen_info = *screen_info_;
645 params.new_size = new_size;
646 params.physical_backing_size = physical_backing_size_;
647 params.overdraw_bottom_height = overdraw_bottom_height_;
648 params.resizer_rect = GetRootWindowResizerRect();
649 params.is_fullscreen = is_fullscreen_;
650 if (!Send(new ViewMsg_Resize(routing_id_, params))) {
651 resize_ack_pending_ = false;
653 last_requested_size_ = new_size;
657 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
658 Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
661 void RenderWidgetHostImpl::GotFocus() {
665 void RenderWidgetHostImpl::Focus() {
666 Send(new InputMsg_SetFocus(routing_id_, true));
669 void RenderWidgetHostImpl::Blur() {
670 // If there is a pending mouse lock request, we don't want to reject it at
671 // this point. The user can switch focus back to this view and approve the
674 view_->UnlockMouse();
676 // If there is a pending overscroll, then that should be cancelled.
677 if (overscroll_controller_)
678 overscroll_controller_->Cancel();
680 Send(new InputMsg_SetFocus(routing_id_, false));
683 void RenderWidgetHostImpl::LostCapture() {
684 Send(new InputMsg_MouseCaptureLost(routing_id_));
687 void RenderWidgetHostImpl::SetActive(bool active) {
688 Send(new ViewMsg_SetActive(routing_id_, active));
691 void RenderWidgetHostImpl::LostMouseLock() {
692 Send(new ViewMsg_MouseLockLost(routing_id_));
695 void RenderWidgetHostImpl::ViewDestroyed() {
696 RejectMouseLockOrUnlockIfNecessary();
698 // TODO(evanm): tracking this may no longer be necessary;
699 // eliminate this function if so.
703 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
704 is_loading_ = is_loading;
707 view_->SetIsLoading(is_loading);
710 void RenderWidgetHostImpl::CopyFromBackingStore(
711 const gfx::Rect& src_subrect,
712 const gfx::Size& accelerated_dst_size,
713 const base::Callback<void(bool, const SkBitmap&)>& callback) {
714 if (view_ && is_accelerated_compositing_active_) {
715 TRACE_EVENT0("browser",
716 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
717 gfx::Rect accelerated_copy_rect = src_subrect.IsEmpty() ?
718 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
719 view_->CopyFromCompositingSurface(accelerated_copy_rect,
720 accelerated_dst_size,
725 BackingStore* backing_store = GetBackingStore(false);
726 if (!backing_store) {
727 callback.Run(false, SkBitmap());
731 TRACE_EVENT0("browser",
732 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
733 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
734 gfx::Rect(backing_store->size()) : src_subrect;
735 // When the result size is equal to the backing store size, copy from the
736 // backing store directly to the output canvas.
737 skia::PlatformBitmap output;
738 bool result = backing_store->CopyFromBackingStore(copy_rect, &output);
739 callback.Run(result, output.GetBitmap());
742 #if defined(TOOLKIT_GTK)
743 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
744 const gfx::Rect& dest_rect, GdkWindow* target) {
745 BackingStore* backing_store = GetBackingStore(false);
748 (static_cast<BackingStoreGtk*>(backing_store))->PaintToRect(
752 #elif defined(OS_MACOSX)
753 gfx::Size RenderWidgetHostImpl::GetBackingStoreSize() {
754 BackingStore* backing_store = GetBackingStore(false);
755 return backing_store ? backing_store->size() : gfx::Size();
758 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
759 const CGRect& dest_rect, CGContextRef target) {
760 BackingStore* backing_store = GetBackingStore(false);
763 (static_cast<BackingStoreMac*>(backing_store))->
764 CopyFromBackingStoreToCGContext(dest_rect, target);
769 void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle,
771 const gfx::Size& page_size,
772 const gfx::Size& desired_size) {
773 // Ask the renderer to create a bitmap regardless of whether it's
774 // hidden, being resized, redrawn, etc. It resizes the web widget
775 // to the page_size and then scales it to the desired_size.
776 Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, tag,
777 page_size, desired_size));
780 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
781 BackingStore** backing_store) {
782 // Check if the view has an accelerated surface of the desired size.
783 if (view_->HasAcceleratedSurface(desired_size)) {
784 *backing_store = NULL;
788 // Check for a software backing store of the desired size.
789 *backing_store = BackingStoreManager::GetBackingStore(this, desired_size);
790 return !!*backing_store;
793 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
797 // The view_size will be current_size_ for auto-sized views and otherwise the
798 // size of the view_. (For auto-sized views, current_size_ is updated during
799 // UpdateRect messages.)
800 gfx::Size view_size = current_size_;
801 if (!should_auto_resize_) {
802 // Get the desired size from the current view bounds.
803 gfx::Rect view_rect = view_->GetViewBounds();
804 if (view_rect.IsEmpty())
806 view_size = view_rect.size();
809 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
810 "width", base::IntToString(view_size.width()),
811 "height", base::IntToString(view_size.height()));
813 // We should not be asked to paint while we are hidden. If we are hidden,
814 // then it means that our consumer failed to call WasShown. If we're not
815 // force creating the backing store, it's OK since we can feel free to give
816 // out our cached one if we have it.
817 DCHECK(!is_hidden_ || !force_create) <<
818 "GetBackingStore called while hidden!";
820 // We should never be called recursively; this can theoretically lead to
821 // infinite recursion and almost certainly leads to lower performance.
822 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!";
823 base::AutoReset<bool> auto_reset_in_get_backing_store(
824 &in_get_backing_store_, true);
826 // We might have a cached backing store that we can reuse!
827 BackingStore* backing_store = NULL;
828 if (TryGetBackingStore(view_size, &backing_store) || !force_create)
829 return backing_store;
831 // We do not have a suitable backing store in the cache, so send out a
832 // request to the renderer to paint the view if required.
833 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
834 repaint_start_time_ = TimeTicks::Now();
835 repaint_ack_pending_ = true;
836 TRACE_EVENT_ASYNC_BEGIN0(
837 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
838 Send(new ViewMsg_Repaint(routing_id_, view_size));
841 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
842 TimeTicks end_time = TimeTicks::Now() + max_delay;
844 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
846 #if defined(OS_MACOSX)
847 view_->AboutToWaitForBackingStoreMsg();
850 // When we have asked the RenderWidget to resize, and we are still waiting
851 // on a response, block for a little while to see if we can't get a response
852 // before returning the old (incorrectly sized) backing store.
854 if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
855 OnMessageReceived(msg);
857 // For auto-resized views, current_size_ determines the view_size and it
858 // may have changed during the handling of an UpdateRect message.
859 if (should_auto_resize_)
860 view_size = current_size_;
862 // Break now if we got a backing store or accelerated surface of the
864 if (TryGetBackingStore(view_size, &backing_store) ||
865 abort_get_backing_store_) {
866 abort_get_backing_store_ = false;
867 return backing_store;
870 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
874 // Loop if we still have time left and haven't gotten a properly sized
875 // BackingStore yet. This is necessary to support the GPU path which
876 // typically has multiple frames pipelined -- we may need to skip one or two
877 // BackingStore messages to get to the latest.
878 max_delay = end_time - TimeTicks::Now();
879 } while (max_delay > TimeDelta::FromSeconds(0));
881 // We have failed to get a backing store of view_size. Fall back on
882 // current_size_ to avoid a white flash while resizing slow pages.
883 if (view_size != current_size_)
884 TryGetBackingStore(current_size_, &backing_store);
885 return backing_store;
888 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) {
891 return view_->AllocBackingStore(size);
894 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
895 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
898 bool RenderWidgetHostImpl::ScheduleComposite() {
899 if (is_hidden_ || !is_accelerated_compositing_active_ ||
900 current_size_.IsEmpty() || repaint_ack_pending_ ||
901 resize_ack_pending_ || view_being_painted_) {
905 // Send out a request to the renderer to paint the view if required.
906 repaint_start_time_ = TimeTicks::Now();
907 repaint_ack_pending_ = true;
908 TRACE_EVENT_ASYNC_BEGIN0(
909 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
910 Send(new ViewMsg_Repaint(routing_id_, current_size_));
914 void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) {
915 if (!GetProcess()->IsGuest() && CommandLine::ForCurrentProcess()->HasSwitch(
916 switches::kDisableHangMonitor)) {
920 // Set time_when_considered_hung_ if it's null. Also, update
921 // time_when_considered_hung_ if the caller's request is sooner than the
922 // existing one. This will have the side effect that the existing timeout will
924 Time requested_end_time = Time::Now() + delay;
925 if (time_when_considered_hung_.is_null() ||
926 time_when_considered_hung_ > requested_end_time)
927 time_when_considered_hung_ = requested_end_time;
929 // If we already have a timer with the same or shorter duration, then we can
930 // wait for it to finish.
931 if (hung_renderer_timer_.IsRunning() &&
932 hung_renderer_timer_.GetCurrentDelay() <= delay) {
933 // If time_when_considered_hung_ was null, this timer may fire early.
934 // CheckRendererIsUnresponsive handles that by calling
935 // StartHangMonitorTimeout with the remaining time.
936 // If time_when_considered_hung_ was non-null, it means we still haven't
937 // heard from the renderer so we leave time_when_considered_hung_ as is.
941 // Either the timer is not yet running, or we need to adjust the timer to
943 time_when_considered_hung_ = requested_end_time;
944 hung_renderer_timer_.Stop();
945 hung_renderer_timer_.Start(FROM_HERE, delay, this,
946 &RenderWidgetHostImpl::CheckRendererIsUnresponsive);
949 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
950 // Setting to null will cause StartHangMonitorTimeout to restart the timer.
951 time_when_considered_hung_ = Time();
952 StartHangMonitorTimeout(
953 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
956 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
957 time_when_considered_hung_ = Time();
958 RendererIsResponsive();
959 // We do not bother to stop the hung_renderer_timer_ here in case it will be
960 // started again shortly, which happens to be the common use case.
963 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
964 SetAccessibilityMode(AccessibilityModeComplete);
967 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
968 ForwardMouseEventWithLatencyInfo(
969 MouseEventWithLatencyInfo(mouse_event,
970 CreateRWHLatencyInfoIfNotExist(NULL)));
973 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
974 const MouseEventWithLatencyInfo& mouse_event) {
975 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
976 "x", mouse_event.event.x, "y", mouse_event.event.y);
978 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
979 if (mouse_event_callbacks_[i].Run(mouse_event.event))
983 if (IgnoreInputEvents())
986 input_router_->SendMouseEvent(mouse_event);
989 void RenderWidgetHostImpl::OnPointerEventActivate() {
992 void RenderWidgetHostImpl::ForwardWheelEvent(
993 const WebMouseWheelEvent& wheel_event) {
994 ForwardWheelEventWithLatencyInfo(
995 MouseWheelEventWithLatencyInfo(wheel_event,
996 CreateRWHLatencyInfoIfNotExist(NULL)));
999 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
1000 const MouseWheelEventWithLatencyInfo& wheel_event) {
1001 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
1002 if (IgnoreInputEvents())
1005 if (delegate_->PreHandleWheelEvent(wheel_event.event))
1008 input_router_->SendWheelEvent(wheel_event);
1011 void RenderWidgetHostImpl::ForwardGestureEvent(
1012 const WebKit::WebGestureEvent& gesture_event) {
1013 ForwardGestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo());
1016 void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
1017 const WebKit::WebGestureEvent& gesture_event,
1018 const ui::LatencyInfo& ui_latency) {
1019 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
1020 // Early out if necessary, prior to performing latency logic.
1021 if (IgnoreInputEvents())
1024 ui::LatencyInfo latency_info = CreateRWHLatencyInfoIfNotExist(&ui_latency);
1026 if (gesture_event.type == WebKit::WebInputEvent::GestureScrollUpdate) {
1027 latency_info.AddLatencyNumber(
1028 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
1029 GetLatencyComponentId(),
1030 ++last_input_number_);
1032 // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
1033 // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
1034 // So we can track the latency specifically for scroll update events.
1035 ui::LatencyInfo::LatencyComponent original_component;
1036 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
1038 &original_component)) {
1039 latency_info.AddLatencyNumberWithTimestamp(
1040 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
1041 GetLatencyComponentId(),
1042 original_component.sequence_number,
1043 original_component.event_time,
1044 original_component.event_count,
1049 GestureEventWithLatencyInfo gesture_with_latency(gesture_event, latency_info);
1050 input_router_->SendGestureEvent(gesture_with_latency);
1053 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1054 const WebKit::WebTouchEvent& touch_event,
1055 const ui::LatencyInfo& ui_latency) {
1056 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1058 // Always forward TouchEvents for touch stream consistency. They will be
1059 // ignored if appropriate in FilterInputEvent().
1061 ui::LatencyInfo latency_info = CreateRWHLatencyInfoIfNotExist(&ui_latency);
1062 TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
1063 input_router_->SendTouchEvent(touch_with_latency);
1066 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1067 const NativeWebKeyboardEvent& key_event) {
1068 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1069 if (IgnoreInputEvents())
1072 if (!process_->HasConnection())
1075 // First, let keypress listeners take a shot at handling the event. If a
1076 // listener handles the event, it should not be propagated to the renderer.
1077 if (KeyPressListenersHandleEvent(key_event)) {
1078 // Some keypresses that are accepted by the listener might have follow up
1079 // char events, which should be ignored.
1080 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1081 suppress_next_char_events_ = true;
1085 if (key_event.type == WebKeyboardEvent::Char &&
1086 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
1087 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
1091 // Double check the type to make sure caller hasn't sent us nonsense that
1092 // will mess up our key queue.
1093 if (!WebInputEvent::isKeyboardEventType(key_event.type))
1096 if (suppress_next_char_events_) {
1097 // If preceding RawKeyDown event was handled by the browser, then we need
1098 // suppress all Char events generated by it. Please note that, one
1099 // RawKeyDown event may generate multiple Char events, so we can't reset
1100 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1101 if (key_event.type == WebKeyboardEvent::Char)
1103 // We get a KeyUp or a RawKeyDown event.
1104 suppress_next_char_events_ = false;
1107 bool is_shortcut = false;
1109 // Only pre-handle the key event if it's not handled by the input method.
1110 if (delegate_ && !key_event.skip_in_browser) {
1111 // We need to set |suppress_next_char_events_| to true if
1112 // PreHandleKeyboardEvent() returns true, but |this| may already be
1113 // destroyed at that time. So set |suppress_next_char_events_| true here,
1114 // then revert it afterwards when necessary.
1115 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1116 suppress_next_char_events_ = true;
1118 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1119 // a hung/malicious renderer from interfering.
1120 if (delegate_->PreHandleKeyboardEvent(key_event, &is_shortcut))
1123 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1124 suppress_next_char_events_ = false;
1127 input_router_->SendKeyboardEvent(key_event,
1128 CreateRWHLatencyInfoIfNotExist(NULL),
1132 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
1133 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
1136 int64 RenderWidgetHostImpl::GetLatencyComponentId() {
1137 return GetRoutingID() | (static_cast<int64>(GetProcess()->GetID()) << 32);
1141 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1142 g_check_for_pending_resize_ack = false;
1145 ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
1146 const ui::LatencyInfo* original) {
1147 ui::LatencyInfo info;
1150 // In Aura, gesture event will already carry its original touch event's
1151 // INPUT_EVENT_LATENCY_RWH_COMPONENT.
1152 if (!info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1153 GetLatencyComponentId(),
1155 info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1156 GetLatencyComponentId(),
1157 ++last_input_number_);
1163 void RenderWidgetHostImpl::AddKeyPressEventCallback(
1164 const KeyPressEventCallback& callback) {
1165 key_press_event_callbacks_.push_back(callback);
1168 void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
1169 const KeyPressEventCallback& callback) {
1170 for (size_t i = 0; i < key_press_event_callbacks_.size(); ++i) {
1171 if (key_press_event_callbacks_[i].Equals(callback)) {
1172 key_press_event_callbacks_.erase(
1173 key_press_event_callbacks_.begin() + i);
1179 void RenderWidgetHostImpl::AddMouseEventCallback(
1180 const MouseEventCallback& callback) {
1181 mouse_event_callbacks_.push_back(callback);
1184 void RenderWidgetHostImpl::RemoveMouseEventCallback(
1185 const MouseEventCallback& callback) {
1186 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
1187 if (mouse_event_callbacks_[i].Equals(callback)) {
1188 mouse_event_callbacks_.erase(mouse_event_callbacks_.begin() + i);
1194 void RenderWidgetHostImpl::GetWebScreenInfo(WebKit::WebScreenInfo* result) {
1195 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1197 static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
1199 RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
1200 screen_info_out_of_date_ = false;
1203 const NativeWebKeyboardEvent*
1204 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1205 return input_router_->GetLastKeyboardEvent();
1208 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1209 // The resize message (which may not happen immediately) will carry with it
1210 // the screen info as well as the new size (if the screen has changed scale
1212 InvalidateScreenInfo();
1216 void RenderWidgetHostImpl::InvalidateScreenInfo() {
1217 screen_info_out_of_date_ = true;
1218 screen_info_.reset();
1221 void RenderWidgetHostImpl::GetSnapshotFromRenderer(
1222 const gfx::Rect& src_subrect,
1223 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1224 TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
1226 callback.Run(false, SkBitmap());
1230 pending_snapshots_.push(callback);
1232 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
1233 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
1235 gfx::Rect copy_rect_in_pixel = ConvertViewRectToPixel(view_, copy_rect);
1236 Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel));
1239 void RenderWidgetHostImpl::OnSnapshot(bool success,
1240 const SkBitmap& bitmap) {
1241 if (pending_snapshots_.size() == 0) {
1242 LOG(ERROR) << "RenderWidgetHostImpl::OnSnapshot: "
1243 "Received a snapshot that was not requested.";
1247 base::Callback<void(bool, const SkBitmap&)> callback =
1248 pending_snapshots_.front();
1249 pending_snapshots_.pop();
1252 callback.Run(success, SkBitmap());
1256 callback.Run(success, bitmap);
1259 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase,
1260 base::TimeDelta interval) {
1261 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase, interval));
1264 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
1266 // Clearing this flag causes us to re-create the renderer when recovering
1267 // from a crashed renderer.
1268 renderer_initialized_ = false;
1270 waiting_for_screen_rects_ack_ = false;
1272 // Reset to ensure that input routing works with a new renderer.
1273 input_router_.reset(
1274 new ImmediateInputRouter(process_, this, this, routing_id_));
1276 if (overscroll_controller_)
1277 overscroll_controller_->Reset();
1279 // Must reset these to ensure that keyboard events work with a new renderer.
1280 suppress_next_char_events_ = false;
1282 // Reset some fields in preparation for recovering from a crash.
1283 ResetSizeAndRepaintPendingFlags();
1284 current_size_.SetSize(0, 0);
1286 is_accelerated_compositing_active_ = false;
1288 // Reset this to ensure the hung renderer mechanism is working properly.
1289 in_flight_event_count_ = 0;
1292 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_,
1293 gfx::GLSurfaceHandle());
1294 view_->RenderProcessGone(status, exit_code);
1295 view_ = NULL; // The View should be deleted by RenderProcessGone.
1298 BackingStoreManager::RemoveBackingStore(this);
1301 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction) {
1302 text_direction_updated_ = true;
1303 text_direction_ = direction;
1306 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1307 if (text_direction_updated_)
1308 text_direction_canceled_ = true;
1311 void RenderWidgetHostImpl::NotifyTextDirection() {
1312 if (text_direction_updated_) {
1313 if (!text_direction_canceled_)
1314 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_));
1315 text_direction_updated_ = false;
1316 text_direction_canceled_ = false;
1320 void RenderWidgetHostImpl::SetInputMethodActive(bool activate) {
1321 input_method_active_ = activate;
1322 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate));
1325 void RenderWidgetHostImpl::ImeSetComposition(
1326 const string16& text,
1327 const std::vector<WebKit::WebCompositionUnderline>& underlines,
1328 int selection_start,
1329 int selection_end) {
1330 Send(new ViewMsg_ImeSetComposition(
1331 GetRoutingID(), text, underlines, selection_start, selection_end));
1334 void RenderWidgetHostImpl::ImeConfirmComposition(
1335 const string16& text,
1336 const gfx::Range& replacement_range,
1337 bool keep_selection) {
1338 Send(new ViewMsg_ImeConfirmComposition(
1339 GetRoutingID(), text, replacement_range, keep_selection));
1342 void RenderWidgetHostImpl::ImeCancelComposition() {
1343 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(),
1344 std::vector<WebKit::WebCompositionUnderline>(), 0, 0));
1347 void RenderWidgetHostImpl::ExtendSelectionAndDelete(
1350 Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before, after));
1353 gfx::Rect RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1357 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture,
1358 bool last_unlocked_by_target) {
1359 // Directly reject to lock the mouse. Subclass can override this method to
1360 // decide whether to allow mouse lock or not.
1361 GotResponseToLockMouseRequest(false);
1364 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1365 DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
1366 if (pending_mouse_lock_request_) {
1367 pending_mouse_lock_request_ = false;
1368 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1369 } else if (IsMouseLocked()) {
1370 view_->UnlockMouse();
1374 bool RenderWidgetHostImpl::IsMouseLocked() const {
1375 return view_ ? view_->IsMouseLocked() : false;
1378 bool RenderWidgetHostImpl::IsFullscreen() const {
1382 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
1383 should_auto_resize_ = enable;
1386 void RenderWidgetHostImpl::Destroy() {
1387 NotificationService::current()->Notify(
1388 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1389 Source<RenderWidgetHost>(this),
1390 NotificationService::NoDetails());
1392 // Tell the view to die.
1393 // Note that in the process of the view shutting down, it can call a ton
1394 // of other messages on us. So if you do any other deinitialization here,
1395 // do it after this call to view_->Destroy().
1402 void RenderWidgetHostImpl::CheckRendererIsUnresponsive() {
1403 // If we received a call to StopHangMonitorTimeout.
1404 if (time_when_considered_hung_.is_null())
1407 // If we have not waited long enough, then wait some more.
1408 Time now = Time::Now();
1409 if (now < time_when_considered_hung_) {
1410 StartHangMonitorTimeout(time_when_considered_hung_ - now);
1414 // OK, looks like we have a hung renderer!
1415 NotificationService::current()->Notify(
1416 NOTIFICATION_RENDERER_PROCESS_HANG,
1417 Source<RenderWidgetHost>(this),
1418 NotificationService::NoDetails());
1419 is_unresponsive_ = true;
1420 NotifyRendererUnresponsive();
1423 void RenderWidgetHostImpl::RendererIsResponsive() {
1424 if (is_unresponsive_) {
1425 is_unresponsive_ = false;
1426 NotifyRendererResponsive();
1430 void RenderWidgetHostImpl::OnRenderViewReady() {
1435 void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
1436 // TODO(evanm): This synchronously ends up calling "delete this".
1437 // Is that really what we want in response to this message? I'm matching
1438 // previous behavior of the code here.
1442 void RenderWidgetHostImpl::OnClose() {
1446 void RenderWidgetHostImpl::OnSetTooltipText(
1447 const string16& tooltip_text,
1448 WebTextDirection text_direction_hint) {
1449 // First, add directionality marks around tooltip text if necessary.
1450 // A naive solution would be to simply always wrap the text. However, on
1451 // windows, Unicode directional embedding characters can't be displayed on
1452 // systems that lack RTL fonts and are instead displayed as empty squares.
1454 // To get around this we only wrap the string when we deem it necessary i.e.
1455 // when the locale direction is different than the tooltip direction hint.
1457 // Currently, we use element's directionality as the tooltip direction hint.
1458 // An alternate solution would be to set the overall directionality based on
1459 // trying to detect the directionality from the tooltip text rather than the
1460 // element direction. One could argue that would be a preferable solution
1461 // but we use the current approach to match Fx & IE's behavior.
1462 string16 wrapped_tooltip_text = tooltip_text;
1463 if (!tooltip_text.empty()) {
1464 if (text_direction_hint == WebKit::WebTextDirectionLeftToRight) {
1465 // Force the tooltip to have LTR directionality.
1466 wrapped_tooltip_text =
1467 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
1468 } else if (text_direction_hint == WebKit::WebTextDirectionRightToLeft &&
1469 !base::i18n::IsRTL()) {
1470 // Force the tooltip to have RTL directionality.
1471 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
1475 view_->SetTooltipText(wrapped_tooltip_text);
1478 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1479 waiting_for_screen_rects_ack_ = false;
1483 if (view_->GetViewBounds() == last_view_screen_rect_ &&
1484 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
1491 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
1493 view_->SetBounds(pos);
1494 Send(new ViewMsg_Move_ACK(routing_id_));
1498 void RenderWidgetHostImpl::OnPaintAtSizeAck(int tag, const gfx::Size& size) {
1499 std::pair<int, gfx::Size> details = std::make_pair(tag, size);
1500 NotificationService::current()->Notify(
1501 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
1502 Source<RenderWidgetHost>(this),
1503 Details<std::pair<int, gfx::Size> >(&details));
1506 #if defined(OS_MACOSX)
1507 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1508 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1509 TRACE_EVENT0("renderer_host",
1510 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1512 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1513 ack_params.sync_point = 0;
1514 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1515 params.gpu_process_host_id,
1519 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
1520 gpu_params.surface_id = params.surface_id;
1521 gpu_params.surface_handle = params.surface_handle;
1522 gpu_params.route_id = params.route_id;
1523 gpu_params.size = params.size;
1524 gpu_params.scale_factor = params.scale_factor;
1525 gpu_params.latency_info = params.latency_info;
1526 view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
1527 params.gpu_process_host_id);
1528 view_->DidReceiveRendererFrame();
1532 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1533 const IPC::Message& message) {
1534 ViewHostMsg_SwapCompositorFrame::Param param;
1535 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m))
1537 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
1538 uint32 output_surface_id = param.a;
1539 param.b.AssignTo(frame.get());
1542 view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
1543 view_->DidReceiveRendererFrame();
1545 cc::CompositorFrameAck ack;
1546 if (frame->gl_frame_data) {
1547 ack.gl_frame_data = frame->gl_frame_data.Pass();
1548 ack.gl_frame_data->sync_point = 0;
1549 } else if (frame->delegated_frame_data) {
1550 cc::TransferableResource::ReturnResources(
1551 frame->delegated_frame_data->resource_list,
1553 } else if (frame->software_frame_data) {
1554 ack.last_software_frame_id = frame->software_frame_data->id;
1556 SendSwapCompositorFrameAck(routing_id_, process_->GetID(),
1557 output_surface_id, ack);
1562 void RenderWidgetHostImpl::OnOverscrolled(
1563 gfx::Vector2dF accumulated_overscroll,
1564 gfx::Vector2dF current_fling_velocity) {
1566 view_->OnOverscrolled(accumulated_overscroll, current_fling_velocity);
1569 void RenderWidgetHostImpl::OnUpdateRect(
1570 const ViewHostMsg_UpdateRect_Params& params) {
1571 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1572 TimeTicks paint_start = TimeTicks::Now();
1574 // Update our knowledge of the RenderWidget's size.
1575 current_size_ = params.view_size;
1576 // Update our knowledge of the RenderWidget's scroll offset.
1577 last_scroll_offset_ = params.scroll_offset;
1579 bool is_resize_ack =
1580 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1582 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1583 // that will end up reaching GetBackingStore.
1584 if (is_resize_ack) {
1585 DCHECK(!g_check_for_pending_resize_ack || resize_ack_pending_);
1586 resize_ack_pending_ = false;
1589 bool is_repaint_ack =
1590 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
1591 if (is_repaint_ack) {
1592 DCHECK(repaint_ack_pending_);
1593 TRACE_EVENT_ASYNC_END0(
1594 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1595 repaint_ack_pending_ = false;
1596 TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
1597 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
1600 DCHECK(!params.view_size.IsEmpty());
1602 bool was_async = false;
1604 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1605 TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
1607 // If gpu process does painting, scroll_rect and copy_rects are always empty
1608 // and backing store is never used.
1610 DCHECK(!params.bitmap_rect.IsEmpty());
1611 gfx::Size pixel_size = gfx::ToFlooredSize(
1612 gfx::ScaleSize(params.bitmap_rect.size(), params.scale_factor));
1613 const size_t size = pixel_size.height() * pixel_size.width() * 4;
1614 if (dib->size() < size) {
1615 DLOG(WARNING) << "Transport DIB too small for given rectangle";
1616 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
1617 GetProcess()->ReceivedBadMessage();
1619 // Scroll the backing store.
1620 if (!params.scroll_rect.IsEmpty()) {
1621 ScrollBackingStoreRect(params.scroll_delta,
1626 // Paint the backing store. This will update it with the
1627 // renderer-supplied bits. The view will read out of the backing store
1628 // later to actually draw to the screen.
1629 was_async = PaintBackingStoreRect(
1634 params.scale_factor,
1635 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
1636 weak_factory_.GetWeakPtr(), params, paint_start));
1641 DidUpdateBackingStore(params, paint_start);
1644 if (should_auto_resize_) {
1645 bool post_callback = new_auto_size_.IsEmpty();
1646 new_auto_size_ = params.view_size;
1647 if (post_callback) {
1648 base::MessageLoop::current()->PostTask(
1650 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
1651 weak_factory_.GetWeakPtr()));
1655 // Log the time delta for processing a paint message. On platforms that don't
1656 // support asynchronous painting, this is equivalent to
1657 // MPArch.RWH_TotalPaintTime.
1658 TimeDelta delta = TimeTicks::Now() - paint_start;
1659 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
1662 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1663 if (in_get_backing_store_)
1664 abort_get_backing_store_ = true;
1667 void RenderWidgetHostImpl::DidUpdateBackingStore(
1668 const ViewHostMsg_UpdateRect_Params& params,
1669 const TimeTicks& paint_start) {
1670 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1671 TimeTicks update_start = TimeTicks::Now();
1673 if (params.needs_ack) {
1674 // ACK early so we can prefetch the next PaintRect if there is a next one.
1675 // This must be done AFTER we're done painting with the bitmap supplied by
1676 // the renderer. This ACK is a signal to the renderer that the backing store
1677 // can be re-used, so the bitmap may be invalid after this call.
1678 Send(new ViewMsg_UpdateRect_ACK(routing_id_));
1681 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1682 // will not be re-issued, so must move them now, regardless of whether we
1683 // paint or not. MovePluginWindows attempts to move the plugin windows and
1684 // in the process could dispatch other window messages which could cause the
1685 // view to be destroyed.
1687 view_->MovePluginWindows(params.scroll_offset, params.plugin_window_moves);
1689 NotificationService::current()->Notify(
1690 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
1691 Source<RenderWidgetHost>(this),
1692 NotificationService::NoDetails());
1694 // We don't need to update the view if the view is hidden. We must do this
1695 // early return after the ACK is sent, however, or the renderer will not send
1700 // Now paint the view. Watch out: it might be destroyed already.
1701 if (view_ && !is_accelerated_compositing_active_) {
1702 view_being_painted_ = true;
1703 view_->DidUpdateBackingStore(params.scroll_rect, params.scroll_delta,
1704 params.copy_rects, params.latency_info);
1705 view_->DidReceiveRendererFrame();
1706 view_being_painted_ = false;
1709 // If we got a resize ack, then perhaps we have another resize to send?
1710 bool is_resize_ack =
1711 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1715 // Log the time delta for processing a paint message.
1716 TimeTicks now = TimeTicks::Now();
1717 TimeDelta delta = now - update_start;
1718 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta);
1720 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1721 // DidUpdateBackingStore() method. On platforms which have asynchronous
1722 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1723 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1724 // waiting for the paint to complete.
1726 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1727 delta = now - paint_start;
1728 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
1731 void RenderWidgetHostImpl::OnBeginSmoothScroll(
1732 const ViewHostMsg_BeginSmoothScroll_Params& params) {
1735 synthetic_gesture_controller_.BeginSmoothScroll(view_, params);
1738 void RenderWidgetHostImpl::OnBeginPinch(
1739 const ViewHostMsg_BeginPinch_Params& params) {
1742 synthetic_gesture_controller_.BeginPinch(view_, params);
1745 void RenderWidgetHostImpl::OnFocus() {
1746 // Only RenderViewHost can deal with that message.
1747 RecordAction(UserMetricsAction("BadMessageTerminate_RWH4"));
1748 GetProcess()->ReceivedBadMessage();
1751 void RenderWidgetHostImpl::OnBlur() {
1752 // Only RenderViewHost can deal with that message.
1753 RecordAction(UserMetricsAction("BadMessageTerminate_RWH5"));
1754 GetProcess()->ReceivedBadMessage();
1757 void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
1761 view_->UpdateCursor(cursor);
1764 void RenderWidgetHostImpl::OnTextInputTypeChanged(
1765 ui::TextInputType type,
1766 ui::TextInputMode input_mode,
1767 bool can_compose_inline) {
1769 view_->TextInputTypeChanged(type, input_mode, can_compose_inline);
1772 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1773 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
1774 const gfx::Range& range,
1775 const std::vector<gfx::Rect>& character_bounds) {
1777 view_->ImeCompositionRangeChanged(range, character_bounds);
1781 void RenderWidgetHostImpl::OnImeCancelComposition() {
1783 view_->ImeCancelComposition();
1786 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated) {
1787 TRACE_EVENT1("renderer_host",
1788 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
1789 "activated", activated);
1790 is_accelerated_compositing_active_ = activated;
1792 view_->OnAcceleratedCompositingStateChange();
1795 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
1796 bool last_unlocked_by_target,
1799 if (pending_mouse_lock_request_) {
1800 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1802 } else if (IsMouseLocked()) {
1803 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
1807 pending_mouse_lock_request_ = true;
1808 if (privileged && allow_privileged_mouse_lock_) {
1809 // Directly approve to lock the mouse.
1810 GotResponseToLockMouseRequest(true);
1812 RequestToLockMouse(user_gesture, last_unlocked_by_target);
1816 void RenderWidgetHostImpl::OnUnlockMouse() {
1817 RejectMouseLockOrUnlockIfNecessary();
1820 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
1821 const gfx::Rect& rect,
1822 const gfx::Size& size,
1823 const TransportDIB::Id& id) {
1824 DCHECK(!rect.IsEmpty());
1825 DCHECK(!size.IsEmpty());
1827 TransportDIB* dib = process_->GetTransportDIB(id);
1828 DCHECK(dib->memory());
1829 DCHECK(dib->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config,
1830 size.width(), size.height()));
1832 SkBitmap zoomed_bitmap;
1833 zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
1834 size.width(), size.height());
1835 zoomed_bitmap.setPixels(dib->memory());
1837 #if defined(OS_ANDROID)
1839 view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
1844 zoomed_bitmap.setPixels(0);
1845 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
1850 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
1851 gfx::NativeViewId dummy_activation_window) {
1852 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1854 // This may happen as a result of a race condition when the plugin is going
1856 wchar_t window_title[MAX_PATH + 1] = {0};
1857 if (!IsWindow(hwnd) ||
1858 !GetWindowText(hwnd, window_title, arraysize(window_title)) ||
1859 lstrcmpiW(window_title, kDummyActivationWindowName) != 0) {
1863 SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
1864 dummy_windows_for_activation_.push_back(hwnd);
1867 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
1868 gfx::NativeViewId dummy_activation_window) {
1869 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1870 std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
1871 for (; i != dummy_windows_for_activation_.end(); ++i) {
1873 dummy_windows_for_activation_.erase(i);
1877 NOTREACHED() << "Unknown dummy window";
1881 bool RenderWidgetHostImpl::PaintBackingStoreRect(
1882 TransportDIB::Id bitmap,
1883 const gfx::Rect& bitmap_rect,
1884 const std::vector<gfx::Rect>& copy_rects,
1885 const gfx::Size& view_size,
1887 const base::Closure& completion_callback) {
1888 // The view may be destroyed already.
1893 // Don't bother updating the backing store when we're hidden. Just mark it
1894 // as being totally invalid. This will cause a complete repaint when the
1895 // view is restored.
1896 needs_repainting_on_restore_ = true;
1900 bool needs_full_paint = false;
1901 bool scheduled_completion_callback = false;
1902 BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
1903 copy_rects, scale_factor,
1904 completion_callback,
1906 &scheduled_completion_callback);
1907 if (needs_full_paint) {
1908 repaint_start_time_ = TimeTicks::Now();
1909 DCHECK(!repaint_ack_pending_);
1910 repaint_ack_pending_ = true;
1911 TRACE_EVENT_ASYNC_BEGIN0(
1912 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1913 Send(new ViewMsg_Repaint(routing_id_, view_size));
1916 return scheduled_completion_callback;
1919 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta,
1920 const gfx::Rect& clip_rect,
1921 const gfx::Size& view_size) {
1923 // Don't bother updating the backing store when we're hidden. Just mark it
1924 // as being totally invalid. This will cause a complete repaint when the
1925 // view is restored.
1926 needs_repainting_on_restore_ = true;
1930 // TODO(darin): do we need to do something else if our backing store is not
1931 // the same size as the advertised view? maybe we just assume there is a
1932 // full paint on its way?
1933 BackingStore* backing_store = BackingStoreManager::Lookup(this);
1934 if (!backing_store || (backing_store->size() != view_size))
1936 backing_store->ScrollBackingStore(delta, clip_rect, view_size);
1939 void RenderWidgetHostImpl::Replace(const string16& word) {
1940 Send(new InputMsg_Replace(routing_id_, word));
1943 void RenderWidgetHostImpl::ReplaceMisspelling(const string16& word) {
1944 Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
1947 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1948 ignore_input_events_ = ignore_input_events;
1951 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
1952 const NativeWebKeyboardEvent& event) {
1953 if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
1956 for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
1957 size_t original_size = key_press_event_callbacks_.size();
1958 if (key_press_event_callbacks_[i].Run(event))
1961 // Check whether the callback that just ran removed itself, in which case
1962 // the iterator needs to be decremented to properly account for the removal.
1963 size_t current_size = key_press_event_callbacks_.size();
1964 if (current_size != original_size) {
1965 DCHECK_EQ(original_size - 1, current_size);
1973 InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
1974 const WebKit::WebInputEvent& event, const ui::LatencyInfo& latency_info) {
1975 // Don't ignore touch cancel events, since they may be sent while input
1976 // events are being ignored in order to keep the renderer from getting
1977 // confused about how many touches are active.
1978 if (IgnoreInputEvents() && event.type != WebInputEvent::TouchCancel)
1979 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
1981 if (!process_->HasConnection())
1982 return INPUT_EVENT_ACK_STATE_UNKNOWN;
1984 if (event.type == WebInputEvent::MouseDown)
1987 return view_ ? view_->FilterInputEvent(event)
1988 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1991 void RenderWidgetHostImpl::IncrementInFlightEventCount() {
1992 StartHangMonitorTimeout(
1993 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
1994 increment_in_flight_event_count();
1997 void RenderWidgetHostImpl::DecrementInFlightEventCount() {
1998 DCHECK(in_flight_event_count_ >= 0);
1999 // Cancel pending hung renderer checks since the renderer is responsive.
2000 if (decrement_in_flight_event_count() <= 0)
2001 StopHangMonitorTimeout();
2004 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
2005 if (has_touch_handler_ == has_handlers)
2007 has_touch_handler_ = has_handlers;
2008 #if defined(OS_ANDROID)
2010 view_->HasTouchEventHandlers(has_touch_handler_);
2014 OverscrollController* RenderWidgetHostImpl::GetOverscrollController() const {
2015 return overscroll_controller_.get();
2018 void RenderWidgetHostImpl::SetNeedsFlush() {
2020 view_->OnSetNeedsFlushInput();
2023 void RenderWidgetHostImpl::DidFlush() {
2025 view_->OnDidFlushInput();
2028 void RenderWidgetHostImpl::OnKeyboardEventAck(
2029 const NativeWebKeyboardEvent& event,
2030 InputEventAckState ack_result) {
2031 #if defined(OS_MACOSX)
2032 if (!is_hidden() && view_ && view_->PostProcessEventForPluginIme(event))
2036 // We only send unprocessed key event upwards if we are not hidden,
2037 // because the user has moved away from us and no longer expect any effect
2038 // of this key event.
2039 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2040 if (delegate_ && !processed && !is_hidden() && !event.skip_in_browser) {
2041 delegate_->HandleKeyboardEvent(event);
2043 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2044 // (i.e. in the case of Ctrl+W, where the call to
2045 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2049 void RenderWidgetHostImpl::OnWheelEventAck(
2050 const MouseWheelEventWithLatencyInfo& wheel_event,
2051 InputEventAckState ack_result) {
2052 if (!wheel_event.latency.FindLatency(
2053 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2054 // MouseWheelEvent latency ends when it is acked but does not cause any
2055 // rendering scheduled.
2056 ui::LatencyInfo latency = wheel_event.latency;
2057 latency.AddLatencyNumber(
2058 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
2061 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2062 if (!processed && !is_hidden() && view_)
2063 view_->UnhandledWheelEvent(wheel_event.event);
2066 void RenderWidgetHostImpl::OnGestureEventAck(
2067 const GestureEventWithLatencyInfo& event,
2068 InputEventAckState ack_result) {
2069 if (!event.latency.FindLatency(
2070 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2071 // GestureEvent latency ends when it is acked but does not cause any
2072 // rendering scheduled.
2073 ui::LatencyInfo latency = event.latency;
2074 latency.AddLatencyNumber(
2075 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0 ,0);
2079 view_->GestureEventAck(event.event.type, ack_result);
2082 void RenderWidgetHostImpl::OnTouchEventAck(
2083 const TouchEventWithLatencyInfo& event,
2084 InputEventAckState ack_result) {
2085 TouchEventWithLatencyInfo touch_event = event;
2086 // TouchEvent latency does not end when acked since it could later on
2087 // become gesture events.
2088 touch_event.latency.AddLatencyNumber(
2089 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0);
2090 ComputeTouchLatency(touch_event.latency);
2092 view_->ProcessAckedTouchEvent(touch_event, ack_result);
2095 void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
2096 if (type == BAD_ACK_MESSAGE) {
2097 RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
2098 process_->ReceivedBadMessage();
2099 } else if (type == UNEXPECTED_EVENT_TYPE) {
2100 suppress_next_char_events_ = false;
2104 const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
2105 return last_scroll_offset_;
2108 bool RenderWidgetHostImpl::IgnoreInputEvents() const {
2109 return ignore_input_events_ || process_->IgnoreInputEvents();
2112 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2113 return input_router_->ShouldForwardTouchEvent();
2116 void RenderWidgetHostImpl::StartUserGesture() {
2120 void RenderWidgetHostImpl::Stop() {
2121 Send(new ViewMsg_Stop(GetRoutingID()));
2124 void RenderWidgetHostImpl::SetBackground(const SkBitmap& background) {
2125 Send(new ViewMsg_SetBackground(GetRoutingID(), background));
2128 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2129 const std::vector<EditCommand>& commands) {
2130 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
2133 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
2134 accessibility_mode_ = mode;
2135 Send(new ViewMsg_SetAccessibilityMode(GetRoutingID(), mode));
2138 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
2139 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
2142 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id) {
2143 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id));
2146 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2147 int acc_obj_id, gfx::Rect subfocus) {
2148 Send(new AccessibilityMsg_ScrollToMakeVisible(
2149 GetRoutingID(), acc_obj_id, subfocus));
2152 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2153 int acc_obj_id, gfx::Point point) {
2154 Send(new AccessibilityMsg_ScrollToPoint(
2155 GetRoutingID(), acc_obj_id, point));
2158 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2159 int object_id, int start_offset, int end_offset) {
2160 Send(new AccessibilityMsg_SetTextSelection(
2161 GetRoutingID(), object_id, start_offset, end_offset));
2164 void RenderWidgetHostImpl::FatalAccessibilityTreeError() {
2165 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2168 #if defined(OS_WIN) && defined(USE_AURA)
2169 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2170 gfx::NativeViewAccessible accessible_parent) {
2172 view_->SetParentNativeViewAccessible(accessible_parent);
2175 gfx::NativeViewAccessible
2176 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2177 return delegate_->GetParentNativeViewAccessible();
2181 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
2182 const std::string& value) {
2183 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
2186 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2187 const gfx::Rect& rect) {
2188 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
2191 void RenderWidgetHostImpl::SelectRange(const gfx::Point& start,
2192 const gfx::Point& end) {
2193 Send(new InputMsg_SelectRange(GetRoutingID(), start, end));
2196 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
2197 Send(new InputMsg_MoveCaret(GetRoutingID(), point));
2200 void RenderWidgetHostImpl::Undo() {
2201 Send(new InputMsg_Undo(GetRoutingID()));
2202 RecordAction(UserMetricsAction("Undo"));
2205 void RenderWidgetHostImpl::Redo() {
2206 Send(new InputMsg_Redo(GetRoutingID()));
2207 RecordAction(UserMetricsAction("Redo"));
2210 void RenderWidgetHostImpl::Cut() {
2211 Send(new InputMsg_Cut(GetRoutingID()));
2212 RecordAction(UserMetricsAction("Cut"));
2215 void RenderWidgetHostImpl::Copy() {
2216 Send(new InputMsg_Copy(GetRoutingID()));
2217 RecordAction(UserMetricsAction("Copy"));
2220 void RenderWidgetHostImpl::CopyToFindPboard() {
2221 #if defined(OS_MACOSX)
2222 // Windows/Linux don't have the concept of a find pasteboard.
2223 Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
2224 RecordAction(UserMetricsAction("CopyToFindPboard"));
2228 void RenderWidgetHostImpl::Paste() {
2229 Send(new InputMsg_Paste(GetRoutingID()));
2230 RecordAction(UserMetricsAction("Paste"));
2233 void RenderWidgetHostImpl::PasteAndMatchStyle() {
2234 Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
2235 RecordAction(UserMetricsAction("PasteAndMatchStyle"));
2238 void RenderWidgetHostImpl::Delete() {
2239 Send(new InputMsg_Delete(GetRoutingID()));
2240 RecordAction(UserMetricsAction("DeleteSelection"));
2243 void RenderWidgetHostImpl::SelectAll() {
2244 Send(new InputMsg_SelectAll(GetRoutingID()));
2245 RecordAction(UserMetricsAction("SelectAll"));
2248 void RenderWidgetHostImpl::Unselect() {
2249 Send(new InputMsg_Unselect(GetRoutingID()));
2250 RecordAction(UserMetricsAction("Unselect"));
2253 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
2255 RejectMouseLockOrUnlockIfNecessary();
2258 if (!pending_mouse_lock_request_) {
2259 // This is possible, e.g., the plugin sends us an unlock request before
2260 // the user allows to lock to mouse.
2264 pending_mouse_lock_request_ = false;
2265 if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
2266 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2269 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2276 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2277 int32 route_id, int gpu_host_id,
2278 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
2279 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
2281 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
2287 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2289 uint32 output_surface_id,
2290 int renderer_host_id,
2291 const cc::CompositorFrameAck& ack) {
2292 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2295 host->Send(new ViewMsg_SwapCompositorFrameAck(
2296 route_id, output_surface_id, ack));
2300 void RenderWidgetHostImpl::SendReclaimCompositorResources(
2302 uint32 output_surface_id,
2303 int renderer_host_id,
2304 const cc::CompositorFrameAck& ack) {
2305 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2309 new ViewMsg_ReclaimCompositorResources(route_id, output_surface_id, ack));
2312 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2313 if (!is_threaded_compositing_enabled_)
2314 Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
2317 #if defined(USE_AURA)
2319 void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent) {
2321 HWND hwnd = reinterpret_cast<HWND>(new_parent);
2323 hwnd = GetDesktopWindow();
2324 for (std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
2325 i != dummy_windows_for_activation_.end(); ++i) {
2326 SetParent(*i, hwnd);
2333 void RenderWidgetHostImpl::DelayedAutoResized() {
2334 gfx::Size new_size = new_auto_size_;
2335 // Clear the new_auto_size_ since the empty value is used as a flag to
2336 // indicate that no callback is in progress (i.e. without this line
2337 // DelayedAutoResized will not get called again).
2338 new_auto_size_.SetSize(0, 0);
2339 if (!should_auto_resize_)
2342 OnRenderAutoResized(new_size);
2345 void RenderWidgetHostImpl::DetachDelegate() {
2349 void RenderWidgetHostImpl::ComputeTouchLatency(
2350 const ui::LatencyInfo& latency_info) {
2351 ui::LatencyInfo::LatencyComponent ui_component;
2352 ui::LatencyInfo::LatencyComponent rwh_component;
2353 ui::LatencyInfo::LatencyComponent acked_component;
2355 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
2358 !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2359 GetLatencyComponentId(),
2363 DCHECK(ui_component.event_count == 1);
2364 DCHECK(rwh_component.event_count == 1);
2366 base::TimeDelta ui_delta =
2367 rwh_component.event_time - ui_component.event_time;
2368 rendering_stats_.touch_ui_count++;
2369 rendering_stats_.total_touch_ui_latency += ui_delta;
2370 UMA_HISTOGRAM_CUSTOM_COUNTS(
2371 "Event.Latency.Browser.TouchUI",
2372 ui_delta.InMicroseconds(),
2377 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT,
2379 &acked_component)) {
2380 DCHECK(acked_component.event_count == 1);
2381 base::TimeDelta acked_delta =
2382 acked_component.event_time - rwh_component.event_time;
2383 rendering_stats_.touch_acked_count++;
2384 rendering_stats_.total_touch_acked_latency += acked_delta;
2385 UMA_HISTOGRAM_CUSTOM_COUNTS(
2386 "Event.Latency.Browser.TouchAcked",
2387 acked_delta.InMicroseconds(),
2393 if (CommandLine::ForCurrentProcess()->HasSwitch(
2394 switches::kEnableGpuBenchmarking))
2395 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_, rendering_stats_));
2398 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
2399 ui::LatencyInfo::LatencyComponent window_snapshot_component;
2400 if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
2401 GetLatencyComponentId(),
2402 &window_snapshot_component)) {
2403 WindowSnapshotReachedScreen(
2404 static_cast<int>(window_snapshot_component.sequence_number));
2407 ui::LatencyInfo::LatencyComponent rwh_component;
2408 ui::LatencyInfo::LatencyComponent swap_component;
2409 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2410 GetLatencyComponentId(),
2412 !latency_info.FindLatency(
2413 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
2414 0, &swap_component)) {
2418 rendering_stats_.input_event_count += rwh_component.event_count;
2419 rendering_stats_.total_input_latency +=
2420 rwh_component.event_count *
2421 (swap_component.event_time - rwh_component.event_time);
2423 ui::LatencyInfo::LatencyComponent original_component;
2424 if (latency_info.FindLatency(
2425 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
2426 GetLatencyComponentId(),
2427 &original_component)) {
2428 // This UMA metric tracks the time from when the original touch event is
2429 // created (averaged if there are multiple) to when the scroll gesture
2430 // results in final frame swap.
2431 base::TimeDelta delta =
2432 swap_component.event_time - original_component.event_time;
2433 for (size_t i = 0; i < original_component.event_count; i++) {
2434 UMA_HISTOGRAM_CUSTOM_COUNTS(
2435 "Event.Latency.TouchToScrollUpdateSwap",
2436 delta.InMicroseconds(),
2441 rendering_stats_.scroll_update_count += original_component.event_count;
2442 rendering_stats_.total_scroll_update_latency +=
2443 original_component.event_count *
2444 (swap_component.event_time - original_component.event_time);
2447 if (CommandLine::ForCurrentProcess()->HasSwitch(
2448 switches::kEnableGpuBenchmarking))
2449 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_, rendering_stats_));
2452 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
2453 view_->DidReceiveRendererFrame();
2456 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
2457 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
2459 std::vector<unsigned char> png;
2461 // This feature is behind the kEnableGpuBenchmarking command line switch
2462 // because it poses security concerns and should only be used for testing.
2463 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2464 if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
2465 gfx::Rect view_bounds = GetView()->GetViewBounds();
2466 gfx::Rect snapshot_bounds(view_bounds.size());
2467 gfx::Size snapshot_size = snapshot_bounds.size();
2469 if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
2470 &png, snapshot_bounds)) {
2471 Send(new ViewMsg_WindowSnapshotCompleted(
2472 GetRoutingID(), snapshot_id, snapshot_size, png));
2477 Send(new ViewMsg_WindowSnapshotCompleted(
2478 GetRoutingID(), snapshot_id, gfx::Size(), png));
2482 void RenderWidgetHostImpl::CompositorFrameDrawn(
2483 const ui::LatencyInfo& latency_info) {
2484 std::set<RenderWidgetHostImpl*> rwhi_set;
2486 for (ui::LatencyInfo::LatencyMap::const_iterator b =
2487 latency_info.latency_components.begin();
2488 b != latency_info.latency_components.end();
2490 if (b->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
2491 b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
2492 // Matches with GetLatencyComponentId
2493 int routing_id = b->first.second & 0xffffffff;
2494 int process_id = (b->first.second >> 32) & 0xffffffff;
2495 RenderWidgetHost* rwh =
2496 RenderWidgetHost::FromID(process_id, routing_id);
2500 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
2501 if (rwhi_set.insert(rwhi).second)
2502 rwhi->FrameSwapped(latency_info);
2507 } // namespace content