Clean up extension confirmation prompts and make them consistent between Views and...
[chromium-blink-merge.git] / components / test_runner / event_sender.cc
blobc78d03972ca4f494195eeb964a3f7bf3a21008dc
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.
5 #include "components/test_runner/event_sender.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/test_runner/mock_spell_check.h"
12 #include "components/test_runner/test_interfaces.h"
13 #include "components/test_runner/web_test_delegate.h"
14 #include "components/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/WebPagePopup.h"
24 #include "third_party/WebKit/public/web/WebView.h"
25 #include "ui/events/keycodes/dom/keycode_converter.h"
26 #include "ui/events/keycodes/keyboard_codes.h"
27 #include "v8/include/v8.h"
29 using blink::WebContextMenuData;
30 using blink::WebDragData;
31 using blink::WebDragOperationsMask;
32 using blink::WebFloatPoint;
33 using blink::WebFrame;
34 using blink::WebGestureEvent;
35 using blink::WebInputEvent;
36 using blink::WebKeyboardEvent;
37 using blink::WebMenuItemInfo;
38 using blink::WebMouseEvent;
39 using blink::WebMouseWheelEvent;
40 using blink::WebPagePopup;
41 using blink::WebPoint;
42 using blink::WebString;
43 using blink::WebTouchEvent;
44 using blink::WebTouchPoint;
45 using blink::WebVector;
46 using blink::WebView;
48 namespace test_runner {
50 namespace {
52 void InitMouseEvent(WebInputEvent::Type t,
53 WebMouseEvent::Button b,
54 const WebPoint& pos,
55 double time_stamp,
56 int click_count,
57 int modifiers,
58 WebMouseEvent* e) {
59 e->type = t;
60 e->button = b;
61 e->modifiers = modifiers;
62 e->x = pos.x;
63 e->y = pos.y;
64 e->globalX = pos.x;
65 e->globalY = pos.y;
66 e->timeStampSeconds = time_stamp;
67 e->clickCount = click_count;
70 int GetKeyModifier(const std::string& modifier_name) {
71 const char* characters = modifier_name.c_str();
72 if (!strcmp(characters, "ctrlKey")
73 #ifndef __APPLE__
74 || !strcmp(characters, "addSelectionKey")
75 #endif
76 ) {
77 return WebInputEvent::ControlKey;
78 } else if (!strcmp(characters, "shiftKey") ||
79 !strcmp(characters, "rangeSelectionKey")) {
80 return WebInputEvent::ShiftKey;
81 } else if (!strcmp(characters, "altKey")) {
82 return WebInputEvent::AltKey;
83 #ifdef __APPLE__
84 } else if (!strcmp(characters, "metaKey") ||
85 !strcmp(characters, "addSelectionKey")) {
86 return WebInputEvent::MetaKey;
87 #else
88 } else if (!strcmp(characters, "metaKey")) {
89 return WebInputEvent::MetaKey;
90 #endif
91 } else if (!strcmp(characters, "autoRepeat")) {
92 return WebInputEvent::IsAutoRepeat;
93 } else if (!strcmp(characters, "copyKey")) {
94 #ifdef __APPLE__
95 return WebInputEvent::AltKey;
96 #else
97 return WebInputEvent::ControlKey;
98 #endif
99 } else if (!strcmp(characters, "leftButton")) {
100 return WebInputEvent::LeftButtonDown;
101 } else if (!strcmp(characters, "middleButton")) {
102 return WebInputEvent::MiddleButtonDown;
103 } else if (!strcmp(characters, "rightButton")) {
104 return WebInputEvent::RightButtonDown;
107 return 0;
110 int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
111 int modifiers = 0;
112 for (std::vector<std::string>::const_iterator it = modifier_names.begin();
113 it != modifier_names.end(); ++it) {
114 modifiers |= GetKeyModifier(*it);
116 return modifiers;
119 int GetKeyModifiersFromV8(v8::Isolate* isolate, v8::Local<v8::Value> value) {
120 std::vector<std::string> modifier_names;
121 if (value->IsString()) {
122 modifier_names.push_back(gin::V8ToString(value));
123 } else if (value->IsArray()) {
124 gin::Converter<std::vector<std::string> >::FromV8(
125 isolate, value, &modifier_names);
127 return GetKeyModifiers(modifier_names);
130 // Maximum distance (in space and time) for a mouse click to register as a
131 // double or triple click.
132 const double kMultipleClickTimeSec = 1;
133 const int kMultipleClickRadiusPixels = 5;
134 const char kSubMenuDepthIdentifier[] = "_";
135 const char kSubMenuIdentifier[] = " >";
136 const char kSeparatorIdentifier[] = "---------";
137 const char kDisabledIdentifier[] = "#";
138 const char kCheckedIdentifier[] = "*";
140 bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
141 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
142 kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
145 void PopulateCustomItems(const WebVector<WebMenuItemInfo>& customItems,
146 const std::string& prefix, std::vector<std::string>* strings) {
147 for (size_t i = 0; i < customItems.size(); ++i) {
148 std::string prefixCopy = prefix;
149 if (!customItems[i].enabled)
150 prefixCopy = kDisabledIdentifier + prefix;
151 if (customItems[i].checked)
152 prefixCopy = kCheckedIdentifier + prefix;
153 if (customItems[i].type == blink::WebMenuItemInfo::Separator) {
154 strings->push_back(prefixCopy + kSeparatorIdentifier);
155 } else if (customItems[i].type == blink::WebMenuItemInfo::SubMenu) {
156 strings->push_back(prefixCopy + customItems[i].label.utf8() +
157 customItems[i].icon.utf8() + kSubMenuIdentifier);
158 PopulateCustomItems(customItems[i].subMenuItems, prefixCopy +
159 kSubMenuDepthIdentifier, strings);
160 } else {
161 strings->push_back(prefixCopy + customItems[i].label.utf8() +
162 customItems[i].icon.utf8());
167 // Because actual context menu is implemented by the browser side,
168 // this function does only what LayoutTests are expecting:
169 // - Many test checks the count of items. So returning non-zero value makes
170 // sense.
171 // - Some test compares the count before and after some action. So changing the
172 // count based on flags also makes sense. This function is doing such for some
173 // flags.
174 // - Some test even checks actual string content. So providing it would be also
175 // helpful.
176 std::vector<std::string> MakeMenuItemStringsFor(
177 WebContextMenuData* context_menu,
178 WebTestDelegate* delegate) {
179 // These constants are based on Safari's context menu because tests are made
180 // for it.
181 static const char* kNonEditableMenuStrings[] = {
182 "Back",
183 "Reload Page",
184 "Open in Dashbaord",
185 "<separator>",
186 "View Source",
187 "Save Page As",
188 "Print Page",
189 "Inspect Element",
192 static const char* kEditableMenuStrings[] = {
193 "Cut",
194 "Copy",
195 "<separator>",
196 "Paste",
197 "Spelling and Grammar",
198 "Substitutions, Transformations",
199 "Font",
200 "Speech",
201 "Paragraph Direction",
202 "<separator>",
206 // This is possible because mouse events are cancelleable.
207 if (!context_menu)
208 return std::vector<std::string>();
210 std::vector<std::string> strings;
212 // Populate custom menu items if provided by blink.
213 PopulateCustomItems(context_menu->customItems, "", &strings);
215 if (context_menu->isEditable) {
216 for (const char** item = kEditableMenuStrings; *item; ++item) {
217 strings.push_back(*item);
219 WebVector<WebString> suggestions;
220 MockSpellCheck::FillSuggestionList(context_menu->misspelledWord,
221 &suggestions);
222 for (size_t i = 0; i < suggestions.size(); ++i) {
223 strings.push_back(suggestions[i].utf8());
225 } else {
226 for (const char** item = kNonEditableMenuStrings; *item; ++item) {
227 strings.push_back(*item);
231 return strings;
234 // How much we should scroll per event - the value here is chosen to match the
235 // WebKit impl and layout test results.
236 const float kScrollbarPixelsPerTick = 40.0f;
238 WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
239 if (!button_code)
240 return WebMouseEvent::ButtonLeft;
241 if (button_code == 2)
242 return WebMouseEvent::ButtonRight;
243 return WebMouseEvent::ButtonMiddle;
246 class MouseDownTask : public WebMethodTask<EventSender> {
247 public:
248 MouseDownTask(EventSender* obj, int button_number, int modifiers)
249 : WebMethodTask<EventSender>(obj),
250 button_number_(button_number),
251 modifiers_(modifiers) {}
253 void RunIfValid() override { object_->MouseDown(button_number_, modifiers_); }
255 private:
256 int button_number_;
257 int modifiers_;
260 class MouseUpTask : public WebMethodTask<EventSender> {
261 public:
262 MouseUpTask(EventSender* obj, int button_number, int modifiers)
263 : WebMethodTask<EventSender>(obj),
264 button_number_(button_number),
265 modifiers_(modifiers) {}
267 void RunIfValid() override { object_->MouseUp(button_number_, modifiers_); }
269 private:
270 int button_number_;
271 int modifiers_;
274 class KeyDownTask : public WebMethodTask<EventSender> {
275 public:
276 KeyDownTask(EventSender* obj,
277 const std::string code_str,
278 int modifiers,
279 KeyLocationCode location)
280 : WebMethodTask<EventSender>(obj),
281 code_str_(code_str),
282 modifiers_(modifiers),
283 location_(location) {}
285 void RunIfValid() override {
286 object_->KeyDown(code_str_, modifiers_, location_);
289 private:
290 std::string code_str_;
291 int modifiers_;
292 KeyLocationCode location_;
295 bool NeedsShiftModifier(int keyCode) {
296 // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
297 return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
300 // Get the edit command corresponding to a keyboard event.
301 // Returns true if the specified event corresponds to an edit command, the name
302 // of the edit command will be stored in |*name|.
303 bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
304 #if defined(OS_MACOSX)
305 // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
306 // modifiers. These key events correspond to some special movement and
307 // selection editor commands. These keys will be marked as system key, which
308 // prevents them from being handled. Thus they must be handled specially.
309 if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
310 WebKeyboardEvent::MetaKey)
311 return false;
313 switch (event.windowsKeyCode) {
314 case ui::VKEY_LEFT:
315 *name = "MoveToBeginningOfLine";
316 break;
317 case ui::VKEY_RIGHT:
318 *name = "MoveToEndOfLine";
319 break;
320 case ui::VKEY_UP:
321 *name = "MoveToBeginningOfDocument";
322 break;
323 case ui::VKEY_DOWN:
324 *name = "MoveToEndOfDocument";
325 break;
326 default:
327 return false;
330 if (event.modifiers & WebKeyboardEvent::ShiftKey)
331 name->append("AndModifySelection");
333 return true;
334 #else
335 return false;
336 #endif
339 bool IsSystemKeyEvent(const WebKeyboardEvent& event) {
340 #if defined(OS_MACOSX)
341 return event.modifiers & WebInputEvent::MetaKey &&
342 event.windowsKeyCode != ui::VKEY_B &&
343 event.windowsKeyCode != ui::VKEY_I;
344 #else
345 return !!(event.modifiers & WebInputEvent::AltKey);
346 #endif
349 const char* kSourceDeviceStringTouchpad = "touchpad";
350 const char* kSourceDeviceStringTouchscreen = "touchscreen";
352 } // namespace
354 class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
355 public:
356 static gin::WrapperInfo kWrapperInfo;
358 static void Install(base::WeakPtr<EventSender> sender,
359 blink::WebFrame* frame);
361 private:
362 explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
363 ~EventSenderBindings() override;
365 // gin::Wrappable:
366 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
367 v8::Isolate* isolate) override;
369 // Bound methods:
370 void EnableDOMUIEventLogging();
371 void FireKeyboardEventsToElement();
372 void ClearKillRing();
373 std::vector<std::string> ContextClick();
374 void TextZoomIn();
375 void TextZoomOut();
376 void ZoomPageIn();
377 void ZoomPageOut();
378 void SetPageZoomFactor(double factor);
379 void ClearTouchPoints();
380 void ReleaseTouchPoint(unsigned index);
381 void UpdateTouchPoint(unsigned index, double x, double y);
382 void CancelTouchPoint(unsigned index);
383 void SetTouchModifier(const std::string& key_name, bool set_mask);
384 void SetTouchCancelable(bool cancelable);
385 void DumpFilenameBeingDragged();
386 void GestureFlingCancel();
387 void GestureFlingStart(float x,
388 float y,
389 float velocity_x,
390 float velocity_y,
391 gin::Arguments* args);
392 void GestureScrollFirstPoint(int x, int y);
393 void TouchStart();
394 void TouchMove();
395 void TouchCancel();
396 void TouchEnd();
397 void LeapForward(int milliseconds);
398 void BeginDragWithFiles(const std::vector<std::string>& files);
399 void AddTouchPoint(gin::Arguments* args);
400 void MouseDragBegin();
401 void MouseDragEnd();
402 void GestureScrollBegin(gin::Arguments* args);
403 void GestureScrollEnd(gin::Arguments* args);
404 void GestureScrollUpdate(gin::Arguments* args);
405 void GesturePinchBegin(gin::Arguments* args);
406 void GesturePinchEnd(gin::Arguments* args);
407 void GesturePinchUpdate(gin::Arguments* args);
408 void GestureTap(gin::Arguments* args);
409 void GestureTapDown(gin::Arguments* args);
410 void GestureShowPress(gin::Arguments* args);
411 void GestureTapCancel(gin::Arguments* args);
412 void GestureLongPress(gin::Arguments* args);
413 void GestureLongTap(gin::Arguments* args);
414 void GestureTwoFingerTap(gin::Arguments* args);
415 void ContinuousMouseScrollBy(gin::Arguments* args);
416 void MouseMoveTo(gin::Arguments* args);
417 void MouseLeave();
418 void TrackpadScrollBegin();
419 void TrackpadScroll(gin::Arguments* args);
420 void TrackpadScrollEnd();
421 void MouseScrollBy(gin::Arguments* args);
422 // TODO(erikchen): Remove MouseMomentumBegin once CL 282743002 has landed.
423 void MouseMomentumBegin();
424 void MouseMomentumBegin2(gin::Arguments* args);
425 void MouseMomentumScrollBy(gin::Arguments* args);
426 void MouseMomentumEnd();
427 void ScheduleAsynchronousClick(gin::Arguments* args);
428 void ScheduleAsynchronousKeyDown(gin::Arguments* args);
429 void MouseDown(gin::Arguments* args);
430 void MouseUp(gin::Arguments* args);
431 void KeyDown(gin::Arguments* args);
433 // Binding properties:
434 bool ForceLayoutOnEvents() const;
435 void SetForceLayoutOnEvents(bool force);
436 bool IsDragMode() const;
437 void SetIsDragMode(bool drag_mode);
439 #if defined(OS_WIN)
440 int WmKeyDown() const;
441 void SetWmKeyDown(int key_down);
443 int WmKeyUp() const;
444 void SetWmKeyUp(int key_up);
446 int WmChar() const;
447 void SetWmChar(int wm_char);
449 int WmDeadChar() const;
450 void SetWmDeadChar(int dead_char);
452 int WmSysKeyDown() const;
453 void SetWmSysKeyDown(int key_down);
455 int WmSysKeyUp() const;
456 void SetWmSysKeyUp(int key_up);
458 int WmSysChar() const;
459 void SetWmSysChar(int sys_char);
461 int WmSysDeadChar() const;
462 void SetWmSysDeadChar(int sys_dead_char);
463 #endif
465 base::WeakPtr<EventSender> sender_;
467 DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
470 gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
472 EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
473 : sender_(sender) {
476 EventSenderBindings::~EventSenderBindings() {}
478 // static
479 void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
480 WebFrame* frame) {
481 v8::Isolate* isolate = blink::mainThreadIsolate();
482 v8::HandleScope handle_scope(isolate);
483 v8::Local<v8::Context> context = frame->mainWorldScriptContext();
484 if (context.IsEmpty())
485 return;
487 v8::Context::Scope context_scope(context);
489 gin::Handle<EventSenderBindings> bindings =
490 gin::CreateHandle(isolate, new EventSenderBindings(sender));
491 if (bindings.IsEmpty())
492 return;
493 v8::Local<v8::Object> global = context->Global();
494 global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
497 gin::ObjectTemplateBuilder
498 EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
499 return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
500 .SetMethod("enableDOMUIEventLogging",
501 &EventSenderBindings::EnableDOMUIEventLogging)
502 .SetMethod("fireKeyboardEventsToElement",
503 &EventSenderBindings::FireKeyboardEventsToElement)
504 .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
505 .SetMethod("contextClick", &EventSenderBindings::ContextClick)
506 .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
507 .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
508 .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
509 .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
510 .SetMethod("setPageZoomFactor", &EventSenderBindings::SetPageZoomFactor)
511 .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
512 .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
513 .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
514 .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
515 .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
516 .SetMethod("setTouchCancelable", &EventSenderBindings::SetTouchCancelable)
517 .SetMethod("dumpFilenameBeingDragged",
518 &EventSenderBindings::DumpFilenameBeingDragged)
519 .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
520 .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
521 .SetMethod("gestureScrollFirstPoint",
522 &EventSenderBindings::GestureScrollFirstPoint)
523 .SetMethod("touchStart", &EventSenderBindings::TouchStart)
524 .SetMethod("touchMove", &EventSenderBindings::TouchMove)
525 .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
526 .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
527 .SetMethod("leapForward", &EventSenderBindings::LeapForward)
528 .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
529 .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
530 .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
531 .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
532 .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
533 .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
534 .SetMethod("gestureScrollUpdate",
535 &EventSenderBindings::GestureScrollUpdate)
536 .SetMethod("gesturePinchBegin", &EventSenderBindings::GesturePinchBegin)
537 .SetMethod("gesturePinchEnd", &EventSenderBindings::GesturePinchEnd)
538 .SetMethod("gesturePinchUpdate", &EventSenderBindings::GesturePinchUpdate)
539 .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
540 .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
541 .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
542 .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
543 .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
544 .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
545 .SetMethod("gestureTwoFingerTap",
546 &EventSenderBindings::GestureTwoFingerTap)
547 .SetMethod("continuousMouseScrollBy",
548 &EventSenderBindings::ContinuousMouseScrollBy)
549 .SetMethod("keyDown", &EventSenderBindings::KeyDown)
550 .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
551 .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
552 .SetMethod("mouseLeave", &EventSenderBindings::MouseLeave)
553 .SetMethod("trackpadScrollBegin",
554 &EventSenderBindings::TrackpadScrollBegin)
555 .SetMethod("trackpadScroll", &EventSenderBindings::TrackpadScroll)
556 .SetMethod("trackpadScrollEnd", &EventSenderBindings::TrackpadScrollEnd)
557 .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
558 .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
559 .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
560 .SetMethod("mouseMomentumBegin2",
561 &EventSenderBindings::MouseMomentumBegin2)
562 .SetMethod("mouseMomentumScrollBy",
563 &EventSenderBindings::MouseMomentumScrollBy)
564 .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
565 .SetMethod("scheduleAsynchronousClick",
566 &EventSenderBindings::ScheduleAsynchronousClick)
567 .SetMethod("scheduleAsynchronousKeyDown",
568 &EventSenderBindings::ScheduleAsynchronousKeyDown)
569 .SetProperty("forceLayoutOnEvents",
570 &EventSenderBindings::ForceLayoutOnEvents,
571 &EventSenderBindings::SetForceLayoutOnEvents)
572 .SetProperty("dragMode",
573 &EventSenderBindings::IsDragMode,
574 &EventSenderBindings::SetIsDragMode)
575 #if defined(OS_WIN)
576 .SetProperty("WM_KEYDOWN",
577 &EventSenderBindings::WmKeyDown,
578 &EventSenderBindings::SetWmKeyDown)
579 .SetProperty("WM_KEYUP",
580 &EventSenderBindings::WmKeyUp,
581 &EventSenderBindings::SetWmKeyUp)
582 .SetProperty("WM_CHAR",
583 &EventSenderBindings::WmChar,
584 &EventSenderBindings::SetWmChar)
585 .SetProperty("WM_DEADCHAR",
586 &EventSenderBindings::WmDeadChar,
587 &EventSenderBindings::SetWmDeadChar)
588 .SetProperty("WM_SYSKEYDOWN",
589 &EventSenderBindings::WmSysKeyDown,
590 &EventSenderBindings::SetWmSysKeyDown)
591 .SetProperty("WM_SYSKEYUP",
592 &EventSenderBindings::WmSysKeyUp,
593 &EventSenderBindings::SetWmSysKeyUp)
594 .SetProperty("WM_SYSCHAR",
595 &EventSenderBindings::WmSysChar,
596 &EventSenderBindings::SetWmSysChar)
597 .SetProperty("WM_SYSDEADCHAR",
598 &EventSenderBindings::WmSysDeadChar,
599 &EventSenderBindings::SetWmSysDeadChar);
600 #else
602 #endif
605 void EventSenderBindings::EnableDOMUIEventLogging() {
606 if (sender_)
607 sender_->EnableDOMUIEventLogging();
610 void EventSenderBindings::FireKeyboardEventsToElement() {
611 if (sender_)
612 sender_->FireKeyboardEventsToElement();
615 void EventSenderBindings::ClearKillRing() {
616 if (sender_)
617 sender_->ClearKillRing();
620 std::vector<std::string> EventSenderBindings::ContextClick() {
621 if (sender_)
622 return sender_->ContextClick();
623 return std::vector<std::string>();
626 void EventSenderBindings::TextZoomIn() {
627 if (sender_)
628 sender_->TextZoomIn();
631 void EventSenderBindings::TextZoomOut() {
632 if (sender_)
633 sender_->TextZoomOut();
636 void EventSenderBindings::ZoomPageIn() {
637 if (sender_)
638 sender_->ZoomPageIn();
641 void EventSenderBindings::ZoomPageOut() {
642 if (sender_)
643 sender_->ZoomPageOut();
646 void EventSenderBindings::SetPageZoomFactor(double factor) {
647 if (sender_)
648 sender_->SetPageZoomFactor(factor);
651 void EventSenderBindings::ClearTouchPoints() {
652 if (sender_)
653 sender_->ClearTouchPoints();
656 void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
657 if (sender_)
658 sender_->ReleaseTouchPoint(index);
661 void EventSenderBindings::UpdateTouchPoint(unsigned index, double x, double y) {
662 if (sender_) {
663 sender_->UpdateTouchPoint(index, static_cast<float>(x),
664 static_cast<float>(y));
668 void EventSenderBindings::CancelTouchPoint(unsigned index) {
669 if (sender_)
670 sender_->CancelTouchPoint(index);
673 void EventSenderBindings::SetTouchModifier(const std::string& key_name,
674 bool set_mask) {
675 if (sender_)
676 sender_->SetTouchModifier(key_name, set_mask);
679 void EventSenderBindings::SetTouchCancelable(bool cancelable) {
680 if (sender_)
681 sender_->SetTouchCancelable(cancelable);
684 void EventSenderBindings::DumpFilenameBeingDragged() {
685 if (sender_)
686 sender_->DumpFilenameBeingDragged();
689 void EventSenderBindings::GestureFlingCancel() {
690 if (sender_)
691 sender_->GestureFlingCancel();
694 void EventSenderBindings::GestureFlingStart(float x,
695 float y,
696 float velocity_x,
697 float velocity_y,
698 gin::Arguments* args) {
699 if (sender_)
700 sender_->GestureFlingStart(x, y, velocity_x, velocity_y, args);
703 void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
704 if (sender_)
705 sender_->GestureScrollFirstPoint(x, y);
708 void EventSenderBindings::TouchStart() {
709 if (sender_)
710 sender_->TouchStart();
713 void EventSenderBindings::TouchMove() {
714 if (sender_)
715 sender_->TouchMove();
718 void EventSenderBindings::TouchCancel() {
719 if (sender_)
720 sender_->TouchCancel();
723 void EventSenderBindings::TouchEnd() {
724 if (sender_)
725 sender_->TouchEnd();
728 void EventSenderBindings::LeapForward(int milliseconds) {
729 if (sender_)
730 sender_->LeapForward(milliseconds);
733 void EventSenderBindings::BeginDragWithFiles(
734 const std::vector<std::string>& files) {
735 if (sender_)
736 sender_->BeginDragWithFiles(files);
739 void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
740 if (sender_)
741 sender_->AddTouchPoint(args);
744 void EventSenderBindings::MouseDragBegin() {
745 if (sender_)
746 sender_->MouseDragBegin();
749 void EventSenderBindings::MouseDragEnd() {
750 if (sender_)
751 sender_->MouseDragEnd();
754 void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
755 if (sender_)
756 sender_->GestureScrollBegin(args);
759 void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
760 if (sender_)
761 sender_->GestureScrollEnd(args);
764 void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
765 if (sender_)
766 sender_->GestureScrollUpdate(args);
769 void EventSenderBindings::GesturePinchBegin(gin::Arguments* args) {
770 if (sender_)
771 sender_->GesturePinchBegin(args);
774 void EventSenderBindings::GesturePinchEnd(gin::Arguments* args) {
775 if (sender_)
776 sender_->GesturePinchEnd(args);
779 void EventSenderBindings::GesturePinchUpdate(gin::Arguments* args) {
780 if (sender_)
781 sender_->GesturePinchUpdate(args);
784 void EventSenderBindings::GestureTap(gin::Arguments* args) {
785 if (sender_)
786 sender_->GestureTap(args);
789 void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
790 if (sender_)
791 sender_->GestureTapDown(args);
794 void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
795 if (sender_)
796 sender_->GestureShowPress(args);
799 void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
800 if (sender_)
801 sender_->GestureTapCancel(args);
804 void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
805 if (sender_)
806 sender_->GestureLongPress(args);
809 void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
810 if (sender_)
811 sender_->GestureLongTap(args);
814 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
815 if (sender_)
816 sender_->GestureTwoFingerTap(args);
819 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
820 if (sender_)
821 sender_->ContinuousMouseScrollBy(args);
824 void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
825 if (sender_)
826 sender_->MouseMoveTo(args);
829 void EventSenderBindings::MouseLeave() {
830 if (sender_)
831 sender_->MouseLeave();
834 void EventSenderBindings::TrackpadScrollBegin() {
835 if (sender_)
836 sender_->TrackpadScrollBegin();
839 void EventSenderBindings::TrackpadScroll(gin::Arguments* args) {
840 if (sender_)
841 sender_->TrackpadScroll(args);
844 void EventSenderBindings::TrackpadScrollEnd() {
845 if (sender_)
846 sender_->TrackpadScrollEnd();
849 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
850 if (sender_)
851 sender_->MouseScrollBy(args);
854 void EventSenderBindings::MouseMomentumBegin() {
855 if (sender_)
856 sender_->MouseMomentumBegin();
859 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments* args) {
860 if (sender_)
861 sender_->MouseMomentumBegin2(args);
864 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
865 if (sender_)
866 sender_->MouseMomentumScrollBy(args);
869 void EventSenderBindings::MouseMomentumEnd() {
870 if (sender_)
871 sender_->MouseMomentumEnd();
874 void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
875 if (!sender_)
876 return;
878 int button_number = 0;
879 int modifiers = 0;
880 if (!args->PeekNext().IsEmpty()) {
881 args->GetNext(&button_number);
882 if (!args->PeekNext().IsEmpty())
883 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
885 sender_->ScheduleAsynchronousClick(button_number, modifiers);
888 void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
889 if (!sender_)
890 return;
892 std::string code_str;
893 int modifiers = 0;
894 int location = DOMKeyLocationStandard;
895 args->GetNext(&code_str);
896 if (!args->PeekNext().IsEmpty()) {
897 v8::Local<v8::Value> value;
898 args->GetNext(&value);
899 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
900 if (!args->PeekNext().IsEmpty())
901 args->GetNext(&location);
903 sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
904 static_cast<KeyLocationCode>(location));
907 void EventSenderBindings::MouseDown(gin::Arguments* args) {
908 if (!sender_)
909 return;
911 int button_number = 0;
912 int modifiers = 0;
913 if (!args->PeekNext().IsEmpty()) {
914 args->GetNext(&button_number);
915 if (!args->PeekNext().IsEmpty())
916 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
918 sender_->MouseDown(button_number, modifiers);
921 void EventSenderBindings::MouseUp(gin::Arguments* args) {
922 if (!sender_)
923 return;
925 int button_number = 0;
926 int modifiers = 0;
927 if (!args->PeekNext().IsEmpty()) {
928 args->GetNext(&button_number);
929 if (!args->PeekNext().IsEmpty())
930 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
932 sender_->MouseUp(button_number, modifiers);
935 void EventSenderBindings::KeyDown(gin::Arguments* args) {
936 if (!sender_)
937 return;
939 std::string code_str;
940 int modifiers = 0;
941 int location = DOMKeyLocationStandard;
942 args->GetNext(&code_str);
943 if (!args->PeekNext().IsEmpty()) {
944 v8::Local<v8::Value> value;
945 args->GetNext(&value);
946 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
947 if (!args->PeekNext().IsEmpty())
948 args->GetNext(&location);
950 sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
953 bool EventSenderBindings::ForceLayoutOnEvents() const {
954 if (sender_)
955 return sender_->force_layout_on_events();
956 return false;
959 void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
960 if (sender_)
961 sender_->set_force_layout_on_events(force);
964 bool EventSenderBindings::IsDragMode() const {
965 if (sender_)
966 return sender_->is_drag_mode();
967 return true;
970 void EventSenderBindings::SetIsDragMode(bool drag_mode) {
971 if (sender_)
972 sender_->set_is_drag_mode(drag_mode);
975 #if defined(OS_WIN)
976 int EventSenderBindings::WmKeyDown() const {
977 if (sender_)
978 return sender_->wm_key_down();
979 return 0;
982 void EventSenderBindings::SetWmKeyDown(int key_down) {
983 if (sender_)
984 sender_->set_wm_key_down(key_down);
987 int EventSenderBindings::WmKeyUp() const {
988 if (sender_)
989 return sender_->wm_key_up();
990 return 0;
993 void EventSenderBindings::SetWmKeyUp(int key_up) {
994 if (sender_)
995 sender_->set_wm_key_up(key_up);
998 int EventSenderBindings::WmChar() const {
999 if (sender_)
1000 return sender_->wm_char();
1001 return 0;
1004 void EventSenderBindings::SetWmChar(int wm_char) {
1005 if (sender_)
1006 sender_->set_wm_char(wm_char);
1009 int EventSenderBindings::WmDeadChar() const {
1010 if (sender_)
1011 return sender_->wm_dead_char();
1012 return 0;
1015 void EventSenderBindings::SetWmDeadChar(int dead_char) {
1016 if (sender_)
1017 sender_->set_wm_dead_char(dead_char);
1020 int EventSenderBindings::WmSysKeyDown() const {
1021 if (sender_)
1022 return sender_->wm_sys_key_down();
1023 return 0;
1026 void EventSenderBindings::SetWmSysKeyDown(int key_down) {
1027 if (sender_)
1028 sender_->set_wm_sys_key_down(key_down);
1031 int EventSenderBindings::WmSysKeyUp() const {
1032 if (sender_)
1033 return sender_->wm_sys_key_up();
1034 return 0;
1037 void EventSenderBindings::SetWmSysKeyUp(int key_up) {
1038 if (sender_)
1039 sender_->set_wm_sys_key_up(key_up);
1042 int EventSenderBindings::WmSysChar() const {
1043 if (sender_)
1044 return sender_->wm_sys_char();
1045 return 0;
1048 void EventSenderBindings::SetWmSysChar(int sys_char) {
1049 if (sender_)
1050 sender_->set_wm_sys_char(sys_char);
1053 int EventSenderBindings::WmSysDeadChar() const {
1054 if (sender_)
1055 return sender_->wm_sys_dead_char();
1056 return 0;
1059 void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
1060 if (sender_)
1061 sender_->set_wm_sys_dead_char(sys_dead_char);
1063 #endif
1065 // EventSender -----------------------------------------------------------------
1067 WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
1068 int EventSender::modifiers_ = 0;
1070 WebPoint EventSender::last_mouse_pos_;
1072 WebMouseEvent::Button EventSender::last_button_type_ =
1073 WebMouseEvent::ButtonNone;
1075 EventSender::SavedEvent::SavedEvent()
1076 : type(TYPE_UNSPECIFIED),
1077 button_type(WebMouseEvent::ButtonNone),
1078 milliseconds(0),
1079 modifiers(0) {}
1081 EventSender::EventSender(TestInterfaces* interfaces)
1082 : interfaces_(interfaces),
1083 delegate_(NULL),
1084 view_(NULL),
1085 force_layout_on_events_(false),
1086 is_drag_mode_(true),
1087 touch_modifiers_(0),
1088 touch_cancelable_(true),
1089 replaying_saved_events_(false),
1090 current_drag_effects_allowed_(blink::WebDragOperationNone),
1091 last_click_time_sec_(0),
1092 current_drag_effect_(blink::WebDragOperationNone),
1093 time_offset_ms_(0),
1094 click_count_(0),
1095 #if defined(OS_WIN)
1096 wm_key_down_(0),
1097 wm_key_up_(0),
1098 wm_char_(0),
1099 wm_dead_char_(0),
1100 wm_sys_key_down_(0),
1101 wm_sys_key_up_(0),
1102 wm_sys_char_(0),
1103 wm_sys_dead_char_(0),
1104 #endif
1105 weak_factory_(this) {}
1107 EventSender::~EventSender() {}
1109 void EventSender::Reset() {
1110 DCHECK(current_drag_data_.isNull());
1111 current_drag_data_.reset();
1112 current_drag_effect_ = blink::WebDragOperationNone;
1113 current_drag_effects_allowed_ = blink::WebDragOperationNone;
1114 if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
1115 view_->mouseCaptureLost();
1116 pressed_button_ = WebMouseEvent::ButtonNone;
1117 is_drag_mode_ = true;
1118 force_layout_on_events_ = true;
1120 #if defined(OS_WIN)
1121 wm_key_down_ = WM_KEYDOWN;
1122 wm_key_up_ = WM_KEYUP;
1123 wm_char_ = WM_CHAR;
1124 wm_dead_char_ = WM_DEADCHAR;
1125 wm_sys_key_down_ = WM_SYSKEYDOWN;
1126 wm_sys_key_up_ = WM_SYSKEYUP;
1127 wm_sys_char_ = WM_SYSCHAR;
1128 wm_sys_dead_char_ = WM_SYSDEADCHAR;
1129 #endif
1131 last_mouse_pos_ = WebPoint(0, 0);
1132 last_click_time_sec_ = 0;
1133 last_click_pos_ = WebPoint(0, 0);
1134 last_button_type_ = WebMouseEvent::ButtonNone;
1135 touch_points_.clear();
1136 last_context_menu_data_.reset();
1137 task_list_.RevokeAll();
1138 current_gesture_location_ = WebPoint(0, 0);
1139 mouse_event_queue_.clear();
1141 time_offset_ms_ = 0;
1142 click_count_ = 0;
1144 touch_modifiers_ = 0;
1145 touch_cancelable_ = true;
1146 touch_points_.clear();
1149 void EventSender::Install(WebFrame* frame) {
1150 EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
1153 void EventSender::SetDelegate(WebTestDelegate* delegate) {
1154 delegate_ = delegate;
1157 void EventSender::SetWebView(WebView* view) {
1158 view_ = view;
1161 void EventSender::SetContextMenuData(const WebContextMenuData& data) {
1162 last_context_menu_data_.reset(new WebContextMenuData(data));
1165 void EventSender::DoDragDrop(const WebDragData& drag_data,
1166 WebDragOperationsMask mask) {
1167 WebMouseEvent event;
1168 InitMouseEvent(WebInputEvent::MouseDown,
1169 pressed_button_,
1170 last_mouse_pos_,
1171 GetCurrentEventTimeSec(),
1172 click_count_,
1173 modifiers_,
1174 &event);
1175 WebPoint client_point(event.x, event.y);
1176 WebPoint screen_point(event.globalX, event.globalY);
1177 current_drag_data_ = drag_data;
1178 current_drag_effects_allowed_ = mask;
1179 current_drag_effect_ = view_->dragTargetDragEnter(
1180 drag_data,
1181 client_point,
1182 screen_point,
1183 current_drag_effects_allowed_,
1184 modifiers_);
1186 // Finish processing events.
1187 ReplaySavedEvents();
1190 void EventSender::MouseDown(int button_number, int modifiers) {
1191 if (force_layout_on_events_)
1192 view_->layout();
1194 DCHECK_NE(-1, button_number);
1196 WebMouseEvent::Button button_type =
1197 GetButtonTypeFromButtonNumber(button_number);
1199 UpdateClickCountForButton(button_type);
1201 pressed_button_ = button_type;
1202 modifiers_ = modifiers;
1204 WebMouseEvent event;
1205 InitMouseEvent(WebInputEvent::MouseDown,
1206 button_type,
1207 last_mouse_pos_,
1208 GetCurrentEventTimeSec(),
1209 click_count_,
1210 modifiers,
1211 &event);
1212 HandleInputEventOnViewOrPopup(event);
1215 void EventSender::MouseUp(int button_number, int modifiers) {
1216 if (force_layout_on_events_)
1217 view_->layout();
1219 DCHECK_NE(-1, button_number);
1221 WebMouseEvent::Button button_type =
1222 GetButtonTypeFromButtonNumber(button_number);
1224 if (is_drag_mode_ && !replaying_saved_events_) {
1225 SavedEvent saved_event;
1226 saved_event.type = SavedEvent::TYPE_MOUSE_UP;
1227 saved_event.button_type = button_type;
1228 saved_event.modifiers = modifiers;
1229 mouse_event_queue_.push_back(saved_event);
1230 ReplaySavedEvents();
1231 } else {
1232 WebMouseEvent event;
1233 InitMouseEvent(WebInputEvent::MouseUp,
1234 button_type,
1235 last_mouse_pos_,
1236 GetCurrentEventTimeSec(),
1237 click_count_,
1238 modifiers,
1239 &event);
1240 DoMouseUp(event);
1244 void EventSender::KeyDown(const std::string& code_str,
1245 int modifiers,
1246 KeyLocationCode location) {
1247 // FIXME: I'm not exactly sure how we should convert the string to a key
1248 // event. This seems to work in the cases I tested.
1249 // FIXME: Should we also generate a KEY_UP?
1251 bool generate_char = false;
1253 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
1254 // Windows uses \r for "Enter".
1255 int code = 0;
1256 int text = 0;
1257 bool needs_shift_key_modifier = false;
1258 std::string domString;
1260 if ("\n" == code_str) {
1261 generate_char = true;
1262 text = code = ui::VKEY_RETURN;
1263 domString.assign("Enter");
1264 } else if ("rightArrow" == code_str) {
1265 code = ui::VKEY_RIGHT;
1266 domString.assign("ArrowRight");
1267 } else if ("downArrow" == code_str) {
1268 code = ui::VKEY_DOWN;
1269 domString.assign("ArrowDown");
1270 } else if ("leftArrow" == code_str) {
1271 code = ui::VKEY_LEFT;
1272 domString.assign("ArrowLeft");
1273 } else if ("upArrow" == code_str) {
1274 code = ui::VKEY_UP;
1275 domString.assign("ArrowUp");
1276 } else if ("insert" == code_str) {
1277 code = ui::VKEY_INSERT;
1278 domString.assign("Insert");
1279 } else if ("delete" == code_str) {
1280 code = ui::VKEY_DELETE;
1281 domString.assign("Delete");
1282 } else if ("pageUp" == code_str) {
1283 code = ui::VKEY_PRIOR;
1284 domString.assign("PageUp");
1285 } else if ("pageDown" == code_str) {
1286 code = ui::VKEY_NEXT;
1287 domString.assign("PageDown");
1288 } else if ("home" == code_str) {
1289 code = ui::VKEY_HOME;
1290 domString.assign("Home");
1291 } else if ("end" == code_str) {
1292 code = ui::VKEY_END;
1293 domString.assign("End");
1294 } else if ("printScreen" == code_str) {
1295 code = ui::VKEY_SNAPSHOT;
1296 domString.assign("PrintScreen");
1297 } else if ("menu" == code_str) {
1298 code = ui::VKEY_APPS;
1299 domString.assign("ContextMenu");
1300 } else if ("leftControl" == code_str) {
1301 code = ui::VKEY_LCONTROL;
1302 domString.assign("ControlLeft");
1303 } else if ("rightControl" == code_str) {
1304 code = ui::VKEY_RCONTROL;
1305 domString.assign("ControlRight");
1306 } else if ("leftShift" == code_str) {
1307 code = ui::VKEY_LSHIFT;
1308 domString.assign("ShiftLeft");
1309 } else if ("rightShift" == code_str) {
1310 code = ui::VKEY_RSHIFT;
1311 domString.assign("ShiftRight");
1312 } else if ("leftAlt" == code_str) {
1313 code = ui::VKEY_LMENU;
1314 domString.assign("AltLeft");
1315 } else if ("rightAlt" == code_str) {
1316 code = ui::VKEY_RMENU;
1317 domString.assign("AltRight");
1318 } else if ("numLock" == code_str) {
1319 code = ui::VKEY_NUMLOCK;
1320 domString.assign("NumLock");
1321 } else if ("backspace" == code_str) {
1322 code = ui::VKEY_BACK;
1323 domString.assign("Backspace");
1324 } else if ("escape" == code_str) {
1325 code = ui::VKEY_ESCAPE;
1326 domString.assign("Escape");
1327 } else {
1328 // Compare the input string with the function-key names defined by the
1329 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
1330 // name, set its key code.
1331 for (int i = 1; i <= 24; ++i) {
1332 std::string function_key_name = base::StringPrintf("F%d", i);
1333 if (function_key_name == code_str) {
1334 code = ui::VKEY_F1 + (i - 1);
1335 domString = function_key_name;
1336 break;
1339 if (!code) {
1340 WebString web_code_str =
1341 WebString::fromUTF8(code_str.data(), code_str.size());
1342 if (web_code_str.length() != 1u) {
1343 v8::Isolate* isolate = blink::mainThreadIsolate();
1344 isolate->ThrowException(v8::Exception::TypeError(
1345 gin::StringToV8(isolate, "Invalid web code.")));
1346 return;
1348 text = code = web_code_str.at(0);
1349 needs_shift_key_modifier = NeedsShiftModifier(code);
1350 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
1351 code -= 'a' - 'A';
1352 if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z')) {
1353 domString.assign("Key");
1354 domString.push_back(base::ToUpperASCII(code));
1355 } else if (code >= '0' && code <= '9') {
1356 domString.assign("Digit");
1357 domString.push_back(code);
1358 } else if (code == ' ') {
1359 domString.assign("Space");
1360 } else if (code == 9) {
1361 domString.assign("Tab");
1363 generate_char = true;
1366 if ("(" == code_str) {
1367 code = '9';
1368 needs_shift_key_modifier = true;
1372 // For one generated keyboard event, we need to generate a keyDown/keyUp
1373 // pair;
1374 // On Windows, we might also need to generate a char event to mimic the
1375 // Windows event flow; on other platforms we create a merged event and test
1376 // the event flow that that platform provides.
1377 WebKeyboardEvent event_down;
1378 event_down.type = WebInputEvent::RawKeyDown;
1379 event_down.modifiers = modifiers;
1380 event_down.windowsKeyCode = code;
1381 event_down.domCode = static_cast<int>(
1382 ui::KeycodeConverter::CodeStringToDomCode(domString.c_str()));
1384 if (generate_char) {
1385 event_down.text[0] = text;
1386 event_down.unmodifiedText[0] = text;
1389 event_down.setKeyIdentifierFromWindowsKeyCode();
1391 if (event_down.modifiers != 0)
1392 event_down.isSystemKey = IsSystemKeyEvent(event_down);
1394 if (needs_shift_key_modifier)
1395 event_down.modifiers |= WebInputEvent::ShiftKey;
1397 // See if KeyLocation argument is given.
1398 if (location == DOMKeyLocationNumpad)
1399 event_down.modifiers |= WebInputEvent::IsKeyPad;
1401 WebKeyboardEvent event_up;
1402 event_up = event_down;
1403 event_up.type = WebInputEvent::KeyUp;
1404 // EventSender.m forces a layout here, with at least one
1405 // test (fast/forms/focus-control-to-page.html) relying on this.
1406 if (force_layout_on_events_)
1407 view_->layout();
1409 // In the browser, if a keyboard event corresponds to an editor command,
1410 // the command will be dispatched to the renderer just before dispatching
1411 // the keyboard event, and then it will be executed in the
1412 // RenderView::handleCurrentKeyboardEvent() method.
1413 // We just simulate the same behavior here.
1414 std::string edit_command;
1415 if (GetEditCommand(event_down, &edit_command))
1416 delegate_->SetEditCommand(edit_command, "");
1418 HandleInputEventOnViewOrPopup(event_down);
1420 if (code == ui::VKEY_ESCAPE && !current_drag_data_.isNull()) {
1421 WebMouseEvent event;
1422 InitMouseEvent(WebInputEvent::MouseDown,
1423 pressed_button_,
1424 last_mouse_pos_,
1425 GetCurrentEventTimeSec(),
1426 click_count_,
1428 &event);
1429 FinishDragAndDrop(event, blink::WebDragOperationNone);
1432 delegate_->ClearEditCommand();
1434 if (generate_char) {
1435 WebKeyboardEvent event_char = event_up;
1436 event_char.type = WebInputEvent::Char;
1437 // keyIdentifier is an empty string, unless the Enter key was pressed.
1438 // This behavior is not standard (keyIdentifier itself is not even a
1439 // standard any more), but it matches the actual behavior in Blink.
1440 if (code != ui::VKEY_RETURN)
1441 event_char.keyIdentifier[0] = '\0';
1442 HandleInputEventOnViewOrPopup(event_char);
1445 HandleInputEventOnViewOrPopup(event_up);
1448 void EventSender::EnableDOMUIEventLogging() {}
1450 void EventSender::FireKeyboardEventsToElement() {}
1452 void EventSender::ClearKillRing() {}
1454 std::vector<std::string> EventSender::ContextClick() {
1455 if (force_layout_on_events_) {
1456 view_->layout();
1459 UpdateClickCountForButton(WebMouseEvent::ButtonRight);
1461 // Clears last context menu data because we need to know if the context menu
1462 // be requested after following mouse events.
1463 last_context_menu_data_.reset();
1465 // Generate right mouse down and up.
1466 WebMouseEvent event;
1467 // This is a hack to work around only allowing a single pressed button since
1468 // we want to test the case where both the left and right mouse buttons are
1469 // pressed.
1470 if (pressed_button_ == WebMouseEvent::ButtonNone) {
1471 pressed_button_ = WebMouseEvent::ButtonRight;
1473 InitMouseEvent(WebInputEvent::MouseDown,
1474 WebMouseEvent::ButtonRight,
1475 last_mouse_pos_,
1476 GetCurrentEventTimeSec(),
1477 click_count_,
1479 &event);
1480 HandleInputEventOnViewOrPopup(event);
1482 #if defined(OS_WIN)
1483 InitMouseEvent(WebInputEvent::MouseUp,
1484 WebMouseEvent::ButtonRight,
1485 last_mouse_pos_,
1486 GetCurrentEventTimeSec(),
1487 click_count_,
1489 &event);
1490 HandleInputEventOnViewOrPopup(event);
1492 pressed_button_= WebMouseEvent::ButtonNone;
1493 #endif
1495 std::vector<std::string> menu_items =
1496 MakeMenuItemStringsFor(last_context_menu_data_.get(), delegate_);
1497 last_context_menu_data_.reset();
1498 return menu_items;
1501 void EventSender::TextZoomIn() {
1502 view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
1505 void EventSender::TextZoomOut() {
1506 view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
1509 void EventSender::ZoomPageIn() {
1510 const std::vector<WebTestProxyBase*>& window_list =
1511 interfaces_->GetWindowList();
1513 for (size_t i = 0; i < window_list.size(); ++i) {
1514 window_list.at(i)->GetWebView()->setZoomLevel(
1515 window_list.at(i)->GetWebView()->zoomLevel() + 1);
1519 void EventSender::ZoomPageOut() {
1520 const std::vector<WebTestProxyBase*>& window_list =
1521 interfaces_->GetWindowList();
1523 for (size_t i = 0; i < window_list.size(); ++i) {
1524 window_list.at(i)->GetWebView()->setZoomLevel(
1525 window_list.at(i)->GetWebView()->zoomLevel() - 1);
1529 void EventSender::SetPageZoomFactor(double zoom_factor) {
1530 const std::vector<WebTestProxyBase*>& window_list =
1531 interfaces_->GetWindowList();
1533 for (size_t i = 0; i < window_list.size(); ++i) {
1534 window_list.at(i)->GetWebView()->setZoomLevel(
1535 std::log(zoom_factor) / std::log(1.2));
1539 void EventSender::ClearTouchPoints() {
1540 touch_points_.clear();
1543 void EventSender::ThrowTouchPointError() {
1544 v8::Isolate* isolate = blink::mainThreadIsolate();
1545 isolate->ThrowException(v8::Exception::TypeError(
1546 gin::StringToV8(isolate, "Invalid touch point.")));
1549 void EventSender::ReleaseTouchPoint(unsigned index) {
1550 if (index >= touch_points_.size()) {
1551 ThrowTouchPointError();
1552 return;
1555 WebTouchPoint* touch_point = &touch_points_[index];
1556 touch_point->state = WebTouchPoint::StateReleased;
1559 void EventSender::UpdateTouchPoint(unsigned index, float x, float y) {
1560 if (index >= touch_points_.size()) {
1561 ThrowTouchPointError();
1562 return;
1565 WebTouchPoint* touch_point = &touch_points_[index];
1566 touch_point->state = WebTouchPoint::StateMoved;
1567 touch_point->position = WebFloatPoint(x, y);
1568 touch_point->screenPosition = touch_point->position;
1571 void EventSender::CancelTouchPoint(unsigned index) {
1572 if (index >= touch_points_.size()) {
1573 ThrowTouchPointError();
1574 return;
1577 WebTouchPoint* touch_point = &touch_points_[index];
1578 touch_point->state = WebTouchPoint::StateCancelled;
1581 void EventSender::SetTouchModifier(const std::string& key_name,
1582 bool set_mask) {
1583 int mask = 0;
1584 if (key_name == "shift")
1585 mask = WebInputEvent::ShiftKey;
1586 else if (key_name == "alt")
1587 mask = WebInputEvent::AltKey;
1588 else if (key_name == "ctrl")
1589 mask = WebInputEvent::ControlKey;
1590 else if (key_name == "meta")
1591 mask = WebInputEvent::MetaKey;
1593 if (set_mask)
1594 touch_modifiers_ |= mask;
1595 else
1596 touch_modifiers_ &= ~mask;
1599 void EventSender::SetTouchCancelable(bool cancelable) {
1600 touch_cancelable_ = cancelable;
1603 void EventSender::DumpFilenameBeingDragged() {
1604 if (current_drag_data_.isNull())
1605 return;
1607 WebString filename;
1608 WebVector<WebDragData::Item> items = current_drag_data_.items();
1609 for (size_t i = 0; i < items.size(); ++i) {
1610 if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
1611 filename = items[i].title;
1612 break;
1615 delegate_->PrintMessage(std::string("Filename being dragged: ") +
1616 filename.utf8().data() + "\n");
1619 void EventSender::GestureFlingCancel() {
1620 WebGestureEvent event;
1621 event.type = WebInputEvent::GestureFlingCancel;
1622 event.timeStampSeconds = GetCurrentEventTimeSec();
1624 if (force_layout_on_events_)
1625 view_->layout();
1627 HandleInputEventOnViewOrPopup(event);
1630 void EventSender::GestureFlingStart(float x,
1631 float y,
1632 float velocity_x,
1633 float velocity_y,
1634 gin::Arguments* args) {
1635 WebGestureEvent event;
1636 event.type = WebInputEvent::GestureFlingStart;
1638 std::string device_string;
1639 if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsString())
1640 args->GetNext(&device_string);
1642 if (device_string == kSourceDeviceStringTouchpad) {
1643 event.sourceDevice = blink::WebGestureDeviceTouchpad;
1644 } else if (device_string == kSourceDeviceStringTouchscreen) {
1645 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
1646 } else {
1647 args->ThrowError();
1648 return;
1651 event.x = x;
1652 event.y = y;
1653 event.globalX = event.x;
1654 event.globalY = event.y;
1656 event.data.flingStart.velocityX = velocity_x;
1657 event.data.flingStart.velocityY = velocity_y;
1658 event.timeStampSeconds = GetCurrentEventTimeSec();
1660 if (force_layout_on_events_)
1661 view_->layout();
1663 HandleInputEventOnViewOrPopup(event);
1666 void EventSender::GestureScrollFirstPoint(int x, int y) {
1667 current_gesture_location_ = WebPoint(x, y);
1670 void EventSender::TouchStart() {
1671 SendCurrentTouchEvent(WebInputEvent::TouchStart);
1674 void EventSender::TouchMove() {
1675 SendCurrentTouchEvent(WebInputEvent::TouchMove);
1678 void EventSender::TouchCancel() {
1679 SendCurrentTouchEvent(WebInputEvent::TouchCancel);
1682 void EventSender::TouchEnd() {
1683 SendCurrentTouchEvent(WebInputEvent::TouchEnd);
1686 void EventSender::LeapForward(int milliseconds) {
1687 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1688 !replaying_saved_events_) {
1689 SavedEvent saved_event;
1690 saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
1691 saved_event.milliseconds = milliseconds;
1692 mouse_event_queue_.push_back(saved_event);
1693 } else {
1694 DoLeapForward(milliseconds);
1698 void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
1699 current_drag_data_.initialize();
1700 WebVector<WebString> absolute_filenames(files.size());
1701 for (size_t i = 0; i < files.size(); ++i) {
1702 WebDragData::Item item;
1703 item.storageType = WebDragData::Item::StorageTypeFilename;
1704 item.filenameData = delegate_->GetAbsoluteWebStringFromUTF8Path(files[i]);
1705 current_drag_data_.addItem(item);
1706 absolute_filenames[i] = item.filenameData;
1708 current_drag_data_.setFilesystemId(
1709 delegate_->RegisterIsolatedFileSystem(absolute_filenames));
1710 current_drag_effects_allowed_ = blink::WebDragOperationCopy;
1712 // Provide a drag source.
1713 view_->dragTargetDragEnter(current_drag_data_,
1714 last_mouse_pos_,
1715 last_mouse_pos_,
1716 current_drag_effects_allowed_,
1718 // |is_drag_mode_| saves events and then replays them later. We don't
1719 // need/want that.
1720 is_drag_mode_ = false;
1722 // Make the rest of eventSender think a drag is in progress.
1723 pressed_button_ = WebMouseEvent::ButtonLeft;
1726 void EventSender::AddTouchPoint(gin::Arguments* args) {
1727 double x;
1728 double y;
1729 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1730 args->ThrowError();
1731 return;
1734 WebTouchPoint touch_point;
1735 touch_point.state = WebTouchPoint::StatePressed;
1736 touch_point.position = WebFloatPoint(static_cast<float>(x),
1737 static_cast<float>(y));
1738 touch_point.screenPosition = touch_point.position;
1740 if (!args->PeekNext().IsEmpty()) {
1741 double radius_x;
1742 if (!args->GetNext(&radius_x)) {
1743 args->ThrowError();
1744 return;
1747 double radius_y = radius_x;
1748 if (!args->PeekNext().IsEmpty()) {
1749 if (!args->GetNext(&radius_y)) {
1750 args->ThrowError();
1751 return;
1755 touch_point.radiusX = static_cast<float>(radius_x);
1756 touch_point.radiusY = static_cast<float>(radius_y);
1759 int lowest_id = 0;
1760 for (size_t i = 0; i < touch_points_.size(); i++) {
1761 if (touch_points_[i].id == lowest_id)
1762 lowest_id++;
1764 touch_point.id = lowest_id;
1765 touch_points_.push_back(touch_point);
1768 void EventSender::MouseDragBegin() {
1769 WebMouseWheelEvent event;
1770 InitMouseEvent(WebInputEvent::MouseWheel,
1771 WebMouseEvent::ButtonNone,
1772 last_mouse_pos_,
1773 GetCurrentEventTimeSec(),
1774 click_count_,
1776 &event);
1777 event.phase = WebMouseWheelEvent::PhaseBegan;
1778 event.hasPreciseScrollingDeltas = true;
1779 HandleInputEventOnViewOrPopup(event);
1782 void EventSender::MouseDragEnd() {
1783 WebMouseWheelEvent event;
1784 InitMouseEvent(WebInputEvent::MouseWheel,
1785 WebMouseEvent::ButtonNone,
1786 last_mouse_pos_,
1787 GetCurrentEventTimeSec(),
1788 click_count_,
1790 &event);
1791 event.phase = WebMouseWheelEvent::PhaseEnded;
1792 event.hasPreciseScrollingDeltas = true;
1793 HandleInputEventOnViewOrPopup(event);
1796 void EventSender::GestureScrollBegin(gin::Arguments* args) {
1797 GestureEvent(WebInputEvent::GestureScrollBegin, args);
1800 void EventSender::GestureScrollEnd(gin::Arguments* args) {
1801 GestureEvent(WebInputEvent::GestureScrollEnd, args);
1804 void EventSender::GestureScrollUpdate(gin::Arguments* args) {
1805 GestureEvent(WebInputEvent::GestureScrollUpdate, args);
1808 void EventSender::GesturePinchBegin(gin::Arguments* args) {
1809 GestureEvent(WebInputEvent::GesturePinchBegin, args);
1812 void EventSender::GesturePinchEnd(gin::Arguments* args) {
1813 GestureEvent(WebInputEvent::GesturePinchEnd, args);
1816 void EventSender::GesturePinchUpdate(gin::Arguments* args) {
1817 GestureEvent(WebInputEvent::GesturePinchUpdate, args);
1820 void EventSender::GestureTap(gin::Arguments* args) {
1821 GestureEvent(WebInputEvent::GestureTap, args);
1824 void EventSender::GestureTapDown(gin::Arguments* args) {
1825 GestureEvent(WebInputEvent::GestureTapDown, args);
1828 void EventSender::GestureShowPress(gin::Arguments* args) {
1829 GestureEvent(WebInputEvent::GestureShowPress, args);
1832 void EventSender::GestureTapCancel(gin::Arguments* args) {
1833 GestureEvent(WebInputEvent::GestureTapCancel, args);
1836 void EventSender::GestureLongPress(gin::Arguments* args) {
1837 GestureEvent(WebInputEvent::GestureLongPress, args);
1840 void EventSender::GestureLongTap(gin::Arguments* args) {
1841 GestureEvent(WebInputEvent::GestureLongTap, args);
1844 void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
1845 GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
1848 void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
1849 WebMouseWheelEvent event;
1850 InitMouseWheelEvent(args, true, &event);
1851 HandleInputEventOnViewOrPopup(event);
1854 void EventSender::MouseMoveTo(gin::Arguments* args) {
1855 if (force_layout_on_events_)
1856 view_->layout();
1858 double x;
1859 double y;
1860 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1861 args->ThrowError();
1862 return;
1864 WebPoint mouse_pos(static_cast<int>(x), static_cast<int>(y));
1866 int modifiers = 0;
1867 if (!args->PeekNext().IsEmpty())
1868 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
1870 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1871 !replaying_saved_events_) {
1872 SavedEvent saved_event;
1873 saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
1874 saved_event.pos = mouse_pos;
1875 saved_event.modifiers = modifiers;
1876 mouse_event_queue_.push_back(saved_event);
1877 } else {
1878 WebMouseEvent event;
1879 InitMouseEvent(WebInputEvent::MouseMove,
1880 pressed_button_,
1881 mouse_pos,
1882 GetCurrentEventTimeSec(),
1883 click_count_,
1884 modifiers,
1885 &event);
1886 DoMouseMove(event);
1890 void EventSender::MouseLeave() {
1891 if (force_layout_on_events_)
1892 view_->layout();
1894 WebMouseEvent event;
1895 InitMouseEvent(WebInputEvent::MouseLeave,
1896 WebMouseEvent::ButtonNone,
1897 last_mouse_pos_,
1898 GetCurrentEventTimeSec(),
1899 click_count_,
1901 &event);
1902 view_->handleInputEvent(event);
1906 void EventSender::TrackpadScrollBegin() {
1907 WebMouseWheelEvent event;
1908 InitMouseEvent(WebInputEvent::MouseWheel,
1909 WebMouseEvent::ButtonNone,
1910 last_mouse_pos_,
1911 GetCurrentEventTimeSec(),
1912 click_count_,
1914 &event);
1915 event.phase = blink::WebMouseWheelEvent::PhaseBegan;
1916 event.hasPreciseScrollingDeltas = true;
1917 HandleInputEventOnViewOrPopup(event);
1920 void EventSender::TrackpadScroll(gin::Arguments* args) {
1921 WebMouseWheelEvent event;
1922 InitMouseWheelEvent(args, true, &event);
1923 event.phase = blink::WebMouseWheelEvent::PhaseChanged;
1924 event.hasPreciseScrollingDeltas = true;
1925 HandleInputEventOnViewOrPopup(event);
1928 void EventSender::TrackpadScrollEnd() {
1929 WebMouseWheelEvent event;
1930 InitMouseEvent(WebInputEvent::MouseWheel,
1931 WebMouseEvent::ButtonNone,
1932 last_mouse_pos_,
1933 GetCurrentEventTimeSec(),
1934 click_count_,
1936 &event);
1937 event.phase = WebMouseWheelEvent::PhaseEnded;
1938 event.hasPreciseScrollingDeltas = true;
1939 HandleInputEventOnViewOrPopup(event);
1942 void EventSender::MouseScrollBy(gin::Arguments* args) {
1943 WebMouseWheelEvent event;
1944 InitMouseWheelEvent(args, false, &event);
1945 HandleInputEventOnViewOrPopup(event);
1948 void EventSender::MouseMomentumBegin() {
1949 WebMouseWheelEvent event;
1950 InitMouseEvent(WebInputEvent::MouseWheel,
1951 WebMouseEvent::ButtonNone,
1952 last_mouse_pos_,
1953 GetCurrentEventTimeSec(),
1954 click_count_,
1956 &event);
1957 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1958 event.hasPreciseScrollingDeltas = true;
1959 HandleInputEventOnViewOrPopup(event);
1962 void EventSender::MouseMomentumBegin2(gin::Arguments* args) {
1963 WebMouseWheelEvent event;
1964 InitMouseWheelEvent(args, true, &event);
1965 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1966 event.hasPreciseScrollingDeltas = true;
1967 HandleInputEventOnViewOrPopup(event);
1970 void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
1971 WebMouseWheelEvent event;
1972 InitMouseWheelEvent(args, true, &event);
1973 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1974 event.hasPreciseScrollingDeltas = true;
1975 HandleInputEventOnViewOrPopup(event);
1978 void EventSender::MouseMomentumEnd() {
1979 WebMouseWheelEvent event;
1980 InitMouseEvent(WebInputEvent::MouseWheel,
1981 WebMouseEvent::ButtonNone,
1982 last_mouse_pos_,
1983 GetCurrentEventTimeSec(),
1984 click_count_,
1986 &event);
1987 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1988 event.hasPreciseScrollingDeltas = true;
1989 HandleInputEventOnViewOrPopup(event);
1992 void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
1993 delegate_->PostTask(new MouseDownTask(this, button_number, modifiers));
1994 delegate_->PostTask(new MouseUpTask(this, button_number, modifiers));
1997 void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
1998 int modifiers,
1999 KeyLocationCode location) {
2000 delegate_->PostTask(new KeyDownTask(this, code_str, modifiers, location));
2003 double EventSender::GetCurrentEventTimeSec() {
2004 return (delegate_->GetCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
2007 void EventSender::DoLeapForward(int milliseconds) {
2008 time_offset_ms_ += milliseconds;
2011 void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
2012 DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
2013 touch_points_.size());
2014 if (force_layout_on_events_)
2015 view_->layout();
2017 WebTouchEvent touch_event;
2018 touch_event.type = type;
2019 touch_event.modifiers = touch_modifiers_;
2020 touch_event.cancelable = touch_cancelable_;
2021 touch_event.timeStampSeconds = GetCurrentEventTimeSec();
2022 touch_event.touchesLength = touch_points_.size();
2023 for (size_t i = 0; i < touch_points_.size(); ++i)
2024 touch_event.touches[i] = touch_points_[i];
2025 HandleInputEventOnViewOrPopup(touch_event);
2027 for (size_t i = 0; i < touch_points_.size(); ++i) {
2028 WebTouchPoint* touch_point = &touch_points_[i];
2029 if (touch_point->state == WebTouchPoint::StateReleased) {
2030 touch_points_.erase(touch_points_.begin() + i);
2031 --i;
2032 } else
2033 touch_point->state = WebTouchPoint::StateStationary;
2037 void EventSender::GestureEvent(WebInputEvent::Type type,
2038 gin::Arguments* args) {
2039 WebGestureEvent event;
2040 event.type = type;
2042 // If the first argument is a string, it is to specify the device, otherwise
2043 // the device is assumed to be a touchscreen (since most tests were written
2044 // assuming this).
2045 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2046 if (args->PeekNext()->IsString()) {
2047 std::string device_string;
2048 if (!args->GetNext(&device_string)) {
2049 args->ThrowError();
2050 return;
2052 if (device_string == kSourceDeviceStringTouchpad) {
2053 event.sourceDevice = blink::WebGestureDeviceTouchpad;
2054 } else if (device_string == kSourceDeviceStringTouchscreen) {
2055 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2056 } else {
2057 args->ThrowError();
2058 return;
2062 double x;
2063 double y;
2064 if (!args->GetNext(&x) || !args->GetNext(&y)) {
2065 args->ThrowError();
2066 return;
2069 switch (type) {
2070 case WebInputEvent::GestureScrollUpdate:
2072 bool preventPropagation = false;
2073 if (!args->PeekNext().IsEmpty()) {
2074 if (!args->GetNext(&preventPropagation)) {
2075 args->ThrowError();
2076 return;
2080 event.data.scrollUpdate.deltaX = static_cast<float>(x);
2081 event.data.scrollUpdate.deltaY = static_cast<float>(y);
2082 event.data.scrollUpdate.preventPropagation = preventPropagation;
2083 event.x = current_gesture_location_.x;
2084 event.y = current_gesture_location_.y;
2085 current_gesture_location_.x =
2086 current_gesture_location_.x + event.data.scrollUpdate.deltaX;
2087 current_gesture_location_.y =
2088 current_gesture_location_.y + event.data.scrollUpdate.deltaY;
2089 break;
2091 case WebInputEvent::GestureScrollBegin:
2092 current_gesture_location_ = WebPoint(x, y);
2093 event.x = current_gesture_location_.x;
2094 event.y = current_gesture_location_.y;
2095 break;
2096 case WebInputEvent::GestureScrollEnd:
2097 case WebInputEvent::GestureFlingStart:
2098 event.x = current_gesture_location_.x;
2099 event.y = current_gesture_location_.y;
2100 break;
2101 case WebInputEvent::GesturePinchBegin:
2102 case WebInputEvent::GesturePinchEnd:
2103 current_gesture_location_ = WebPoint(x, y);
2104 event.x = current_gesture_location_.x;
2105 event.y = current_gesture_location_.y;
2106 break;
2107 case WebInputEvent::GesturePinchUpdate:
2109 float scale = 1;
2110 if (!args->PeekNext().IsEmpty()) {
2111 if (!args->GetNext(&scale)) {
2112 args->ThrowError();
2113 return;
2116 event.data.pinchUpdate.scale = scale;
2117 current_gesture_location_ = WebPoint(x, y);
2118 event.x = current_gesture_location_.x;
2119 event.y = current_gesture_location_.y;
2120 break;
2122 case WebInputEvent::GestureTap:
2124 float tap_count = 1;
2125 float width = 30;
2126 float height = 30;
2127 if (!args->PeekNext().IsEmpty()) {
2128 if (!args->GetNext(&tap_count)) {
2129 args->ThrowError();
2130 return;
2133 if (!args->PeekNext().IsEmpty()) {
2134 if (!args->GetNext(&width)) {
2135 args->ThrowError();
2136 return;
2139 if (!args->PeekNext().IsEmpty()) {
2140 if (!args->GetNext(&height)) {
2141 args->ThrowError();
2142 return;
2145 event.data.tap.tapCount = tap_count;
2146 event.data.tap.width = width;
2147 event.data.tap.height = height;
2148 event.x = x;
2149 event.y = y;
2150 break;
2152 case WebInputEvent::GestureTapUnconfirmed:
2153 if (!args->PeekNext().IsEmpty()) {
2154 float tap_count;
2155 if (!args->GetNext(&tap_count)) {
2156 args->ThrowError();
2157 return;
2159 event.data.tap.tapCount = tap_count;
2160 } else {
2161 event.data.tap.tapCount = 1;
2163 event.x = x;
2164 event.y = y;
2165 break;
2166 case WebInputEvent::GestureTapDown:
2168 float width = 30;
2169 float height = 30;
2170 if (!args->PeekNext().IsEmpty()) {
2171 if (!args->GetNext(&width)) {
2172 args->ThrowError();
2173 return;
2176 if (!args->PeekNext().IsEmpty()) {
2177 if (!args->GetNext(&height)) {
2178 args->ThrowError();
2179 return;
2182 event.x = x;
2183 event.y = y;
2184 event.data.tapDown.width = width;
2185 event.data.tapDown.height = height;
2186 break;
2188 case WebInputEvent::GestureShowPress:
2190 float width = 30;
2191 float height = 30;
2192 if (!args->PeekNext().IsEmpty()) {
2193 if (!args->GetNext(&width)) {
2194 args->ThrowError();
2195 return;
2197 if (!args->PeekNext().IsEmpty()) {
2198 if (!args->GetNext(&height)) {
2199 args->ThrowError();
2200 return;
2204 event.x = x;
2205 event.y = y;
2206 event.data.showPress.width = width;
2207 event.data.showPress.height = height;
2208 break;
2210 case WebInputEvent::GestureTapCancel:
2211 event.x = x;
2212 event.y = y;
2213 break;
2214 case WebInputEvent::GestureLongPress:
2215 event.x = x;
2216 event.y = y;
2217 if (!args->PeekNext().IsEmpty()) {
2218 float width;
2219 if (!args->GetNext(&width)) {
2220 args->ThrowError();
2221 return;
2223 event.data.longPress.width = width;
2224 if (!args->PeekNext().IsEmpty()) {
2225 float height;
2226 if (!args->GetNext(&height)) {
2227 args->ThrowError();
2228 return;
2230 event.data.longPress.height = height;
2233 break;
2234 case WebInputEvent::GestureLongTap:
2235 event.x = x;
2236 event.y = y;
2237 if (!args->PeekNext().IsEmpty()) {
2238 float width;
2239 if (!args->GetNext(&width)) {
2240 args->ThrowError();
2241 return;
2243 event.data.longPress.width = width;
2244 if (!args->PeekNext().IsEmpty()) {
2245 float height;
2246 if (!args->GetNext(&height)) {
2247 args->ThrowError();
2248 return;
2250 event.data.longPress.height = height;
2253 break;
2254 case WebInputEvent::GestureTwoFingerTap:
2255 event.x = x;
2256 event.y = y;
2257 if (!args->PeekNext().IsEmpty()) {
2258 float first_finger_width;
2259 if (!args->GetNext(&first_finger_width)) {
2260 args->ThrowError();
2261 return;
2263 event.data.twoFingerTap.firstFingerWidth = first_finger_width;
2264 if (!args->PeekNext().IsEmpty()) {
2265 float first_finger_height;
2266 if (!args->GetNext(&first_finger_height)) {
2267 args->ThrowError();
2268 return;
2270 event.data.twoFingerTap.firstFingerHeight = first_finger_height;
2273 break;
2274 default:
2275 NOTREACHED();
2278 event.globalX = event.x;
2279 event.globalY = event.y;
2280 event.timeStampSeconds = GetCurrentEventTimeSec();
2282 if (force_layout_on_events_)
2283 view_->layout();
2285 bool result = HandleInputEventOnViewOrPopup(event);
2287 // Long press might start a drag drop session. Complete it if so.
2288 if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
2289 WebMouseEvent mouse_event;
2290 InitMouseEvent(WebInputEvent::MouseDown,
2291 pressed_button_,
2292 WebPoint(x, y),
2293 GetCurrentEventTimeSec(),
2294 click_count_,
2296 &mouse_event);
2298 FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
2300 args->Return(result);
2303 void EventSender::UpdateClickCountForButton(
2304 WebMouseEvent::Button button_type) {
2305 if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
2306 kMultipleClickTimeSec) &&
2307 (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
2308 (button_type == last_button_type_)) {
2309 ++click_count_;
2310 } else {
2311 click_count_ = 1;
2312 last_button_type_ = button_type;
2316 void EventSender::InitMouseWheelEvent(gin::Arguments* args,
2317 bool continuous,
2318 WebMouseWheelEvent* event) {
2319 // Force a layout here just to make sure every position has been
2320 // determined before we send events (as well as all the other methods
2321 // that send an event do).
2322 if (force_layout_on_events_)
2323 view_->layout();
2325 double horizontal;
2326 if (!args->GetNext(&horizontal)) {
2327 args->ThrowError();
2328 return;
2330 double vertical;
2331 if (!args->GetNext(&vertical)) {
2332 args->ThrowError();
2333 return;
2336 bool paged = false;
2337 bool has_precise_scrolling_deltas = false;
2338 int modifiers = 0;
2339 bool can_scroll = true;
2340 if (!args->PeekNext().IsEmpty()) {
2341 args->GetNext(&paged);
2342 if (!args->PeekNext().IsEmpty()) {
2343 args->GetNext(&has_precise_scrolling_deltas);
2344 if (!args->PeekNext().IsEmpty()) {
2345 v8::Local<v8::Value> value;
2346 args->GetNext(&value);
2347 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
2348 if (!args->PeekNext().IsEmpty())
2349 args->GetNext(&can_scroll);
2354 InitMouseEvent(WebInputEvent::MouseWheel,
2355 pressed_button_,
2356 last_mouse_pos_,
2357 GetCurrentEventTimeSec(),
2358 click_count_,
2359 modifiers,
2360 event);
2361 event->wheelTicksX = static_cast<float>(horizontal);
2362 event->wheelTicksY = static_cast<float>(vertical);
2363 event->deltaX = event->wheelTicksX;
2364 event->deltaY = event->wheelTicksY;
2365 event->scrollByPage = paged;
2366 event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
2367 event->canScroll = can_scroll;
2368 if (continuous) {
2369 event->wheelTicksX /= kScrollbarPixelsPerTick;
2370 event->wheelTicksY /= kScrollbarPixelsPerTick;
2371 } else {
2372 event->deltaX *= kScrollbarPixelsPerTick;
2373 event->deltaY *= kScrollbarPixelsPerTick;
2377 void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
2378 blink::WebDragOperation drag_effect) {
2379 WebPoint client_point(e.x, e.y);
2380 WebPoint screen_point(e.globalX, e.globalY);
2381 current_drag_effect_ = drag_effect;
2382 if (current_drag_effect_) {
2383 // Specifically pass any keyboard modifiers to the drop method. This allows
2384 // tests to control the drop type (i.e. copy or move).
2385 view_->dragTargetDrop(client_point, screen_point, e.modifiers);
2386 } else {
2387 view_->dragTargetDragLeave();
2389 view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
2390 view_->dragSourceSystemDragEnded();
2392 current_drag_data_.reset();
2395 void EventSender::DoMouseUp(const WebMouseEvent& e) {
2396 HandleInputEventOnViewOrPopup(e);
2398 pressed_button_ = WebMouseEvent::ButtonNone;
2399 last_click_time_sec_ = e.timeStampSeconds;
2400 last_click_pos_ = last_mouse_pos_;
2402 // If we're in a drag operation, complete it.
2403 if (current_drag_data_.isNull())
2404 return;
2406 WebPoint client_point(e.x, e.y);
2407 WebPoint screen_point(e.globalX, e.globalY);
2408 FinishDragAndDrop(
2410 view_->dragTargetDragOver(
2411 client_point,
2412 screen_point,
2413 current_drag_effects_allowed_,
2414 e.modifiers));
2417 void EventSender::DoMouseMove(const WebMouseEvent& e) {
2418 last_mouse_pos_ = WebPoint(e.x, e.y);
2420 HandleInputEventOnViewOrPopup(e);
2422 if (pressed_button_ == WebMouseEvent::ButtonNone ||
2423 current_drag_data_.isNull()) {
2424 return;
2427 WebPoint client_point(e.x, e.y);
2428 WebPoint screen_point(e.globalX, e.globalY);
2429 current_drag_effect_ = view_->dragTargetDragOver(
2430 client_point, screen_point, current_drag_effects_allowed_, e.modifiers);
2433 void EventSender::ReplaySavedEvents() {
2434 replaying_saved_events_ = true;
2435 while (!mouse_event_queue_.empty()) {
2436 SavedEvent e = mouse_event_queue_.front();
2437 mouse_event_queue_.pop_front();
2439 switch (e.type) {
2440 case SavedEvent::TYPE_MOUSE_MOVE: {
2441 WebMouseEvent event;
2442 InitMouseEvent(WebInputEvent::MouseMove,
2443 pressed_button_,
2444 e.pos,
2445 GetCurrentEventTimeSec(),
2446 click_count_,
2447 e.modifiers,
2448 &event);
2449 DoMouseMove(event);
2450 break;
2452 case SavedEvent::TYPE_LEAP_FORWARD:
2453 DoLeapForward(e.milliseconds);
2454 break;
2455 case SavedEvent::TYPE_MOUSE_UP: {
2456 WebMouseEvent event;
2457 InitMouseEvent(WebInputEvent::MouseUp,
2458 e.button_type,
2459 last_mouse_pos_,
2460 GetCurrentEventTimeSec(),
2461 click_count_,
2462 e.modifiers,
2463 &event);
2464 DoMouseUp(event);
2465 break;
2467 default:
2468 NOTREACHED();
2472 replaying_saved_events_ = false;
2475 bool EventSender::HandleInputEventOnViewOrPopup(const WebInputEvent& event) {
2476 if (WebPagePopup* popup = view_->pagePopup()) {
2477 if (!WebInputEvent::isKeyboardEventType(event.type))
2478 return popup->handleInputEvent(event);
2480 return view_->handleInputEvent(event);
2483 } // namespace test_runner