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.
4
5 #include "content/browser/renderer_host/render_widget_host_impl.h"
6
7 #include <math.h>
8 #include <set>
9 #include <utility>
10
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/input_router_impl.h"
34 #include "content/browser/renderer_host/input/synthetic_gesture.h"
35 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
36 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
37 #include "content/browser/renderer_host/input/timeout_monitor.h"
38 #include "content/browser/renderer_host/overscroll_controller.h"
39 #include "content/browser/renderer_host/render_process_host_impl.h"
40 #include "content/browser/renderer_host/render_view_host_impl.h"
41 #include "content/browser/renderer_host/render_widget_helper.h"
42 #include "content/browser/renderer_host/render_widget_host_delegate.h"
43 #include "content/common/accessibility_messages.h"
44 #include "content/common/content_constants_internal.h"
45 #include "content/common/gpu/gpu_messages.h"
46 #include "content/common/input_messages.h"
47 #include "content/common/view_messages.h"
48 #include "content/port/browser/render_widget_host_view_port.h"
49 #include "content/public/browser/native_web_keyboard_event.h"
50 #include "content/public/browser/notification_service.h"
51 #include "content/public/browser/notification_types.h"
52 #include "content/public/browser/render_widget_host_iterator.h"
53 #include "content/public/browser/user_metrics.h"
54 #include "content/public/common/content_constants.h"
55 #include "content/public/common/content_switches.h"
56 #include "content/public/common/result_codes.h"
57 #include "skia/ext/image_operations.h"
58 #include "skia/ext/platform_canvas.h"
59 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
60 #include "ui/events/event.h"
61 #include "ui/events/keycodes/keyboard_codes.h"
62 #include "ui/gfx/size_conversions.h"
63 #include "ui/gfx/skbitmap_operations.h"
64 #include "ui/gfx/vector2d_conversions.h"
65 #include "ui/snapshot/snapshot.h"
66 #include "webkit/common/cursors/webcursor.h"
67 #include "webkit/common/webpreferences.h"
68
69 #if defined(TOOLKIT_GTK)
70 #include "content/browser/renderer_host/backing_store_gtk.h"
71 #elif defined(OS_MACOSX)
72 #include "content/browser/renderer_host/backing_store_mac.h"
73 #elif defined(OS_WIN)
74 #include "content/common/plugin_constants_win.h"
75 #endif
76
77 using base::Time;
78 using base::TimeDelta;
79 using base::TimeTicks;
80 using blink::WebGestureEvent;
81 using blink::WebInputEvent;
82 using blink::WebKeyboardEvent;
83 using blink::WebMouseEvent;
84 using blink::WebMouseWheelEvent;
85 using blink::WebTextDirection;
86
87 namespace content {
88 namespace {
89
90 bool g_check_for_pending_resize_ack = true;
91
92 // How long to (synchronously) wait for the renderer to respond with a
93 // PaintRect message, when our backing-store is invalid, before giving up and
94 // returning a null or incorrectly sized backing-store from GetBackingStore.
95 // This timeout impacts the "choppiness" of our window resize perf.
96 const int kPaintMsgTimeoutMS = 50;
97
98 typedef std::pair<int32, int32> RenderWidgetHostID;
99 typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
100 RoutingIDWidgetMap;
101 base::LazyInstance<RoutingIDWidgetMap> g_routing_id_widget_map =
102 LAZY_INSTANCE_INITIALIZER;
103
104 // Implements the RenderWidgetHostIterator interface. It keeps a list of
105 // RenderWidgetHosts, and makes sure it returns a live RenderWidgetHost at each
106 // iteration (or NULL if there isn't any left).
107 class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
108 public:
RenderWidgetHostIteratorImpl()109 RenderWidgetHostIteratorImpl()
110 : current_index_(0) {
111 }
112
~RenderWidgetHostIteratorImpl()113 virtual ~RenderWidgetHostIteratorImpl() {
114 }
115
Add(RenderWidgetHost * host)116 void Add(RenderWidgetHost* host) {
117 hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
118 host->GetRoutingID()));
119 }
120
121 // RenderWidgetHostIterator:
GetNextHost()122 virtual RenderWidgetHost* GetNextHost() OVERRIDE {
123 RenderWidgetHost* host = NULL;
124 while (current_index_ < hosts_.size() && !host) {
125 RenderWidgetHostID id = hosts_[current_index_];
126 host = RenderWidgetHost::FromID(id.first, id.second);
127 ++current_index_;
128 }
129 return host;
130 }
131
132 private:
133 std::vector<RenderWidgetHostID> hosts_;
134 size_t current_index_;
135
136 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostIteratorImpl);
137 };
138
139 } // namespace
140
141
142 // static
RemoveAllBackingStores()143 void RenderWidgetHost::RemoveAllBackingStores() {
144 BackingStoreManager::RemoveAllBackingStores();
145 }
146
147 // static
BackingStoreMemorySize()148 size_t RenderWidgetHost::BackingStoreMemorySize() {
149 return BackingStoreManager::MemorySize();
150 }
151
152 ///////////////////////////////////////////////////////////////////////////////
153 // RenderWidgetHostImpl
154
RenderWidgetHostImpl(RenderWidgetHostDelegate * delegate,RenderProcessHost * process,int routing_id,bool hidden)155 RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
156 RenderProcessHost* process,
157 int routing_id,
158 bool hidden)
159 : view_(NULL),
160 renderer_initialized_(false),
161 hung_renderer_delay_ms_(kHungRendererDelayMs),
162 delegate_(delegate),
163 process_(process),
164 routing_id_(routing_id),
165 surface_id_(0),
166 is_loading_(false),
167 is_hidden_(hidden),
168 is_fullscreen_(false),
169 is_accelerated_compositing_active_(false),
170 repaint_ack_pending_(false),
171 resize_ack_pending_(false),
172 screen_info_out_of_date_(false),
173 overdraw_bottom_height_(0.f),
174 should_auto_resize_(false),
175 waiting_for_screen_rects_ack_(false),
176 accessibility_mode_(AccessibilityModeOff),
177 needs_repainting_on_restore_(false),
178 is_unresponsive_(false),
179 in_flight_event_count_(0),
180 in_get_backing_store_(false),
181 abort_get_backing_store_(false),
182 view_being_painted_(false),
183 ignore_input_events_(false),
184 input_method_active_(false),
185 text_direction_updated_(false),
186 text_direction_(blink::WebTextDirectionLeftToRight),
187 text_direction_canceled_(false),
188 suppress_next_char_events_(false),
189 pending_mouse_lock_request_(false),
190 allow_privileged_mouse_lock_(false),
191 has_touch_handler_(false),
192 weak_factory_(this),
193 last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32) {
194 CHECK(delegate_);
195 if (routing_id_ == MSG_ROUTING_NONE) {
196 routing_id_ = process_->GetNextRoutingID();
197 surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
198 process_->GetID(),
199 routing_id_);
200 } else {
201 // TODO(piman): This is a O(N) lookup, where we could forward the
202 // information from the RenderWidgetHelper. The problem is that doing so
203 // currently leaks outside of content all the way to chrome classes, and
204 // would be a layering violation. Since we don't expect more than a few
205 // hundreds of RWH, this seems acceptable. Revisit if performance become a
206 // problem, for example by tracking in the RenderWidgetHelper the routing id
207 // (and surface id) that have been created, but whose RWH haven't yet.
208 surface_id_ = GpuSurfaceTracker::Get()->LookupSurfaceForRenderer(
209 process_->GetID(),
210 routing_id_);
211 DCHECK(surface_id_);
212 }
213
214 is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled();
215
216 std::pair<RoutingIDWidgetMap::iterator, bool> result =
217 g_routing_id_widget_map.Get().insert(std::make_pair(
218 RenderWidgetHostID(process->GetID(), routing_id_), this));
219 CHECK(result.second) << "Inserting a duplicate item!";
220 process_->AddRoute(routing_id_, this);
221
222 // If we're initially visible, tell the process host that we're alive.
223 // Otherwise we'll notify the process host when we are first shown.
224 if (!hidden)
225 process_->WidgetRestored();
226
227 accessibility_mode_ =
228 BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
229
230 input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
231
232 #if defined(USE_AURA)
233 bool overscroll_enabled = CommandLine::ForCurrentProcess()->
234 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
235 SetOverscrollControllerEnabled(overscroll_enabled);
236 #endif
237
238 if (GetProcess()->IsGuest() || !CommandLine::ForCurrentProcess()->HasSwitch(
239 switches::kDisableHangMonitor)) {
240 hang_monitor_timeout_.reset(new TimeoutMonitor(
241 base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
242 weak_factory_.GetWeakPtr())));
243 }
244 }
245
~RenderWidgetHostImpl()246 RenderWidgetHostImpl::~RenderWidgetHostImpl() {
247 SetView(NULL);
248
249 // Clear our current or cached backing store if either remains.
250 BackingStoreManager::RemoveBackingStore(this);
251
252 GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
253 surface_id_ = 0;
254
255 process_->RemoveRoute(routing_id_);
256 g_routing_id_widget_map.Get().erase(
257 RenderWidgetHostID(process_->GetID(), routing_id_));
258
259 if (delegate_)
260 delegate_->RenderWidgetDeleted(this);
261 }
262
263 // static
FromID(int32 process_id,int32 routing_id)264 RenderWidgetHost* RenderWidgetHost::FromID(
265 int32 process_id,
266 int32 routing_id) {
267 return RenderWidgetHostImpl::FromID(process_id, routing_id);
268 }
269
270 // static
FromID(int32 process_id,int32 routing_id)271 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
272 int32 process_id,
273 int32 routing_id) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
276 RoutingIDWidgetMap::iterator it = widgets->find(
277 RenderWidgetHostID(process_id, routing_id));
278 return it == widgets->end() ? NULL : it->second;
279 }
280
281 // static
GetRenderWidgetHosts()282 scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
283 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
284 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
285 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
286 it != widgets->end();
287 ++it) {
288 RenderWidgetHost* widget = it->second;
289
290 if (!widget->IsRenderView()) {
291 hosts->Add(widget);
292 continue;
293 }
294
295 // Add only active RenderViewHosts.
296 RenderViewHost* rvh = RenderViewHost::From(widget);
297 if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out())
298 hosts->Add(widget);
299 }
300
301 return scoped_ptr<RenderWidgetHostIterator>(hosts);
302 }
303
304 // static
305 scoped_ptr<RenderWidgetHostIterator>
GetAllRenderWidgetHosts()306 RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
307 RenderWidgetHostIteratorImpl* hosts = new RenderWidgetHostIteratorImpl();
308 RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
309 for (RoutingIDWidgetMap::const_iterator it = widgets->begin();
310 it != widgets->end();
311 ++it) {
312 hosts->Add(it->second);
313 }
314
315 return scoped_ptr<RenderWidgetHostIterator>(hosts);
316 }
317
318 // static
From(RenderWidgetHost * rwh)319 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
320 return rwh->AsRenderWidgetHostImpl();
321 }
322
SetView(RenderWidgetHostView * view)323 void RenderWidgetHostImpl::SetView(RenderWidgetHostView* view) {
324 view_ = RenderWidgetHostViewPort::FromRWHV(view);
325
326 if (!view_) {
327 GpuSurfaceTracker::Get()->SetSurfaceHandle(
328 surface_id_, gfx::GLSurfaceHandle());
329 }
330
331 synthetic_gesture_controller_.reset();
332 }
333
GetProcess() const334 RenderProcessHost* RenderWidgetHostImpl::GetProcess() const {
335 return process_;
336 }
337
GetRoutingID() const338 int RenderWidgetHostImpl::GetRoutingID() const {
339 return routing_id_;
340 }
341
GetView() const342 RenderWidgetHostView* RenderWidgetHostImpl::GetView() const {
343 return view_;
344 }
345
AsRenderWidgetHostImpl()346 RenderWidgetHostImpl* RenderWidgetHostImpl::AsRenderWidgetHostImpl() {
347 return this;
348 }
349
GetNativeViewId() const350 gfx::NativeViewId RenderWidgetHostImpl::GetNativeViewId() const {
351 if (view_)
352 return view_->GetNativeViewId();
353 return 0;
354 }
355
GetCompositingSurface()356 gfx::GLSurfaceHandle RenderWidgetHostImpl::GetCompositingSurface() {
357 if (view_)
358 return view_->GetCompositingSurface();
359 return gfx::GLSurfaceHandle();
360 }
361
CompositingSurfaceUpdated()362 void RenderWidgetHostImpl::CompositingSurfaceUpdated() {
363 GpuSurfaceTracker::Get()->SetSurfaceHandle(
364 surface_id_, GetCompositingSurface());
365 process_->SurfaceUpdated(surface_id_);
366 }
367
ResetSizeAndRepaintPendingFlags()368 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
369 resize_ack_pending_ = false;
370 if (repaint_ack_pending_) {
371 TRACE_EVENT_ASYNC_END0(
372 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
373 }
374 repaint_ack_pending_ = false;
375 last_requested_size_.SetSize(0, 0);
376 }
377
SendScreenRects()378 void RenderWidgetHostImpl::SendScreenRects() {
379 if (!renderer_initialized_ || waiting_for_screen_rects_ack_)
380 return;
381
382 if (is_hidden_) {
383 // On GTK, this comes in for backgrounded tabs. Ignore, to match what
384 // happens on Win & Mac, and when the view is shown it'll call this again.
385 return;
386 }
387
388 if (!view_)
389 return;
390
391 last_view_screen_rect_ = view_->GetViewBounds();
392 last_window_screen_rect_ = view_->GetBoundsInRootWindow();
393 Send(new ViewMsg_UpdateScreenRects(
394 GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
395 if (delegate_)
396 delegate_->DidSendScreenRects(this);
397 waiting_for_screen_rects_ack_ = true;
398 }
399
SetOverscrollControllerEnabled(bool enabled)400 void RenderWidgetHostImpl::SetOverscrollControllerEnabled(bool enabled) {
401 if (!enabled)
402 overscroll_controller_.reset();
403 else if (!overscroll_controller_)
404 overscroll_controller_.reset(new OverscrollController());
405 }
406
SuppressNextCharEvents()407 void RenderWidgetHostImpl::SuppressNextCharEvents() {
408 suppress_next_char_events_ = true;
409 }
410
FlushInput()411 void RenderWidgetHostImpl::FlushInput() {
412 input_router_->Flush();
413 if (synthetic_gesture_controller_)
414 synthetic_gesture_controller_->Flush(base::TimeTicks::Now());
415 }
416
SetNeedsFlush()417 void RenderWidgetHostImpl::SetNeedsFlush() {
418 if (view_)
419 view_->OnSetNeedsFlushInput();
420 }
421
Init()422 void RenderWidgetHostImpl::Init() {
423 DCHECK(process_->HasConnection());
424
425 renderer_initialized_ = true;
426
427 GpuSurfaceTracker::Get()->SetSurfaceHandle(
428 surface_id_, GetCompositingSurface());
429
430 // Send the ack along with the information on placement.
431 Send(new ViewMsg_CreatingNew_ACK(routing_id_));
432 GetProcess()->ResumeRequestsForView(routing_id_);
433
434 WasResized();
435 }
436
Shutdown()437 void RenderWidgetHostImpl::Shutdown() {
438 RejectMouseLockOrUnlockIfNecessary();
439
440 if (process_->HasConnection()) {
441 // Tell the renderer object to close.
442 bool rv = Send(new ViewMsg_Close(routing_id_));
443 DCHECK(rv);
444 }
445
446 Destroy();
447 }
448
IsLoading() const449 bool RenderWidgetHostImpl::IsLoading() const {
450 return is_loading_;
451 }
452
IsRenderView() const453 bool RenderWidgetHostImpl::IsRenderView() const {
454 return false;
455 }
456
OnMessageReceived(const IPC::Message & msg)457 bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
458 bool handled = true;
459 bool msg_is_ok = true;
460 IPC_BEGIN_MESSAGE_MAP_EX(RenderWidgetHostImpl, msg, msg_is_ok)
461 IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
462 OnQueueSyntheticGesture)
463 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
464 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
465 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
466 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
467 OnUpdateScreenRectsAck)
468 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
469 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
470 IPC_MESSAGE_HANDLER(ViewHostMsg_PaintAtSize_ACK, OnPaintAtSizeAck)
471 #if defined(OS_MACOSX)
472 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
473 OnCompositorSurfaceBuffersSwapped)
474 #endif
475 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
476 msg_is_ok = OnSwapCompositorFrame(msg))
477 IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
478 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
479 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateIsDelayed, OnUpdateIsDelayed)
480 IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
481 IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
482 IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
483 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
484 OnTextInputTypeChanged)
485 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
486 OnImeCancelComposition)
487 IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing,
488 OnDidActivateAcceleratedCompositing)
489 IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
490 IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
491 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
492 OnShowDisambiguationPopup)
493 #if defined(OS_WIN)
494 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
495 OnWindowlessPluginDummyWindowCreated)
496 IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
497 OnWindowlessPluginDummyWindowDestroyed)
498 #endif
499 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
500 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
501 IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
502 OnImeCompositionRangeChanged)
503 #endif
504 IPC_MESSAGE_UNHANDLED(handled = false)
505 IPC_END_MESSAGE_MAP_EX()
506
507 if (!handled && input_router_ && input_router_->OnMessageReceived(msg))
508 return true;
509
510 if (!handled && view_ && view_->OnMessageReceived(msg))
511 return true;
512
513 if (!msg_is_ok) {
514 // The message de-serialization failed. Kill the renderer process.
515 RecordAction(UserMetricsAction("BadMessageTerminate_RWH"));
516 GetProcess()->ReceivedBadMessage();
517 }
518 return handled;
519 }
520
Send(IPC::Message * msg)521 bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
522 if (IPC_MESSAGE_ID_CLASS(msg->type()) == InputMsgStart)
523 return input_router_->SendInput(make_scoped_ptr(msg));
524
525 return process_->Send(msg);
526 }
527
WasHidden()528 void RenderWidgetHostImpl::WasHidden() {
529 if (is_hidden_)
530 return;
531
532 is_hidden_ = true;
533
534 // Don't bother reporting hung state when we aren't active.
535 StopHangMonitorTimeout();
536
537 // If we have a renderer, then inform it that we are being hidden so it can
538 // reduce its resource utilization.
539 Send(new ViewMsg_WasHidden(routing_id_));
540
541 // Tell the RenderProcessHost we were hidden.
542 process_->WidgetHidden();
543
544 bool is_visible = false;
545 NotificationService::current()->Notify(
546 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
547 Source<RenderWidgetHost>(this),
548 Details<bool>(&is_visible));
549 }
550
WasShown()551 void RenderWidgetHostImpl::WasShown() {
552 if (!is_hidden_)
553 return;
554 is_hidden_ = false;
555
556 SendScreenRects();
557
558 BackingStore* backing_store = BackingStoreManager::Lookup(this);
559 // If we already have a backing store for this widget, then we don't need to
560 // repaint on restore _unless_ we know that our backing store is invalid.
561 // When accelerated compositing is on, we must always repaint, even when
562 // the backing store exists.
563 bool needs_repainting;
564 if (needs_repainting_on_restore_ || !backing_store ||
565 is_accelerated_compositing_active()) {
566 needs_repainting = true;
567 needs_repainting_on_restore_ = false;
568 } else {
569 needs_repainting = false;
570 }
571 Send(new ViewMsg_WasShown(routing_id_, needs_repainting));
572
573 process_->WidgetRestored();
574
575 bool is_visible = true;
576 NotificationService::current()->Notify(
577 NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
578 Source<RenderWidgetHost>(this),
579 Details<bool>(&is_visible));
580
581 // It's possible for our size to be out of sync with the renderer. The
582 // following is one case that leads to this:
583 // 1. WasResized -> Send ViewMsg_Resize to render
584 // 2. WasResized -> do nothing as resize_ack_pending_ is true
585 // 3. WasHidden
586 // 4. OnUpdateRect from (1) processed. Does NOT invoke WasResized as view
587 // is hidden. Now renderer/browser out of sync with what they think size
588 // is.
589 // By invoking WasResized the renderer is updated as necessary. WasResized
590 // does nothing if the sizes are already in sync.
591 //
592 // TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
593 // could handle both the restore and resize at once. This isn't that big a
594 // deal as RenderWidget::WasShown delays updating, so that the resize from
595 // WasResized is usually processed before the renderer is painted.
596 WasResized();
597 }
598
WasResized()599 void RenderWidgetHostImpl::WasResized() {
600 // Skip if the |delegate_| has already been detached because
601 // it's web contents is being deleted.
602 if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
603 !renderer_initialized_ || should_auto_resize_ || !delegate_) {
604 return;
605 }
606
607 gfx::Rect view_bounds = view_->GetViewBounds();
608 gfx::Size new_size(view_bounds.size());
609
610 gfx::Size old_physical_backing_size = physical_backing_size_;
611 physical_backing_size_ = view_->GetPhysicalBackingSize();
612 bool was_fullscreen = is_fullscreen_;
613 is_fullscreen_ = IsFullscreen();
614 float old_overdraw_bottom_height = overdraw_bottom_height_;
615 overdraw_bottom_height_ = view_->GetOverdrawBottomHeight();
616
617 bool size_changed = new_size != last_requested_size_;
618 bool side_payload_changed =
619 screen_info_out_of_date_ ||
620 old_physical_backing_size != physical_backing_size_ ||
621 was_fullscreen != is_fullscreen_ ||
622 old_overdraw_bottom_height != overdraw_bottom_height_;
623
624 if (!size_changed && !side_payload_changed)
625 return;
626
627 if (!screen_info_) {
628 screen_info_.reset(new blink::WebScreenInfo);
629 GetWebScreenInfo(screen_info_.get());
630 }
631
632 // We don't expect to receive an ACK when the requested size or the physical
633 // backing size is empty, or when the main viewport size didn't change.
634 if (!new_size.IsEmpty() && !physical_backing_size_.IsEmpty() && size_changed)
635 resize_ack_pending_ = g_check_for_pending_resize_ack;
636
637 ViewMsg_Resize_Params params;
638 params.screen_info = *screen_info_;
639 params.new_size = new_size;
640 params.physical_backing_size = physical_backing_size_;
641 params.overdraw_bottom_height = overdraw_bottom_height_;
642 params.resizer_rect = GetRootWindowResizerRect();
643 params.is_fullscreen = is_fullscreen_;
644 if (!Send(new ViewMsg_Resize(routing_id_, params))) {
645 resize_ack_pending_ = false;
646 } else {
647 last_requested_size_ = new_size;
648 }
649 }
650
ResizeRectChanged(const gfx::Rect & new_rect)651 void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
652 Send(new ViewMsg_ChangeResizeRect(routing_id_, new_rect));
653 }
654
GotFocus()655 void RenderWidgetHostImpl::GotFocus() {
656 Focus();
657 }
658
Focus()659 void RenderWidgetHostImpl::Focus() {
660 Send(new InputMsg_SetFocus(routing_id_, true));
661 }
662
Blur()663 void RenderWidgetHostImpl::Blur() {
664 // If there is a pending mouse lock request, we don't want to reject it at
665 // this point. The user can switch focus back to this view and approve the
666 // request later.
667 if (IsMouseLocked())
668 view_->UnlockMouse();
669
670 // If there is a pending overscroll, then that should be cancelled.
671 if (overscroll_controller_)
672 overscroll_controller_->Cancel();
673
674 Send(new InputMsg_SetFocus(routing_id_, false));
675 }
676
LostCapture()677 void RenderWidgetHostImpl::LostCapture() {
678 Send(new InputMsg_MouseCaptureLost(routing_id_));
679 }
680
SetActive(bool active)681 void RenderWidgetHostImpl::SetActive(bool active) {
682 Send(new ViewMsg_SetActive(routing_id_, active));
683 }
684
LostMouseLock()685 void RenderWidgetHostImpl::LostMouseLock() {
686 Send(new ViewMsg_MouseLockLost(routing_id_));
687 }
688
ViewDestroyed()689 void RenderWidgetHostImpl::ViewDestroyed() {
690 RejectMouseLockOrUnlockIfNecessary();
691
692 // TODO(evanm): tracking this may no longer be necessary;
693 // eliminate this function if so.
694 SetView(NULL);
695 }
696
SetIsLoading(bool is_loading)697 void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
698 is_loading_ = is_loading;
699 if (!view_)
700 return;
701 view_->SetIsLoading(is_loading);
702 }
703
CopyFromBackingStore(const gfx::Rect & src_subrect,const gfx::Size & accelerated_dst_size,const base::Callback<void (bool,const SkBitmap &)> & callback)704 void RenderWidgetHostImpl::CopyFromBackingStore(
705 const gfx::Rect& src_subrect,
706 const gfx::Size& accelerated_dst_size,
707 const base::Callback<void(bool, const SkBitmap&)>& callback) {
708 if (view_ && is_accelerated_compositing_active_) {
709 TRACE_EVENT0("browser",
710 "RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
711 gfx::Rect accelerated_copy_rect = src_subrect.IsEmpty() ?
712 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
713 view_->CopyFromCompositingSurface(accelerated_copy_rect,
714 accelerated_dst_size,
715 callback);
716 return;
717 }
718
719 BackingStore* backing_store = GetBackingStore(false);
720 if (!backing_store) {
721 callback.Run(false, SkBitmap());
722 return;
723 }
724
725 TRACE_EVENT0("browser",
726 "RenderWidgetHostImpl::CopyFromBackingStore::FromBackingStore");
727 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
728 gfx::Rect(backing_store->size()) : src_subrect;
729 // When the result size is equal to the backing store size, copy from the
730 // backing store directly to the output canvas.
731 skia::PlatformBitmap output;
732 bool result = backing_store->CopyFromBackingStore(copy_rect, &output);
733 callback.Run(result, output.GetBitmap());
734 }
735
736 #if defined(TOOLKIT_GTK)
CopyFromBackingStoreToGtkWindow(const gfx::Rect & dest_rect,GdkWindow * target)737 bool RenderWidgetHostImpl::CopyFromBackingStoreToGtkWindow(
738 const gfx::Rect& dest_rect, GdkWindow* target) {
739 BackingStore* backing_store = GetBackingStore(false);
740 if (!backing_store)
741 return false;
742 (static_cast<BackingStoreGtk*>(backing_store))->PaintToRect(
743 dest_rect, target);
744 return true;
745 }
746 #elif defined(OS_MACOSX)
GetBackingStoreSize()747 gfx::Size RenderWidgetHostImpl::GetBackingStoreSize() {
748 BackingStore* backing_store = GetBackingStore(false);
749 return backing_store ? backing_store->size() : gfx::Size();
750 }
751
CopyFromBackingStoreToCGContext(const CGRect & dest_rect,CGContextRef target)752 bool RenderWidgetHostImpl::CopyFromBackingStoreToCGContext(
753 const CGRect& dest_rect, CGContextRef target) {
754 BackingStore* backing_store = GetBackingStore(false);
755 if (!backing_store)
756 return false;
757 (static_cast<BackingStoreMac*>(backing_store))->
758 CopyFromBackingStoreToCGContext(dest_rect, target);
759 return true;
760 }
761 #endif
762
PaintAtSize(TransportDIB::Handle dib_handle,int tag,const gfx::Size & page_size,const gfx::Size & desired_size)763 void RenderWidgetHostImpl::PaintAtSize(TransportDIB::Handle dib_handle,
764 int tag,
765 const gfx::Size& page_size,
766 const gfx::Size& desired_size) {
767 // Ask the renderer to create a bitmap regardless of whether it's
768 // hidden, being resized, redrawn, etc. It resizes the web widget
769 // to the page_size and then scales it to the desired_size.
770 Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, tag,
771 page_size, desired_size));
772 }
773
TryGetBackingStore(const gfx::Size & desired_size,BackingStore ** backing_store)774 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
775 BackingStore** backing_store) {
776 // Check if the view has an accelerated surface of the desired size.
777 if (view_->HasAcceleratedSurface(desired_size)) {
778 *backing_store = NULL;
779 return true;
780 }
781
782 // Check for a software backing store of the desired size.
783 *backing_store = BackingStoreManager::GetBackingStore(this, desired_size);
784 return !!*backing_store;
785 }
786
GetBackingStore(bool force_create)787 BackingStore* RenderWidgetHostImpl::GetBackingStore(bool force_create) {
788 if (!view_)
789 return NULL;
790
791 // The view_size will be current_size_ for auto-sized views and otherwise the
792 // size of the view_. (For auto-sized views, current_size_ is updated during
793 // UpdateRect messages.)
794 gfx::Size view_size = current_size_;
795 if (!should_auto_resize_) {
796 // Get the desired size from the current view bounds.
797 gfx::Rect view_rect = view_->GetViewBounds();
798 if (view_rect.IsEmpty())
799 return NULL;
800 view_size = view_rect.size();
801 }
802
803 TRACE_EVENT2("renderer_host", "RenderWidgetHostImpl::GetBackingStore",
804 "width", base::IntToString(view_size.width()),
805 "height", base::IntToString(view_size.height()));
806
807 // We should not be asked to paint while we are hidden. If we are hidden,
808 // then it means that our consumer failed to call WasShown. If we're not
809 // force creating the backing store, it's OK since we can feel free to give
810 // out our cached one if we have it.
811 DCHECK(!is_hidden_ || !force_create) <<
812 "GetBackingStore called while hidden!";
813
814 // We should never be called recursively; this can theoretically lead to
815 // infinite recursion and almost certainly leads to lower performance.
816 DCHECK(!in_get_backing_store_) << "GetBackingStore called recursively!";
817 base::AutoReset<bool> auto_reset_in_get_backing_store(
818 &in_get_backing_store_, true);
819
820 // We might have a cached backing store that we can reuse!
821 BackingStore* backing_store = NULL;
822 if (TryGetBackingStore(view_size, &backing_store) || !force_create)
823 return backing_store;
824
825 // We do not have a suitable backing store in the cache, so send out a
826 // request to the renderer to paint the view if required.
827 if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
828 repaint_start_time_ = TimeTicks::Now();
829 repaint_ack_pending_ = true;
830 TRACE_EVENT_ASYNC_BEGIN0(
831 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
832 Send(new ViewMsg_Repaint(routing_id_, view_size));
833 }
834
835 TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
836 TimeTicks end_time = TimeTicks::Now() + max_delay;
837 do {
838 TRACE_EVENT0("renderer_host", "GetBackingStore::WaitForUpdate");
839
840 #if defined(OS_MACOSX)
841 view_->AboutToWaitForBackingStoreMsg();
842 #endif
843
844 // When we have asked the RenderWidget to resize, and we are still waiting
845 // on a response, block for a little while to see if we can't get a response
846 // before returning the old (incorrectly sized) backing store.
847 IPC::Message msg;
848 if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
849 OnMessageReceived(msg);
850
851 // For auto-resized views, current_size_ determines the view_size and it
852 // may have changed during the handling of an UpdateRect message.
853 if (should_auto_resize_)
854 view_size = current_size_;
855
856 // Break now if we got a backing store or accelerated surface of the
857 // correct size.
858 if (TryGetBackingStore(view_size, &backing_store) ||
859 abort_get_backing_store_) {
860 abort_get_backing_store_ = false;
861 return backing_store;
862 }
863 } else {
864 TRACE_EVENT0("renderer_host", "GetBackingStore::Timeout");
865 break;
866 }
867
868 // Loop if we still have time left and haven't gotten a properly sized
869 // BackingStore yet. This is necessary to support the GPU path which
870 // typically has multiple frames pipelined -- we may need to skip one or two
871 // BackingStore messages to get to the latest.
872 max_delay = end_time - TimeTicks::Now();
873 } while (max_delay > TimeDelta::FromSeconds(0));
874
875 // We have failed to get a backing store of view_size. Fall back on
876 // current_size_ to avoid a white flash while resizing slow pages.
877 if (view_size != current_size_)
878 TryGetBackingStore(current_size_, &backing_store);
879 return backing_store;
880 }
881
AllocBackingStore(const gfx::Size & size)882 BackingStore* RenderWidgetHostImpl::AllocBackingStore(const gfx::Size& size) {
883 if (!view_)
884 return NULL;
885 return view_->AllocBackingStore(size);
886 }
887
DonePaintingToBackingStore()888 void RenderWidgetHostImpl::DonePaintingToBackingStore() {
889 Send(new ViewMsg_UpdateRect_ACK(GetRoutingID()));
890 }
891
ScheduleComposite()892 bool RenderWidgetHostImpl::ScheduleComposite() {
893 if (is_hidden_ || !is_accelerated_compositing_active_ ||
894 current_size_.IsEmpty() || repaint_ack_pending_ ||
895 resize_ack_pending_ || view_being_painted_) {
896 return false;
897 }
898
899 // Send out a request to the renderer to paint the view if required.
900 repaint_start_time_ = TimeTicks::Now();
901 repaint_ack_pending_ = true;
902 TRACE_EVENT_ASYNC_BEGIN0(
903 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
904 Send(new ViewMsg_Repaint(routing_id_, current_size_));
905 return true;
906 }
907
StartHangMonitorTimeout(base::TimeDelta delay)908 void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay) {
909 if (hang_monitor_timeout_)
910 hang_monitor_timeout_->Start(delay);
911 }
912
RestartHangMonitorTimeout()913 void RenderWidgetHostImpl::RestartHangMonitorTimeout() {
914 if (hang_monitor_timeout_)
915 hang_monitor_timeout_->Restart(
916 base::TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
917 }
918
StopHangMonitorTimeout()919 void RenderWidgetHostImpl::StopHangMonitorTimeout() {
920 if (hang_monitor_timeout_)
921 hang_monitor_timeout_->Stop();
922 RendererIsResponsive();
923 }
924
EnableFullAccessibilityMode()925 void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
926 SetAccessibilityMode(AccessibilityModeComplete);
927 }
928
ForwardMouseEvent(const WebMouseEvent & mouse_event)929 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
930 ForwardMouseEventWithLatencyInfo(MouseEventWithLatencyInfo(
931 mouse_event, CreateRWHLatencyInfoIfNotExist(NULL, mouse_event.type)));
932 }
933
ForwardMouseEventWithLatencyInfo(const MouseEventWithLatencyInfo & mouse_event)934 void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
935 const MouseEventWithLatencyInfo& mouse_event) {
936 TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
937 "x", mouse_event.event.x, "y", mouse_event.event.y);
938
939 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
940 if (mouse_event_callbacks_[i].Run(mouse_event.event))
941 return;
942 }
943
944 if (IgnoreInputEvents())
945 return;
946
947 input_router_->SendMouseEvent(mouse_event);
948 }
949
OnPointerEventActivate()950 void RenderWidgetHostImpl::OnPointerEventActivate() {
951 }
952
ForwardWheelEvent(const WebMouseWheelEvent & wheel_event)953 void RenderWidgetHostImpl::ForwardWheelEvent(
954 const WebMouseWheelEvent& wheel_event) {
955 ForwardWheelEventWithLatencyInfo(MouseWheelEventWithLatencyInfo(
956 wheel_event, CreateRWHLatencyInfoIfNotExist(NULL, wheel_event.type)));
957 }
958
ForwardWheelEventWithLatencyInfo(const MouseWheelEventWithLatencyInfo & wheel_event)959 void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
960 const MouseWheelEventWithLatencyInfo& wheel_event) {
961 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
962 if (IgnoreInputEvents())
963 return;
964
965 if (delegate_->PreHandleWheelEvent(wheel_event.event))
966 return;
967
968 input_router_->SendWheelEvent(wheel_event);
969 }
970
ForwardGestureEvent(const blink::WebGestureEvent & gesture_event)971 void RenderWidgetHostImpl::ForwardGestureEvent(
972 const blink::WebGestureEvent& gesture_event) {
973 ForwardGestureEventWithLatencyInfo(gesture_event, ui::LatencyInfo());
974 }
975
ForwardGestureEventWithLatencyInfo(const blink::WebGestureEvent & gesture_event,const ui::LatencyInfo & ui_latency)976 void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
977 const blink::WebGestureEvent& gesture_event,
978 const ui::LatencyInfo& ui_latency) {
979 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardGestureEvent");
980 // Early out if necessary, prior to performing latency logic.
981 if (IgnoreInputEvents())
982 return;
983
984 ui::LatencyInfo latency_info =
985 CreateRWHLatencyInfoIfNotExist(&ui_latency, gesture_event.type);
986
987 if (gesture_event.type == blink::WebInputEvent::GestureScrollUpdate) {
988 latency_info.AddLatencyNumber(
989 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT,
990 GetLatencyComponentId(),
991 ++last_input_number_);
992
993 // Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
994 // different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
995 // So we can track the latency specifically for scroll update events.
996 ui::LatencyInfo::LatencyComponent original_component;
997 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
998 0,
999 &original_component)) {
1000 latency_info.AddLatencyNumberWithTimestamp(
1001 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
1002 GetLatencyComponentId(),
1003 original_component.sequence_number,
1004 original_component.event_time,
1005 original_component.event_count,
1006 true);
1007 }
1008 }
1009
1010 GestureEventWithLatencyInfo gesture_with_latency(gesture_event, latency_info);
1011 input_router_->SendGestureEvent(gesture_with_latency);
1012 }
1013
ForwardTouchEventWithLatencyInfo(const blink::WebTouchEvent & touch_event,const ui::LatencyInfo & ui_latency)1014 void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
1015 const blink::WebTouchEvent& touch_event,
1016 const ui::LatencyInfo& ui_latency) {
1017 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardTouchEvent");
1018
1019 // Always forward TouchEvents for touch stream consistency. They will be
1020 // ignored if appropriate in FilterInputEvent().
1021
1022 ui::LatencyInfo latency_info =
1023 CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type);
1024 TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
1025 input_router_->SendTouchEvent(touch_with_latency);
1026 }
1027
ForwardKeyboardEvent(const NativeWebKeyboardEvent & key_event)1028 void RenderWidgetHostImpl::ForwardKeyboardEvent(
1029 const NativeWebKeyboardEvent& key_event) {
1030 TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardKeyboardEvent");
1031 if (IgnoreInputEvents())
1032 return;
1033
1034 if (!process_->HasConnection())
1035 return;
1036
1037 // First, let keypress listeners take a shot at handling the event. If a
1038 // listener handles the event, it should not be propagated to the renderer.
1039 if (KeyPressListenersHandleEvent(key_event)) {
1040 // Some keypresses that are accepted by the listener might have follow up
1041 // char events, which should be ignored.
1042 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1043 suppress_next_char_events_ = true;
1044 return;
1045 }
1046
1047 if (key_event.type == WebKeyboardEvent::Char &&
1048 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
1049 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
1050 OnUserGesture();
1051 }
1052
1053 // Double check the type to make sure caller hasn't sent us nonsense that
1054 // will mess up our key queue.
1055 if (!WebInputEvent::isKeyboardEventType(key_event.type))
1056 return;
1057
1058 if (suppress_next_char_events_) {
1059 // If preceding RawKeyDown event was handled by the browser, then we need
1060 // suppress all Char events generated by it. Please note that, one
1061 // RawKeyDown event may generate multiple Char events, so we can't reset
1062 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown.
1063 if (key_event.type == WebKeyboardEvent::Char)
1064 return;
1065 // We get a KeyUp or a RawKeyDown event.
1066 suppress_next_char_events_ = false;
1067 }
1068
1069 bool is_shortcut = false;
1070
1071 // Only pre-handle the key event if it's not handled by the input method.
1072 if (delegate_ && !key_event.skip_in_browser) {
1073 // We need to set |suppress_next_char_events_| to true if
1074 // PreHandleKeyboardEvent() returns true, but |this| may already be
1075 // destroyed at that time. So set |suppress_next_char_events_| true here,
1076 // then revert it afterwards when necessary.
1077 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1078 suppress_next_char_events_ = true;
1079
1080 // Tab switching/closing accelerators aren't sent to the renderer to avoid
1081 // a hung/malicious renderer from interfering.
1082 if (delegate_->PreHandleKeyboardEvent(key_event, &is_shortcut))
1083 return;
1084
1085 if (key_event.type == WebKeyboardEvent::RawKeyDown)
1086 suppress_next_char_events_ = false;
1087 }
1088
1089 input_router_->SendKeyboardEvent(
1090 key_event,
1091 CreateRWHLatencyInfoIfNotExist(NULL, key_event.type),
1092 is_shortcut);
1093 }
1094
SendCursorVisibilityState(bool is_visible)1095 void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
1096 Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
1097 }
1098
GetLatencyComponentId()1099 int64 RenderWidgetHostImpl::GetLatencyComponentId() {
1100 return GetRoutingID() | (static_cast<int64>(GetProcess()->GetID()) << 32);
1101 }
1102
1103 // static
DisableResizeAckCheckForTesting()1104 void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
1105 g_check_for_pending_resize_ack = false;
1106 }
1107
CreateRWHLatencyInfoIfNotExist(const ui::LatencyInfo * original,WebInputEvent::Type type)1108 ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
1109 const ui::LatencyInfo* original, WebInputEvent::Type type) {
1110 ui::LatencyInfo info;
1111 if (original)
1112 info = *original;
1113 // In Aura, gesture event will already carry its original touch event's
1114 // INPUT_EVENT_LATENCY_RWH_COMPONENT.
1115 if (!info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1116 GetLatencyComponentId(),
1117 NULL)) {
1118 info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1119 GetLatencyComponentId(),
1120 ++last_input_number_);
1121 info.TraceEventType(WebInputEventTraits::GetName(type));
1122 }
1123 return info;
1124 }
1125
1126
AddKeyPressEventCallback(const KeyPressEventCallback & callback)1127 void RenderWidgetHostImpl::AddKeyPressEventCallback(
1128 const KeyPressEventCallback& callback) {
1129 key_press_event_callbacks_.push_back(callback);
1130 }
1131
RemoveKeyPressEventCallback(const KeyPressEventCallback & callback)1132 void RenderWidgetHostImpl::RemoveKeyPressEventCallback(
1133 const KeyPressEventCallback& callback) {
1134 for (size_t i = 0; i < key_press_event_callbacks_.size(); ++i) {
1135 if (key_press_event_callbacks_[i].Equals(callback)) {
1136 key_press_event_callbacks_.erase(
1137 key_press_event_callbacks_.begin() + i);
1138 return;
1139 }
1140 }
1141 }
1142
AddMouseEventCallback(const MouseEventCallback & callback)1143 void RenderWidgetHostImpl::AddMouseEventCallback(
1144 const MouseEventCallback& callback) {
1145 mouse_event_callbacks_.push_back(callback);
1146 }
1147
RemoveMouseEventCallback(const MouseEventCallback & callback)1148 void RenderWidgetHostImpl::RemoveMouseEventCallback(
1149 const MouseEventCallback& callback) {
1150 for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
1151 if (mouse_event_callbacks_[i].Equals(callback)) {
1152 mouse_event_callbacks_.erase(mouse_event_callbacks_.begin() + i);
1153 return;
1154 }
1155 }
1156 }
1157
GetWebScreenInfo(blink::WebScreenInfo * result)1158 void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
1159 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetWebScreenInfo");
1160 if (GetView())
1161 static_cast<RenderWidgetHostViewPort*>(GetView())->GetScreenInfo(result);
1162 else
1163 RenderWidgetHostViewPort::GetDefaultScreenInfo(result);
1164 screen_info_out_of_date_ = false;
1165 }
1166
1167 const NativeWebKeyboardEvent*
GetLastKeyboardEvent() const1168 RenderWidgetHostImpl::GetLastKeyboardEvent() const {
1169 return input_router_->GetLastKeyboardEvent();
1170 }
1171
NotifyScreenInfoChanged()1172 void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
1173 // The resize message (which may not happen immediately) will carry with it
1174 // the screen info as well as the new size (if the screen has changed scale
1175 // factor).
1176 InvalidateScreenInfo();
1177 WasResized();
1178 }
1179
InvalidateScreenInfo()1180 void RenderWidgetHostImpl::InvalidateScreenInfo() {
1181 screen_info_out_of_date_ = true;
1182 screen_info_.reset();
1183 }
1184
GetSnapshotFromRenderer(const gfx::Rect & src_subrect,const base::Callback<void (bool,const SkBitmap &)> & callback)1185 void RenderWidgetHostImpl::GetSnapshotFromRenderer(
1186 const gfx::Rect& src_subrect,
1187 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1188 TRACE_EVENT0("browser", "RenderWidgetHostImpl::GetSnapshotFromRenderer");
1189 if (!view_) {
1190 callback.Run(false, SkBitmap());
1191 return;
1192 }
1193
1194 pending_snapshots_.push(callback);
1195
1196 gfx::Rect copy_rect = src_subrect.IsEmpty() ?
1197 gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
1198
1199 gfx::Rect copy_rect_in_pixel = ConvertViewRectToPixel(view_, copy_rect);
1200 Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel));
1201 }
1202
OnSnapshot(bool success,const SkBitmap & bitmap)1203 void RenderWidgetHostImpl::OnSnapshot(bool success,
1204 const SkBitmap& bitmap) {
1205 if (pending_snapshots_.size() == 0) {
1206 LOG(ERROR) << "RenderWidgetHostImpl::OnSnapshot: "
1207 "Received a snapshot that was not requested.";
1208 return;
1209 }
1210
1211 base::Callback<void(bool, const SkBitmap&)> callback =
1212 pending_snapshots_.front();
1213 pending_snapshots_.pop();
1214
1215 if (!success) {
1216 callback.Run(success, SkBitmap());
1217 return;
1218 }
1219
1220 callback.Run(success, bitmap);
1221 }
1222
UpdateVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)1223 void RenderWidgetHostImpl::UpdateVSyncParameters(base::TimeTicks timebase,
1224 base::TimeDelta interval) {
1225 Send(new ViewMsg_UpdateVSyncParameters(GetRoutingID(), timebase, interval));
1226 }
1227
RendererExited(base::TerminationStatus status,int exit_code)1228 void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
1229 int exit_code) {
1230 // Clearing this flag causes us to re-create the renderer when recovering
1231 // from a crashed renderer.
1232 renderer_initialized_ = false;
1233
1234 waiting_for_screen_rects_ack_ = false;
1235
1236 // Reset to ensure that input routing works with a new renderer.
1237 input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_));
1238
1239 if (overscroll_controller_)
1240 overscroll_controller_->Reset();
1241
1242 // Must reset these to ensure that keyboard events work with a new renderer.
1243 suppress_next_char_events_ = false;
1244
1245 // Reset some fields in preparation for recovering from a crash.
1246 ResetSizeAndRepaintPendingFlags();
1247 current_size_.SetSize(0, 0);
1248 is_hidden_ = false;
1249 is_accelerated_compositing_active_ = false;
1250
1251 // Reset this to ensure the hung renderer mechanism is working properly.
1252 in_flight_event_count_ = 0;
1253
1254 if (view_) {
1255 GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_,
1256 gfx::GLSurfaceHandle());
1257 view_->RenderProcessGone(status, exit_code);
1258 view_ = NULL; // The View should be deleted by RenderProcessGone.
1259 }
1260
1261 BackingStoreManager::RemoveBackingStore(this);
1262
1263 synthetic_gesture_controller_.reset();
1264 }
1265
UpdateTextDirection(WebTextDirection direction)1266 void RenderWidgetHostImpl::UpdateTextDirection(WebTextDirection direction) {
1267 text_direction_updated_ = true;
1268 text_direction_ = direction;
1269 }
1270
CancelUpdateTextDirection()1271 void RenderWidgetHostImpl::CancelUpdateTextDirection() {
1272 if (text_direction_updated_)
1273 text_direction_canceled_ = true;
1274 }
1275
NotifyTextDirection()1276 void RenderWidgetHostImpl::NotifyTextDirection() {
1277 if (text_direction_updated_) {
1278 if (!text_direction_canceled_)
1279 Send(new ViewMsg_SetTextDirection(GetRoutingID(), text_direction_));
1280 text_direction_updated_ = false;
1281 text_direction_canceled_ = false;
1282 }
1283 }
1284
SetInputMethodActive(bool activate)1285 void RenderWidgetHostImpl::SetInputMethodActive(bool activate) {
1286 input_method_active_ = activate;
1287 Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate));
1288 }
1289
CandidateWindowShown()1290 void RenderWidgetHostImpl::CandidateWindowShown() {
1291 Send(new ViewMsg_CandidateWindowShown(GetRoutingID()));
1292 }
1293
CandidateWindowUpdated()1294 void RenderWidgetHostImpl::CandidateWindowUpdated() {
1295 Send(new ViewMsg_CandidateWindowUpdated(GetRoutingID()));
1296 }
1297
CandidateWindowHidden()1298 void RenderWidgetHostImpl::CandidateWindowHidden() {
1299 Send(new ViewMsg_CandidateWindowHidden(GetRoutingID()));
1300 }
1301
ImeSetComposition(const base::string16 & text,const std::vector<blink::WebCompositionUnderline> & underlines,int selection_start,int selection_end)1302 void RenderWidgetHostImpl::ImeSetComposition(
1303 const base::string16& text,
1304 const std::vector<blink::WebCompositionUnderline>& underlines,
1305 int selection_start,
1306 int selection_end) {
1307 Send(new ViewMsg_ImeSetComposition(
1308 GetRoutingID(), text, underlines, selection_start, selection_end));
1309 }
1310
ImeConfirmComposition(const base::string16 & text,const gfx::Range & replacement_range,bool keep_selection)1311 void RenderWidgetHostImpl::ImeConfirmComposition(
1312 const base::string16& text,
1313 const gfx::Range& replacement_range,
1314 bool keep_selection) {
1315 Send(new ViewMsg_ImeConfirmComposition(
1316 GetRoutingID(), text, replacement_range, keep_selection));
1317 }
1318
ImeCancelComposition()1319 void RenderWidgetHostImpl::ImeCancelComposition() {
1320 Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(),
1321 std::vector<blink::WebCompositionUnderline>(), 0, 0));
1322 }
1323
ExtendSelectionAndDelete(size_t before,size_t after)1324 void RenderWidgetHostImpl::ExtendSelectionAndDelete(
1325 size_t before,
1326 size_t after) {
1327 Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before, after));
1328 }
1329
GetRootWindowResizerRect() const1330 gfx::Rect RenderWidgetHostImpl::GetRootWindowResizerRect() const {
1331 return gfx::Rect();
1332 }
1333
RequestToLockMouse(bool user_gesture,bool last_unlocked_by_target)1334 void RenderWidgetHostImpl::RequestToLockMouse(bool user_gesture,
1335 bool last_unlocked_by_target) {
1336 // Directly reject to lock the mouse. Subclass can override this method to
1337 // decide whether to allow mouse lock or not.
1338 GotResponseToLockMouseRequest(false);
1339 }
1340
RejectMouseLockOrUnlockIfNecessary()1341 void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
1342 DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
1343 if (pending_mouse_lock_request_) {
1344 pending_mouse_lock_request_ = false;
1345 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1346 } else if (IsMouseLocked()) {
1347 view_->UnlockMouse();
1348 }
1349 }
1350
IsMouseLocked() const1351 bool RenderWidgetHostImpl::IsMouseLocked() const {
1352 return view_ ? view_->IsMouseLocked() : false;
1353 }
1354
IsFullscreen() const1355 bool RenderWidgetHostImpl::IsFullscreen() const {
1356 return false;
1357 }
1358
SetShouldAutoResize(bool enable)1359 void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
1360 should_auto_resize_ = enable;
1361 }
1362
Destroy()1363 void RenderWidgetHostImpl::Destroy() {
1364 NotificationService::current()->Notify(
1365 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1366 Source<RenderWidgetHost>(this),
1367 NotificationService::NoDetails());
1368
1369 // Tell the view to die.
1370 // Note that in the process of the view shutting down, it can call a ton
1371 // of other messages on us. So if you do any other deinitialization here,
1372 // do it after this call to view_->Destroy().
1373 if (view_)
1374 view_->Destroy();
1375
1376 delete this;
1377 }
1378
RendererIsUnresponsive()1379 void RenderWidgetHostImpl::RendererIsUnresponsive() {
1380 NotificationService::current()->Notify(
1381 NOTIFICATION_RENDER_WIDGET_HOST_HANG,
1382 Source<RenderWidgetHost>(this),
1383 NotificationService::NoDetails());
1384 is_unresponsive_ = true;
1385 NotifyRendererUnresponsive();
1386 }
1387
RendererIsResponsive()1388 void RenderWidgetHostImpl::RendererIsResponsive() {
1389 if (is_unresponsive_) {
1390 is_unresponsive_ = false;
1391 NotifyRendererResponsive();
1392 }
1393 }
1394
OnRenderViewReady()1395 void RenderWidgetHostImpl::OnRenderViewReady() {
1396 SendScreenRects();
1397 WasResized();
1398 }
1399
OnRenderProcessGone(int status,int exit_code)1400 void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
1401 // TODO(evanm): This synchronously ends up calling "delete this".
1402 // Is that really what we want in response to this message? I'm matching
1403 // previous behavior of the code here.
1404 Destroy();
1405 }
1406
OnClose()1407 void RenderWidgetHostImpl::OnClose() {
1408 Shutdown();
1409 }
1410
OnSetTooltipText(const base::string16 & tooltip_text,WebTextDirection text_direction_hint)1411 void RenderWidgetHostImpl::OnSetTooltipText(
1412 const base::string16& tooltip_text,
1413 WebTextDirection text_direction_hint) {
1414 // First, add directionality marks around tooltip text if necessary.
1415 // A naive solution would be to simply always wrap the text. However, on
1416 // windows, Unicode directional embedding characters can't be displayed on
1417 // systems that lack RTL fonts and are instead displayed as empty squares.
1418 //
1419 // To get around this we only wrap the string when we deem it necessary i.e.
1420 // when the locale direction is different than the tooltip direction hint.
1421 //
1422 // Currently, we use element's directionality as the tooltip direction hint.
1423 // An alternate solution would be to set the overall directionality based on
1424 // trying to detect the directionality from the tooltip text rather than the
1425 // element direction. One could argue that would be a preferable solution
1426 // but we use the current approach to match Fx & IE's behavior.
1427 base::string16 wrapped_tooltip_text = tooltip_text;
1428 if (!tooltip_text.empty()) {
1429 if (text_direction_hint == blink::WebTextDirectionLeftToRight) {
1430 // Force the tooltip to have LTR directionality.
1431 wrapped_tooltip_text =
1432 base::i18n::GetDisplayStringInLTRDirectionality(wrapped_tooltip_text);
1433 } else if (text_direction_hint == blink::WebTextDirectionRightToLeft &&
1434 !base::i18n::IsRTL()) {
1435 // Force the tooltip to have RTL directionality.
1436 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
1437 }
1438 }
1439 if (GetView())
1440 view_->SetTooltipText(wrapped_tooltip_text);
1441 }
1442
OnUpdateScreenRectsAck()1443 void RenderWidgetHostImpl::OnUpdateScreenRectsAck() {
1444 waiting_for_screen_rects_ack_ = false;
1445 if (!view_)
1446 return;
1447
1448 if (view_->GetViewBounds() == last_view_screen_rect_ &&
1449 view_->GetBoundsInRootWindow() == last_window_screen_rect_) {
1450 return;
1451 }
1452
1453 SendScreenRects();
1454 }
1455
OnRequestMove(const gfx::Rect & pos)1456 void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
1457 if (view_) {
1458 view_->SetBounds(pos);
1459 Send(new ViewMsg_Move_ACK(routing_id_));
1460 }
1461 }
1462
OnPaintAtSizeAck(int tag,const gfx::Size & size)1463 void RenderWidgetHostImpl::OnPaintAtSizeAck(int tag, const gfx::Size& size) {
1464 std::pair<int, gfx::Size> details = std::make_pair(tag, size);
1465 NotificationService::current()->Notify(
1466 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK,
1467 Source<RenderWidgetHost>(this),
1468 Details<std::pair<int, gfx::Size> >(&details));
1469 }
1470
1471 #if defined(OS_MACOSX)
OnCompositorSurfaceBuffersSwapped(const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params & params)1472 void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
1473 const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
1474 TRACE_EVENT0("renderer_host",
1475 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
1476 if (!view_) {
1477 AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
1478 ack_params.sync_point = 0;
1479 RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
1480 params.gpu_process_host_id,
1481 ack_params);
1482 return;
1483 }
1484 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
1485 gpu_params.surface_id = params.surface_id;
1486 gpu_params.surface_handle = params.surface_handle;
1487 gpu_params.route_id = params.route_id;
1488 gpu_params.size = params.size;
1489 gpu_params.scale_factor = params.scale_factor;
1490 gpu_params.latency_info = params.latency_info;
1491 view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
1492 params.gpu_process_host_id);
1493 view_->DidReceiveRendererFrame();
1494 }
1495 #endif // OS_MACOSX
1496
OnSwapCompositorFrame(const IPC::Message & message)1497 bool RenderWidgetHostImpl::OnSwapCompositorFrame(
1498 const IPC::Message& message) {
1499 ViewHostMsg_SwapCompositorFrame::Param param;
1500 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m))
1501 return false;
1502 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
1503 uint32 output_surface_id = param.a;
1504 param.b.AssignTo(frame.get());
1505
1506 bool fixed_page_scale =
1507 frame->metadata.min_page_scale_factor ==
1508 frame->metadata.max_page_scale_factor;
1509 int updated_view_flags = fixed_page_scale ? InputRouter::FIXED_PAGE_SCALE
1510 : InputRouter::VIEW_FLAGS_NONE;
1511 input_router_->OnViewUpdated(updated_view_flags);
1512
1513 if (view_) {
1514 view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
1515 view_->DidReceiveRendererFrame();
1516 } else {
1517 cc::CompositorFrameAck ack;
1518 if (frame->gl_frame_data) {
1519 ack.gl_frame_data = frame->gl_frame_data.Pass();
1520 ack.gl_frame_data->sync_point = 0;
1521 } else if (frame->delegated_frame_data) {
1522 cc::TransferableResource::ReturnResources(
1523 frame->delegated_frame_data->resource_list,
1524 &ack.resources);
1525 } else if (frame->software_frame_data) {
1526 ack.last_software_frame_id = frame->software_frame_data->id;
1527 }
1528 SendSwapCompositorFrameAck(routing_id_, process_->GetID(),
1529 output_surface_id, ack);
1530 }
1531 return true;
1532 }
1533
OnOverscrolled(gfx::Vector2dF accumulated_overscroll,gfx::Vector2dF current_fling_velocity)1534 void RenderWidgetHostImpl::OnOverscrolled(
1535 gfx::Vector2dF accumulated_overscroll,
1536 gfx::Vector2dF current_fling_velocity) {
1537 if (view_)
1538 view_->OnOverscrolled(accumulated_overscroll, current_fling_velocity);
1539 }
1540
OnUpdateRect(const ViewHostMsg_UpdateRect_Params & params)1541 void RenderWidgetHostImpl::OnUpdateRect(
1542 const ViewHostMsg_UpdateRect_Params& params) {
1543 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnUpdateRect");
1544 TimeTicks paint_start = TimeTicks::Now();
1545
1546 // Update our knowledge of the RenderWidget's size.
1547 current_size_ = params.view_size;
1548 // Update our knowledge of the RenderWidget's scroll offset.
1549 last_scroll_offset_ = params.scroll_offset;
1550
1551 bool is_resize_ack =
1552 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1553
1554 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
1555 // that will end up reaching GetBackingStore.
1556 if (is_resize_ack) {
1557 DCHECK(!g_check_for_pending_resize_ack || resize_ack_pending_);
1558 resize_ack_pending_ = false;
1559 }
1560
1561 bool is_repaint_ack =
1562 ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
1563 if (is_repaint_ack) {
1564 DCHECK(repaint_ack_pending_);
1565 TRACE_EVENT_ASYNC_END0(
1566 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1567 repaint_ack_pending_ = false;
1568 TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
1569 UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
1570 }
1571
1572 DCHECK(!params.view_size.IsEmpty());
1573
1574 bool was_async = false;
1575
1576 // If this is a GPU UpdateRect, params.bitmap is invalid and dib will be NULL.
1577 TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
1578
1579 // If gpu process does painting, scroll_rect and copy_rects are always empty
1580 // and backing store is never used.
1581 if (dib) {
1582 DCHECK(!params.bitmap_rect.IsEmpty());
1583 gfx::Size pixel_size = gfx::ToFlooredSize(
1584 gfx::ScaleSize(params.bitmap_rect.size(), params.scale_factor));
1585 const size_t size = pixel_size.height() * pixel_size.width() * 4;
1586 if (dib->size() < size) {
1587 DLOG(WARNING) << "Transport DIB too small for given rectangle";
1588 RecordAction(UserMetricsAction("BadMessageTerminate_RWH1"));
1589 GetProcess()->ReceivedBadMessage();
1590 } else {
1591 // Scroll the backing store.
1592 if (!params.scroll_rect.IsEmpty()) {
1593 ScrollBackingStoreRect(params.scroll_delta,
1594 params.scroll_rect,
1595 params.view_size);
1596 }
1597
1598 // Paint the backing store. This will update it with the
1599 // renderer-supplied bits. The view will read out of the backing store
1600 // later to actually draw to the screen.
1601 was_async = PaintBackingStoreRect(
1602 params.bitmap,
1603 params.bitmap_rect,
1604 params.copy_rects,
1605 params.view_size,
1606 params.scale_factor,
1607 base::Bind(&RenderWidgetHostImpl::DidUpdateBackingStore,
1608 weak_factory_.GetWeakPtr(), params, paint_start));
1609 }
1610 }
1611
1612 if (!was_async) {
1613 DidUpdateBackingStore(params, paint_start);
1614 }
1615
1616 if (should_auto_resize_) {
1617 bool post_callback = new_auto_size_.IsEmpty();
1618 new_auto_size_ = params.view_size;
1619 if (post_callback) {
1620 base::MessageLoop::current()->PostTask(
1621 FROM_HERE,
1622 base::Bind(&RenderWidgetHostImpl::DelayedAutoResized,
1623 weak_factory_.GetWeakPtr()));
1624 }
1625 }
1626
1627 // Log the time delta for processing a paint message. On platforms that don't
1628 // support asynchronous painting, this is equivalent to
1629 // MPArch.RWH_TotalPaintTime.
1630 TimeDelta delta = TimeTicks::Now() - paint_start;
1631 UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
1632 }
1633
OnUpdateIsDelayed()1634 void RenderWidgetHostImpl::OnUpdateIsDelayed() {
1635 if (in_get_backing_store_)
1636 abort_get_backing_store_ = true;
1637 }
1638
DidUpdateBackingStore(const ViewHostMsg_UpdateRect_Params & params,const TimeTicks & paint_start)1639 void RenderWidgetHostImpl::DidUpdateBackingStore(
1640 const ViewHostMsg_UpdateRect_Params& params,
1641 const TimeTicks& paint_start) {
1642 TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
1643 TimeTicks update_start = TimeTicks::Now();
1644
1645 if (params.needs_ack) {
1646 // ACK early so we can prefetch the next PaintRect if there is a next one.
1647 // This must be done AFTER we're done painting with the bitmap supplied by
1648 // the renderer. This ACK is a signal to the renderer that the backing store
1649 // can be re-used, so the bitmap may be invalid after this call.
1650 Send(new ViewMsg_UpdateRect_ACK(routing_id_));
1651 }
1652
1653 // Move the plugins if the view hasn't already been destroyed. Plugin moves
1654 // will not be re-issued, so must move them now, regardless of whether we
1655 // paint or not. MovePluginWindows attempts to move the plugin windows and
1656 // in the process could dispatch other window messages which could cause the
1657 // view to be destroyed.
1658 if (view_)
1659 view_->MovePluginWindows(params.scroll_offset, params.plugin_window_moves);
1660
1661 NotificationService::current()->Notify(
1662 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
1663 Source<RenderWidgetHost>(this),
1664 NotificationService::NoDetails());
1665
1666 // We don't need to update the view if the view is hidden. We must do this
1667 // early return after the ACK is sent, however, or the renderer will not send
1668 // us more data.
1669 if (is_hidden_)
1670 return;
1671
1672 // Now paint the view. Watch out: it might be destroyed already.
1673 if (view_ && !is_accelerated_compositing_active_) {
1674 view_being_painted_ = true;
1675 view_->DidUpdateBackingStore(params.scroll_rect, params.scroll_delta,
1676 params.copy_rects, params.latency_info);
1677 view_->DidReceiveRendererFrame();
1678 view_being_painted_ = false;
1679 }
1680
1681 // If we got a resize ack, then perhaps we have another resize to send?
1682 bool is_resize_ack =
1683 ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
1684 if (is_resize_ack)
1685 WasResized();
1686
1687 // Log the time delta for processing a paint message.
1688 TimeTicks now = TimeTicks::Now();
1689 TimeDelta delta = now - update_start;
1690 UMA_HISTOGRAM_TIMES("MPArch.RWH_DidUpdateBackingStore", delta);
1691
1692 // Measures the time from receiving the MsgUpdateRect IPC to completing the
1693 // DidUpdateBackingStore() method. On platforms which have asynchronous
1694 // painting, such as Linux, this is the sum of MPArch.RWH_OnMsgUpdateRect,
1695 // MPArch.RWH_DidUpdateBackingStore, and the time spent asynchronously
1696 // waiting for the paint to complete.
1697 //
1698 // On other platforms, this will be equivalent to MPArch.RWH_OnMsgUpdateRect.
1699 delta = now - paint_start;
1700 UMA_HISTOGRAM_TIMES("MPArch.RWH_TotalPaintTime", delta);
1701 }
1702
OnQueueSyntheticGesture(const SyntheticGesturePacket & gesture_packet)1703 void RenderWidgetHostImpl::OnQueueSyntheticGesture(
1704 const SyntheticGesturePacket& gesture_packet) {
1705 if (!synthetic_gesture_controller_) {
1706 if (!view_)
1707 return;
1708 synthetic_gesture_controller_.reset(
1709 new SyntheticGestureController(
1710 view_->CreateSyntheticGestureTarget().Pass()));
1711 }
1712
1713 synthetic_gesture_controller_->QueueSyntheticGesture(
1714 SyntheticGesture::Create(*gesture_packet.gesture_params()));
1715 }
1716
OnFocus()1717 void RenderWidgetHostImpl::OnFocus() {
1718 // Only RenderViewHost can deal with that message.
1719 RecordAction(UserMetricsAction("BadMessageTerminate_RWH4"));
1720 GetProcess()->ReceivedBadMessage();
1721 }
1722
OnBlur()1723 void RenderWidgetHostImpl::OnBlur() {
1724 // Only RenderViewHost can deal with that message.
1725 RecordAction(UserMetricsAction("BadMessageTerminate_RWH5"));
1726 GetProcess()->ReceivedBadMessage();
1727 }
1728
OnSetCursor(const WebCursor & cursor)1729 void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
1730 if (!view_) {
1731 return;
1732 }
1733 view_->UpdateCursor(cursor);
1734 }
1735
OnTextInputTypeChanged(ui::TextInputType type,ui::TextInputMode input_mode,bool can_compose_inline)1736 void RenderWidgetHostImpl::OnTextInputTypeChanged(
1737 ui::TextInputType type,
1738 ui::TextInputMode input_mode,
1739 bool can_compose_inline) {
1740 if (view_)
1741 view_->TextInputTypeChanged(type, input_mode, can_compose_inline);
1742 }
1743
1744 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
OnImeCompositionRangeChanged(const gfx::Range & range,const std::vector<gfx::Rect> & character_bounds)1745 void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
1746 const gfx::Range& range,
1747 const std::vector<gfx::Rect>& character_bounds) {
1748 if (view_)
1749 view_->ImeCompositionRangeChanged(range, character_bounds);
1750 }
1751 #endif
1752
OnImeCancelComposition()1753 void RenderWidgetHostImpl::OnImeCancelComposition() {
1754 if (view_)
1755 view_->ImeCancelComposition();
1756 }
1757
OnDidActivateAcceleratedCompositing(bool activated)1758 void RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing(bool activated) {
1759 TRACE_EVENT1("renderer_host",
1760 "RenderWidgetHostImpl::OnDidActivateAcceleratedCompositing",
1761 "activated", activated);
1762 is_accelerated_compositing_active_ = activated;
1763 if (view_)
1764 view_->OnAcceleratedCompositingStateChange();
1765 }
1766
OnLockMouse(bool user_gesture,bool last_unlocked_by_target,bool privileged)1767 void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
1768 bool last_unlocked_by_target,
1769 bool privileged) {
1770
1771 if (pending_mouse_lock_request_) {
1772 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
1773 return;
1774 } else if (IsMouseLocked()) {
1775 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
1776 return;
1777 }
1778
1779 pending_mouse_lock_request_ = true;
1780 if (privileged && allow_privileged_mouse_lock_) {
1781 // Directly approve to lock the mouse.
1782 GotResponseToLockMouseRequest(true);
1783 } else {
1784 RequestToLockMouse(user_gesture, last_unlocked_by_target);
1785 }
1786 }
1787
OnUnlockMouse()1788 void RenderWidgetHostImpl::OnUnlockMouse() {
1789 RejectMouseLockOrUnlockIfNecessary();
1790 }
1791
OnShowDisambiguationPopup(const gfx::Rect & rect,const gfx::Size & size,const TransportDIB::Id & id)1792 void RenderWidgetHostImpl::OnShowDisambiguationPopup(
1793 const gfx::Rect& rect,
1794 const gfx::Size& size,
1795 const TransportDIB::Id& id) {
1796 DCHECK(!rect.IsEmpty());
1797 DCHECK(!size.IsEmpty());
1798
1799 TransportDIB* dib = process_->GetTransportDIB(id);
1800 DCHECK(dib->memory());
1801 DCHECK(dib->size() == SkBitmap::ComputeSize(SkBitmap::kARGB_8888_Config,
1802 size.width(), size.height()));
1803
1804 SkBitmap zoomed_bitmap;
1805 zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
1806 size.width(), size.height());
1807 zoomed_bitmap.setPixels(dib->memory());
1808
1809 #if defined(OS_ANDROID)
1810 if (view_)
1811 view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
1812 #else
1813 NOTIMPLEMENTED();
1814 #endif
1815
1816 zoomed_bitmap.setPixels(0);
1817 Send(new ViewMsg_ReleaseDisambiguationPopupDIB(GetRoutingID(),
1818 dib->handle()));
1819 }
1820
1821 #if defined(OS_WIN)
OnWindowlessPluginDummyWindowCreated(gfx::NativeViewId dummy_activation_window)1822 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
1823 gfx::NativeViewId dummy_activation_window) {
1824 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1825
1826 // This may happen as a result of a race condition when the plugin is going
1827 // away.
1828 wchar_t window_title[MAX_PATH + 1] = {0};
1829 if (!IsWindow(hwnd) ||
1830 !GetWindowText(hwnd, window_title, arraysize(window_title)) ||
1831 lstrcmpiW(window_title, kDummyActivationWindowName) != 0) {
1832 return;
1833 }
1834
1835 SetParent(hwnd,
1836 reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
1837 dummy_windows_for_activation_.push_back(hwnd);
1838 }
1839
OnWindowlessPluginDummyWindowDestroyed(gfx::NativeViewId dummy_activation_window)1840 void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
1841 gfx::NativeViewId dummy_activation_window) {
1842 HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
1843 std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
1844 for (; i != dummy_windows_for_activation_.end(); ++i) {
1845 if ((*i) == hwnd) {
1846 dummy_windows_for_activation_.erase(i);
1847 return;
1848 }
1849 }
1850 NOTREACHED() << "Unknown dummy window";
1851 }
1852 #endif
1853
PaintBackingStoreRect(TransportDIB::Id bitmap,const gfx::Rect & bitmap_rect,const std::vector<gfx::Rect> & copy_rects,const gfx::Size & view_size,float scale_factor,const base::Closure & completion_callback)1854 bool RenderWidgetHostImpl::PaintBackingStoreRect(
1855 TransportDIB::Id bitmap,
1856 const gfx::Rect& bitmap_rect,
1857 const std::vector<gfx::Rect>& copy_rects,
1858 const gfx::Size& view_size,
1859 float scale_factor,
1860 const base::Closure& completion_callback) {
1861 // The view may be destroyed already.
1862 if (!view_)
1863 return false;
1864
1865 if (is_hidden_) {
1866 // Don't bother updating the backing store when we're hidden. Just mark it
1867 // as being totally invalid. This will cause a complete repaint when the
1868 // view is restored.
1869 needs_repainting_on_restore_ = true;
1870 return false;
1871 }
1872
1873 bool needs_full_paint = false;
1874 bool scheduled_completion_callback = false;
1875 BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
1876 copy_rects, scale_factor,
1877 completion_callback,
1878 &needs_full_paint,
1879 &scheduled_completion_callback);
1880 if (needs_full_paint) {
1881 repaint_start_time_ = TimeTicks::Now();
1882 DCHECK(!repaint_ack_pending_);
1883 repaint_ack_pending_ = true;
1884 TRACE_EVENT_ASYNC_BEGIN0(
1885 "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
1886 Send(new ViewMsg_Repaint(routing_id_, view_size));
1887 }
1888
1889 return scheduled_completion_callback;
1890 }
1891
ScrollBackingStoreRect(const gfx::Vector2d & delta,const gfx::Rect & clip_rect,const gfx::Size & view_size)1892 void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta,
1893 const gfx::Rect& clip_rect,
1894 const gfx::Size& view_size) {
1895 if (is_hidden_) {
1896 // Don't bother updating the backing store when we're hidden. Just mark it
1897 // as being totally invalid. This will cause a complete repaint when the
1898 // view is restored.
1899 needs_repainting_on_restore_ = true;
1900 return;
1901 }
1902
1903 // TODO(darin): do we need to do something else if our backing store is not
1904 // the same size as the advertised view? maybe we just assume there is a
1905 // full paint on its way?
1906 BackingStore* backing_store = BackingStoreManager::Lookup(this);
1907 if (!backing_store || (backing_store->size() != view_size))
1908 return;
1909 backing_store->ScrollBackingStore(delta, clip_rect, view_size);
1910 }
1911
Replace(const base::string16 & word)1912 void RenderWidgetHostImpl::Replace(const base::string16& word) {
1913 Send(new InputMsg_Replace(routing_id_, word));
1914 }
1915
ReplaceMisspelling(const base::string16 & word)1916 void RenderWidgetHostImpl::ReplaceMisspelling(const base::string16& word) {
1917 Send(new InputMsg_ReplaceMisspelling(routing_id_, word));
1918 }
1919
SetIgnoreInputEvents(bool ignore_input_events)1920 void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
1921 ignore_input_events_ = ignore_input_events;
1922 }
1923
KeyPressListenersHandleEvent(const NativeWebKeyboardEvent & event)1924 bool RenderWidgetHostImpl::KeyPressListenersHandleEvent(
1925 const NativeWebKeyboardEvent& event) {
1926 if (event.skip_in_browser || event.type != WebKeyboardEvent::RawKeyDown)
1927 return false;
1928
1929 for (size_t i = 0; i < key_press_event_callbacks_.size(); i++) {
1930 size_t original_size = key_press_event_callbacks_.size();
1931 if (key_press_event_callbacks_[i].Run(event))
1932 return true;
1933
1934 // Check whether the callback that just ran removed itself, in which case
1935 // the iterator needs to be decremented to properly account for the removal.
1936 size_t current_size = key_press_event_callbacks_.size();
1937 if (current_size != original_size) {
1938 DCHECK_EQ(original_size - 1, current_size);
1939 --i;
1940 }
1941 }
1942
1943 return false;
1944 }
1945
FilterInputEvent(const blink::WebInputEvent & event,const ui::LatencyInfo & latency_info)1946 InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
1947 const blink::WebInputEvent& event, const ui::LatencyInfo& latency_info) {
1948 // Don't ignore touch cancel events, since they may be sent while input
1949 // events are being ignored in order to keep the renderer from getting
1950 // confused about how many touches are active.
1951 if (IgnoreInputEvents() && event.type != WebInputEvent::TouchCancel)
1952 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
1953
1954 if (!process_->HasConnection())
1955 return INPUT_EVENT_ACK_STATE_UNKNOWN;
1956
1957 if (event.type == WebInputEvent::MouseDown)
1958 OnUserGesture();
1959
1960 return view_ ? view_->FilterInputEvent(event)
1961 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1962 }
1963
IncrementInFlightEventCount()1964 void RenderWidgetHostImpl::IncrementInFlightEventCount() {
1965 StartHangMonitorTimeout(
1966 TimeDelta::FromMilliseconds(hung_renderer_delay_ms_));
1967 increment_in_flight_event_count();
1968 }
1969
DecrementInFlightEventCount()1970 void RenderWidgetHostImpl::DecrementInFlightEventCount() {
1971 DCHECK(in_flight_event_count_ >= 0);
1972 // Cancel pending hung renderer checks since the renderer is responsive.
1973 if (decrement_in_flight_event_count() <= 0)
1974 StopHangMonitorTimeout();
1975 }
1976
OnHasTouchEventHandlers(bool has_handlers)1977 void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
1978 if (has_touch_handler_ == has_handlers)
1979 return;
1980 has_touch_handler_ = has_handlers;
1981 #if defined(OS_ANDROID)
1982 if (view_)
1983 view_->HasTouchEventHandlers(has_touch_handler_);
1984 #endif
1985 }
1986
GetOverscrollController() const1987 OverscrollController* RenderWidgetHostImpl::GetOverscrollController() const {
1988 return overscroll_controller_.get();
1989 }
1990
DidFlush()1991 void RenderWidgetHostImpl::DidFlush() {
1992 if (view_)
1993 view_->OnDidFlushInput();
1994 }
1995
OnKeyboardEventAck(const NativeWebKeyboardEvent & event,InputEventAckState ack_result)1996 void RenderWidgetHostImpl::OnKeyboardEventAck(
1997 const NativeWebKeyboardEvent& event,
1998 InputEventAckState ack_result) {
1999 #if defined(OS_MACOSX)
2000 if (!is_hidden() && view_ && view_->PostProcessEventForPluginIme(event))
2001 return;
2002 #endif
2003
2004 // We only send unprocessed key event upwards if we are not hidden,
2005 // because the user has moved away from us and no longer expect any effect
2006 // of this key event.
2007 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2008 if (delegate_ && !processed && !is_hidden() && !event.skip_in_browser) {
2009 delegate_->HandleKeyboardEvent(event);
2010
2011 // WARNING: This RenderWidgetHostImpl can be deallocated at this point
2012 // (i.e. in the case of Ctrl+W, where the call to
2013 // HandleKeyboardEvent destroys this RenderWidgetHostImpl).
2014 }
2015 }
2016
OnWheelEventAck(const MouseWheelEventWithLatencyInfo & wheel_event,InputEventAckState ack_result)2017 void RenderWidgetHostImpl::OnWheelEventAck(
2018 const MouseWheelEventWithLatencyInfo& wheel_event,
2019 InputEventAckState ack_result) {
2020 if (!wheel_event.latency.FindLatency(
2021 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2022 // MouseWheelEvent latency ends when it is acked but does not cause any
2023 // rendering scheduled.
2024 ui::LatencyInfo latency = wheel_event.latency;
2025 latency.AddLatencyNumber(
2026 ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
2027 }
2028
2029 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
2030 if (!processed && !is_hidden() && view_)
2031 view_->UnhandledWheelEvent(wheel_event.event);
2032 }
2033
OnGestureEventAck(const GestureEventWithLatencyInfo & event,InputEventAckState ack_result)2034 void RenderWidgetHostImpl::OnGestureEventAck(
2035 const GestureEventWithLatencyInfo& event,
2036 InputEventAckState ack_result) {
2037 if (!event.latency.FindLatency(
2038 ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
2039 // GestureEvent latency ends when it is acked but does not cause any
2040 // rendering scheduled.
2041 ui::LatencyInfo latency = event.latency;
2042 latency.AddLatencyNumber(
2043 ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0 ,0);
2044 }
2045
2046 if (view_)
2047 view_->GestureEventAck(event.event.type, ack_result);
2048 }
2049
OnTouchEventAck(const TouchEventWithLatencyInfo & event,InputEventAckState ack_result)2050 void RenderWidgetHostImpl::OnTouchEventAck(
2051 const TouchEventWithLatencyInfo& event,
2052 InputEventAckState ack_result) {
2053 TouchEventWithLatencyInfo touch_event = event;
2054 // TouchEvent latency does not end when acked since it could later on
2055 // become gesture events.
2056 touch_event.latency.AddLatencyNumber(
2057 ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0);
2058 ComputeTouchLatency(touch_event.latency);
2059 if (view_)
2060 view_->ProcessAckedTouchEvent(touch_event, ack_result);
2061 }
2062
OnUnexpectedEventAck(UnexpectedEventAckType type)2063 void RenderWidgetHostImpl::OnUnexpectedEventAck(UnexpectedEventAckType type) {
2064 if (type == BAD_ACK_MESSAGE) {
2065 RecordAction(UserMetricsAction("BadMessageTerminate_RWH2"));
2066 process_->ReceivedBadMessage();
2067 } else if (type == UNEXPECTED_EVENT_TYPE) {
2068 suppress_next_char_events_ = false;
2069 }
2070 }
2071
GetLastScrollOffset() const2072 const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
2073 return last_scroll_offset_;
2074 }
2075
IgnoreInputEvents() const2076 bool RenderWidgetHostImpl::IgnoreInputEvents() const {
2077 return ignore_input_events_ || process_->IgnoreInputEvents();
2078 }
2079
ShouldForwardTouchEvent() const2080 bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
2081 return input_router_->ShouldForwardTouchEvent();
2082 }
2083
StartUserGesture()2084 void RenderWidgetHostImpl::StartUserGesture() {
2085 OnUserGesture();
2086 }
2087
Stop()2088 void RenderWidgetHostImpl::Stop() {
2089 Send(new ViewMsg_Stop(GetRoutingID()));
2090 }
2091
SetBackground(const SkBitmap & background)2092 void RenderWidgetHostImpl::SetBackground(const SkBitmap& background) {
2093 Send(new ViewMsg_SetBackground(GetRoutingID(), background));
2094 }
2095
SetEditCommandsForNextKeyEvent(const std::vector<EditCommand> & commands)2096 void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
2097 const std::vector<EditCommand>& commands) {
2098 Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
2099 }
2100
SetAccessibilityMode(AccessibilityMode mode)2101 void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
2102 accessibility_mode_ = mode;
2103 Send(new ViewMsg_SetAccessibilityMode(GetRoutingID(), mode));
2104 }
2105
AccessibilityDoDefaultAction(int object_id)2106 void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
2107 Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
2108 }
2109
AccessibilitySetFocus(int object_id)2110 void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id) {
2111 Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id));
2112 }
2113
AccessibilityScrollToMakeVisible(int acc_obj_id,gfx::Rect subfocus)2114 void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
2115 int acc_obj_id, gfx::Rect subfocus) {
2116 Send(new AccessibilityMsg_ScrollToMakeVisible(
2117 GetRoutingID(), acc_obj_id, subfocus));
2118 }
2119
AccessibilityScrollToPoint(int acc_obj_id,gfx::Point point)2120 void RenderWidgetHostImpl::AccessibilityScrollToPoint(
2121 int acc_obj_id, gfx::Point point) {
2122 Send(new AccessibilityMsg_ScrollToPoint(
2123 GetRoutingID(), acc_obj_id, point));
2124 }
2125
AccessibilitySetTextSelection(int object_id,int start_offset,int end_offset)2126 void RenderWidgetHostImpl::AccessibilitySetTextSelection(
2127 int object_id, int start_offset, int end_offset) {
2128 Send(new AccessibilityMsg_SetTextSelection(
2129 GetRoutingID(), object_id, start_offset, end_offset));
2130 }
2131
FatalAccessibilityTreeError()2132 void RenderWidgetHostImpl::FatalAccessibilityTreeError() {
2133 Send(new AccessibilityMsg_FatalError(GetRoutingID()));
2134 }
2135
2136 #if defined(OS_WIN) && defined(USE_AURA)
SetParentNativeViewAccessible(gfx::NativeViewAccessible accessible_parent)2137 void RenderWidgetHostImpl::SetParentNativeViewAccessible(
2138 gfx::NativeViewAccessible accessible_parent) {
2139 if (view_)
2140 view_->SetParentNativeViewAccessible(accessible_parent);
2141 }
2142
2143 gfx::NativeViewAccessible
GetParentNativeViewAccessible() const2144 RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
2145 return delegate_->GetParentNativeViewAccessible();
2146 }
2147 #endif
2148
ExecuteEditCommand(const std::string & command,const std::string & value)2149 void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
2150 const std::string& value) {
2151 Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
2152 }
2153
ScrollFocusedEditableNodeIntoRect(const gfx::Rect & rect)2154 void RenderWidgetHostImpl::ScrollFocusedEditableNodeIntoRect(
2155 const gfx::Rect& rect) {
2156 Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
2157 }
2158
SelectRange(const gfx::Point & start,const gfx::Point & end)2159 void RenderWidgetHostImpl::SelectRange(const gfx::Point& start,
2160 const gfx::Point& end) {
2161 Send(new InputMsg_SelectRange(GetRoutingID(), start, end));
2162 }
2163
MoveCaret(const gfx::Point & point)2164 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
2165 Send(new InputMsg_MoveCaret(GetRoutingID(), point));
2166 }
2167
Undo()2168 void RenderWidgetHostImpl::Undo() {
2169 Send(new InputMsg_Undo(GetRoutingID()));
2170 RecordAction(UserMetricsAction("Undo"));
2171 }
2172
Redo()2173 void RenderWidgetHostImpl::Redo() {
2174 Send(new InputMsg_Redo(GetRoutingID()));
2175 RecordAction(UserMetricsAction("Redo"));
2176 }
2177
Cut()2178 void RenderWidgetHostImpl::Cut() {
2179 Send(new InputMsg_Cut(GetRoutingID()));
2180 RecordAction(UserMetricsAction("Cut"));
2181 }
2182
Copy()2183 void RenderWidgetHostImpl::Copy() {
2184 Send(new InputMsg_Copy(GetRoutingID()));
2185 RecordAction(UserMetricsAction("Copy"));
2186 }
2187
CopyToFindPboard()2188 void RenderWidgetHostImpl::CopyToFindPboard() {
2189 #if defined(OS_MACOSX)
2190 // Windows/Linux don't have the concept of a find pasteboard.
2191 Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
2192 RecordAction(UserMetricsAction("CopyToFindPboard"));
2193 #endif
2194 }
2195
Paste()2196 void RenderWidgetHostImpl::Paste() {
2197 Send(new InputMsg_Paste(GetRoutingID()));
2198 RecordAction(UserMetricsAction("Paste"));
2199 }
2200
PasteAndMatchStyle()2201 void RenderWidgetHostImpl::PasteAndMatchStyle() {
2202 Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
2203 RecordAction(UserMetricsAction("PasteAndMatchStyle"));
2204 }
2205
Delete()2206 void RenderWidgetHostImpl::Delete() {
2207 Send(new InputMsg_Delete(GetRoutingID()));
2208 RecordAction(UserMetricsAction("DeleteSelection"));
2209 }
2210
SelectAll()2211 void RenderWidgetHostImpl::SelectAll() {
2212 Send(new InputMsg_SelectAll(GetRoutingID()));
2213 RecordAction(UserMetricsAction("SelectAll"));
2214 }
2215
Unselect()2216 void RenderWidgetHostImpl::Unselect() {
2217 Send(new InputMsg_Unselect(GetRoutingID()));
2218 RecordAction(UserMetricsAction("Unselect"));
2219 }
2220
GotResponseToLockMouseRequest(bool allowed)2221 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
2222 if (!allowed) {
2223 RejectMouseLockOrUnlockIfNecessary();
2224 return false;
2225 } else {
2226 if (!pending_mouse_lock_request_) {
2227 // This is possible, e.g., the plugin sends us an unlock request before
2228 // the user allows to lock to mouse.
2229 return false;
2230 }
2231
2232 pending_mouse_lock_request_ = false;
2233 if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) {
2234 Send(new ViewMsg_LockMouse_ACK(routing_id_, false));
2235 return false;
2236 } else {
2237 Send(new ViewMsg_LockMouse_ACK(routing_id_, true));
2238 return true;
2239 }
2240 }
2241 }
2242
2243 // static
AcknowledgeBufferPresent(int32 route_id,int gpu_host_id,const AcceleratedSurfaceMsg_BufferPresented_Params & params)2244 void RenderWidgetHostImpl::AcknowledgeBufferPresent(
2245 int32 route_id, int gpu_host_id,
2246 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
2247 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
2248 if (ui_shim) {
2249 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
2250 params));
2251 }
2252 }
2253
2254 // static
SendSwapCompositorFrameAck(int32 route_id,uint32 output_surface_id,int renderer_host_id,const cc::CompositorFrameAck & ack)2255 void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
2256 int32 route_id,
2257 uint32 output_surface_id,
2258 int renderer_host_id,
2259 const cc::CompositorFrameAck& ack) {
2260 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2261 if (!host)
2262 return;
2263 host->Send(new ViewMsg_SwapCompositorFrameAck(
2264 route_id, output_surface_id, ack));
2265 }
2266
2267 // static
SendReclaimCompositorResources(int32 route_id,uint32 output_surface_id,int renderer_host_id,const cc::CompositorFrameAck & ack)2268 void RenderWidgetHostImpl::SendReclaimCompositorResources(
2269 int32 route_id,
2270 uint32 output_surface_id,
2271 int renderer_host_id,
2272 const cc::CompositorFrameAck& ack) {
2273 RenderProcessHost* host = RenderProcessHost::FromID(renderer_host_id);
2274 if (!host)
2275 return;
2276 host->Send(
2277 new ViewMsg_ReclaimCompositorResources(route_id, output_surface_id, ack));
2278 }
2279
AcknowledgeSwapBuffersToRenderer()2280 void RenderWidgetHostImpl::AcknowledgeSwapBuffersToRenderer() {
2281 if (!is_threaded_compositing_enabled_)
2282 Send(new ViewMsg_SwapBuffers_ACK(routing_id_));
2283 }
2284
2285 #if defined(USE_AURA)
2286
ParentChanged(gfx::NativeViewId new_parent)2287 void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent) {
2288 #if defined(OS_WIN)
2289 HWND hwnd = reinterpret_cast<HWND>(new_parent);
2290 if (!hwnd)
2291 hwnd = GetDesktopWindow();
2292 // On Windows GetParentForWindowlessPlugin returns the dummy window used as
2293 // the parent for windowless NPAPI plugins. Reparenting this window to the
2294 // new parent should be good enough.
2295 if (view_ && view_->GetParentForWindowlessPlugin())
2296 SetParent(reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()),
2297 reinterpret_cast<HWND>(new_parent));
2298 #endif
2299 }
2300
2301 #endif
2302
DelayedAutoResized()2303 void RenderWidgetHostImpl::DelayedAutoResized() {
2304 gfx::Size new_size = new_auto_size_;
2305 // Clear the new_auto_size_ since the empty value is used as a flag to
2306 // indicate that no callback is in progress (i.e. without this line
2307 // DelayedAutoResized will not get called again).
2308 new_auto_size_.SetSize(0, 0);
2309 if (!should_auto_resize_)
2310 return;
2311
2312 OnRenderAutoResized(new_size);
2313 }
2314
DetachDelegate()2315 void RenderWidgetHostImpl::DetachDelegate() {
2316 delegate_ = NULL;
2317 }
2318
ComputeTouchLatency(const ui::LatencyInfo & latency_info)2319 void RenderWidgetHostImpl::ComputeTouchLatency(
2320 const ui::LatencyInfo& latency_info) {
2321 ui::LatencyInfo::LatencyComponent ui_component;
2322 ui::LatencyInfo::LatencyComponent rwh_component;
2323 ui::LatencyInfo::LatencyComponent acked_component;
2324
2325 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
2326 0,
2327 &ui_component) ||
2328 !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2329 GetLatencyComponentId(),
2330 &rwh_component))
2331 return;
2332
2333 DCHECK(ui_component.event_count == 1);
2334 DCHECK(rwh_component.event_count == 1);
2335
2336 base::TimeDelta ui_delta =
2337 rwh_component.event_time - ui_component.event_time;
2338 rendering_stats_.touch_ui_count++;
2339 rendering_stats_.total_touch_ui_latency += ui_delta;
2340 UMA_HISTOGRAM_CUSTOM_COUNTS(
2341 "Event.Latency.Browser.TouchUI",
2342 ui_delta.InMicroseconds(),
2343 0,
2344 20000,
2345 100);
2346
2347 if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT,
2348 0,
2349 &acked_component)) {
2350 DCHECK(acked_component.event_count == 1);
2351 base::TimeDelta acked_delta =
2352 acked_component.event_time - rwh_component.event_time;
2353 rendering_stats_.touch_acked_count++;
2354 rendering_stats_.total_touch_acked_latency += acked_delta;
2355 UMA_HISTOGRAM_CUSTOM_COUNTS(
2356 "Event.Latency.Browser.TouchAcked",
2357 acked_delta.InMicroseconds(),
2358 0,
2359 1000000,
2360 100);
2361 }
2362
2363 if (CommandLine::ForCurrentProcess()->HasSwitch(
2364 switches::kEnableGpuBenchmarking))
2365 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_, rendering_stats_));
2366 }
2367
FrameSwapped(const ui::LatencyInfo & latency_info)2368 void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
2369 ui::LatencyInfo::LatencyComponent window_snapshot_component;
2370 if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
2371 GetLatencyComponentId(),
2372 &window_snapshot_component)) {
2373 WindowSnapshotReachedScreen(
2374 static_cast<int>(window_snapshot_component.sequence_number));
2375 }
2376
2377 ui::LatencyInfo::LatencyComponent rwh_component;
2378 ui::LatencyInfo::LatencyComponent swap_component;
2379 if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
2380 GetLatencyComponentId(),
2381 &rwh_component) ||
2382 !latency_info.FindLatency(
2383 ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
2384 0, &swap_component)) {
2385 return;
2386 }
2387
2388 rendering_stats_.input_event_count += rwh_component.event_count;
2389 rendering_stats_.total_input_latency +=
2390 rwh_component.event_count *
2391 (swap_component.event_time - rwh_component.event_time);
2392
2393 ui::LatencyInfo::LatencyComponent original_component;
2394 if (latency_info.FindLatency(
2395 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
2396 GetLatencyComponentId(),
2397 &original_component)) {
2398 // This UMA metric tracks the time from when the original touch event is
2399 // created (averaged if there are multiple) to when the scroll gesture
2400 // results in final frame swap.
2401 base::TimeDelta delta =
2402 swap_component.event_time - original_component.event_time;
2403 for (size_t i = 0; i < original_component.event_count; i++) {
2404 UMA_HISTOGRAM_CUSTOM_COUNTS(
2405 "Event.Latency.TouchToScrollUpdateSwap",
2406 delta.InMicroseconds(),
2407 0,
2408 1000000,
2409 100);
2410 }
2411 rendering_stats_.scroll_update_count += original_component.event_count;
2412 rendering_stats_.total_scroll_update_latency +=
2413 original_component.event_count *
2414 (swap_component.event_time - original_component.event_time);
2415 }
2416
2417 if (CommandLine::ForCurrentProcess()->HasSwitch(
2418 switches::kEnableGpuBenchmarking))
2419 Send(new ViewMsg_SetBrowserRenderingStats(routing_id_, rendering_stats_));
2420 }
2421
DidReceiveRendererFrame()2422 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
2423 view_->DidReceiveRendererFrame();
2424 }
2425
WindowSnapshotReachedScreen(int snapshot_id)2426 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
2427 DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
2428
2429 std::vector<unsigned char> png;
2430
2431 // This feature is behind the kEnableGpuBenchmarking command line switch
2432 // because it poses security concerns and should only be used for testing.
2433 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2434 if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
2435 gfx::Rect view_bounds = GetView()->GetViewBounds();
2436 gfx::Rect snapshot_bounds(view_bounds.size());
2437 gfx::Size snapshot_size = snapshot_bounds.size();
2438
2439 if (ui::GrabViewSnapshot(GetView()->GetNativeView(),
2440 &png, snapshot_bounds)) {
2441 Send(new ViewMsg_WindowSnapshotCompleted(
2442 GetRoutingID(), snapshot_id, snapshot_size, png));
2443 return;
2444 }
2445 }
2446
2447 Send(new ViewMsg_WindowSnapshotCompleted(
2448 GetRoutingID(), snapshot_id, gfx::Size(), png));
2449 }
2450
2451 // static
CompositorFrameDrawn(const ui::LatencyInfo & latency_info)2452 void RenderWidgetHostImpl::CompositorFrameDrawn(
2453 const ui::LatencyInfo& latency_info) {
2454 std::set<RenderWidgetHostImpl*> rwhi_set;
2455
2456 for (ui::LatencyInfo::LatencyMap::const_iterator b =
2457 latency_info.latency_components.begin();
2458 b != latency_info.latency_components.end();
2459 ++b) {
2460 if (b->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
2461 b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
2462 // Matches with GetLatencyComponentId
2463 int routing_id = b->first.second & 0xffffffff;
2464 int process_id = (b->first.second >> 32) & 0xffffffff;
2465 RenderWidgetHost* rwh =
2466 RenderWidgetHost::FromID(process_id, routing_id);
2467 if (!rwh) {
2468 continue;
2469 }
2470 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
2471 if (rwhi_set.insert(rwhi).second)
2472 rwhi->FrameSwapped(latency_info);
2473 }
2474 }
2475 }
2476
2477 } // namespace content
2478