Home | History | Annotate | Download | only in frame_host
      1 // Copyright 2014 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 "base/bind_helpers.h"
      6 #include "base/command_line.h"
      7 #include "base/logging.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "content/browser/browser_plugin/browser_plugin_guest.h"
     10 #include "content/browser/frame_host/render_widget_host_view_guest.h"
     11 #include "content/browser/renderer_host/render_view_host_impl.h"
     12 #include "content/common/browser_plugin/browser_plugin_messages.h"
     13 #include "content/common/frame_messages.h"
     14 #include "content/common/gpu/gpu_messages.h"
     15 #include "content/common/input/web_touch_event_traits.h"
     16 #include "content/common/view_messages.h"
     17 #include "content/common/webplugin_geometry.h"
     18 #include "content/public/common/content_switches.h"
     19 #include "skia/ext/platform_canvas.h"
     20 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
     21 
     22 #if defined(OS_MACOSX)
     23 #import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
     24 #endif
     25 
     26 #if defined(USE_AURA)
     27 #include "content/browser/renderer_host/ui_events_helper.h"
     28 #endif
     29 
     30 namespace content {
     31 
     32 namespace {
     33 
     34 #if defined(USE_AURA)
     35 blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
     36   blink::WebGestureEvent gesture_event;
     37   gesture_event.timeStampSeconds = time_stamp;
     38   gesture_event.type = blink::WebGestureEvent::GestureFlingCancel;
     39   gesture_event.sourceDevice = blink::WebGestureDeviceTouchscreen;
     40   return gesture_event;
     41 }
     42 #endif  // defined(USE_AURA)
     43 
     44 }  // namespace
     45 
     46 RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
     47     RenderWidgetHost* widget_host,
     48     BrowserPluginGuest* guest,
     49     RenderWidgetHostViewBase* platform_view)
     50     : RenderWidgetHostViewChildFrame(widget_host),
     51       // |guest| is NULL during test.
     52       guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
     53       platform_view_(platform_view) {
     54 #if defined(USE_AURA)
     55   gesture_recognizer_.reset(ui::GestureRecognizer::Create());
     56   gesture_recognizer_->AddGestureEventHelper(this);
     57 #endif  // defined(USE_AURA)
     58 }
     59 
     60 RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
     61 #if defined(USE_AURA)
     62   gesture_recognizer_->RemoveGestureEventHelper(this);
     63 #endif  // defined(USE_AURA)
     64 }
     65 
     66 bool RenderWidgetHostViewGuest::OnMessageReceivedFromEmbedder(
     67     const IPC::Message& message,
     68     RenderWidgetHostImpl* embedder) {
     69   bool handled = true;
     70   IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(RenderWidgetHostViewGuest, message,
     71                                    embedder)
     72     IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
     73                         OnHandleInputEvent)
     74     IPC_MESSAGE_UNHANDLED(handled = false)
     75   IPC_END_MESSAGE_MAP()
     76   return handled;
     77 }
     78 
     79 void RenderWidgetHostViewGuest::WasShown() {
     80   // If the WebContents associated with us showed an interstitial page in the
     81   // beginning, the teardown path might call WasShown() while |host_| is in
     82   // the process of destruction. Avoid calling WasShown below in this case.
     83   // TODO(lazyboy): We shouldn't be showing interstitial pages in guests in the
     84   // first place: http://crbug.com/273089.
     85   //
     86   // |guest_| is NULL during test.
     87   if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
     88     return;
     89   // Make sure the size of this view matches the size of the WebContentsView.
     90   // The two sizes may fall out of sync if we switch RenderWidgetHostViews,
     91   // resize, and then switch page, as is the case with interstitial pages.
     92   // NOTE: |guest_| is NULL in unit tests.
     93   if (guest_)
     94     SetSize(guest_->web_contents()->GetViewBounds().size());
     95   host_->WasShown(ui::LatencyInfo());
     96 }
     97 
     98 void RenderWidgetHostViewGuest::WasHidden() {
     99   // |guest_| is NULL during test.
    100   if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
    101     return;
    102   host_->WasHidden();
    103 }
    104 
    105 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
    106   size_ = size;
    107   host_->WasResized();
    108 }
    109 
    110 void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
    111   SetSize(rect.size());
    112 }
    113 
    114 void RenderWidgetHostViewGuest::Focus() {
    115   // InterstitialPageImpl focuses views directly, so we place focus logic here.
    116   // InterstitialPages are not WebContents, and so BrowserPluginGuest does not
    117   // have direct access to the interstitial page's RenderWidgetHost.
    118   if (guest_)
    119     guest_->SetFocus(host_, true);
    120 }
    121 
    122 bool RenderWidgetHostViewGuest::HasFocus() const {
    123   if (!guest_)
    124     return false;
    125   return guest_->focused();
    126 }
    127 
    128 #if defined(USE_AURA)
    129 void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
    130     const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
    131   // TODO(fsamuel): Currently we will only take this codepath if the guest has
    132   // requested touch events. A better solution is to always forward touchpresses
    133   // to the embedder process to target a BrowserPlugin, and then route all
    134   // subsequent touch points of that touchdown to the appropriate guest until
    135   // that touch point is released.
    136   ScopedVector<ui::TouchEvent> events;
    137   if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, LOCAL_COORDINATES))
    138     return;
    139 
    140   ui::EventResult result = (ack_result ==
    141       INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
    142   for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
    143       end = events.end(); iter != end; ++iter)  {
    144     if (!gesture_recognizer_->ProcessTouchEventPreDispatch(*(*iter), this))
    145       continue;
    146 
    147     scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
    148     gestures.reset(gesture_recognizer_->ProcessTouchEventPostDispatch(
    149         *(*iter), result, this));
    150     ProcessGestures(gestures.get());
    151   }
    152 }
    153 #endif
    154 
    155 gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
    156   if (!guest_)
    157     return gfx::Rect();
    158 
    159   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
    160   gfx::Rect embedder_bounds;
    161   if (rwhv)
    162     embedder_bounds = rwhv->GetViewBounds();
    163   return gfx::Rect(
    164       guest_->GetScreenCoordinates(embedder_bounds.origin()), size_);
    165 }
    166 
    167 void RenderWidgetHostViewGuest::RenderProcessGone(
    168     base::TerminationStatus status,
    169     int error_code) {
    170   platform_view_->RenderProcessGone(status, error_code);
    171   // Destroy the guest view instance only, so we don't end up calling
    172   // platform_view_->Destroy().
    173   DestroyGuestView();
    174 }
    175 
    176 void RenderWidgetHostViewGuest::Destroy() {
    177   // The RenderWidgetHost's destruction led here, so don't call it.
    178   DestroyGuestView();
    179 
    180   platform_view_->Destroy();
    181 }
    182 
    183 gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
    184   return RenderWidgetHostViewBase::GetPhysicalBackingSize();
    185 }
    186 
    187 base::string16 RenderWidgetHostViewGuest::GetSelectedText() const {
    188   return platform_view_->GetSelectedText();
    189 }
    190 
    191 void RenderWidgetHostViewGuest::SetTooltipText(
    192     const base::string16& tooltip_text) {
    193   platform_view_->SetTooltipText(tooltip_text);
    194 }
    195 
    196 void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
    197     const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
    198     int gpu_host_id) {
    199   NOTREACHED();
    200 }
    201 
    202 void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
    203     const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
    204     int gpu_host_id) {
    205   NOTREACHED();
    206 }
    207 
    208 void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
    209     uint32 output_surface_id,
    210     scoped_ptr<cc::CompositorFrame> frame) {
    211   if (!guest_)
    212     return;
    213 
    214   last_scroll_offset_ = frame->metadata.root_scroll_offset;
    215   guest_->SwapCompositorFrame(output_surface_id,
    216                               host_->GetProcess()->GetID(),
    217                               host_->GetRoutingID(),
    218                               frame.Pass());
    219 }
    220 
    221 bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
    222   return platform_view_->OnMessageReceived(msg);
    223 }
    224 
    225 void RenderWidgetHostViewGuest::InitAsChild(
    226     gfx::NativeView parent_view) {
    227   platform_view_->InitAsChild(parent_view);
    228 }
    229 
    230 void RenderWidgetHostViewGuest::InitAsPopup(
    231     RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
    232   // This should never get called.
    233   NOTREACHED();
    234 }
    235 
    236 void RenderWidgetHostViewGuest::InitAsFullscreen(
    237     RenderWidgetHostView* reference_host_view) {
    238   // This should never get called.
    239   NOTREACHED();
    240 }
    241 
    242 gfx::NativeView RenderWidgetHostViewGuest::GetNativeView() const {
    243   if (!guest_)
    244     return gfx::NativeView();
    245 
    246   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
    247   if (!rwhv)
    248     return gfx::NativeView();
    249   return rwhv->GetNativeView();
    250 }
    251 
    252 gfx::NativeViewId RenderWidgetHostViewGuest::GetNativeViewId() const {
    253   if (!guest_)
    254     return static_cast<gfx::NativeViewId>(NULL);
    255 
    256   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
    257   if (!rwhv)
    258     return static_cast<gfx::NativeViewId>(NULL);
    259   return rwhv->GetNativeViewId();
    260 }
    261 
    262 gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
    263   if (!guest_)
    264     return gfx::NativeViewAccessible();
    265 
    266   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
    267   if (!rwhv)
    268     return gfx::NativeViewAccessible();
    269   return rwhv->GetNativeViewAccessible();
    270 }
    271 
    272 void RenderWidgetHostViewGuest::MovePluginWindows(
    273     const std::vector<WebPluginGeometry>& moves) {
    274   platform_view_->MovePluginWindows(moves);
    275 }
    276 
    277 void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
    278   // InterstitialPages are not WebContents so we cannot intercept
    279   // ViewHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
    280   // All guest RenderViewHosts have RenderWidgetHostViewGuests however,
    281   // and so we will always hit this code path.
    282   if (!guest_)
    283     return;
    284   guest_->SendMessageToEmbedder(
    285       new BrowserPluginMsg_SetCursor(guest_->browser_plugin_instance_id(),
    286                                      cursor));
    287 
    288 }
    289 
    290 void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
    291   platform_view_->SetIsLoading(is_loading);
    292 }
    293 
    294 void RenderWidgetHostViewGuest::TextInputTypeChanged(
    295     ui::TextInputType type,
    296     ui::TextInputMode input_mode,
    297     bool can_compose_inline) {
    298   if (!guest_)
    299     return;
    300 
    301   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
    302   if (!rwhv)
    303     return;
    304   // Forward the information to embedding RWHV.
    305   rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline);
    306 }
    307 
    308 void RenderWidgetHostViewGuest::ImeCancelComposition() {
    309   if (!guest_)
    310     return;
    311 
    312   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
    313   if (!rwhv)
    314     return;
    315   // Forward the information to embedding RWHV.
    316   rwhv->ImeCancelComposition();
    317 }
    318 
    319 #if defined(OS_MACOSX) || defined(USE_AURA)
    320 void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
    321     const gfx::Range& range,
    322     const std::vector<gfx::Rect>& character_bounds) {
    323   if (!guest_)
    324     return;
    325 
    326   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
    327   if (!rwhv)
    328     return;
    329   std::vector<gfx::Rect> guest_character_bounds;
    330   for (size_t i = 0; i < character_bounds.size(); ++i) {
    331     guest_character_bounds.push_back(gfx::Rect(
    332         guest_->GetScreenCoordinates(character_bounds[i].origin()),
    333         character_bounds[i].size()));
    334   }
    335   // Forward the information to embedding RWHV.
    336   rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
    337 }
    338 #endif
    339 
    340 void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text,
    341                                                  size_t offset,
    342                                                  const gfx::Range& range) {
    343   platform_view_->SelectionChanged(text, offset, range);
    344 }
    345 
    346 void RenderWidgetHostViewGuest::SelectionBoundsChanged(
    347     const ViewHostMsg_SelectionBounds_Params& params) {
    348   if (!guest_)
    349     return;
    350 
    351   RenderWidgetHostViewBase* rwhv = GetGuestRenderWidgetHostView();
    352   if (!rwhv)
    353     return;
    354   ViewHostMsg_SelectionBounds_Params guest_params(params);
    355   guest_params.anchor_rect.set_origin(
    356       guest_->GetScreenCoordinates(params.anchor_rect.origin()));
    357   guest_params.focus_rect.set_origin(
    358       guest_->GetScreenCoordinates(params.focus_rect.origin()));
    359   rwhv->SelectionBoundsChanged(guest_params);
    360 }
    361 
    362 void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
    363     const gfx::Rect& src_subrect,
    364     const gfx::Size& dst_size,
    365     CopyFromCompositingSurfaceCallback& callback,
    366     const SkColorType color_type) {
    367   CHECK(guest_);
    368   guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
    369 }
    370 
    371 void RenderWidgetHostViewGuest::SetBackgroundOpaque(bool opaque) {
    372   // Content embedders can toggle opaque backgrounds through this API.
    373   // We plumb the value here so that BrowserPlugin updates its compositing
    374   // state in response to this change. We also want to preserve this flag
    375   // after recovering from a crash so we let BrowserPluginGuest store it.
    376   if (!guest_)
    377     return;
    378   RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
    379   host_->SetBackgroundOpaque(opaque);
    380   guest_->SetContentsOpaque(opaque);
    381 }
    382 
    383 bool RenderWidgetHostViewGuest::LockMouse() {
    384   return platform_view_->LockMouse();
    385 }
    386 
    387 void RenderWidgetHostViewGuest::UnlockMouse() {
    388   return platform_view_->UnlockMouse();
    389 }
    390 
    391 void RenderWidgetHostViewGuest::GetScreenInfo(blink::WebScreenInfo* results) {
    392   if (!guest_)
    393     return;
    394   RenderWidgetHostViewBase* embedder_view = GetGuestRenderWidgetHostView();
    395   if (embedder_view)
    396     embedder_view->GetScreenInfo(results);
    397 }
    398 
    399 #if defined(OS_MACOSX)
    400 void RenderWidgetHostViewGuest::SetActive(bool active) {
    401   platform_view_->SetActive(active);
    402 }
    403 
    404 void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
    405   platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
    406 }
    407 
    408 void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
    409   platform_view_->SetWindowVisibility(visible);
    410 }
    411 
    412 void RenderWidgetHostViewGuest::WindowFrameChanged() {
    413   platform_view_->WindowFrameChanged();
    414 }
    415 
    416 void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
    417   if (!guest_)
    418     return;
    419 
    420   gfx::Point origin;
    421   gfx::Rect guest_bounds = GetViewBounds();
    422   RenderWidgetHostView* rwhv = guest_->GetEmbedderRenderWidgetHostView();
    423   gfx::Rect embedder_bounds;
    424   if (rwhv)
    425     embedder_bounds = rwhv->GetViewBounds();
    426 
    427   gfx::Vector2d guest_offset = gfx::Vector2d(
    428       // Horizontal offset of guest from embedder.
    429       guest_bounds.x() - embedder_bounds.x(),
    430       // Vertical offset from guest's top to embedder's bottom edge.
    431       embedder_bounds.bottom() - guest_bounds.y());
    432 
    433   RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
    434   helper.SetTargetView(rwhv);
    435   helper.set_offset(guest_offset);
    436   helper.ShowDefinitionForSelection();
    437 }
    438 
    439 bool RenderWidgetHostViewGuest::SupportsSpeech() const {
    440   return platform_view_->SupportsSpeech();
    441 }
    442 
    443 void RenderWidgetHostViewGuest::SpeakSelection() {
    444   platform_view_->SpeakSelection();
    445 }
    446 
    447 bool RenderWidgetHostViewGuest::IsSpeaking() const {
    448   return platform_view_->IsSpeaking();
    449 }
    450 
    451 void RenderWidgetHostViewGuest::StopSpeaking() {
    452   platform_view_->StopSpeaking();
    453 }
    454 
    455 bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
    456     const NativeWebKeyboardEvent& event) {
    457   return false;
    458 }
    459 
    460 #endif  // defined(OS_MACOSX)
    461 
    462 #if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
    463 void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
    464     const gfx::Rect& rect_pixels,
    465     const SkBitmap& zoomed_bitmap) {
    466 }
    467 #endif  // defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
    468 
    469 #if defined(OS_ANDROID)
    470 void RenderWidgetHostViewGuest::LockCompositingSurface() {
    471 }
    472 
    473 void RenderWidgetHostViewGuest::UnlockCompositingSurface() {
    474 }
    475 #endif  // defined(OS_ANDROID)
    476 
    477 #if defined(OS_WIN)
    478 void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
    479     gfx::NativeViewAccessible accessible_parent) {
    480 }
    481 
    482 gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
    483     const {
    484   return NULL;
    485 }
    486 #endif
    487 
    488 void RenderWidgetHostViewGuest::DestroyGuestView() {
    489   host_->SetView(NULL);
    490   host_ = NULL;
    491   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    492 }
    493 
    494 bool RenderWidgetHostViewGuest::CanDispatchToConsumer(
    495     ui::GestureConsumer* consumer) {
    496   CHECK_EQ(static_cast<RenderWidgetHostViewGuest*>(consumer), this);
    497   return true;
    498 }
    499 
    500 void RenderWidgetHostViewGuest::DispatchGestureEvent(
    501     ui::GestureEvent* event) {
    502   ForwardGestureEventToRenderer(event);
    503 }
    504 
    505 void RenderWidgetHostViewGuest::DispatchCancelTouchEvent(
    506     ui::TouchEvent* event) {
    507   if (!host_)
    508     return;
    509 
    510   blink::WebTouchEvent cancel_event;
    511   // TODO(rbyers): This event has no touches in it.  Don't we need to know what
    512   // touches are currently active in order to cancel them all properly?
    513   WebTouchEventTraits::ResetType(blink::WebInputEvent::TouchCancel,
    514                                  event->time_stamp().InSecondsF(),
    515                                  &cancel_event);
    516 
    517   host_->ForwardTouchEventWithLatencyInfo(cancel_event, *event->latency());
    518 }
    519 
    520 bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
    521     ui::GestureEvent* gesture) {
    522 #if defined(USE_AURA)
    523   if (!host_)
    524     return false;
    525 
    526   if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
    527       gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
    528       gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
    529     return true;
    530   }
    531 
    532   blink::WebGestureEvent web_gesture =
    533       MakeWebGestureEventFromUIEvent(*gesture);
    534   const gfx::Point& client_point = gesture->location();
    535   const gfx::Point& screen_point = gesture->location();
    536 
    537   web_gesture.x = client_point.x();
    538   web_gesture.y = client_point.y();
    539   web_gesture.globalX = screen_point.x();
    540   web_gesture.globalY = screen_point.y();
    541 
    542   if (web_gesture.type == blink::WebGestureEvent::Undefined)
    543     return false;
    544   if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
    545     host_->ForwardGestureEvent(
    546         CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
    547   }
    548   host_->ForwardGestureEvent(web_gesture);
    549   return true;
    550 #else
    551   return false;
    552 #endif
    553 }
    554 
    555 void RenderWidgetHostViewGuest::ProcessGestures(
    556     ui::GestureRecognizer::Gestures* gestures) {
    557   if ((gestures == NULL) || gestures->empty())
    558     return;
    559   for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
    560       g_it != gestures->end();
    561       ++g_it) {
    562     ForwardGestureEventToRenderer(*g_it);
    563   }
    564 }
    565 
    566 SkColorType RenderWidgetHostViewGuest::PreferredReadbackFormat() {
    567   return kN32_SkColorType;
    568 }
    569 
    570 RenderWidgetHostViewBase*
    571 RenderWidgetHostViewGuest::GetGuestRenderWidgetHostView() const {
    572   return static_cast<RenderWidgetHostViewBase*>(
    573       guest_->GetEmbedderRenderWidgetHostView());
    574 }
    575 
    576 void RenderWidgetHostViewGuest::OnHandleInputEvent(
    577     RenderWidgetHostImpl* embedder,
    578     int browser_plugin_instance_id,
    579     const gfx::Rect& guest_window_rect,
    580     const blink::WebInputEvent* event) {
    581   if (blink::WebInputEvent::isMouseEventType(event->type)) {
    582     host_->ForwardMouseEvent(
    583         *static_cast<const blink::WebMouseEvent*>(event));
    584     return;
    585   }
    586 
    587   if (event->type == blink::WebInputEvent::MouseWheel) {
    588     host_->ForwardWheelEvent(
    589         *static_cast<const blink::WebMouseWheelEvent*>(event));
    590     return;
    591   }
    592 
    593   if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
    594     if (!embedder->GetLastKeyboardEvent())
    595       return;
    596     NativeWebKeyboardEvent keyboard_event(*embedder->GetLastKeyboardEvent());
    597     host_->ForwardKeyboardEvent(keyboard_event);
    598     return;
    599   }
    600 
    601   if (blink::WebInputEvent::isTouchEventType(event->type)) {
    602     host_->ForwardTouchEventWithLatencyInfo(
    603         *static_cast<const blink::WebTouchEvent*>(event),
    604         ui::LatencyInfo());
    605     return;
    606   }
    607 
    608   if (blink::WebInputEvent::isGestureEventType(event->type)) {
    609     host_->ForwardGestureEvent(
    610         *static_cast<const blink::WebGestureEvent*>(event));
    611     return;
    612   }
    613 }
    614 
    615 }  // namespace content
    616