Enable right clicking on the applist doodle web contents and log the data.
[chromium-blink-merge.git] / content / shell / renderer / test_runner / event_sender.cc
blob1960be99e20fa3f6a35c36f14288099ac31c78e5
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 "content/shell/renderer/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 "content/public/common/page_zoom.h"
12 #include "content/shell/renderer/test_runner/mock_spell_check.h"
13 #include "content/shell/renderer/test_runner/test_interfaces.h"
14 #include "content/shell/renderer/test_runner/web_test_delegate.h"
15 #include "content/shell/renderer/test_runner/web_test_proxy.h"
16 #include "gin/handle.h"
17 #include "gin/object_template_builder.h"
18 #include "gin/wrappable.h"
19 #include "third_party/WebKit/public/platform/WebString.h"
20 #include "third_party/WebKit/public/platform/WebVector.h"
21 #include "third_party/WebKit/public/web/WebContextMenuData.h"
22 #include "third_party/WebKit/public/web/WebFrame.h"
23 #include "third_party/WebKit/public/web/WebKit.h"
24 #include "third_party/WebKit/public/web/WebPagePopup.h"
25 #include "third_party/WebKit/public/web/WebView.h"
26 #include "ui/events/keycodes/dom4/keycode_converter.h"
27 #include "ui/events/keycodes/keyboard_codes.h"
28 #include "v8/include/v8.h"
30 using blink::WebContextMenuData;
31 using blink::WebDragData;
32 using blink::WebDragOperationsMask;
33 using blink::WebFloatPoint;
34 using blink::WebFrame;
35 using blink::WebGestureEvent;
36 using blink::WebInputEvent;
37 using blink::WebKeyboardEvent;
38 using blink::WebMenuItemInfo;
39 using blink::WebMouseEvent;
40 using blink::WebMouseWheelEvent;
41 using blink::WebPagePopup;
42 using blink::WebPoint;
43 using blink::WebString;
44 using blink::WebTouchEvent;
45 using blink::WebTouchPoint;
46 using blink::WebVector;
47 using blink::WebView;
49 namespace content {
51 namespace {
53 void InitMouseEvent(WebInputEvent::Type t,
54 WebMouseEvent::Button b,
55 const WebPoint& pos,
56 double time_stamp,
57 int click_count,
58 int modifiers,
59 WebMouseEvent* e) {
60 e->type = t;
61 e->button = b;
62 e->modifiers = modifiers;
63 e->x = pos.x;
64 e->y = pos.y;
65 e->globalX = pos.x;
66 e->globalY = pos.y;
67 e->timeStampSeconds = time_stamp;
68 e->clickCount = click_count;
71 int GetKeyModifier(const std::string& modifier_name) {
72 const char* characters = modifier_name.c_str();
73 if (!strcmp(characters, "ctrlKey")
74 #ifndef __APPLE__
75 || !strcmp(characters, "addSelectionKey")
76 #endif
77 ) {
78 return WebInputEvent::ControlKey;
79 } else if (!strcmp(characters, "shiftKey") ||
80 !strcmp(characters, "rangeSelectionKey")) {
81 return WebInputEvent::ShiftKey;
82 } else if (!strcmp(characters, "altKey")) {
83 return WebInputEvent::AltKey;
84 #ifdef __APPLE__
85 } else if (!strcmp(characters, "metaKey") ||
86 !strcmp(characters, "addSelectionKey")) {
87 return WebInputEvent::MetaKey;
88 #else
89 } else if (!strcmp(characters, "metaKey")) {
90 return WebInputEvent::MetaKey;
91 #endif
92 } else if (!strcmp(characters, "autoRepeat")) {
93 return WebInputEvent::IsAutoRepeat;
94 } else if (!strcmp(characters, "copyKey")) {
95 #ifdef __APPLE__
96 return WebInputEvent::AltKey;
97 #else
98 return WebInputEvent::ControlKey;
99 #endif
100 } else if (!strcmp(characters, "leftButton")) {
101 return WebInputEvent::LeftButtonDown;
102 } else if (!strcmp(characters, "middleButton")) {
103 return WebInputEvent::MiddleButtonDown;
104 } else if (!strcmp(characters, "rightButton")) {
105 return WebInputEvent::RightButtonDown;
108 return 0;
111 int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
112 int modifiers = 0;
113 for (std::vector<std::string>::const_iterator it = modifier_names.begin();
114 it != modifier_names.end(); ++it) {
115 modifiers |= GetKeyModifier(*it);
117 return modifiers;
120 int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
121 std::vector<std::string> modifier_names;
122 if (value->IsString()) {
123 modifier_names.push_back(gin::V8ToString(value));
124 } else if (value->IsArray()) {
125 gin::Converter<std::vector<std::string> >::FromV8(
126 NULL, value, &modifier_names);
128 return GetKeyModifiers(modifier_names);
131 // Maximum distance (in space and time) for a mouse click to register as a
132 // double or triple click.
133 const double kMultipleClickTimeSec = 1;
134 const int kMultipleClickRadiusPixels = 5;
135 const char kSubMenuDepthIdentifier[] = "_";
136 const char kSubMenuIdentifier[] = " >";
137 const char kSeparatorIdentifier[] = "---------";
138 const char kDisabledIdentifier[] = "#";
139 const char kCheckedIdentifier[] = "*";
141 bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
142 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
143 kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
146 void PopulateCustomItems(const WebVector<WebMenuItemInfo>& customItems,
147 const std::string& prefix, std::vector<std::string>* strings) {
148 for (size_t i = 0; i < customItems.size(); ++i) {
149 std::string prefixCopy = prefix;
150 if (!customItems[i].enabled)
151 prefixCopy = kDisabledIdentifier + prefix;
152 if (customItems[i].checked)
153 prefixCopy = kCheckedIdentifier + prefix;
154 if (customItems[i].type == blink::WebMenuItemInfo::Separator) {
155 strings->push_back(prefixCopy + kSeparatorIdentifier);
156 } else if (customItems[i].type == blink::WebMenuItemInfo::SubMenu) {
157 strings->push_back(prefixCopy + customItems[i].label.utf8() +
158 customItems[i].icon.utf8() + kSubMenuIdentifier);
159 PopulateCustomItems(customItems[i].subMenuItems, prefixCopy +
160 kSubMenuDepthIdentifier, strings);
161 } else {
162 strings->push_back(prefixCopy + customItems[i].label.utf8() +
163 customItems[i].icon.utf8());
168 // Because actual context menu is implemented by the browser side,
169 // this function does only what LayoutTests are expecting:
170 // - Many test checks the count of items. So returning non-zero value makes
171 // sense.
172 // - Some test compares the count before and after some action. So changing the
173 // count based on flags also makes sense. This function is doing such for some
174 // flags.
175 // - Some test even checks actual string content. So providing it would be also
176 // helpful.
177 std::vector<std::string> MakeMenuItemStringsFor(
178 WebContextMenuData* context_menu,
179 WebTestDelegate* delegate) {
180 // These constants are based on Safari's context menu because tests are made
181 // for it.
182 static const char* kNonEditableMenuStrings[] = {
183 "Back",
184 "Reload Page",
185 "Open in Dashbaord",
186 "<separator>",
187 "View Source",
188 "Save Page As",
189 "Print Page",
190 "Inspect Element",
193 static const char* kEditableMenuStrings[] = {
194 "Cut",
195 "Copy",
196 "<separator>",
197 "Paste",
198 "Spelling and Grammar",
199 "Substitutions, Transformations",
200 "Font",
201 "Speech",
202 "Paragraph Direction",
203 "<separator>",
207 // This is possible because mouse events are cancelleable.
208 if (!context_menu)
209 return std::vector<std::string>();
211 std::vector<std::string> strings;
213 // Populate custom menu items if provided by blink.
214 PopulateCustomItems(context_menu->customItems, "", &strings);
216 if (context_menu->isEditable) {
217 for (const char** item = kEditableMenuStrings; *item; ++item) {
218 strings.push_back(*item);
220 WebVector<WebString> suggestions;
221 MockSpellCheck::FillSuggestionList(context_menu->misspelledWord,
222 &suggestions);
223 for (size_t i = 0; i < suggestions.size(); ++i) {
224 strings.push_back(suggestions[i].utf8());
226 } else {
227 for (const char** item = kNonEditableMenuStrings; *item; ++item) {
228 strings.push_back(*item);
232 return strings;
235 // How much we should scroll per event - the value here is chosen to match the
236 // WebKit impl and layout test results.
237 const float kScrollbarPixelsPerTick = 40.0f;
239 WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
240 if (!button_code)
241 return WebMouseEvent::ButtonLeft;
242 if (button_code == 2)
243 return WebMouseEvent::ButtonRight;
244 return WebMouseEvent::ButtonMiddle;
247 class MouseDownTask : public WebMethodTask<EventSender> {
248 public:
249 MouseDownTask(EventSender* obj, int button_number, int modifiers)
250 : WebMethodTask<EventSender>(obj),
251 button_number_(button_number),
252 modifiers_(modifiers) {}
254 void RunIfValid() override { object_->MouseDown(button_number_, modifiers_); }
256 private:
257 int button_number_;
258 int modifiers_;
261 class MouseUpTask : public WebMethodTask<EventSender> {
262 public:
263 MouseUpTask(EventSender* obj, int button_number, int modifiers)
264 : WebMethodTask<EventSender>(obj),
265 button_number_(button_number),
266 modifiers_(modifiers) {}
268 void RunIfValid() override { object_->MouseUp(button_number_, modifiers_); }
270 private:
271 int button_number_;
272 int modifiers_;
275 class KeyDownTask : public WebMethodTask<EventSender> {
276 public:
277 KeyDownTask(EventSender* obj,
278 const std::string code_str,
279 int modifiers,
280 KeyLocationCode location)
281 : WebMethodTask<EventSender>(obj),
282 code_str_(code_str),
283 modifiers_(modifiers),
284 location_(location) {}
286 void RunIfValid() override {
287 object_->KeyDown(code_str_, modifiers_, location_);
290 private:
291 std::string code_str_;
292 int modifiers_;
293 KeyLocationCode location_;
296 bool NeedsShiftModifier(int keyCode) {
297 // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
298 return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
301 // Get the edit command corresponding to a keyboard event.
302 // Returns true if the specified event corresponds to an edit command, the name
303 // of the edit command will be stored in |*name|.
304 bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
305 #if defined(OS_MACOSX)
306 // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
307 // modifiers. These key events correspond to some special movement and
308 // selection editor commands. These keys will be marked as system key, which
309 // prevents them from being handled. Thus they must be handled specially.
310 if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
311 WebKeyboardEvent::MetaKey)
312 return false;
314 switch (event.windowsKeyCode) {
315 case ui::VKEY_LEFT:
316 *name = "MoveToBeginningOfLine";
317 break;
318 case ui::VKEY_RIGHT:
319 *name = "MoveToEndOfLine";
320 break;
321 case ui::VKEY_UP:
322 *name = "MoveToBeginningOfDocument";
323 break;
324 case ui::VKEY_DOWN:
325 *name = "MoveToEndOfDocument";
326 break;
327 default:
328 return false;
331 if (event.modifiers & WebKeyboardEvent::ShiftKey)
332 name->append("AndModifySelection");
334 return true;
335 #else
336 return false;
337 #endif
340 bool IsSystemKeyEvent(const WebKeyboardEvent& event) {
341 #if defined(OS_MACOSX)
342 return event.modifiers & WebInputEvent::MetaKey &&
343 event.windowsKeyCode != ui::VKEY_B &&
344 event.windowsKeyCode != ui::VKEY_I;
345 #else
346 return !!(event.modifiers & WebInputEvent::AltKey);
347 #endif
350 const char* kSourceDeviceStringTouchpad = "touchpad";
351 const char* kSourceDeviceStringTouchscreen = "touchscreen";
353 } // namespace
355 class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
356 public:
357 static gin::WrapperInfo kWrapperInfo;
359 static void Install(base::WeakPtr<EventSender> sender,
360 blink::WebFrame* frame);
362 private:
363 explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
364 ~EventSenderBindings() override;
366 // gin::Wrappable:
367 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
368 v8::Isolate* isolate) override;
370 // Bound methods:
371 void EnableDOMUIEventLogging();
372 void FireKeyboardEventsToElement();
373 void ClearKillRing();
374 std::vector<std::string> ContextClick();
375 void TextZoomIn();
376 void TextZoomOut();
377 void ZoomPageIn();
378 void ZoomPageOut();
379 void SetPageZoomFactor(double factor);
380 void SetPageScaleFactor(gin::Arguments* args);
381 void SetPageScaleFactorLimits(gin::Arguments* args);
382 void ClearTouchPoints();
383 void ReleaseTouchPoint(unsigned index);
384 void UpdateTouchPoint(unsigned index, double x, double y);
385 void CancelTouchPoint(unsigned index);
386 void SetTouchModifier(const std::string& key_name, bool set_mask);
387 void SetTouchCancelable(bool cancelable);
388 void DumpFilenameBeingDragged();
389 void GestureFlingCancel();
390 void GestureFlingStart(float x,
391 float y,
392 float velocity_x,
393 float velocity_y,
394 gin::Arguments* args);
395 void GestureScrollFirstPoint(int x, int y);
396 void TouchStart();
397 void TouchMove();
398 void TouchCancel();
399 void TouchEnd();
400 void LeapForward(int milliseconds);
401 void BeginDragWithFiles(const std::vector<std::string>& files);
402 void AddTouchPoint(gin::Arguments* args);
403 void MouseDragBegin();
404 void MouseDragEnd();
405 void GestureScrollBegin(gin::Arguments* args);
406 void GestureScrollEnd(gin::Arguments* args);
407 void GestureScrollUpdate(gin::Arguments* args);
408 void GesturePinchBegin(gin::Arguments* args);
409 void GesturePinchEnd(gin::Arguments* args);
410 void GesturePinchUpdate(gin::Arguments* args);
411 void GestureTap(gin::Arguments* args);
412 void GestureTapDown(gin::Arguments* args);
413 void GestureShowPress(gin::Arguments* args);
414 void GestureTapCancel(gin::Arguments* args);
415 void GestureLongPress(gin::Arguments* args);
416 void GestureLongTap(gin::Arguments* args);
417 void GestureTwoFingerTap(gin::Arguments* args);
418 void ContinuousMouseScrollBy(gin::Arguments* args);
419 void MouseMoveTo(gin::Arguments* args);
420 void TrackpadScrollBegin();
421 void TrackpadScroll(gin::Arguments* args);
422 void TrackpadScrollEnd();
423 void MouseScrollBy(gin::Arguments* args);
424 // TODO(erikchen): Remove MouseMomentumBegin once CL 282743002 has landed.
425 void MouseMomentumBegin();
426 void MouseMomentumBegin2(gin::Arguments* args);
427 void MouseMomentumScrollBy(gin::Arguments* args);
428 void MouseMomentumEnd();
429 void ScheduleAsynchronousClick(gin::Arguments* args);
430 void ScheduleAsynchronousKeyDown(gin::Arguments* args);
431 void MouseDown(gin::Arguments* args);
432 void MouseUp(gin::Arguments* args);
433 void KeyDown(gin::Arguments* args);
435 // Binding properties:
436 bool ForceLayoutOnEvents() const;
437 void SetForceLayoutOnEvents(bool force);
438 bool IsDragMode() const;
439 void SetIsDragMode(bool drag_mode);
441 #if defined(OS_WIN)
442 int WmKeyDown() const;
443 void SetWmKeyDown(int key_down);
445 int WmKeyUp() const;
446 void SetWmKeyUp(int key_up);
448 int WmChar() const;
449 void SetWmChar(int wm_char);
451 int WmDeadChar() const;
452 void SetWmDeadChar(int dead_char);
454 int WmSysKeyDown() const;
455 void SetWmSysKeyDown(int key_down);
457 int WmSysKeyUp() const;
458 void SetWmSysKeyUp(int key_up);
460 int WmSysChar() const;
461 void SetWmSysChar(int sys_char);
463 int WmSysDeadChar() const;
464 void SetWmSysDeadChar(int sys_dead_char);
465 #endif
467 base::WeakPtr<EventSender> sender_;
469 DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
472 gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
474 EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
475 : sender_(sender) {
478 EventSenderBindings::~EventSenderBindings() {}
480 // static
481 void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
482 WebFrame* frame) {
483 v8::Isolate* isolate = blink::mainThreadIsolate();
484 v8::HandleScope handle_scope(isolate);
485 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
486 if (context.IsEmpty())
487 return;
489 v8::Context::Scope context_scope(context);
491 gin::Handle<EventSenderBindings> bindings =
492 gin::CreateHandle(isolate, new EventSenderBindings(sender));
493 if (bindings.IsEmpty())
494 return;
495 v8::Handle<v8::Object> global = context->Global();
496 global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
499 gin::ObjectTemplateBuilder
500 EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
501 return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
502 .SetMethod("enableDOMUIEventLogging",
503 &EventSenderBindings::EnableDOMUIEventLogging)
504 .SetMethod("fireKeyboardEventsToElement",
505 &EventSenderBindings::FireKeyboardEventsToElement)
506 .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
507 .SetMethod("contextClick", &EventSenderBindings::ContextClick)
508 .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
509 .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
510 .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
511 .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
512 .SetMethod("setPageZoomFactor", &EventSenderBindings::SetPageZoomFactor)
513 .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
514 .SetMethod("setPageScaleFactorLimits",
515 &EventSenderBindings::SetPageScaleFactorLimits)
516 .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
517 .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
518 .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
519 .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
520 .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
521 .SetMethod("setTouchCancelable", &EventSenderBindings::SetTouchCancelable)
522 .SetMethod("dumpFilenameBeingDragged",
523 &EventSenderBindings::DumpFilenameBeingDragged)
524 .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
525 .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
526 .SetMethod("gestureScrollFirstPoint",
527 &EventSenderBindings::GestureScrollFirstPoint)
528 .SetMethod("touchStart", &EventSenderBindings::TouchStart)
529 .SetMethod("touchMove", &EventSenderBindings::TouchMove)
530 .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
531 .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
532 .SetMethod("leapForward", &EventSenderBindings::LeapForward)
533 .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
534 .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
535 .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
536 .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
537 .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
538 .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
539 .SetMethod("gestureScrollUpdate",
540 &EventSenderBindings::GestureScrollUpdate)
541 .SetMethod("gesturePinchBegin", &EventSenderBindings::GesturePinchBegin)
542 .SetMethod("gesturePinchEnd", &EventSenderBindings::GesturePinchEnd)
543 .SetMethod("gesturePinchUpdate", &EventSenderBindings::GesturePinchUpdate)
544 .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
545 .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
546 .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
547 .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
548 .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
549 .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
550 .SetMethod("gestureTwoFingerTap",
551 &EventSenderBindings::GestureTwoFingerTap)
552 .SetMethod("continuousMouseScrollBy",
553 &EventSenderBindings::ContinuousMouseScrollBy)
554 .SetMethod("keyDown", &EventSenderBindings::KeyDown)
555 .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
556 .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
557 .SetMethod("trackpadScrollBegin",
558 &EventSenderBindings::TrackpadScrollBegin)
559 .SetMethod("trackpadScroll", &EventSenderBindings::TrackpadScroll)
560 .SetMethod("trackpadScrollEnd", &EventSenderBindings::TrackpadScrollEnd)
561 .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
562 .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
563 .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
564 .SetMethod("mouseMomentumBegin2",
565 &EventSenderBindings::MouseMomentumBegin2)
566 .SetMethod("mouseMomentumScrollBy",
567 &EventSenderBindings::MouseMomentumScrollBy)
568 .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
569 .SetMethod("scheduleAsynchronousClick",
570 &EventSenderBindings::ScheduleAsynchronousClick)
571 .SetMethod("scheduleAsynchronousKeyDown",
572 &EventSenderBindings::ScheduleAsynchronousKeyDown)
573 .SetProperty("forceLayoutOnEvents",
574 &EventSenderBindings::ForceLayoutOnEvents,
575 &EventSenderBindings::SetForceLayoutOnEvents)
576 .SetProperty("dragMode",
577 &EventSenderBindings::IsDragMode,
578 &EventSenderBindings::SetIsDragMode)
579 #if defined(OS_WIN)
580 .SetProperty("WM_KEYDOWN",
581 &EventSenderBindings::WmKeyDown,
582 &EventSenderBindings::SetWmKeyDown)
583 .SetProperty("WM_KEYUP",
584 &EventSenderBindings::WmKeyUp,
585 &EventSenderBindings::SetWmKeyUp)
586 .SetProperty("WM_CHAR",
587 &EventSenderBindings::WmChar,
588 &EventSenderBindings::SetWmChar)
589 .SetProperty("WM_DEADCHAR",
590 &EventSenderBindings::WmDeadChar,
591 &EventSenderBindings::SetWmDeadChar)
592 .SetProperty("WM_SYSKEYDOWN",
593 &EventSenderBindings::WmSysKeyDown,
594 &EventSenderBindings::SetWmSysKeyDown)
595 .SetProperty("WM_SYSKEYUP",
596 &EventSenderBindings::WmSysKeyUp,
597 &EventSenderBindings::SetWmSysKeyUp)
598 .SetProperty("WM_SYSCHAR",
599 &EventSenderBindings::WmSysChar,
600 &EventSenderBindings::SetWmSysChar)
601 .SetProperty("WM_SYSDEADCHAR",
602 &EventSenderBindings::WmSysDeadChar,
603 &EventSenderBindings::SetWmSysDeadChar);
604 #else
606 #endif
609 void EventSenderBindings::EnableDOMUIEventLogging() {
610 if (sender_)
611 sender_->EnableDOMUIEventLogging();
614 void EventSenderBindings::FireKeyboardEventsToElement() {
615 if (sender_)
616 sender_->FireKeyboardEventsToElement();
619 void EventSenderBindings::ClearKillRing() {
620 if (sender_)
621 sender_->ClearKillRing();
624 std::vector<std::string> EventSenderBindings::ContextClick() {
625 if (sender_)
626 return sender_->ContextClick();
627 return std::vector<std::string>();
630 void EventSenderBindings::TextZoomIn() {
631 if (sender_)
632 sender_->TextZoomIn();
635 void EventSenderBindings::TextZoomOut() {
636 if (sender_)
637 sender_->TextZoomOut();
640 void EventSenderBindings::ZoomPageIn() {
641 if (sender_)
642 sender_->ZoomPageIn();
645 void EventSenderBindings::ZoomPageOut() {
646 if (sender_)
647 sender_->ZoomPageOut();
650 void EventSenderBindings::SetPageZoomFactor(double factor) {
651 if (sender_)
652 sender_->SetPageZoomFactor(factor);
655 void EventSenderBindings::SetPageScaleFactor(gin::Arguments* args) {
656 if (!sender_)
657 return;
658 float scale_factor;
659 double x;
660 double y;
661 if (args->PeekNext().IsEmpty())
662 return;
663 args->GetNext(&scale_factor);
664 if (args->PeekNext().IsEmpty())
665 return;
666 args->GetNext(&x);
667 if (args->PeekNext().IsEmpty())
668 return;
669 args->GetNext(&y);
670 sender_->SetPageScaleFactor(scale_factor,
671 static_cast<int>(x), static_cast<int>(y));
674 void EventSenderBindings::SetPageScaleFactorLimits(gin::Arguments* args) {
675 if (!sender_)
676 return;
677 float min_scale_factor;
678 float max_scale_factor;
679 if (args->PeekNext().IsEmpty())
680 return;
681 args->GetNext(&min_scale_factor);
682 if (args->PeekNext().IsEmpty())
683 return;
684 args->GetNext(&max_scale_factor);
685 sender_->SetPageScaleFactorLimits(min_scale_factor, max_scale_factor);
688 void EventSenderBindings::ClearTouchPoints() {
689 if (sender_)
690 sender_->ClearTouchPoints();
693 void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
694 if (sender_)
695 sender_->ReleaseTouchPoint(index);
698 void EventSenderBindings::UpdateTouchPoint(unsigned index, double x, double y) {
699 if (sender_)
700 sender_->UpdateTouchPoint(index, static_cast<float>(x), static_cast<float>(y));
703 void EventSenderBindings::CancelTouchPoint(unsigned index) {
704 if (sender_)
705 sender_->CancelTouchPoint(index);
708 void EventSenderBindings::SetTouchModifier(const std::string& key_name,
709 bool set_mask) {
710 if (sender_)
711 sender_->SetTouchModifier(key_name, set_mask);
714 void EventSenderBindings::SetTouchCancelable(bool cancelable) {
715 if (sender_)
716 sender_->SetTouchCancelable(cancelable);
719 void EventSenderBindings::DumpFilenameBeingDragged() {
720 if (sender_)
721 sender_->DumpFilenameBeingDragged();
724 void EventSenderBindings::GestureFlingCancel() {
725 if (sender_)
726 sender_->GestureFlingCancel();
729 void EventSenderBindings::GestureFlingStart(float x,
730 float y,
731 float velocity_x,
732 float velocity_y,
733 gin::Arguments* args) {
734 if (sender_)
735 sender_->GestureFlingStart(x, y, velocity_x, velocity_y, args);
738 void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
739 if (sender_)
740 sender_->GestureScrollFirstPoint(x, y);
743 void EventSenderBindings::TouchStart() {
744 if (sender_)
745 sender_->TouchStart();
748 void EventSenderBindings::TouchMove() {
749 if (sender_)
750 sender_->TouchMove();
753 void EventSenderBindings::TouchCancel() {
754 if (sender_)
755 sender_->TouchCancel();
758 void EventSenderBindings::TouchEnd() {
759 if (sender_)
760 sender_->TouchEnd();
763 void EventSenderBindings::LeapForward(int milliseconds) {
764 if (sender_)
765 sender_->LeapForward(milliseconds);
768 void EventSenderBindings::BeginDragWithFiles(
769 const std::vector<std::string>& files) {
770 if (sender_)
771 sender_->BeginDragWithFiles(files);
774 void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
775 if (sender_)
776 sender_->AddTouchPoint(args);
779 void EventSenderBindings::MouseDragBegin() {
780 if (sender_)
781 sender_->MouseDragBegin();
784 void EventSenderBindings::MouseDragEnd() {
785 if (sender_)
786 sender_->MouseDragEnd();
789 void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
790 if (sender_)
791 sender_->GestureScrollBegin(args);
794 void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
795 if (sender_)
796 sender_->GestureScrollEnd(args);
799 void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
800 if (sender_)
801 sender_->GestureScrollUpdate(args);
804 void EventSenderBindings::GesturePinchBegin(gin::Arguments* args) {
805 if (sender_)
806 sender_->GesturePinchBegin(args);
809 void EventSenderBindings::GesturePinchEnd(gin::Arguments* args) {
810 if (sender_)
811 sender_->GesturePinchEnd(args);
814 void EventSenderBindings::GesturePinchUpdate(gin::Arguments* args) {
815 if (sender_)
816 sender_->GesturePinchUpdate(args);
819 void EventSenderBindings::GestureTap(gin::Arguments* args) {
820 if (sender_)
821 sender_->GestureTap(args);
824 void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
825 if (sender_)
826 sender_->GestureTapDown(args);
829 void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
830 if (sender_)
831 sender_->GestureShowPress(args);
834 void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
835 if (sender_)
836 sender_->GestureTapCancel(args);
839 void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
840 if (sender_)
841 sender_->GestureLongPress(args);
844 void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
845 if (sender_)
846 sender_->GestureLongTap(args);
849 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
850 if (sender_)
851 sender_->GestureTwoFingerTap(args);
854 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
855 if (sender_)
856 sender_->ContinuousMouseScrollBy(args);
859 void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
860 if (sender_)
861 sender_->MouseMoveTo(args);
864 void EventSenderBindings::TrackpadScrollBegin() {
865 if (sender_)
866 sender_->TrackpadScrollBegin();
869 void EventSenderBindings::TrackpadScroll(gin::Arguments* args) {
870 if (sender_)
871 sender_->TrackpadScroll(args);
874 void EventSenderBindings::TrackpadScrollEnd() {
875 if (sender_)
876 sender_->TrackpadScrollEnd();
879 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
880 if (sender_)
881 sender_->MouseScrollBy(args);
884 void EventSenderBindings::MouseMomentumBegin() {
885 if (sender_)
886 sender_->MouseMomentumBegin();
889 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments* args) {
890 if (sender_)
891 sender_->MouseMomentumBegin2(args);
894 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
895 if (sender_)
896 sender_->MouseMomentumScrollBy(args);
899 void EventSenderBindings::MouseMomentumEnd() {
900 if (sender_)
901 sender_->MouseMomentumEnd();
904 void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
905 if (!sender_)
906 return;
908 int button_number = 0;
909 int modifiers = 0;
910 if (!args->PeekNext().IsEmpty()) {
911 args->GetNext(&button_number);
912 if (!args->PeekNext().IsEmpty())
913 modifiers = GetKeyModifiersFromV8(args->PeekNext());
915 sender_->ScheduleAsynchronousClick(button_number, modifiers);
918 void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
919 if (!sender_)
920 return;
922 std::string code_str;
923 int modifiers = 0;
924 int location = DOMKeyLocationStandard;
925 args->GetNext(&code_str);
926 if (!args->PeekNext().IsEmpty()) {
927 v8::Handle<v8::Value> value;
928 args->GetNext(&value);
929 modifiers = GetKeyModifiersFromV8(value);
930 if (!args->PeekNext().IsEmpty())
931 args->GetNext(&location);
933 sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
934 static_cast<KeyLocationCode>(location));
937 void EventSenderBindings::MouseDown(gin::Arguments* args) {
938 if (!sender_)
939 return;
941 int button_number = 0;
942 int modifiers = 0;
943 if (!args->PeekNext().IsEmpty()) {
944 args->GetNext(&button_number);
945 if (!args->PeekNext().IsEmpty())
946 modifiers = GetKeyModifiersFromV8(args->PeekNext());
948 sender_->MouseDown(button_number, modifiers);
951 void EventSenderBindings::MouseUp(gin::Arguments* args) {
952 if (!sender_)
953 return;
955 int button_number = 0;
956 int modifiers = 0;
957 if (!args->PeekNext().IsEmpty()) {
958 args->GetNext(&button_number);
959 if (!args->PeekNext().IsEmpty())
960 modifiers = GetKeyModifiersFromV8(args->PeekNext());
962 sender_->MouseUp(button_number, modifiers);
965 void EventSenderBindings::KeyDown(gin::Arguments* args) {
966 if (!sender_)
967 return;
969 std::string code_str;
970 int modifiers = 0;
971 int location = DOMKeyLocationStandard;
972 args->GetNext(&code_str);
973 if (!args->PeekNext().IsEmpty()) {
974 v8::Handle<v8::Value> value;
975 args->GetNext(&value);
976 modifiers = GetKeyModifiersFromV8(value);
977 if (!args->PeekNext().IsEmpty())
978 args->GetNext(&location);
980 sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
983 bool EventSenderBindings::ForceLayoutOnEvents() const {
984 if (sender_)
985 return sender_->force_layout_on_events();
986 return false;
989 void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
990 if (sender_)
991 sender_->set_force_layout_on_events(force);
994 bool EventSenderBindings::IsDragMode() const {
995 if (sender_)
996 return sender_->is_drag_mode();
997 return true;
1000 void EventSenderBindings::SetIsDragMode(bool drag_mode) {
1001 if (sender_)
1002 sender_->set_is_drag_mode(drag_mode);
1005 #if defined(OS_WIN)
1006 int EventSenderBindings::WmKeyDown() const {
1007 if (sender_)
1008 return sender_->wm_key_down();
1009 return 0;
1012 void EventSenderBindings::SetWmKeyDown(int key_down) {
1013 if (sender_)
1014 sender_->set_wm_key_down(key_down);
1017 int EventSenderBindings::WmKeyUp() const {
1018 if (sender_)
1019 return sender_->wm_key_up();
1020 return 0;
1023 void EventSenderBindings::SetWmKeyUp(int key_up) {
1024 if (sender_)
1025 sender_->set_wm_key_up(key_up);
1028 int EventSenderBindings::WmChar() const {
1029 if (sender_)
1030 return sender_->wm_char();
1031 return 0;
1034 void EventSenderBindings::SetWmChar(int wm_char) {
1035 if (sender_)
1036 sender_->set_wm_char(wm_char);
1039 int EventSenderBindings::WmDeadChar() const {
1040 if (sender_)
1041 return sender_->wm_dead_char();
1042 return 0;
1045 void EventSenderBindings::SetWmDeadChar(int dead_char) {
1046 if (sender_)
1047 sender_->set_wm_dead_char(dead_char);
1050 int EventSenderBindings::WmSysKeyDown() const {
1051 if (sender_)
1052 return sender_->wm_sys_key_down();
1053 return 0;
1056 void EventSenderBindings::SetWmSysKeyDown(int key_down) {
1057 if (sender_)
1058 sender_->set_wm_sys_key_down(key_down);
1061 int EventSenderBindings::WmSysKeyUp() const {
1062 if (sender_)
1063 return sender_->wm_sys_key_up();
1064 return 0;
1067 void EventSenderBindings::SetWmSysKeyUp(int key_up) {
1068 if (sender_)
1069 sender_->set_wm_sys_key_up(key_up);
1072 int EventSenderBindings::WmSysChar() const {
1073 if (sender_)
1074 return sender_->wm_sys_char();
1075 return 0;
1078 void EventSenderBindings::SetWmSysChar(int sys_char) {
1079 if (sender_)
1080 sender_->set_wm_sys_char(sys_char);
1083 int EventSenderBindings::WmSysDeadChar() const {
1084 if (sender_)
1085 return sender_->wm_sys_dead_char();
1086 return 0;
1089 void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
1090 if (sender_)
1091 sender_->set_wm_sys_dead_char(sys_dead_char);
1093 #endif
1095 // EventSender -----------------------------------------------------------------
1097 WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
1099 WebPoint EventSender::last_mouse_pos_;
1101 WebMouseEvent::Button EventSender::last_button_type_ =
1102 WebMouseEvent::ButtonNone;
1104 EventSender::SavedEvent::SavedEvent()
1105 : type(TYPE_UNSPECIFIED),
1106 button_type(WebMouseEvent::ButtonNone),
1107 milliseconds(0),
1108 modifiers(0) {}
1110 EventSender::EventSender(TestInterfaces* interfaces)
1111 : interfaces_(interfaces),
1112 delegate_(NULL),
1113 view_(NULL),
1114 force_layout_on_events_(false),
1115 is_drag_mode_(true),
1116 touch_modifiers_(0),
1117 touch_cancelable_(true),
1118 replaying_saved_events_(false),
1119 current_drag_effects_allowed_(blink::WebDragOperationNone),
1120 last_click_time_sec_(0),
1121 current_drag_effect_(blink::WebDragOperationNone),
1122 time_offset_ms_(0),
1123 click_count_(0),
1124 #if defined(OS_WIN)
1125 wm_key_down_(0),
1126 wm_key_up_(0),
1127 wm_char_(0),
1128 wm_dead_char_(0),
1129 wm_sys_key_down_(0),
1130 wm_sys_key_up_(0),
1131 wm_sys_char_(0),
1132 wm_sys_dead_char_(0),
1133 #endif
1134 weak_factory_(this) {}
1136 EventSender::~EventSender() {}
1138 void EventSender::Reset() {
1139 DCHECK(current_drag_data_.isNull());
1140 current_drag_data_.reset();
1141 current_drag_effect_ = blink::WebDragOperationNone;
1142 current_drag_effects_allowed_ = blink::WebDragOperationNone;
1143 if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
1144 view_->mouseCaptureLost();
1145 pressed_button_ = WebMouseEvent::ButtonNone;
1146 is_drag_mode_ = true;
1147 force_layout_on_events_ = true;
1149 #if defined(OS_WIN)
1150 wm_key_down_ = WM_KEYDOWN;
1151 wm_key_up_ = WM_KEYUP;
1152 wm_char_ = WM_CHAR;
1153 wm_dead_char_ = WM_DEADCHAR;
1154 wm_sys_key_down_ = WM_SYSKEYDOWN;
1155 wm_sys_key_up_ = WM_SYSKEYUP;
1156 wm_sys_char_ = WM_SYSCHAR;
1157 wm_sys_dead_char_ = WM_SYSDEADCHAR;
1158 #endif
1160 last_mouse_pos_ = WebPoint(0, 0);
1161 last_click_time_sec_ = 0;
1162 last_click_pos_ = WebPoint(0, 0);
1163 last_button_type_ = WebMouseEvent::ButtonNone;
1164 touch_points_.clear();
1165 last_context_menu_data_.reset();
1166 task_list_.RevokeAll();
1167 current_gesture_location_ = WebPoint(0, 0);
1168 mouse_event_queue_.clear();
1170 time_offset_ms_ = 0;
1171 click_count_ = 0;
1173 touch_modifiers_ = 0;
1174 touch_cancelable_ = true;
1175 touch_points_.clear();
1178 void EventSender::Install(WebFrame* frame) {
1179 EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
1182 void EventSender::SetDelegate(WebTestDelegate* delegate) {
1183 delegate_ = delegate;
1186 void EventSender::SetWebView(WebView* view) {
1187 view_ = view;
1190 void EventSender::SetContextMenuData(const WebContextMenuData& data) {
1191 last_context_menu_data_.reset(new WebContextMenuData(data));
1194 void EventSender::DoDragDrop(const WebDragData& drag_data,
1195 WebDragOperationsMask mask) {
1196 WebMouseEvent event;
1197 InitMouseEvent(WebInputEvent::MouseDown,
1198 pressed_button_,
1199 last_mouse_pos_,
1200 GetCurrentEventTimeSec(),
1201 click_count_,
1203 &event);
1204 WebPoint client_point(event.x, event.y);
1205 WebPoint screen_point(event.globalX, event.globalY);
1206 current_drag_data_ = drag_data;
1207 current_drag_effects_allowed_ = mask;
1208 current_drag_effect_ = view_->dragTargetDragEnter(
1209 drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
1211 // Finish processing events.
1212 ReplaySavedEvents();
1215 void EventSender::MouseDown(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 UpdateClickCountForButton(button_type);
1226 pressed_button_ = button_type;
1228 WebMouseEvent event;
1229 InitMouseEvent(WebInputEvent::MouseDown,
1230 button_type,
1231 last_mouse_pos_,
1232 GetCurrentEventTimeSec(),
1233 click_count_,
1234 modifiers,
1235 &event);
1236 HandleInputEventOnViewOrPopup(event);
1239 void EventSender::MouseUp(int button_number, int modifiers) {
1240 if (force_layout_on_events_)
1241 view_->layout();
1243 DCHECK_NE(-1, button_number);
1245 WebMouseEvent::Button button_type =
1246 GetButtonTypeFromButtonNumber(button_number);
1248 if (is_drag_mode_ && !replaying_saved_events_) {
1249 SavedEvent saved_event;
1250 saved_event.type = SavedEvent::TYPE_MOUSE_UP;
1251 saved_event.button_type = button_type;
1252 saved_event.modifiers = modifiers;
1253 mouse_event_queue_.push_back(saved_event);
1254 ReplaySavedEvents();
1255 } else {
1256 WebMouseEvent event;
1257 InitMouseEvent(WebInputEvent::MouseUp,
1258 button_type,
1259 last_mouse_pos_,
1260 GetCurrentEventTimeSec(),
1261 click_count_,
1262 modifiers,
1263 &event);
1264 DoMouseUp(event);
1268 void EventSender::KeyDown(const std::string& code_str,
1269 int modifiers,
1270 KeyLocationCode location) {
1271 // FIXME: I'm not exactly sure how we should convert the string to a key
1272 // event. This seems to work in the cases I tested.
1273 // FIXME: Should we also generate a KEY_UP?
1275 bool generate_char = false;
1277 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
1278 // Windows uses \r for "Enter".
1279 int code = 0;
1280 int text = 0;
1281 bool needs_shift_key_modifier = false;
1282 std::string domString;
1284 if ("\n" == code_str) {
1285 generate_char = true;
1286 text = code = ui::VKEY_RETURN;
1287 domString.assign("Enter");
1288 } else if ("rightArrow" == code_str) {
1289 code = ui::VKEY_RIGHT;
1290 domString.assign("ArrowRight");
1291 } else if ("downArrow" == code_str) {
1292 code = ui::VKEY_DOWN;
1293 domString.assign("ArrowDown");
1294 } else if ("leftArrow" == code_str) {
1295 code = ui::VKEY_LEFT;
1296 domString.assign("ArrowLeft");
1297 } else if ("upArrow" == code_str) {
1298 code = ui::VKEY_UP;
1299 domString.assign("ArrowUp");
1300 } else if ("insert" == code_str) {
1301 code = ui::VKEY_INSERT;
1302 domString.assign("Insert");
1303 } else if ("delete" == code_str) {
1304 code = ui::VKEY_DELETE;
1305 domString.assign("Delete");
1306 } else if ("pageUp" == code_str) {
1307 code = ui::VKEY_PRIOR;
1308 domString.assign("PageUp");
1309 } else if ("pageDown" == code_str) {
1310 code = ui::VKEY_NEXT;
1311 domString.assign("PageDown");
1312 } else if ("home" == code_str) {
1313 code = ui::VKEY_HOME;
1314 domString.assign("Home");
1315 } else if ("end" == code_str) {
1316 code = ui::VKEY_END;
1317 domString.assign("End");
1318 } else if ("printScreen" == code_str) {
1319 code = ui::VKEY_SNAPSHOT;
1320 domString.assign("PrintScreen");
1321 } else if ("menu" == code_str) {
1322 code = ui::VKEY_APPS;
1323 domString.assign("ContextMenu");
1324 } else if ("leftControl" == code_str) {
1325 code = ui::VKEY_LCONTROL;
1326 domString.assign("ControlLeft");
1327 } else if ("rightControl" == code_str) {
1328 code = ui::VKEY_RCONTROL;
1329 domString.assign("ControlRight");
1330 } else if ("leftShift" == code_str) {
1331 code = ui::VKEY_LSHIFT;
1332 domString.assign("ShiftLeft");
1333 } else if ("rightShift" == code_str) {
1334 code = ui::VKEY_RSHIFT;
1335 domString.assign("ShiftRight");
1336 } else if ("leftAlt" == code_str) {
1337 code = ui::VKEY_LMENU;
1338 domString.assign("AltLeft");
1339 } else if ("rightAlt" == code_str) {
1340 code = ui::VKEY_RMENU;
1341 domString.assign("AltRight");
1342 } else if ("numLock" == code_str) {
1343 code = ui::VKEY_NUMLOCK;
1344 domString.assign("NumLock");
1345 } else if ("backspace" == code_str) {
1346 code = ui::VKEY_BACK;
1347 domString.assign("Backspace");
1348 } else if ("escape" == code_str) {
1349 code = ui::VKEY_ESCAPE;
1350 domString.assign("Escape");
1351 } else {
1352 // Compare the input string with the function-key names defined by the
1353 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
1354 // name, set its key code.
1355 for (int i = 1; i <= 24; ++i) {
1356 std::string function_key_name = base::StringPrintf("F%d", i);
1357 if (function_key_name == code_str) {
1358 code = ui::VKEY_F1 + (i - 1);
1359 domString = function_key_name;
1360 break;
1363 if (!code) {
1364 WebString web_code_str =
1365 WebString::fromUTF8(code_str.data(), code_str.size());
1366 DCHECK_EQ(1u, web_code_str.length());
1367 text = code = web_code_str.at(0);
1368 needs_shift_key_modifier = NeedsShiftModifier(code);
1369 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
1370 code -= 'a' - 'A';
1371 if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z')) {
1372 domString.assign("Key");
1373 domString.push_back(base::ToUpperASCII(code));
1374 } else if (code >= '0' && code <= '9') {
1375 domString.assign("Digit");
1376 domString.push_back(code);
1377 } else if (code == ' ') {
1378 domString.assign("Space");
1379 } else if (code == 9) {
1380 domString.assign("Tab");
1382 generate_char = true;
1385 if ("(" == code_str) {
1386 code = '9';
1387 needs_shift_key_modifier = true;
1391 // For one generated keyboard event, we need to generate a keyDown/keyUp
1392 // pair;
1393 // On Windows, we might also need to generate a char event to mimic the
1394 // Windows event flow; on other platforms we create a merged event and test
1395 // the event flow that that platform provides.
1396 WebKeyboardEvent event_down;
1397 event_down.type = WebInputEvent::RawKeyDown;
1398 event_down.modifiers = modifiers;
1399 event_down.windowsKeyCode = code;
1400 event_down.domCode = static_cast<int>(
1401 ui::KeycodeConverter::CodeStringToDomCode(domString.c_str()));
1403 if (generate_char) {
1404 event_down.text[0] = text;
1405 event_down.unmodifiedText[0] = text;
1408 event_down.setKeyIdentifierFromWindowsKeyCode();
1410 if (event_down.modifiers != 0)
1411 event_down.isSystemKey = IsSystemKeyEvent(event_down);
1413 if (needs_shift_key_modifier)
1414 event_down.modifiers |= WebInputEvent::ShiftKey;
1416 // See if KeyLocation argument is given.
1417 if (location == DOMKeyLocationNumpad)
1418 event_down.modifiers |= WebInputEvent::IsKeyPad;
1420 WebKeyboardEvent event_up;
1421 event_up = event_down;
1422 event_up.type = WebInputEvent::KeyUp;
1423 // EventSender.m forces a layout here, with at least one
1424 // test (fast/forms/focus-control-to-page.html) relying on this.
1425 if (force_layout_on_events_)
1426 view_->layout();
1428 // In the browser, if a keyboard event corresponds to an editor command,
1429 // the command will be dispatched to the renderer just before dispatching
1430 // the keyboard event, and then it will be executed in the
1431 // RenderView::handleCurrentKeyboardEvent() method.
1432 // We just simulate the same behavior here.
1433 std::string edit_command;
1434 if (GetEditCommand(event_down, &edit_command))
1435 delegate_->SetEditCommand(edit_command, "");
1437 HandleInputEventOnViewOrPopup(event_down);
1439 if (code == ui::VKEY_ESCAPE && !current_drag_data_.isNull()) {
1440 WebMouseEvent event;
1441 InitMouseEvent(WebInputEvent::MouseDown,
1442 pressed_button_,
1443 last_mouse_pos_,
1444 GetCurrentEventTimeSec(),
1445 click_count_,
1447 &event);
1448 FinishDragAndDrop(event, blink::WebDragOperationNone);
1451 delegate_->ClearEditCommand();
1453 if (generate_char) {
1454 WebKeyboardEvent event_char = event_up;
1455 event_char.type = WebInputEvent::Char;
1456 // keyIdentifier is an empty string, unless the Enter key was pressed.
1457 // This behavior is not standard (keyIdentifier itself is not even a
1458 // standard any more), but it matches the actual behavior in Blink.
1459 if (code != ui::VKEY_RETURN)
1460 event_char.keyIdentifier[0] = '\0';
1461 HandleInputEventOnViewOrPopup(event_char);
1464 HandleInputEventOnViewOrPopup(event_up);
1467 void EventSender::EnableDOMUIEventLogging() {}
1469 void EventSender::FireKeyboardEventsToElement() {}
1471 void EventSender::ClearKillRing() {}
1473 std::vector<std::string> EventSender::ContextClick() {
1474 if (force_layout_on_events_) {
1475 view_->layout();
1478 UpdateClickCountForButton(WebMouseEvent::ButtonRight);
1480 // Clears last context menu data because we need to know if the context menu
1481 // be requested after following mouse events.
1482 last_context_menu_data_.reset();
1484 // Generate right mouse down and up.
1485 WebMouseEvent event;
1486 // This is a hack to work around only allowing a single pressed button since
1487 // we want to test the case where both the left and right mouse buttons are
1488 // pressed.
1489 if (pressed_button_ == WebMouseEvent::ButtonNone) {
1490 pressed_button_ = WebMouseEvent::ButtonRight;
1492 InitMouseEvent(WebInputEvent::MouseDown,
1493 WebMouseEvent::ButtonRight,
1494 last_mouse_pos_,
1495 GetCurrentEventTimeSec(),
1496 click_count_,
1498 &event);
1499 HandleInputEventOnViewOrPopup(event);
1501 #if defined(OS_WIN)
1502 InitMouseEvent(WebInputEvent::MouseUp,
1503 WebMouseEvent::ButtonRight,
1504 last_mouse_pos_,
1505 GetCurrentEventTimeSec(),
1506 click_count_,
1508 &event);
1509 HandleInputEventOnViewOrPopup(event);
1511 pressed_button_= WebMouseEvent::ButtonNone;
1512 #endif
1514 std::vector<std::string> menu_items = MakeMenuItemStringsFor(last_context_menu_data_.get(), delegate_);
1515 last_context_menu_data_.reset();
1516 return menu_items;
1519 void EventSender::TextZoomIn() {
1520 view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
1523 void EventSender::TextZoomOut() {
1524 view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
1527 void EventSender::ZoomPageIn() {
1528 const std::vector<WebTestProxyBase*>& window_list =
1529 interfaces_->GetWindowList();
1531 for (size_t i = 0; i < window_list.size(); ++i) {
1532 window_list.at(i)->GetWebView()->setZoomLevel(
1533 window_list.at(i)->GetWebView()->zoomLevel() + 1);
1537 void EventSender::ZoomPageOut() {
1538 const std::vector<WebTestProxyBase*>& window_list =
1539 interfaces_->GetWindowList();
1541 for (size_t i = 0; i < window_list.size(); ++i) {
1542 window_list.at(i)->GetWebView()->setZoomLevel(
1543 window_list.at(i)->GetWebView()->zoomLevel() - 1);
1547 void EventSender::SetPageZoomFactor(double zoom_factor) {
1548 const std::vector<WebTestProxyBase*>& window_list =
1549 interfaces_->GetWindowList();
1551 for (size_t i = 0; i < window_list.size(); ++i) {
1552 window_list.at(i)->GetWebView()->setZoomLevel(
1553 ZoomFactorToZoomLevel(zoom_factor));
1557 void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
1558 view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
1561 void EventSender::SetPageScaleFactorLimits(float min_scale, float max_scale) {
1562 view_->setDefaultPageScaleLimits(min_scale, max_scale);
1565 void EventSender::ClearTouchPoints() {
1566 touch_points_.clear();
1569 void EventSender::ThrowTouchPointError() {
1570 v8::Isolate* isolate = blink::mainThreadIsolate();
1571 isolate->ThrowException(v8::Exception::TypeError(
1572 gin::StringToV8(isolate, "Invalid touch point.")));
1575 void EventSender::ReleaseTouchPoint(unsigned index) {
1576 if (index >= touch_points_.size()) {
1577 ThrowTouchPointError();
1578 return;
1581 WebTouchPoint* touch_point = &touch_points_[index];
1582 touch_point->state = WebTouchPoint::StateReleased;
1585 void EventSender::UpdateTouchPoint(unsigned index, float x, float y) {
1586 if (index >= touch_points_.size()) {
1587 ThrowTouchPointError();
1588 return;
1591 WebTouchPoint* touch_point = &touch_points_[index];
1592 touch_point->state = WebTouchPoint::StateMoved;
1593 touch_point->position = WebFloatPoint(x, y);
1594 touch_point->screenPosition = touch_point->position;
1597 void EventSender::CancelTouchPoint(unsigned index) {
1598 if (index >= touch_points_.size()) {
1599 ThrowTouchPointError();
1600 return;
1603 WebTouchPoint* touch_point = &touch_points_[index];
1604 touch_point->state = WebTouchPoint::StateCancelled;
1607 void EventSender::SetTouchModifier(const std::string& key_name,
1608 bool set_mask) {
1609 int mask = 0;
1610 if (key_name == "shift")
1611 mask = WebInputEvent::ShiftKey;
1612 else if (key_name == "alt")
1613 mask = WebInputEvent::AltKey;
1614 else if (key_name == "ctrl")
1615 mask = WebInputEvent::ControlKey;
1616 else if (key_name == "meta")
1617 mask = WebInputEvent::MetaKey;
1619 if (set_mask)
1620 touch_modifiers_ |= mask;
1621 else
1622 touch_modifiers_ &= ~mask;
1625 void EventSender::SetTouchCancelable(bool cancelable) {
1626 touch_cancelable_ = cancelable;
1629 void EventSender::DumpFilenameBeingDragged() {
1630 if (current_drag_data_.isNull())
1631 return;
1633 WebString filename;
1634 WebVector<WebDragData::Item> items = current_drag_data_.items();
1635 for (size_t i = 0; i < items.size(); ++i) {
1636 if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
1637 filename = items[i].title;
1638 break;
1641 delegate_->PrintMessage(std::string("Filename being dragged: ") +
1642 filename.utf8().data() + "\n");
1645 void EventSender::GestureFlingCancel() {
1646 WebGestureEvent event;
1647 event.type = WebInputEvent::GestureFlingCancel;
1648 event.timeStampSeconds = GetCurrentEventTimeSec();
1650 if (force_layout_on_events_)
1651 view_->layout();
1653 HandleInputEventOnViewOrPopup(event);
1656 void EventSender::GestureFlingStart(float x,
1657 float y,
1658 float velocity_x,
1659 float velocity_y,
1660 gin::Arguments* args) {
1661 WebGestureEvent event;
1662 event.type = WebInputEvent::GestureFlingStart;
1664 std::string device_string;
1665 if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsString())
1666 args->GetNext(&device_string);
1668 if (device_string == kSourceDeviceStringTouchpad) {
1669 event.sourceDevice = blink::WebGestureDeviceTouchpad;
1670 } else if (device_string == kSourceDeviceStringTouchscreen) {
1671 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
1672 } else {
1673 args->ThrowError();
1674 return;
1677 event.x = x;
1678 event.y = y;
1679 event.globalX = event.x;
1680 event.globalY = event.y;
1682 event.data.flingStart.velocityX = velocity_x;
1683 event.data.flingStart.velocityY = velocity_y;
1684 event.timeStampSeconds = GetCurrentEventTimeSec();
1686 if (force_layout_on_events_)
1687 view_->layout();
1689 HandleInputEventOnViewOrPopup(event);
1692 void EventSender::GestureScrollFirstPoint(int x, int y) {
1693 current_gesture_location_ = WebPoint(x, y);
1696 void EventSender::TouchStart() {
1697 SendCurrentTouchEvent(WebInputEvent::TouchStart);
1700 void EventSender::TouchMove() {
1701 SendCurrentTouchEvent(WebInputEvent::TouchMove);
1704 void EventSender::TouchCancel() {
1705 SendCurrentTouchEvent(WebInputEvent::TouchCancel);
1708 void EventSender::TouchEnd() {
1709 SendCurrentTouchEvent(WebInputEvent::TouchEnd);
1712 void EventSender::LeapForward(int milliseconds) {
1713 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1714 !replaying_saved_events_) {
1715 SavedEvent saved_event;
1716 saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
1717 saved_event.milliseconds = milliseconds;
1718 mouse_event_queue_.push_back(saved_event);
1719 } else {
1720 DoLeapForward(milliseconds);
1724 void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
1725 current_drag_data_.initialize();
1726 WebVector<WebString> absolute_filenames(files.size());
1727 for (size_t i = 0; i < files.size(); ++i) {
1728 WebDragData::Item item;
1729 item.storageType = WebDragData::Item::StorageTypeFilename;
1730 item.filenameData = delegate_->GetAbsoluteWebStringFromUTF8Path(files[i]);
1731 current_drag_data_.addItem(item);
1732 absolute_filenames[i] = item.filenameData;
1734 current_drag_data_.setFilesystemId(
1735 delegate_->RegisterIsolatedFileSystem(absolute_filenames));
1736 current_drag_effects_allowed_ = blink::WebDragOperationCopy;
1738 // Provide a drag source.
1739 view_->dragTargetDragEnter(current_drag_data_,
1740 last_mouse_pos_,
1741 last_mouse_pos_,
1742 current_drag_effects_allowed_,
1744 // |is_drag_mode_| saves events and then replays them later. We don't
1745 // need/want that.
1746 is_drag_mode_ = false;
1748 // Make the rest of eventSender think a drag is in progress.
1749 pressed_button_ = WebMouseEvent::ButtonLeft;
1752 void EventSender::AddTouchPoint(gin::Arguments* args) {
1753 double x;
1754 double y;
1755 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1756 args->ThrowError();
1757 return;
1760 WebTouchPoint touch_point;
1761 touch_point.state = WebTouchPoint::StatePressed;
1762 touch_point.position = WebFloatPoint(static_cast<float>(x),
1763 static_cast<float>(y));
1764 touch_point.screenPosition = touch_point.position;
1766 if (!args->PeekNext().IsEmpty()) {
1767 double radius_x;
1768 if (!args->GetNext(&radius_x)) {
1769 args->ThrowError();
1770 return;
1773 double radius_y = radius_x;
1774 if (!args->PeekNext().IsEmpty()) {
1775 if (!args->GetNext(&radius_y)) {
1776 args->ThrowError();
1777 return;
1781 touch_point.radiusX = static_cast<float>(radius_x);
1782 touch_point.radiusY = static_cast<float>(radius_y);
1785 int lowest_id = 0;
1786 for (size_t i = 0; i < touch_points_.size(); i++) {
1787 if (touch_points_[i].id == lowest_id)
1788 lowest_id++;
1790 touch_point.id = lowest_id;
1791 touch_points_.push_back(touch_point);
1794 void EventSender::MouseDragBegin() {
1795 WebMouseWheelEvent event;
1796 InitMouseEvent(WebInputEvent::MouseWheel,
1797 WebMouseEvent::ButtonNone,
1798 last_mouse_pos_,
1799 GetCurrentEventTimeSec(),
1800 click_count_,
1802 &event);
1803 event.phase = WebMouseWheelEvent::PhaseBegan;
1804 event.hasPreciseScrollingDeltas = true;
1805 HandleInputEventOnViewOrPopup(event);
1808 void EventSender::MouseDragEnd() {
1809 WebMouseWheelEvent event;
1810 InitMouseEvent(WebInputEvent::MouseWheel,
1811 WebMouseEvent::ButtonNone,
1812 last_mouse_pos_,
1813 GetCurrentEventTimeSec(),
1814 click_count_,
1816 &event);
1817 event.phase = WebMouseWheelEvent::PhaseEnded;
1818 event.hasPreciseScrollingDeltas = true;
1819 HandleInputEventOnViewOrPopup(event);
1822 void EventSender::GestureScrollBegin(gin::Arguments* args) {
1823 GestureEvent(WebInputEvent::GestureScrollBegin, args);
1826 void EventSender::GestureScrollEnd(gin::Arguments* args) {
1827 GestureEvent(WebInputEvent::GestureScrollEnd, args);
1830 void EventSender::GestureScrollUpdate(gin::Arguments* args) {
1831 GestureEvent(WebInputEvent::GestureScrollUpdate, args);
1834 void EventSender::GesturePinchBegin(gin::Arguments* args) {
1835 GestureEvent(WebInputEvent::GesturePinchBegin, args);
1838 void EventSender::GesturePinchEnd(gin::Arguments* args) {
1839 GestureEvent(WebInputEvent::GesturePinchEnd, args);
1842 void EventSender::GesturePinchUpdate(gin::Arguments* args) {
1843 GestureEvent(WebInputEvent::GesturePinchUpdate, args);
1846 void EventSender::GestureTap(gin::Arguments* args) {
1847 GestureEvent(WebInputEvent::GestureTap, args);
1850 void EventSender::GestureTapDown(gin::Arguments* args) {
1851 GestureEvent(WebInputEvent::GestureTapDown, args);
1854 void EventSender::GestureShowPress(gin::Arguments* args) {
1855 GestureEvent(WebInputEvent::GestureShowPress, args);
1858 void EventSender::GestureTapCancel(gin::Arguments* args) {
1859 GestureEvent(WebInputEvent::GestureTapCancel, args);
1862 void EventSender::GestureLongPress(gin::Arguments* args) {
1863 GestureEvent(WebInputEvent::GestureLongPress, args);
1866 void EventSender::GestureLongTap(gin::Arguments* args) {
1867 GestureEvent(WebInputEvent::GestureLongTap, args);
1870 void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
1871 GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
1874 void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
1875 WebMouseWheelEvent event;
1876 InitMouseWheelEvent(args, true, &event);
1877 HandleInputEventOnViewOrPopup(event);
1880 void EventSender::MouseMoveTo(gin::Arguments* args) {
1881 if (force_layout_on_events_)
1882 view_->layout();
1884 double x;
1885 double y;
1886 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1887 args->ThrowError();
1888 return;
1890 WebPoint mouse_pos(static_cast<int>(x), static_cast<int>(y));
1892 int modifiers = 0;
1893 if (!args->PeekNext().IsEmpty())
1894 modifiers = GetKeyModifiersFromV8(args->PeekNext());
1896 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1897 !replaying_saved_events_) {
1898 SavedEvent saved_event;
1899 saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
1900 saved_event.pos = mouse_pos;
1901 saved_event.modifiers = modifiers;
1902 mouse_event_queue_.push_back(saved_event);
1903 } else {
1904 WebMouseEvent event;
1905 InitMouseEvent(WebInputEvent::MouseMove,
1906 pressed_button_,
1907 mouse_pos,
1908 GetCurrentEventTimeSec(),
1909 click_count_,
1910 modifiers,
1911 &event);
1912 DoMouseMove(event);
1916 void EventSender::TrackpadScrollBegin() {
1917 WebMouseWheelEvent event;
1918 InitMouseEvent(WebInputEvent::MouseWheel,
1919 WebMouseEvent::ButtonNone,
1920 last_mouse_pos_,
1921 GetCurrentEventTimeSec(),
1922 click_count_,
1924 &event);
1925 event.phase = blink::WebMouseWheelEvent::PhaseBegan;
1926 event.hasPreciseScrollingDeltas = true;
1927 HandleInputEventOnViewOrPopup(event);
1930 void EventSender::TrackpadScroll(gin::Arguments* args) {
1931 WebMouseWheelEvent event;
1932 InitMouseWheelEvent(args, true, &event);
1933 event.phase = blink::WebMouseWheelEvent::PhaseChanged;
1934 event.hasPreciseScrollingDeltas = true;
1935 HandleInputEventOnViewOrPopup(event);
1938 void EventSender::TrackpadScrollEnd() {
1939 WebMouseWheelEvent event;
1940 InitMouseEvent(WebInputEvent::MouseWheel,
1941 WebMouseEvent::ButtonNone,
1942 last_mouse_pos_,
1943 GetCurrentEventTimeSec(),
1944 click_count_,
1946 &event);
1947 event.phase = WebMouseWheelEvent::PhaseEnded;
1948 event.hasPreciseScrollingDeltas = true;
1949 HandleInputEventOnViewOrPopup(event);
1952 void EventSender::MouseScrollBy(gin::Arguments* args) {
1953 WebMouseWheelEvent event;
1954 InitMouseWheelEvent(args, false, &event);
1955 HandleInputEventOnViewOrPopup(event);
1958 void EventSender::MouseMomentumBegin() {
1959 WebMouseWheelEvent event;
1960 InitMouseEvent(WebInputEvent::MouseWheel,
1961 WebMouseEvent::ButtonNone,
1962 last_mouse_pos_,
1963 GetCurrentEventTimeSec(),
1964 click_count_,
1966 &event);
1967 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1968 event.hasPreciseScrollingDeltas = true;
1969 HandleInputEventOnViewOrPopup(event);
1972 void EventSender::MouseMomentumBegin2(gin::Arguments* args) {
1973 WebMouseWheelEvent event;
1974 InitMouseWheelEvent(args, true, &event);
1975 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1976 event.hasPreciseScrollingDeltas = true;
1977 HandleInputEventOnViewOrPopup(event);
1980 void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
1981 WebMouseWheelEvent event;
1982 InitMouseWheelEvent(args, true, &event);
1983 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1984 event.hasPreciseScrollingDeltas = true;
1985 HandleInputEventOnViewOrPopup(event);
1988 void EventSender::MouseMomentumEnd() {
1989 WebMouseWheelEvent event;
1990 InitMouseEvent(WebInputEvent::MouseWheel,
1991 WebMouseEvent::ButtonNone,
1992 last_mouse_pos_,
1993 GetCurrentEventTimeSec(),
1994 click_count_,
1996 &event);
1997 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1998 event.hasPreciseScrollingDeltas = true;
1999 HandleInputEventOnViewOrPopup(event);
2002 void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
2003 delegate_->PostTask(new MouseDownTask(this, button_number, modifiers));
2004 delegate_->PostTask(new MouseUpTask(this, button_number, modifiers));
2007 void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
2008 int modifiers,
2009 KeyLocationCode location) {
2010 delegate_->PostTask(new KeyDownTask(this, code_str, modifiers, location));
2013 double EventSender::GetCurrentEventTimeSec() {
2014 return (delegate_->GetCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
2017 void EventSender::DoLeapForward(int milliseconds) {
2018 time_offset_ms_ += milliseconds;
2021 void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
2022 DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
2023 touch_points_.size());
2024 if (force_layout_on_events_)
2025 view_->layout();
2027 WebTouchEvent touch_event;
2028 touch_event.type = type;
2029 touch_event.modifiers = touch_modifiers_;
2030 touch_event.cancelable = touch_cancelable_;
2031 touch_event.timeStampSeconds = GetCurrentEventTimeSec();
2032 touch_event.touchesLength = touch_points_.size();
2033 for (size_t i = 0; i < touch_points_.size(); ++i)
2034 touch_event.touches[i] = touch_points_[i];
2035 HandleInputEventOnViewOrPopup(touch_event);
2037 for (size_t i = 0; i < touch_points_.size(); ++i) {
2038 WebTouchPoint* touch_point = &touch_points_[i];
2039 if (touch_point->state == WebTouchPoint::StateReleased) {
2040 touch_points_.erase(touch_points_.begin() + i);
2041 --i;
2042 } else
2043 touch_point->state = WebTouchPoint::StateStationary;
2047 void EventSender::GestureEvent(WebInputEvent::Type type,
2048 gin::Arguments* args) {
2049 WebGestureEvent event;
2050 event.type = type;
2052 // If the first argument is a string, it is to specify the device, otherwise
2053 // the device is assumed to be a touchscreen (since most tests were written
2054 // assuming this).
2055 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2056 if (args->PeekNext()->IsString()) {
2057 std::string device_string;
2058 if (!args->GetNext(&device_string)) {
2059 args->ThrowError();
2060 return;
2062 if (device_string == kSourceDeviceStringTouchpad) {
2063 event.sourceDevice = blink::WebGestureDeviceTouchpad;
2064 } else if (device_string == kSourceDeviceStringTouchscreen) {
2065 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2066 } else {
2067 args->ThrowError();
2068 return;
2072 double x;
2073 double y;
2074 if (!args->GetNext(&x) || !args->GetNext(&y)) {
2075 args->ThrowError();
2076 return;
2079 switch (type) {
2080 case WebInputEvent::GestureScrollUpdate:
2082 bool preventPropagation = false;
2083 if (!args->PeekNext().IsEmpty()) {
2084 if (!args->GetNext(&preventPropagation)) {
2085 args->ThrowError();
2086 return;
2090 event.data.scrollUpdate.deltaX = static_cast<float>(x);
2091 event.data.scrollUpdate.deltaY = static_cast<float>(y);
2092 event.data.scrollUpdate.preventPropagation = preventPropagation;
2093 event.x = current_gesture_location_.x;
2094 event.y = current_gesture_location_.y;
2095 current_gesture_location_.x =
2096 current_gesture_location_.x + event.data.scrollUpdate.deltaX;
2097 current_gesture_location_.y =
2098 current_gesture_location_.y + event.data.scrollUpdate.deltaY;
2099 break;
2101 case WebInputEvent::GestureScrollBegin:
2102 current_gesture_location_ = WebPoint(x, y);
2103 event.x = current_gesture_location_.x;
2104 event.y = current_gesture_location_.y;
2105 break;
2106 case WebInputEvent::GestureScrollEnd:
2107 case WebInputEvent::GestureFlingStart:
2108 event.x = current_gesture_location_.x;
2109 event.y = current_gesture_location_.y;
2110 break;
2111 case WebInputEvent::GesturePinchBegin:
2112 case WebInputEvent::GesturePinchEnd:
2113 current_gesture_location_ = WebPoint(x, y);
2114 event.x = current_gesture_location_.x;
2115 event.y = current_gesture_location_.y;
2116 break;
2117 case WebInputEvent::GesturePinchUpdate:
2119 float scale = 1;
2120 if (!args->PeekNext().IsEmpty()) {
2121 if (!args->GetNext(&scale)) {
2122 args->ThrowError();
2123 return;
2126 event.data.pinchUpdate.scale = scale;
2127 current_gesture_location_ = WebPoint(x, y);
2128 event.x = current_gesture_location_.x;
2129 event.y = current_gesture_location_.y;
2130 break;
2132 case WebInputEvent::GestureTap:
2134 float tap_count = 1;
2135 float width = 30;
2136 float height = 30;
2137 if (!args->PeekNext().IsEmpty()) {
2138 if (!args->GetNext(&tap_count)) {
2139 args->ThrowError();
2140 return;
2143 if (!args->PeekNext().IsEmpty()) {
2144 if (!args->GetNext(&width)) {
2145 args->ThrowError();
2146 return;
2149 if (!args->PeekNext().IsEmpty()) {
2150 if (!args->GetNext(&height)) {
2151 args->ThrowError();
2152 return;
2155 event.data.tap.tapCount = tap_count;
2156 event.data.tap.width = width;
2157 event.data.tap.height = height;
2158 event.x = x;
2159 event.y = y;
2160 break;
2162 case WebInputEvent::GestureTapUnconfirmed:
2163 if (!args->PeekNext().IsEmpty()) {
2164 float tap_count;
2165 if (!args->GetNext(&tap_count)) {
2166 args->ThrowError();
2167 return;
2169 event.data.tap.tapCount = tap_count;
2170 } else {
2171 event.data.tap.tapCount = 1;
2173 event.x = x;
2174 event.y = y;
2175 break;
2176 case WebInputEvent::GestureTapDown:
2178 float width = 30;
2179 float height = 30;
2180 if (!args->PeekNext().IsEmpty()) {
2181 if (!args->GetNext(&width)) {
2182 args->ThrowError();
2183 return;
2186 if (!args->PeekNext().IsEmpty()) {
2187 if (!args->GetNext(&height)) {
2188 args->ThrowError();
2189 return;
2192 event.x = x;
2193 event.y = y;
2194 event.data.tapDown.width = width;
2195 event.data.tapDown.height = height;
2196 break;
2198 case WebInputEvent::GestureShowPress:
2200 float width = 30;
2201 float height = 30;
2202 if (!args->PeekNext().IsEmpty()) {
2203 if (!args->GetNext(&width)) {
2204 args->ThrowError();
2205 return;
2207 if (!args->PeekNext().IsEmpty()) {
2208 if (!args->GetNext(&height)) {
2209 args->ThrowError();
2210 return;
2214 event.x = x;
2215 event.y = y;
2216 event.data.showPress.width = width;
2217 event.data.showPress.height = height;
2218 break;
2220 case WebInputEvent::GestureTapCancel:
2221 event.x = x;
2222 event.y = y;
2223 break;
2224 case WebInputEvent::GestureLongPress:
2225 event.x = x;
2226 event.y = y;
2227 if (!args->PeekNext().IsEmpty()) {
2228 float width;
2229 if (!args->GetNext(&width)) {
2230 args->ThrowError();
2231 return;
2233 event.data.longPress.width = width;
2234 if (!args->PeekNext().IsEmpty()) {
2235 float height;
2236 if (!args->GetNext(&height)) {
2237 args->ThrowError();
2238 return;
2240 event.data.longPress.height = height;
2243 break;
2244 case WebInputEvent::GestureLongTap:
2245 event.x = x;
2246 event.y = y;
2247 if (!args->PeekNext().IsEmpty()) {
2248 float width;
2249 if (!args->GetNext(&width)) {
2250 args->ThrowError();
2251 return;
2253 event.data.longPress.width = width;
2254 if (!args->PeekNext().IsEmpty()) {
2255 float height;
2256 if (!args->GetNext(&height)) {
2257 args->ThrowError();
2258 return;
2260 event.data.longPress.height = height;
2263 break;
2264 case WebInputEvent::GestureTwoFingerTap:
2265 event.x = x;
2266 event.y = y;
2267 if (!args->PeekNext().IsEmpty()) {
2268 float first_finger_width;
2269 if (!args->GetNext(&first_finger_width)) {
2270 args->ThrowError();
2271 return;
2273 event.data.twoFingerTap.firstFingerWidth = first_finger_width;
2274 if (!args->PeekNext().IsEmpty()) {
2275 float first_finger_height;
2276 if (!args->GetNext(&first_finger_height)) {
2277 args->ThrowError();
2278 return;
2280 event.data.twoFingerTap.firstFingerHeight = first_finger_height;
2283 break;
2284 default:
2285 NOTREACHED();
2288 event.globalX = event.x;
2289 event.globalY = event.y;
2290 event.timeStampSeconds = GetCurrentEventTimeSec();
2292 if (force_layout_on_events_)
2293 view_->layout();
2295 bool result = HandleInputEventOnViewOrPopup(event);
2297 // Long press might start a drag drop session. Complete it if so.
2298 if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
2299 WebMouseEvent mouse_event;
2300 InitMouseEvent(WebInputEvent::MouseDown,
2301 pressed_button_,
2302 WebPoint(x, y),
2303 GetCurrentEventTimeSec(),
2304 click_count_,
2306 &mouse_event);
2308 FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
2310 args->Return(result);
2313 void EventSender::UpdateClickCountForButton(
2314 WebMouseEvent::Button button_type) {
2315 if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
2316 kMultipleClickTimeSec) &&
2317 (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
2318 (button_type == last_button_type_)) {
2319 ++click_count_;
2320 } else {
2321 click_count_ = 1;
2322 last_button_type_ = button_type;
2326 void EventSender::InitMouseWheelEvent(gin::Arguments* args,
2327 bool continuous,
2328 WebMouseWheelEvent* event) {
2329 // Force a layout here just to make sure every position has been
2330 // determined before we send events (as well as all the other methods
2331 // that send an event do).
2332 if (force_layout_on_events_)
2333 view_->layout();
2335 double horizontal;
2336 if (!args->GetNext(&horizontal)) {
2337 args->ThrowError();
2338 return;
2340 double vertical;
2341 if (!args->GetNext(&vertical)) {
2342 args->ThrowError();
2343 return;
2346 bool paged = false;
2347 bool has_precise_scrolling_deltas = false;
2348 int modifiers = 0;
2349 bool can_scroll = true;
2350 if (!args->PeekNext().IsEmpty()) {
2351 args->GetNext(&paged);
2352 if (!args->PeekNext().IsEmpty()) {
2353 args->GetNext(&has_precise_scrolling_deltas);
2354 if (!args->PeekNext().IsEmpty()) {
2355 v8::Handle<v8::Value> value;
2356 args->GetNext(&value);
2357 modifiers = GetKeyModifiersFromV8(value);
2358 if (!args->PeekNext().IsEmpty())
2359 args->GetNext(&can_scroll);
2364 InitMouseEvent(WebInputEvent::MouseWheel,
2365 pressed_button_,
2366 last_mouse_pos_,
2367 GetCurrentEventTimeSec(),
2368 click_count_,
2369 modifiers,
2370 event);
2371 event->wheelTicksX = static_cast<float>(horizontal);
2372 event->wheelTicksY = static_cast<float>(vertical);
2373 event->deltaX = event->wheelTicksX;
2374 event->deltaY = event->wheelTicksY;
2375 event->scrollByPage = paged;
2376 event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
2377 event->canScroll = can_scroll;
2378 if (continuous) {
2379 event->wheelTicksX /= kScrollbarPixelsPerTick;
2380 event->wheelTicksY /= kScrollbarPixelsPerTick;
2381 } else {
2382 event->deltaX *= kScrollbarPixelsPerTick;
2383 event->deltaY *= kScrollbarPixelsPerTick;
2387 void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
2388 blink::WebDragOperation drag_effect) {
2389 WebPoint client_point(e.x, e.y);
2390 WebPoint screen_point(e.globalX, e.globalY);
2391 current_drag_effect_ = drag_effect;
2392 if (current_drag_effect_) {
2393 // Specifically pass any keyboard modifiers to the drop method. This allows
2394 // tests to control the drop type (i.e. copy or move).
2395 view_->dragTargetDrop(client_point, screen_point, e.modifiers);
2396 } else {
2397 view_->dragTargetDragLeave();
2399 view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
2400 view_->dragSourceSystemDragEnded();
2402 current_drag_data_.reset();
2405 void EventSender::DoMouseUp(const WebMouseEvent& e) {
2406 HandleInputEventOnViewOrPopup(e);
2408 pressed_button_ = WebMouseEvent::ButtonNone;
2409 last_click_time_sec_ = e.timeStampSeconds;
2410 last_click_pos_ = last_mouse_pos_;
2412 // If we're in a drag operation, complete it.
2413 if (current_drag_data_.isNull())
2414 return;
2416 WebPoint client_point(e.x, e.y);
2417 WebPoint screen_point(e.globalX, e.globalY);
2418 FinishDragAndDrop(
2420 view_->dragTargetDragOver(
2421 client_point, screen_point, current_drag_effects_allowed_, 0));
2424 void EventSender::DoMouseMove(const WebMouseEvent& e) {
2425 last_mouse_pos_ = WebPoint(e.x, e.y);
2427 HandleInputEventOnViewOrPopup(e);
2429 if (pressed_button_ == WebMouseEvent::ButtonNone ||
2430 current_drag_data_.isNull()) {
2431 return;
2434 WebPoint client_point(e.x, e.y);
2435 WebPoint screen_point(e.globalX, e.globalY);
2436 current_drag_effect_ = view_->dragTargetDragOver(
2437 client_point, screen_point, current_drag_effects_allowed_, 0);
2440 void EventSender::ReplaySavedEvents() {
2441 replaying_saved_events_ = true;
2442 while (!mouse_event_queue_.empty()) {
2443 SavedEvent e = mouse_event_queue_.front();
2444 mouse_event_queue_.pop_front();
2446 switch (e.type) {
2447 case SavedEvent::TYPE_MOUSE_MOVE: {
2448 WebMouseEvent event;
2449 InitMouseEvent(WebInputEvent::MouseMove,
2450 pressed_button_,
2451 e.pos,
2452 GetCurrentEventTimeSec(),
2453 click_count_,
2454 e.modifiers,
2455 &event);
2456 DoMouseMove(event);
2457 break;
2459 case SavedEvent::TYPE_LEAP_FORWARD:
2460 DoLeapForward(e.milliseconds);
2461 break;
2462 case SavedEvent::TYPE_MOUSE_UP: {
2463 WebMouseEvent event;
2464 InitMouseEvent(WebInputEvent::MouseUp,
2465 e.button_type,
2466 last_mouse_pos_,
2467 GetCurrentEventTimeSec(),
2468 click_count_,
2469 e.modifiers,
2470 &event);
2471 DoMouseUp(event);
2472 break;
2474 default:
2475 NOTREACHED();
2479 replaying_saved_events_ = false;
2482 bool EventSender::HandleInputEventOnViewOrPopup(const WebInputEvent& event) {
2483 if (WebPagePopup* popup = view_->pagePopup()) {
2484 if (!WebInputEvent::isKeyboardEventType(event.type))
2485 return popup->handleInputEvent(event);
2487 return view_->handleInputEvent(event);
2490 } // namespace content