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