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