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