Home | History | Annotate | Download | only in test_runner
      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 "content/shell/renderer/test_runner/event_sender.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/logging.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "content/public/common/page_zoom.h"
     11 #include "content/shell/renderer/test_runner/MockSpellCheck.h"
     12 #include "content/shell/renderer/test_runner/TestInterfaces.h"
     13 #include "content/shell/renderer/test_runner/WebTestDelegate.h"
     14 #include "content/shell/renderer/test_runner/web_test_proxy.h"
     15 #include "gin/handle.h"
     16 #include "gin/object_template_builder.h"
     17 #include "gin/wrappable.h"
     18 #include "third_party/WebKit/public/platform/WebString.h"
     19 #include "third_party/WebKit/public/platform/WebVector.h"
     20 #include "third_party/WebKit/public/web/WebContextMenuData.h"
     21 #include "third_party/WebKit/public/web/WebFrame.h"
     22 #include "third_party/WebKit/public/web/WebKit.h"
     23 #include "third_party/WebKit/public/web/WebView.h"
     24 #include "ui/events/keycodes/keyboard_codes.h"
     25 #include "v8/include/v8.h"
     26 
     27 using blink::WebContextMenuData;
     28 using blink::WebDragData;
     29 using blink::WebDragOperationsMask;
     30 using blink::WebFloatPoint;
     31 using blink::WebFrame;
     32 using blink::WebGestureEvent;
     33 using blink::WebInputEvent;
     34 using blink::WebKeyboardEvent;
     35 using blink::WebMouseEvent;
     36 using blink::WebMouseWheelEvent;
     37 using blink::WebPoint;
     38 using blink::WebString;
     39 using blink::WebTouchEvent;
     40 using blink::WebTouchPoint;
     41 using blink::WebVector;
     42 using blink::WebView;
     43 
     44 namespace content {
     45 
     46 namespace {
     47 
     48 void InitMouseEvent(WebInputEvent::Type t,
     49                     WebMouseEvent::Button b,
     50                     const WebPoint& pos,
     51                     double time_stamp,
     52                     int click_count,
     53                     int modifiers,
     54                     WebMouseEvent* e) {
     55   e->type = t;
     56   e->button = b;
     57   e->modifiers = modifiers;
     58   e->x = pos.x;
     59   e->y = pos.y;
     60   e->globalX = pos.x;
     61   e->globalY = pos.y;
     62   e->timeStampSeconds = time_stamp;
     63   e->clickCount = click_count;
     64 }
     65 
     66 int GetKeyModifier(const std::string& modifier_name) {
     67   const char* characters = modifier_name.c_str();
     68   if (!strcmp(characters, "ctrlKey")
     69 #ifndef __APPLE__
     70       || !strcmp(characters, "addSelectionKey")
     71 #endif
     72       ) {
     73     return WebInputEvent::ControlKey;
     74   } else if (!strcmp(characters, "shiftKey") ||
     75              !strcmp(characters, "rangeSelectionKey")) {
     76     return WebInputEvent::ShiftKey;
     77   } else if (!strcmp(characters, "altKey")) {
     78     return WebInputEvent::AltKey;
     79 #ifdef __APPLE__
     80   } else if (!strcmp(characters, "metaKey") ||
     81              !strcmp(characters, "addSelectionKey")) {
     82     return WebInputEvent::MetaKey;
     83 #else
     84   } else if (!strcmp(characters, "metaKey")) {
     85     return WebInputEvent::MetaKey;
     86 #endif
     87   } else if (!strcmp(characters, "autoRepeat")) {
     88     return WebInputEvent::IsAutoRepeat;
     89   } else if (!strcmp(characters, "copyKey")) {
     90 #ifdef __APPLE__
     91     return WebInputEvent::AltKey;
     92 #else
     93     return WebInputEvent::ControlKey;
     94 #endif
     95   }
     96 
     97   return 0;
     98 }
     99 
    100 int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
    101   int modifiers = 0;
    102   for (std::vector<std::string>::const_iterator it = modifier_names.begin();
    103        it != modifier_names.end(); ++it) {
    104     modifiers |= GetKeyModifier(*it);
    105   }
    106   return modifiers;
    107 }
    108 
    109 int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
    110   std::vector<std::string> modifier_names;
    111   if (value->IsString()) {
    112     modifier_names.push_back(gin::V8ToString(value));
    113   } else if (value->IsArray()) {
    114     gin::Converter<std::vector<std::string> >::FromV8(
    115         NULL, value, &modifier_names);
    116   }
    117   return GetKeyModifiers(modifier_names);
    118 }
    119 
    120 // Maximum distance (in space and time) for a mouse click to register as a
    121 // double or triple click.
    122 const double kMultipleClickTimeSec = 1;
    123 const int kMultipleClickRadiusPixels = 5;
    124 
    125 bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
    126   return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
    127          kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
    128 }
    129 
    130 // Because actual context menu is implemented by the browser side,
    131 // this function does only what LayoutTests are expecting:
    132 // - Many test checks the count of items. So returning non-zero value makes
    133 // sense.
    134 // - Some test compares the count before and after some action. So changing the
    135 // count based on flags also makes sense. This function is doing such for some
    136 // flags.
    137 // - Some test even checks actual string content. So providing it would be also
    138 // helpful.
    139 std::vector<std::string> MakeMenuItemStringsFor(
    140     WebContextMenuData* context_menu,
    141     WebTestDelegate* delegate) {
    142   // These constants are based on Safari's context menu because tests are made
    143   // for it.
    144   static const char* kNonEditableMenuStrings[] = {
    145     "Back",
    146     "Reload Page",
    147     "Open in Dashbaord",
    148     "<separator>",
    149     "View Source",
    150     "Save Page As",
    151     "Print Page",
    152     "Inspect Element",
    153     0
    154   };
    155   static const char* kEditableMenuStrings[] = {
    156     "Cut",
    157     "Copy",
    158     "<separator>",
    159     "Paste",
    160     "Spelling and Grammar",
    161     "Substitutions, Transformations",
    162     "Font",
    163     "Speech",
    164     "Paragraph Direction",
    165     "<separator>",
    166     0
    167   };
    168 
    169   // This is possible because mouse events are cancelleable.
    170   if (!context_menu)
    171     return std::vector<std::string>();
    172 
    173   std::vector<std::string> strings;
    174 
    175   if (context_menu->isEditable) {
    176     for (const char** item = kEditableMenuStrings; *item; ++item) {
    177       strings.push_back(*item);
    178     }
    179     WebVector<WebString> suggestions;
    180     MockSpellCheck::fillSuggestionList(
    181         context_menu->misspelledWord, &suggestions);
    182     for (size_t i = 0; i < suggestions.size(); ++i) {
    183       strings.push_back(suggestions[i].utf8());
    184     }
    185   } else {
    186     for (const char** item = kNonEditableMenuStrings; *item; ++item) {
    187       strings.push_back(*item);
    188     }
    189   }
    190 
    191   return strings;
    192 }
    193 
    194 // How much we should scroll per event - the value here is chosen to match the
    195 // WebKit impl and layout test results.
    196 const float kScrollbarPixelsPerTick = 40.0f;
    197 
    198 WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
    199   if (!button_code)
    200     return WebMouseEvent::ButtonLeft;
    201   if (button_code == 2)
    202     return WebMouseEvent::ButtonRight;
    203   return WebMouseEvent::ButtonMiddle;
    204 }
    205 
    206 class MouseDownTask : public WebMethodTask<EventSender> {
    207  public:
    208   MouseDownTask(EventSender* obj, int button_number, int modifiers)
    209       : WebMethodTask<EventSender>(obj),
    210         button_number_(button_number),
    211         modifiers_(modifiers) {}
    212 
    213   virtual void runIfValid() OVERRIDE {
    214     m_object->MouseDown(button_number_, modifiers_);
    215   }
    216 
    217  private:
    218   int button_number_;
    219   int modifiers_;
    220 };
    221 
    222 class MouseUpTask : public WebMethodTask<EventSender> {
    223  public:
    224   MouseUpTask(EventSender* obj, int button_number, int modifiers)
    225       : WebMethodTask<EventSender>(obj),
    226         button_number_(button_number),
    227         modifiers_(modifiers) {}
    228 
    229   virtual void runIfValid() OVERRIDE {
    230     m_object->MouseUp(button_number_, modifiers_);
    231   }
    232 
    233  private:
    234   int button_number_;
    235   int modifiers_;
    236 };
    237 
    238 class KeyDownTask : public WebMethodTask<EventSender> {
    239  public:
    240   KeyDownTask(EventSender* obj,
    241               const std::string code_str,
    242               int modifiers,
    243               KeyLocationCode location)
    244       : WebMethodTask<EventSender>(obj),
    245         code_str_(code_str),
    246         modifiers_(modifiers),
    247         location_(location) {}
    248 
    249   virtual void runIfValid() OVERRIDE {
    250     m_object->KeyDown(code_str_, modifiers_, location_);
    251   }
    252 
    253  private:
    254   std::string code_str_;
    255   int modifiers_;
    256   KeyLocationCode location_;
    257 };
    258 
    259 bool NeedsShiftModifier(int keyCode) {
    260   // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
    261   return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
    262 }
    263 
    264 // Get the edit command corresponding to a keyboard event.
    265 // Returns true if the specified event corresponds to an edit command, the name
    266 // of the edit command will be stored in |*name|.
    267 bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
    268 #if defined(OS_MACOSX)
    269 // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
    270 // modifiers. These key events correspond to some special movement and
    271 // selection editor commands. These keys will be marked as system key, which
    272 // prevents them from being handled. Thus they must be handled specially.
    273   if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
    274       WebKeyboardEvent::MetaKey)
    275     return false;
    276 
    277   switch (event.windowsKeyCode) {
    278     case ui::VKEY_LEFT:
    279       *name = "MoveToBeginningOfLine";
    280       break;
    281     case ui::VKEY_RIGHT:
    282       *name = "MoveToEndOfLine";
    283       break;
    284     case ui::VKEY_UP:
    285       *name = "MoveToBeginningOfDocument";
    286       break;
    287     case ui::VKEY_DOWN:
    288       *name = "MoveToEndOfDocument";
    289       break;
    290     default:
    291       return false;
    292   }
    293 
    294   if (event.modifiers & WebKeyboardEvent::ShiftKey)
    295     name->append("AndModifySelection");
    296 
    297   return true;
    298 #else
    299   return false;
    300 #endif
    301 }
    302 
    303 bool IsSystemKeyEvent(const WebKeyboardEvent& event) {
    304 #if defined(OS_MACOSX)
    305   return event.modifiers & WebInputEvent::MetaKey &&
    306       event.windowsKeyCode != ui::VKEY_B &&
    307       event.windowsKeyCode != ui::VKEY_I;
    308 #else
    309   return !!(event.modifiers & WebInputEvent::AltKey);
    310 #endif
    311 }
    312 
    313 }  // namespace
    314 
    315 class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
    316  public:
    317   static gin::WrapperInfo kWrapperInfo;
    318 
    319   static void Install(base::WeakPtr<EventSender> sender,
    320                       blink::WebFrame* frame);
    321 
    322  private:
    323   explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
    324   virtual ~EventSenderBindings();
    325 
    326   // gin::Wrappable:
    327   virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
    328       v8::Isolate* isolate) OVERRIDE;
    329 
    330   // Bound methods:
    331   void EnableDOMUIEventLogging();
    332   void FireKeyboardEventsToElement();
    333   void ClearKillRing();
    334   std::vector<std::string> ContextClick();
    335   void TextZoomIn();
    336   void TextZoomOut();
    337   void ZoomPageIn();
    338   void ZoomPageOut();
    339   void SetPageZoomFactor(double factor);
    340   void SetPageScaleFactor(gin::Arguments* args);
    341   void ClearTouchPoints();
    342   void ReleaseTouchPoint(unsigned index);
    343   void UpdateTouchPoint(unsigned index, double x, double y);
    344   void CancelTouchPoint(unsigned index);
    345   void SetTouchModifier(const std::string& key_name, bool set_mask);
    346   void SetTouchCancelable(bool cancelable);
    347   void DumpFilenameBeingDragged();
    348   void GestureFlingCancel();
    349   void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
    350   void GestureScrollFirstPoint(int x, int y);
    351   void TouchStart();
    352   void TouchMove();
    353   void TouchCancel();
    354   void TouchEnd();
    355   void LeapForward(int milliseconds);
    356   void BeginDragWithFiles(const std::vector<std::string>& files);
    357   void AddTouchPoint(gin::Arguments* args);
    358   void MouseDragBegin();
    359   void MouseDragEnd();
    360   void GestureScrollBegin(gin::Arguments* args);
    361   void GestureScrollEnd(gin::Arguments* args);
    362   void GestureScrollUpdate(gin::Arguments* args);
    363   void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
    364   void GestureTap(gin::Arguments* args);
    365   void GestureTapDown(gin::Arguments* args);
    366   void GestureShowPress(gin::Arguments* args);
    367   void GestureTapCancel(gin::Arguments* args);
    368   void GestureLongPress(gin::Arguments* args);
    369   void GestureLongTap(gin::Arguments* args);
    370   void GestureTwoFingerTap(gin::Arguments* args);
    371   void ContinuousMouseScrollBy(gin::Arguments* args);
    372   void MouseMoveTo(gin::Arguments* args);
    373   void TrackpadScrollBegin();
    374   void TrackpadScroll(gin::Arguments* args);
    375   void TrackpadScrollEnd();
    376   void MouseScrollBy(gin::Arguments* args);
    377   // TODO(erikchen): Remove MouseMomentumBegin once CL 282743002 has landed.
    378   void MouseMomentumBegin();
    379   void MouseMomentumBegin2(gin::Arguments* args);
    380   void MouseMomentumScrollBy(gin::Arguments* args);
    381   void MouseMomentumEnd();
    382   void ScheduleAsynchronousClick(gin::Arguments* args);
    383   void ScheduleAsynchronousKeyDown(gin::Arguments* args);
    384   void MouseDown(gin::Arguments* args);
    385   void MouseUp(gin::Arguments* args);
    386   void KeyDown(gin::Arguments* args);
    387 
    388   // Binding properties:
    389   bool ForceLayoutOnEvents() const;
    390   void SetForceLayoutOnEvents(bool force);
    391   bool IsDragMode() const;
    392   void SetIsDragMode(bool drag_mode);
    393 
    394 #if defined(OS_WIN)
    395   int WmKeyDown() const;
    396   void SetWmKeyDown(int key_down);
    397 
    398   int WmKeyUp() const;
    399   void SetWmKeyUp(int key_up);
    400 
    401   int WmChar() const;
    402   void SetWmChar(int wm_char);
    403 
    404   int WmDeadChar() const;
    405   void SetWmDeadChar(int dead_char);
    406 
    407   int WmSysKeyDown() const;
    408   void SetWmSysKeyDown(int key_down);
    409 
    410   int WmSysKeyUp() const;
    411   void SetWmSysKeyUp(int key_up);
    412 
    413   int WmSysChar() const;
    414   void SetWmSysChar(int sys_char);
    415 
    416   int WmSysDeadChar() const;
    417   void SetWmSysDeadChar(int sys_dead_char);
    418 #endif
    419 
    420   base::WeakPtr<EventSender> sender_;
    421 
    422   DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
    423 };
    424 
    425 gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
    426 
    427 EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
    428     : sender_(sender) {
    429 }
    430 
    431 EventSenderBindings::~EventSenderBindings() {}
    432 
    433 // static
    434 void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
    435                                   WebFrame* frame) {
    436   v8::Isolate* isolate = blink::mainThreadIsolate();
    437   v8::HandleScope handle_scope(isolate);
    438   v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
    439   if (context.IsEmpty())
    440     return;
    441 
    442   v8::Context::Scope context_scope(context);
    443 
    444   gin::Handle<EventSenderBindings> bindings =
    445       gin::CreateHandle(isolate, new EventSenderBindings(sender));
    446   if (bindings.IsEmpty())
    447     return;
    448   v8::Handle<v8::Object> global = context->Global();
    449   global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
    450 }
    451 
    452 gin::ObjectTemplateBuilder
    453 EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
    454   return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
    455       .SetMethod("enableDOMUIEventLogging",
    456                  &EventSenderBindings::EnableDOMUIEventLogging)
    457       .SetMethod("fireKeyboardEventsToElement",
    458                  &EventSenderBindings::FireKeyboardEventsToElement)
    459       .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
    460       .SetMethod("contextClick", &EventSenderBindings::ContextClick)
    461       .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
    462       .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
    463       .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
    464       .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
    465       .SetMethod("setPageZoomFactor", &EventSenderBindings::SetPageZoomFactor)
    466       .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
    467       .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
    468       .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
    469       .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
    470       .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
    471       .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
    472       .SetMethod("setTouchCancelable", &EventSenderBindings::SetTouchCancelable)
    473       .SetMethod("dumpFilenameBeingDragged",
    474                  &EventSenderBindings::DumpFilenameBeingDragged)
    475       .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
    476       .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
    477       .SetMethod("gestureScrollFirstPoint",
    478                  &EventSenderBindings::GestureScrollFirstPoint)
    479       .SetMethod("touchStart", &EventSenderBindings::TouchStart)
    480       .SetMethod("touchMove", &EventSenderBindings::TouchMove)
    481       .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
    482       .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
    483       .SetMethod("leapForward", &EventSenderBindings::LeapForward)
    484       .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
    485       .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
    486       .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
    487       .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
    488       .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
    489       .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
    490       .SetMethod("gestureScrollUpdate",
    491                  &EventSenderBindings::GestureScrollUpdate)
    492       .SetMethod("gestureScrollUpdateWithoutPropagation",
    493                  &EventSenderBindings::GestureScrollUpdateWithoutPropagation)
    494       .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
    495       .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
    496       .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
    497       .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
    498       .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
    499       .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
    500       .SetMethod("gestureTwoFingerTap",
    501                  &EventSenderBindings::GestureTwoFingerTap)
    502       .SetMethod("continuousMouseScrollBy",
    503                  &EventSenderBindings::ContinuousMouseScrollBy)
    504       .SetMethod("keyDown", &EventSenderBindings::KeyDown)
    505       .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
    506       .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
    507       .SetMethod("trackpadScrollBegin",
    508                  &EventSenderBindings::TrackpadScrollBegin)
    509       .SetMethod("trackpadScroll", &EventSenderBindings::TrackpadScroll)
    510       .SetMethod("trackpadScrollEnd", &EventSenderBindings::TrackpadScrollEnd)
    511       .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
    512       .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
    513       .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
    514       .SetMethod("mouseMomentumBegin2",
    515                  &EventSenderBindings::MouseMomentumBegin2)
    516       .SetMethod("mouseMomentumScrollBy",
    517                  &EventSenderBindings::MouseMomentumScrollBy)
    518       .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
    519       .SetMethod("scheduleAsynchronousClick",
    520                  &EventSenderBindings::ScheduleAsynchronousClick)
    521       .SetMethod("scheduleAsynchronousKeyDown",
    522                  &EventSenderBindings::ScheduleAsynchronousKeyDown)
    523       .SetProperty("forceLayoutOnEvents",
    524                    &EventSenderBindings::ForceLayoutOnEvents,
    525                    &EventSenderBindings::SetForceLayoutOnEvents)
    526       .SetProperty("dragMode",
    527                    &EventSenderBindings::IsDragMode,
    528                    &EventSenderBindings::SetIsDragMode)
    529 #if defined(OS_WIN)
    530       .SetProperty("WM_KEYDOWN",
    531                    &EventSenderBindings::WmKeyDown,
    532                    &EventSenderBindings::SetWmKeyDown)
    533       .SetProperty("WM_KEYUP",
    534                    &EventSenderBindings::WmKeyUp,
    535                    &EventSenderBindings::SetWmKeyUp)
    536       .SetProperty("WM_CHAR",
    537                    &EventSenderBindings::WmChar,
    538                    &EventSenderBindings::SetWmChar)
    539       .SetProperty("WM_DEADCHAR",
    540                    &EventSenderBindings::WmDeadChar,
    541                    &EventSenderBindings::SetWmDeadChar)
    542       .SetProperty("WM_SYSKEYDOWN",
    543                    &EventSenderBindings::WmSysKeyDown,
    544                    &EventSenderBindings::SetWmSysKeyDown)
    545       .SetProperty("WM_SYSKEYUP",
    546                    &EventSenderBindings::WmSysKeyUp,
    547                    &EventSenderBindings::SetWmSysKeyUp)
    548       .SetProperty("WM_SYSCHAR",
    549                    &EventSenderBindings::WmSysChar,
    550                    &EventSenderBindings::SetWmSysChar)
    551       .SetProperty("WM_SYSDEADCHAR",
    552                    &EventSenderBindings::WmSysDeadChar,
    553                    &EventSenderBindings::SetWmSysDeadChar);
    554 #else
    555       ;
    556 #endif
    557 }
    558 
    559 void EventSenderBindings::EnableDOMUIEventLogging() {
    560   if (sender_)
    561     sender_->EnableDOMUIEventLogging();
    562 }
    563 
    564 void EventSenderBindings::FireKeyboardEventsToElement() {
    565   if (sender_)
    566     sender_->FireKeyboardEventsToElement();
    567 }
    568 
    569 void EventSenderBindings::ClearKillRing() {
    570   if (sender_)
    571     sender_->ClearKillRing();
    572 }
    573 
    574 std::vector<std::string> EventSenderBindings::ContextClick() {
    575   if (sender_)
    576     return sender_->ContextClick();
    577   return std::vector<std::string>();
    578 }
    579 
    580 void EventSenderBindings::TextZoomIn() {
    581   if (sender_)
    582     sender_->TextZoomIn();
    583 }
    584 
    585 void EventSenderBindings::TextZoomOut() {
    586   if (sender_)
    587     sender_->TextZoomOut();
    588 }
    589 
    590 void EventSenderBindings::ZoomPageIn() {
    591   if (sender_)
    592     sender_->ZoomPageIn();
    593 }
    594 
    595 void EventSenderBindings::ZoomPageOut() {
    596   if (sender_)
    597     sender_->ZoomPageOut();
    598 }
    599 
    600 void EventSenderBindings::SetPageZoomFactor(double factor) {
    601   if (sender_)
    602     sender_->SetPageZoomFactor(factor);
    603 }
    604 
    605 void EventSenderBindings::SetPageScaleFactor(gin::Arguments* args) {
    606   if (!sender_)
    607     return;
    608   float scale_factor;
    609   double x;
    610   double y;
    611   if (args->PeekNext().IsEmpty())
    612     return;
    613   args->GetNext(&scale_factor);
    614   if (args->PeekNext().IsEmpty())
    615     return;
    616   args->GetNext(&x);
    617   if (args->PeekNext().IsEmpty())
    618     return;
    619   args->GetNext(&y);
    620   sender_->SetPageScaleFactor(scale_factor,
    621                               static_cast<int>(x), static_cast<int>(y));
    622 }
    623 
    624 void EventSenderBindings::ClearTouchPoints() {
    625   if (sender_)
    626     sender_->ClearTouchPoints();
    627 }
    628 
    629 void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
    630   if (sender_)
    631     sender_->ReleaseTouchPoint(index);
    632 }
    633 
    634 void EventSenderBindings::UpdateTouchPoint(unsigned index, double x, double y) {
    635   if (sender_)
    636     sender_->UpdateTouchPoint(index, static_cast<float>(x), static_cast<float>(y));
    637 }
    638 
    639 void EventSenderBindings::CancelTouchPoint(unsigned index) {
    640   if (sender_)
    641     sender_->CancelTouchPoint(index);
    642 }
    643 
    644 void EventSenderBindings::SetTouchModifier(const std::string& key_name,
    645                                            bool set_mask) {
    646   if (sender_)
    647     sender_->SetTouchModifier(key_name, set_mask);
    648 }
    649 
    650 void EventSenderBindings::SetTouchCancelable(bool cancelable) {
    651   if (sender_)
    652     sender_->SetTouchCancelable(cancelable);
    653 }
    654 
    655 void EventSenderBindings::DumpFilenameBeingDragged() {
    656   if (sender_)
    657     sender_->DumpFilenameBeingDragged();
    658 }
    659 
    660 void EventSenderBindings::GestureFlingCancel() {
    661   if (sender_)
    662     sender_->GestureFlingCancel();
    663 }
    664 
    665 void EventSenderBindings::GestureFlingStart(float x,
    666                                             float y,
    667                                             float velocity_x,
    668                                             float velocity_y) {
    669   if (sender_)
    670     sender_->GestureFlingStart(x, y, velocity_x, velocity_y);
    671 }
    672 
    673 void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
    674   if (sender_)
    675     sender_->GestureScrollFirstPoint(x, y);
    676 }
    677 
    678 void EventSenderBindings::TouchStart() {
    679   if (sender_)
    680     sender_->TouchStart();
    681 }
    682 
    683 void EventSenderBindings::TouchMove() {
    684   if (sender_)
    685     sender_->TouchMove();
    686 }
    687 
    688 void EventSenderBindings::TouchCancel() {
    689   if (sender_)
    690     sender_->TouchCancel();
    691 }
    692 
    693 void EventSenderBindings::TouchEnd() {
    694   if (sender_)
    695     sender_->TouchEnd();
    696 }
    697 
    698 void EventSenderBindings::LeapForward(int milliseconds) {
    699   if (sender_)
    700     sender_->LeapForward(milliseconds);
    701 }
    702 
    703 void EventSenderBindings::BeginDragWithFiles(
    704     const std::vector<std::string>& files) {
    705   if (sender_)
    706     sender_->BeginDragWithFiles(files);
    707 }
    708 
    709 void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
    710   if (sender_)
    711     sender_->AddTouchPoint(args);
    712 }
    713 
    714 void EventSenderBindings::MouseDragBegin() {
    715   if (sender_)
    716     sender_->MouseDragBegin();
    717 }
    718 
    719 void EventSenderBindings::MouseDragEnd() {
    720   if (sender_)
    721     sender_->MouseDragEnd();
    722 }
    723 
    724 void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
    725   if (sender_)
    726     sender_->GestureScrollBegin(args);
    727 }
    728 
    729 void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
    730   if (sender_)
    731     sender_->GestureScrollEnd(args);
    732 }
    733 
    734 void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
    735   if (sender_)
    736     sender_->GestureScrollUpdate(args);
    737 }
    738 
    739 void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
    740     gin::Arguments* args) {
    741   if (sender_)
    742     sender_->GestureScrollUpdateWithoutPropagation(args);
    743 }
    744 
    745 void EventSenderBindings::GestureTap(gin::Arguments* args) {
    746   if (sender_)
    747     sender_->GestureTap(args);
    748 }
    749 
    750 void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
    751   if (sender_)
    752     sender_->GestureTapDown(args);
    753 }
    754 
    755 void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
    756   if (sender_)
    757     sender_->GestureShowPress(args);
    758 }
    759 
    760 void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
    761   if (sender_)
    762     sender_->GestureTapCancel(args);
    763 }
    764 
    765 void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
    766   if (sender_)
    767     sender_->GestureLongPress(args);
    768 }
    769 
    770 void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
    771   if (sender_)
    772     sender_->GestureLongTap(args);
    773 }
    774 
    775 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
    776   if (sender_)
    777     sender_->GestureTwoFingerTap(args);
    778 }
    779 
    780 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
    781   if (sender_)
    782     sender_->ContinuousMouseScrollBy(args);
    783 }
    784 
    785 void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
    786   if (sender_)
    787     sender_->MouseMoveTo(args);
    788 }
    789 
    790 void EventSenderBindings::TrackpadScrollBegin() {
    791   if (sender_)
    792     sender_->TrackpadScrollBegin();
    793 }
    794 
    795 void EventSenderBindings::TrackpadScroll(gin::Arguments* args) {
    796   if (sender_)
    797     sender_->TrackpadScroll(args);
    798 }
    799 
    800 void EventSenderBindings::TrackpadScrollEnd() {
    801   if (sender_)
    802     sender_->TrackpadScrollEnd();
    803 }
    804 
    805 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
    806   if (sender_)
    807     sender_->MouseScrollBy(args);
    808 }
    809 
    810 void EventSenderBindings::MouseMomentumBegin() {
    811   if (sender_)
    812     sender_->MouseMomentumBegin();
    813 }
    814 
    815 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments* args) {
    816   if (sender_)
    817     sender_->MouseMomentumBegin2(args);
    818 }
    819 
    820 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
    821   if (sender_)
    822     sender_->MouseMomentumScrollBy(args);
    823 }
    824 
    825 void EventSenderBindings::MouseMomentumEnd() {
    826   if (sender_)
    827     sender_->MouseMomentumEnd();
    828 }
    829 
    830 void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
    831   if (!sender_)
    832     return;
    833 
    834   int button_number = 0;
    835   int modifiers = 0;
    836   if (!args->PeekNext().IsEmpty()) {
    837     args->GetNext(&button_number);
    838     if (!args->PeekNext().IsEmpty())
    839       modifiers = GetKeyModifiersFromV8(args->PeekNext());
    840   }
    841   sender_->ScheduleAsynchronousClick(button_number, modifiers);
    842 }
    843 
    844 void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
    845   if (!sender_)
    846     return;
    847 
    848   std::string code_str;
    849   int modifiers = 0;
    850   int location = DOMKeyLocationStandard;
    851   args->GetNext(&code_str);
    852   if (!args->PeekNext().IsEmpty()) {
    853     v8::Handle<v8::Value> value;
    854     args->GetNext(&value);
    855     modifiers = GetKeyModifiersFromV8(value);
    856     if (!args->PeekNext().IsEmpty())
    857       args->GetNext(&location);
    858   }
    859   sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
    860                                        static_cast<KeyLocationCode>(location));
    861 }
    862 
    863 void EventSenderBindings::MouseDown(gin::Arguments* args) {
    864   if (!sender_)
    865     return;
    866 
    867   int button_number = 0;
    868   int modifiers = 0;
    869   if (!args->PeekNext().IsEmpty()) {
    870     args->GetNext(&button_number);
    871     if (!args->PeekNext().IsEmpty())
    872       modifiers = GetKeyModifiersFromV8(args->PeekNext());
    873   }
    874   sender_->MouseDown(button_number, modifiers);
    875 }
    876 
    877 void EventSenderBindings::MouseUp(gin::Arguments* args) {
    878   if (!sender_)
    879     return;
    880 
    881   int button_number = 0;
    882   int modifiers = 0;
    883   if (!args->PeekNext().IsEmpty()) {
    884     args->GetNext(&button_number);
    885     if (!args->PeekNext().IsEmpty())
    886       modifiers = GetKeyModifiersFromV8(args->PeekNext());
    887   }
    888   sender_->MouseUp(button_number, modifiers);
    889 }
    890 
    891 void EventSenderBindings::KeyDown(gin::Arguments* args) {
    892   if (!sender_)
    893     return;
    894 
    895   std::string code_str;
    896   int modifiers = 0;
    897   int location = DOMKeyLocationStandard;
    898   args->GetNext(&code_str);
    899   if (!args->PeekNext().IsEmpty()) {
    900     v8::Handle<v8::Value> value;
    901     args->GetNext(&value);
    902     modifiers = GetKeyModifiersFromV8(value);
    903     if (!args->PeekNext().IsEmpty())
    904       args->GetNext(&location);
    905   }
    906   sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
    907 }
    908 
    909 bool EventSenderBindings::ForceLayoutOnEvents() const {
    910   if (sender_)
    911     return sender_->force_layout_on_events();
    912   return false;
    913 }
    914 
    915 void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
    916   if (sender_)
    917     sender_->set_force_layout_on_events(force);
    918 }
    919 
    920 bool EventSenderBindings::IsDragMode() const {
    921   if (sender_)
    922     return sender_->is_drag_mode();
    923   return true;
    924 }
    925 
    926 void EventSenderBindings::SetIsDragMode(bool drag_mode) {
    927   if (sender_)
    928     sender_->set_is_drag_mode(drag_mode);
    929 }
    930 
    931 #if defined(OS_WIN)
    932 int EventSenderBindings::WmKeyDown() const {
    933   if (sender_)
    934     return sender_->wm_key_down();
    935   return 0;
    936 }
    937 
    938 void EventSenderBindings::SetWmKeyDown(int key_down) {
    939   if (sender_)
    940     sender_->set_wm_key_down(key_down);
    941 }
    942 
    943 int EventSenderBindings::WmKeyUp() const {
    944   if (sender_)
    945     return sender_->wm_key_up();
    946   return 0;
    947 }
    948 
    949 void EventSenderBindings::SetWmKeyUp(int key_up) {
    950   if (sender_)
    951     sender_->set_wm_key_up(key_up);
    952 }
    953 
    954 int EventSenderBindings::WmChar() const {
    955   if (sender_)
    956     return sender_->wm_char();
    957   return 0;
    958 }
    959 
    960 void EventSenderBindings::SetWmChar(int wm_char) {
    961   if (sender_)
    962     sender_->set_wm_char(wm_char);
    963 }
    964 
    965 int EventSenderBindings::WmDeadChar() const {
    966   if (sender_)
    967     return sender_->wm_dead_char();
    968   return 0;
    969 }
    970 
    971 void EventSenderBindings::SetWmDeadChar(int dead_char) {
    972   if (sender_)
    973     sender_->set_wm_dead_char(dead_char);
    974 }
    975 
    976 int EventSenderBindings::WmSysKeyDown() const {
    977   if (sender_)
    978     return sender_->wm_sys_key_down();
    979   return 0;
    980 }
    981 
    982 void EventSenderBindings::SetWmSysKeyDown(int key_down) {
    983   if (sender_)
    984     sender_->set_wm_sys_key_down(key_down);
    985 }
    986 
    987 int EventSenderBindings::WmSysKeyUp() const {
    988   if (sender_)
    989     return sender_->wm_sys_key_up();
    990   return 0;
    991 }
    992 
    993 void EventSenderBindings::SetWmSysKeyUp(int key_up) {
    994   if (sender_)
    995     sender_->set_wm_sys_key_up(key_up);
    996 }
    997 
    998 int EventSenderBindings::WmSysChar() const {
    999   if (sender_)
   1000     return sender_->wm_sys_char();
   1001   return 0;
   1002 }
   1003 
   1004 void EventSenderBindings::SetWmSysChar(int sys_char) {
   1005   if (sender_)
   1006     sender_->set_wm_sys_char(sys_char);
   1007 }
   1008 
   1009 int EventSenderBindings::WmSysDeadChar() const {
   1010   if (sender_)
   1011     return sender_->wm_sys_dead_char();
   1012   return 0;
   1013 }
   1014 
   1015 void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
   1016   if (sender_)
   1017     sender_->set_wm_sys_dead_char(sys_dead_char);
   1018 }
   1019 #endif
   1020 
   1021 // EventSender -----------------------------------------------------------------
   1022 
   1023 WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
   1024 
   1025 WebPoint EventSender::last_mouse_pos_;
   1026 
   1027 WebMouseEvent::Button EventSender::last_button_type_ =
   1028     WebMouseEvent::ButtonNone;
   1029 
   1030 EventSender::SavedEvent::SavedEvent()
   1031     : type(TYPE_UNSPECIFIED),
   1032       button_type(WebMouseEvent::ButtonNone),
   1033       milliseconds(0),
   1034       modifiers(0) {}
   1035 
   1036 EventSender::EventSender(TestInterfaces* interfaces)
   1037     : interfaces_(interfaces),
   1038       delegate_(NULL),
   1039       view_(NULL),
   1040       force_layout_on_events_(false),
   1041       is_drag_mode_(true),
   1042       touch_modifiers_(0),
   1043       touch_cancelable_(true),
   1044       replaying_saved_events_(false),
   1045       current_drag_effects_allowed_(blink::WebDragOperationNone),
   1046       last_click_time_sec_(0),
   1047       current_drag_effect_(blink::WebDragOperationNone),
   1048       time_offset_ms_(0),
   1049       click_count_(0),
   1050 #if defined(OS_WIN)
   1051       wm_key_down_(0),
   1052       wm_key_up_(0),
   1053       wm_char_(0),
   1054       wm_dead_char_(0),
   1055       wm_sys_key_down_(0),
   1056       wm_sys_key_up_(0),
   1057       wm_sys_char_(0),
   1058       wm_sys_dead_char_(0),
   1059 #endif
   1060       weak_factory_(this) {}
   1061 
   1062 EventSender::~EventSender() {}
   1063 
   1064 void EventSender::Reset() {
   1065   DCHECK(current_drag_data_.isNull());
   1066   current_drag_data_.reset();
   1067   current_drag_effect_ = blink::WebDragOperationNone;
   1068   current_drag_effects_allowed_ = blink::WebDragOperationNone;
   1069   if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
   1070     view_->mouseCaptureLost();
   1071   pressed_button_ = WebMouseEvent::ButtonNone;
   1072   is_drag_mode_ = true;
   1073   force_layout_on_events_ = true;
   1074 
   1075 #if defined(OS_WIN)
   1076   wm_key_down_ = WM_KEYDOWN;
   1077   wm_key_up_ = WM_KEYUP;
   1078   wm_char_ = WM_CHAR;
   1079   wm_dead_char_ = WM_DEADCHAR;
   1080   wm_sys_key_down_ = WM_SYSKEYDOWN;
   1081   wm_sys_key_up_ = WM_SYSKEYUP;
   1082   wm_sys_char_ = WM_SYSCHAR;
   1083   wm_sys_dead_char_ = WM_SYSDEADCHAR;
   1084 #endif
   1085 
   1086   last_mouse_pos_ = WebPoint(0, 0);
   1087   last_click_time_sec_ = 0;
   1088   last_click_pos_ = WebPoint(0, 0);
   1089   last_button_type_ = WebMouseEvent::ButtonNone;
   1090   touch_points_.clear();
   1091   last_context_menu_data_.reset();
   1092   task_list_.revokeAll();
   1093   current_gesture_location_ = WebPoint(0, 0);
   1094   mouse_event_queue_.clear();
   1095 
   1096   time_offset_ms_ = 0;
   1097   click_count_ = 0;
   1098 
   1099   touch_modifiers_ = 0;
   1100   touch_cancelable_ = true;
   1101   touch_points_.clear();
   1102 }
   1103 
   1104 void EventSender::Install(WebFrame* frame) {
   1105   EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
   1106 }
   1107 
   1108 void EventSender::SetDelegate(WebTestDelegate* delegate) {
   1109   delegate_ = delegate;
   1110 }
   1111 
   1112 void EventSender::SetWebView(WebView* view) {
   1113   view_ = view;
   1114 }
   1115 
   1116 void EventSender::SetContextMenuData(const WebContextMenuData& data) {
   1117   last_context_menu_data_.reset(new WebContextMenuData(data));
   1118 }
   1119 
   1120 void EventSender::DoDragDrop(const WebDragData& drag_data,
   1121                               WebDragOperationsMask mask) {
   1122   WebMouseEvent event;
   1123   InitMouseEvent(WebInputEvent::MouseDown,
   1124                  pressed_button_,
   1125                  last_mouse_pos_,
   1126                  GetCurrentEventTimeSec(),
   1127                  click_count_,
   1128                  0,
   1129                  &event);
   1130   WebPoint client_point(event.x, event.y);
   1131   WebPoint screen_point(event.globalX, event.globalY);
   1132   current_drag_data_ = drag_data;
   1133   current_drag_effects_allowed_ = mask;
   1134   current_drag_effect_ = view_->dragTargetDragEnter(
   1135       drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
   1136 
   1137   // Finish processing events.
   1138   ReplaySavedEvents();
   1139 }
   1140 
   1141 void EventSender::MouseDown(int button_number, int modifiers) {
   1142   if (force_layout_on_events_)
   1143     view_->layout();
   1144 
   1145   DCHECK_NE(-1, button_number);
   1146 
   1147   WebMouseEvent::Button button_type =
   1148       GetButtonTypeFromButtonNumber(button_number);
   1149 
   1150   UpdateClickCountForButton(button_type);
   1151 
   1152   pressed_button_ = button_type;
   1153 
   1154   WebMouseEvent event;
   1155   InitMouseEvent(WebInputEvent::MouseDown,
   1156                  button_type,
   1157                  last_mouse_pos_,
   1158                  GetCurrentEventTimeSec(),
   1159                  click_count_,
   1160                  modifiers,
   1161                  &event);
   1162   view_->handleInputEvent(event);
   1163 }
   1164 
   1165 void EventSender::MouseUp(int button_number, int modifiers) {
   1166   if (force_layout_on_events_)
   1167     view_->layout();
   1168 
   1169   DCHECK_NE(-1, button_number);
   1170 
   1171   WebMouseEvent::Button button_type =
   1172       GetButtonTypeFromButtonNumber(button_number);
   1173 
   1174   if (is_drag_mode_ && !replaying_saved_events_) {
   1175     SavedEvent saved_event;
   1176     saved_event.type = SavedEvent::TYPE_MOUSE_UP;
   1177     saved_event.button_type = button_type;
   1178     saved_event.modifiers = modifiers;
   1179     mouse_event_queue_.push_back(saved_event);
   1180     ReplaySavedEvents();
   1181   } else {
   1182     WebMouseEvent event;
   1183     InitMouseEvent(WebInputEvent::MouseUp,
   1184                    button_type,
   1185                    last_mouse_pos_,
   1186                    GetCurrentEventTimeSec(),
   1187                    click_count_,
   1188                    modifiers,
   1189                    &event);
   1190     DoMouseUp(event);
   1191   }
   1192 }
   1193 
   1194 void EventSender::KeyDown(const std::string& code_str,
   1195                           int modifiers,
   1196                           KeyLocationCode location) {
   1197   // FIXME: I'm not exactly sure how we should convert the string to a key
   1198   // event. This seems to work in the cases I tested.
   1199   // FIXME: Should we also generate a KEY_UP?
   1200 
   1201   bool generate_char = false;
   1202 
   1203   // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
   1204   // Windows uses \r for "Enter".
   1205   int code = 0;
   1206   int text = 0;
   1207   bool needs_shift_key_modifier = false;
   1208 
   1209   if ("\n" == code_str) {
   1210     generate_char = true;
   1211     text = code = ui::VKEY_RETURN;
   1212   } else if ("rightArrow" == code_str) {
   1213     code = ui::VKEY_RIGHT;
   1214   } else if ("downArrow" == code_str) {
   1215     code = ui::VKEY_DOWN;
   1216   } else if ("leftArrow" == code_str) {
   1217     code = ui::VKEY_LEFT;
   1218   } else if ("upArrow" == code_str) {
   1219     code = ui::VKEY_UP;
   1220   } else if ("insert" == code_str) {
   1221     code = ui::VKEY_INSERT;
   1222   } else if ("delete" == code_str) {
   1223     code = ui::VKEY_DELETE;
   1224   } else if ("pageUp" == code_str) {
   1225     code = ui::VKEY_PRIOR;
   1226   } else if ("pageDown" == code_str) {
   1227     code = ui::VKEY_NEXT;
   1228   } else if ("home" == code_str) {
   1229     code = ui::VKEY_HOME;
   1230   } else if ("end" == code_str) {
   1231     code = ui::VKEY_END;
   1232   } else if ("printScreen" == code_str) {
   1233     code = ui::VKEY_SNAPSHOT;
   1234   } else if ("menu" == code_str) {
   1235     code = ui::VKEY_APPS;
   1236   } else if ("leftControl" == code_str) {
   1237     code = ui::VKEY_LCONTROL;
   1238   } else if ("rightControl" == code_str) {
   1239     code = ui::VKEY_RCONTROL;
   1240   } else if ("leftShift" == code_str) {
   1241     code = ui::VKEY_LSHIFT;
   1242   } else if ("rightShift" == code_str) {
   1243     code = ui::VKEY_RSHIFT;
   1244   } else if ("leftAlt" == code_str) {
   1245     code = ui::VKEY_LMENU;
   1246   } else if ("rightAlt" == code_str) {
   1247     code = ui::VKEY_RMENU;
   1248   } else if ("numLock" == code_str) {
   1249     code = ui::VKEY_NUMLOCK;
   1250   } else {
   1251     // Compare the input string with the function-key names defined by the
   1252     // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
   1253     // name, set its key code.
   1254     for (int i = 1; i <= 24; ++i) {
   1255       std::string function_key_name = base::StringPrintf("F%d", i);
   1256       if (function_key_name == code_str) {
   1257         code = ui::VKEY_F1 + (i - 1);
   1258         break;
   1259       }
   1260     }
   1261     if (!code) {
   1262       WebString web_code_str =
   1263           WebString::fromUTF8(code_str.data(), code_str.size());
   1264       DCHECK_EQ(1u, web_code_str.length());
   1265       text = code = web_code_str.at(0);
   1266       needs_shift_key_modifier = NeedsShiftModifier(code);
   1267       if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
   1268         code -= 'a' - 'A';
   1269       generate_char = true;
   1270     }
   1271 
   1272     if ("(" == code_str) {
   1273       code = '9';
   1274       needs_shift_key_modifier = true;
   1275     }
   1276   }
   1277 
   1278   // For one generated keyboard event, we need to generate a keyDown/keyUp
   1279   // pair;
   1280   // On Windows, we might also need to generate a char event to mimic the
   1281   // Windows event flow; on other platforms we create a merged event and test
   1282   // the event flow that that platform provides.
   1283   WebKeyboardEvent event_down;
   1284   event_down.type = WebInputEvent::RawKeyDown;
   1285   event_down.modifiers = modifiers;
   1286   event_down.windowsKeyCode = code;
   1287 
   1288   if (generate_char) {
   1289     event_down.text[0] = text;
   1290     event_down.unmodifiedText[0] = text;
   1291   }
   1292 
   1293   event_down.setKeyIdentifierFromWindowsKeyCode();
   1294 
   1295   if (event_down.modifiers != 0)
   1296     event_down.isSystemKey = IsSystemKeyEvent(event_down);
   1297 
   1298   if (needs_shift_key_modifier)
   1299     event_down.modifiers |= WebInputEvent::ShiftKey;
   1300 
   1301   // See if KeyLocation argument is given.
   1302   if (location == DOMKeyLocationNumpad)
   1303     event_down.modifiers |= WebInputEvent::IsKeyPad;
   1304 
   1305   WebKeyboardEvent event_up;
   1306   event_up = event_down;
   1307   event_up.type = WebInputEvent::KeyUp;
   1308   // EventSender.m forces a layout here, with at least one
   1309   // test (fast/forms/focus-control-to-page.html) relying on this.
   1310   if (force_layout_on_events_)
   1311     view_->layout();
   1312 
   1313   // In the browser, if a keyboard event corresponds to an editor command,
   1314   // the command will be dispatched to the renderer just before dispatching
   1315   // the keyboard event, and then it will be executed in the
   1316   // RenderView::handleCurrentKeyboardEvent() method.
   1317   // We just simulate the same behavior here.
   1318   std::string edit_command;
   1319   if (GetEditCommand(event_down, &edit_command))
   1320     delegate_->setEditCommand(edit_command, "");
   1321 
   1322   view_->handleInputEvent(event_down);
   1323 
   1324   if (code == ui::VKEY_ESCAPE && !current_drag_data_.isNull()) {
   1325     WebMouseEvent event;
   1326     InitMouseEvent(WebInputEvent::MouseDown,
   1327                    pressed_button_,
   1328                    last_mouse_pos_,
   1329                    GetCurrentEventTimeSec(),
   1330                    click_count_,
   1331                    0,
   1332                    &event);
   1333     FinishDragAndDrop(event, blink::WebDragOperationNone);
   1334   }
   1335 
   1336   delegate_->clearEditCommand();
   1337 
   1338   if (generate_char) {
   1339     WebKeyboardEvent event_char = event_up;
   1340     event_char.type = WebInputEvent::Char;
   1341     event_char.keyIdentifier[0] = '\0';
   1342     view_->handleInputEvent(event_char);
   1343   }
   1344 
   1345   view_->handleInputEvent(event_up);
   1346 }
   1347 
   1348 void EventSender::EnableDOMUIEventLogging() {}
   1349 
   1350 void EventSender::FireKeyboardEventsToElement() {}
   1351 
   1352 void EventSender::ClearKillRing() {}
   1353 
   1354 std::vector<std::string> EventSender::ContextClick() {
   1355   if (force_layout_on_events_) {
   1356     view_->layout();
   1357   }
   1358 
   1359   UpdateClickCountForButton(WebMouseEvent::ButtonRight);
   1360 
   1361   // Clears last context menu data because we need to know if the context menu
   1362   // be requested after following mouse events.
   1363   last_context_menu_data_.reset();
   1364 
   1365   // Generate right mouse down and up.
   1366   WebMouseEvent event;
   1367   // This is a hack to work around only allowing a single pressed button since
   1368   // we want to test the case where both the left and right mouse buttons are
   1369   // pressed.
   1370   if (pressed_button_ == WebMouseEvent::ButtonNone) {
   1371     pressed_button_ = WebMouseEvent::ButtonRight;
   1372   }
   1373   InitMouseEvent(WebInputEvent::MouseDown,
   1374                  WebMouseEvent::ButtonRight,
   1375                  last_mouse_pos_,
   1376                  GetCurrentEventTimeSec(),
   1377                  click_count_,
   1378                  0,
   1379                  &event);
   1380   view_->handleInputEvent(event);
   1381 
   1382 #if defined(OS_WIN)
   1383   InitMouseEvent(WebInputEvent::MouseUp,
   1384                  WebMouseEvent::ButtonRight,
   1385                  last_mouse_pos_,
   1386                  GetCurrentEventTimeSec(),
   1387                  click_count_,
   1388                  0,
   1389                  &event);
   1390   view_->handleInputEvent(event);
   1391 
   1392   pressed_button_= WebMouseEvent::ButtonNone;
   1393 #endif
   1394 
   1395   std::vector<std::string> menu_items = MakeMenuItemStringsFor(last_context_menu_data_.get(), delegate_);
   1396   last_context_menu_data_.reset();
   1397   return menu_items;
   1398 }
   1399 
   1400 void EventSender::TextZoomIn() {
   1401   view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
   1402 }
   1403 
   1404 void EventSender::TextZoomOut() {
   1405   view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
   1406 }
   1407 
   1408 void EventSender::ZoomPageIn() {
   1409   const std::vector<WebTestProxyBase*>& window_list = interfaces_->windowList();
   1410 
   1411   for (size_t i = 0; i < window_list.size(); ++i) {
   1412     window_list.at(i)->GetWebView()->setZoomLevel(
   1413         window_list.at(i)->GetWebView()->zoomLevel() + 1);
   1414   }
   1415 }
   1416 
   1417 void EventSender::ZoomPageOut() {
   1418   const std::vector<WebTestProxyBase*>& window_list = interfaces_->windowList();
   1419 
   1420   for (size_t i = 0; i < window_list.size(); ++i) {
   1421     window_list.at(i)->GetWebView()->setZoomLevel(
   1422         window_list.at(i)->GetWebView()->zoomLevel() - 1);
   1423   }
   1424 }
   1425 
   1426 void EventSender::SetPageZoomFactor(double zoom_factor) {
   1427   const std::vector<WebTestProxyBase*>& window_list = interfaces_->windowList();
   1428 
   1429   for (size_t i = 0; i < window_list.size(); ++i) {
   1430     window_list.at(i)->GetWebView()->setZoomLevel(
   1431         ZoomFactorToZoomLevel(zoom_factor));
   1432   }
   1433 }
   1434 
   1435 void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
   1436   view_->setPageScaleFactorLimits(scale_factor, scale_factor);
   1437   view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
   1438 }
   1439 
   1440 void EventSender::ClearTouchPoints() {
   1441   touch_points_.clear();
   1442 }
   1443 
   1444 void EventSender::ThrowTouchPointError() {
   1445   v8::Isolate* isolate = blink::mainThreadIsolate();
   1446   isolate->ThrowException(v8::Exception::TypeError(
   1447       gin::StringToV8(isolate, "Invalid touch point.")));
   1448 }
   1449 
   1450 void EventSender::ReleaseTouchPoint(unsigned index) {
   1451   if (index >= touch_points_.size()) {
   1452     ThrowTouchPointError();
   1453     return;
   1454   }
   1455 
   1456   WebTouchPoint* touch_point = &touch_points_[index];
   1457   touch_point->state = WebTouchPoint::StateReleased;
   1458 }
   1459 
   1460 void EventSender::UpdateTouchPoint(unsigned index, float x, float y) {
   1461   if (index >= touch_points_.size()) {
   1462     ThrowTouchPointError();
   1463     return;
   1464   }
   1465 
   1466   WebTouchPoint* touch_point = &touch_points_[index];
   1467   touch_point->state = WebTouchPoint::StateMoved;
   1468   touch_point->position = WebFloatPoint(x, y);
   1469   touch_point->screenPosition = touch_point->position;
   1470 }
   1471 
   1472 void EventSender::CancelTouchPoint(unsigned index) {
   1473   if (index >= touch_points_.size()) {
   1474     ThrowTouchPointError();
   1475     return;
   1476   }
   1477 
   1478   WebTouchPoint* touch_point = &touch_points_[index];
   1479   touch_point->state = WebTouchPoint::StateCancelled;
   1480 }
   1481 
   1482 void EventSender::SetTouchModifier(const std::string& key_name,
   1483                                     bool set_mask) {
   1484   int mask = 0;
   1485   if (key_name == "shift")
   1486     mask = WebInputEvent::ShiftKey;
   1487   else if (key_name == "alt")
   1488     mask = WebInputEvent::AltKey;
   1489   else if (key_name == "ctrl")
   1490     mask = WebInputEvent::ControlKey;
   1491   else if (key_name == "meta")
   1492     mask = WebInputEvent::MetaKey;
   1493 
   1494   if (set_mask)
   1495     touch_modifiers_ |= mask;
   1496   else
   1497     touch_modifiers_ &= ~mask;
   1498 }
   1499 
   1500 void EventSender::SetTouchCancelable(bool cancelable) {
   1501   touch_cancelable_ = cancelable;
   1502 }
   1503 
   1504 void EventSender::DumpFilenameBeingDragged() {
   1505   WebString filename;
   1506   WebVector<WebDragData::Item> items = current_drag_data_.items();
   1507   for (size_t i = 0; i < items.size(); ++i) {
   1508     if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
   1509       filename = items[i].title;
   1510       break;
   1511     }
   1512   }
   1513   delegate_->printMessage(std::string("Filename being dragged: ") +
   1514                           filename.utf8().data() + "\n");
   1515 }
   1516 
   1517 void EventSender::GestureFlingCancel() {
   1518   WebGestureEvent event;
   1519   event.type = WebInputEvent::GestureFlingCancel;
   1520   event.timeStampSeconds = GetCurrentEventTimeSec();
   1521 
   1522   if (force_layout_on_events_)
   1523     view_->layout();
   1524 
   1525   view_->handleInputEvent(event);
   1526 }
   1527 
   1528 void EventSender::GestureFlingStart(float x,
   1529                                      float y,
   1530                                      float velocity_x,
   1531                                      float velocity_y) {
   1532   WebGestureEvent event;
   1533   event.type = WebInputEvent::GestureFlingStart;
   1534 
   1535   event.x = x;
   1536   event.y = y;
   1537   event.globalX = event.x;
   1538   event.globalY = event.y;
   1539 
   1540   event.data.flingStart.velocityX = velocity_x;
   1541   event.data.flingStart.velocityY = velocity_y;
   1542   event.timeStampSeconds = GetCurrentEventTimeSec();
   1543 
   1544   if (force_layout_on_events_)
   1545     view_->layout();
   1546 
   1547   view_->handleInputEvent(event);
   1548 }
   1549 
   1550 void EventSender::GestureScrollFirstPoint(int x, int y) {
   1551   current_gesture_location_ = WebPoint(x, y);
   1552 }
   1553 
   1554 void EventSender::TouchStart() {
   1555   SendCurrentTouchEvent(WebInputEvent::TouchStart);
   1556 }
   1557 
   1558 void EventSender::TouchMove() {
   1559   SendCurrentTouchEvent(WebInputEvent::TouchMove);
   1560 }
   1561 
   1562 void EventSender::TouchCancel() {
   1563   SendCurrentTouchEvent(WebInputEvent::TouchCancel);
   1564 }
   1565 
   1566 void EventSender::TouchEnd() {
   1567   SendCurrentTouchEvent(WebInputEvent::TouchEnd);
   1568 }
   1569 
   1570 void EventSender::LeapForward(int milliseconds) {
   1571   if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
   1572       !replaying_saved_events_) {
   1573     SavedEvent saved_event;
   1574     saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
   1575     saved_event.milliseconds = milliseconds;
   1576     mouse_event_queue_.push_back(saved_event);
   1577   } else {
   1578     DoLeapForward(milliseconds);
   1579   }
   1580 }
   1581 
   1582 void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
   1583   current_drag_data_.initialize();
   1584   WebVector<WebString> absolute_filenames(files.size());
   1585   for (size_t i = 0; i < files.size(); ++i) {
   1586     WebDragData::Item item;
   1587     item.storageType = WebDragData::Item::StorageTypeFilename;
   1588     item.filenameData = delegate_->getAbsoluteWebStringFromUTF8Path(files[i]);
   1589     current_drag_data_.addItem(item);
   1590     absolute_filenames[i] = item.filenameData;
   1591   }
   1592   current_drag_data_.setFilesystemId(
   1593       delegate_->registerIsolatedFileSystem(absolute_filenames));
   1594   current_drag_effects_allowed_ = blink::WebDragOperationCopy;
   1595 
   1596   // Provide a drag source.
   1597   view_->dragTargetDragEnter(current_drag_data_,
   1598                              last_mouse_pos_,
   1599                              last_mouse_pos_,
   1600                              current_drag_effects_allowed_,
   1601                              0);
   1602   // |is_drag_mode_| saves events and then replays them later. We don't
   1603   // need/want that.
   1604   is_drag_mode_ = false;
   1605 
   1606   // Make the rest of eventSender think a drag is in progress.
   1607   pressed_button_ = WebMouseEvent::ButtonLeft;
   1608 }
   1609 
   1610 void EventSender::AddTouchPoint(gin::Arguments* args) {
   1611   double x;
   1612   double y;
   1613   args->GetNext(&x);
   1614   args->GetNext(&y);
   1615 
   1616   WebTouchPoint touch_point;
   1617   touch_point.state = WebTouchPoint::StatePressed;
   1618   touch_point.position = WebFloatPoint(static_cast<float>(x),
   1619                                        static_cast<float>(y));
   1620   touch_point.screenPosition = touch_point.position;
   1621 
   1622   if (!args->PeekNext().IsEmpty()) {
   1623     double radius_x;
   1624     if (!args->GetNext(&radius_x)) {
   1625       args->ThrowError();
   1626       return;
   1627     }
   1628 
   1629     double radius_y = radius_x;
   1630     if (!args->PeekNext().IsEmpty()) {
   1631       if (!args->GetNext(&radius_y)) {
   1632         args->ThrowError();
   1633         return;
   1634       }
   1635     }
   1636 
   1637     touch_point.radiusX = static_cast<float>(radius_x);
   1638     touch_point.radiusY = static_cast<float>(radius_y);
   1639   }
   1640 
   1641   int lowest_id = 0;
   1642   for (size_t i = 0; i < touch_points_.size(); i++) {
   1643     if (touch_points_[i].id == lowest_id)
   1644       lowest_id++;
   1645   }
   1646   touch_point.id = lowest_id;
   1647   touch_points_.push_back(touch_point);
   1648 }
   1649 
   1650 void EventSender::MouseDragBegin() {
   1651   WebMouseWheelEvent event;
   1652   InitMouseEvent(WebInputEvent::MouseWheel,
   1653                  WebMouseEvent::ButtonNone,
   1654                  last_mouse_pos_,
   1655                  GetCurrentEventTimeSec(),
   1656                  click_count_,
   1657                  0,
   1658                  &event);
   1659   event.phase = WebMouseWheelEvent::PhaseBegan;
   1660   event.hasPreciseScrollingDeltas = true;
   1661   view_->handleInputEvent(event);
   1662 }
   1663 
   1664 void EventSender::MouseDragEnd() {
   1665   WebMouseWheelEvent event;
   1666   InitMouseEvent(WebInputEvent::MouseWheel,
   1667                  WebMouseEvent::ButtonNone,
   1668                  last_mouse_pos_,
   1669                  GetCurrentEventTimeSec(),
   1670                  click_count_,
   1671                  0,
   1672                  &event);
   1673   event.phase = WebMouseWheelEvent::PhaseEnded;
   1674   event.hasPreciseScrollingDeltas = true;
   1675   view_->handleInputEvent(event);
   1676 }
   1677 
   1678 void EventSender::GestureScrollBegin(gin::Arguments* args) {
   1679   GestureEvent(WebInputEvent::GestureScrollBegin, args);
   1680 }
   1681 
   1682 void EventSender::GestureScrollEnd(gin::Arguments* args) {
   1683   GestureEvent(WebInputEvent::GestureScrollEnd, args);
   1684 }
   1685 
   1686 void EventSender::GestureScrollUpdate(gin::Arguments* args) {
   1687   GestureEvent(WebInputEvent::GestureScrollUpdate, args);
   1688 }
   1689 
   1690 void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
   1691   GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
   1692 }
   1693 
   1694 void EventSender::GestureTap(gin::Arguments* args) {
   1695   GestureEvent(WebInputEvent::GestureTap, args);
   1696 }
   1697 
   1698 void EventSender::GestureTapDown(gin::Arguments* args) {
   1699   GestureEvent(WebInputEvent::GestureTapDown, args);
   1700 }
   1701 
   1702 void EventSender::GestureShowPress(gin::Arguments* args) {
   1703   GestureEvent(WebInputEvent::GestureShowPress, args);
   1704 }
   1705 
   1706 void EventSender::GestureTapCancel(gin::Arguments* args) {
   1707   GestureEvent(WebInputEvent::GestureTapCancel, args);
   1708 }
   1709 
   1710 void EventSender::GestureLongPress(gin::Arguments* args) {
   1711   GestureEvent(WebInputEvent::GestureLongPress, args);
   1712 }
   1713 
   1714 void EventSender::GestureLongTap(gin::Arguments* args) {
   1715   GestureEvent(WebInputEvent::GestureLongTap, args);
   1716 }
   1717 
   1718 void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
   1719   GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
   1720 }
   1721 
   1722 void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
   1723   WebMouseWheelEvent event;
   1724   InitMouseWheelEvent(args, true, &event);
   1725   view_->handleInputEvent(event);
   1726 }
   1727 
   1728 void EventSender::MouseMoveTo(gin::Arguments* args) {
   1729   if (force_layout_on_events_)
   1730     view_->layout();
   1731 
   1732   double x;
   1733   double y;
   1734   args->GetNext(&x);
   1735   args->GetNext(&y);
   1736   WebPoint mouse_pos(static_cast<int>(x), static_cast<int>(y));
   1737 
   1738   int modifiers = 0;
   1739   if (!args->PeekNext().IsEmpty())
   1740     modifiers = GetKeyModifiersFromV8(args->PeekNext());
   1741 
   1742   if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
   1743       !replaying_saved_events_) {
   1744     SavedEvent saved_event;
   1745     saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
   1746     saved_event.pos = mouse_pos;
   1747     saved_event.modifiers = modifiers;
   1748     mouse_event_queue_.push_back(saved_event);
   1749   } else {
   1750     WebMouseEvent event;
   1751     InitMouseEvent(WebInputEvent::MouseMove,
   1752                    pressed_button_,
   1753                    mouse_pos,
   1754                    GetCurrentEventTimeSec(),
   1755                    click_count_,
   1756                    modifiers,
   1757                    &event);
   1758     DoMouseMove(event);
   1759   }
   1760 }
   1761 
   1762 void EventSender::TrackpadScrollBegin() {
   1763   WebMouseWheelEvent event;
   1764   InitMouseEvent(WebInputEvent::MouseWheel,
   1765                  WebMouseEvent::ButtonNone,
   1766                  last_mouse_pos_,
   1767                  GetCurrentEventTimeSec(),
   1768                  click_count_,
   1769                  0,
   1770                  &event);
   1771   event.phase = blink::WebMouseWheelEvent::PhaseBegan;
   1772   event.hasPreciseScrollingDeltas = true;
   1773   view_->handleInputEvent(event);
   1774 }
   1775 
   1776 void EventSender::TrackpadScroll(gin::Arguments* args) {
   1777   WebMouseWheelEvent event;
   1778   InitMouseWheelEvent(args, true, &event);
   1779   event.phase = blink::WebMouseWheelEvent::PhaseChanged;
   1780   event.hasPreciseScrollingDeltas = true;
   1781   view_->handleInputEvent(event);
   1782 }
   1783 
   1784 void EventSender::TrackpadScrollEnd() {
   1785   WebMouseWheelEvent event;
   1786   InitMouseEvent(WebInputEvent::MouseWheel,
   1787                  WebMouseEvent::ButtonNone,
   1788                  last_mouse_pos_,
   1789                  GetCurrentEventTimeSec(),
   1790                  click_count_,
   1791                  0,
   1792                  &event);
   1793   event.phase = WebMouseWheelEvent::PhaseEnded;
   1794   event.hasPreciseScrollingDeltas = true;
   1795   view_->handleInputEvent(event);
   1796 }
   1797 
   1798 void EventSender::MouseScrollBy(gin::Arguments* args) {
   1799    WebMouseWheelEvent event;
   1800   InitMouseWheelEvent(args, false, &event);
   1801   view_->handleInputEvent(event);
   1802 }
   1803 
   1804 void EventSender::MouseMomentumBegin() {
   1805   WebMouseWheelEvent event;
   1806   InitMouseEvent(WebInputEvent::MouseWheel,
   1807                  WebMouseEvent::ButtonNone,
   1808                  last_mouse_pos_,
   1809                  GetCurrentEventTimeSec(),
   1810                  click_count_,
   1811                  0,
   1812                  &event);
   1813   event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
   1814   event.hasPreciseScrollingDeltas = true;
   1815   view_->handleInputEvent(event);
   1816 }
   1817 
   1818 void EventSender::MouseMomentumBegin2(gin::Arguments* args) {
   1819   WebMouseWheelEvent event;
   1820   InitMouseWheelEvent(args, true, &event);
   1821   event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
   1822   event.hasPreciseScrollingDeltas = true;
   1823   view_->handleInputEvent(event);
   1824 }
   1825 
   1826 void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
   1827   WebMouseWheelEvent event;
   1828   InitMouseWheelEvent(args, true, &event);
   1829   event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
   1830   event.hasPreciseScrollingDeltas = true;
   1831   view_->handleInputEvent(event);
   1832 }
   1833 
   1834 void EventSender::MouseMomentumEnd() {
   1835   WebMouseWheelEvent event;
   1836   InitMouseEvent(WebInputEvent::MouseWheel,
   1837                  WebMouseEvent::ButtonNone,
   1838                  last_mouse_pos_,
   1839                  GetCurrentEventTimeSec(),
   1840                  click_count_,
   1841                  0,
   1842                  &event);
   1843   event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
   1844   event.hasPreciseScrollingDeltas = true;
   1845   view_->handleInputEvent(event);
   1846 }
   1847 
   1848 void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
   1849   delegate_->postTask(new MouseDownTask(this, button_number, modifiers));
   1850   delegate_->postTask(new MouseUpTask(this, button_number, modifiers));
   1851 }
   1852 
   1853 void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
   1854                                               int modifiers,
   1855                                               KeyLocationCode location) {
   1856   delegate_->postTask(new KeyDownTask(this, code_str, modifiers, location));
   1857 }
   1858 
   1859 double EventSender::GetCurrentEventTimeSec() {
   1860   return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
   1861 }
   1862 
   1863 void EventSender::DoLeapForward(int milliseconds) {
   1864   time_offset_ms_ += milliseconds;
   1865 }
   1866 
   1867 void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
   1868   DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
   1869             touch_points_.size());
   1870   if (force_layout_on_events_)
   1871     view_->layout();
   1872 
   1873   WebTouchEvent touch_event;
   1874   touch_event.type = type;
   1875   touch_event.modifiers = touch_modifiers_;
   1876   touch_event.cancelable = touch_cancelable_;
   1877   touch_event.timeStampSeconds = GetCurrentEventTimeSec();
   1878   touch_event.touchesLength = touch_points_.size();
   1879   for (size_t i = 0; i < touch_points_.size(); ++i)
   1880     touch_event.touches[i] = touch_points_[i];
   1881   view_->handleInputEvent(touch_event);
   1882 
   1883   for (size_t i = 0; i < touch_points_.size(); ++i) {
   1884     WebTouchPoint* touch_point = &touch_points_[i];
   1885     if (touch_point->state == WebTouchPoint::StateReleased) {
   1886       touch_points_.erase(touch_points_.begin() + i);
   1887       --i;
   1888     } else
   1889       touch_point->state = WebTouchPoint::StateStationary;
   1890   }
   1891 }
   1892 
   1893 void EventSender::GestureEvent(WebInputEvent::Type type,
   1894                                gin::Arguments* args) {
   1895   double x;
   1896   double y;
   1897   args->GetNext(&x);
   1898   args->GetNext(&y);
   1899   WebPoint point(x, y);
   1900 
   1901   WebGestureEvent event;
   1902   event.type = type;
   1903 
   1904   switch (type) {
   1905     case WebInputEvent::GestureScrollUpdate:
   1906     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
   1907       event.data.scrollUpdate.deltaX = static_cast<float>(x);
   1908       event.data.scrollUpdate.deltaY = static_cast<float>(y);
   1909       event.x = current_gesture_location_.x;
   1910       event.y = current_gesture_location_.y;
   1911       current_gesture_location_.x =
   1912           current_gesture_location_.x + event.data.scrollUpdate.deltaX;
   1913       current_gesture_location_.y =
   1914           current_gesture_location_.y + event.data.scrollUpdate.deltaY;
   1915       break;
   1916     case WebInputEvent::GestureScrollBegin:
   1917       current_gesture_location_ = WebPoint(point.x, point.y);
   1918       event.x = current_gesture_location_.x;
   1919       event.y = current_gesture_location_.y;
   1920       break;
   1921     case WebInputEvent::GestureScrollEnd:
   1922     case WebInputEvent::GestureFlingStart:
   1923       event.x = current_gesture_location_.x;
   1924       event.y = current_gesture_location_.y;
   1925       break;
   1926     case WebInputEvent::GestureTap:
   1927       if (!args->PeekNext().IsEmpty()) {
   1928         float tap_count;
   1929         if (!args->GetNext(&tap_count)) {
   1930           args->ThrowError();
   1931           return;
   1932         }
   1933         event.data.tap.tapCount = tap_count;
   1934       } else {
   1935         event.data.tap.tapCount = 1;
   1936       }
   1937 
   1938       event.x = point.x;
   1939       event.y = point.y;
   1940       break;
   1941     case WebInputEvent::GestureTapUnconfirmed:
   1942       if (!args->PeekNext().IsEmpty()) {
   1943         float tap_count;
   1944         if (!args->GetNext(&tap_count)) {
   1945           args->ThrowError();
   1946           return;
   1947         }
   1948         event.data.tap.tapCount = tap_count;
   1949       } else {
   1950         event.data.tap.tapCount = 1;
   1951       }
   1952       event.x = point.x;
   1953       event.y = point.y;
   1954       break;
   1955     case WebInputEvent::GestureTapDown:
   1956       event.x = point.x;
   1957       event.y = point.y;
   1958       if (!args->PeekNext().IsEmpty()) {
   1959         float width;
   1960         if (!args->GetNext(&width)) {
   1961           args->ThrowError();
   1962           return;
   1963         }
   1964         event.data.tapDown.width = width;
   1965       }
   1966       if (!args->PeekNext().IsEmpty()) {
   1967         float height;
   1968         if (!args->GetNext(&height)) {
   1969           args->ThrowError();
   1970           return;
   1971         }
   1972         event.data.tapDown.height = height;
   1973       }
   1974       break;
   1975     case WebInputEvent::GestureShowPress:
   1976       event.x = point.x;
   1977       event.y = point.y;
   1978       if (!args->PeekNext().IsEmpty()) {
   1979         float width;
   1980         if (!args->GetNext(&width)) {
   1981           args->ThrowError();
   1982           return;
   1983         }
   1984         event.data.showPress.width = width;
   1985         if (!args->PeekNext().IsEmpty()) {
   1986           float height;
   1987           if (!args->GetNext(&height)) {
   1988             args->ThrowError();
   1989             return;
   1990           }
   1991           event.data.showPress.height = height;
   1992         }
   1993       }
   1994       break;
   1995     case WebInputEvent::GestureTapCancel:
   1996       event.x = point.x;
   1997       event.y = point.y;
   1998       break;
   1999     case WebInputEvent::GestureLongPress:
   2000       event.x = point.x;
   2001       event.y = point.y;
   2002       if (!args->PeekNext().IsEmpty()) {
   2003         float width;
   2004         if (!args->GetNext(&width)) {
   2005           args->ThrowError();
   2006           return;
   2007         }
   2008         event.data.longPress.width = width;
   2009         if (!args->PeekNext().IsEmpty()) {
   2010           float height;
   2011           if (!args->GetNext(&height)) {
   2012             args->ThrowError();
   2013             return;
   2014           }
   2015           event.data.longPress.height = height;
   2016         }
   2017       }
   2018       break;
   2019     case WebInputEvent::GestureLongTap:
   2020       event.x = point.x;
   2021       event.y = point.y;
   2022       if (!args->PeekNext().IsEmpty()) {
   2023         float width;
   2024         if (!args->GetNext(&width)) {
   2025           args->ThrowError();
   2026           return;
   2027         }
   2028         event.data.longPress.width = width;
   2029         if (!args->PeekNext().IsEmpty()) {
   2030           float height;
   2031           if (!args->GetNext(&height)) {
   2032             args->ThrowError();
   2033             return;
   2034           }
   2035           event.data.longPress.height = height;
   2036         }
   2037       }
   2038       break;
   2039     case WebInputEvent::GestureTwoFingerTap:
   2040       event.x = point.x;
   2041       event.y = point.y;
   2042       if (!args->PeekNext().IsEmpty()) {
   2043         float first_finger_width;
   2044         if (!args->GetNext(&first_finger_width)) {
   2045           args->ThrowError();
   2046           return;
   2047         }
   2048         event.data.twoFingerTap.firstFingerWidth = first_finger_width;
   2049         if (!args->PeekNext().IsEmpty()) {
   2050           float first_finger_height;
   2051           if (!args->GetNext(&first_finger_height)) {
   2052             args->ThrowError();
   2053             return;
   2054           }
   2055           event.data.twoFingerTap.firstFingerHeight = first_finger_height;
   2056         }
   2057       }
   2058       break;
   2059     default:
   2060       NOTREACHED();
   2061   }
   2062 
   2063   event.globalX = event.x;
   2064   event.globalY = event.y;
   2065   event.timeStampSeconds = GetCurrentEventTimeSec();
   2066 
   2067   if (force_layout_on_events_)
   2068     view_->layout();
   2069 
   2070   bool result = view_->handleInputEvent(event);
   2071 
   2072   // Long press might start a drag drop session. Complete it if so.
   2073   if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
   2074     WebMouseEvent mouse_event;
   2075     InitMouseEvent(WebInputEvent::MouseDown,
   2076                    pressed_button_,
   2077                    point,
   2078                    GetCurrentEventTimeSec(),
   2079                    click_count_,
   2080                    0,
   2081                    &mouse_event);
   2082 
   2083     FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
   2084   }
   2085   args->Return(result);
   2086 }
   2087 
   2088 void EventSender::UpdateClickCountForButton(
   2089     WebMouseEvent::Button button_type) {
   2090   if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
   2091        kMultipleClickTimeSec) &&
   2092       (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
   2093       (button_type == last_button_type_)) {
   2094     ++click_count_;
   2095   } else {
   2096     click_count_ = 1;
   2097     last_button_type_ = button_type;
   2098   }
   2099 }
   2100 
   2101 void EventSender::InitMouseWheelEvent(gin::Arguments* args,
   2102                                       bool continuous,
   2103                                       WebMouseWheelEvent* event) {
   2104   // Force a layout here just to make sure every position has been
   2105   // determined before we send events (as well as all the other methods
   2106   // that send an event do).
   2107   if (force_layout_on_events_)
   2108     view_->layout();
   2109 
   2110   double horizontal;
   2111   if (!args->GetNext(&horizontal)) {
   2112     args->ThrowError();
   2113     return;
   2114   }
   2115   double vertical;
   2116   if (!args->GetNext(&vertical)) {
   2117     args->ThrowError();
   2118     return;
   2119   }
   2120 
   2121   bool paged = false;
   2122   bool has_precise_scrolling_deltas = false;
   2123   int modifiers = 0;
   2124   if (!args->PeekNext().IsEmpty()) {
   2125     args->GetNext(&paged);
   2126     if (!args->PeekNext().IsEmpty()) {
   2127       args->GetNext(&has_precise_scrolling_deltas);
   2128       if (!args->PeekNext().IsEmpty())
   2129         modifiers = GetKeyModifiersFromV8(args->PeekNext());
   2130     }
   2131   }
   2132 
   2133   InitMouseEvent(WebInputEvent::MouseWheel,
   2134                  pressed_button_,
   2135                  last_mouse_pos_,
   2136                  GetCurrentEventTimeSec(),
   2137                  click_count_,
   2138                  modifiers,
   2139                  event);
   2140   event->wheelTicksX = static_cast<float>(horizontal);
   2141   event->wheelTicksY = static_cast<float>(vertical);
   2142   event->deltaX = event->wheelTicksX;
   2143   event->deltaY = event->wheelTicksY;
   2144   event->scrollByPage = paged;
   2145   event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
   2146 
   2147   if (continuous) {
   2148     event->wheelTicksX /= kScrollbarPixelsPerTick;
   2149     event->wheelTicksY /= kScrollbarPixelsPerTick;
   2150   } else {
   2151     event->deltaX *= kScrollbarPixelsPerTick;
   2152     event->deltaY *= kScrollbarPixelsPerTick;
   2153   }
   2154 }
   2155 
   2156 void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
   2157                                      blink::WebDragOperation drag_effect) {
   2158   WebPoint client_point(e.x, e.y);
   2159   WebPoint screen_point(e.globalX, e.globalY);
   2160   current_drag_effect_ = drag_effect;
   2161   if (current_drag_effect_) {
   2162     // Specifically pass any keyboard modifiers to the drop method. This allows
   2163     // tests to control the drop type (i.e. copy or move).
   2164     view_->dragTargetDrop(client_point, screen_point, e.modifiers);
   2165   } else {
   2166     view_->dragTargetDragLeave();
   2167   }
   2168   view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
   2169   view_->dragSourceSystemDragEnded();
   2170 
   2171   current_drag_data_.reset();
   2172 }
   2173 
   2174 void EventSender::DoMouseUp(const WebMouseEvent& e) {
   2175   view_->handleInputEvent(e);
   2176 
   2177   pressed_button_ = WebMouseEvent::ButtonNone;
   2178   last_click_time_sec_ = e.timeStampSeconds;
   2179   last_click_pos_ = last_mouse_pos_;
   2180 
   2181   // If we're in a drag operation, complete it.
   2182   if (current_drag_data_.isNull())
   2183     return;
   2184 
   2185   WebPoint client_point(e.x, e.y);
   2186   WebPoint screen_point(e.globalX, e.globalY);
   2187   FinishDragAndDrop(
   2188       e,
   2189       view_->dragTargetDragOver(
   2190           client_point, screen_point, current_drag_effects_allowed_, 0));
   2191 }
   2192 
   2193 void EventSender::DoMouseMove(const WebMouseEvent& e) {
   2194   last_mouse_pos_ = WebPoint(e.x, e.y);
   2195 
   2196   view_->handleInputEvent(e);
   2197 
   2198   if (pressed_button_ == WebMouseEvent::ButtonNone ||
   2199       current_drag_data_.isNull()) {
   2200     return;
   2201   }
   2202 
   2203   WebPoint client_point(e.x, e.y);
   2204   WebPoint screen_point(e.globalX, e.globalY);
   2205   current_drag_effect_ = view_->dragTargetDragOver(
   2206       client_point, screen_point, current_drag_effects_allowed_, 0);
   2207 }
   2208 
   2209 void EventSender::ReplaySavedEvents() {
   2210   replaying_saved_events_ = true;
   2211   while (!mouse_event_queue_.empty()) {
   2212     SavedEvent e = mouse_event_queue_.front();
   2213     mouse_event_queue_.pop_front();
   2214 
   2215     switch (e.type) {
   2216       case SavedEvent::TYPE_MOUSE_MOVE: {
   2217         WebMouseEvent event;
   2218         InitMouseEvent(WebInputEvent::MouseMove,
   2219                        pressed_button_,
   2220                        e.pos,
   2221                        GetCurrentEventTimeSec(),
   2222                        click_count_,
   2223                        e.modifiers,
   2224                        &event);
   2225         DoMouseMove(event);
   2226         break;
   2227       }
   2228       case SavedEvent::TYPE_LEAP_FORWARD:
   2229         DoLeapForward(e.milliseconds);
   2230         break;
   2231       case SavedEvent::TYPE_MOUSE_UP: {
   2232         WebMouseEvent event;
   2233         InitMouseEvent(WebInputEvent::MouseUp,
   2234                        e.button_type,
   2235                        last_mouse_pos_,
   2236                        GetCurrentEventTimeSec(),
   2237                        click_count_,
   2238                        e.modifiers,
   2239                        &event);
   2240         DoMouseUp(event);
   2241         break;
   2242       }
   2243       default:
   2244         NOTREACHED();
   2245     }
   2246   }
   2247 
   2248   replaying_saved_events_ = false;
   2249 }
   2250 
   2251 }  // namespace content
   2252