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