1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_impl.h"
11 #include "base/auto_reset.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/debug/trace_event.h"
16 #include "base/i18n/rtl.h"
17 #include "base/lazy_instance.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/histogram.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "cc/base/switches.h"
25 #include "cc/output/compositor_frame.h"
26 #include "cc/output/compositor_frame_ack.h"
27 #include "content/browser/accessibility/accessibility_mode_helper.h"
28 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
29 #include "content/browser/gpu/compositor_util.h"
30 #include "content/browser/gpu/gpu_process_host.h"
31 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
32 #include "content/browser/gpu/gpu_surface_tracker.h"
33 #include "content/browser/renderer_host/backing_store.h"
34 #include "content/browser/renderer_host/backing_store_manager.h"
35 #include "content/browser/renderer_host/dip_util.h"
36 #include "content/browser/renderer_host/input/input_router_impl.h"
37 #include "content/browser/renderer_host/input/synthetic_gesture.h"
38 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
39 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
40 #include "content/browser/renderer_host/input/timeout_monitor.h"
41 #include "content/browser/renderer_host/overscroll_controller.h"
42 #include "content/browser/renderer_host/render_process_host_impl.h"
43 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/renderer_host/render_widget_helper.h"
45 #include "content/browser/renderer_host/render_widget_host_delegate.h"
46 #include "content/common/accessibility_messages.h"
47 #include "content/common/content_constants_internal.h"
48 #include "content/common/cursors/webcursor.h"
49 #include "content/common/gpu/gpu_messages.h"
50 #include "content/common/input_messages.h"
51 #include "content/common/view_messages.h"
52 #include "content/port/browser/render_widget_host_view_port.h"
53 #include "content/public/browser/native_web_keyboard_event.h"
54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/notification_types.h"
56 #include "content/public/browser/render_widget_host_iterator.h"
57 #include "content/public/browser/user_metrics.h"
58 #include "content/public/common/content_constants.h"
59 #include "content/public/common/content_switches.h"
60 #include "content/public/common/result_codes.h"
61 #include "skia/ext/image_operations.h"
62 #include "skia/ext/platform_canvas.h"
63 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
64 #include "ui/events/event.h"
65 #include "ui/events/keycodes/keyboard_codes.h"
66 #include "ui/gfx/size_conversions.h"
67 #include "ui/gfx/skbitmap_operations.h"
68 #include "ui/gfx/vector2d_conversions.h"
69 #include "ui/snapshot/snapshot.h"
70 #include "webkit/common/webpreferences.h"
72 #if defined(TOOLKIT_GTK)
73 #include "content/browser/renderer_host/backing_store_gtk.h"
74 #elif defined(OS_MACOSX)
75 #include "content/browser/renderer_host/backing_store_mac.h"
77 #include "content/common/plugin_constants_win.h"
81 using base::TimeDelta;
82 using base::TimeTicks;
83 using blink::WebGestureEvent;
84 using blink::WebInputEvent;
85 using blink::WebKeyboardEvent;
86 using blink::WebMouseEvent;
87 using blink::WebMouseWheelEvent;
88 using blink::WebTextDirection;
93 bool g_check_for_pending_resize_ack = true;
95 // How long to (synchronously) wait for the renderer to respond with a
96 // PaintRect message, when our backing-store is invalid, before giving up and
97 // returning a null or incorrectly sized backing-store from GetBackingStore.
98 // This timeout impacts the "choppiness" of our window resize perf.
99 const int kPaintMsgTimeoutMS = 50;
101 typedef std::pair<int32, int32> RenderWidgetHostID;
102 typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
104 base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
105 LAZY_INSTANCE_INITIALIZER;
107 int GetInputRouterViewFlagsFromCompositorFrameMetadata(
108 const cc::CompositorFrameMetadata metadata) {
109 int view_flags = InputRouter::VIEW_FLAGS_NONE;
111 if (metadata.min_page_scale_factor == metadata.max_page_scale_factor)
112 view_flags |= InputRouter::FIXED_PAGE_SCALE;
114 const float window_width_dip =
115 std::ceil(metadata.page_scale_factor * metadata.viewport_size.width());
116 const float content_width_css = metadata.root_layer_size.width();
117 if (content_width_css <= window_width_dip)
118 view_flags |= InputRouter::MOBILE_VIEWPORT;
123 // Implements the RenderWidgetHostIterator interface. It keeps a list of
124 // RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
125 // iteration (or NULL if there isn't any left).
126 class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
128 RenderWidgetHostIteratorImpl()
129 : current_index_(0) {
132 virtual ~RenderWidgetHostIteratorImpl() {
135 void Add(RenderWidgetHost* host) {
136 hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
137 host->GetRoutingID()));
140 // RenderWidgetHostIterator:
141 virtual RenderWidgetHost* GetNextHost() OVERRIDE {
142 RenderWidgetHost* host = NULL;
143 while (current_index_ < hosts_.size() && !host) {
144 RenderWidgetHostID id = hosts_[current_index_];
145 host = RenderWidgetHost::FromID(id.first, id.second);
152 std::vector<RenderWidgetHostID> hosts_;
153 size_t current_index_;
155 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
162 size_t RenderWidgetHost::BackingStoreMemorySize() {
163 return BackingStoreManager::MemorySize();
166 ///////////////////////////////////////////////////////////////////////////////
167 // RenderWidgetHostImpl
169 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
170 RenderProcessHost* process,
174 renderer_initialized_(false),
175 hung_renderer_delay_ms_(kHungRendererDelayMs),
178 routing_id_(routing_id),
182 is_fullscreen_(false),
183 is_accelerated_compositing_active_(false),
184 repaint_ack_pending_(false),
185 resize_ack_pending_(false),
186 screen_info_out_of_date_(false),
187 overdraw_bottom_height_(0.f),
188 should_auto_resize_(false),
189 waiting_for_screen_rects_ack_(false),
190 accessibility_mode_(AccessibilityModeOff),
191 needs_repainting_on_restore_(false),
192 is_unresponsive_(false),
193 in_flight_event_count_(0),
194 in_get_backing_store_(false),
195 abort_get_backing_store_(false),
196 view_being_painted_(false),
197 ignore_input_events_(false),
198 input_method_active_(false),
199 text_direction_updated_(false),
200 text_direction_(blink::WebTextDirectionLeftToRight),
201 text_direction_canceled_(false),
202 suppress_next_char_events_(false),
203 pending_mouse_lock_request_(false),
204 allow_privileged_mouse_lock_(false),
205 has_touch_handler_(false),
207 last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32) {
209 if (routing_id_ == MSG_ROUTING_NONE) {
210 routing_id_ = process_->GetNextRoutingID();
211 surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
215 // TODO(piman): This is a O(N) lookup, where we could forward the
216 // information from the RenderWidgetHelper. The problem is that doing so
217 // currently leaks outside of content all the way to chrome classes, and
218 // would be a layering violation. Since we don't expect more than a few
219 // hundreds of RWH, this seems acceptable. Revisit if performance become a
220 // problem, for example by tracking in the RenderWidgetHelper the routing id
221 // (and surface id) that have been created, but whose RWH haven't yet.
222 surface_id_ = GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
228 is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled();
230 std::pair<RoutingIDWidgetMap::iterator, bool> result =
231 g_routing_id_widget_map.Get().insert(std::make_pair(
232 RenderWidgetHostID(process->GetID(), routing_id_), this));
233 CHECK(result.second) << "Inserting a duplicate item!";
234 process_->AddRoute(routing_id_, this);
236 // If we're initially visible, tell the process host that we're alive.
237 // Otherwise we'll notify the process host when we are first shown.
239 process_->WidgetRestored();
241 accessibility_mode_ =
242 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
244 input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
246 #if defined(USE_AURA)
247 bool overscroll_enabled = CommandLine::ForCurrentProcess()->
248 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
249 SetOverscrollControllerEnabled(overscroll_enabled);
252 if (GetProcess()->IsGuest() || !CommandLine::ForCurrentProcess()->HasSwitch(
253 switches::kDisableHangMonitor)) {
254 hang_monitor_timeout_.reset(new TimeoutMonitor(
255 base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
256 weak_factory_.GetWeakPtr())));
260 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
263 // Clear our current or cached backing store if either remains.
264 BackingStoreManager::RemoveBackingStore(this);
266 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
269 process_->RemoveRoute(routing_id_);
270 g_routing_id_widget_map.Get().erase(
271 RenderWidgetHostID(process_->GetID(), routing_id_));
274 delegate_->RenderWidgetDeleted(this);
278 RenderWidgetHost* RenderWidgetHost::FromID(
281 return RenderWidgetHostImpl::FromID(process_id, routing_id);
285 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
290 RoutingIDWidgetMap::iterator it = widgets->find(
291 RenderWidgetHostID(process_id, routing_id));
292 return it == widgets->end() ? NULL : it->second;
296 scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
297 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
298 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
299 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
300 it != widgets->end();
302 RenderWidgetHost* widget = it->second;
304 if (!widget->IsRenderView()) {
309 // Add only active RenderViewHosts.
310 RenderViewHost* rvh = RenderViewHost::From(widget);
311 if (RenderViewHostImpl::IsRVHStateActive(
312 static_cast<RenderViewHostImpl*>(rvh)->rvh_state()))
316 return scoped_ptr<RenderWidgetHostIterator>(hosts);
320 scoped_ptr<RenderWidgetHostIterator>
321 RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
322 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
323 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
324 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
325 it != widgets->end();
327 hosts->Add(it->second);
330 return scoped_ptr<RenderWidgetHostIterator>(hosts);
334 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
335 return rwh->AsRenderWidgetHostImpl();
338 void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
339 view_ = RenderWidgetHostViewPort::FromRWHV(view);
341 GpuSurfaceTracker::Get()->SetSurfaceHandle(
342 surface_id_, GetCompositingSurface());
344 synthetic_gesture_controller_.reset();
347 RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
351 int RenderWidgetHostImpl::GetRoutingID() const {
355 RenderWidgetHostView* RenderWidgetHostImpl::GetView() const {
359 RenderWidgetHostImpl* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
363 gfx::NativeViewId RenderWidgetHostImpl::GetNativeViewId() const {
365 return view_->GetNativeViewId();
369 gfx::GLSurfaceHandle RenderWidgetHostImpl::GetCompositingSurface() {
371 return view_->GetCompositingSurface();
372 return gfx::GLSurfaceHandle();
375 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
376 resize_ack_pending_ = false;
377 if (repaint_ack_pending_) {
378 TRACE_EVENT_ASYNC_END0(
379 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
381 repaint_ack_pending_ = false;
382 last_requested_size_.SetSize(0, 0);
385 void RenderWidgetHostImpl::SendScreenRects() {
386 if (!renderer_initialized_ || waiting_for_screen_rects_ack_)
390 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
391 // happens on Win & Mac, and when the view is shown it'll call this again.
398 last_view_screen_rect_ = view_->GetViewBounds();
399 last_window_screen_rect_ = view_->GetBoundsInRootWindow();
400 Send(new ViewMsg_UpdateScreenRects(
401 GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
403 delegate_->DidSendScreenRects(this);
404 waiting_for_screen_rects_ack_ = true;
407 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
409 overscroll_controller_.reset();
410 else if (!overscroll_controller_)
411 overscroll_controller_.reset(new OverscrollController());
414 void RenderWidgetHostImpl::SuppressNextCharEvents() {
415 suppress_next_char_events_ = true;
418 void RenderWidgetHostImpl::FlushInput() {
419 input_router_->Flush();
420 if (synthetic_gesture_controller_)
421 synthetic_gesture_controller_->Flush(base::TimeTicks::Now());
424 void RenderWidgetHostImpl::SetNeedsFlush() {
426 view_->OnSetNeedsFlushInput();
429 void RenderWidgetHostImpl::Init() {
430 DCHECK(process_->HasConnection());
432 renderer_initialized_ = true;
434 GpuSurfaceTracker::Get()->SetSurfaceHandle(
435 surface_id_, GetCompositingSurface());
437 // Send the ack along with the information on placement.
438 Send(new ViewMsg_CreatingNew_ACK(routing_id_));
439 GetProcess()->ResumeRequestsForView(routing_id_);
444 void RenderWidgetHostImpl::Shutdown() {
445 RejectMouseLockOrUnlockIfNecessary();
447 if (process_->HasConnection()) {
448 // Tell the renderer object to close.
449 bool rv = Send(new ViewMsg_Close(routing_id_));
456 bool RenderWidgetHostImpl::IsLoading() const {
460 bool RenderWidgetHostImpl::IsRenderView() const {
464 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
466 bool msg_is_ok = true;
467 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl, msg, msg_is_ok)
468 IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
469 OnQueueSyntheticGesture)
470 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
471 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
473 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
474 OnUpdateScreenRectsAck)
475 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
476 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
477 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
478 msg_is_ok = OnSwapCompositorFrame(msg))
479 IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
480 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopFlinging, OnFlingingStopped)
481 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
482 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
483 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
484 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
485 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
486 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
487 OnTextInputTypeChanged)
488 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
489 OnImeCancelComposition)
490 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing,
491 OnDidActivateAcceleratedCompositing)
492 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
493 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
494 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
495 OnShowDisambiguationPopup)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
497 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
498 OnSelectionBoundsChanged)
499 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
501 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
502 OnWindowlessPluginDummyWindowCreated)
503 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
504 OnWindowlessPluginDummyWindowDestroyed)
506 #if defined(OS_MACOSX)
507 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
508 OnCompositorSurfaceBuffersSwapped)
510 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
511 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
512 OnImeCompositionRangeChanged)
514 IPC_MESSAGE_UNHANDLED(handled = false)
515 IPC_END_MESSAGE_MAP_EX()
517 if (!handled && input_router_ && input_router_->OnMessageReceived(msg))
520 if (!handled && view_ && view_->OnMessageReceived(msg))
524 // The message de-serialization failed. Kill the renderer process.
525 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH"));
526 GetProcess()->ReceivedBadMessage();
531 bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
532 if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
533 return input_router_->SendInput(make_scoped_ptr(msg));
535 return process_->Send(msg);
538 void RenderWidgetHostImpl::WasHidden() {
544 // Don't bother reporting hung state when we aren't active.
545 StopHangMonitorTimeout();
547 // If we have a renderer, then inform it that we are being hidden so it can
548 // reduce its resource utilization.
549 Send(new ViewMsg_WasHidden(routing_id_));
551 // Tell the RenderProcessHost we were hidden.
552 process_->WidgetHidden();
554 bool is_visible = false;
555 NotificationService::current()->Notify(
556 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
557 Source<RenderWidgetHost>(this),
558 Details<bool>(&is_visible));
561 void RenderWidgetHostImpl::WasShown() {
568 BackingStore* backing_store = BackingStoreManager::Lookup(this);
569 // If we already have a backing store for this widget, then we don't need to
570 // repaint on restore _unless_ we know that our backing store is invalid.
571 // When accelerated compositing is on, we must always repaint, even when
572 // the backing store exists.
573 bool needs_repainting;
574 if (needs_repainting_on_restore_ || !backing_store ||
575 is_accelerated_compositing_active()) {
576 needs_repainting = true;
577 needs_repainting_on_restore_ = false;
579 needs_repainting = false;
581 Send(new ViewMsg_WasShown(routing_id_, needs_repainting));
583 process_->WidgetRestored();
585 bool is_visible = true;
586 NotificationService::current()->Notify(
587 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
588 Source<RenderWidgetHost>(this),
589 Details<bool>(&is_visible));
591 // It's possible for our size to be out of sync with the renderer. The
592 // following is one case that leads to this:
593 // 1. WasResized -> Send ViewMsg_Resize to render
594 // 2. WasResized -> do nothing as resize_ack_pending_ is true
596 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
597 // is hidden. Now renderer/browser out of sync with what they think size
599 // By invoking WasResized the renderer is updated as necessary. WasResized
600 // does nothing if the sizes are already in sync.
602 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
603 // could handle both the restore and resize at once. This isn't that big a
604 // deal as RenderWidget::WasShown delays updating, so that the resize from
605 // WasResized is usually processed before the renderer is painted.
609 void RenderWidgetHostImpl::WasResized() {
610 // Skip if the |delegate_| has already been detached because
611 // it's web contents is being deleted.
612 if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
613 !renderer_initialized_ || should_auto_resize_ || !delegate_) {
617 gfx::Rect view_bounds = view_->GetViewBounds();
618 gfx::Size new_size(view_bounds.size());
620 gfx::Size old_physical_backing_size = physical_backing_size_;
621 physical_backing_size_ = view_->GetPhysicalBackingSize();
622 bool was_fullscreen = is_fullscreen_;
623 is_fullscreen_ = IsFullscreen();
624 float old_overdraw_bottom_height = overdraw_bottom_height_;
625 overdraw_bottom_height_ = view_->GetOverdrawBottomHeight();
627 bool size_changed = new_size != last_requested_size_;
628 bool side_payload_changed =
629 screen_info_out_of_date_ ||
630 old_physical_backing_size != physical_backing_size_ ||
631 was_fullscreen != is_fullscreen_ ||
632 old_overdraw_bottom_height != overdraw_bottom_height_;
634 if (!size_changed && !side_payload_changed)
638 screen_info_.reset(new blink::WebScreenInfo);
639 GetWebScreenInfo(screen_info_.get());
642 // We don't expect to receive an ACK when the requested size or the physical
643 // backing size is empty, or when the main viewport size didn't change.
644 if (!new_size.IsEmpty() && !physical_backing_size_.IsEmpty() && size_changed)
645 resize_ack_pending_ = g_check_for_pending_resize_ack;
647 ViewMsg_Resize_Params params;
648 params.screen_info = *screen_info_;
649 params.new_size = new_size;
650 params.physical_backing_size = physical_backing_size_;
651 params.overdraw_bottom_height = overdraw_bottom_height_;
652 params.resizer_rect = GetRootWindowResizerRect();
653 params.is_fullscreen = is_fullscreen_;
654 if (!Send(new ViewMsg_Resize(routing_id_, params))) {
655 resize_ack_pending_ = false;
657 last_requested_size_ = new_size;
661 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
662 Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
665 void RenderWidgetHostImpl::GotFocus() {
669 void RenderWidgetHostImpl::Focus() {
670 Send(new InputMsg_SetFocus(routing_id_, true));
673 void RenderWidgetHostImpl::Blur() {
674 // If there is a pending mouse lock request, we don't want to reject it at
675 // this point. The user can switch focus back to this view and approve the
678 view_->UnlockMouse();
680 // If there is a pending overscroll, then that should be cancelled.
681 if (overscroll_controller_)
682 overscroll_controller_->Cancel();
684 Send(new InputMsg_SetFocus(routing_id_, false));
687 void RenderWidgetHostImpl::LostCapture() {
688 Send(new InputMsg_MouseCaptureLost(routing_id_));
691 void RenderWidgetHostImpl::SetActive(bool active) {
692 Send(new ViewMsg_SetActive(routing_id_, active));
695 void RenderWidgetHostImpl::LostMouseLock() {
696 Send(new ViewMsg_MouseLockLost(routing_id_));
699 void RenderWidgetHostImpl::ViewDestroyed() {
700 RejectMouseLockOrUnlockIfNecessary();
702 // TODO(evanm): tracking this may no longer be necessary;
703 // eliminate this function if so.
707 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
708 is_loading_ = is_loading;
711 view_->SetIsLoading(is_loading);
714 void RenderWidgetHostImpl::CopyFromBackingStore(
715 const gfx::Rect& src_subrect,
716 const gfx::Size& accelerated_dst_size,
717 const base::Callback<void(bool, const SkBitmap&)>& callback,
718 const SkBitmap::Config& bitmap_config) {
719 if (view_ && is_accelerated_compositing_active_) {
720 TRACE_EVENT0("browser",
721 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
722 gfx::Rect accelerated_copy_rect = src_subrect.IsEmpty() ?
723 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
724 view_->CopyFromCompositingSurface(
725 accelerated_copy_rect, accelerated_dst_size, callback, bitmap_config);
729 BackingStore* backing_store = GetBackingStore(false);
730 if (!backing_store) {
731 callback.Run(false, SkBitmap());
735 TRACE_EVENT0("browser",
736 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
737 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
738 gfx::Rect(backing_store->size()) : src_subrect;
739 // When the result size is equal to the backing store size, copy from the
740 // backing store directly to the output canvas.
741 skia::PlatformBitmap output;
742 bool result = backing_store->CopyFromBackingStore(copy_rect, &output);
743 callback.Run(result, output.GetBitmap());
746 bool RenderWidgetHostImpl::CanCopyFromBackingStore() {
748 return view_->IsSurfaceAvailableForCopy();
752 #if defined(OS_ANDROID)
753 void RenderWidgetHostImpl::LockBackingStore() {
755 view_->LockCompositingSurface();
758 void RenderWidgetHostImpl::UnlockBackingStore() {
760 view_->UnlockCompositingSurface();
764 #if defined(TOOLKIT_GTK)
765 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
766 const gfx::Rect& dest_rect, GdkWindow* target) {
767 BackingStore* backing_store = GetBackingStore(false);
770 (static_cast<BackingStoreGtk*>(backing_store))->PaintToRect(
774 #elif defined(OS_MACOSX)
775 gfx::Size RenderWidgetHostImpl::GetBackingStoreSize() {
776 BackingStore* backing_store = GetBackingStore(false);
777 return backing_store ? backing_store->size() : gfx::Size();
780 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
781 const CGRect& dest_rect, CGContextRef target) {
782 BackingStore* backing_store = GetBackingStore(false);
785 (static_cast<BackingStoreMac*>(backing_store))->
786 CopyFromBackingStoreToCGContext(dest_rect, target);
791 void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
792 TRACE_EVENT0("browser",
793 "RenderWidgetHostImpl::PauseForPendingResizeOrRepaints");
795 // Do not pause if the view is hidden.
799 // Do not pause if there is not a paint or resize already coming.
800 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_)
803 // Waiting for a backing store will do the wait for us.
804 ignore_result(GetBackingStore(true));
807 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
808 BackingStore** backing_store) {
809 // Check if the view has an accelerated surface of the desired size.
810 if (view_->HasAcceleratedSurface(desired_size)) {
811 *backing_store = NULL;
815 // Check for a software backing store of the desired size.
816 *backing_store = BackingStoreManager::GetBackingStore(this, desired_size);
817 return !!*backing_store;
820 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
821 TRACE_EVENT1("browser", "RenderWidgetHostImpl::GetBackingStore",
822 "force_create", force_create);
827 // The view_size will be current_size_ for auto-sized views and otherwise the
828 // size of the view_. (For auto-sized views, current_size_ is updated during
829 // UpdateRect messages.)
830 gfx::Size view_size = current_size_;
831 if (!should_auto_resize_) {
832 // Get the desired size from the current view bounds.
833 gfx::Rect view_rect = view_->GetViewBounds();
834 if (view_rect.IsEmpty())
836 view_size = view_rect.size();
839 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
840 "width", base::IntToString(view_size.width()),
841 "height", base::IntToString(view_size.height()));
843 // We should not be asked to paint while we are hidden. If we are hidden,
844 // then it means that our consumer failed to call WasShown. If we're not
845 // force creating the backing store, it's OK since we can feel free to give
846 // out our cached one if we have it.
847 DCHECK(!is_hidden_ || !force_create) <<
848 "GetBackingStore called while hidden!";
850 // We should never be called recursively; this can theoretically lead to
851 // infinite recursion and almost certainly leads to lower performance.
852 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!";
853 base::AutoReset<bool> auto_reset_in_get_backing_store(
854 &in_get_backing_store_, true);
856 // We might have a cached backing store that we can reuse!
857 BackingStore* backing_store = NULL;
858 if (TryGetBackingStore(view_size, &backing_store) || !force_create)
859 return backing_store;
861 // We do not have a suitable backing store in the cache, so send out a
862 // request to the renderer to paint the view if required.
863 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
864 repaint_start_time_ = TimeTicks::Now();
865 repaint_ack_pending_ = true;
866 TRACE_EVENT_ASYNC_BEGIN0(
867 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
868 Send(new ViewMsg_Repaint(routing_id_, view_size));
871 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
872 TimeTicks end_time = TimeTicks::Now() + max_delay;
874 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
876 // When we have asked the RenderWidget to resize, and we are still waiting
877 // on a response, block for a little while to see if we can't get a response
878 // before returning the old (incorrectly sized) backing store.
880 if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
881 OnMessageReceived(msg);
883 // For auto-resized views, current_size_ determines the view_size and it
884 // may have changed during the handling of an UpdateRect message.
885 if (should_auto_resize_)
886 view_size = current_size_;
888 // Break now if we got a backing store or accelerated surface of the
890 if (TryGetBackingStore(view_size, &backing_store) ||
891 abort_get_backing_store_) {
892 abort_get_backing_store_ = false;
893 return backing_store;
896 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
900 // Loop if we still have time left and haven't gotten a properly sized
901 // BackingStore yet. This is necessary to support the GPU path which
902 // typically has multiple frames pipelined -- we may need to skip one or two
903 // BackingStore messages to get to the latest.
904 max_delay = end_time - TimeTicks::Now();
905 } while (max_delay > TimeDelta::FromSeconds(0));
907 // We have failed to get a backing store of view_size. Fall back on
908 // current_size_ to avoid a white flash while resizing slow pages.
909 if (view_size != current_size_)
910 TryGetBackingStore(current_size_, &backing_store);
911 return backing_store;
914 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) {
917 return view_->AllocBackingStore(size);
920 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
921 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
924 bool RenderWidgetHostImpl::ScheduleComposite() {
925 if (is_hidden_ || !is_accelerated_compositing_active_ ||
926 current_size_.IsEmpty() || repaint_ack_pending_ ||
927 resize_ack_pending_ || view_being_painted_) {
931 // Send out a request to the renderer to paint the view if required.
932 repaint_start_time_ = TimeTicks::Now();
933 repaint_ack_pending_ = true;
934 TRACE_EVENT_ASYNC_BEGIN0(
935 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
936 Send(new ViewMsg_Repaint(routing_id_, current_size_));
940 void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay) {
941 if (hang_monitor_timeout_)
942 hang_monitor_timeout_->Start(delay);
945 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
946 if (hang_monitor_timeout_)
947 hang_monitor_timeout_->Restart(
948 base::TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
951 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
952 if (hang_monitor_timeout_)
953 hang_monitor_timeout_->Stop();
954 RendererIsResponsive();
957 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
958 AddAccessibilityMode(AccessibilityModeComplete);
961 bool RenderWidgetHostImpl::IsFullAccessibilityModeForTesting() {
962 return accessibility_mode() == AccessibilityModeComplete;
965 void RenderWidgetHostImpl::EnableTreeOnlyAccessibilityMode() {
966 AddAccessibilityMode(AccessibilityModeTreeOnly);
969 bool RenderWidgetHostImpl::IsTreeOnlyAccessibilityModeForTesting() {
970 return accessibility_mode() == AccessibilityModeTreeOnly;
973 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
974 ForwardMouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo());
977 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
978 const blink::WebMouseEvent& mouse_event,
979 const ui::LatencyInfo& ui_latency) {
980 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
981 "x", mouse_event.x, "y", mouse_event.y);
983 ui::LatencyInfo latency_info =
984 CreateRWHLatencyInfoIfNotExist(&ui_latency, mouse_event.type);
986 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
987 if (mouse_event_callbacks_[i].Run(mouse_event))
991 if (IgnoreInputEvents())
994 input_router_->SendMouseEvent(MouseEventWithLatencyInfo(mouse_event,
998 void RenderWidgetHostImpl::OnPointerEventActivate() {
1001 void RenderWidgetHostImpl::ForwardWheelEvent(
1002 const WebMouseWheelEvent& wheel_event) {
1003 ForwardWheelEventWithLatencyInfo(wheel_event, ui::LatencyInfo());
1006 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
1007 const blink::WebMouseWheelEvent& wheel_event,
1008 const ui::LatencyInfo& ui_latency) {
1009 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
1011 ui::LatencyInfo latency_info =
1012 CreateRWHLatencyInfoIfNotExist(&ui_latency, wheel_event.type);
1014 if (IgnoreInputEvents())
1017 input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event,
1021 void RenderWidgetHostImpl::ForwardGestureEvent(
1022 const blink::WebGestureEvent& gesture_event) {
1023 ForwardGestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo());
1026 void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
1027 const blink::WebGestureEvent& gesture_event,
1028 const ui::LatencyInfo& ui_latency) {
1029 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
1030 // Early out if necessary, prior to performing latency logic.
1031 if (IgnoreInputEvents())
1034 if (delegate_->PreHandleGestureEvent(gesture_event))
1037 ui::LatencyInfo latency_info =
1038 CreateRWHLatencyInfoIfNotExist(&ui_latency, gesture_event.type);
1040 if (gesture_event.type == blink::WebInputEvent::GestureScrollUpdate) {
1041 latency_info.AddLatencyNumber(
1042 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
1043 GetLatencyComponentId(),
1044 ++last_input_number_);
1046 // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
1047 // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
1048 // So we can track the latency specifically for scroll update events.
1049 ui::LatencyInfo::LatencyComponent original_component;
1050 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
1052 &original_component)) {
1053 latency_info.AddLatencyNumberWithTimestamp(
1054 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
1055 GetLatencyComponentId(),
1056 original_component.sequence_number,
1057 original_component.event_time,
1058 original_component.event_count);
1062 GestureEventWithLatencyInfo gesture_with_latency(gesture_event, latency_info);
1063 input_router_->SendGestureEvent(gesture_with_latency);
1066 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1067 const blink::WebTouchEvent& touch_event,
1068 const ui::LatencyInfo& ui_latency) {
1069 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1071 // Always forward TouchEvents for touch stream consistency. They will be
1072 // ignored if appropriate in FilterInputEvent().
1074 ui::LatencyInfo latency_info =
1075 CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type);
1076 TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
1077 input_router_->SendTouchEvent(touch_with_latency);
1080 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1081 const NativeWebKeyboardEvent& key_event) {
1082 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1083 if (IgnoreInputEvents())
1086 if (!process_->HasConnection())
1089 // First, let keypress listeners take a shot at handling the event. If a
1090 // listener handles the event, it should not be propagated to the renderer.
1091 if (KeyPressListenersHandleEvent(key_event)) {
1092 // Some keypresses that are accepted by the listener might have follow up
1093 // char events, which should be ignored.
1094 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1095 suppress_next_char_events_ = true;
1099 if (key_event.type == WebKeyboardEvent::Char &&
1100 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
1101 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
1105 // Double check the type to make sure caller hasn't sent us nonsense that
1106 // will mess up our key queue.
1107 if (!WebInputEvent::isKeyboardEventType(key_event.type))
1110 if (suppress_next_char_events_) {
1111 // If preceding RawKeyDown event was handled by the browser, then we need
1112 // suppress all Char events generated by it. Please note that, one
1113 // RawKeyDown event may generate multiple Char events, so we can't reset
1114 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1115 if (key_event.type == WebKeyboardEvent::Char)
1117 // We get a KeyUp or a RawKeyDown event.
1118 suppress_next_char_events_ = false;
1121 bool is_shortcut = false;
1123 // Only pre-handle the key event if it's not handled by the input method.
1124 if (delegate_ && !key_event.skip_in_browser) {
1125 // We need to set |suppress_next_char_events_| to true if
1126 // PreHandleKeyboardEvent() returns true, but |this| may already be
1127 // destroyed at that time. So set |suppress_next_char_events_| true here,
1128 // then revert it afterwards when necessary.
1129 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1130 suppress_next_char_events_ = true;
1132 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1133 // a hung/malicious renderer from interfering.
1134 if (delegate_->PreHandleKeyboardEvent(key_event, &is_shortcut))
1137 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1138 suppress_next_char_events_ = false;
1141 input_router_->SendKeyboardEvent(
1143 CreateRWHLatencyInfoIfNotExist(NULL, key_event.type),
1147 void RenderWidgetHostImpl::QueueSyntheticGesture(
1148 scoped_ptr<SyntheticGesture> synthetic_gesture,
1149 const base::Callback<void(SyntheticGesture::Result)>& on_complete) {
1150 if (!synthetic_gesture_controller_ && view_) {
1151 synthetic_gesture_controller_.reset(
1152 new SyntheticGestureController(
1153 view_->CreateSyntheticGestureTarget().Pass()));
1155 if (synthetic_gesture_controller_) {
1156 synthetic_gesture_controller_->QueueSyntheticGesture(
1157 synthetic_gesture.Pass(), on_complete);
1161 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
1162 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
1165 int64 RenderWidgetHostImpl::GetLatencyComponentId() {
1166 return GetRoutingID() | (static_cast<int64>(GetProcess()->GetID()) << 32);
1170 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1171 g_check_for_pending_resize_ack = false;
1174 ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
1175 const ui::LatencyInfo* original, WebInputEvent::Type type) {
1176 ui::LatencyInfo info;
1179 // In Aura, gesture event will already carry its original touch event's
1180 // INPUT_EVENT_LATENCY_RWH_COMPONENT.
1181 if (!info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1182 GetLatencyComponentId(),
1184 info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1185 GetLatencyComponentId(),
1186 ++last_input_number_);
1187 info.TraceEventType(WebInputEventTraits::GetName(type));
1193 void RenderWidgetHostImpl::AddKeyPressEventCallback(
1194 const KeyPressEventCallback& callback) {
1195 key_press_event_callbacks_.push_back(callback);
1198 void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
1199 const KeyPressEventCallback& callback) {
1200 for (size_t i = 0; i < key_press_event_callbacks_.size(); ++i) {
1201 if (key_press_event_callbacks_[i].Equals(callback)) {
1202 key_press_event_callbacks_.erase(
1203 key_press_event_callbacks_.begin() + i);
1209 void RenderWidgetHostImpl::AddMouseEventCallback(
1210 const MouseEventCallback& callback) {
1211 mouse_event_callbacks_.push_back(callback);
1214 void RenderWidgetHostImpl::RemoveMouseEventCallback(
1215 const MouseEventCallback& callback) {
1216 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
1217 if (mouse_event_callbacks_[i].Equals(callback)) {
1218 mouse_event_callbacks_.erase(mouse_event_callbacks_.begin() + i);
1224 void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
1225 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1227 static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
1229 RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
1230 screen_info_out_of_date_ = false;
1233 const NativeWebKeyboardEvent*
1234 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1235 return input_router_->GetLastKeyboardEvent();
1238 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1239 // The resize message (which may not happen immediately) will carry with it
1240 // the screen info as well as the new size (if the screen has changed scale
1242 InvalidateScreenInfo();
1246 void RenderWidgetHostImpl::InvalidateScreenInfo() {
1247 screen_info_out_of_date_ = true;
1248 screen_info_.reset();
1251 void RenderWidgetHostImpl::GetSnapshotFromRenderer(
1252 const gfx::Rect& src_subrect,
1253 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1254 TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
1256 callback.Run(false, SkBitmap());
1260 pending_snapshots_.push(callback);
1262 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
1263 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
1265 gfx::Rect copy_rect_in_pixel = ConvertViewRectToPixel(view_, copy_rect);
1266 Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel));
1269 void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
1271 const gfx::Range& range) {
1273 view_->SelectionChanged(text, offset, range);
1276 void RenderWidgetHostImpl::OnSelectionBoundsChanged(
1277 const ViewHostMsg_SelectionBounds_Params& params) {
1279 view_->SelectionBoundsChanged(params);
1283 void RenderWidgetHostImpl::OnSnapshot(bool success,
1284 const SkBitmap& bitmap) {
1285 if (pending_snapshots_.size() == 0) {
1286 LOG(ERROR) << "RenderWidgetHostImpl::OnSnapshot: "
1287 "Received a snapshot that was not requested.";
1291 base::Callback<void(bool, const SkBitmap&)> callback =
1292 pending_snapshots_.front();
1293 pending_snapshots_.pop();
1296 callback.Run(success, SkBitmap());
1300 callback.Run(success, bitmap);
1303 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase,
1304 base::TimeDelta interval) {
1305 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase, interval));
1308 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
1310 // Clearing this flag causes us to re-create the renderer when recovering
1311 // from a crashed renderer.
1312 renderer_initialized_ = false;
1314 waiting_for_screen_rects_ack_ = false;
1316 // Reset to ensure that input routing works with a new renderer.
1317 input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
1319 if (overscroll_controller_)
1320 overscroll_controller_->Reset();
1322 // Must reset these to ensure that keyboard events work with a new renderer.
1323 suppress_next_char_events_ = false;
1325 // Reset some fields in preparation for recovering from a crash.
1326 ResetSizeAndRepaintPendingFlags();
1327 current_size_.SetSize(0, 0);
1329 is_accelerated_compositing_active_ = false;
1331 // Reset this to ensure the hung renderer mechanism is working properly.
1332 in_flight_event_count_ = 0;
1335 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_,
1336 gfx::GLSurfaceHandle());
1337 view_->RenderProcessGone(status, exit_code);
1338 view_ = NULL; // The View should be deleted by RenderProcessGone.
1341 BackingStoreManager::RemoveBackingStore(this);
1343 synthetic_gesture_controller_.reset();
1346 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction) {
1347 text_direction_updated_ = true;
1348 text_direction_ = direction;
1351 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1352 if (text_direction_updated_)
1353 text_direction_canceled_ = true;
1356 void RenderWidgetHostImpl::NotifyTextDirection() {
1357 if (text_direction_updated_) {
1358 if (!text_direction_canceled_)
1359 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_));
1360 text_direction_updated_ = false;
1361 text_direction_canceled_ = false;
1365 void RenderWidgetHostImpl::SetInputMethodActive(bool activate) {
1366 input_method_active_ = activate;
1367 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate));
1370 void RenderWidgetHostImpl::CandidateWindowShown() {
1371 Send(new ViewMsg_CandidateWindowShown(GetRoutingID()));
1374 void RenderWidgetHostImpl::CandidateWindowUpdated() {
1375 Send(new ViewMsg_CandidateWindowUpdated(GetRoutingID()));
1378 void RenderWidgetHostImpl::CandidateWindowHidden() {
1379 Send(new ViewMsg_CandidateWindowHidden(GetRoutingID()));
1382 void RenderWidgetHostImpl::ImeSetComposition(
1383 const base::string16& text,
1384 const std::vector<blink::WebCompositionUnderline>& underlines,
1385 int selection_start,
1386 int selection_end) {
1387 Send(new ViewMsg_ImeSetComposition(
1388 GetRoutingID(), text, underlines, selection_start, selection_end));
1391 void RenderWidgetHostImpl::ImeConfirmComposition(
1392 const base::string16& text,
1393 const gfx::Range& replacement_range,
1394 bool keep_selection) {
1395 Send(new ViewMsg_ImeConfirmComposition(
1396 GetRoutingID(), text, replacement_range, keep_selection));
1399 void RenderWidgetHostImpl::ImeCancelComposition() {
1400 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(),
1401 std::vector<blink::WebCompositionUnderline>(), 0, 0));
1404 gfx::Rect RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1408 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture,
1409 bool last_unlocked_by_target) {
1410 // Directly reject to lock the mouse. Subclass can override this method to
1411 // decide whether to allow mouse lock or not.
1412 GotResponseToLockMouseRequest(false);
1415 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1416 DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
1417 if (pending_mouse_lock_request_) {
1418 pending_mouse_lock_request_ = false;
1419 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1420 } else if (IsMouseLocked()) {
1421 view_->UnlockMouse();
1425 bool RenderWidgetHostImpl::IsMouseLocked() const {
1426 return view_ ? view_->IsMouseLocked() : false;
1429 bool RenderWidgetHostImpl::IsFullscreen() const {
1433 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
1434 should_auto_resize_ = enable;
1437 void RenderWidgetHostImpl::Destroy() {
1438 NotificationService::current()->Notify(
1439 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1440 Source<RenderWidgetHost>(this),
1441 NotificationService::NoDetails());
1443 // Tell the view to die.
1444 // Note that in the process of the view shutting down, it can call a ton
1445 // of other messages on us. So if you do any other deinitialization here,
1446 // do it after this call to view_->Destroy().
1453 void RenderWidgetHostImpl::RendererIsUnresponsive() {
1454 NotificationService::current()->Notify(
1455 NOTIFICATION_RENDER_WIDGET_HOST_HANG,
1456 Source<RenderWidgetHost>(this),
1457 NotificationService::NoDetails());
1458 is_unresponsive_ = true;
1459 NotifyRendererUnresponsive();
1462 void RenderWidgetHostImpl::RendererIsResponsive() {
1463 if (is_unresponsive_) {
1464 is_unresponsive_ = false;
1465 NotifyRendererResponsive();
1469 void RenderWidgetHostImpl::OnRenderViewReady() {
1474 void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
1475 // TODO(evanm): This synchronously ends up calling "delete this".
1476 // Is that really what we want in response to this message? I'm matching
1477 // previous behavior of the code here.
1481 void RenderWidgetHostImpl::OnClose() {
1485 void RenderWidgetHostImpl::OnSetTooltipText(
1486 const base::string16& tooltip_text,
1487 WebTextDirection text_direction_hint) {
1488 // First, add directionality marks around tooltip text if necessary.
1489 // A naive solution would be to simply always wrap the text. However, on
1490 // windows, Unicode directional embedding characters can't be displayed on
1491 // systems that lack RTL fonts and are instead displayed as empty squares.
1493 // To get around this we only wrap the string when we deem it necessary i.e.
1494 // when the locale direction is different than the tooltip direction hint.
1496 // Currently, we use element's directionality as the tooltip direction hint.
1497 // An alternate solution would be to set the overall directionality based on
1498 // trying to detect the directionality from the tooltip text rather than the
1499 // element direction. One could argue that would be a preferable solution
1500 // but we use the current approach to match Fx & IE's behavior.
1501 base::string16 wrapped_tooltip_text = tooltip_text;
1502 if (!tooltip_text.empty()) {
1503 if (text_direction_hint == blink::WebTextDirectionLeftToRight) {
1504 // Force the tooltip to have LTR directionality.
1505 wrapped_tooltip_text =
1506 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
1507 } else if (text_direction_hint == blink::WebTextDirectionRightToLeft &&
1508 !base::i18n::IsRTL()) {
1509 // Force the tooltip to have RTL directionality.
1510 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
1514 view_->SetTooltipText(wrapped_tooltip_text);
1517 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1518 waiting_for_screen_rects_ack_ = false;
1522 if (view_->GetViewBounds() == last_view_screen_rect_ &&
1523 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
1530 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
1532 view_->SetBounds(pos);
1533 Send(new ViewMsg_Move_ACK(routing_id_));
1537 #if defined(OS_MACOSX)
1538 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1539 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1540 TRACE_EVENT0("renderer_host",
1541 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1542 if (!ui::LatencyInfo::Verify(params.latency_info,
1543 "ViewHostMsg_CompositorSurfaceBuffersSwapped"))
1546 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1547 ack_params.sync_point = 0;
1548 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1549 params.gpu_process_host_id,
1553 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
1554 gpu_params.surface_id = params.surface_id;
1555 gpu_params.surface_handle = params.surface_handle;
1556 gpu_params.route_id = params.route_id;
1557 gpu_params.size = params.size;
1558 gpu_params.scale_factor = params.scale_factor;
1559 gpu_params.latency_info = params.latency_info;
1560 for (size_t i = 0; i < gpu_params.latency_info.size(); i++)
1561 AddLatencyInfoComponentIds(&gpu_params.latency_info[i]);
1562 view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
1563 params.gpu_process_host_id);
1564 view_->DidReceiveRendererFrame();
1568 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1569 const IPC::Message& message) {
1570 ViewHostMsg_SwapCompositorFrame::Param param;
1571 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m))
1573 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
1574 uint32 output_surface_id = param.a;
1575 param.b.AssignTo(frame.get());
1577 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++)
1578 AddLatencyInfoComponentIds(&frame->metadata.latency_info[i]);
1580 input_router_->OnViewUpdated(
1581 GetInputRouterViewFlagsFromCompositorFrameMetadata(frame->metadata));
1584 view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
1585 view_->DidReceiveRendererFrame();
1587 cc::CompositorFrameAck ack;
1588 if (frame->gl_frame_data) {
1589 ack.gl_frame_data = frame->gl_frame_data.Pass();
1590 ack.gl_frame_data->sync_point = 0;
1591 } else if (frame->delegated_frame_data) {
1592 cc::TransferableResource::ReturnResources(
1593 frame->delegated_frame_data->resource_list,
1595 } else if (frame->software_frame_data) {
1596 ack.last_software_frame_id = frame->software_frame_data->id;
1598 SendSwapCompositorFrameAck(routing_id_, output_surface_id,
1599 process_->GetID(), ack);
1604 void RenderWidgetHostImpl::OnOverscrolled(
1605 gfx::Vector2dF accumulated_overscroll,
1606 gfx::Vector2dF current_fling_velocity) {
1608 view_->OnOverscrolled(accumulated_overscroll, current_fling_velocity);
1611 void RenderWidgetHostImpl::OnFlingingStopped() {
1613 view_->DidStopFlinging();
1616 void RenderWidgetHostImpl::OnUpdateRect(
1617 const ViewHostMsg_UpdateRect_Params& params) {
1618 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1619 TimeTicks paint_start = TimeTicks::Now();
1621 // Update our knowledge of the RenderWidget's size.
1622 current_size_ = params.view_size;
1623 // Update our knowledge of the RenderWidget's scroll offset.
1624 last_scroll_offset_ = params.scroll_offset;
1626 bool is_resize_ack =
1627 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1629 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1630 // that will end up reaching GetBackingStore.
1631 if (is_resize_ack) {
1632 DCHECK(!g_check_for_pending_resize_ack || resize_ack_pending_);
1633 resize_ack_pending_ = false;
1636 bool is_repaint_ack =
1637 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
1638 if (is_repaint_ack) {
1639 DCHECK(repaint_ack_pending_);
1640 TRACE_EVENT_ASYNC_END0(
1641 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1642 repaint_ack_pending_ = false;
1643 TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
1644 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
1647 DCHECK(!params.view_size.IsEmpty());
1649 bool was_async = false;
1651 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1652 TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
1654 // If gpu process does painting, scroll_rect and copy_rects are always empty
1655 // and backing store is never used.
1657 DCHECK(!params.bitmap_rect.IsEmpty());
1658 gfx::Size pixel_size = gfx::ToFlooredSize(
1659 gfx::ScaleSize(params.bitmap_rect.size(), params.scale_factor));
1660 const size_t size = pixel_size.height() * pixel_size.width() * 4;
1661 if (dib->size() < size) {
1662 DLOG(WARNING) << "Transport DIB too small for given rectangle";
1663 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH1"));
1664 GetProcess()->ReceivedBadMessage();
1666 // Scroll the backing store.
1667 if (!params.scroll_rect.IsEmpty()) {
1668 ScrollBackingStoreRect(params.scroll_delta,
1673 // Paint the backing store. This will update it with the
1674 // renderer-supplied bits. The view will read out of the backing store
1675 // later to actually draw to the screen.
1676 was_async = PaintBackingStoreRect(
1681 params.scale_factor,
1682 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
1683 weak_factory_.GetWeakPtr(), params, paint_start));
1688 DidUpdateBackingStore(params, paint_start);
1691 if (should_auto_resize_) {
1692 bool post_callback = new_auto_size_.IsEmpty();
1693 new_auto_size_ = params.view_size;
1694 if (post_callback) {
1695 base::MessageLoop::current()->PostTask(
1697 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
1698 weak_factory_.GetWeakPtr()));
1702 // Log the time delta for processing a paint message. On platforms that don't
1703 // support asynchronous painting, this is equivalent to
1704 // MPArch.RWH_TotalPaintTime.
1705 TimeDelta delta = TimeTicks::Now() - paint_start;
1706 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
1709 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1710 if (in_get_backing_store_)
1711 abort_get_backing_store_ = true;
1714 void RenderWidgetHostImpl::DidUpdateBackingStore(
1715 const ViewHostMsg_UpdateRect_Params& params,
1716 const TimeTicks& paint_start) {
1717 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1718 TimeTicks update_start = TimeTicks::Now();
1720 if (params.needs_ack) {
1721 // ACK early so we can prefetch the next PaintRect if there is a next one.
1722 // This must be done AFTER we're done painting with the bitmap supplied by
1723 // the renderer. This ACK is a signal to the renderer that the backing store
1724 // can be re-used, so the bitmap may be invalid after this call.
1725 Send(new ViewMsg_UpdateRect_ACK(routing_id_));
1728 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1729 // will not be re-issued, so must move them now, regardless of whether we
1730 // paint or not. MovePluginWindows attempts to move the plugin windows and
1731 // in the process could dispatch other window messages which could cause the
1732 // view to be destroyed.
1734 view_->MovePluginWindows(params.scroll_offset, params.plugin_window_moves);
1736 NotificationService::current()->Notify(
1737 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
1738 Source<RenderWidgetHost>(this),
1739 NotificationService::NoDetails());
1741 // We don't need to update the view if the view is hidden. We must do this
1742 // early return after the ACK is sent, however, or the renderer will not send
1747 // Now paint the view. Watch out: it might be destroyed already.
1748 if (view_ && !is_accelerated_compositing_active_) {
1750 std::vector<ui::LatencyInfo> latency_info;
1751 for (size_t i = 0; i < params.latency_info.size(); i++) {
1752 ui::LatencyInfo info = params.latency_info[i];
1753 AddLatencyInfoComponentIds(&info);
1754 latency_info.push_back(info);
1757 view_being_painted_ = true;
1758 view_->DidUpdateBackingStore(params.scroll_rect, params.scroll_delta,
1759 params.copy_rects, latency_info);
1760 view_->DidReceiveRendererFrame();
1761 view_being_painted_ = false;
1764 // If we got a resize ack, then perhaps we have another resize to send?
1765 bool is_resize_ack =
1766 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1770 // Log the time delta for processing a paint message.
1771 TimeTicks now = TimeTicks::Now();
1772 TimeDelta delta = now - update_start;
1773 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta);
1775 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1776 // DidUpdateBackingStore() method. On platforms which have asynchronous
1777 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1778 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1779 // waiting for the paint to complete.
1781 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1782 delta = now - paint_start;
1783 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
1786 void RenderWidgetHostImpl::OnQueueSyntheticGesture(
1787 const SyntheticGesturePacket& gesture_packet) {
1788 // Only allow untrustworthy gestures if explicitly enabled.
1789 if (!CommandLine::ForCurrentProcess()->HasSwitch(
1790 cc::switches::kEnableGpuBenchmarking)) {
1791 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH7"));
1792 GetProcess()->ReceivedBadMessage();
1796 QueueSyntheticGesture(
1797 SyntheticGesture::Create(*gesture_packet.gesture_params()),
1798 base::Bind(&RenderWidgetHostImpl::OnSyntheticGestureCompleted,
1799 weak_factory_.GetWeakPtr()));
1802 void RenderWidgetHostImpl::OnFocus() {
1803 // Only RenderViewHost can deal with that message.
1804 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH4"));
1805 GetProcess()->ReceivedBadMessage();
1808 void RenderWidgetHostImpl::OnBlur() {
1809 // Only RenderViewHost can deal with that message.
1810 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH5"));
1811 GetProcess()->ReceivedBadMessage();
1814 void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
1818 view_->UpdateCursor(cursor);
1821 void RenderWidgetHostImpl::OnTextInputTypeChanged(
1822 ui::TextInputType type,
1823 ui::TextInputMode input_mode,
1824 bool can_compose_inline) {
1826 view_->TextInputTypeChanged(type, input_mode, can_compose_inline);
1829 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1830 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
1831 const gfx::Range& range,
1832 const std::vector<gfx::Rect>& character_bounds) {
1834 view_->ImeCompositionRangeChanged(range, character_bounds);
1838 void RenderWidgetHostImpl::OnImeCancelComposition() {
1840 view_->ImeCancelComposition();
1843 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated) {
1844 TRACE_EVENT1("renderer_host",
1845 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
1846 "activated", activated);
1847 is_accelerated_compositing_active_ = activated;
1849 view_->OnAcceleratedCompositingStateChange();
1852 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
1853 bool last_unlocked_by_target,
1856 if (pending_mouse_lock_request_) {
1857 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1859 } else if (IsMouseLocked()) {
1860 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
1864 pending_mouse_lock_request_ = true;
1865 if (privileged && allow_privileged_mouse_lock_) {
1866 // Directly approve to lock the mouse.
1867 GotResponseToLockMouseRequest(true);
1869 RequestToLockMouse(user_gesture, last_unlocked_by_target);
1873 void RenderWidgetHostImpl::OnUnlockMouse() {
1874 RejectMouseLockOrUnlockIfNecessary();
1877 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
1878 const gfx::Rect& rect,
1879 const gfx::Size& size,
1880 const TransportDIB::Id& id) {
1881 DCHECK(!rect.IsEmpty());
1882 DCHECK(!size.IsEmpty());
1884 TransportDIB* dib = process_->GetTransportDIB(id);
1886 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH6"));
1887 GetProcess()->ReceivedBadMessage();
1891 DCHECK(dib->memory());
1892 DCHECK(dib->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config,
1893 size.width(), size.height()));
1895 SkBitmap zoomed_bitmap;
1896 zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
1897 size.width(), size.height());
1898 zoomed_bitmap.setPixels(dib->memory());
1900 #if defined(OS_ANDROID)
1902 view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
1907 zoomed_bitmap.setPixels(0);
1908 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
1913 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
1914 gfx::NativeViewId dummy_activation_window) {
1915 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1917 // This may happen as a result of a race condition when the plugin is going
1919 wchar_t window_title[MAX_PATH + 1] = {0};
1920 if (!IsWindow(hwnd) ||
1921 !GetWindowText(hwnd, window_title, arraysize(window_title)) ||
1922 lstrcmpiW(window_title, kDummyActivationWindowName) != 0) {
1926 #if defined(USE_AURA)
1928 reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
1930 SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
1932 dummy_windows_for_activation_.push_back(hwnd);
1935 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
1936 gfx::NativeViewId dummy_activation_window) {
1937 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1938 std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
1939 for (; i != dummy_windows_for_activation_.end(); ++i) {
1941 dummy_windows_for_activation_.erase(i);
1945 NOTREACHED() << "Unknown dummy window";
1949 bool RenderWidgetHostImpl::PaintBackingStoreRect(
1950 TransportDIB::Id bitmap,
1951 const gfx::Rect& bitmap_rect,
1952 const std::vector<gfx::Rect>& copy_rects,
1953 const gfx::Size& view_size,
1955 const base::Closure& completion_callback) {
1956 // The view may be destroyed already.
1961 // Don't bother updating the backing store when we're hidden. Just mark it
1962 // as being totally invalid. This will cause a complete repaint when the
1963 // view is restored.
1964 needs_repainting_on_restore_ = true;
1968 bool needs_full_paint = false;
1969 bool scheduled_completion_callback = false;
1970 BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
1971 copy_rects, scale_factor,
1972 completion_callback,
1974 &scheduled_completion_callback);
1975 if (needs_full_paint) {
1976 repaint_start_time_ = TimeTicks::Now();
1977 DCHECK(!repaint_ack_pending_);
1978 repaint_ack_pending_ = true;
1979 TRACE_EVENT_ASYNC_BEGIN0(
1980 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1981 Send(new ViewMsg_Repaint(routing_id_, view_size));
1984 return scheduled_completion_callback;
1987 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta,
1988 const gfx::Rect& clip_rect,
1989 const gfx::Size& view_size) {
1991 // Don't bother updating the backing store when we're hidden. Just mark it
1992 // as being totally invalid. This will cause a complete repaint when the
1993 // view is restored.
1994 needs_repainting_on_restore_ = true;
1998 // TODO(darin): do we need to do something else if our backing store is not
1999 // the same size as the advertised view? maybe we just assume there is a
2000 // full paint on its way?
2001 BackingStore* backing_store = BackingStoreManager::Lookup(this);
2002 if (!backing_store || (backing_store->size() != view_size))
2004 backing_store->ScrollBackingStore(delta, clip_rect, view_size);
2007 void RenderWidgetHostImpl::Replace(const base::string16& word) {
2008 Send(new InputMsg_Replace(routing_id_, word));
2011 void RenderWidgetHostImpl::ReplaceMisspelling(const base::string16& word) {
2012 Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
2015 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
2016 ignore_input_events_ = ignore_input_events;
2019 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
2020 const NativeWebKeyboardEvent& event) {
2021 if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
2024 for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
2025 size_t original_size = key_press_event_callbacks_.size();
2026 if (key_press_event_callbacks_[i].Run(event))
2029 // Check whether the callback that just ran removed itself, in which case
2030 // the iterator needs to be decremented to properly account for the removal.
2031 size_t current_size = key_press_event_callbacks_.size();
2032 if (current_size != original_size) {
2033 DCHECK_EQ(original_size - 1, current_size);
2041 InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
2042 const blink::WebInputEvent& event, const ui::LatencyInfo& latency_info) {
2043 // Don't ignore touch cancel events, since they may be sent while input
2044 // events are being ignored in order to keep the renderer from getting
2045 // confused about how many touches are active.
2046 if (IgnoreInputEvents() && event.type != WebInputEvent::TouchCancel)
2047 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
2049 if (!process_->HasConnection())
2050 return INPUT_EVENT_ACK_STATE_UNKNOWN;
2052 if (event.type == WebInputEvent::MouseDown)
2055 return view_ ? view_->FilterInputEvent(event)
2056 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
2059 void RenderWidgetHostImpl::IncrementInFlightEventCount() {
2060 StartHangMonitorTimeout(
2061 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
2062 increment_in_flight_event_count();
2065 void RenderWidgetHostImpl::DecrementInFlightEventCount() {
2066 DCHECK(in_flight_event_count_ >= 0);
2067 // Cancel pending hung renderer checks since the renderer is responsive.
2068 if (decrement_in_flight_event_count() <= 0)
2069 StopHangMonitorTimeout();
2072 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
2073 has_touch_handler_ = has_handlers;
2076 OverscrollController* RenderWidgetHostImpl::GetOverscrollController() const {
2077 return overscroll_controller_.get();
2080 void RenderWidgetHostImpl::DidFlush() {
2082 view_->OnDidFlushInput();
2085 void RenderWidgetHostImpl::OnKeyboardEventAck(
2086 const NativeWebKeyboardEvent& event,
2087 InputEventAckState ack_result) {
2088 #if defined(OS_MACOSX)
2089 if (!is_hidden() && view_ && view_->PostProcessEventForPluginIme(event))
2093 // We only send unprocessed key event upwards if we are not hidden,
2094 // because the user has moved away from us and no longer expect any effect
2095 // of this key event.
2096 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2097 if (delegate_ && !processed && !is_hidden() && !event.skip_in_browser) {
2098 delegate_->HandleKeyboardEvent(event);
2100 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2101 // (i.e. in the case of Ctrl+W, where the call to
2102 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2106 void RenderWidgetHostImpl::OnWheelEventAck(
2107 const MouseWheelEventWithLatencyInfo& wheel_event,
2108 InputEventAckState ack_result) {
2109 if (!wheel_event.latency.FindLatency(
2110 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2111 // MouseWheelEvent latency ends when it is acked but does not cause any
2112 // rendering scheduled.
2113 ui::LatencyInfo latency = wheel_event.latency;
2114 latency.AddLatencyNumber(
2115 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
2118 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2119 if (!processed && !is_hidden() && view_) {
2120 if (!delegate_->HandleWheelEvent(wheel_event.event))
2121 view_->UnhandledWheelEvent(wheel_event.event);
2125 void RenderWidgetHostImpl::OnGestureEventAck(
2126 const GestureEventWithLatencyInfo& event,
2127 InputEventAckState ack_result) {
2128 if (!event.latency.FindLatency(
2129 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2130 // GestureEvent latency ends when it is acked but does not cause any
2131 // rendering scheduled.
2132 ui::LatencyInfo latency = event.latency;
2133 latency.AddLatencyNumber(
2134 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0 ,0);
2138 view_->GestureEventAck(event.event, ack_result);
2141 void RenderWidgetHostImpl::OnTouchEventAck(
2142 const TouchEventWithLatencyInfo& event,
2143 InputEventAckState ack_result) {
2144 TouchEventWithLatencyInfo touch_event = event;
2145 touch_event.latency.AddLatencyNumber(
2146 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0);
2147 // TouchEvent latency ends at ack if it didn't cause any rendering.
2148 if (!touch_event.latency.FindLatency(
2149 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2150 touch_event.latency.AddLatencyNumber(
2151 ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0);
2153 ComputeTouchLatency(touch_event.latency);
2155 view_->ProcessAckedTouchEvent(touch_event, ack_result);
2158 void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
2159 if (type == BAD_ACK_MESSAGE) {
2160 RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH2"));
2161 process_->ReceivedBadMessage();
2162 } else if (type == UNEXPECTED_EVENT_TYPE) {
2163 suppress_next_char_events_ = false;
2167 void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
2168 SyntheticGesture::Result result) {
2169 Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
2172 const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
2173 return last_scroll_offset_;
2176 bool RenderWidgetHostImpl::IgnoreInputEvents() const {
2177 return ignore_input_events_ || process_->IgnoreInputEvents();
2180 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2181 return input_router_->ShouldForwardTouchEvent();
2184 void RenderWidgetHostImpl::StartUserGesture() {
2188 void RenderWidgetHostImpl::Stop() {
2189 Send(new ViewMsg_Stop(GetRoutingID()));
2192 void RenderWidgetHostImpl::SetBackground(const SkBitmap& background) {
2193 Send(new ViewMsg_SetBackground(GetRoutingID(), background));
2196 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2197 const std::vector<EditCommand>& commands) {
2198 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
2201 void RenderWidgetHostImpl::AddAccessibilityMode(AccessibilityMode mode) {
2202 SetAccessibilityMode(
2203 content::AddAccessibilityModeTo(accessibility_mode_, mode));
2206 void RenderWidgetHostImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
2207 SetAccessibilityMode(
2208 content::RemoveAccessibilityModeFrom(accessibility_mode_, mode));
2211 void RenderWidgetHostImpl::ResetAccessibilityMode() {
2212 SetAccessibilityMode(
2213 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
2216 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
2217 accessibility_mode_ = mode;
2218 Send(new ViewMsg_SetAccessibilityMode(GetRoutingID(), mode));
2221 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
2222 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
2225 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id) {
2226 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id));
2229 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2230 int acc_obj_id, gfx::Rect subfocus) {
2231 Send(new AccessibilityMsg_ScrollToMakeVisible(
2232 GetRoutingID(), acc_obj_id, subfocus));
2235 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2236 int acc_obj_id, gfx::Point point) {
2237 Send(new AccessibilityMsg_ScrollToPoint(
2238 GetRoutingID(), acc_obj_id, point));
2241 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2242 int object_id, int start_offset, int end_offset) {
2243 Send(new AccessibilityMsg_SetTextSelection(
2244 GetRoutingID(), object_id, start_offset, end_offset));
2247 void RenderWidgetHostImpl::FatalAccessibilityTreeError() {
2248 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2252 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2253 gfx::NativeViewAccessible accessible_parent) {
2255 view_->SetParentNativeViewAccessible(accessible_parent);
2258 gfx::NativeViewAccessible
2259 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2260 return delegate_->GetParentNativeViewAccessible();
2264 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
2265 const std::string& value) {
2266 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
2269 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2270 const gfx::Rect& rect) {
2271 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
2274 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
2275 Send(new InputMsg_MoveCaret(GetRoutingID(), point));
2278 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
2280 RejectMouseLockOrUnlockIfNecessary();
2283 if (!pending_mouse_lock_request_) {
2284 // This is possible, e.g., the plugin sends us an unlock request before
2285 // the user allows to lock to mouse.
2289 pending_mouse_lock_request_ = false;
2290 if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
2291 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2294 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2301 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2302 int32 route_id, int gpu_host_id,
2303 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
2304 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
2306 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
2312 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2314 uint32 output_surface_id,
2315 int renderer_host_id,
2316 const cc::CompositorFrameAck& ack) {
2317 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2320 host->Send(new ViewMsg_SwapCompositorFrameAck(
2321 route_id, output_surface_id, ack));
2325 void RenderWidgetHostImpl::SendReclaimCompositorResources(
2327 uint32 output_surface_id,
2328 int renderer_host_id,
2329 const cc::CompositorFrameAck& ack) {
2330 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2334 new ViewMsg_ReclaimCompositorResources(route_id, output_surface_id, ack));
2337 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2338 if (!is_threaded_compositing_enabled_)
2339 Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
2342 void RenderWidgetHostImpl::DelayedAutoResized() {
2343 gfx::Size new_size = new_auto_size_;
2344 // Clear the new_auto_size_ since the empty value is used as a flag to
2345 // indicate that no callback is in progress (i.e. without this line
2346 // DelayedAutoResized will not get called again).
2347 new_auto_size_.SetSize(0, 0);
2348 if (!should_auto_resize_)
2351 OnRenderAutoResized(new_size);
2354 void RenderWidgetHostImpl::DetachDelegate() {
2358 void RenderWidgetHostImpl::ComputeTouchLatency(
2359 const ui::LatencyInfo& latency_info) {
2360 ui::LatencyInfo::LatencyComponent ui_component;
2361 ui::LatencyInfo::LatencyComponent rwh_component;
2362 ui::LatencyInfo::LatencyComponent acked_component;
2364 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
2367 !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2368 GetLatencyComponentId(),
2372 DCHECK(ui_component.event_count == 1);
2373 DCHECK(rwh_component.event_count == 1);
2375 base::TimeDelta ui_delta =
2376 rwh_component.event_time - ui_component.event_time;
2377 UMA_HISTOGRAM_CUSTOM_COUNTS(
2378 "Event.Latency.Browser.TouchUI",
2379 ui_delta.InMicroseconds(),
2384 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT,
2386 &acked_component)) {
2387 DCHECK(acked_component.event_count == 1);
2388 base::TimeDelta acked_delta =
2389 acked_component.event_time - rwh_component.event_time;
2390 UMA_HISTOGRAM_CUSTOM_COUNTS(
2391 "Event.Latency.Browser.TouchAcked",
2392 acked_delta.InMicroseconds(),
2399 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
2400 ui::LatencyInfo::LatencyComponent window_snapshot_component;
2401 if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
2402 GetLatencyComponentId(),
2403 &window_snapshot_component)) {
2404 WindowSnapshotReachedScreen(
2405 static_cast<int>(window_snapshot_component.sequence_number));
2408 ui::LatencyInfo::LatencyComponent rwh_component;
2409 ui::LatencyInfo::LatencyComponent swap_component;
2410 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2411 GetLatencyComponentId(),
2413 !latency_info.FindLatency(
2414 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
2415 0, &swap_component)) {
2419 ui::LatencyInfo::LatencyComponent original_component;
2420 if (latency_info.FindLatency(
2421 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
2422 GetLatencyComponentId(),
2423 &original_component)) {
2424 // This UMA metric tracks the time from when the original touch event is
2425 // created (averaged if there are multiple) to when the scroll gesture
2426 // results in final frame swap.
2427 base::TimeDelta delta =
2428 swap_component.event_time - original_component.event_time;
2429 for (size_t i = 0; i < original_component.event_count; i++) {
2430 UMA_HISTOGRAM_CUSTOM_COUNTS(
2431 "Event.Latency.TouchToScrollUpdateSwap",
2432 delta.InMicroseconds(),
2440 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
2441 view_->DidReceiveRendererFrame();
2444 void RenderWidgetHostImpl::WindowSnapshotAsyncCallback(
2447 gfx::Size snapshot_size,
2448 scoped_refptr<base::RefCountedBytes> png_data) {
2450 std::vector<unsigned char> png_vector;
2451 Send(new ViewMsg_WindowSnapshotCompleted(
2452 routing_id, snapshot_id, gfx::Size(), png_vector));
2456 Send(new ViewMsg_WindowSnapshotCompleted(
2457 routing_id, snapshot_id, snapshot_size, png_data->data()));
2460 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
2461 DCHECK(base::MessageLoopForUI::IsCurrent());
2463 std::vector<unsigned char> png;
2465 // This feature is behind the kEnableGpuBenchmarking command line switch
2466 // because it poses security concerns and should only be used for testing.
2467 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2468 if (!command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking)) {
2469 Send(new ViewMsg_WindowSnapshotCompleted(
2470 GetRoutingID(), snapshot_id, gfx::Size(), png));
2474 gfx::Rect view_bounds = GetView()->GetViewBounds();
2475 gfx::Rect snapshot_bounds(view_bounds.size());
2476 gfx::Size snapshot_size = snapshot_bounds.size();
2478 if (ui::GrabViewSnapshot(
2479 GetView()->GetNativeView(), &png, snapshot_bounds)) {
2480 Send(new ViewMsg_WindowSnapshotCompleted(
2481 GetRoutingID(), snapshot_id, snapshot_size, png));
2485 ui::GrabViewSnapshotAsync(
2486 GetView()->GetNativeView(),
2488 base::ThreadTaskRunnerHandle::Get(),
2489 base::Bind(&RenderWidgetHostImpl::WindowSnapshotAsyncCallback,
2490 weak_factory_.GetWeakPtr(),
2497 void RenderWidgetHostImpl::CompositorFrameDrawn(
2498 const std::vector<ui::LatencyInfo>& latency_info) {
2499 for (size_t i = 0; i < latency_info.size(); i++) {
2500 std::set<RenderWidgetHostImpl*> rwhi_set;
2501 for (ui::LatencyInfo::LatencyMap::const_iterator b =
2502 latency_info[i].latency_components.begin();
2503 b != latency_info[i].latency_components.end();
2505 if (b->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
2506 b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
2507 // Matches with GetLatencyComponentId
2508 int routing_id = b->first.second & 0xffffffff;
2509 int process_id = (b->first.second >> 32) & 0xffffffff;
2510 RenderWidgetHost* rwh =
2511 RenderWidgetHost::FromID(process_id, routing_id);
2515 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
2516 if (rwhi_set.insert(rwhi).second)
2517 rwhi->FrameSwapped(latency_info[i]);
2523 void RenderWidgetHostImpl::AddLatencyInfoComponentIds(
2524 ui::LatencyInfo* latency_info) {
2525 ui::LatencyInfo::LatencyMap new_components;
2526 ui::LatencyInfo::LatencyMap::iterator lc =
2527 latency_info->latency_components.begin();
2528 while (lc != latency_info->latency_components.end()) {
2529 ui::LatencyComponentType component_type = lc->first.first;
2530 if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
2531 // Generate a new component entry with the correct component ID
2532 ui::LatencyInfo::LatencyMap::key_type key =
2533 std::make_pair(component_type, GetLatencyComponentId());
2534 new_components[key] = lc->second;
2536 // Remove the old entry
2537 latency_info->latency_components.erase(lc++);
2543 // Add newly generated components into the latency info
2544 for (lc = new_components.begin(); lc != new_components.end(); ++lc) {
2545 latency_info->latency_components[lc->first] = lc->second;
2549 SkBitmap::Config RenderWidgetHostImpl::PreferredReadbackFormat() {
2551 return view_->PreferredReadbackFormat();
2552 return SkBitmap::kARGB_8888_Config;
2555 } // namespace content