Home | History | Annotate | Download | only in pepper
      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/pepper/event_conversion.h"
      6 
      7 #include <map>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/i18n/char_iterator.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "base/strings/utf_string_conversion_utils.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "content/renderer/pepper/common.h"
     18 #include "content/renderer/pepper/usb_key_code_conversion.h"
     19 #include "ppapi/c/pp_input_event.h"
     20 #include "ppapi/shared_impl/ppb_input_event_shared.h"
     21 #include "ppapi/shared_impl/time_conversion.h"
     22 #include "third_party/WebKit/public/platform/WebGamepads.h"
     23 #include "third_party/WebKit/public/platform/WebString.h"
     24 #include "third_party/WebKit/public/web/WebInputEvent.h"
     25 
     26 using ppapi::EventTimeToPPTimeTicks;
     27 using ppapi::InputEventData;
     28 using ppapi::PPTimeTicksToEventTime;
     29 using WebKit::WebInputEvent;
     30 using WebKit::WebKeyboardEvent;
     31 using WebKit::WebMouseEvent;
     32 using WebKit::WebMouseWheelEvent;
     33 using WebKit::WebString;
     34 using WebKit::WebTouchEvent;
     35 using WebKit::WebTouchPoint;
     36 using WebKit::WebUChar;
     37 
     38 namespace content {
     39 
     40 namespace {
     41 
     42 // Verify the modifier flags WebKit uses match the Pepper ones. If these start
     43 // not matching, we'll need to write conversion code to preserve the Pepper
     44 // values (since plugins will be depending on them).
     45 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_SHIFTKEY) ==
     46                static_cast<int>(WebInputEvent::ShiftKey),
     47                ShiftKeyMatches);
     48 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CONTROLKEY) ==
     49                static_cast<int>(WebInputEvent::ControlKey),
     50                ControlKeyMatches);
     51 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ALTKEY) ==
     52                static_cast<int>(WebInputEvent::AltKey),
     53                AltKeyMatches);
     54 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_METAKEY) ==
     55                static_cast<int>(WebInputEvent::MetaKey),
     56                MetaKeyMatches);
     57 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISKEYPAD) ==
     58                static_cast<int>(WebInputEvent::IsKeyPad),
     59                KeyPadMatches);
     60 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) ==
     61                static_cast<int>(WebInputEvent::IsAutoRepeat),
     62                AutoRepeatMatches);
     63 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) ==
     64                static_cast<int>(WebInputEvent::LeftButtonDown),
     65                LeftButtonMatches);
     66 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) ==
     67                static_cast<int>(WebInputEvent::MiddleButtonDown),
     68                MiddleButtonMatches);
     69 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) ==
     70                static_cast<int>(WebInputEvent::RightButtonDown),
     71                RightButtonMatches);
     72 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) ==
     73                static_cast<int>(WebInputEvent::CapsLockOn),
     74                CapsLockMatches);
     75 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) ==
     76                static_cast<int>(WebInputEvent::NumLockOn),
     77                NumLockMatches);
     78 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISLEFT) ==
     79                static_cast<int>(WebInputEvent::IsLeft),
     80                LeftMatches);
     81 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISRIGHT) ==
     82                static_cast<int>(WebInputEvent::IsRight),
     83                RightMatches);
     84 
     85 PP_InputEvent_Type ConvertEventTypes(WebInputEvent::Type wetype) {
     86   switch (wetype) {
     87     case WebInputEvent::MouseDown:
     88       return PP_INPUTEVENT_TYPE_MOUSEDOWN;
     89     case WebInputEvent::MouseUp:
     90       return PP_INPUTEVENT_TYPE_MOUSEUP;
     91     case WebInputEvent::MouseMove:
     92       return PP_INPUTEVENT_TYPE_MOUSEMOVE;
     93     case WebInputEvent::MouseEnter:
     94       return PP_INPUTEVENT_TYPE_MOUSEENTER;
     95     case WebInputEvent::MouseLeave:
     96       return PP_INPUTEVENT_TYPE_MOUSELEAVE;
     97     case WebInputEvent::ContextMenu:
     98       return PP_INPUTEVENT_TYPE_CONTEXTMENU;
     99     case WebInputEvent::MouseWheel:
    100       return PP_INPUTEVENT_TYPE_WHEEL;
    101     case WebInputEvent::RawKeyDown:
    102       return PP_INPUTEVENT_TYPE_RAWKEYDOWN;
    103     case WebInputEvent::KeyDown:
    104       return PP_INPUTEVENT_TYPE_KEYDOWN;
    105     case WebInputEvent::KeyUp:
    106       return PP_INPUTEVENT_TYPE_KEYUP;
    107     case WebInputEvent::Char:
    108       return PP_INPUTEVENT_TYPE_CHAR;
    109     case WebInputEvent::TouchStart:
    110       return PP_INPUTEVENT_TYPE_TOUCHSTART;
    111     case WebInputEvent::TouchMove:
    112       return PP_INPUTEVENT_TYPE_TOUCHMOVE;
    113     case WebInputEvent::TouchEnd:
    114       return PP_INPUTEVENT_TYPE_TOUCHEND;
    115     case WebInputEvent::TouchCancel:
    116       return PP_INPUTEVENT_TYPE_TOUCHCANCEL;
    117     case WebInputEvent::Undefined:
    118     default:
    119       return PP_INPUTEVENT_TYPE_UNDEFINED;
    120   }
    121 }
    122 
    123 // Generates a PP_InputEvent with the fields common to all events, as well as
    124 // the event type from the given web event. Event-specific fields will be zero
    125 // initialized.
    126 InputEventData GetEventWithCommonFieldsAndType(const WebInputEvent& web_event) {
    127   InputEventData result;
    128   result.event_type = ConvertEventTypes(web_event.type);
    129   result.event_time_stamp = EventTimeToPPTimeTicks(web_event.timeStampSeconds);
    130   result.usb_key_code = 0;
    131   return result;
    132 }
    133 
    134 void AppendKeyEvent(const WebInputEvent& event,
    135                     std::vector<InputEventData>* result_events) {
    136   const WebKeyboardEvent& key_event =
    137       static_cast<const WebKeyboardEvent&>(event);
    138   InputEventData result = GetEventWithCommonFieldsAndType(event);
    139   result.event_modifiers = key_event.modifiers;
    140   result.key_code = key_event.windowsKeyCode;
    141   result.usb_key_code = UsbKeyCodeForKeyboardEvent(key_event);
    142   result_events->push_back(result);
    143 }
    144 
    145 void AppendCharEvent(const WebInputEvent& event,
    146                      std::vector<InputEventData>* result_events) {
    147   const WebKeyboardEvent& key_event =
    148       static_cast<const WebKeyboardEvent&>(event);
    149 
    150   // This is a bit complex, the input event will normally just have one 16-bit
    151   // character in it, but may be zero or more than one. The text array is
    152   // just padded with 0 values for the unused ones, but is not necessarily
    153   // null-terminated.
    154   //
    155   // Here we see how many UTF-16 characters we have.
    156   size_t utf16_char_count = 0;
    157   while (utf16_char_count < WebKeyboardEvent::textLengthCap &&
    158          key_event.text[utf16_char_count])
    159     utf16_char_count++;
    160 
    161   // Make a separate InputEventData for each Unicode character in the input.
    162   base::i18n::UTF16CharIterator iter(key_event.text, utf16_char_count);
    163   while (!iter.end()) {
    164     InputEventData result = GetEventWithCommonFieldsAndType(event);
    165     result.event_modifiers = key_event.modifiers;
    166     base::WriteUnicodeCharacter(iter.get(), &result.character_text);
    167 
    168     result_events->push_back(result);
    169     iter.Advance();
    170   }
    171 }
    172 
    173 void AppendMouseEvent(const WebInputEvent& event,
    174                       std::vector<InputEventData>* result_events) {
    175   COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonNone) ==
    176                  static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_NONE),
    177                  MouseNone);
    178   COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonLeft) ==
    179                  static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_LEFT),
    180                  MouseLeft);
    181   COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonRight) ==
    182                  static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_RIGHT),
    183                  MouseRight);
    184   COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonMiddle) ==
    185                  static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_MIDDLE),
    186                  MouseMiddle);
    187 
    188   const WebMouseEvent& mouse_event =
    189       static_cast<const WebMouseEvent&>(event);
    190   InputEventData result = GetEventWithCommonFieldsAndType(event);
    191   result.event_modifiers = mouse_event.modifiers;
    192   if (mouse_event.type == WebInputEvent::MouseDown ||
    193       mouse_event.type == WebInputEvent::MouseMove ||
    194       mouse_event.type == WebInputEvent::MouseUp) {
    195     result.mouse_button =
    196         static_cast<PP_InputEvent_MouseButton>(mouse_event.button);
    197   }
    198   result.mouse_position.x = mouse_event.x;
    199   result.mouse_position.y = mouse_event.y;
    200   result.mouse_click_count = mouse_event.clickCount;
    201   result.mouse_movement.x = mouse_event.movementX;
    202   result.mouse_movement.y = mouse_event.movementY;
    203   result_events->push_back(result);
    204 }
    205 
    206 void AppendMouseWheelEvent(const WebInputEvent& event,
    207                            std::vector<InputEventData>* result_events) {
    208   const WebMouseWheelEvent& mouse_wheel_event =
    209       static_cast<const WebMouseWheelEvent&>(event);
    210   InputEventData result = GetEventWithCommonFieldsAndType(event);
    211   result.event_modifiers = mouse_wheel_event.modifiers;
    212   result.wheel_delta.x = mouse_wheel_event.deltaX;
    213   result.wheel_delta.y = mouse_wheel_event.deltaY;
    214   result.wheel_ticks.x = mouse_wheel_event.wheelTicksX;
    215   result.wheel_ticks.y = mouse_wheel_event.wheelTicksY;
    216   result.wheel_scroll_by_page = !!mouse_wheel_event.scrollByPage;
    217   result_events->push_back(result);
    218 }
    219 
    220 void SetPPTouchPoints(const WebTouchPoint* touches, uint32_t touches_length,
    221                       std::vector<PP_TouchPoint>* result) {
    222   for (uint32_t i = 0; i < touches_length; i++) {
    223     const WebTouchPoint& touch_point = touches[i];
    224     PP_TouchPoint pp_pt;
    225     pp_pt.id = touch_point.id;
    226     pp_pt.position.x = touch_point.position.x;
    227     pp_pt.position.y = touch_point.position.y;
    228     pp_pt.radius.x = touch_point.radiusX;
    229     pp_pt.radius.y = touch_point.radiusY;
    230     pp_pt.rotation_angle = touch_point.rotationAngle;
    231     pp_pt.pressure = touch_point.force;
    232     result->push_back(pp_pt);
    233   }
    234 }
    235 
    236 void AppendTouchEvent(const WebInputEvent& event,
    237                       std::vector<InputEventData>* result_events) {
    238   const WebTouchEvent& touch_event =
    239       reinterpret_cast<const WebTouchEvent&>(event);
    240 
    241   InputEventData result = GetEventWithCommonFieldsAndType(event);
    242   SetPPTouchPoints(touch_event.touches, touch_event.touchesLength,
    243                    &result.touches);
    244   SetPPTouchPoints(touch_event.changedTouches, touch_event.changedTouchesLength,
    245                    &result.changed_touches);
    246   SetPPTouchPoints(touch_event.targetTouches, touch_event.targetTouchesLength,
    247                    &result.target_touches);
    248 
    249   result_events->push_back(result);
    250 }
    251 
    252 // Structure used to map touch point id's to touch states.  Since the pepper
    253 // touch event structure does not have states for individual touch points and
    254 // instead relies on the event type in combination with the set of touch lists,
    255 // we have to set the state for the changed touches to be the same as the event
    256 // type and all others to be 'stationary.'
    257 typedef std::map<uint32_t, WebTouchPoint::State> TouchStateMap;
    258 
    259 void SetWebTouchPoints(const std::vector<PP_TouchPoint>& pp_touches,
    260                        const TouchStateMap& states_map,
    261                        WebTouchPoint* web_touches,
    262                        uint32_t* web_touches_length) {
    263 
    264   for (uint32_t i = 0; i < pp_touches.size() &&
    265        i < WebTouchEvent::touchesLengthCap; i++) {
    266     WebTouchPoint pt;
    267     const PP_TouchPoint& pp_pt = pp_touches[i];
    268     pt.id = pp_pt.id;
    269 
    270     if (states_map.find(pt.id) == states_map.end())
    271       pt.state = WebTouchPoint::StateStationary;
    272     else
    273       pt.state = states_map.find(pt.id)->second;
    274 
    275     pt.position.x = pp_pt.position.x;
    276     pt.position.y = pp_pt.position.y;
    277     // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
    278     pt.screenPosition.x = 0;
    279     pt.screenPosition.y = 0;
    280     pt.force = pp_pt.pressure;
    281     pt.radiusX = pp_pt.radius.x;
    282     pt.radiusY = pp_pt.radius.y;
    283     pt.rotationAngle = pp_pt.rotation_angle;
    284     web_touches[i] = pt;
    285     (*web_touches_length)++;
    286   }
    287 }
    288 
    289 WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
    290   WebTouchEvent* web_event = new WebTouchEvent();
    291   WebTouchPoint::State state = WebTouchPoint::StateUndefined;
    292   switch (event.event_type) {
    293     case PP_INPUTEVENT_TYPE_TOUCHSTART:
    294       web_event->type = WebInputEvent::TouchStart;
    295       state = WebTouchPoint::StatePressed;
    296       break;
    297     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
    298       web_event->type = WebInputEvent::TouchMove;
    299       state = WebTouchPoint::StateMoved;
    300       break;
    301     case PP_INPUTEVENT_TYPE_TOUCHEND:
    302       web_event->type = WebInputEvent::TouchEnd;
    303       state = WebTouchPoint::StateReleased;
    304       break;
    305     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
    306       web_event->type = WebInputEvent::TouchCancel;
    307       state = WebTouchPoint::StateCancelled;
    308       break;
    309     default:
    310       NOTREACHED();
    311   }
    312 
    313   TouchStateMap states_map;
    314   for (uint32_t i = 0; i < event.changed_touches.size(); i++)
    315     states_map[event.changed_touches[i].id] = state;
    316 
    317   web_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
    318 
    319   SetWebTouchPoints(event.changed_touches, states_map,
    320                     web_event->changedTouches,
    321                     &web_event->changedTouchesLength);
    322 
    323   SetWebTouchPoints(event.touches, states_map, web_event->touches,
    324                     &web_event->touchesLength);
    325 
    326   SetWebTouchPoints(event.target_touches, states_map, web_event->targetTouches,
    327                     &web_event->targetTouchesLength);
    328 
    329   if (web_event->type == WebInputEvent::TouchEnd ||
    330       web_event->type == WebInputEvent::TouchCancel) {
    331     SetWebTouchPoints(event.changed_touches, states_map,
    332                       web_event->touches, &web_event->touchesLength);
    333     SetWebTouchPoints(event.changed_touches, states_map,
    334                       web_event->targetTouches,
    335                       &web_event->targetTouchesLength);
    336   }
    337 
    338   return web_event;
    339 }
    340 
    341 WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) {
    342   WebKeyboardEvent* key_event = new WebKeyboardEvent();
    343   switch (event.event_type) {
    344     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
    345       key_event->type = WebInputEvent::RawKeyDown;
    346       break;
    347     case PP_INPUTEVENT_TYPE_KEYDOWN:
    348       key_event->type = WebInputEvent::KeyDown;
    349       break;
    350     case PP_INPUTEVENT_TYPE_KEYUP:
    351       key_event->type = WebInputEvent::KeyUp;
    352       break;
    353     default:
    354       NOTREACHED();
    355   }
    356   key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
    357   key_event->modifiers = event.event_modifiers;
    358   key_event->windowsKeyCode = event.key_code;
    359   key_event->setKeyIdentifierFromWindowsKeyCode();
    360   return key_event;
    361 }
    362 
    363 WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
    364   WebKeyboardEvent* key_event = new WebKeyboardEvent();
    365   key_event->type = WebInputEvent::Char;
    366   key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
    367   key_event->modifiers = event.event_modifiers;
    368 
    369   // Make sure to not read beyond the buffer in case some bad code doesn't
    370   // NULL-terminate it (this is called from plugins).
    371   size_t text_length_cap = WebKeyboardEvent::textLengthCap;
    372   base::string16 text16 = UTF8ToUTF16(event.character_text);
    373 
    374   memset(key_event->text, 0, text_length_cap);
    375   memset(key_event->unmodifiedText, 0, text_length_cap);
    376   for (size_t i = 0;
    377        i < std::min(text_length_cap, text16.size());
    378        ++i)
    379     key_event->text[i] = text16[i];
    380   return key_event;
    381 }
    382 
    383 WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
    384   WebMouseEvent* mouse_event = new WebMouseEvent();
    385   switch (event.event_type) {
    386     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
    387       mouse_event->type = WebInputEvent::MouseDown;
    388       break;
    389     case PP_INPUTEVENT_TYPE_MOUSEUP:
    390       mouse_event->type = WebInputEvent::MouseUp;
    391       break;
    392     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
    393       mouse_event->type = WebInputEvent::MouseMove;
    394       break;
    395     case PP_INPUTEVENT_TYPE_MOUSEENTER:
    396       mouse_event->type = WebInputEvent::MouseEnter;
    397       break;
    398     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
    399       mouse_event->type = WebInputEvent::MouseLeave;
    400       break;
    401     case PP_INPUTEVENT_TYPE_CONTEXTMENU:
    402       mouse_event->type = WebInputEvent::ContextMenu;
    403       break;
    404     default:
    405       NOTREACHED();
    406   }
    407   mouse_event->timeStampSeconds =
    408       PPTimeTicksToEventTime(event.event_time_stamp);
    409   mouse_event->modifiers = event.event_modifiers;
    410   mouse_event->button =
    411       static_cast<WebMouseEvent::Button>(event.mouse_button);
    412   if (mouse_event->type == WebInputEvent::MouseMove) {
    413     if (mouse_event->modifiers & WebInputEvent::LeftButtonDown)
    414       mouse_event->button = WebMouseEvent::ButtonLeft;
    415     else if (mouse_event->modifiers & WebInputEvent::MiddleButtonDown)
    416       mouse_event->button = WebMouseEvent::ButtonMiddle;
    417     else if (mouse_event->modifiers & WebInputEvent::RightButtonDown)
    418       mouse_event->button = WebMouseEvent::ButtonRight;
    419   }
    420   mouse_event->x = event.mouse_position.x;
    421   mouse_event->y = event.mouse_position.y;
    422   mouse_event->clickCount = event.mouse_click_count;
    423   mouse_event->movementX = event.mouse_movement.x;
    424   mouse_event->movementY = event.mouse_movement.y;
    425   return mouse_event;
    426 }
    427 
    428 WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) {
    429   WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent();
    430   mouse_wheel_event->type = WebInputEvent::MouseWheel;
    431   mouse_wheel_event->timeStampSeconds =
    432       PPTimeTicksToEventTime(event.event_time_stamp);
    433   mouse_wheel_event->modifiers = event.event_modifiers;
    434   mouse_wheel_event->deltaX = event.wheel_delta.x;
    435   mouse_wheel_event->deltaY = event.wheel_delta.y;
    436   mouse_wheel_event->wheelTicksX = event.wheel_ticks.x;
    437   mouse_wheel_event->wheelTicksY = event.wheel_ticks.y;
    438   mouse_wheel_event->scrollByPage = event.wheel_scroll_by_page;
    439   return mouse_wheel_event;
    440 }
    441 
    442 #if !defined(OS_WIN)
    443 #define VK_RETURN         0x0D
    444 
    445 #define VK_PRIOR          0x21
    446 #define VK_NEXT           0x22
    447 #define VK_END            0x23
    448 #define VK_HOME           0x24
    449 #define VK_LEFT           0x25
    450 #define VK_UP             0x26
    451 #define VK_RIGHT          0x27
    452 #define VK_DOWN           0x28
    453 #define VK_SNAPSHOT       0x2C
    454 #define VK_INSERT         0x2D
    455 #define VK_DELETE         0x2E
    456 
    457 #define VK_APPS           0x5D
    458 
    459 #define VK_F1             0x70
    460 #endif
    461 
    462 // Convert a character string to a Windows virtual key code. Adapted from
    463 // src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp. This
    464 // is used by CreateSimulatedWebInputEvents to convert keyboard events.
    465 void GetKeyCode(const std::string& char_text,
    466                 WebUChar* code,
    467                 WebUChar* text,
    468                 bool* needs_shift_modifier,
    469                 bool* generate_char) {
    470   WebUChar vk_code = 0;
    471   WebUChar vk_text = 0;
    472   *needs_shift_modifier = false;
    473   *generate_char = false;
    474   if ("\n" == char_text) {
    475     vk_text = vk_code = VK_RETURN;
    476     *generate_char = true;
    477   } else if ("rightArrow" == char_text) {
    478     vk_code = VK_RIGHT;
    479   } else if ("downArrow" == char_text) {
    480     vk_code = VK_DOWN;
    481   } else if ("leftArrow" == char_text) {
    482     vk_code = VK_LEFT;
    483   } else if ("upArrow" == char_text) {
    484     vk_code = VK_UP;
    485   } else if ("insert" == char_text) {
    486     vk_code = VK_INSERT;
    487   } else if ("delete" == char_text) {
    488     vk_code = VK_DELETE;
    489   } else if ("pageUp" == char_text) {
    490     vk_code = VK_PRIOR;
    491   } else if ("pageDown" == char_text) {
    492     vk_code = VK_NEXT;
    493   } else if ("home" == char_text) {
    494     vk_code = VK_HOME;
    495   } else if ("end" == char_text) {
    496     vk_code = VK_END;
    497   } else if ("printScreen" == char_text) {
    498     vk_code = VK_SNAPSHOT;
    499   } else if ("menu" == char_text) {
    500     vk_code = VK_APPS;
    501   } else {
    502     // Compare the input string with the function-key names defined by the
    503     // DOM spec (i.e. "F1",...,"F24").
    504     for (int i = 1; i <= 24; ++i) {
    505       std::string functionKeyName = base::StringPrintf("F%d", i);
    506       if (functionKeyName == char_text) {
    507         vk_code = VK_F1 + (i - 1);
    508         break;
    509       }
    510     }
    511     if (!vk_code) {
    512       WebString web_char_text =
    513           WebString::fromUTF8(char_text.data(), char_text.size());
    514       DCHECK_EQ(web_char_text.length(), 1U);
    515       vk_text = vk_code = web_char_text.at(0);
    516       *needs_shift_modifier =
    517           (vk_code & 0xFF) >= 'A' && (vk_code & 0xFF) <= 'Z';
    518       if ((vk_code & 0xFF) >= 'a' && (vk_code & 0xFF) <= 'z')
    519           vk_code -= 'a' - 'A';
    520       *generate_char = true;
    521     }
    522   }
    523 
    524   *code = vk_code;
    525   *text = vk_text;
    526 }
    527 
    528 }  // namespace
    529 
    530 void CreateInputEventData(const WebInputEvent& event,
    531                           std::vector<InputEventData>* result) {
    532   result->clear();
    533 
    534   switch (event.type) {
    535     case WebInputEvent::MouseDown:
    536     case WebInputEvent::MouseUp:
    537     case WebInputEvent::MouseMove:
    538     case WebInputEvent::MouseEnter:
    539     case WebInputEvent::MouseLeave:
    540     case WebInputEvent::ContextMenu:
    541       AppendMouseEvent(event, result);
    542       break;
    543     case WebInputEvent::MouseWheel:
    544       AppendMouseWheelEvent(event, result);
    545       break;
    546     case WebInputEvent::RawKeyDown:
    547     case WebInputEvent::KeyDown:
    548     case WebInputEvent::KeyUp:
    549       AppendKeyEvent(event, result);
    550       break;
    551     case WebInputEvent::Char:
    552       AppendCharEvent(event, result);
    553       break;
    554     case WebInputEvent::TouchStart:
    555     case WebInputEvent::TouchMove:
    556     case WebInputEvent::TouchEnd:
    557     case WebInputEvent::TouchCancel:
    558       AppendTouchEvent(event, result);
    559       break;
    560     case WebInputEvent::Undefined:
    561     default:
    562       break;
    563   }
    564 }
    565 
    566 WebInputEvent* CreateWebInputEvent(const InputEventData& event) {
    567   scoped_ptr<WebInputEvent> web_input_event;
    568   switch (event.event_type) {
    569     case PP_INPUTEVENT_TYPE_UNDEFINED:
    570       return NULL;
    571     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
    572     case PP_INPUTEVENT_TYPE_MOUSEUP:
    573     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
    574     case PP_INPUTEVENT_TYPE_MOUSEENTER:
    575     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
    576     case PP_INPUTEVENT_TYPE_CONTEXTMENU:
    577       web_input_event.reset(BuildMouseEvent(event));
    578       break;
    579     case PP_INPUTEVENT_TYPE_WHEEL:
    580       web_input_event.reset(BuildMouseWheelEvent(event));
    581       break;
    582     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
    583     case PP_INPUTEVENT_TYPE_KEYDOWN:
    584     case PP_INPUTEVENT_TYPE_KEYUP:
    585       web_input_event.reset(BuildKeyEvent(event));
    586       break;
    587     case PP_INPUTEVENT_TYPE_CHAR:
    588       web_input_event.reset(BuildCharEvent(event));
    589       break;
    590     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
    591     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
    592     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
    593     case PP_INPUTEVENT_TYPE_IME_TEXT:
    594       // TODO(kinaba) implement in WebKit an event structure to handle
    595       // composition events.
    596       NOTREACHED();
    597       break;
    598     case PP_INPUTEVENT_TYPE_TOUCHSTART:
    599     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
    600     case PP_INPUTEVENT_TYPE_TOUCHEND:
    601     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
    602       web_input_event.reset(BuildTouchEvent(event));
    603       break;
    604   }
    605 
    606   return web_input_event.release();
    607 }
    608 
    609 // Generate a coherent sequence of input events to simulate a user event.
    610 // From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp.
    611 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
    612     const ppapi::InputEventData& event,
    613     int plugin_x,
    614     int plugin_y) {
    615   std::vector<linked_ptr<WebInputEvent> > events;
    616   linked_ptr<WebInputEvent> original_event(CreateWebInputEvent(event));
    617 
    618   switch (event.event_type) {
    619     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
    620     case PP_INPUTEVENT_TYPE_MOUSEUP:
    621     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
    622     case PP_INPUTEVENT_TYPE_MOUSEENTER:
    623     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
    624     case PP_INPUTEVENT_TYPE_TOUCHSTART:
    625     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
    626     case PP_INPUTEVENT_TYPE_TOUCHEND:
    627     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
    628       events.push_back(original_event);
    629       break;
    630 
    631     case PP_INPUTEVENT_TYPE_WHEEL: {
    632       WebMouseWheelEvent* web_mouse_wheel_event =
    633           static_cast<WebMouseWheelEvent*>(original_event.get());
    634       web_mouse_wheel_event->x = plugin_x;
    635       web_mouse_wheel_event->y = plugin_y;
    636       events.push_back(original_event);
    637       break;
    638     }
    639 
    640     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
    641     case PP_INPUTEVENT_TYPE_KEYDOWN:
    642     case PP_INPUTEVENT_TYPE_KEYUP: {
    643       // Windows key down events should always be "raw" to avoid an ASSERT.
    644 #if defined(OS_WIN)
    645       WebKeyboardEvent* web_keyboard_event =
    646           static_cast<WebKeyboardEvent*>(original_event.get());
    647       if (web_keyboard_event->type == WebInputEvent::KeyDown)
    648         web_keyboard_event->type = WebInputEvent::RawKeyDown;
    649 #endif
    650       events.push_back(original_event);
    651       break;
    652     }
    653 
    654     case PP_INPUTEVENT_TYPE_CHAR: {
    655       WebKeyboardEvent* web_char_event =
    656           static_cast<WebKeyboardEvent*>(original_event.get());
    657 
    658       WebUChar code = 0, text = 0;
    659       bool needs_shift_modifier = false, generate_char = false;
    660       GetKeyCode(event.character_text,
    661                  &code,
    662                  &text,
    663                  &needs_shift_modifier,
    664                  &generate_char);
    665 
    666       // Synthesize key down and key up events in all cases.
    667       scoped_ptr<WebKeyboardEvent> key_down_event(new WebKeyboardEvent());
    668       scoped_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent());
    669 
    670       key_down_event->type = WebInputEvent::RawKeyDown;
    671       key_down_event->windowsKeyCode = code;
    672       key_down_event->nativeKeyCode = code;
    673       if (needs_shift_modifier)
    674         key_down_event->modifiers |= WebInputEvent::ShiftKey;
    675 
    676       // If a char event is needed, set the text fields.
    677       if (generate_char) {
    678         key_down_event->text[0] = text;
    679         key_down_event->unmodifiedText[0] = text;
    680       }
    681       // Convert the key code to a string identifier.
    682       key_down_event->setKeyIdentifierFromWindowsKeyCode();
    683 
    684       *key_up_event = *web_char_event = *key_down_event;
    685 
    686       events.push_back(linked_ptr<WebInputEvent>(key_down_event.release()));
    687 
    688       if (generate_char) {
    689         web_char_event->type = WebInputEvent::Char;
    690         web_char_event->keyIdentifier[0] = '\0';
    691         events.push_back(original_event);
    692       }
    693 
    694       key_up_event->type = WebInputEvent::KeyUp;
    695       events.push_back(linked_ptr<WebInputEvent>(key_up_event.release()));
    696       break;
    697     }
    698 
    699     default:
    700       break;
    701   }
    702   return events;
    703 }
    704 
    705 PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) {
    706   switch (type) {
    707     case WebInputEvent::MouseDown:
    708     case WebInputEvent::MouseUp:
    709     case WebInputEvent::MouseMove:
    710     case WebInputEvent::MouseEnter:
    711     case WebInputEvent::MouseLeave:
    712     case WebInputEvent::ContextMenu:
    713       return PP_INPUTEVENT_CLASS_MOUSE;
    714     case WebInputEvent::MouseWheel:
    715       return PP_INPUTEVENT_CLASS_WHEEL;
    716     case WebInputEvent::RawKeyDown:
    717     case WebInputEvent::KeyDown:
    718     case WebInputEvent::KeyUp:
    719     case WebInputEvent::Char:
    720       return PP_INPUTEVENT_CLASS_KEYBOARD;
    721     case WebInputEvent::TouchCancel:
    722     case WebInputEvent::TouchEnd:
    723     case WebInputEvent::TouchMove:
    724     case WebInputEvent::TouchStart:
    725       return PP_INPUTEVENT_CLASS_TOUCH;
    726     case WebInputEvent::Undefined:
    727     default:
    728       NOTREACHED();
    729       return PP_InputEvent_Class(0);
    730   }
    731 }
    732 
    733 }  // namespace content
    734