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