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