• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitMouseEvent(WebInputEvent::Type t,WebMouseEvent::Button b,const WebPoint & pos,double time_stamp,int click_count,int modifiers,WebMouseEvent * e)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 
GetKeyModifier(const std::string & modifier_name)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 
GetKeyModifiers(const std::vector<std::string> & modifier_names)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 
GetKeyModifiersFromV8(v8::Handle<v8::Value> value)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 
OutsideMultiClickRadius(const WebPoint & a,const WebPoint & b)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.
MakeMenuItemStringsFor(WebContextMenuData * context_menu,WebTestDelegate * delegate)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 
GetButtonTypeFromButtonNumber(int button_code)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:
MouseDownTask(EventSender * obj,int button_number,int modifiers)208   MouseDownTask(EventSender* obj, int button_number, int modifiers)
209       : WebMethodTask<EventSender>(obj),
210         button_number_(button_number),
211         modifiers_(modifiers) {}
212 
runIfValid()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:
MouseUpTask(EventSender * obj,int button_number,int modifiers)224   MouseUpTask(EventSender* obj, int button_number, int modifiers)
225       : WebMethodTask<EventSender>(obj),
226         button_number_(button_number),
227         modifiers_(modifiers) {}
228 
runIfValid()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:
KeyDownTask(EventSender * obj,const std::string code_str,int modifiers,KeyLocationCode location)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 
runIfValid()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 
NeedsShiftModifier(int keyCode)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|.
GetEditCommand(const WebKeyboardEvent & event,std::string * 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 
IsSystemKeyEvent(const WebKeyboardEvent & event)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 
EventSenderBindings(base::WeakPtr<EventSender> sender)427 EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
428     : sender_(sender) {
429 }
430 
~EventSenderBindings()431 EventSenderBindings::~EventSenderBindings() {}
432 
433 // static
Install(base::WeakPtr<EventSender> sender,WebFrame * frame)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
GetObjectTemplateBuilder(v8::Isolate * isolate)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 
EnableDOMUIEventLogging()559 void EventSenderBindings::EnableDOMUIEventLogging() {
560   if (sender_)
561     sender_->EnableDOMUIEventLogging();
562 }
563 
FireKeyboardEventsToElement()564 void EventSenderBindings::FireKeyboardEventsToElement() {
565   if (sender_)
566     sender_->FireKeyboardEventsToElement();
567 }
568 
ClearKillRing()569 void EventSenderBindings::ClearKillRing() {
570   if (sender_)
571     sender_->ClearKillRing();
572 }
573 
ContextClick()574 std::vector<std::string> EventSenderBindings::ContextClick() {
575   if (sender_)
576     return sender_->ContextClick();
577   return std::vector<std::string>();
578 }
579 
TextZoomIn()580 void EventSenderBindings::TextZoomIn() {
581   if (sender_)
582     sender_->TextZoomIn();
583 }
584 
TextZoomOut()585 void EventSenderBindings::TextZoomOut() {
586   if (sender_)
587     sender_->TextZoomOut();
588 }
589 
ZoomPageIn()590 void EventSenderBindings::ZoomPageIn() {
591   if (sender_)
592     sender_->ZoomPageIn();
593 }
594 
ZoomPageOut()595 void EventSenderBindings::ZoomPageOut() {
596   if (sender_)
597     sender_->ZoomPageOut();
598 }
599 
SetPageZoomFactor(double factor)600 void EventSenderBindings::SetPageZoomFactor(double factor) {
601   if (sender_)
602     sender_->SetPageZoomFactor(factor);
603 }
604 
SetPageScaleFactor(gin::Arguments * args)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 
ClearTouchPoints()624 void EventSenderBindings::ClearTouchPoints() {
625   if (sender_)
626     sender_->ClearTouchPoints();
627 }
628 
ReleaseTouchPoint(unsigned index)629 void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
630   if (sender_)
631     sender_->ReleaseTouchPoint(index);
632 }
633 
UpdateTouchPoint(unsigned index,double x,double y)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 
CancelTouchPoint(unsigned index)639 void EventSenderBindings::CancelTouchPoint(unsigned index) {
640   if (sender_)
641     sender_->CancelTouchPoint(index);
642 }
643 
SetTouchModifier(const std::string & key_name,bool set_mask)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 
SetTouchCancelable(bool cancelable)650 void EventSenderBindings::SetTouchCancelable(bool cancelable) {
651   if (sender_)
652     sender_->SetTouchCancelable(cancelable);
653 }
654 
DumpFilenameBeingDragged()655 void EventSenderBindings::DumpFilenameBeingDragged() {
656   if (sender_)
657     sender_->DumpFilenameBeingDragged();
658 }
659 
GestureFlingCancel()660 void EventSenderBindings::GestureFlingCancel() {
661   if (sender_)
662     sender_->GestureFlingCancel();
663 }
664 
GestureFlingStart(float x,float y,float velocity_x,float velocity_y)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 
GestureScrollFirstPoint(int x,int y)673 void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
674   if (sender_)
675     sender_->GestureScrollFirstPoint(x, y);
676 }
677 
TouchStart()678 void EventSenderBindings::TouchStart() {
679   if (sender_)
680     sender_->TouchStart();
681 }
682 
TouchMove()683 void EventSenderBindings::TouchMove() {
684   if (sender_)
685     sender_->TouchMove();
686 }
687 
TouchCancel()688 void EventSenderBindings::TouchCancel() {
689   if (sender_)
690     sender_->TouchCancel();
691 }
692 
TouchEnd()693 void EventSenderBindings::TouchEnd() {
694   if (sender_)
695     sender_->TouchEnd();
696 }
697 
LeapForward(int milliseconds)698 void EventSenderBindings::LeapForward(int milliseconds) {
699   if (sender_)
700     sender_->LeapForward(milliseconds);
701 }
702 
BeginDragWithFiles(const std::vector<std::string> & files)703 void EventSenderBindings::BeginDragWithFiles(
704     const std::vector<std::string>& files) {
705   if (sender_)
706     sender_->BeginDragWithFiles(files);
707 }
708 
AddTouchPoint(gin::Arguments * args)709 void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
710   if (sender_)
711     sender_->AddTouchPoint(args);
712 }
713 
MouseDragBegin()714 void EventSenderBindings::MouseDragBegin() {
715   if (sender_)
716     sender_->MouseDragBegin();
717 }
718 
MouseDragEnd()719 void EventSenderBindings::MouseDragEnd() {
720   if (sender_)
721     sender_->MouseDragEnd();
722 }
723 
GestureScrollBegin(gin::Arguments * args)724 void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
725   if (sender_)
726     sender_->GestureScrollBegin(args);
727 }
728 
GestureScrollEnd(gin::Arguments * args)729 void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
730   if (sender_)
731     sender_->GestureScrollEnd(args);
732 }
733 
GestureScrollUpdate(gin::Arguments * args)734 void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
735   if (sender_)
736     sender_->GestureScrollUpdate(args);
737 }
738 
GestureScrollUpdateWithoutPropagation(gin::Arguments * args)739 void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
740     gin::Arguments* args) {
741   if (sender_)
742     sender_->GestureScrollUpdateWithoutPropagation(args);
743 }
744 
GestureTap(gin::Arguments * args)745 void EventSenderBindings::GestureTap(gin::Arguments* args) {
746   if (sender_)
747     sender_->GestureTap(args);
748 }
749 
GestureTapDown(gin::Arguments * args)750 void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
751   if (sender_)
752     sender_->GestureTapDown(args);
753 }
754 
GestureShowPress(gin::Arguments * args)755 void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
756   if (sender_)
757     sender_->GestureShowPress(args);
758 }
759 
GestureTapCancel(gin::Arguments * args)760 void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
761   if (sender_)
762     sender_->GestureTapCancel(args);
763 }
764 
GestureLongPress(gin::Arguments * args)765 void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
766   if (sender_)
767     sender_->GestureLongPress(args);
768 }
769 
GestureLongTap(gin::Arguments * args)770 void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
771   if (sender_)
772     sender_->GestureLongTap(args);
773 }
774 
GestureTwoFingerTap(gin::Arguments * args)775 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
776   if (sender_)
777     sender_->GestureTwoFingerTap(args);
778 }
779 
ContinuousMouseScrollBy(gin::Arguments * args)780 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
781   if (sender_)
782     sender_->ContinuousMouseScrollBy(args);
783 }
784 
MouseMoveTo(gin::Arguments * args)785 void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
786   if (sender_)
787     sender_->MouseMoveTo(args);
788 }
789 
TrackpadScrollBegin()790 void EventSenderBindings::TrackpadScrollBegin() {
791   if (sender_)
792     sender_->TrackpadScrollBegin();
793 }
794 
TrackpadScroll(gin::Arguments * args)795 void EventSenderBindings::TrackpadScroll(gin::Arguments* args) {
796   if (sender_)
797     sender_->TrackpadScroll(args);
798 }
799 
TrackpadScrollEnd()800 void EventSenderBindings::TrackpadScrollEnd() {
801   if (sender_)
802     sender_->TrackpadScrollEnd();
803 }
804 
MouseScrollBy(gin::Arguments * args)805 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
806   if (sender_)
807     sender_->MouseScrollBy(args);
808 }
809 
MouseMomentumBegin()810 void EventSenderBindings::MouseMomentumBegin() {
811   if (sender_)
812     sender_->MouseMomentumBegin();
813 }
814 
MouseMomentumBegin2(gin::Arguments * args)815 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments* args) {
816   if (sender_)
817     sender_->MouseMomentumBegin2(args);
818 }
819 
MouseMomentumScrollBy(gin::Arguments * args)820 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
821   if (sender_)
822     sender_->MouseMomentumScrollBy(args);
823 }
824 
MouseMomentumEnd()825 void EventSenderBindings::MouseMomentumEnd() {
826   if (sender_)
827     sender_->MouseMomentumEnd();
828 }
829 
ScheduleAsynchronousClick(gin::Arguments * args)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 
ScheduleAsynchronousKeyDown(gin::Arguments * args)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 
MouseDown(gin::Arguments * args)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 
MouseUp(gin::Arguments * args)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 
KeyDown(gin::Arguments * args)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 
ForceLayoutOnEvents() const909 bool EventSenderBindings::ForceLayoutOnEvents() const {
910   if (sender_)
911     return sender_->force_layout_on_events();
912   return false;
913 }
914 
SetForceLayoutOnEvents(bool force)915 void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
916   if (sender_)
917     sender_->set_force_layout_on_events(force);
918 }
919 
IsDragMode() const920 bool EventSenderBindings::IsDragMode() const {
921   if (sender_)
922     return sender_->is_drag_mode();
923   return true;
924 }
925 
SetIsDragMode(bool drag_mode)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)
WmKeyDown() const932 int EventSenderBindings::WmKeyDown() const {
933   if (sender_)
934     return sender_->wm_key_down();
935   return 0;
936 }
937 
SetWmKeyDown(int key_down)938 void EventSenderBindings::SetWmKeyDown(int key_down) {
939   if (sender_)
940     sender_->set_wm_key_down(key_down);
941 }
942 
WmKeyUp() const943 int EventSenderBindings::WmKeyUp() const {
944   if (sender_)
945     return sender_->wm_key_up();
946   return 0;
947 }
948 
SetWmKeyUp(int key_up)949 void EventSenderBindings::SetWmKeyUp(int key_up) {
950   if (sender_)
951     sender_->set_wm_key_up(key_up);
952 }
953 
WmChar() const954 int EventSenderBindings::WmChar() const {
955   if (sender_)
956     return sender_->wm_char();
957   return 0;
958 }
959 
SetWmChar(int wm_char)960 void EventSenderBindings::SetWmChar(int wm_char) {
961   if (sender_)
962     sender_->set_wm_char(wm_char);
963 }
964 
WmDeadChar() const965 int EventSenderBindings::WmDeadChar() const {
966   if (sender_)
967     return sender_->wm_dead_char();
968   return 0;
969 }
970 
SetWmDeadChar(int dead_char)971 void EventSenderBindings::SetWmDeadChar(int dead_char) {
972   if (sender_)
973     sender_->set_wm_dead_char(dead_char);
974 }
975 
WmSysKeyDown() const976 int EventSenderBindings::WmSysKeyDown() const {
977   if (sender_)
978     return sender_->wm_sys_key_down();
979   return 0;
980 }
981 
SetWmSysKeyDown(int key_down)982 void EventSenderBindings::SetWmSysKeyDown(int key_down) {
983   if (sender_)
984     sender_->set_wm_sys_key_down(key_down);
985 }
986 
WmSysKeyUp() const987 int EventSenderBindings::WmSysKeyUp() const {
988   if (sender_)
989     return sender_->wm_sys_key_up();
990   return 0;
991 }
992 
SetWmSysKeyUp(int key_up)993 void EventSenderBindings::SetWmSysKeyUp(int key_up) {
994   if (sender_)
995     sender_->set_wm_sys_key_up(key_up);
996 }
997 
WmSysChar() const998 int EventSenderBindings::WmSysChar() const {
999   if (sender_)
1000     return sender_->wm_sys_char();
1001   return 0;
1002 }
1003 
SetWmSysChar(int sys_char)1004 void EventSenderBindings::SetWmSysChar(int sys_char) {
1005   if (sender_)
1006     sender_->set_wm_sys_char(sys_char);
1007 }
1008 
WmSysDeadChar() const1009 int EventSenderBindings::WmSysDeadChar() const {
1010   if (sender_)
1011     return sender_->wm_sys_dead_char();
1012   return 0;
1013 }
1014 
SetWmSysDeadChar(int sys_dead_char)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 
SavedEvent()1030 EventSender::SavedEvent::SavedEvent()
1031     : type(TYPE_UNSPECIFIED),
1032       button_type(WebMouseEvent::ButtonNone),
1033       milliseconds(0),
1034       modifiers(0) {}
1035 
EventSender(TestInterfaces * interfaces)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 
~EventSender()1062 EventSender::~EventSender() {}
1063 
Reset()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 
Install(WebFrame * frame)1104 void EventSender::Install(WebFrame* frame) {
1105   EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
1106 }
1107 
SetDelegate(WebTestDelegate * delegate)1108 void EventSender::SetDelegate(WebTestDelegate* delegate) {
1109   delegate_ = delegate;
1110 }
1111 
SetWebView(WebView * view)1112 void EventSender::SetWebView(WebView* view) {
1113   view_ = view;
1114 }
1115 
SetContextMenuData(const WebContextMenuData & data)1116 void EventSender::SetContextMenuData(const WebContextMenuData& data) {
1117   last_context_menu_data_.reset(new WebContextMenuData(data));
1118 }
1119 
DoDragDrop(const WebDragData & drag_data,WebDragOperationsMask mask)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 
MouseDown(int button_number,int modifiers)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 
MouseUp(int button_number,int modifiers)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 
KeyDown(const std::string & code_str,int modifiers,KeyLocationCode location)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 
EnableDOMUIEventLogging()1348 void EventSender::EnableDOMUIEventLogging() {}
1349 
FireKeyboardEventsToElement()1350 void EventSender::FireKeyboardEventsToElement() {}
1351 
ClearKillRing()1352 void EventSender::ClearKillRing() {}
1353 
ContextClick()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 
TextZoomIn()1400 void EventSender::TextZoomIn() {
1401   view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
1402 }
1403 
TextZoomOut()1404 void EventSender::TextZoomOut() {
1405   view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
1406 }
1407 
ZoomPageIn()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 
ZoomPageOut()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 
SetPageZoomFactor(double zoom_factor)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 
SetPageScaleFactor(float scale_factor,int x,int y)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 
ClearTouchPoints()1440 void EventSender::ClearTouchPoints() {
1441   touch_points_.clear();
1442 }
1443 
ThrowTouchPointError()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 
ReleaseTouchPoint(unsigned index)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 
UpdateTouchPoint(unsigned index,float x,float y)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 
CancelTouchPoint(unsigned index)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 
SetTouchModifier(const std::string & key_name,bool set_mask)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 
SetTouchCancelable(bool cancelable)1500 void EventSender::SetTouchCancelable(bool cancelable) {
1501   touch_cancelable_ = cancelable;
1502 }
1503 
DumpFilenameBeingDragged()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 
GestureFlingCancel()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 
GestureFlingStart(float x,float y,float velocity_x,float velocity_y)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 
GestureScrollFirstPoint(int x,int y)1550 void EventSender::GestureScrollFirstPoint(int x, int y) {
1551   current_gesture_location_ = WebPoint(x, y);
1552 }
1553 
TouchStart()1554 void EventSender::TouchStart() {
1555   SendCurrentTouchEvent(WebInputEvent::TouchStart);
1556 }
1557 
TouchMove()1558 void EventSender::TouchMove() {
1559   SendCurrentTouchEvent(WebInputEvent::TouchMove);
1560 }
1561 
TouchCancel()1562 void EventSender::TouchCancel() {
1563   SendCurrentTouchEvent(WebInputEvent::TouchCancel);
1564 }
1565 
TouchEnd()1566 void EventSender::TouchEnd() {
1567   SendCurrentTouchEvent(WebInputEvent::TouchEnd);
1568 }
1569 
LeapForward(int milliseconds)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 
BeginDragWithFiles(const std::vector<std::string> & files)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 
AddTouchPoint(gin::Arguments * args)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 
MouseDragBegin()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 
MouseDragEnd()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 
GestureScrollBegin(gin::Arguments * args)1678 void EventSender::GestureScrollBegin(gin::Arguments* args) {
1679   GestureEvent(WebInputEvent::GestureScrollBegin, args);
1680 }
1681 
GestureScrollEnd(gin::Arguments * args)1682 void EventSender::GestureScrollEnd(gin::Arguments* args) {
1683   GestureEvent(WebInputEvent::GestureScrollEnd, args);
1684 }
1685 
GestureScrollUpdate(gin::Arguments * args)1686 void EventSender::GestureScrollUpdate(gin::Arguments* args) {
1687   GestureEvent(WebInputEvent::GestureScrollUpdate, args);
1688 }
1689 
GestureScrollUpdateWithoutPropagation(gin::Arguments * args)1690 void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
1691   GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
1692 }
1693 
GestureTap(gin::Arguments * args)1694 void EventSender::GestureTap(gin::Arguments* args) {
1695   GestureEvent(WebInputEvent::GestureTap, args);
1696 }
1697 
GestureTapDown(gin::Arguments * args)1698 void EventSender::GestureTapDown(gin::Arguments* args) {
1699   GestureEvent(WebInputEvent::GestureTapDown, args);
1700 }
1701 
GestureShowPress(gin::Arguments * args)1702 void EventSender::GestureShowPress(gin::Arguments* args) {
1703   GestureEvent(WebInputEvent::GestureShowPress, args);
1704 }
1705 
GestureTapCancel(gin::Arguments * args)1706 void EventSender::GestureTapCancel(gin::Arguments* args) {
1707   GestureEvent(WebInputEvent::GestureTapCancel, args);
1708 }
1709 
GestureLongPress(gin::Arguments * args)1710 void EventSender::GestureLongPress(gin::Arguments* args) {
1711   GestureEvent(WebInputEvent::GestureLongPress, args);
1712 }
1713 
GestureLongTap(gin::Arguments * args)1714 void EventSender::GestureLongTap(gin::Arguments* args) {
1715   GestureEvent(WebInputEvent::GestureLongTap, args);
1716 }
1717 
GestureTwoFingerTap(gin::Arguments * args)1718 void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
1719   GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
1720 }
1721 
ContinuousMouseScrollBy(gin::Arguments * args)1722 void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
1723   WebMouseWheelEvent event;
1724   InitMouseWheelEvent(args, true, &event);
1725   view_->handleInputEvent(event);
1726 }
1727 
MouseMoveTo(gin::Arguments * args)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 
TrackpadScrollBegin()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 
TrackpadScroll(gin::Arguments * args)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 
TrackpadScrollEnd()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 
MouseScrollBy(gin::Arguments * args)1798 void EventSender::MouseScrollBy(gin::Arguments* args) {
1799    WebMouseWheelEvent event;
1800   InitMouseWheelEvent(args, false, &event);
1801   view_->handleInputEvent(event);
1802 }
1803 
MouseMomentumBegin()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 
MouseMomentumBegin2(gin::Arguments * args)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 
MouseMomentumScrollBy(gin::Arguments * args)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 
MouseMomentumEnd()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 
ScheduleAsynchronousClick(int button_number,int modifiers)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 
ScheduleAsynchronousKeyDown(const std::string & code_str,int modifiers,KeyLocationCode location)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 
GetCurrentEventTimeSec()1859 double EventSender::GetCurrentEventTimeSec() {
1860   return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
1861 }
1862 
DoLeapForward(int milliseconds)1863 void EventSender::DoLeapForward(int milliseconds) {
1864   time_offset_ms_ += milliseconds;
1865 }
1866 
SendCurrentTouchEvent(WebInputEvent::Type type)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 
GestureEvent(WebInputEvent::Type type,gin::Arguments * args)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 
UpdateClickCountForButton(WebMouseEvent::Button button_type)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 
InitMouseWheelEvent(gin::Arguments * args,bool continuous,WebMouseWheelEvent * event)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 
FinishDragAndDrop(const WebMouseEvent & e,blink::WebDragOperation drag_effect)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 
DoMouseUp(const WebMouseEvent & e)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 
DoMouseMove(const WebMouseEvent & e)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 
ReplaySavedEvents()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