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

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

Powered by Google App Engine
This is Rietveld 408576698