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