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