Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: content/shell/renderer/test_runner/event_sender.cc

Issue 1167703002: Move test runner to a component (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updates Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/shell/renderer/test_runner/event_sender.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "content/shell/renderer/test_runner/mock_spell_check.h"
12 #include "content/shell/renderer/test_runner/test_interfaces.h"
13 #include "content/shell/renderer/test_runner/web_test_delegate.h"
14 #include "content/shell/renderer/test_runner/web_test_proxy.h"
15 #include "gin/handle.h"
16 #include "gin/object_template_builder.h"
17 #include "gin/wrappable.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebVector.h"
20 #include "third_party/WebKit/public/web/WebContextMenuData.h"
21 #include "third_party/WebKit/public/web/WebFrame.h"
22 #include "third_party/WebKit/public/web/WebKit.h"
23 #include "third_party/WebKit/public/web/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"
28
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;
47
48 namespace content {
49
50 namespace {
51
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;
68 }
69
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;
105 }
106
107 return 0;
108 }
109
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);
115 }
116 return modifiers;
117 }
118
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);
126 }
127 return GetKeyModifiers(modifier_names);
128 }
129
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[] = "*";
139
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;
143 }
144
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());
163 }
164 }
165 }
166
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",
190 0
191 };
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>",
203 0
204 };
205
206 // This is possible because mouse events are cancelleable.
207 if (!context_menu)
208 return std::vector<std::string>();
209
210 std::vector<std::string> strings;
211
212 // Populate custom menu items if provided by blink.
213 PopulateCustomItems(context_menu->customItems, "", &strings);
214
215 if (context_menu->isEditable) {
216 for (const char** item = kEditableMenuStrings; *item; ++item) {
217 strings.push_back(*item);
218 }
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());
224 }
225 } else {
226 for (const char** item = kNonEditableMenuStrings; *item; ++item) {
227 strings.push_back(*item);
228 }
229 }
230
231 return strings;
232 }
233
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;
237
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;
244 }
245
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) {}
252
253 void RunIfValid() override { object_->MouseDown(button_number_, modifiers_); }
254
255 private:
256 int button_number_;
257 int modifiers_;
258 };
259
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) {}
266
267 void RunIfValid() override { object_->MouseUp(button_number_, modifiers_); }
268
269 private:
270 int button_number_;
271 int modifiers_;
272 };
273
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) {}
284
285 void RunIfValid() override {
286 object_->KeyDown(code_str_, modifiers_, location_);
287 }
288
289 private:
290 std::string code_str_;
291 int modifiers_;
292 KeyLocationCode location_;
293 };
294
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';
298 }
299
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;
312
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;
328 }
329
330 if (event.modifiers & WebKeyboardEvent::ShiftKey)
331 name->append("AndModifySelection");
332
333 return true;
334 #else
335 return false;
336 #endif
337 }
338
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
347 }
348
349 const char* kSourceDeviceStringTouchpad = "touchpad";
350 const char* kSourceDeviceStringTouchscreen = "touchscreen";
351
352 } // namespace
353
354 class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
355 public:
356 static gin::WrapperInfo kWrapperInfo;
357
358 static void Install(base::WeakPtr<EventSender> sender,
359 blink::WebFrame* frame);
360
361 private:
362 explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
363 ~EventSenderBindings() override;
364
365 // gin::Wrappable:
366 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
367 v8::Isolate* isolate) override;
368
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);
432
433 // Binding properties:
434 bool ForceLayoutOnEvents() const;
435 void SetForceLayoutOnEvents(bool force);
436 bool IsDragMode() const;
437 void SetIsDragMode(bool drag_mode);
438
439 #if defined(OS_WIN)
440 int WmKeyDown() const;
441 void SetWmKeyDown(int key_down);
442
443 int WmKeyUp() const;
444 void SetWmKeyUp(int key_up);
445
446 int WmChar() const;
447 void SetWmChar(int wm_char);
448
449 int WmDeadChar() const;
450 void SetWmDeadChar(int dead_char);
451
452 int WmSysKeyDown() const;
453 void SetWmSysKeyDown(int key_down);
454
455 int WmSysKeyUp() const;
456 void SetWmSysKeyUp(int key_up);
457
458 int WmSysChar() const;
459 void SetWmSysChar(int sys_char);
460
461 int WmSysDeadChar() const;
462 void SetWmSysDeadChar(int sys_dead_char);
463 #endif
464
465 base::WeakPtr<EventSender> sender_;
466
467 DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
468 };
469
470 gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
471
472 EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
473 : sender_(sender) {
474 }
475
476 EventSenderBindings::~EventSenderBindings() {}
477
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;
486
487 v8::Context::Scope context_scope(context);
488
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());
495 }
496
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
601 ;
602 #endif
603 }
604
605 void EventSenderBindings::EnableDOMUIEventLogging() {
606 if (sender_)
607 sender_->EnableDOMUIEventLogging();
608 }
609
610 void EventSenderBindings::FireKeyboardEventsToElement() {
611 if (sender_)
612 sender_->FireKeyboardEventsToElement();
613 }
614
615 void EventSenderBindings::ClearKillRing() {
616 if (sender_)
617 sender_->ClearKillRing();
618 }
619
620 std::vector<std::string> EventSenderBindings::ContextClick() {
621 if (sender_)
622 return sender_->ContextClick();
623 return std::vector<std::string>();
624 }
625
626 void EventSenderBindings::TextZoomIn() {
627 if (sender_)
628 sender_->TextZoomIn();
629 }
630
631 void EventSenderBindings::TextZoomOut() {
632 if (sender_)
633 sender_->TextZoomOut();
634 }
635
636 void EventSenderBindings::ZoomPageIn() {
637 if (sender_)
638 sender_->ZoomPageIn();
639 }
640
641 void EventSenderBindings::ZoomPageOut() {
642 if (sender_)
643 sender_->ZoomPageOut();
644 }
645
646 void EventSenderBindings::SetPageZoomFactor(double factor) {
647 if (sender_)
648 sender_->SetPageZoomFactor(factor);
649 }
650
651 void EventSenderBindings::ClearTouchPoints() {
652 if (sender_)
653 sender_->ClearTouchPoints();
654 }
655
656 void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
657 if (sender_)
658 sender_->ReleaseTouchPoint(index);
659 }
660
661 void EventSenderBindings::UpdateTouchPoint(unsigned index, double x, double y) {
662 if (sender_)
663 sender_->UpdateTouchPoint(index, static_cast<float>(x), static_cast<float>(y ));
664 }
665
666 void EventSenderBindings::CancelTouchPoint(unsigned index) {
667 if (sender_)
668 sender_->CancelTouchPoint(index);
669 }
670
671 void EventSenderBindings::SetTouchModifier(const std::string& key_name,
672 bool set_mask) {
673 if (sender_)
674 sender_->SetTouchModifier(key_name, set_mask);
675 }
676
677 void EventSenderBindings::SetTouchCancelable(bool cancelable) {
678 if (sender_)
679 sender_->SetTouchCancelable(cancelable);
680 }
681
682 void EventSenderBindings::DumpFilenameBeingDragged() {
683 if (sender_)
684 sender_->DumpFilenameBeingDragged();
685 }
686
687 void EventSenderBindings::GestureFlingCancel() {
688 if (sender_)
689 sender_->GestureFlingCancel();
690 }
691
692 void EventSenderBindings::GestureFlingStart(float x,
693 float y,
694 float velocity_x,
695 float velocity_y,
696 gin::Arguments* args) {
697 if (sender_)
698 sender_->GestureFlingStart(x, y, velocity_x, velocity_y, args);
699 }
700
701 void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
702 if (sender_)
703 sender_->GestureScrollFirstPoint(x, y);
704 }
705
706 void EventSenderBindings::TouchStart() {
707 if (sender_)
708 sender_->TouchStart();
709 }
710
711 void EventSenderBindings::TouchMove() {
712 if (sender_)
713 sender_->TouchMove();
714 }
715
716 void EventSenderBindings::TouchCancel() {
717 if (sender_)
718 sender_->TouchCancel();
719 }
720
721 void EventSenderBindings::TouchEnd() {
722 if (sender_)
723 sender_->TouchEnd();
724 }
725
726 void EventSenderBindings::LeapForward(int milliseconds) {
727 if (sender_)
728 sender_->LeapForward(milliseconds);
729 }
730
731 void EventSenderBindings::BeginDragWithFiles(
732 const std::vector<std::string>& files) {
733 if (sender_)
734 sender_->BeginDragWithFiles(files);
735 }
736
737 void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
738 if (sender_)
739 sender_->AddTouchPoint(args);
740 }
741
742 void EventSenderBindings::MouseDragBegin() {
743 if (sender_)
744 sender_->MouseDragBegin();
745 }
746
747 void EventSenderBindings::MouseDragEnd() {
748 if (sender_)
749 sender_->MouseDragEnd();
750 }
751
752 void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
753 if (sender_)
754 sender_->GestureScrollBegin(args);
755 }
756
757 void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
758 if (sender_)
759 sender_->GestureScrollEnd(args);
760 }
761
762 void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
763 if (sender_)
764 sender_->GestureScrollUpdate(args);
765 }
766
767 void EventSenderBindings::GesturePinchBegin(gin::Arguments* args) {
768 if (sender_)
769 sender_->GesturePinchBegin(args);
770 }
771
772 void EventSenderBindings::GesturePinchEnd(gin::Arguments* args) {
773 if (sender_)
774 sender_->GesturePinchEnd(args);
775 }
776
777 void EventSenderBindings::GesturePinchUpdate(gin::Arguments* args) {
778 if (sender_)
779 sender_->GesturePinchUpdate(args);
780 }
781
782 void EventSenderBindings::GestureTap(gin::Arguments* args) {
783 if (sender_)
784 sender_->GestureTap(args);
785 }
786
787 void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
788 if (sender_)
789 sender_->GestureTapDown(args);
790 }
791
792 void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
793 if (sender_)
794 sender_->GestureShowPress(args);
795 }
796
797 void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
798 if (sender_)
799 sender_->GestureTapCancel(args);
800 }
801
802 void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
803 if (sender_)
804 sender_->GestureLongPress(args);
805 }
806
807 void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
808 if (sender_)
809 sender_->GestureLongTap(args);
810 }
811
812 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
813 if (sender_)
814 sender_->GestureTwoFingerTap(args);
815 }
816
817 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
818 if (sender_)
819 sender_->ContinuousMouseScrollBy(args);
820 }
821
822 void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
823 if (sender_)
824 sender_->MouseMoveTo(args);
825 }
826
827 void EventSenderBindings::MouseLeave() {
828 if (sender_)
829 sender_->MouseLeave();
830 }
831
832 void EventSenderBindings::TrackpadScrollBegin() {
833 if (sender_)
834 sender_->TrackpadScrollBegin();
835 }
836
837 void EventSenderBindings::TrackpadScroll(gin::Arguments* args) {
838 if (sender_)
839 sender_->TrackpadScroll(args);
840 }
841
842 void EventSenderBindings::TrackpadScrollEnd() {
843 if (sender_)
844 sender_->TrackpadScrollEnd();
845 }
846
847 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
848 if (sender_)
849 sender_->MouseScrollBy(args);
850 }
851
852 void EventSenderBindings::MouseMomentumBegin() {
853 if (sender_)
854 sender_->MouseMomentumBegin();
855 }
856
857 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments* args) {
858 if (sender_)
859 sender_->MouseMomentumBegin2(args);
860 }
861
862 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
863 if (sender_)
864 sender_->MouseMomentumScrollBy(args);
865 }
866
867 void EventSenderBindings::MouseMomentumEnd() {
868 if (sender_)
869 sender_->MouseMomentumEnd();
870 }
871
872 void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
873 if (!sender_)
874 return;
875
876 int button_number = 0;
877 int modifiers = 0;
878 if (!args->PeekNext().IsEmpty()) {
879 args->GetNext(&button_number);
880 if (!args->PeekNext().IsEmpty())
881 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
882 }
883 sender_->ScheduleAsynchronousClick(button_number, modifiers);
884 }
885
886 void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
887 if (!sender_)
888 return;
889
890 std::string code_str;
891 int modifiers = 0;
892 int location = DOMKeyLocationStandard;
893 args->GetNext(&code_str);
894 if (!args->PeekNext().IsEmpty()) {
895 v8::Local<v8::Value> value;
896 args->GetNext(&value);
897 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
898 if (!args->PeekNext().IsEmpty())
899 args->GetNext(&location);
900 }
901 sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
902 static_cast<KeyLocationCode>(location));
903 }
904
905 void EventSenderBindings::MouseDown(gin::Arguments* args) {
906 if (!sender_)
907 return;
908
909 int button_number = 0;
910 int modifiers = 0;
911 if (!args->PeekNext().IsEmpty()) {
912 args->GetNext(&button_number);
913 if (!args->PeekNext().IsEmpty())
914 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
915 }
916 sender_->MouseDown(button_number, modifiers);
917 }
918
919 void EventSenderBindings::MouseUp(gin::Arguments* args) {
920 if (!sender_)
921 return;
922
923 int button_number = 0;
924 int modifiers = 0;
925 if (!args->PeekNext().IsEmpty()) {
926 args->GetNext(&button_number);
927 if (!args->PeekNext().IsEmpty())
928 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
929 }
930 sender_->MouseUp(button_number, modifiers);
931 }
932
933 void EventSenderBindings::KeyDown(gin::Arguments* args) {
934 if (!sender_)
935 return;
936
937 std::string code_str;
938 int modifiers = 0;
939 int location = DOMKeyLocationStandard;
940 args->GetNext(&code_str);
941 if (!args->PeekNext().IsEmpty()) {
942 v8::Local<v8::Value> value;
943 args->GetNext(&value);
944 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
945 if (!args->PeekNext().IsEmpty())
946 args->GetNext(&location);
947 }
948 sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
949 }
950
951 bool EventSenderBindings::ForceLayoutOnEvents() const {
952 if (sender_)
953 return sender_->force_layout_on_events();
954 return false;
955 }
956
957 void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
958 if (sender_)
959 sender_->set_force_layout_on_events(force);
960 }
961
962 bool EventSenderBindings::IsDragMode() const {
963 if (sender_)
964 return sender_->is_drag_mode();
965 return true;
966 }
967
968 void EventSenderBindings::SetIsDragMode(bool drag_mode) {
969 if (sender_)
970 sender_->set_is_drag_mode(drag_mode);
971 }
972
973 #if defined(OS_WIN)
974 int EventSenderBindings::WmKeyDown() const {
975 if (sender_)
976 return sender_->wm_key_down();
977 return 0;
978 }
979
980 void EventSenderBindings::SetWmKeyDown(int key_down) {
981 if (sender_)
982 sender_->set_wm_key_down(key_down);
983 }
984
985 int EventSenderBindings::WmKeyUp() const {
986 if (sender_)
987 return sender_->wm_key_up();
988 return 0;
989 }
990
991 void EventSenderBindings::SetWmKeyUp(int key_up) {
992 if (sender_)
993 sender_->set_wm_key_up(key_up);
994 }
995
996 int EventSenderBindings::WmChar() const {
997 if (sender_)
998 return sender_->wm_char();
999 return 0;
1000 }
1001
1002 void EventSenderBindings::SetWmChar(int wm_char) {
1003 if (sender_)
1004 sender_->set_wm_char(wm_char);
1005 }
1006
1007 int EventSenderBindings::WmDeadChar() const {
1008 if (sender_)
1009 return sender_->wm_dead_char();
1010 return 0;
1011 }
1012
1013 void EventSenderBindings::SetWmDeadChar(int dead_char) {
1014 if (sender_)
1015 sender_->set_wm_dead_char(dead_char);
1016 }
1017
1018 int EventSenderBindings::WmSysKeyDown() const {
1019 if (sender_)
1020 return sender_->wm_sys_key_down();
1021 return 0;
1022 }
1023
1024 void EventSenderBindings::SetWmSysKeyDown(int key_down) {
1025 if (sender_)
1026 sender_->set_wm_sys_key_down(key_down);
1027 }
1028
1029 int EventSenderBindings::WmSysKeyUp() const {
1030 if (sender_)
1031 return sender_->wm_sys_key_up();
1032 return 0;
1033 }
1034
1035 void EventSenderBindings::SetWmSysKeyUp(int key_up) {
1036 if (sender_)
1037 sender_->set_wm_sys_key_up(key_up);
1038 }
1039
1040 int EventSenderBindings::WmSysChar() const {
1041 if (sender_)
1042 return sender_->wm_sys_char();
1043 return 0;
1044 }
1045
1046 void EventSenderBindings::SetWmSysChar(int sys_char) {
1047 if (sender_)
1048 sender_->set_wm_sys_char(sys_char);
1049 }
1050
1051 int EventSenderBindings::WmSysDeadChar() const {
1052 if (sender_)
1053 return sender_->wm_sys_dead_char();
1054 return 0;
1055 }
1056
1057 void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
1058 if (sender_)
1059 sender_->set_wm_sys_dead_char(sys_dead_char);
1060 }
1061 #endif
1062
1063 // EventSender -----------------------------------------------------------------
1064
1065 WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
1066 int EventSender::modifiers_ = 0;
1067
1068 WebPoint EventSender::last_mouse_pos_;
1069
1070 WebMouseEvent::Button EventSender::last_button_type_ =
1071 WebMouseEvent::ButtonNone;
1072
1073 EventSender::SavedEvent::SavedEvent()
1074 : type(TYPE_UNSPECIFIED),
1075 button_type(WebMouseEvent::ButtonNone),
1076 milliseconds(0),
1077 modifiers(0) {}
1078
1079 EventSender::EventSender(TestInterfaces* interfaces)
1080 : interfaces_(interfaces),
1081 delegate_(NULL),
1082 view_(NULL),
1083 force_layout_on_events_(false),
1084 is_drag_mode_(true),
1085 touch_modifiers_(0),
1086 touch_cancelable_(true),
1087 replaying_saved_events_(false),
1088 current_drag_effects_allowed_(blink::WebDragOperationNone),
1089 last_click_time_sec_(0),
1090 current_drag_effect_(blink::WebDragOperationNone),
1091 time_offset_ms_(0),
1092 click_count_(0),
1093 #if defined(OS_WIN)
1094 wm_key_down_(0),
1095 wm_key_up_(0),
1096 wm_char_(0),
1097 wm_dead_char_(0),
1098 wm_sys_key_down_(0),
1099 wm_sys_key_up_(0),
1100 wm_sys_char_(0),
1101 wm_sys_dead_char_(0),
1102 #endif
1103 weak_factory_(this) {}
1104
1105 EventSender::~EventSender() {}
1106
1107 void EventSender::Reset() {
1108 DCHECK(current_drag_data_.isNull());
1109 current_drag_data_.reset();
1110 current_drag_effect_ = blink::WebDragOperationNone;
1111 current_drag_effects_allowed_ = blink::WebDragOperationNone;
1112 if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
1113 view_->mouseCaptureLost();
1114 pressed_button_ = WebMouseEvent::ButtonNone;
1115 is_drag_mode_ = true;
1116 force_layout_on_events_ = true;
1117
1118 #if defined(OS_WIN)
1119 wm_key_down_ = WM_KEYDOWN;
1120 wm_key_up_ = WM_KEYUP;
1121 wm_char_ = WM_CHAR;
1122 wm_dead_char_ = WM_DEADCHAR;
1123 wm_sys_key_down_ = WM_SYSKEYDOWN;
1124 wm_sys_key_up_ = WM_SYSKEYUP;
1125 wm_sys_char_ = WM_SYSCHAR;
1126 wm_sys_dead_char_ = WM_SYSDEADCHAR;
1127 #endif
1128
1129 last_mouse_pos_ = WebPoint(0, 0);
1130 last_click_time_sec_ = 0;
1131 last_click_pos_ = WebPoint(0, 0);
1132 last_button_type_ = WebMouseEvent::ButtonNone;
1133 touch_points_.clear();
1134 last_context_menu_data_.reset();
1135 task_list_.RevokeAll();
1136 current_gesture_location_ = WebPoint(0, 0);
1137 mouse_event_queue_.clear();
1138
1139 time_offset_ms_ = 0;
1140 click_count_ = 0;
1141
1142 touch_modifiers_ = 0;
1143 touch_cancelable_ = true;
1144 touch_points_.clear();
1145 }
1146
1147 void EventSender::Install(WebFrame* frame) {
1148 EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
1149 }
1150
1151 void EventSender::SetDelegate(WebTestDelegate* delegate) {
1152 delegate_ = delegate;
1153 }
1154
1155 void EventSender::SetWebView(WebView* view) {
1156 view_ = view;
1157 }
1158
1159 void EventSender::SetContextMenuData(const WebContextMenuData& data) {
1160 last_context_menu_data_.reset(new WebContextMenuData(data));
1161 }
1162
1163 void EventSender::DoDragDrop(const WebDragData& drag_data,
1164 WebDragOperationsMask mask) {
1165 WebMouseEvent event;
1166 InitMouseEvent(WebInputEvent::MouseDown,
1167 pressed_button_,
1168 last_mouse_pos_,
1169 GetCurrentEventTimeSec(),
1170 click_count_,
1171 modifiers_,
1172 &event);
1173 WebPoint client_point(event.x, event.y);
1174 WebPoint screen_point(event.globalX, event.globalY);
1175 current_drag_data_ = drag_data;
1176 current_drag_effects_allowed_ = mask;
1177 current_drag_effect_ = view_->dragTargetDragEnter(
1178 drag_data,
1179 client_point,
1180 screen_point,
1181 current_drag_effects_allowed_,
1182 modifiers_);
1183
1184 // Finish processing events.
1185 ReplaySavedEvents();
1186 }
1187
1188 void EventSender::MouseDown(int button_number, int modifiers) {
1189 if (force_layout_on_events_)
1190 view_->layout();
1191
1192 DCHECK_NE(-1, button_number);
1193
1194 WebMouseEvent::Button button_type =
1195 GetButtonTypeFromButtonNumber(button_number);
1196
1197 UpdateClickCountForButton(button_type);
1198
1199 pressed_button_ = button_type;
1200 modifiers_ = modifiers;
1201
1202 WebMouseEvent event;
1203 InitMouseEvent(WebInputEvent::MouseDown,
1204 button_type,
1205 last_mouse_pos_,
1206 GetCurrentEventTimeSec(),
1207 click_count_,
1208 modifiers,
1209 &event);
1210 HandleInputEventOnViewOrPopup(event);
1211 }
1212
1213 void EventSender::MouseUp(int button_number, int modifiers) {
1214 if (force_layout_on_events_)
1215 view_->layout();
1216
1217 DCHECK_NE(-1, button_number);
1218
1219 WebMouseEvent::Button button_type =
1220 GetButtonTypeFromButtonNumber(button_number);
1221
1222 if (is_drag_mode_ && !replaying_saved_events_) {
1223 SavedEvent saved_event;
1224 saved_event.type = SavedEvent::TYPE_MOUSE_UP;
1225 saved_event.button_type = button_type;
1226 saved_event.modifiers = modifiers;
1227 mouse_event_queue_.push_back(saved_event);
1228 ReplaySavedEvents();
1229 } else {
1230 WebMouseEvent event;
1231 InitMouseEvent(WebInputEvent::MouseUp,
1232 button_type,
1233 last_mouse_pos_,
1234 GetCurrentEventTimeSec(),
1235 click_count_,
1236 modifiers,
1237 &event);
1238 DoMouseUp(event);
1239 }
1240 }
1241
1242 void EventSender::KeyDown(const std::string& code_str,
1243 int modifiers,
1244 KeyLocationCode location) {
1245 // FIXME: I'm not exactly sure how we should convert the string to a key
1246 // event. This seems to work in the cases I tested.
1247 // FIXME: Should we also generate a KEY_UP?
1248
1249 bool generate_char = false;
1250
1251 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
1252 // Windows uses \r for "Enter".
1253 int code = 0;
1254 int text = 0;
1255 bool needs_shift_key_modifier = false;
1256 std::string domString;
1257
1258 if ("\n" == code_str) {
1259 generate_char = true;
1260 text = code = ui::VKEY_RETURN;
1261 domString.assign("Enter");
1262 } else if ("rightArrow" == code_str) {
1263 code = ui::VKEY_RIGHT;
1264 domString.assign("ArrowRight");
1265 } else if ("downArrow" == code_str) {
1266 code = ui::VKEY_DOWN;
1267 domString.assign("ArrowDown");
1268 } else if ("leftArrow" == code_str) {
1269 code = ui::VKEY_LEFT;
1270 domString.assign("ArrowLeft");
1271 } else if ("upArrow" == code_str) {
1272 code = ui::VKEY_UP;
1273 domString.assign("ArrowUp");
1274 } else if ("insert" == code_str) {
1275 code = ui::VKEY_INSERT;
1276 domString.assign("Insert");
1277 } else if ("delete" == code_str) {
1278 code = ui::VKEY_DELETE;
1279 domString.assign("Delete");
1280 } else if ("pageUp" == code_str) {
1281 code = ui::VKEY_PRIOR;
1282 domString.assign("PageUp");
1283 } else if ("pageDown" == code_str) {
1284 code = ui::VKEY_NEXT;
1285 domString.assign("PageDown");
1286 } else if ("home" == code_str) {
1287 code = ui::VKEY_HOME;
1288 domString.assign("Home");
1289 } else if ("end" == code_str) {
1290 code = ui::VKEY_END;
1291 domString.assign("End");
1292 } else if ("printScreen" == code_str) {
1293 code = ui::VKEY_SNAPSHOT;
1294 domString.assign("PrintScreen");
1295 } else if ("menu" == code_str) {
1296 code = ui::VKEY_APPS;
1297 domString.assign("ContextMenu");
1298 } else if ("leftControl" == code_str) {
1299 code = ui::VKEY_LCONTROL;
1300 domString.assign("ControlLeft");
1301 } else if ("rightControl" == code_str) {
1302 code = ui::VKEY_RCONTROL;
1303 domString.assign("ControlRight");
1304 } else if ("leftShift" == code_str) {
1305 code = ui::VKEY_LSHIFT;
1306 domString.assign("ShiftLeft");
1307 } else if ("rightShift" == code_str) {
1308 code = ui::VKEY_RSHIFT;
1309 domString.assign("ShiftRight");
1310 } else if ("leftAlt" == code_str) {
1311 code = ui::VKEY_LMENU;
1312 domString.assign("AltLeft");
1313 } else if ("rightAlt" == code_str) {
1314 code = ui::VKEY_RMENU;
1315 domString.assign("AltRight");
1316 } else if ("numLock" == code_str) {
1317 code = ui::VKEY_NUMLOCK;
1318 domString.assign("NumLock");
1319 } else if ("backspace" == code_str) {
1320 code = ui::VKEY_BACK;
1321 domString.assign("Backspace");
1322 } else if ("escape" == code_str) {
1323 code = ui::VKEY_ESCAPE;
1324 domString.assign("Escape");
1325 } else {
1326 // Compare the input string with the function-key names defined by the
1327 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
1328 // name, set its key code.
1329 for (int i = 1; i <= 24; ++i) {
1330 std::string function_key_name = base::StringPrintf("F%d", i);
1331 if (function_key_name == code_str) {
1332 code = ui::VKEY_F1 + (i - 1);
1333 domString = function_key_name;
1334 break;
1335 }
1336 }
1337 if (!code) {
1338 WebString web_code_str =
1339 WebString::fromUTF8(code_str.data(), code_str.size());
1340 if (web_code_str.length() != 1u) {
1341 v8::Isolate* isolate = blink::mainThreadIsolate();
1342 isolate->ThrowException(v8::Exception::TypeError(
1343 gin::StringToV8(isolate, "Invalid web code.")));
1344 return;
1345 }
1346 text = code = web_code_str.at(0);
1347 needs_shift_key_modifier = NeedsShiftModifier(code);
1348 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
1349 code -= 'a' - 'A';
1350 if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z')) {
1351 domString.assign("Key");
1352 domString.push_back(base::ToUpperASCII(code));
1353 } else if (code >= '0' && code <= '9') {
1354 domString.assign("Digit");
1355 domString.push_back(code);
1356 } else if (code == ' ') {
1357 domString.assign("Space");
1358 } else if (code == 9) {
1359 domString.assign("Tab");
1360 }
1361 generate_char = true;
1362 }
1363
1364 if ("(" == code_str) {
1365 code = '9';
1366 needs_shift_key_modifier = true;
1367 }
1368 }
1369
1370 // For one generated keyboard event, we need to generate a keyDown/keyUp
1371 // pair;
1372 // On Windows, we might also need to generate a char event to mimic the
1373 // Windows event flow; on other platforms we create a merged event and test
1374 // the event flow that that platform provides.
1375 WebKeyboardEvent event_down;
1376 event_down.type = WebInputEvent::RawKeyDown;
1377 event_down.modifiers = modifiers;
1378 event_down.windowsKeyCode = code;
1379 event_down.domCode = static_cast<int>(
1380 ui::KeycodeConverter::CodeStringToDomCode(domString.c_str()));
1381
1382 if (generate_char) {
1383 event_down.text[0] = text;
1384 event_down.unmodifiedText[0] = text;
1385 }
1386
1387 event_down.setKeyIdentifierFromWindowsKeyCode();
1388
1389 if (event_down.modifiers != 0)
1390 event_down.isSystemKey = IsSystemKeyEvent(event_down);
1391
1392 if (needs_shift_key_modifier)
1393 event_down.modifiers |= WebInputEvent::ShiftKey;
1394
1395 // See if KeyLocation argument is given.
1396 if (location == DOMKeyLocationNumpad)
1397 event_down.modifiers |= WebInputEvent::IsKeyPad;
1398
1399 WebKeyboardEvent event_up;
1400 event_up = event_down;
1401 event_up.type = WebInputEvent::KeyUp;
1402 // EventSender.m forces a layout here, with at least one
1403 // test (fast/forms/focus-control-to-page.html) relying on this.
1404 if (force_layout_on_events_)
1405 view_->layout();
1406
1407 // In the browser, if a keyboard event corresponds to an editor command,
1408 // the command will be dispatched to the renderer just before dispatching
1409 // the keyboard event, and then it will be executed in the
1410 // RenderView::handleCurrentKeyboardEvent() method.
1411 // We just simulate the same behavior here.
1412 std::string edit_command;
1413 if (GetEditCommand(event_down, &edit_command))
1414 delegate_->SetEditCommand(edit_command, "");
1415
1416 HandleInputEventOnViewOrPopup(event_down);
1417
1418 if (code == ui::VKEY_ESCAPE && !current_drag_data_.isNull()) {
1419 WebMouseEvent event;
1420 InitMouseEvent(WebInputEvent::MouseDown,
1421 pressed_button_,
1422 last_mouse_pos_,
1423 GetCurrentEventTimeSec(),
1424 click_count_,
1425 0,
1426 &event);
1427 FinishDragAndDrop(event, blink::WebDragOperationNone);
1428 }
1429
1430 delegate_->ClearEditCommand();
1431
1432 if (generate_char) {
1433 WebKeyboardEvent event_char = event_up;
1434 event_char.type = WebInputEvent::Char;
1435 // keyIdentifier is an empty string, unless the Enter key was pressed.
1436 // This behavior is not standard (keyIdentifier itself is not even a
1437 // standard any more), but it matches the actual behavior in Blink.
1438 if (code != ui::VKEY_RETURN)
1439 event_char.keyIdentifier[0] = '\0';
1440 HandleInputEventOnViewOrPopup(event_char);
1441 }
1442
1443 HandleInputEventOnViewOrPopup(event_up);
1444 }
1445
1446 void EventSender::EnableDOMUIEventLogging() {}
1447
1448 void EventSender::FireKeyboardEventsToElement() {}
1449
1450 void EventSender::ClearKillRing() {}
1451
1452 std::vector<std::string> EventSender::ContextClick() {
1453 if (force_layout_on_events_) {
1454 view_->layout();
1455 }
1456
1457 UpdateClickCountForButton(WebMouseEvent::ButtonRight);
1458
1459 // Clears last context menu data because we need to know if the context menu
1460 // be requested after following mouse events.
1461 last_context_menu_data_.reset();
1462
1463 // Generate right mouse down and up.
1464 WebMouseEvent event;
1465 // This is a hack to work around only allowing a single pressed button since
1466 // we want to test the case where both the left and right mouse buttons are
1467 // pressed.
1468 if (pressed_button_ == WebMouseEvent::ButtonNone) {
1469 pressed_button_ = WebMouseEvent::ButtonRight;
1470 }
1471 InitMouseEvent(WebInputEvent::MouseDown,
1472 WebMouseEvent::ButtonRight,
1473 last_mouse_pos_,
1474 GetCurrentEventTimeSec(),
1475 click_count_,
1476 0,
1477 &event);
1478 HandleInputEventOnViewOrPopup(event);
1479
1480 #if defined(OS_WIN)
1481 InitMouseEvent(WebInputEvent::MouseUp,
1482 WebMouseEvent::ButtonRight,
1483 last_mouse_pos_,
1484 GetCurrentEventTimeSec(),
1485 click_count_,
1486 0,
1487 &event);
1488 HandleInputEventOnViewOrPopup(event);
1489
1490 pressed_button_= WebMouseEvent::ButtonNone;
1491 #endif
1492
1493 std::vector<std::string> menu_items = MakeMenuItemStringsFor(last_context_menu _data_.get(), delegate_);
1494 last_context_menu_data_.reset();
1495 return menu_items;
1496 }
1497
1498 void EventSender::TextZoomIn() {
1499 view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
1500 }
1501
1502 void EventSender::TextZoomOut() {
1503 view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
1504 }
1505
1506 void EventSender::ZoomPageIn() {
1507 const std::vector<WebTestProxyBase*>& window_list =
1508 interfaces_->GetWindowList();
1509
1510 for (size_t i = 0; i < window_list.size(); ++i) {
1511 window_list.at(i)->GetWebView()->setZoomLevel(
1512 window_list.at(i)->GetWebView()->zoomLevel() + 1);
1513 }
1514 }
1515
1516 void EventSender::ZoomPageOut() {
1517 const std::vector<WebTestProxyBase*>& window_list =
1518 interfaces_->GetWindowList();
1519
1520 for (size_t i = 0; i < window_list.size(); ++i) {
1521 window_list.at(i)->GetWebView()->setZoomLevel(
1522 window_list.at(i)->GetWebView()->zoomLevel() - 1);
1523 }
1524 }
1525
1526 void EventSender::SetPageZoomFactor(double zoom_factor) {
1527 const std::vector<WebTestProxyBase*>& window_list =
1528 interfaces_->GetWindowList();
1529
1530 for (size_t i = 0; i < window_list.size(); ++i) {
1531 window_list.at(i)->GetWebView()->setZoomLevel(
1532 std::log(zoom_factor) / std::log(1.2));
1533 }
1534 }
1535
1536 void EventSender::ClearTouchPoints() {
1537 touch_points_.clear();
1538 }
1539
1540 void EventSender::ThrowTouchPointError() {
1541 v8::Isolate* isolate = blink::mainThreadIsolate();
1542 isolate->ThrowException(v8::Exception::TypeError(
1543 gin::StringToV8(isolate, "Invalid touch point.")));
1544 }
1545
1546 void EventSender::ReleaseTouchPoint(unsigned index) {
1547 if (index >= touch_points_.size()) {
1548 ThrowTouchPointError();
1549 return;
1550 }
1551
1552 WebTouchPoint* touch_point = &touch_points_[index];
1553 touch_point->state = WebTouchPoint::StateReleased;
1554 }
1555
1556 void EventSender::UpdateTouchPoint(unsigned index, float x, float y) {
1557 if (index >= touch_points_.size()) {
1558 ThrowTouchPointError();
1559 return;
1560 }
1561
1562 WebTouchPoint* touch_point = &touch_points_[index];
1563 touch_point->state = WebTouchPoint::StateMoved;
1564 touch_point->position = WebFloatPoint(x, y);
1565 touch_point->screenPosition = touch_point->position;
1566 }
1567
1568 void EventSender::CancelTouchPoint(unsigned index) {
1569 if (index >= touch_points_.size()) {
1570 ThrowTouchPointError();
1571 return;
1572 }
1573
1574 WebTouchPoint* touch_point = &touch_points_[index];
1575 touch_point->state = WebTouchPoint::StateCancelled;
1576 }
1577
1578 void EventSender::SetTouchModifier(const std::string& key_name,
1579 bool set_mask) {
1580 int mask = 0;
1581 if (key_name == "shift")
1582 mask = WebInputEvent::ShiftKey;
1583 else if (key_name == "alt")
1584 mask = WebInputEvent::AltKey;
1585 else if (key_name == "ctrl")
1586 mask = WebInputEvent::ControlKey;
1587 else if (key_name == "meta")
1588 mask = WebInputEvent::MetaKey;
1589
1590 if (set_mask)
1591 touch_modifiers_ |= mask;
1592 else
1593 touch_modifiers_ &= ~mask;
1594 }
1595
1596 void EventSender::SetTouchCancelable(bool cancelable) {
1597 touch_cancelable_ = cancelable;
1598 }
1599
1600 void EventSender::DumpFilenameBeingDragged() {
1601 if (current_drag_data_.isNull())
1602 return;
1603
1604 WebString filename;
1605 WebVector<WebDragData::Item> items = current_drag_data_.items();
1606 for (size_t i = 0; i < items.size(); ++i) {
1607 if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
1608 filename = items[i].title;
1609 break;
1610 }
1611 }
1612 delegate_->PrintMessage(std::string("Filename being dragged: ") +
1613 filename.utf8().data() + "\n");
1614 }
1615
1616 void EventSender::GestureFlingCancel() {
1617 WebGestureEvent event;
1618 event.type = WebInputEvent::GestureFlingCancel;
1619 event.timeStampSeconds = GetCurrentEventTimeSec();
1620
1621 if (force_layout_on_events_)
1622 view_->layout();
1623
1624 HandleInputEventOnViewOrPopup(event);
1625 }
1626
1627 void EventSender::GestureFlingStart(float x,
1628 float y,
1629 float velocity_x,
1630 float velocity_y,
1631 gin::Arguments* args) {
1632 WebGestureEvent event;
1633 event.type = WebInputEvent::GestureFlingStart;
1634
1635 std::string device_string;
1636 if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsString())
1637 args->GetNext(&device_string);
1638
1639 if (device_string == kSourceDeviceStringTouchpad) {
1640 event.sourceDevice = blink::WebGestureDeviceTouchpad;
1641 } else if (device_string == kSourceDeviceStringTouchscreen) {
1642 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
1643 } else {
1644 args->ThrowError();
1645 return;
1646 }
1647
1648 event.x = x;
1649 event.y = y;
1650 event.globalX = event.x;
1651 event.globalY = event.y;
1652
1653 event.data.flingStart.velocityX = velocity_x;
1654 event.data.flingStart.velocityY = velocity_y;
1655 event.timeStampSeconds = GetCurrentEventTimeSec();
1656
1657 if (force_layout_on_events_)
1658 view_->layout();
1659
1660 HandleInputEventOnViewOrPopup(event);
1661 }
1662
1663 void EventSender::GestureScrollFirstPoint(int x, int y) {
1664 current_gesture_location_ = WebPoint(x, y);
1665 }
1666
1667 void EventSender::TouchStart() {
1668 SendCurrentTouchEvent(WebInputEvent::TouchStart);
1669 }
1670
1671 void EventSender::TouchMove() {
1672 SendCurrentTouchEvent(WebInputEvent::TouchMove);
1673 }
1674
1675 void EventSender::TouchCancel() {
1676 SendCurrentTouchEvent(WebInputEvent::TouchCancel);
1677 }
1678
1679 void EventSender::TouchEnd() {
1680 SendCurrentTouchEvent(WebInputEvent::TouchEnd);
1681 }
1682
1683 void EventSender::LeapForward(int milliseconds) {
1684 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1685 !replaying_saved_events_) {
1686 SavedEvent saved_event;
1687 saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
1688 saved_event.milliseconds = milliseconds;
1689 mouse_event_queue_.push_back(saved_event);
1690 } else {
1691 DoLeapForward(milliseconds);
1692 }
1693 }
1694
1695 void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
1696 current_drag_data_.initialize();
1697 WebVector<WebString> absolute_filenames(files.size());
1698 for (size_t i = 0; i < files.size(); ++i) {
1699 WebDragData::Item item;
1700 item.storageType = WebDragData::Item::StorageTypeFilename;
1701 item.filenameData = delegate_->GetAbsoluteWebStringFromUTF8Path(files[i]);
1702 current_drag_data_.addItem(item);
1703 absolute_filenames[i] = item.filenameData;
1704 }
1705 current_drag_data_.setFilesystemId(
1706 delegate_->RegisterIsolatedFileSystem(absolute_filenames));
1707 current_drag_effects_allowed_ = blink::WebDragOperationCopy;
1708
1709 // Provide a drag source.
1710 view_->dragTargetDragEnter(current_drag_data_,
1711 last_mouse_pos_,
1712 last_mouse_pos_,
1713 current_drag_effects_allowed_,
1714 0);
1715 // |is_drag_mode_| saves events and then replays them later. We don't
1716 // need/want that.
1717 is_drag_mode_ = false;
1718
1719 // Make the rest of eventSender think a drag is in progress.
1720 pressed_button_ = WebMouseEvent::ButtonLeft;
1721 }
1722
1723 void EventSender::AddTouchPoint(gin::Arguments* args) {
1724 double x;
1725 double y;
1726 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1727 args->ThrowError();
1728 return;
1729 }
1730
1731 WebTouchPoint touch_point;
1732 touch_point.state = WebTouchPoint::StatePressed;
1733 touch_point.position = WebFloatPoint(static_cast<float>(x),
1734 static_cast<float>(y));
1735 touch_point.screenPosition = touch_point.position;
1736
1737 if (!args->PeekNext().IsEmpty()) {
1738 double radius_x;
1739 if (!args->GetNext(&radius_x)) {
1740 args->ThrowError();
1741 return;
1742 }
1743
1744 double radius_y = radius_x;
1745 if (!args->PeekNext().IsEmpty()) {
1746 if (!args->GetNext(&radius_y)) {
1747 args->ThrowError();
1748 return;
1749 }
1750 }
1751
1752 touch_point.radiusX = static_cast<float>(radius_x);
1753 touch_point.radiusY = static_cast<float>(radius_y);
1754 }
1755
1756 int lowest_id = 0;
1757 for (size_t i = 0; i < touch_points_.size(); i++) {
1758 if (touch_points_[i].id == lowest_id)
1759 lowest_id++;
1760 }
1761 touch_point.id = lowest_id;
1762 touch_points_.push_back(touch_point);
1763 }
1764
1765 void EventSender::MouseDragBegin() {
1766 WebMouseWheelEvent event;
1767 InitMouseEvent(WebInputEvent::MouseWheel,
1768 WebMouseEvent::ButtonNone,
1769 last_mouse_pos_,
1770 GetCurrentEventTimeSec(),
1771 click_count_,
1772 0,
1773 &event);
1774 event.phase = WebMouseWheelEvent::PhaseBegan;
1775 event.hasPreciseScrollingDeltas = true;
1776 HandleInputEventOnViewOrPopup(event);
1777 }
1778
1779 void EventSender::MouseDragEnd() {
1780 WebMouseWheelEvent event;
1781 InitMouseEvent(WebInputEvent::MouseWheel,
1782 WebMouseEvent::ButtonNone,
1783 last_mouse_pos_,
1784 GetCurrentEventTimeSec(),
1785 click_count_,
1786 0,
1787 &event);
1788 event.phase = WebMouseWheelEvent::PhaseEnded;
1789 event.hasPreciseScrollingDeltas = true;
1790 HandleInputEventOnViewOrPopup(event);
1791 }
1792
1793 void EventSender::GestureScrollBegin(gin::Arguments* args) {
1794 GestureEvent(WebInputEvent::GestureScrollBegin, args);
1795 }
1796
1797 void EventSender::GestureScrollEnd(gin::Arguments* args) {
1798 GestureEvent(WebInputEvent::GestureScrollEnd, args);
1799 }
1800
1801 void EventSender::GestureScrollUpdate(gin::Arguments* args) {
1802 GestureEvent(WebInputEvent::GestureScrollUpdate, args);
1803 }
1804
1805 void EventSender::GesturePinchBegin(gin::Arguments* args) {
1806 GestureEvent(WebInputEvent::GesturePinchBegin, args);
1807 }
1808
1809 void EventSender::GesturePinchEnd(gin::Arguments* args) {
1810 GestureEvent(WebInputEvent::GesturePinchEnd, args);
1811 }
1812
1813 void EventSender::GesturePinchUpdate(gin::Arguments* args) {
1814 GestureEvent(WebInputEvent::GesturePinchUpdate, args);
1815 }
1816
1817 void EventSender::GestureTap(gin::Arguments* args) {
1818 GestureEvent(WebInputEvent::GestureTap, args);
1819 }
1820
1821 void EventSender::GestureTapDown(gin::Arguments* args) {
1822 GestureEvent(WebInputEvent::GestureTapDown, args);
1823 }
1824
1825 void EventSender::GestureShowPress(gin::Arguments* args) {
1826 GestureEvent(WebInputEvent::GestureShowPress, args);
1827 }
1828
1829 void EventSender::GestureTapCancel(gin::Arguments* args) {
1830 GestureEvent(WebInputEvent::GestureTapCancel, args);
1831 }
1832
1833 void EventSender::GestureLongPress(gin::Arguments* args) {
1834 GestureEvent(WebInputEvent::GestureLongPress, args);
1835 }
1836
1837 void EventSender::GestureLongTap(gin::Arguments* args) {
1838 GestureEvent(WebInputEvent::GestureLongTap, args);
1839 }
1840
1841 void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
1842 GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
1843 }
1844
1845 void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
1846 WebMouseWheelEvent event;
1847 InitMouseWheelEvent(args, true, &event);
1848 HandleInputEventOnViewOrPopup(event);
1849 }
1850
1851 void EventSender::MouseMoveTo(gin::Arguments* args) {
1852 if (force_layout_on_events_)
1853 view_->layout();
1854
1855 double x;
1856 double y;
1857 if (!args->GetNext(&x) || !args->GetNext(&y)) {
1858 args->ThrowError();
1859 return;
1860 }
1861 WebPoint mouse_pos(static_cast<int>(x), static_cast<int>(y));
1862
1863 int modifiers = 0;
1864 if (!args->PeekNext().IsEmpty())
1865 modifiers = GetKeyModifiersFromV8(args->isolate(), args->PeekNext());
1866
1867 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1868 !replaying_saved_events_) {
1869 SavedEvent saved_event;
1870 saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
1871 saved_event.pos = mouse_pos;
1872 saved_event.modifiers = modifiers;
1873 mouse_event_queue_.push_back(saved_event);
1874 } else {
1875 WebMouseEvent event;
1876 InitMouseEvent(WebInputEvent::MouseMove,
1877 pressed_button_,
1878 mouse_pos,
1879 GetCurrentEventTimeSec(),
1880 click_count_,
1881 modifiers,
1882 &event);
1883 DoMouseMove(event);
1884 }
1885 }
1886
1887 void EventSender::MouseLeave() {
1888 if (force_layout_on_events_)
1889 view_->layout();
1890
1891 WebMouseEvent event;
1892 InitMouseEvent(WebInputEvent::MouseLeave,
1893 WebMouseEvent::ButtonNone,
1894 last_mouse_pos_,
1895 GetCurrentEventTimeSec(),
1896 click_count_,
1897 0,
1898 &event);
1899 view_->handleInputEvent(event);
1900 }
1901
1902
1903 void EventSender::TrackpadScrollBegin() {
1904 WebMouseWheelEvent event;
1905 InitMouseEvent(WebInputEvent::MouseWheel,
1906 WebMouseEvent::ButtonNone,
1907 last_mouse_pos_,
1908 GetCurrentEventTimeSec(),
1909 click_count_,
1910 0,
1911 &event);
1912 event.phase = blink::WebMouseWheelEvent::PhaseBegan;
1913 event.hasPreciseScrollingDeltas = true;
1914 HandleInputEventOnViewOrPopup(event);
1915 }
1916
1917 void EventSender::TrackpadScroll(gin::Arguments* args) {
1918 WebMouseWheelEvent event;
1919 InitMouseWheelEvent(args, true, &event);
1920 event.phase = blink::WebMouseWheelEvent::PhaseChanged;
1921 event.hasPreciseScrollingDeltas = true;
1922 HandleInputEventOnViewOrPopup(event);
1923 }
1924
1925 void EventSender::TrackpadScrollEnd() {
1926 WebMouseWheelEvent event;
1927 InitMouseEvent(WebInputEvent::MouseWheel,
1928 WebMouseEvent::ButtonNone,
1929 last_mouse_pos_,
1930 GetCurrentEventTimeSec(),
1931 click_count_,
1932 0,
1933 &event);
1934 event.phase = WebMouseWheelEvent::PhaseEnded;
1935 event.hasPreciseScrollingDeltas = true;
1936 HandleInputEventOnViewOrPopup(event);
1937 }
1938
1939 void EventSender::MouseScrollBy(gin::Arguments* args) {
1940 WebMouseWheelEvent event;
1941 InitMouseWheelEvent(args, false, &event);
1942 HandleInputEventOnViewOrPopup(event);
1943 }
1944
1945 void EventSender::MouseMomentumBegin() {
1946 WebMouseWheelEvent event;
1947 InitMouseEvent(WebInputEvent::MouseWheel,
1948 WebMouseEvent::ButtonNone,
1949 last_mouse_pos_,
1950 GetCurrentEventTimeSec(),
1951 click_count_,
1952 0,
1953 &event);
1954 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1955 event.hasPreciseScrollingDeltas = true;
1956 HandleInputEventOnViewOrPopup(event);
1957 }
1958
1959 void EventSender::MouseMomentumBegin2(gin::Arguments* args) {
1960 WebMouseWheelEvent event;
1961 InitMouseWheelEvent(args, true, &event);
1962 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1963 event.hasPreciseScrollingDeltas = true;
1964 HandleInputEventOnViewOrPopup(event);
1965 }
1966
1967 void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
1968 WebMouseWheelEvent event;
1969 InitMouseWheelEvent(args, true, &event);
1970 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1971 event.hasPreciseScrollingDeltas = true;
1972 HandleInputEventOnViewOrPopup(event);
1973 }
1974
1975 void EventSender::MouseMomentumEnd() {
1976 WebMouseWheelEvent event;
1977 InitMouseEvent(WebInputEvent::MouseWheel,
1978 WebMouseEvent::ButtonNone,
1979 last_mouse_pos_,
1980 GetCurrentEventTimeSec(),
1981 click_count_,
1982 0,
1983 &event);
1984 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1985 event.hasPreciseScrollingDeltas = true;
1986 HandleInputEventOnViewOrPopup(event);
1987 }
1988
1989 void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
1990 delegate_->PostTask(new MouseDownTask(this, button_number, modifiers));
1991 delegate_->PostTask(new MouseUpTask(this, button_number, modifiers));
1992 }
1993
1994 void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
1995 int modifiers,
1996 KeyLocationCode location) {
1997 delegate_->PostTask(new KeyDownTask(this, code_str, modifiers, location));
1998 }
1999
2000 double EventSender::GetCurrentEventTimeSec() {
2001 return (delegate_->GetCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
2002 }
2003
2004 void EventSender::DoLeapForward(int milliseconds) {
2005 time_offset_ms_ += milliseconds;
2006 }
2007
2008 void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
2009 DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
2010 touch_points_.size());
2011 if (force_layout_on_events_)
2012 view_->layout();
2013
2014 WebTouchEvent touch_event;
2015 touch_event.type = type;
2016 touch_event.modifiers = touch_modifiers_;
2017 touch_event.cancelable = touch_cancelable_;
2018 touch_event.timeStampSeconds = GetCurrentEventTimeSec();
2019 touch_event.touchesLength = touch_points_.size();
2020 for (size_t i = 0; i < touch_points_.size(); ++i)
2021 touch_event.touches[i] = touch_points_[i];
2022 HandleInputEventOnViewOrPopup(touch_event);
2023
2024 for (size_t i = 0; i < touch_points_.size(); ++i) {
2025 WebTouchPoint* touch_point = &touch_points_[i];
2026 if (touch_point->state == WebTouchPoint::StateReleased) {
2027 touch_points_.erase(touch_points_.begin() + i);
2028 --i;
2029 } else
2030 touch_point->state = WebTouchPoint::StateStationary;
2031 }
2032 }
2033
2034 void EventSender::GestureEvent(WebInputEvent::Type type,
2035 gin::Arguments* args) {
2036 WebGestureEvent event;
2037 event.type = type;
2038
2039 // If the first argument is a string, it is to specify the device, otherwise
2040 // the device is assumed to be a touchscreen (since most tests were written
2041 // assuming this).
2042 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2043 if (args->PeekNext()->IsString()) {
2044 std::string device_string;
2045 if (!args->GetNext(&device_string)) {
2046 args->ThrowError();
2047 return;
2048 }
2049 if (device_string == kSourceDeviceStringTouchpad) {
2050 event.sourceDevice = blink::WebGestureDeviceTouchpad;
2051 } else if (device_string == kSourceDeviceStringTouchscreen) {
2052 event.sourceDevice = blink::WebGestureDeviceTouchscreen;
2053 } else {
2054 args->ThrowError();
2055 return;
2056 }
2057 }
2058
2059 double x;
2060 double y;
2061 if (!args->GetNext(&x) || !args->GetNext(&y)) {
2062 args->ThrowError();
2063 return;
2064 }
2065
2066 switch (type) {
2067 case WebInputEvent::GestureScrollUpdate:
2068 {
2069 bool preventPropagation = false;
2070 if (!args->PeekNext().IsEmpty()) {
2071 if (!args->GetNext(&preventPropagation)) {
2072 args->ThrowError();
2073 return;
2074 }
2075 }
2076
2077 event.data.scrollUpdate.deltaX = static_cast<float>(x);
2078 event.data.scrollUpdate.deltaY = static_cast<float>(y);
2079 event.data.scrollUpdate.preventPropagation = preventPropagation;
2080 event.x = current_gesture_location_.x;
2081 event.y = current_gesture_location_.y;
2082 current_gesture_location_.x =
2083 current_gesture_location_.x + event.data.scrollUpdate.deltaX;
2084 current_gesture_location_.y =
2085 current_gesture_location_.y + event.data.scrollUpdate.deltaY;
2086 break;
2087 }
2088 case WebInputEvent::GestureScrollBegin:
2089 current_gesture_location_ = WebPoint(x, y);
2090 event.x = current_gesture_location_.x;
2091 event.y = current_gesture_location_.y;
2092 break;
2093 case WebInputEvent::GestureScrollEnd:
2094 case WebInputEvent::GestureFlingStart:
2095 event.x = current_gesture_location_.x;
2096 event.y = current_gesture_location_.y;
2097 break;
2098 case WebInputEvent::GesturePinchBegin:
2099 case WebInputEvent::GesturePinchEnd:
2100 current_gesture_location_ = WebPoint(x, y);
2101 event.x = current_gesture_location_.x;
2102 event.y = current_gesture_location_.y;
2103 break;
2104 case WebInputEvent::GesturePinchUpdate:
2105 {
2106 float scale = 1;
2107 if (!args->PeekNext().IsEmpty()) {
2108 if (!args->GetNext(&scale)) {
2109 args->ThrowError();
2110 return;
2111 }
2112 }
2113 event.data.pinchUpdate.scale = scale;
2114 current_gesture_location_ = WebPoint(x, y);
2115 event.x = current_gesture_location_.x;
2116 event.y = current_gesture_location_.y;
2117 break;
2118 }
2119 case WebInputEvent::GestureTap:
2120 {
2121 float tap_count = 1;
2122 float width = 30;
2123 float height = 30;
2124 if (!args->PeekNext().IsEmpty()) {
2125 if (!args->GetNext(&tap_count)) {
2126 args->ThrowError();
2127 return;
2128 }
2129 }
2130 if (!args->PeekNext().IsEmpty()) {
2131 if (!args->GetNext(&width)) {
2132 args->ThrowError();
2133 return;
2134 }
2135 }
2136 if (!args->PeekNext().IsEmpty()) {
2137 if (!args->GetNext(&height)) {
2138 args->ThrowError();
2139 return;
2140 }
2141 }
2142 event.data.tap.tapCount = tap_count;
2143 event.data.tap.width = width;
2144 event.data.tap.height = height;
2145 event.x = x;
2146 event.y = y;
2147 break;
2148 }
2149 case WebInputEvent::GestureTapUnconfirmed:
2150 if (!args->PeekNext().IsEmpty()) {
2151 float tap_count;
2152 if (!args->GetNext(&tap_count)) {
2153 args->ThrowError();
2154 return;
2155 }
2156 event.data.tap.tapCount = tap_count;
2157 } else {
2158 event.data.tap.tapCount = 1;
2159 }
2160 event.x = x;
2161 event.y = y;
2162 break;
2163 case WebInputEvent::GestureTapDown:
2164 {
2165 float width = 30;
2166 float height = 30;
2167 if (!args->PeekNext().IsEmpty()) {
2168 if (!args->GetNext(&width)) {
2169 args->ThrowError();
2170 return;
2171 }
2172 }
2173 if (!args->PeekNext().IsEmpty()) {
2174 if (!args->GetNext(&height)) {
2175 args->ThrowError();
2176 return;
2177 }
2178 }
2179 event.x = x;
2180 event.y = y;
2181 event.data.tapDown.width = width;
2182 event.data.tapDown.height = height;
2183 break;
2184 }
2185 case WebInputEvent::GestureShowPress:
2186 {
2187 float width = 30;
2188 float height = 30;
2189 if (!args->PeekNext().IsEmpty()) {
2190 if (!args->GetNext(&width)) {
2191 args->ThrowError();
2192 return;
2193 }
2194 if (!args->PeekNext().IsEmpty()) {
2195 if (!args->GetNext(&height)) {
2196 args->ThrowError();
2197 return;
2198 }
2199 }
2200 }
2201 event.x = x;
2202 event.y = y;
2203 event.data.showPress.width = width;
2204 event.data.showPress.height = height;
2205 break;
2206 }
2207 case WebInputEvent::GestureTapCancel:
2208 event.x = x;
2209 event.y = y;
2210 break;
2211 case WebInputEvent::GestureLongPress:
2212 event.x = x;
2213 event.y = y;
2214 if (!args->PeekNext().IsEmpty()) {
2215 float width;
2216 if (!args->GetNext(&width)) {
2217 args->ThrowError();
2218 return;
2219 }
2220 event.data.longPress.width = width;
2221 if (!args->PeekNext().IsEmpty()) {
2222 float height;
2223 if (!args->GetNext(&height)) {
2224 args->ThrowError();
2225 return;
2226 }
2227 event.data.longPress.height = height;
2228 }
2229 }
2230 break;
2231 case WebInputEvent::GestureLongTap:
2232 event.x = x;
2233 event.y = y;
2234 if (!args->PeekNext().IsEmpty()) {
2235 float width;
2236 if (!args->GetNext(&width)) {
2237 args->ThrowError();
2238 return;
2239 }
2240 event.data.longPress.width = width;
2241 if (!args->PeekNext().IsEmpty()) {
2242 float height;
2243 if (!args->GetNext(&height)) {
2244 args->ThrowError();
2245 return;
2246 }
2247 event.data.longPress.height = height;
2248 }
2249 }
2250 break;
2251 case WebInputEvent::GestureTwoFingerTap:
2252 event.x = x;
2253 event.y = y;
2254 if (!args->PeekNext().IsEmpty()) {
2255 float first_finger_width;
2256 if (!args->GetNext(&first_finger_width)) {
2257 args->ThrowError();
2258 return;
2259 }
2260 event.data.twoFingerTap.firstFingerWidth = first_finger_width;
2261 if (!args->PeekNext().IsEmpty()) {
2262 float first_finger_height;
2263 if (!args->GetNext(&first_finger_height)) {
2264 args->ThrowError();
2265 return;
2266 }
2267 event.data.twoFingerTap.firstFingerHeight = first_finger_height;
2268 }
2269 }
2270 break;
2271 default:
2272 NOTREACHED();
2273 }
2274
2275 event.globalX = event.x;
2276 event.globalY = event.y;
2277 event.timeStampSeconds = GetCurrentEventTimeSec();
2278
2279 if (force_layout_on_events_)
2280 view_->layout();
2281
2282 bool result = HandleInputEventOnViewOrPopup(event);
2283
2284 // Long press might start a drag drop session. Complete it if so.
2285 if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
2286 WebMouseEvent mouse_event;
2287 InitMouseEvent(WebInputEvent::MouseDown,
2288 pressed_button_,
2289 WebPoint(x, y),
2290 GetCurrentEventTimeSec(),
2291 click_count_,
2292 0,
2293 &mouse_event);
2294
2295 FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
2296 }
2297 args->Return(result);
2298 }
2299
2300 void EventSender::UpdateClickCountForButton(
2301 WebMouseEvent::Button button_type) {
2302 if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
2303 kMultipleClickTimeSec) &&
2304 (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
2305 (button_type == last_button_type_)) {
2306 ++click_count_;
2307 } else {
2308 click_count_ = 1;
2309 last_button_type_ = button_type;
2310 }
2311 }
2312
2313 void EventSender::InitMouseWheelEvent(gin::Arguments* args,
2314 bool continuous,
2315 WebMouseWheelEvent* event) {
2316 // Force a layout here just to make sure every position has been
2317 // determined before we send events (as well as all the other methods
2318 // that send an event do).
2319 if (force_layout_on_events_)
2320 view_->layout();
2321
2322 double horizontal;
2323 if (!args->GetNext(&horizontal)) {
2324 args->ThrowError();
2325 return;
2326 }
2327 double vertical;
2328 if (!args->GetNext(&vertical)) {
2329 args->ThrowError();
2330 return;
2331 }
2332
2333 bool paged = false;
2334 bool has_precise_scrolling_deltas = false;
2335 int modifiers = 0;
2336 bool can_scroll = true;
2337 if (!args->PeekNext().IsEmpty()) {
2338 args->GetNext(&paged);
2339 if (!args->PeekNext().IsEmpty()) {
2340 args->GetNext(&has_precise_scrolling_deltas);
2341 if (!args->PeekNext().IsEmpty()) {
2342 v8::Local<v8::Value> value;
2343 args->GetNext(&value);
2344 modifiers = GetKeyModifiersFromV8(args->isolate(), value);
2345 if (!args->PeekNext().IsEmpty())
2346 args->GetNext(&can_scroll);
2347 }
2348 }
2349 }
2350
2351 InitMouseEvent(WebInputEvent::MouseWheel,
2352 pressed_button_,
2353 last_mouse_pos_,
2354 GetCurrentEventTimeSec(),
2355 click_count_,
2356 modifiers,
2357 event);
2358 event->wheelTicksX = static_cast<float>(horizontal);
2359 event->wheelTicksY = static_cast<float>(vertical);
2360 event->deltaX = event->wheelTicksX;
2361 event->deltaY = event->wheelTicksY;
2362 event->scrollByPage = paged;
2363 event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
2364 event->canScroll = can_scroll;
2365 if (continuous) {
2366 event->wheelTicksX /= kScrollbarPixelsPerTick;
2367 event->wheelTicksY /= kScrollbarPixelsPerTick;
2368 } else {
2369 event->deltaX *= kScrollbarPixelsPerTick;
2370 event->deltaY *= kScrollbarPixelsPerTick;
2371 }
2372 }
2373
2374 void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
2375 blink::WebDragOperation drag_effect) {
2376 WebPoint client_point(e.x, e.y);
2377 WebPoint screen_point(e.globalX, e.globalY);
2378 current_drag_effect_ = drag_effect;
2379 if (current_drag_effect_) {
2380 // Specifically pass any keyboard modifiers to the drop method. This allows
2381 // tests to control the drop type (i.e. copy or move).
2382 view_->dragTargetDrop(client_point, screen_point, e.modifiers);
2383 } else {
2384 view_->dragTargetDragLeave();
2385 }
2386 view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
2387 view_->dragSourceSystemDragEnded();
2388
2389 current_drag_data_.reset();
2390 }
2391
2392 void EventSender::DoMouseUp(const WebMouseEvent& e) {
2393 HandleInputEventOnViewOrPopup(e);
2394
2395 pressed_button_ = WebMouseEvent::ButtonNone;
2396 last_click_time_sec_ = e.timeStampSeconds;
2397 last_click_pos_ = last_mouse_pos_;
2398
2399 // If we're in a drag operation, complete it.
2400 if (current_drag_data_.isNull())
2401 return;
2402
2403 WebPoint client_point(e.x, e.y);
2404 WebPoint screen_point(e.globalX, e.globalY);
2405 FinishDragAndDrop(
2406 e,
2407 view_->dragTargetDragOver(
2408 client_point,
2409 screen_point,
2410 current_drag_effects_allowed_,
2411 e.modifiers));
2412 }
2413
2414 void EventSender::DoMouseMove(const WebMouseEvent& e) {
2415 last_mouse_pos_ = WebPoint(e.x, e.y);
2416
2417 HandleInputEventOnViewOrPopup(e);
2418
2419 if (pressed_button_ == WebMouseEvent::ButtonNone ||
2420 current_drag_data_.isNull()) {
2421 return;
2422 }
2423
2424 WebPoint client_point(e.x, e.y);
2425 WebPoint screen_point(e.globalX, e.globalY);
2426 current_drag_effect_ = view_->dragTargetDragOver(
2427 client_point, screen_point, current_drag_effects_allowed_, e.modifiers);
2428 }
2429
2430 void EventSender::ReplaySavedEvents() {
2431 replaying_saved_events_ = true;
2432 while (!mouse_event_queue_.empty()) {
2433 SavedEvent e = mouse_event_queue_.front();
2434 mouse_event_queue_.pop_front();
2435
2436 switch (e.type) {
2437 case SavedEvent::TYPE_MOUSE_MOVE: {
2438 WebMouseEvent event;
2439 InitMouseEvent(WebInputEvent::MouseMove,
2440 pressed_button_,
2441 e.pos,
2442 GetCurrentEventTimeSec(),
2443 click_count_,
2444 e.modifiers,
2445 &event);
2446 DoMouseMove(event);
2447 break;
2448 }
2449 case SavedEvent::TYPE_LEAP_FORWARD:
2450 DoLeapForward(e.milliseconds);
2451 break;
2452 case SavedEvent::TYPE_MOUSE_UP: {
2453 WebMouseEvent event;
2454 InitMouseEvent(WebInputEvent::MouseUp,
2455 e.button_type,
2456 last_mouse_pos_,
2457 GetCurrentEventTimeSec(),
2458 click_count_,
2459 e.modifiers,
2460 &event);
2461 DoMouseUp(event);
2462 break;
2463 }
2464 default:
2465 NOTREACHED();
2466 }
2467 }
2468
2469 replaying_saved_events_ = false;
2470 }
2471
2472 bool EventSender::HandleInputEventOnViewOrPopup(const WebInputEvent& event) {
2473 if (WebPagePopup* popup = view_->pagePopup()) {
2474 if (!WebInputEvent::isKeyboardEventType(event.type))
2475 return popup->handleInputEvent(event);
2476 }
2477 return view_->handleInputEvent(event);
2478 }
2479
2480 } // namespace content
OLDNEW
« no previous file with comments | « content/shell/renderer/test_runner/event_sender.h ('k') | content/shell/renderer/test_runner/gamepad_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698