render_widget.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
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/renderer/render_widget.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/debug/trace_event.h"
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/message_loop.h"
13#include "base/metrics/histogram.h"
14#include "base/stl_util.h"
15#include "base/strings/utf_string_conversions.h"
16#include "build/build_config.h"
17#include "cc/base/switches.h"
18#include "cc/base/thread.h"
19#include "cc/base/thread_impl.h"
20#include "cc/output/output_surface.h"
21#include "cc/trees/layer_tree_host.h"
22#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
23#include "content/common/input_messages.h"
24#include "content/common/swapped_out_messages.h"
25#include "content/common/view_messages.h"
26#include "content/public/common/content_switches.h"
27#include "content/renderer/gpu/compositor_output_surface.h"
28#include "content/renderer/gpu/compositor_software_output_device.h"
29#include "content/renderer/gpu/delegated_compositor_output_surface.h"
30#include "content/renderer/gpu/input_handler_manager.h"
31#include "content/renderer/gpu/mailbox_output_surface.h"
32#include "content/renderer/gpu/render_widget_compositor.h"
33#include "content/renderer/ime_event_guard.h"
34#include "content/renderer/render_process.h"
35#include "content/renderer/render_thread_impl.h"
36#include "content/renderer/renderer_webkitplatformsupport_impl.h"
37#include "ipc/ipc_sync_message.h"
38#include "skia/ext/platform_canvas.h"
39#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
40#include "third_party/WebKit/public/platform/WebPoint.h"
41#include "third_party/WebKit/public/platform/WebRect.h"
42#include "third_party/WebKit/public/platform/WebSize.h"
43#include "third_party/WebKit/public/platform/WebString.h"
44#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
45#include "third_party/WebKit/Source/WebKit/chromium/public/WebHelperPlugin.h"
46#include "third_party/WebKit/Source/WebKit/chromium/public/WebPagePopup.h"
47#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
48#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenuInfo.h"
49#include "third_party/WebKit/Source/WebKit/chromium/public/WebRange.h"
50#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
51#include "third_party/skia/include/core/SkShader.h"
52#include "ui/base/ui_base_switches.h"
53#include "ui/gfx/point.h"
54#include "ui/gfx/rect_conversions.h"
55#include "ui/gfx/size_conversions.h"
56#include "ui/gfx/skia_util.h"
57#include "ui/gl/gl_switches.h"
58#include "ui/surface/transport_dib.h"
59#include "webkit/glue/cursor_utils.h"
60#include "webkit/glue/webkit_glue.h"
61#include "webkit/plugins/npapi/webplugin.h"
62#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
63#include "webkit/renderer/compositor_bindings/web_rendering_stats_impl.h"
64
65#if defined(OS_ANDROID)
66#include "content/renderer/android/synchronous_compositor_factory.h"
67#endif
68
69#if defined(OS_POSIX)
70#include "ipc/ipc_channel_posix.h"
71#include "third_party/skia/include/core/SkMallocPixelRef.h"
72#include "third_party/skia/include/core/SkPixelRef.h"
73#endif  // defined(OS_POSIX)
74
75#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
76
77using WebKit::WebCompositionUnderline;
78using WebKit::WebCursorInfo;
79using WebKit::WebGestureEvent;
80using WebKit::WebInputEvent;
81using WebKit::WebMouseEvent;
82using WebKit::WebNavigationPolicy;
83using WebKit::WebPagePopup;
84using WebKit::WebPoint;
85using WebKit::WebPopupMenu;
86using WebKit::WebPopupMenuInfo;
87using WebKit::WebPopupType;
88using WebKit::WebRange;
89using WebKit::WebRect;
90using WebKit::WebScreenInfo;
91using WebKit::WebSize;
92using WebKit::WebTextDirection;
93using WebKit::WebTouchEvent;
94using WebKit::WebVector;
95using WebKit::WebWidget;
96
97namespace {
98const char* GetEventName(WebInputEvent::Type type) {
99#define CASE_TYPE(t) case WebInputEvent::t:  return #t
100  switch(type) {
101    CASE_TYPE(Undefined);
102    CASE_TYPE(MouseDown);
103    CASE_TYPE(MouseUp);
104    CASE_TYPE(MouseMove);
105    CASE_TYPE(MouseEnter);
106    CASE_TYPE(MouseLeave);
107    CASE_TYPE(ContextMenu);
108    CASE_TYPE(MouseWheel);
109    CASE_TYPE(RawKeyDown);
110    CASE_TYPE(KeyDown);
111    CASE_TYPE(KeyUp);
112    CASE_TYPE(Char);
113    CASE_TYPE(GestureScrollBegin);
114    CASE_TYPE(GestureScrollEnd);
115    CASE_TYPE(GestureScrollUpdate);
116    CASE_TYPE(GestureFlingStart);
117    CASE_TYPE(GestureFlingCancel);
118    CASE_TYPE(GestureTap);
119    CASE_TYPE(GestureTapUnconfirmed);
120    CASE_TYPE(GestureTapDown);
121    CASE_TYPE(GestureTapCancel);
122    CASE_TYPE(GestureDoubleTap);
123    CASE_TYPE(GestureTwoFingerTap);
124    CASE_TYPE(GestureLongPress);
125    CASE_TYPE(GestureLongTap);
126    CASE_TYPE(GesturePinchBegin);
127    CASE_TYPE(GesturePinchEnd);
128    CASE_TYPE(GesturePinchUpdate);
129    CASE_TYPE(TouchStart);
130    CASE_TYPE(TouchMove);
131    CASE_TYPE(TouchEnd);
132    CASE_TYPE(TouchCancel);
133    default:
134      // Must include default to let WebKit::WebInputEvent add new event types
135      // before they're added here.
136      DLOG(WARNING) << "Unhandled WebInputEvent type in GetEventName.\n";
137      break;
138  }
139#undef CASE_TYPE
140  return "";
141}
142}
143namespace content {
144
145RenderWidget::RenderWidget(WebKit::WebPopupType popup_type,
146                           const WebKit::WebScreenInfo& screen_info,
147                           bool swapped_out)
148    : routing_id_(MSG_ROUTING_NONE),
149      surface_id_(0),
150      webwidget_(NULL),
151      opener_id_(MSG_ROUTING_NONE),
152      init_complete_(false),
153      current_paint_buf_(NULL),
154      overdraw_bottom_height_(0.f),
155      next_paint_flags_(0),
156      filtered_time_per_frame_(0.0f),
157      update_reply_pending_(false),
158      auto_resize_mode_(false),
159      need_update_rect_for_auto_resize_(false),
160      using_asynchronous_swapbuffers_(false),
161      num_swapbuffers_complete_pending_(0),
162      did_show_(false),
163      is_hidden_(false),
164      is_fullscreen_(false),
165      needs_repainting_on_restore_(false),
166      has_focus_(false),
167      handling_input_event_(false),
168      handling_ime_event_(false),
169      closing_(false),
170      is_swapped_out_(swapped_out),
171      input_method_is_active_(false),
172      text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
173      can_compose_inline_(true),
174      popup_type_(popup_type),
175      pending_window_rect_count_(0),
176      suppress_next_char_events_(false),
177      is_accelerated_compositing_active_(false),
178      animation_update_pending_(false),
179      invalidation_task_posted_(false),
180      screen_info_(screen_info),
181      device_scale_factor_(screen_info_.deviceScaleFactor),
182      is_threaded_compositing_enabled_(false),
183      overscroll_notifications_enabled_(false),
184      weak_ptr_factory_(this) {
185  if (!swapped_out)
186    RenderProcess::current()->AddRefProcess();
187  DCHECK(RenderThread::Get());
188  has_disable_gpu_vsync_switch_ = CommandLine::ForCurrentProcess()->HasSwitch(
189      switches::kDisableGpuVsync);
190  is_threaded_compositing_enabled_ =
191      CommandLine::ForCurrentProcess()->HasSwitch(
192          switches::kEnableThreadedCompositing);
193  overscroll_notifications_enabled_ =
194      CommandLine::ForCurrentProcess()->HasSwitch(
195          switches::kEnableOverscrollNotifications);
196}
197
198RenderWidget::~RenderWidget() {
199  DCHECK(!webwidget_) << "Leaking our WebWidget!";
200  STLDeleteElements(&updates_pending_swap_);
201  if (current_paint_buf_) {
202    RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
203    current_paint_buf_ = NULL;
204  }
205  // If we are swapped out, we have released already.
206  if (!is_swapped_out_)
207    RenderProcess::current()->ReleaseProcess();
208}
209
210// static
211RenderWidget* RenderWidget::Create(int32 opener_id,
212                                   WebKit::WebPopupType popup_type,
213                                   const WebKit::WebScreenInfo& screen_info) {
214  DCHECK(opener_id != MSG_ROUTING_NONE);
215  scoped_refptr<RenderWidget> widget(
216      new RenderWidget(popup_type, screen_info, false));
217  if (widget->Init(opener_id)) {  // adds reference on success.
218    return widget.get();
219  }
220  return NULL;
221}
222
223// static
224WebWidget* RenderWidget::CreateWebWidget(RenderWidget* render_widget) {
225  switch (render_widget->popup_type_) {
226    case WebKit::WebPopupTypeNone:  // Nothing to create.
227      break;
228    case WebKit::WebPopupTypeSelect:
229    case WebKit::WebPopupTypeSuggestion:
230      return WebPopupMenu::create(render_widget);
231    case WebKit::WebPopupTypePage:
232      return WebPagePopup::create(render_widget);
233    case WebKit::WebPopupTypeHelperPlugin:
234      return WebKit::WebHelperPlugin::create(render_widget);
235    default:
236      NOTREACHED();
237  }
238  return NULL;
239}
240
241bool RenderWidget::Init(int32 opener_id) {
242  return DoInit(opener_id,
243                RenderWidget::CreateWebWidget(this),
244                new ViewHostMsg_CreateWidget(opener_id, popup_type_,
245                                             &routing_id_, &surface_id_));
246}
247
248bool RenderWidget::DoInit(int32 opener_id,
249                          WebWidget* web_widget,
250                          IPC::SyncMessage* create_widget_message) {
251  DCHECK(!webwidget_);
252
253  if (opener_id != MSG_ROUTING_NONE)
254    opener_id_ = opener_id;
255
256  webwidget_ = web_widget;
257
258  bool result = RenderThread::Get()->Send(create_widget_message);
259  if (result) {
260    RenderThread::Get()->AddRoute(routing_id_, this);
261    // Take a reference on behalf of the RenderThread.  This will be balanced
262    // when we receive ViewMsg_Close.
263    AddRef();
264    return true;
265  } else {
266    // The above Send can fail when the tab is closing.
267    return false;
268  }
269}
270
271// This is used to complete pending inits and non-pending inits.
272void RenderWidget::CompleteInit() {
273  DCHECK(routing_id_ != MSG_ROUTING_NONE);
274
275  init_complete_ = true;
276
277  if (webwidget_ && is_threaded_compositing_enabled_) {
278    webwidget_->enterForceCompositingMode(true);
279  }
280  if (compositor_) {
281    compositor_->setSurfaceReady();
282  }
283  DoDeferredUpdate();
284
285  Send(new ViewHostMsg_RenderViewReady(routing_id_));
286}
287
288void RenderWidget::SetSwappedOut(bool is_swapped_out) {
289  // We should only toggle between states.
290  DCHECK(is_swapped_out_ != is_swapped_out);
291  is_swapped_out_ = is_swapped_out;
292
293  // If we are swapping out, we will call ReleaseProcess, allowing the process
294  // to exit if all of its RenderViews are swapped out.  We wait until the
295  // WasSwappedOut call to do this, to avoid showing the sad tab.
296  // If we are swapping in, we call AddRefProcess to prevent the process from
297  // exiting.
298  if (!is_swapped_out)
299    RenderProcess::current()->AddRefProcess();
300}
301
302bool RenderWidget::AllowPartialSwap() const {
303  return true;
304}
305
306bool RenderWidget::UsingSynchronousRendererCompositor() const {
307#if defined(OS_ANDROID)
308  return SynchronousCompositorFactory::GetInstance() != NULL;
309#else
310  return false;
311#endif
312}
313
314bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
315  bool handled = true;
316  IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
317    IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
318    IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange,
319                        OnCursorVisibilityChange)
320    IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
321    IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
322    IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
323    IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
324    IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
325    IPC_MESSAGE_HANDLER(ViewMsg_ChangeResizeRect, OnChangeResizeRect)
326    IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
327    IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown)
328    IPC_MESSAGE_HANDLER(ViewMsg_WasSwappedOut, OnWasSwappedOut)
329    IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
330    IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK,
331                        OnViewContextSwapBuffersComplete)
332    IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive)
333    IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
334    IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition)
335    IPC_MESSAGE_HANDLER(ViewMsg_PaintAtSize, OnPaintAtSize)
336    IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnRepaint)
337    IPC_MESSAGE_HANDLER(ViewMsg_SmoothScrollCompleted, OnSmoothScrollCompleted)
338    IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
339    IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
340    IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects)
341#if defined(OS_ANDROID)
342    IPC_MESSAGE_HANDLER(ViewMsg_ImeBatchStateChanged, OnImeBatchStateChanged)
343    IPC_MESSAGE_HANDLER(ViewMsg_ShowImeIfNeeded, OnShowImeIfNeeded)
344#endif
345    IPC_MESSAGE_HANDLER(ViewMsg_Snapshot, OnSnapshot)
346    IPC_MESSAGE_HANDLER(ViewMsg_SetBrowserRenderingStats,
347                        OnSetBrowserRenderingStats)
348    IPC_MESSAGE_UNHANDLED(handled = false)
349  IPC_END_MESSAGE_MAP()
350  return handled;
351}
352
353bool RenderWidget::Send(IPC::Message* message) {
354  // Don't send any messages after the browser has told us to close, and filter
355  // most outgoing messages while swapped out.
356  if ((is_swapped_out_ &&
357       !SwappedOutMessages::CanSendWhileSwappedOut(message)) ||
358      closing_) {
359    delete message;
360    return false;
361  }
362
363  // If given a messsage without a routing ID, then assign our routing ID.
364  if (message->routing_id() == MSG_ROUTING_NONE)
365    message->set_routing_id(routing_id_);
366
367  return RenderThread::Get()->Send(message);
368}
369
370void RenderWidget::Resize(const gfx::Size& new_size,
371                          const gfx::Size& physical_backing_size,
372                          float overdraw_bottom_height,
373                          const gfx::Rect& resizer_rect,
374                          bool is_fullscreen,
375                          ResizeAck resize_ack) {
376  if (!RenderThreadImpl::current() ||  // Will be NULL during unit tests.
377      !RenderThreadImpl::current()->layout_test_mode()) {
378    // A resize ack shouldn't be requested if we have not ACK'd the previous
379    // one.
380    DCHECK(resize_ack != SEND_RESIZE_ACK || !next_paint_is_resize_ack());
381    DCHECK(resize_ack == SEND_RESIZE_ACK || resize_ack == NO_RESIZE_ACK);
382  }
383
384  // Ignore this during shutdown.
385  if (!webwidget_)
386    return;
387
388  if (compositor_) {
389    compositor_->setViewportSize(new_size, physical_backing_size);
390    compositor_->SetOverdrawBottomHeight(overdraw_bottom_height);
391  }
392
393  physical_backing_size_ = physical_backing_size;
394  overdraw_bottom_height_ = overdraw_bottom_height;
395  resizer_rect_ = resizer_rect;
396
397  // NOTE: We may have entered fullscreen mode without changing our size.
398  bool fullscreen_change = is_fullscreen_ != is_fullscreen;
399  if (fullscreen_change)
400    WillToggleFullscreen();
401  is_fullscreen_ = is_fullscreen;
402
403  if (size_ != new_size) {
404    // TODO(darin): We should not need to reset this here.
405    needs_repainting_on_restore_ = false;
406
407    size_ = new_size;
408
409    paint_aggregator_.ClearPendingUpdate();
410
411    // When resizing, we want to wait to paint before ACK'ing the resize.  This
412    // ensures that we only resize as fast as we can paint.  We only need to
413    // send an ACK if we are resized to a non-empty rect.
414    webwidget_->resize(new_size);
415
416    if (!RenderThreadImpl::current() ||  // Will be NULL during unit tests.
417        !RenderThreadImpl::current()->layout_test_mode()) {
418      // Resize should have caused an invalidation of the entire view.
419      DCHECK(new_size.IsEmpty() || is_accelerated_compositing_active_ ||
420             paint_aggregator_.HasPendingUpdate());
421    }
422  } else if (!RenderThreadImpl::current() ||  // Will be NULL during unit tests.
423             !RenderThreadImpl::current()->layout_test_mode()) {
424    resize_ack = NO_RESIZE_ACK;
425  }
426
427  if (new_size.IsEmpty() || physical_backing_size.IsEmpty()) {
428    // For empty size or empty physical_backing_size, there is no next paint
429    // (along with which to send the ack) until they are set to non-empty.
430    resize_ack = NO_RESIZE_ACK;
431  }
432
433  // Send the Resize_ACK flag once we paint again if requested.
434  if (resize_ack == SEND_RESIZE_ACK)
435    set_next_paint_is_resize_ack();
436
437  if (fullscreen_change)
438    DidToggleFullscreen();
439
440  // If a resize ack is requested and it isn't set-up, then no more resizes will
441  // come in and in general things will go wrong.
442  DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack());
443}
444
445void RenderWidget::OnClose() {
446  if (closing_)
447    return;
448  closing_ = true;
449
450  // Browser correspondence is no longer needed at this point.
451  if (routing_id_ != MSG_ROUTING_NONE) {
452    RenderThread::Get()->RemoveRoute(routing_id_);
453    SetHidden(false);
454  }
455
456  // If there is a Send call on the stack, then it could be dangerous to close
457  // now.  Post a task that only gets invoked when there are no nested message
458  // loops.
459  base::MessageLoop::current()->PostNonNestableTask(
460      FROM_HERE, base::Bind(&RenderWidget::Close, this));
461
462  // Balances the AddRef taken when we called AddRoute.
463  Release();
464}
465
466// Got a response from the browser after the renderer decided to create a new
467// view.
468void RenderWidget::OnCreatingNewAck() {
469  DCHECK(routing_id_ != MSG_ROUTING_NONE);
470
471  CompleteInit();
472}
473
474void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) {
475  screen_info_ = params.screen_info;
476  SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
477  Resize(params.new_size, params.physical_backing_size,
478         params.overdraw_bottom_height, params.resizer_rect,
479         params.is_fullscreen, SEND_RESIZE_ACK);
480}
481
482void RenderWidget::OnChangeResizeRect(const gfx::Rect& resizer_rect) {
483  if (resizer_rect_ != resizer_rect) {
484    gfx::Rect view_rect(size_);
485
486    gfx::Rect old_damage_rect = gfx::IntersectRects(view_rect, resizer_rect_);
487    if (!old_damage_rect.IsEmpty())
488      paint_aggregator_.InvalidateRect(old_damage_rect);
489
490    gfx::Rect new_damage_rect = gfx::IntersectRects(view_rect, resizer_rect);
491    if (!new_damage_rect.IsEmpty())
492      paint_aggregator_.InvalidateRect(new_damage_rect);
493
494    resizer_rect_ = resizer_rect;
495
496    if (webwidget_)
497      webwidget_->didChangeWindowResizerRect();
498  }
499}
500
501void RenderWidget::OnWasHidden() {
502  TRACE_EVENT0("renderer", "RenderWidget::OnWasHidden");
503  // Go into a mode where we stop generating paint and scrolling events.
504  SetHidden(true);
505}
506
507void RenderWidget::OnWasShown(bool needs_repainting) {
508  TRACE_EVENT0("renderer", "RenderWidget::OnWasShown");
509  // During shutdown we can just ignore this message.
510  if (!webwidget_)
511    return;
512
513  // See OnWasHidden
514  SetHidden(false);
515
516  if (!needs_repainting && !needs_repainting_on_restore_)
517    return;
518  needs_repainting_on_restore_ = false;
519
520  // Tag the next paint as a restore ack, which is picked up by
521  // DoDeferredUpdate when it sends out the next PaintRect message.
522  set_next_paint_is_restore_ack();
523
524  // Generate a full repaint.
525  if (!is_accelerated_compositing_active_) {
526    didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
527  } else {
528    scheduleComposite();
529  }
530}
531
532void RenderWidget::OnWasSwappedOut() {
533  // If we have been swapped out and no one else is using this process,
534  // it's safe to exit now.  If we get swapped back in, we will call
535  // AddRefProcess in SetSwappedOut.
536  if (is_swapped_out_)
537    RenderProcess::current()->ReleaseProcess();
538}
539
540void RenderWidget::OnRequestMoveAck() {
541  DCHECK(pending_window_rect_count_);
542  pending_window_rect_count_--;
543}
544
545void RenderWidget::OnUpdateRectAck() {
546  TRACE_EVENT0("renderer", "RenderWidget::OnUpdateRectAck");
547  DCHECK(update_reply_pending_);
548  update_reply_pending_ = false;
549
550  // If we sent an UpdateRect message with a zero-sized bitmap, then we should
551  // have no current paint buffer.
552  if (current_paint_buf_) {
553    RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
554    current_paint_buf_ = NULL;
555  }
556
557  // If swapbuffers is still pending, then defer the update until the
558  // swapbuffers occurs.
559  if (num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
560    TRACE_EVENT0("renderer", "EarlyOut_SwapStillPending");
561    return;
562  }
563
564  // Notify subclasses that software rendering was flushed to the screen.
565  if (!is_accelerated_compositing_active_) {
566    DidFlushPaint();
567  }
568
569  // Continue painting if necessary...
570  DoDeferredUpdateAndSendInputAck();
571}
572
573bool RenderWidget::SupportsAsynchronousSwapBuffers() {
574  // Contexts using the command buffer support asynchronous swapbuffers.
575  // See RenderWidget::CreateOutputSurface().
576  if (RenderThreadImpl::current()->compositor_message_loop_proxy())
577    return false;
578
579  return true;
580}
581
582GURL RenderWidget::GetURLForGraphicsContext3D() {
583  return GURL();
584}
585
586bool RenderWidget::ForceCompositingModeEnabled() {
587  return false;
588}
589
590scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface() {
591  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
592
593#if defined(OS_ANDROID)
594   if (SynchronousCompositorFactory* factory =
595       SynchronousCompositorFactory::GetInstance()) {
596    return factory->CreateOutputSurface(routing_id());
597  }
598#endif
599
600  if (command_line.HasSwitch(switches::kEnableSoftwareCompositingGLAdapter)) {
601      return scoped_ptr<cc::OutputSurface>(
602          new CompositorOutputSurface(routing_id(), NULL,
603              new CompositorSoftwareOutputDevice(), true));
604  }
605
606  // Explicitly disable antialiasing for the compositor. As of the time of
607  // this writing, the only platform that supported antialiasing for the
608  // compositor was Mac OS X, because the on-screen OpenGL context creation
609  // code paths on Windows and Linux didn't yet have multisampling support.
610  // Mac OS X essentially always behaves as though it's rendering offscreen.
611  // Multisampling has a heavy cost especially on devices with relatively low
612  // fill rate like most notebooks, and the Mac implementation would need to
613  // be optimized to resolve directly into the IOSurface shared between the
614  // GPU and browser processes. For these reasons and to avoid platform
615  // disparities we explicitly disable antialiasing.
616  WebKit::WebGraphicsContext3D::Attributes attributes;
617  attributes.antialias = false;
618  attributes.shareResources = true;
619  attributes.noAutomaticFlushes = true;
620  attributes.depth = false;
621  attributes.stencil = false;
622  if (command_line.HasSwitch(cc::switches::kForceDirectLayerDrawing))
623    attributes.stencil = true;
624  WebGraphicsContext3DCommandBufferImpl* context =
625      CreateGraphicsContext3D(attributes);
626  if (!context)
627    return scoped_ptr<cc::OutputSurface>();
628
629  if (command_line.HasSwitch(switches::kEnableDelegatedRenderer)) {
630    DCHECK(is_threaded_compositing_enabled_);
631    return scoped_ptr<cc::OutputSurface>(
632        new DelegatedCompositorOutputSurface(routing_id(), context, NULL));
633  }
634  if (command_line.HasSwitch(cc::switches::kCompositeToMailbox)) {
635    DCHECK(is_threaded_compositing_enabled_);
636    return scoped_ptr<cc::OutputSurface>(
637        new MailboxOutputSurface(routing_id(), context, NULL));
638  }
639  return scoped_ptr<cc::OutputSurface>(
640      new CompositorOutputSurface(routing_id(), context, NULL, false));
641}
642
643void RenderWidget::OnViewContextSwapBuffersAborted() {
644  TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersAborted");
645  while (!updates_pending_swap_.empty()) {
646    ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front();
647    updates_pending_swap_.pop_front();
648    // msg can be NULL if the swap doesn't correspond to an DoDeferredUpdate
649    // compositing pass, hence doesn't require an UpdateRect message.
650    if (msg)
651      Send(msg);
652  }
653  num_swapbuffers_complete_pending_ = 0;
654  using_asynchronous_swapbuffers_ = false;
655  // Schedule another frame so the compositor learns about it.
656  scheduleComposite();
657}
658
659void RenderWidget::OnViewContextSwapBuffersPosted() {
660  TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersPosted");
661
662  if (using_asynchronous_swapbuffers_) {
663    ViewHostMsg_UpdateRect* msg = NULL;
664    // pending_update_params_ can be NULL if the swap doesn't correspond to an
665    // DoDeferredUpdate compositing pass, hence doesn't require an UpdateRect
666    // message.
667    if (pending_update_params_) {
668      msg = new ViewHostMsg_UpdateRect(routing_id_, *pending_update_params_);
669      pending_update_params_.reset();
670    }
671    updates_pending_swap_.push_back(msg);
672    num_swapbuffers_complete_pending_++;
673  }
674}
675
676void RenderWidget::OnViewContextSwapBuffersComplete() {
677  TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete");
678
679  // Notify subclasses that composited rendering was flushed to the screen.
680  DidFlushPaint();
681
682  // When compositing deactivates, we reset the swapbuffers pending count.  The
683  // swapbuffers acks may still arrive, however.
684  if (num_swapbuffers_complete_pending_ == 0) {
685    TRACE_EVENT0("renderer", "EarlyOut_ZeroSwapbuffersPending");
686    return;
687  }
688  DCHECK(!updates_pending_swap_.empty());
689  ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front();
690  updates_pending_swap_.pop_front();
691  // msg can be NULL if the swap doesn't correspond to an DoDeferredUpdate
692  // compositing pass, hence doesn't require an UpdateRect message.
693  if (msg)
694    Send(msg);
695  num_swapbuffers_complete_pending_--;
696
697  // If update reply is still pending, then defer the update until that reply
698  // occurs.
699  if (update_reply_pending_) {
700    TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
701    return;
702  }
703
704  // If we are not accelerated rendering, then this is a stale swapbuffers from
705  // when we were previously rendering. However, if an invalidation task is not
706  // posted, there may be software rendering work pending. In that case, don't
707  // early out.
708  if (!is_accelerated_compositing_active_ && invalidation_task_posted_) {
709    TRACE_EVENT0("renderer", "EarlyOut_AcceleratedCompositingOff");
710    return;
711  }
712
713  // Do not call DoDeferredUpdate unless there's animation work to be done or
714  // a real invalidation. This prevents rendering in response to a swapbuffers
715  // callback coming back after we've navigated away from the page that
716  // generated it.
717  if (!animation_update_pending_ && !paint_aggregator_.HasPendingUpdate()) {
718    TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate");
719    return;
720  }
721
722  // Continue painting if necessary...
723  DoDeferredUpdateAndSendInputAck();
724}
725
726void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
727                                      const ui::LatencyInfo& latency_info,
728                                      bool is_keyboard_shortcut) {
729  handling_input_event_ = true;
730  if (!input_event) {
731    handling_input_event_ = false;
732    return;
733  }
734
735  const char* const event_name = GetEventName(input_event->type);
736  TRACE_EVENT1("renderer", "RenderWidget::OnHandleInputEvent",
737               "event", event_name);
738
739  if (compositor_)
740    compositor_->SetLatencyInfo(latency_info);
741  else
742    latency_info_.MergeWith(latency_info);
743
744  base::TimeDelta now = base::TimeDelta::FromInternalValue(
745      base::TimeTicks::Now().ToInternalValue());
746
747  int64 delta = static_cast<int64>(
748      (now.InSecondsF() - input_event->timeStampSeconds) *
749          base::Time::kMicrosecondsPerSecond);
750  UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Renderer", delta, 0, 1000000, 100);
751  base::HistogramBase* counter_for_type =
752      base::Histogram::FactoryGet(
753          base::StringPrintf("Event.Latency.Renderer.%s", event_name),
754          0,
755          1000000,
756          100,
757          base::HistogramBase::kUmaTargetedHistogramFlag);
758  counter_for_type->Add(delta);
759
760  bool prevent_default = false;
761  if (WebInputEvent::isMouseEventType(input_event->type)) {
762    const WebMouseEvent& mouse_event =
763        *static_cast<const WebMouseEvent*>(input_event);
764    TRACE_EVENT2("renderer", "HandleMouseMove",
765                 "x", mouse_event.x, "y", mouse_event.y);
766    prevent_default = WillHandleMouseEvent(mouse_event);
767  }
768
769  if (WebInputEvent::isGestureEventType(input_event->type)) {
770    const WebGestureEvent& gesture_event =
771        *static_cast<const WebGestureEvent*>(input_event);
772    prevent_default = prevent_default || WillHandleGestureEvent(gesture_event);
773  }
774
775  if (input_event->type == WebInputEvent::GestureTap ||
776      input_event->type == WebInputEvent::GestureLongPress)
777    resetInputMethod();
778
779  bool processed = prevent_default;
780  if (input_event->type != WebInputEvent::Char || !suppress_next_char_events_) {
781    suppress_next_char_events_ = false;
782    if (!processed && webwidget_)
783      processed = webwidget_->handleInputEvent(*input_event);
784  }
785
786  // If this RawKeyDown event corresponds to a browser keyboard shortcut and
787  // it's not processed by webkit, then we need to suppress the upcoming Char
788  // events.
789  if (!processed && is_keyboard_shortcut)
790    suppress_next_char_events_ = true;
791
792  InputEventAckState ack_result = processed ?
793      INPUT_EVENT_ACK_STATE_CONSUMED : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
794  if (!processed &&  input_event->type == WebInputEvent::TouchStart) {
795    const WebTouchEvent& touch_event =
796        *static_cast<const WebTouchEvent*>(input_event);
797    ack_result = HasTouchEventHandlersAt(touch_event.touches[0].position) ?
798        INPUT_EVENT_ACK_STATE_NOT_CONSUMED :
799        INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
800  }
801
802  IPC::Message* response =
803      new InputHostMsg_HandleInputEvent_ACK(routing_id_, input_event->type,
804                                                ack_result);
805  bool event_type_gets_rate_limited =
806      input_event->type == WebInputEvent::MouseMove ||
807      input_event->type == WebInputEvent::MouseWheel ||
808      WebInputEvent::isTouchEventType(input_event->type);
809
810  bool frame_pending = paint_aggregator_.HasPendingUpdate();
811  if (is_accelerated_compositing_active_) {
812    frame_pending = compositor_ &&
813                    compositor_->commitRequested();
814  }
815
816  if (event_type_gets_rate_limited && frame_pending && !is_hidden_) {
817    // We want to rate limit the input events in this case, so we'll wait for
818    // painting to finish before ACKing this message.
819    if (pending_input_event_ack_) {
820      // As two different kinds of events could cause us to postpone an ack
821      // we send it now, if we have one pending. The Browser should never
822      // send us the same kind of event we are delaying the ack for.
823      Send(pending_input_event_ack_.release());
824    }
825    pending_input_event_ack_.reset(response);
826  } else {
827    Send(response);
828  }
829
830#if defined(OS_ANDROID)
831  // Allow the IME to be shown when the focus changes as a consequence
832  // of a processed touch end event.
833  if (input_event->type == WebInputEvent::TouchEnd && processed)
834    UpdateTextInputState(SHOW_IME_IF_NEEDED);
835#endif
836
837  handling_input_event_ = false;
838
839  if (!prevent_default) {
840    if (WebInputEvent::isKeyboardEventType(input_event->type))
841      DidHandleKeyEvent();
842    if (WebInputEvent::isMouseEventType(input_event->type))
843      DidHandleMouseEvent(*(static_cast<const WebMouseEvent*>(input_event)));
844    if (WebInputEvent::isTouchEventType(input_event->type))
845      DidHandleTouchEvent(*(static_cast<const WebTouchEvent*>(input_event)));
846  }
847}
848
849void RenderWidget::OnCursorVisibilityChange(bool is_visible) {
850  if (webwidget_)
851    webwidget_->setCursorVisibilityState(is_visible);
852}
853
854void RenderWidget::OnMouseCaptureLost() {
855  if (webwidget_)
856    webwidget_->mouseCaptureLost();
857}
858
859void RenderWidget::OnSetFocus(bool enable) {
860  has_focus_ = enable;
861  if (webwidget_)
862    webwidget_->setFocus(enable);
863}
864
865void RenderWidget::ClearFocus() {
866  // We may have got the focus from the browser before this gets processed, in
867  // which case we do not want to unfocus ourself.
868  if (!has_focus_ && webwidget_)
869    webwidget_->setFocus(false);
870}
871
872void RenderWidget::PaintRect(const gfx::Rect& rect,
873                             const gfx::Point& canvas_origin,
874                             skia::PlatformCanvas* canvas) {
875  TRACE_EVENT2("renderer", "PaintRect",
876               "width", rect.width(), "height", rect.height());
877
878  const bool kEnableGpuBenchmarking =
879      CommandLine::ForCurrentProcess()->HasSwitch(
880          switches::kEnableGpuBenchmarking);
881  canvas->save();
882
883  // Bring the canvas into the coordinate system of the paint rect.
884  canvas->translate(static_cast<SkScalar>(-canvas_origin.x()),
885                    static_cast<SkScalar>(-canvas_origin.y()));
886
887  // If there is a custom background, tile it.
888  if (!background_.empty()) {
889    SkPaint paint;
890    skia::RefPtr<SkShader> shader = skia::AdoptRef(
891        SkShader::CreateBitmapShader(background_,
892                                     SkShader::kRepeat_TileMode,
893                                     SkShader::kRepeat_TileMode));
894    paint.setShader(shader.get());
895
896    // Use kSrc_Mode to handle background_ transparency properly.
897    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
898
899    // Canvas could contain multiple update rects. Clip to given rect so that
900    // we don't accidentally clear other update rects.
901    canvas->save();
902    canvas->scale(device_scale_factor_, device_scale_factor_);
903    canvas->clipRect(gfx::RectToSkRect(rect));
904    canvas->drawPaint(paint);
905    canvas->restore();
906  }
907
908  // First see if this rect is a plugin that can paint itself faster.
909  TransportDIB* optimized_dib = NULL;
910  gfx::Rect optimized_copy_rect, optimized_copy_location;
911  float dib_scale_factor;
912  webkit::ppapi::PluginInstance* optimized_instance =
913      GetBitmapForOptimizedPluginPaint(rect, &optimized_dib,
914                                       &optimized_copy_location,
915                                       &optimized_copy_rect,
916                                       &dib_scale_factor);
917  if (optimized_instance) {
918    // This plugin can be optimize-painted and we can just ask it to paint
919    // itself. We don't actually need the TransportDIB in this case.
920    //
921    // This is an optimization for PPAPI plugins that know they're on top of
922    // the page content. If this rect is inside such a plugin, we can save some
923    // time and avoid re-rendering the page content which we know will be
924    // covered by the plugin later (this time can be significant, especially
925    // for a playing movie that is invalidating a lot).
926    //
927    // In the plugin movie case, hopefully the similar call to
928    // GetBitmapForOptimizedPluginPaint in DoDeferredUpdate handles the
929    // painting, because that avoids copying the plugin image to a different
930    // paint rect. Unfortunately, if anything on the page is animating other
931    // than the movie, it break this optimization since the union of the
932    // invalid regions will be larger than the plugin.
933    //
934    // This code optimizes that case, where we can still avoid painting in
935    // WebKit and filling the background (which can be slow) and just painting
936    // the plugin. Unlike the DoDeferredUpdate case, an extra copy is still
937    // required.
938    base::TimeTicks paint_begin_ticks;
939    if (kEnableGpuBenchmarking)
940      paint_begin_ticks = base::TimeTicks::HighResNow();
941
942    SkAutoCanvasRestore auto_restore(canvas, true);
943    canvas->scale(device_scale_factor_, device_scale_factor_);
944    optimized_instance->Paint(webkit_glue::ToWebCanvas(canvas),
945                              optimized_copy_location, rect);
946    canvas->restore();
947    if (kEnableGpuBenchmarking) {
948      base::TimeDelta paint_time =
949          base::TimeTicks::HighResNow() - paint_begin_ticks;
950      if (!is_accelerated_compositing_active_)
951        software_stats_.total_paint_time += paint_time;
952    }
953  } else {
954    // Normal painting case.
955    base::TimeTicks paint_begin_ticks;
956    if (kEnableGpuBenchmarking)
957      paint_begin_ticks = base::TimeTicks::HighResNow();
958
959    webwidget_->paint(webkit_glue::ToWebCanvas(canvas), rect);
960
961    if (kEnableGpuBenchmarking) {
962      base::TimeDelta paint_time =
963          base::TimeTicks::HighResNow() - paint_begin_ticks;
964      if (!is_accelerated_compositing_active_)
965        software_stats_.total_paint_time += paint_time;
966    }
967
968    // Flush to underlying bitmap.  TODO(darin): is this needed?
969    skia::GetTopDevice(*canvas)->accessBitmap(false);
970  }
971
972  PaintDebugBorder(rect, canvas);
973  canvas->restore();
974
975  if (kEnableGpuBenchmarking) {
976    int64 num_pixels_processed = rect.width() * rect.height();
977    software_stats_.total_pixels_painted += num_pixels_processed;
978  }
979}
980
981void RenderWidget::PaintDebugBorder(const gfx::Rect& rect,
982                                    skia::PlatformCanvas* canvas) {
983  static bool kPaintBorder =
984      CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowPaintRects);
985  if (!kPaintBorder)
986    return;
987
988  // Cycle through these colors to help distinguish new paint rects.
989  const SkColor colors[] = {
990    SkColorSetARGB(0x3F, 0xFF, 0, 0),
991    SkColorSetARGB(0x3F, 0xFF, 0, 0xFF),
992    SkColorSetARGB(0x3F, 0, 0, 0xFF),
993  };
994  static int color_selector = 0;
995
996  SkPaint paint;
997  paint.setStyle(SkPaint::kStroke_Style);
998  paint.setColor(colors[color_selector++ % arraysize(colors)]);
999  paint.setStrokeWidth(1);
1000
1001  SkIRect irect;
1002  irect.set(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1);
1003  canvas->drawIRect(irect, paint);
1004}
1005
1006void RenderWidget::AnimationCallback() {
1007  TRACE_EVENT0("renderer", "RenderWidget::AnimationCallback");
1008  if (!animation_update_pending_) {
1009    TRACE_EVENT0("renderer", "EarlyOut_NoAnimationUpdatePending");
1010    return;
1011  }
1012  if (!animation_floor_time_.is_null() && IsRenderingVSynced()) {
1013    // Record when we fired (according to base::Time::Now()) relative to when
1014    // we posted the task to quantify how much the base::Time/base::TimeTicks
1015    // skew is affecting animations.
1016    base::TimeDelta animation_callback_delay = base::Time::Now() -
1017        (animation_floor_time_ - base::TimeDelta::FromMilliseconds(16));
1018    UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.AnimationCallbackDelayTime",
1019                               animation_callback_delay,
1020                               base::TimeDelta::FromMilliseconds(0),
1021                               base::TimeDelta::FromMilliseconds(30),
1022                               25);
1023  }
1024  DoDeferredUpdateAndSendInputAck();
1025}
1026
1027void RenderWidget::AnimateIfNeeded() {
1028  if (!animation_update_pending_)
1029    return;
1030
1031  // Target 60FPS if vsync is on. Go as fast as we can if vsync is off.
1032  base::TimeDelta animationInterval = IsRenderingVSynced() ?
1033      base::TimeDelta::FromMilliseconds(16) : base::TimeDelta();
1034
1035  base::Time now = base::Time::Now();
1036
1037  // animation_floor_time_ is the earliest time that we should animate when
1038  // using the dead reckoning software scheduler. If we're using swapbuffers
1039  // complete callbacks to rate limit, we can ignore this floor.
1040  if (now >= animation_floor_time_ || num_swapbuffers_complete_pending_ > 0) {
1041    TRACE_EVENT0("renderer", "RenderWidget::AnimateIfNeeded")
1042    animation_floor_time_ = now + animationInterval;
1043    // Set a timer to call us back after animationInterval before
1044    // running animation callbacks so that if a callback requests another
1045    // we'll be sure to run it at the proper time.
1046    animation_timer_.Stop();
1047    animation_timer_.Start(FROM_HERE, animationInterval, this,
1048                           &RenderWidget::AnimationCallback);
1049    animation_update_pending_ = false;
1050    if (is_accelerated_compositing_active_ && compositor_) {
1051      compositor_->Animate(base::TimeTicks::Now());
1052    } else {
1053      double frame_begin_time =
1054        (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
1055      webwidget_->animate(frame_begin_time);
1056    }
1057    return;
1058  }
1059  TRACE_EVENT0("renderer", "EarlyOut_AnimatedTooRecently");
1060  if (!animation_timer_.IsRunning()) {
1061    // This code uses base::Time::Now() to calculate the floor and next fire
1062    // time because javascript's Date object uses base::Time::Now().  The
1063    // message loop uses base::TimeTicks, which on windows can have a
1064    // different granularity than base::Time.
1065    // The upshot of all this is that this function might be called before
1066    // base::Time::Now() has advanced past the animation_floor_time_.  To
1067    // avoid exposing this delay to javascript, we keep posting delayed
1068    // tasks until base::Time::Now() has advanced far enough.
1069    base::TimeDelta delay = animation_floor_time_ - now;
1070    animation_timer_.Start(FROM_HERE, delay, this,
1071                           &RenderWidget::AnimationCallback);
1072  }
1073}
1074
1075bool RenderWidget::IsRenderingVSynced() {
1076  // TODO(nduca): Forcing a driver to disable vsync (e.g. in a control panel) is
1077  // not caught by this check. This will lead to artificially low frame rates
1078  // for people who force vsync off at a driver level and expect Chrome to speed
1079  // up.
1080  return !has_disable_gpu_vsync_switch_;
1081}
1082
1083void RenderWidget::InvalidationCallback() {
1084  TRACE_EVENT0("renderer", "RenderWidget::InvalidationCallback");
1085  invalidation_task_posted_ = false;
1086  DoDeferredUpdateAndSendInputAck();
1087}
1088
1089void RenderWidget::DoDeferredUpdateAndSendInputAck() {
1090  DoDeferredUpdate();
1091
1092  if (pending_input_event_ack_)
1093    Send(pending_input_event_ack_.release());
1094}
1095
1096void RenderWidget::DoDeferredUpdate() {
1097  TRACE_EVENT0("renderer", "RenderWidget::DoDeferredUpdate");
1098
1099  if (!webwidget_)
1100    return;
1101
1102  if (!init_complete_) {
1103    TRACE_EVENT0("renderer", "EarlyOut_InitNotComplete");
1104    return;
1105  }
1106  if (update_reply_pending_) {
1107    TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
1108    return;
1109  }
1110  if (is_accelerated_compositing_active_ &&
1111      num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
1112    TRACE_EVENT0("renderer", "EarlyOut_MaxSwapBuffersPending");
1113    return;
1114  }
1115
1116  // Suppress updating when we are hidden.
1117  if (is_hidden_ || size_.IsEmpty() || is_swapped_out_) {
1118    paint_aggregator_.ClearPendingUpdate();
1119    needs_repainting_on_restore_ = true;
1120    TRACE_EVENT0("renderer", "EarlyOut_NotVisible");
1121    return;
1122  }
1123
1124  // Tracking of frame rate jitter
1125  base::TimeTicks frame_begin_ticks = base::TimeTicks::Now();
1126  InstrumentWillBeginFrame();
1127  AnimateIfNeeded();
1128
1129  // Layout may generate more invalidation.  It may also enable the
1130  // GPU acceleration, so make sure to run layout before we send the
1131  // GpuRenderingActivated message.
1132  webwidget_->layout();
1133
1134  // Check for whether we need to track swap buffers. We need to do that after
1135  // layout() because it may have switched us to accelerated compositing.
1136  if (is_accelerated_compositing_active_)
1137    using_asynchronous_swapbuffers_ = SupportsAsynchronousSwapBuffers();
1138
1139  // The following two can result in further layout and possibly
1140  // enable GPU acceleration so they need to be called before any painting
1141  // is done.
1142  UpdateTextInputState(DO_NOT_SHOW_IME);
1143  UpdateSelectionBounds();
1144
1145  // Suppress painting if nothing is dirty.  This has to be done after updating
1146  // animations running layout as these may generate further invalidations.
1147  if (!paint_aggregator_.HasPendingUpdate()) {
1148    TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate");
1149    InstrumentDidCancelFrame();
1150    return;
1151  }
1152
1153  if (!is_accelerated_compositing_active_ &&
1154      !is_threaded_compositing_enabled_ &&
1155      ForceCompositingModeEnabled()) {
1156    webwidget_->enterForceCompositingMode(true);
1157  }
1158
1159  if (!last_do_deferred_update_time_.is_null()) {
1160    base::TimeDelta delay = frame_begin_ticks - last_do_deferred_update_time_;
1161    if (is_accelerated_compositing_active_) {
1162      UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.AccelDoDeferredUpdateDelay",
1163                                 delay,
1164                                 base::TimeDelta::FromMilliseconds(1),
1165                                 base::TimeDelta::FromMilliseconds(120),
1166                                 60);
1167    } else {
1168      UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.SoftwareDoDeferredUpdateDelay",
1169                                 delay,
1170                                 base::TimeDelta::FromMilliseconds(1),
1171                                 base::TimeDelta::FromMilliseconds(120),
1172                                 60);
1173    }
1174
1175    // Calculate filtered time per frame:
1176    float frame_time_elapsed = static_cast<float>(delay.InSecondsF());
1177    filtered_time_per_frame_ =
1178        0.9f * filtered_time_per_frame_ + 0.1f * frame_time_elapsed;
1179  }
1180  last_do_deferred_update_time_ = frame_begin_ticks;
1181
1182  if (!is_accelerated_compositing_active_) {
1183    software_stats_.animation_frame_count++;
1184    software_stats_.screen_frame_count++;
1185  }
1186
1187  // OK, save the pending update to a local since painting may cause more
1188  // invalidation.  Some WebCore rendering objects only layout when painted.
1189  PaintAggregator::PendingUpdate update;
1190  paint_aggregator_.PopPendingUpdate(&update);
1191
1192  gfx::Rect scroll_damage = update.GetScrollDamage();
1193  gfx::Rect bounds = gfx::UnionRects(update.GetPaintBounds(), scroll_damage);
1194
1195  // Notify derived classes that we're about to initiate a paint.
1196  WillInitiatePaint();
1197
1198  // A plugin may be able to do an optimized paint. First check this, in which
1199  // case we can skip all of the bitmap generation and regular paint code.
1200  // This optimization allows PPAPI plugins that declare themselves on top of
1201  // the page (like a traditional windowed plugin) to be able to animate (think
1202  // movie playing) without repeatedly re-painting the page underneath, or
1203  // copying the plugin backing store (since we can send the plugin's backing
1204  // store directly to the browser).
1205  //
1206  // This optimization only works when the entire invalid region is contained
1207  // within the plugin. There is a related optimization in PaintRect for the
1208  // case where there may be multiple invalid regions.
1209  TransportDIB* dib = NULL;
1210  gfx::Rect optimized_copy_rect, optimized_copy_location;
1211  float dib_scale_factor = 1;
1212  DCHECK(!pending_update_params_.get());
1213  pending_update_params_.reset(new ViewHostMsg_UpdateRect_Params);
1214  pending_update_params_->scroll_delta = update.scroll_delta;
1215  pending_update_params_->scroll_rect = update.scroll_rect;
1216  pending_update_params_->view_size = size_;
1217  pending_update_params_->plugin_window_moves.swap(plugin_window_moves_);
1218  pending_update_params_->flags = next_paint_flags_;
1219  pending_update_params_->scroll_offset = GetScrollOffset();
1220  pending_update_params_->needs_ack = true;
1221  pending_update_params_->scale_factor = device_scale_factor_;
1222  next_paint_flags_ = 0;
1223  need_update_rect_for_auto_resize_ = false;
1224
1225  if (!is_accelerated_compositing_active_)
1226    pending_update_params_->latency_info = latency_info_;
1227
1228  latency_info_.Clear();
1229
1230  if (update.scroll_rect.IsEmpty() &&
1231      !is_accelerated_compositing_active_ &&
1232      GetBitmapForOptimizedPluginPaint(bounds, &dib, &optimized_copy_location,
1233                                       &optimized_copy_rect,
1234                                       &dib_scale_factor)) {
1235    // Only update the part of the plugin that actually changed.
1236    optimized_copy_rect.Intersect(bounds);
1237    pending_update_params_->bitmap = dib->id();
1238    pending_update_params_->bitmap_rect = optimized_copy_location;
1239    pending_update_params_->copy_rects.push_back(optimized_copy_rect);
1240    pending_update_params_->scale_factor = dib_scale_factor;
1241  } else if (!is_accelerated_compositing_active_) {
1242    // Compute a buffer for painting and cache it.
1243
1244    bool fractional_scale = device_scale_factor_ -
1245        static_cast<int>(device_scale_factor_) != 0;
1246    if (fractional_scale) {
1247      // Damage might not be DIP aligned. Inflate damage to compensate.
1248      bounds.Inset(-1, -1);
1249      bounds.Intersect(gfx::Rect(size_));
1250    }
1251
1252    gfx::Rect pixel_bounds = gfx::ToEnclosingRect(
1253        gfx::ScaleRect(bounds, device_scale_factor_));
1254
1255    scoped_ptr<skia::PlatformCanvas> canvas(
1256        RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
1257                                                   pixel_bounds));
1258    if (!canvas) {
1259      NOTREACHED();
1260      return;
1261    }
1262
1263    // We may get back a smaller canvas than we asked for.
1264    // TODO(darin): This seems like it could cause painting problems!
1265    DCHECK_EQ(pixel_bounds.width(), canvas->getDevice()->width());
1266    DCHECK_EQ(pixel_bounds.height(), canvas->getDevice()->height());
1267    pixel_bounds.set_width(canvas->getDevice()->width());
1268    pixel_bounds.set_height(canvas->getDevice()->height());
1269    bounds.set_width(pixel_bounds.width() / device_scale_factor_);
1270    bounds.set_height(pixel_bounds.height() / device_scale_factor_);
1271
1272    HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
1273
1274    pending_update_params_->bitmap = current_paint_buf_->id();
1275    pending_update_params_->bitmap_rect = bounds;
1276
1277    std::vector<gfx::Rect>& copy_rects = pending_update_params_->copy_rects;
1278    // The scroll damage is just another rectangle to paint and copy.
1279    copy_rects.swap(update.paint_rects);
1280    if (!scroll_damage.IsEmpty())
1281      copy_rects.push_back(scroll_damage);
1282
1283    for (size_t i = 0; i < copy_rects.size(); ++i) {
1284      gfx::Rect rect = copy_rects[i];
1285      if (fractional_scale) {
1286        // Damage might not be DPI aligned.  Inflate rect to compensate.
1287        rect.Inset(-1, -1);
1288      }
1289      PaintRect(rect, pixel_bounds.origin(), canvas.get());
1290    }
1291
1292    // Software FPS tick for performance tests. The accelerated path traces the
1293    // frame events in didCommitAndDrawCompositorFrame. See throughput_tests.cc.
1294    // NOTE: Tests may break if this event is renamed or moved.
1295    UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickSW",
1296                                   TRACE_EVENT_SCOPE_THREAD);
1297  } else {  // Accelerated compositing path
1298    // Begin painting.
1299    // If painting is done via the gpu process then we don't set any damage
1300    // rects to save the browser process from doing unecessary work.
1301    pending_update_params_->bitmap_rect = bounds;
1302    pending_update_params_->scroll_rect = gfx::Rect();
1303    // We don't need an ack, because we're not sharing a DIB with the browser.
1304    // If it needs to (e.g. composited UI), the GPU process does its own ACK
1305    // with the browser for the GPU surface.
1306    pending_update_params_->needs_ack = false;
1307    Composite(frame_begin_ticks);
1308  }
1309
1310  // If we're holding a pending input event ACK, send the ACK before sending the
1311  // UpdateReply message so we can receive another input event before the
1312  // UpdateRect_ACK on platforms where the UpdateRect_ACK is sent from within
1313  // the UpdateRect IPC message handler.
1314  if (pending_input_event_ack_)
1315    Send(pending_input_event_ack_.release());
1316
1317  // If Composite() called SwapBuffers, pending_update_params_ will be reset (in
1318  // OnSwapBuffersPosted), meaning a message has been added to the
1319  // updates_pending_swap_ queue, that will be sent later. Otherwise, we send
1320  // the message now.
1321  if (pending_update_params_) {
1322    // sending an ack to browser process that the paint is complete...
1323    update_reply_pending_ = pending_update_params_->needs_ack;
1324    Send(new ViewHostMsg_UpdateRect(routing_id_, *pending_update_params_));
1325    pending_update_params_.reset();
1326  }
1327
1328  // If we're software rendering then we're done initiating the paint.
1329  if (!is_accelerated_compositing_active_)
1330    DidInitiatePaint();
1331}
1332
1333void RenderWidget::Composite(base::TimeTicks frame_begin_time) {
1334  DCHECK(is_accelerated_compositing_active_);
1335  if (compositor_)  // TODO(jamesr): Figure out how this can be null.
1336    compositor_->Composite(frame_begin_time);
1337}
1338
1339///////////////////////////////////////////////////////////////////////////////
1340// WebWidgetClient
1341
1342void RenderWidget::didInvalidateRect(const WebRect& rect) {
1343  TRACE_EVENT2("renderer", "RenderWidget::didInvalidateRect",
1344               "width", rect.width, "height", rect.height);
1345  // The invalidated rect might be outside the bounds of the view.
1346  gfx::Rect view_rect(size_);
1347  gfx::Rect damaged_rect = gfx::IntersectRects(view_rect, rect);
1348  if (damaged_rect.IsEmpty())
1349    return;
1350
1351  paint_aggregator_.InvalidateRect(damaged_rect);
1352
1353  // We may not need to schedule another call to DoDeferredUpdate.
1354  if (invalidation_task_posted_)
1355    return;
1356  if (!paint_aggregator_.HasPendingUpdate())
1357    return;
1358  if (update_reply_pending_ ||
1359      num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending)
1360    return;
1361
1362  // When GPU rendering, combine pending animations and invalidations into
1363  // a single update.
1364  if (is_accelerated_compositing_active_ &&
1365      animation_update_pending_ &&
1366      animation_timer_.IsRunning())
1367    return;
1368
1369  // Perform updating asynchronously.  This serves two purposes:
1370  // 1) Ensures that we call WebView::Paint without a bunch of other junk
1371  //    on the call stack.
1372  // 2) Allows us to collect more damage rects before painting to help coalesce
1373  //    the work that we will need to do.
1374  invalidation_task_posted_ = true;
1375  base::MessageLoop::current()->PostTask(
1376      FROM_HERE, base::Bind(&RenderWidget::InvalidationCallback, this));
1377}
1378
1379void RenderWidget::didScrollRect(int dx, int dy,
1380                                 const WebRect& clip_rect) {
1381  // Drop scrolls on the floor when we are in compositing mode.
1382  // TODO(nduca): stop WebViewImpl from sending scrolls in the first place.
1383  if (is_accelerated_compositing_active_)
1384    return;
1385
1386  // The scrolled rect might be outside the bounds of the view.
1387  gfx::Rect view_rect(size_);
1388  gfx::Rect damaged_rect = gfx::IntersectRects(view_rect, clip_rect);
1389  if (damaged_rect.IsEmpty())
1390    return;
1391
1392  paint_aggregator_.ScrollRect(gfx::Vector2d(dx, dy), damaged_rect);
1393
1394  // We may not need to schedule another call to DoDeferredUpdate.
1395  if (invalidation_task_posted_)
1396    return;
1397  if (!paint_aggregator_.HasPendingUpdate())
1398    return;
1399  if (update_reply_pending_ ||
1400      num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending)
1401    return;
1402
1403  // When GPU rendering, combine pending animations and invalidations into
1404  // a single update.
1405  if (is_accelerated_compositing_active_ &&
1406      animation_update_pending_ &&
1407      animation_timer_.IsRunning())
1408    return;
1409
1410  // Perform updating asynchronously.  This serves two purposes:
1411  // 1) Ensures that we call WebView::Paint without a bunch of other junk
1412  //    on the call stack.
1413  // 2) Allows us to collect more damage rects before painting to help coalesce
1414  //    the work that we will need to do.
1415  invalidation_task_posted_ = true;
1416  base::MessageLoop::current()->PostTask(
1417      FROM_HERE, base::Bind(&RenderWidget::InvalidationCallback, this));
1418}
1419
1420void RenderWidget::didAutoResize(const WebSize& new_size) {
1421  if (size_.width() != new_size.width || size_.height() != new_size.height) {
1422    size_ = new_size;
1423
1424    // If we don't clear PaintAggregator after changing autoResize state, then
1425    // we might end up in a situation where bitmap_rect is larger than the
1426    // view_size. By clearing PaintAggregator, we ensure that we don't end up
1427    // with invalid damage rects.
1428    paint_aggregator_.ClearPendingUpdate();
1429
1430    if (RenderThreadImpl::current()->layout_test_mode()) {
1431      WebRect new_pos(rootWindowRect().x,
1432                      rootWindowRect().y,
1433                      new_size.width,
1434                      new_size.height);
1435      view_screen_rect_ = new_pos;
1436      window_screen_rect_ = new_pos;
1437    }
1438
1439    AutoResizeCompositor();
1440
1441    if (!RenderThreadImpl::current()->layout_test_mode())
1442      need_update_rect_for_auto_resize_ = true;
1443  }
1444}
1445
1446void RenderWidget::AutoResizeCompositor()  {
1447  physical_backing_size_ = gfx::ToCeiledSize(gfx::ScaleSize(size_,
1448      device_scale_factor_));
1449  if (compositor_)
1450    compositor_->setViewportSize(size_, physical_backing_size_);
1451}
1452
1453void RenderWidget::didActivateCompositor(int input_handler_identifier) {
1454  TRACE_EVENT0("gpu", "RenderWidget::didActivateCompositor");
1455
1456#if !defined(OS_MACOSX)
1457  if (!is_accelerated_compositing_active_) {
1458    // When not in accelerated compositing mode, in certain cases (e.g. waiting
1459    // for a resize or if no backing store) the RenderWidgetHost is blocking the
1460    // browser's UI thread for some time, waiting for an UpdateRect. If we are
1461    // going to switch to accelerated compositing, the GPU process may need
1462    // round-trips to the browser's UI thread before finishing the frame,
1463    // causing deadlocks if we delay the UpdateRect until we receive the
1464    // OnSwapBuffersComplete.  So send a dummy message that will unblock the
1465    // browser's UI thread. This is not necessary on Mac, because SwapBuffers
1466    // now unblocks GetBackingStore on Mac.
1467    Send(new ViewHostMsg_UpdateIsDelayed(routing_id_));
1468  }
1469#endif
1470
1471  is_accelerated_compositing_active_ = true;
1472  Send(new ViewHostMsg_DidActivateAcceleratedCompositing(
1473      routing_id_, is_accelerated_compositing_active_));
1474}
1475
1476void RenderWidget::didDeactivateCompositor() {
1477  TRACE_EVENT0("gpu", "RenderWidget::didDeactivateCompositor");
1478
1479  is_accelerated_compositing_active_ = false;
1480  Send(new ViewHostMsg_DidActivateAcceleratedCompositing(
1481      routing_id_, is_accelerated_compositing_active_));
1482
1483  if (using_asynchronous_swapbuffers_)
1484    using_asynchronous_swapbuffers_ = false;
1485
1486  // In single-threaded mode, we exit force compositing mode and re-enter in
1487  // DoDeferredUpdate() if appropriate. In threaded compositing mode,
1488  // DoDeferredUpdate() is bypassed and WebKit is responsible for exiting and
1489  // entering force compositing mode at the appropriate times.
1490  if (!is_threaded_compositing_enabled_)
1491    webwidget_->enterForceCompositingMode(false);
1492}
1493
1494void RenderWidget::initializeLayerTreeView() {
1495  compositor_ = RenderWidgetCompositor::Create(this);
1496  if (!compositor_)
1497    return;
1498
1499  compositor_->setViewportSize(size_, physical_backing_size_);
1500  if (init_complete_)
1501    compositor_->setSurfaceReady();
1502}
1503
1504WebKit::WebLayerTreeView* RenderWidget::layerTreeView() {
1505  return compositor_.get();
1506}
1507
1508void RenderWidget::suppressCompositorScheduling(bool enable) {
1509  if (compositor_)
1510    compositor_->SetSuppressScheduleComposite(enable);
1511}
1512
1513void RenderWidget::willBeginCompositorFrame() {
1514  TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame");
1515
1516  DCHECK(RenderThreadImpl::current()->compositor_message_loop_proxy());
1517
1518  // The following two can result in further layout and possibly
1519  // enable GPU acceleration so they need to be called before any painting
1520  // is done.
1521  UpdateTextInputState(DO_NOT_SHOW_IME);
1522  UpdateSelectionBounds();
1523
1524  WillInitiatePaint();
1525}
1526
1527void RenderWidget::didBecomeReadyForAdditionalInput() {
1528  TRACE_EVENT0("renderer", "RenderWidget::didBecomeReadyForAdditionalInput");
1529  if (pending_input_event_ack_)
1530    Send(pending_input_event_ack_.release());
1531}
1532
1533void RenderWidget::DidCommitCompositorFrame() {
1534}
1535
1536void RenderWidget::didCommitAndDrawCompositorFrame() {
1537  TRACE_EVENT0("gpu", "RenderWidget::didCommitAndDrawCompositorFrame");
1538  // Accelerated FPS tick for performance tests. See throughput_tests.cc.
1539  // NOTE: Tests may break if this event is renamed or moved.
1540  UNSHIPPED_TRACE_EVENT_INSTANT0("test_fps", "TestFrameTickGPU",
1541                                 TRACE_EVENT_SCOPE_THREAD);
1542  // Notify subclasses that we initiated the paint operation.
1543  DidInitiatePaint();
1544}
1545
1546void RenderWidget::didCompleteSwapBuffers() {
1547  TRACE_EVENT0("renderer", "RenderWidget::didCompleteSwapBuffers");
1548
1549  // Notify subclasses threaded composited rendering was flushed to the screen.
1550  DidFlushPaint();
1551
1552  if (update_reply_pending_)
1553    return;
1554
1555  if (!next_paint_flags_ &&
1556      !need_update_rect_for_auto_resize_ &&
1557      !plugin_window_moves_.size()) {
1558    return;
1559  }
1560
1561  ViewHostMsg_UpdateRect_Params params;
1562  params.view_size = size_;
1563  params.plugin_window_moves.swap(plugin_window_moves_);
1564  params.flags = next_paint_flags_;
1565  params.scroll_offset = GetScrollOffset();
1566  params.needs_ack = false;
1567  params.scale_factor = device_scale_factor_;
1568
1569  Send(new ViewHostMsg_UpdateRect(routing_id_, params));
1570  next_paint_flags_ = 0;
1571  need_update_rect_for_auto_resize_ = false;
1572}
1573
1574void RenderWidget::scheduleComposite() {
1575  TRACE_EVENT0("gpu", "RenderWidget::scheduleComposite");
1576  if (RenderThreadImpl::current()->compositor_message_loop_proxy() &&
1577      compositor_) {
1578    compositor_->setNeedsRedraw();
1579  } else {
1580    // TODO(nduca): replace with something a little less hacky.  The reason this
1581    // hack is still used is because the Invalidate-DoDeferredUpdate loop
1582    // contains a lot of host-renderer synchronization logic that is still
1583    // important for the accelerated compositing case. The option of simply
1584    // duplicating all that code is less desirable than "faking out" the
1585    // invalidation path using a magical damage rect.
1586    didInvalidateRect(WebRect(0, 0, 1, 1));
1587  }
1588}
1589
1590void RenderWidget::scheduleAnimation() {
1591  if (animation_update_pending_)
1592    return;
1593
1594  TRACE_EVENT0("gpu", "RenderWidget::scheduleAnimation");
1595  animation_update_pending_ = true;
1596  if (!animation_timer_.IsRunning()) {
1597    animation_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(0), this,
1598                           &RenderWidget::AnimationCallback);
1599  }
1600}
1601
1602void RenderWidget::didChangeCursor(const WebCursorInfo& cursor_info) {
1603  // TODO(darin): Eliminate this temporary.
1604  WebCursor cursor;
1605  webkit_glue::InitializeCursorFromWebKitCursorInfo(&cursor, cursor_info);
1606  // Only send a SetCursor message if we need to make a change.
1607  if (!current_cursor_.IsEqual(cursor)) {
1608    current_cursor_ = cursor;
1609    Send(new ViewHostMsg_SetCursor(routing_id_, cursor));
1610  }
1611}
1612
1613// We are supposed to get a single call to Show for a newly created RenderWidget
1614// that was created via RenderWidget::CreateWebView.  So, we wait until this
1615// point to dispatch the ShowWidget message.
1616//
1617// This method provides us with the information about how to display the newly
1618// created RenderWidget (i.e., as a blocked popup or as a new tab).
1619//
1620void RenderWidget::show(WebNavigationPolicy) {
1621  DCHECK(!did_show_) << "received extraneous Show call";
1622  DCHECK(routing_id_ != MSG_ROUTING_NONE);
1623  DCHECK(opener_id_ != MSG_ROUTING_NONE);
1624
1625  if (did_show_)
1626    return;
1627
1628  did_show_ = true;
1629  // NOTE: initial_pos_ may still have its default values at this point, but
1630  // that's okay.  It'll be ignored if as_popup is false, or the browser
1631  // process will impose a default position otherwise.
1632  Send(new ViewHostMsg_ShowWidget(opener_id_, routing_id_, initial_pos_));
1633  SetPendingWindowRect(initial_pos_);
1634}
1635
1636void RenderWidget::didProgrammaticallyScroll(
1637    const WebKit::WebPoint& scroll_point) {
1638  if (!compositor_)
1639    return;
1640  Send(new ViewHostMsg_DidProgrammaticallyScroll(
1641    routing_id_, gfx::Vector2d(scroll_point.x, scroll_point.y)));
1642}
1643
1644void RenderWidget::didFocus() {
1645}
1646
1647void RenderWidget::didBlur() {
1648}
1649
1650void RenderWidget::DoDeferredClose() {
1651  Send(new ViewHostMsg_Close(routing_id_));
1652}
1653
1654void RenderWidget::closeWidgetSoon() {
1655  if (is_swapped_out_) {
1656    // This widget is currently swapped out, and the active widget is in a
1657    // different process.  Have the browser route the close request to the
1658    // active widget instead, so that the correct unload handlers are run.
1659    Send(new ViewHostMsg_RouteCloseEvent(routing_id_));
1660    return;
1661  }
1662
1663  // If a page calls window.close() twice, we'll end up here twice, but that's
1664  // OK.  It is safe to send multiple Close messages.
1665
1666  // Ask the RenderWidgetHost to initiate close.  We could be called from deep
1667  // in Javascript.  If we ask the RendwerWidgetHost to close now, the window
1668  // could be closed before the JS finishes executing.  So instead, post a
1669  // message back to the message loop, which won't run until the JS is
1670  // complete, and then the Close message can be sent.
1671  base::MessageLoop::current()->PostTask(
1672      FROM_HERE, base::Bind(&RenderWidget::DoDeferredClose, this));
1673}
1674
1675void RenderWidget::Close() {
1676  if (webwidget_) {
1677    webwidget_->willCloseLayerTreeView();
1678    compositor_.reset();
1679    webwidget_->close();
1680    webwidget_ = NULL;
1681  }
1682}
1683
1684WebRect RenderWidget::windowRect() {
1685  if (pending_window_rect_count_)
1686    return pending_window_rect_;
1687
1688  return view_screen_rect_;
1689}
1690
1691void RenderWidget::setToolTipText(const WebKit::WebString& text,
1692                                  WebTextDirection hint) {
1693  Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint));
1694}
1695
1696void RenderWidget::setWindowRect(const WebRect& pos) {
1697  if (did_show_) {
1698    if (!RenderThreadImpl::current()->layout_test_mode()) {
1699      Send(new ViewHostMsg_RequestMove(routing_id_, pos));
1700      SetPendingWindowRect(pos);
1701    } else {
1702      WebSize new_size(pos.width, pos.height);
1703      Resize(new_size, new_size, overdraw_bottom_height_,
1704             WebRect(), is_fullscreen_, NO_RESIZE_ACK);
1705      view_screen_rect_ = pos;
1706      window_screen_rect_ = pos;
1707    }
1708  } else {
1709    initial_pos_ = pos;
1710  }
1711}
1712
1713void RenderWidget::SetPendingWindowRect(const WebRect& rect) {
1714  pending_window_rect_ = rect;
1715  pending_window_rect_count_++;
1716}
1717
1718WebRect RenderWidget::rootWindowRect() {
1719  if (pending_window_rect_count_) {
1720    // NOTE(mbelshe): If there is a pending_window_rect_, then getting
1721    // the RootWindowRect is probably going to return wrong results since the
1722    // browser may not have processed the Move yet.  There isn't really anything
1723    // good to do in this case, and it shouldn't happen - since this size is
1724    // only really needed for windowToScreen, which is only used for Popups.
1725    return pending_window_rect_;
1726  }
1727
1728  return window_screen_rect_;
1729}
1730
1731WebRect RenderWidget::windowResizerRect() {
1732  return resizer_rect_;
1733}
1734
1735void RenderWidget::OnSetInputMethodActive(bool is_active) {
1736  // To prevent this renderer process from sending unnecessary IPC messages to
1737  // a browser process, we permit the renderer process to send IPC messages
1738  // only during the input method attached to the browser process is active.
1739  input_method_is_active_ = is_active;
1740}
1741
1742void RenderWidget::UpdateCompositionInfo(
1743    const ui::Range& range,
1744    const std::vector<gfx::Rect>& character_bounds) {
1745  if (!ShouldUpdateCompositionInfo(range, character_bounds))
1746    return;
1747  composition_character_bounds_ = character_bounds;
1748  composition_range_ = range;
1749  Send(new ViewHostMsg_ImeCompositionRangeChanged(
1750      routing_id(), composition_range_, composition_character_bounds_));
1751}
1752
1753void RenderWidget::OnImeSetComposition(
1754    const string16& text,
1755    const std::vector<WebCompositionUnderline>& underlines,
1756    int selection_start, int selection_end) {
1757  if (!webwidget_)
1758    return;
1759  ImeEventGuard guard(this);
1760  if (webwidget_->setComposition(
1761      text, WebVector<WebCompositionUnderline>(underlines),
1762      selection_start, selection_end)) {
1763    // Setting the IME composition was successful. Send the new composition
1764    // range to the browser.
1765    ui::Range range(ui::Range::InvalidRange());
1766    size_t location, length;
1767    if (webwidget_->compositionRange(&location, &length)) {
1768      range.set_start(location);
1769      range.set_end(location + length);
1770    }
1771    // The IME was cancelled via the Esc key, so just send back the caret.
1772    else if (webwidget_->caretOrSelectionRange(&location, &length)) {
1773      range.set_start(location);
1774      range.set_end(location + length);
1775    }
1776    std::vector<gfx::Rect> character_bounds;
1777    GetCompositionCharacterBounds(&character_bounds);
1778    UpdateCompositionInfo(range, character_bounds);
1779  } else {
1780    // If we failed to set the composition text, then we need to let the browser
1781    // process to cancel the input method's ongoing composition session, to make
1782    // sure we are in a consistent state.
1783    Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
1784
1785    // Send an updated IME range with just the caret range.
1786    ui::Range range(ui::Range::InvalidRange());
1787    size_t location, length;
1788    if (webwidget_->caretOrSelectionRange(&location, &length)) {
1789      range.set_start(location);
1790      range.set_end(location + length);
1791    }
1792    UpdateCompositionInfo(range, std::vector<gfx::Rect>());
1793  }
1794}
1795
1796void RenderWidget::OnImeConfirmComposition(
1797    const string16& text, const ui::Range& replacement_range) {
1798  if (!webwidget_)
1799    return;
1800  ImeEventGuard guard(this);
1801  handling_input_event_ = true;
1802  webwidget_->confirmComposition(text);
1803  handling_input_event_ = false;
1804
1805  // Send an updated IME range with just the caret range.
1806  ui::Range range(ui::Range::InvalidRange());
1807  size_t location, length;
1808  if (webwidget_->caretOrSelectionRange(&location, &length)) {
1809    range.set_start(location);
1810    range.set_end(location + length);
1811  }
1812  UpdateCompositionInfo(range, std::vector<gfx::Rect>());
1813}
1814
1815// This message causes the renderer to render an image of the
1816// desired_size, regardless of whether the tab is hidden or not.
1817void RenderWidget::OnPaintAtSize(const TransportDIB::Handle& dib_handle,
1818                                 int tag,
1819                                 const gfx::Size& page_size,
1820                                 const gfx::Size& desired_size) {
1821  if (!webwidget_ || !TransportDIB::is_valid_handle(dib_handle)) {
1822    if (TransportDIB::is_valid_handle(dib_handle)) {
1823      // Close our unused handle.
1824#if defined(OS_WIN)
1825      ::CloseHandle(dib_handle);
1826#elif defined(OS_MACOSX)
1827      base::SharedMemory::CloseHandle(dib_handle);
1828#endif
1829    }
1830    return;
1831  }
1832
1833  if (page_size.IsEmpty() || desired_size.IsEmpty()) {
1834    // If one of these is empty, then we just return the dib we were
1835    // given, to avoid leaking it.
1836    Send(new ViewHostMsg_PaintAtSize_ACK(routing_id_, tag, desired_size));
1837    return;
1838  }
1839
1840  // Map the given DIB ID into this process, and unmap it at the end
1841  // of this function.
1842  scoped_ptr<TransportDIB> paint_at_size_buffer(
1843      TransportDIB::CreateWithHandle(dib_handle));
1844
1845  gfx::Size page_size_in_pixel = gfx::ToFlooredSize(
1846      gfx::ScaleSize(page_size, device_scale_factor_));
1847  gfx::Size desired_size_in_pixel = gfx::ToFlooredSize(
1848      gfx::ScaleSize(desired_size, device_scale_factor_));
1849  gfx::Size canvas_size = page_size_in_pixel;
1850  float x_scale = static_cast<float>(desired_size_in_pixel.width()) /
1851                  static_cast<float>(canvas_size.width());
1852  float y_scale = static_cast<float>(desired_size_in_pixel.height()) /
1853                  static_cast<float>(canvas_size.height());
1854
1855  gfx::Rect orig_bounds(canvas_size);
1856  canvas_size.set_width(static_cast<int>(canvas_size.width() * x_scale));
1857  canvas_size.set_height(static_cast<int>(canvas_size.height() * y_scale));
1858  gfx::Rect bounds(canvas_size);
1859
1860  scoped_ptr<skia::PlatformCanvas> canvas(
1861      paint_at_size_buffer->GetPlatformCanvas(canvas_size.width(),
1862                                              canvas_size.height()));
1863  if (!canvas) {
1864    NOTREACHED();
1865    return;
1866  }
1867
1868  // Reset bounds to what we actually received, but they should be the
1869  // same.
1870  DCHECK_EQ(bounds.width(), canvas->getDevice()->width());
1871  DCHECK_EQ(bounds.height(), canvas->getDevice()->height());
1872  bounds.set_width(canvas->getDevice()->width());
1873  bounds.set_height(canvas->getDevice()->height());
1874
1875  canvas->save();
1876  // Add the scale factor to the canvas, so that we'll get the desired size.
1877  canvas->scale(SkFloatToScalar(x_scale), SkFloatToScalar(y_scale));
1878
1879  // Have to make sure we're laid out at the right size before
1880  // rendering.
1881  gfx::Size old_size = webwidget_->size();
1882  webwidget_->resize(page_size);
1883  webwidget_->layout();
1884
1885  // Paint the entire thing (using original bounds, not scaled bounds).
1886  PaintRect(orig_bounds, orig_bounds.origin(), canvas.get());
1887  canvas->restore();
1888
1889  // Return the widget to its previous size.
1890  webwidget_->resize(old_size);
1891
1892  Send(new ViewHostMsg_PaintAtSize_ACK(routing_id_, tag, bounds.size()));
1893}
1894
1895void RenderWidget::OnSnapshot(const gfx::Rect& src_subrect) {
1896  SkBitmap snapshot;
1897
1898  if (OnSnapshotHelper(src_subrect, &snapshot)) {
1899    Send(new ViewHostMsg_Snapshot(routing_id(), true, snapshot));
1900  } else {
1901    Send(new ViewHostMsg_Snapshot(routing_id(), false, SkBitmap()));
1902  }
1903}
1904
1905bool RenderWidget::OnSnapshotHelper(const gfx::Rect& src_subrect,
1906                                    SkBitmap* snapshot) {
1907  base::TimeTicks beginning_time = base::TimeTicks::Now();
1908
1909  if (!webwidget_ || src_subrect.IsEmpty())
1910    return false;
1911
1912  gfx::Rect viewport_size = gfx::IntersectRects(
1913      src_subrect, gfx::Rect(physical_backing_size_));
1914
1915  skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(
1916      skia::CreatePlatformCanvas(viewport_size.width(),
1917                                 viewport_size.height(),
1918                                 true,
1919                                 NULL,
1920                                 skia::RETURN_NULL_ON_FAILURE));
1921  if (!canvas)
1922    return false;
1923
1924  canvas->save();
1925  webwidget_->layout();
1926
1927  PaintRect(viewport_size, viewport_size.origin(), canvas.get());
1928  canvas->restore();
1929
1930  const SkBitmap& bitmap = skia::GetTopDevice(*canvas)->accessBitmap(false);
1931  if (!bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config))
1932    return false;
1933
1934  UMA_HISTOGRAM_TIMES("Renderer4.Snapshot",
1935                      base::TimeTicks::Now() - beginning_time);
1936  return true;
1937}
1938
1939void RenderWidget::OnRepaint(gfx::Size size_to_paint) {
1940  // During shutdown we can just ignore this message.
1941  if (!webwidget_)
1942    return;
1943
1944  // Even if the browser provides an empty damage rect, it's still expecting to
1945  // receive a repaint ack so just damage the entire widget bounds.
1946  if (size_to_paint.IsEmpty()) {
1947    size_to_paint = size_;
1948  }
1949
1950  set_next_paint_is_repaint_ack();
1951  if (is_accelerated_compositing_active_ && compositor_) {
1952    compositor_->SetNeedsRedrawRect(gfx::Rect(size_to_paint));
1953  } else {
1954    gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height());
1955    didInvalidateRect(repaint_rect);
1956  }
1957}
1958
1959void RenderWidget::OnSmoothScrollCompleted() {
1960  pending_smooth_scroll_gesture_.Run();
1961}
1962
1963void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
1964  if (!webwidget_)
1965    return;
1966  webwidget_->setTextDirection(direction);
1967}
1968
1969void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
1970                                       const gfx::Rect& window_screen_rect) {
1971  view_screen_rect_ = view_screen_rect;
1972  window_screen_rect_ = window_screen_rect;
1973  Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
1974}
1975
1976#if defined(OS_ANDROID)
1977void RenderWidget::OnImeBatchStateChanged(bool is_begin) {
1978  Send(new ViewHostMsg_ImeBatchStateChanged_ACK(routing_id(), is_begin));
1979}
1980
1981void RenderWidget::OnShowImeIfNeeded() {
1982  UpdateTextInputState(SHOW_IME_IF_NEEDED);
1983}
1984#endif
1985
1986void RenderWidget::SetDeviceScaleFactor(float device_scale_factor) {
1987  if (device_scale_factor_ == device_scale_factor)
1988    return;
1989
1990  device_scale_factor_ = device_scale_factor;
1991
1992  if (!is_accelerated_compositing_active_) {
1993    didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
1994  } else {
1995    scheduleComposite();
1996  }
1997}
1998
1999webkit::ppapi::PluginInstance* RenderWidget::GetBitmapForOptimizedPluginPaint(
2000    const gfx::Rect& paint_bounds,
2001    TransportDIB** dib,
2002    gfx::Rect* location,
2003    gfx::Rect* clip,
2004    float* scale_factor) {
2005  // Bare RenderWidgets don't support optimized plugin painting.
2006  return NULL;
2007}
2008
2009gfx::Vector2d RenderWidget::GetScrollOffset() {
2010  // Bare RenderWidgets don't support scroll offset.
2011  return gfx::Vector2d();
2012}
2013
2014void RenderWidget::SetHidden(bool hidden) {
2015  if (is_hidden_ == hidden)
2016    return;
2017
2018  // The status has changed.  Tell the RenderThread about it.
2019  is_hidden_ = hidden;
2020  if (is_hidden_)
2021    RenderThread::Get()->WidgetHidden();
2022  else
2023    RenderThread::Get()->WidgetRestored();
2024}
2025
2026void RenderWidget::WillToggleFullscreen() {
2027  if (!webwidget_)
2028    return;
2029
2030  if (is_fullscreen_) {
2031    webwidget_->willExitFullScreen();
2032  } else {
2033    webwidget_->willEnterFullScreen();
2034  }
2035}
2036
2037void RenderWidget::DidToggleFullscreen() {
2038  if (!webwidget_)
2039    return;
2040
2041  if (is_fullscreen_) {
2042    webwidget_->didEnterFullScreen();
2043  } else {
2044    webwidget_->didExitFullScreen();
2045  }
2046}
2047
2048void RenderWidget::SetBackground(const SkBitmap& background) {
2049  background_ = background;
2050
2051  // Generate a full repaint.
2052  didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
2053}
2054
2055bool RenderWidget::next_paint_is_resize_ack() const {
2056  return ViewHostMsg_UpdateRect_Flags::is_resize_ack(next_paint_flags_);
2057}
2058
2059bool RenderWidget::next_paint_is_restore_ack() const {
2060  return ViewHostMsg_UpdateRect_Flags::is_restore_ack(next_paint_flags_);
2061}
2062
2063void RenderWidget::set_next_paint_is_resize_ack() {
2064  next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
2065}
2066
2067void RenderWidget::set_next_paint_is_restore_ack() {
2068  next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK;
2069}
2070
2071void RenderWidget::set_next_paint_is_repaint_ack() {
2072  next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
2073}
2074
2075static bool IsDateTimeInput(ui::TextInputType type) {
2076  return type == ui::TEXT_INPUT_TYPE_DATE ||
2077      type == ui::TEXT_INPUT_TYPE_DATE_TIME ||
2078      type == ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL ||
2079      type == ui::TEXT_INPUT_TYPE_MONTH ||
2080      type == ui::TEXT_INPUT_TYPE_TIME ||
2081      type == ui::TEXT_INPUT_TYPE_WEEK;
2082}
2083
2084
2085void RenderWidget::StartHandlingImeEvent() {
2086  DCHECK(!handling_ime_event_);
2087  handling_ime_event_ = true;
2088}
2089
2090void RenderWidget::FinishHandlingImeEvent() {
2091  DCHECK(handling_ime_event_);
2092  handling_ime_event_ = false;
2093  // While handling an ime event, text input state and selection bounds updates
2094  // are ignored. These must explicitly be updated once finished handling the
2095  // ime event.
2096  UpdateSelectionBounds();
2097  UpdateTextInputState(DO_NOT_SHOW_IME);
2098}
2099
2100void RenderWidget::UpdateTextInputState(ShowIme show_ime) {
2101  if (handling_ime_event_)
2102    return;
2103  bool show_ime_if_needed = (show_ime == SHOW_IME_IF_NEEDED);
2104  if (!show_ime_if_needed && !input_method_is_active_)
2105    return;
2106  ui::TextInputType new_type = GetTextInputType();
2107  if (IsDateTimeInput(new_type))
2108    return;  // Not considered as a text input field in WebKit/Chromium.
2109
2110  WebKit::WebTextInputInfo new_info;
2111  if (webwidget_)
2112    new_info = webwidget_->textInputInfo();
2113
2114  bool new_can_compose_inline = CanComposeInline();
2115
2116  // Only sends text input params if they are changed or if the ime should be
2117  // shown.
2118  if (show_ime_if_needed || (text_input_type_ != new_type
2119      || text_input_info_ != new_info
2120      || can_compose_inline_ != new_can_compose_inline)) {
2121    ViewHostMsg_TextInputState_Params p;
2122    p.type = new_type;
2123    p.value = new_info.value.utf8();
2124    p.selection_start = new_info.selectionStart;
2125    p.selection_end = new_info.selectionEnd;
2126    p.composition_start = new_info.compositionStart;
2127    p.composition_end = new_info.compositionEnd;
2128    p.can_compose_inline = new_can_compose_inline;
2129    p.show_ime_if_needed = show_ime_if_needed;
2130    Send(new ViewHostMsg_TextInputStateChanged(routing_id(), p));
2131
2132    text_input_info_ = new_info;
2133    text_input_type_ = new_type;
2134    can_compose_inline_ = new_can_compose_inline;
2135  }
2136}
2137
2138void RenderWidget::GetSelectionBounds(gfx::Rect* focus, gfx::Rect* anchor) {
2139  WebRect focus_webrect;
2140  WebRect anchor_webrect;
2141  webwidget_->selectionBounds(focus_webrect, anchor_webrect);
2142  *focus = focus_webrect;
2143  *anchor = anchor_webrect;
2144}
2145
2146void RenderWidget::UpdateSelectionBounds() {
2147  if (!webwidget_)
2148    return;
2149  if (handling_ime_event_)
2150    return;
2151
2152  ViewHostMsg_SelectionBounds_Params params;
2153  GetSelectionBounds(&params.anchor_rect, &params.focus_rect);
2154  if (selection_anchor_rect_ != params.anchor_rect ||
2155      selection_focus_rect_ != params.focus_rect) {
2156    selection_anchor_rect_ = params.anchor_rect;
2157    selection_focus_rect_ = params.focus_rect;
2158    webwidget_->selectionTextDirection(params.focus_dir, params.anchor_dir);
2159    params.is_anchor_first = webwidget_->isSelectionAnchorFirst();
2160    Send(new ViewHostMsg_SelectionBoundsChanged(routing_id_, params));
2161  }
2162
2163  std::vector<gfx::Rect> character_bounds;
2164  GetCompositionCharacterBounds(&character_bounds);
2165  UpdateCompositionInfo(composition_range_, character_bounds);
2166}
2167
2168bool RenderWidget::ShouldUpdateCompositionInfo(
2169    const ui::Range& range,
2170    const std::vector<gfx::Rect>& bounds) {
2171  if (composition_range_ != range)
2172    return true;
2173  if (bounds.size() != composition_character_bounds_.size())
2174    return true;
2175  for (size_t i = 0; i < bounds.size(); ++i) {
2176    if (bounds[i] != composition_character_bounds_[i])
2177      return true;
2178  }
2179  return false;
2180}
2181
2182// Check WebKit::WebTextInputType and ui::TextInputType is kept in sync.
2183COMPILE_ASSERT(int(WebKit::WebTextInputTypeNone) == \
2184               int(ui::TEXT_INPUT_TYPE_NONE), mismatching_enums);
2185COMPILE_ASSERT(int(WebKit::WebTextInputTypeText) == \
2186               int(ui::TEXT_INPUT_TYPE_TEXT), mismatching_enums);
2187COMPILE_ASSERT(int(WebKit::WebTextInputTypePassword) == \
2188               int(ui::TEXT_INPUT_TYPE_PASSWORD), mismatching_enums);
2189COMPILE_ASSERT(int(WebKit::WebTextInputTypeSearch) == \
2190               int(ui::TEXT_INPUT_TYPE_SEARCH), mismatching_enums);
2191COMPILE_ASSERT(int(WebKit::WebTextInputTypeEmail) == \
2192               int(ui::TEXT_INPUT_TYPE_EMAIL), mismatching_enums);
2193COMPILE_ASSERT(int(WebKit::WebTextInputTypeNumber) == \
2194               int(ui::TEXT_INPUT_TYPE_NUMBER), mismatching_enums);
2195COMPILE_ASSERT(int(WebKit::WebTextInputTypeTelephone) == \
2196               int(ui::TEXT_INPUT_TYPE_TELEPHONE), mismatching_enums);
2197COMPILE_ASSERT(int(WebKit::WebTextInputTypeURL) == \
2198               int(ui::TEXT_INPUT_TYPE_URL), mismatching_enums);
2199COMPILE_ASSERT(int(WebKit::WebTextInputTypeDate) == \
2200               int(ui::TEXT_INPUT_TYPE_DATE), mismatching_enum);
2201COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTime) == \
2202               int(ui::TEXT_INPUT_TYPE_DATE_TIME), mismatching_enum);
2203COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeLocal) == \
2204               int(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL), mismatching_enum);
2205COMPILE_ASSERT(int(WebKit::WebTextInputTypeMonth) == \
2206               int(ui::TEXT_INPUT_TYPE_MONTH), mismatching_enum);
2207COMPILE_ASSERT(int(WebKit::WebTextInputTypeTime) == \
2208               int(ui::TEXT_INPUT_TYPE_TIME), mismatching_enum);
2209COMPILE_ASSERT(int(WebKit::WebTextInputTypeWeek) == \
2210               int(ui::TEXT_INPUT_TYPE_WEEK), mismatching_enum);
2211COMPILE_ASSERT(int(WebKit::WebTextInputTypeTextArea) == \
2212               int(ui::TEXT_INPUT_TYPE_TEXT_AREA), mismatching_enums);
2213COMPILE_ASSERT(int(WebKit::WebTextInputTypeContentEditable) == \
2214               int(ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE), mismatching_enums);
2215COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeField) == \
2216               int(ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD), mismatching_enums);
2217
2218ui::TextInputType RenderWidget::WebKitToUiTextInputType(
2219    WebKit::WebTextInputType type) {
2220  // Check the type is in the range representable by ui::TextInputType.
2221  DCHECK_LE(type, static_cast<int>(ui::TEXT_INPUT_TYPE_MAX)) <<
2222    "WebKit::WebTextInputType and ui::TextInputType not synchronized";
2223  return static_cast<ui::TextInputType>(type);
2224}
2225
2226ui::TextInputType RenderWidget::GetTextInputType() {
2227  if (webwidget_)
2228    return WebKitToUiTextInputType(webwidget_->textInputInfo().type);
2229  return ui::TEXT_INPUT_TYPE_NONE;
2230}
2231
2232void RenderWidget::GetCompositionCharacterBounds(
2233    std::vector<gfx::Rect>* bounds) {
2234  DCHECK(bounds);
2235  bounds->clear();
2236}
2237
2238bool RenderWidget::CanComposeInline() {
2239  return true;
2240}
2241
2242WebScreenInfo RenderWidget::screenInfo() {
2243  return screen_info_;
2244}
2245
2246float RenderWidget::deviceScaleFactor() {
2247  return device_scale_factor_;
2248}
2249
2250void RenderWidget::resetInputMethod() {
2251  if (!input_method_is_active_)
2252    return;
2253
2254  // If the last text input type is not None, then we should finish any
2255  // ongoing composition regardless of the new text input type.
2256  if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE) {
2257    // If a composition text exists, then we need to let the browser process
2258    // to cancel the input method's ongoing composition session.
2259    if (webwidget_->confirmComposition())
2260      Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
2261  }
2262
2263  // Send an updated IME range with the current caret rect.
2264  ui::Range range(ui::Range::InvalidRange());
2265  size_t location, length;
2266  if (webwidget_->caretOrSelectionRange(&location, &length)) {
2267    range.set_start(location);
2268    range.set_end(location + length);
2269  }
2270
2271  UpdateCompositionInfo(range, std::vector<gfx::Rect>());
2272}
2273
2274void RenderWidget::didHandleGestureEvent(
2275    const WebGestureEvent& event,
2276    bool event_cancelled) {
2277#if defined(OS_ANDROID)
2278  if (event_cancelled)
2279    return;
2280  if (event.type == WebInputEvent::GestureTap ||
2281      event.type == WebInputEvent::GestureLongPress) {
2282    UpdateTextInputState(SHOW_IME_IF_NEEDED);
2283  }
2284#endif
2285}
2286
2287void RenderWidget::SchedulePluginMove(
2288    const webkit::npapi::WebPluginGeometry& move) {
2289  size_t i = 0;
2290  for (; i < plugin_window_moves_.size(); ++i) {
2291    if (plugin_window_moves_[i].window == move.window) {
2292      if (move.rects_valid) {
2293        plugin_window_moves_[i] = move;
2294      } else {
2295        plugin_window_moves_[i].visible = move.visible;
2296      }
2297      break;
2298    }
2299  }
2300
2301  if (i == plugin_window_moves_.size())
2302    plugin_window_moves_.push_back(move);
2303}
2304
2305void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
2306  for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin();
2307       i != plugin_window_moves_.end(); ++i) {
2308    if (i->window == window) {
2309      plugin_window_moves_.erase(i);
2310      break;
2311    }
2312  }
2313}
2314
2315void RenderWidget::GetRenderingStats(
2316    WebKit::WebRenderingStatsImpl& stats) const {
2317  if (compositor_)
2318    compositor_->GetRenderingStats(&stats.rendering_stats);
2319
2320  stats.rendering_stats.animation_frame_count +=
2321      software_stats_.animation_frame_count;
2322  stats.rendering_stats.screen_frame_count +=
2323      software_stats_.screen_frame_count;
2324  stats.rendering_stats.total_paint_time +=
2325      software_stats_.total_paint_time;
2326  stats.rendering_stats.total_pixels_painted +=
2327      software_stats_.total_pixels_painted;
2328}
2329
2330bool RenderWidget::GetGpuRenderingStats(GpuRenderingStats* stats) const {
2331  GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
2332  if (!gpu_channel)
2333    return false;
2334
2335  return gpu_channel->CollectRenderingStatsForSurface(surface_id(), stats);
2336}
2337
2338RenderWidgetCompositor* RenderWidget::compositor() const {
2339  return compositor_.get();
2340}
2341
2342void RenderWidget::OnSetBrowserRenderingStats(
2343    const BrowserRenderingStats& stats) {
2344  browser_rendering_stats_ = stats;
2345}
2346
2347void RenderWidget::GetBrowserRenderingStats(BrowserRenderingStats* stats) {
2348  *stats = browser_rendering_stats_;
2349}
2350
2351void RenderWidget::BeginSmoothScroll(
2352    bool down,
2353    const SmoothScrollCompletionCallback& callback,
2354    int pixels_to_scroll,
2355    int mouse_event_x,
2356    int mouse_event_y) {
2357  DCHECK(!callback.is_null());
2358
2359  ViewHostMsg_BeginSmoothScroll_Params params;
2360  params.scroll_down = down;
2361  params.pixels_to_scroll = pixels_to_scroll;
2362  params.mouse_event_x = mouse_event_x;
2363  params.mouse_event_y = mouse_event_y;
2364
2365  Send(new ViewHostMsg_BeginSmoothScroll(routing_id_, params));
2366  pending_smooth_scroll_gesture_ = callback;
2367}
2368
2369void RenderWidget::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
2370                                 gfx::Vector2dF current_fling_velocity) {
2371  if (overscroll_notifications_enabled_) {
2372    Send(new ViewHostMsg_DidOverscroll(routing_id_,
2373                                       accumulated_overscroll,
2374                                       current_fling_velocity));
2375  }
2376}
2377
2378bool RenderWidget::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
2379  return false;
2380}
2381
2382bool RenderWidget::WillHandleGestureEvent(
2383    const WebKit::WebGestureEvent& event) {
2384  return false;
2385}
2386
2387void RenderWidget::hasTouchEventHandlers(bool has_handlers) {
2388  Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers));
2389}
2390
2391bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const {
2392  return true;
2393}
2394
2395WebGraphicsContext3DCommandBufferImpl* RenderWidget::CreateGraphicsContext3D(
2396    const WebKit::WebGraphicsContext3D::Attributes& attributes) {
2397  if (!webwidget_)
2398    return NULL;
2399  scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
2400      new WebGraphicsContext3DCommandBufferImpl(
2401          surface_id(),
2402          GetURLForGraphicsContext3D(),
2403          RenderThreadImpl::current(),
2404          weak_ptr_factory_.GetWeakPtr()));
2405
2406  if (!context->InitializeWithDefaultBufferSizes(
2407          attributes,
2408          false /* bind generates resources */,
2409          CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE))
2410    return NULL;
2411  return context.release();
2412}
2413
2414}  // namespace content
2415