1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/test_runner/event_sender.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/test_runner/mock_spell_check.h"
12 #include "components/test_runner/test_interfaces.h"
13 #include "components/test_runner/web_test_delegate.h"
14 #include "components/test_runner/web_test_proxy.h"
15 #include "gin/handle.h"
16 #include "gin/object_template_builder.h"
17 #include "gin/wrappable.h"
18 #include "third_party/WebKit/public/platform/WebString.h"
19 #include "third_party/WebKit/public/platform/WebVector.h"
20 #include "third_party/WebKit/public/web/WebContextMenuData.h"
21 #include "third_party/WebKit/public/web/WebFrame.h"
22 #include "third_party/WebKit/public/web/WebKit.h"
23 #include "third_party/WebKit/public/web/WebPagePopup.h"
24 #include "third_party/WebKit/public/web/WebView.h"
25 #include "ui/events/keycodes/dom/keycode_converter.h"
26 #include "ui/events/keycodes/keyboard_codes.h"
27 #include "v8/include/v8.h"
29 using blink::WebContextMenuData
;
30 using blink::WebDragData
;
31 using blink::WebDragOperationsMask
;
32 using blink::WebFloatPoint
;
33 using blink::WebFrame
;
34 using blink::WebGestureEvent
;
35 using blink::WebInputEvent
;
36 using blink::WebKeyboardEvent
;
37 using blink::WebMenuItemInfo
;
38 using blink::WebMouseEvent
;
39 using blink::WebMouseWheelEvent
;
40 using blink::WebPagePopup
;
41 using blink::WebPoint
;
42 using blink::WebString
;
43 using blink::WebTouchEvent
;
44 using blink::WebTouchPoint
;
45 using blink::WebVector
;
48 namespace test_runner
{
52 void InitMouseEvent(WebInputEvent::Type t
,
53 WebMouseEvent::Button b
,
61 e
->modifiers
= modifiers
;
66 e
->timeStampSeconds
= time_stamp
;
67 e
->clickCount
= click_count
;
70 int GetKeyModifier(const std::string
& modifier_name
) {
71 const char* characters
= modifier_name
.c_str();
72 if (!strcmp(characters
, "ctrlKey")
74 || !strcmp(characters
, "addSelectionKey")
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
;
84 } else if (!strcmp(characters
, "metaKey") ||
85 !strcmp(characters
, "addSelectionKey")) {
86 return WebInputEvent::MetaKey
;
88 } else if (!strcmp(characters
, "metaKey")) {
89 return WebInputEvent::MetaKey
;
91 } else if (!strcmp(characters
, "autoRepeat")) {
92 return WebInputEvent::IsAutoRepeat
;
93 } else if (!strcmp(characters
, "copyKey")) {
95 return WebInputEvent::AltKey
;
97 return WebInputEvent::ControlKey
;
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
;
110 int GetKeyModifiers(const std::vector
<std::string
>& modifier_names
) {
112 for (std::vector
<std::string
>::const_iterator it
= modifier_names
.begin();
113 it
!= modifier_names
.end(); ++it
) {
114 modifiers
|= GetKeyModifier(*it
);
119 int GetKeyModifiersFromV8(v8::Isolate
* isolate
, v8::Local
<v8::Value
> value
) {
120 std::vector
<std::string
> modifier_names
;
121 if (value
->IsString()) {
122 modifier_names
.push_back(gin::V8ToString(value
));
123 } else if (value
->IsArray()) {
124 gin::Converter
<std::vector
<std::string
> >::FromV8(
125 isolate
, value
, &modifier_names
);
127 return GetKeyModifiers(modifier_names
);
130 // Maximum distance (in space and time) for a mouse click to register as a
131 // double or triple click.
132 const double kMultipleClickTimeSec
= 1;
133 const int kMultipleClickRadiusPixels
= 5;
134 const char kSubMenuDepthIdentifier
[] = "_";
135 const char kSubMenuIdentifier
[] = " >";
136 const char kSeparatorIdentifier
[] = "---------";
137 const char kDisabledIdentifier
[] = "#";
138 const char kCheckedIdentifier
[] = "*";
140 bool OutsideMultiClickRadius(const WebPoint
& a
, const WebPoint
& b
) {
141 return ((a
.x
- b
.x
) * (a
.x
- b
.x
) + (a
.y
- b
.y
) * (a
.y
- b
.y
)) >
142 kMultipleClickRadiusPixels
* kMultipleClickRadiusPixels
;
145 void PopulateCustomItems(const WebVector
<WebMenuItemInfo
>& customItems
,
146 const std::string
& prefix
, std::vector
<std::string
>* strings
) {
147 for (size_t i
= 0; i
< customItems
.size(); ++i
) {
148 std::string prefixCopy
= prefix
;
149 if (!customItems
[i
].enabled
)
150 prefixCopy
= kDisabledIdentifier
+ prefix
;
151 if (customItems
[i
].checked
)
152 prefixCopy
= kCheckedIdentifier
+ prefix
;
153 if (customItems
[i
].type
== blink::WebMenuItemInfo::Separator
) {
154 strings
->push_back(prefixCopy
+ kSeparatorIdentifier
);
155 } else if (customItems
[i
].type
== blink::WebMenuItemInfo::SubMenu
) {
156 strings
->push_back(prefixCopy
+ customItems
[i
].label
.utf8() +
157 customItems
[i
].icon
.utf8() + kSubMenuIdentifier
);
158 PopulateCustomItems(customItems
[i
].subMenuItems
, prefixCopy
+
159 kSubMenuDepthIdentifier
, strings
);
161 strings
->push_back(prefixCopy
+ customItems
[i
].label
.utf8() +
162 customItems
[i
].icon
.utf8());
167 // Because actual context menu is implemented by the browser side,
168 // this function does only what LayoutTests are expecting:
169 // - Many test checks the count of items. So returning non-zero value makes
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
174 // - Some test even checks actual string content. So providing it would be also
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
181 static const char* kNonEditableMenuStrings
[] = {
192 static const char* kEditableMenuStrings
[] = {
197 "Spelling and Grammar",
198 "Substitutions, Transformations",
201 "Paragraph Direction",
206 // This is possible because mouse events are cancelleable.
208 return std::vector
<std::string
>();
210 std::vector
<std::string
> strings
;
212 // Populate custom menu items if provided by blink.
213 PopulateCustomItems(context_menu
->customItems
, "", &strings
);
215 if (context_menu
->isEditable
) {
216 for (const char** item
= kEditableMenuStrings
; *item
; ++item
) {
217 strings
.push_back(*item
);
219 WebVector
<WebString
> suggestions
;
220 MockSpellCheck::FillSuggestionList(context_menu
->misspelledWord
,
222 for (size_t i
= 0; i
< suggestions
.size(); ++i
) {
223 strings
.push_back(suggestions
[i
].utf8());
226 for (const char** item
= kNonEditableMenuStrings
; *item
; ++item
) {
227 strings
.push_back(*item
);
234 // How much we should scroll per event - the value here is chosen to match the
235 // WebKit impl and layout test results.
236 const float kScrollbarPixelsPerTick
= 40.0f
;
238 WebMouseEvent::Button
GetButtonTypeFromButtonNumber(int button_code
) {
240 return WebMouseEvent::ButtonLeft
;
241 if (button_code
== 2)
242 return WebMouseEvent::ButtonRight
;
243 return WebMouseEvent::ButtonMiddle
;
246 class MouseDownTask
: public WebMethodTask
<EventSender
> {
248 MouseDownTask(EventSender
* obj
, int button_number
, int modifiers
)
249 : WebMethodTask
<EventSender
>(obj
),
250 button_number_(button_number
),
251 modifiers_(modifiers
) {}
253 void RunIfValid() override
{ object_
->MouseDown(button_number_
, modifiers_
); }
260 class MouseUpTask
: public WebMethodTask
<EventSender
> {
262 MouseUpTask(EventSender
* obj
, int button_number
, int modifiers
)
263 : WebMethodTask
<EventSender
>(obj
),
264 button_number_(button_number
),
265 modifiers_(modifiers
) {}
267 void RunIfValid() override
{ object_
->MouseUp(button_number_
, modifiers_
); }
274 class KeyDownTask
: public WebMethodTask
<EventSender
> {
276 KeyDownTask(EventSender
* obj
,
277 const std::string code_str
,
279 KeyLocationCode location
)
280 : WebMethodTask
<EventSender
>(obj
),
282 modifiers_(modifiers
),
283 location_(location
) {}
285 void RunIfValid() override
{
286 object_
->KeyDown(code_str_
, modifiers_
, location_
);
290 std::string code_str_
;
292 KeyLocationCode location_
;
295 bool NeedsShiftModifier(int keyCode
) {
296 // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
297 return (keyCode
& 0xFF) >= 'A' && (keyCode
& 0xFF) <= 'Z';
300 // Get the edit command corresponding to a keyboard event.
301 // Returns true if the specified event corresponds to an edit command, the name
302 // of the edit command will be stored in |*name|.
303 bool GetEditCommand(const WebKeyboardEvent
& event
, std::string
* name
) {
304 #if defined(OS_MACOSX)
305 // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
306 // modifiers. These key events correspond to some special movement and
307 // selection editor commands. These keys will be marked as system key, which
308 // prevents them from being handled. Thus they must be handled specially.
309 if ((event
.modifiers
& ~WebKeyboardEvent::ShiftKey
) !=
310 WebKeyboardEvent::MetaKey
)
313 switch (event
.windowsKeyCode
) {
315 *name
= "MoveToBeginningOfLine";
318 *name
= "MoveToEndOfLine";
321 *name
= "MoveToBeginningOfDocument";
324 *name
= "MoveToEndOfDocument";
330 if (event
.modifiers
& WebKeyboardEvent::ShiftKey
)
331 name
->append("AndModifySelection");
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
;
345 return !!(event
.modifiers
& WebInputEvent::AltKey
);
349 const char* kSourceDeviceStringTouchpad
= "touchpad";
350 const char* kSourceDeviceStringTouchscreen
= "touchscreen";
352 const char* kPointerTypeStringUnknown
= "";
353 const char* kPointerTypeStringMouse
= "mouse";
354 const char* kPointerTypeStringPen
= "pen";
355 const char* kPointerTypeStringTouch
= "touch";
359 class EventSenderBindings
: public gin::Wrappable
<EventSenderBindings
> {
361 static gin::WrapperInfo kWrapperInfo
;
363 static void Install(base::WeakPtr
<EventSender
> sender
,
364 blink::WebFrame
* frame
);
367 explicit EventSenderBindings(base::WeakPtr
<EventSender
> sender
);
368 ~EventSenderBindings() override
;
371 gin::ObjectTemplateBuilder
GetObjectTemplateBuilder(
372 v8::Isolate
* isolate
) override
;
375 void EnableDOMUIEventLogging();
376 void FireKeyboardEventsToElement();
377 void ClearKillRing();
378 std::vector
<std::string
> ContextClick();
383 void SetPageZoomFactor(double factor
);
384 void ClearTouchPoints();
385 void ReleaseTouchPoint(unsigned index
);
386 void UpdateTouchPoint(unsigned index
,
389 gin::Arguments
* args
);
390 void CancelTouchPoint(unsigned index
);
391 void SetTouchModifier(const std::string
& key_name
, bool set_mask
);
392 void SetTouchCancelable(bool cancelable
);
393 void DumpFilenameBeingDragged();
394 void GestureFlingCancel();
395 void GestureFlingStart(float x
,
399 gin::Arguments
* args
);
400 void GestureScrollFirstPoint(int x
, int y
);
403 void TouchMoveCausingScrollIfUncanceled();
406 void LeapForward(int milliseconds
);
407 void BeginDragWithFiles(const std::vector
<std::string
>& files
);
408 void AddTouchPoint(double x
, double y
, gin::Arguments
* args
);
409 void MouseDragBegin();
411 void GestureScrollBegin(gin::Arguments
* args
);
412 void GestureScrollEnd(gin::Arguments
* args
);
413 void GestureScrollUpdate(gin::Arguments
* args
);
414 void GesturePinchBegin(gin::Arguments
* args
);
415 void GesturePinchEnd(gin::Arguments
* args
);
416 void GesturePinchUpdate(gin::Arguments
* args
);
417 void GestureTap(gin::Arguments
* args
);
418 void GestureTapDown(gin::Arguments
* args
);
419 void GestureShowPress(gin::Arguments
* args
);
420 void GestureTapCancel(gin::Arguments
* args
);
421 void GestureLongPress(gin::Arguments
* args
);
422 void GestureLongTap(gin::Arguments
* args
);
423 void GestureTwoFingerTap(gin::Arguments
* args
);
424 void ContinuousMouseScrollBy(gin::Arguments
* args
);
425 void MouseMoveTo(gin::Arguments
* args
);
427 void TrackpadScrollBegin();
428 void TrackpadScroll(gin::Arguments
* args
);
429 void TrackpadScrollEnd();
430 void MouseScrollBy(gin::Arguments
* args
);
431 // TODO(erikchen): Remove MouseMomentumBegin once CL 282743002 has landed.
432 void MouseMomentumBegin();
433 void MouseMomentumBegin2(gin::Arguments
* args
);
434 void MouseMomentumScrollBy(gin::Arguments
* args
);
435 void MouseMomentumEnd();
436 void ScheduleAsynchronousClick(gin::Arguments
* args
);
437 void ScheduleAsynchronousKeyDown(gin::Arguments
* args
);
438 void MouseDown(gin::Arguments
* args
);
439 void MouseUp(gin::Arguments
* args
);
440 void KeyDown(gin::Arguments
* args
);
442 // Binding properties:
443 bool ForceLayoutOnEvents() const;
444 void SetForceLayoutOnEvents(bool force
);
445 bool IsDragMode() const;
446 void SetIsDragMode(bool drag_mode
);
449 int WmKeyDown() const;
450 void SetWmKeyDown(int key_down
);
453 void SetWmKeyUp(int key_up
);
456 void SetWmChar(int wm_char
);
458 int WmDeadChar() const;
459 void SetWmDeadChar(int dead_char
);
461 int WmSysKeyDown() const;
462 void SetWmSysKeyDown(int key_down
);
464 int WmSysKeyUp() const;
465 void SetWmSysKeyUp(int key_up
);
467 int WmSysChar() const;
468 void SetWmSysChar(int sys_char
);
470 int WmSysDeadChar() const;
471 void SetWmSysDeadChar(int sys_dead_char
);
474 base::WeakPtr
<EventSender
> sender_
;
476 DISALLOW_COPY_AND_ASSIGN(EventSenderBindings
);
479 gin::WrapperInfo
EventSenderBindings::kWrapperInfo
= {gin::kEmbedderNativeGin
};
481 EventSenderBindings::EventSenderBindings(base::WeakPtr
<EventSender
> sender
)
485 EventSenderBindings::~EventSenderBindings() {}
488 void EventSenderBindings::Install(base::WeakPtr
<EventSender
> sender
,
490 v8::Isolate
* isolate
= blink::mainThreadIsolate();
491 v8::HandleScope
handle_scope(isolate
);
492 v8::Local
<v8::Context
> context
= frame
->mainWorldScriptContext();
493 if (context
.IsEmpty())
496 v8::Context::Scope
context_scope(context
);
498 gin::Handle
<EventSenderBindings
> bindings
=
499 gin::CreateHandle(isolate
, new EventSenderBindings(sender
));
500 if (bindings
.IsEmpty())
502 v8::Local
<v8::Object
> global
= context
->Global();
503 global
->Set(gin::StringToV8(isolate
, "eventSender"), bindings
.ToV8());
506 gin::ObjectTemplateBuilder
507 EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate
* isolate
) {
508 return gin::Wrappable
<EventSenderBindings
>::GetObjectTemplateBuilder(isolate
)
509 .SetMethod("enableDOMUIEventLogging",
510 &EventSenderBindings::EnableDOMUIEventLogging
)
511 .SetMethod("fireKeyboardEventsToElement",
512 &EventSenderBindings::FireKeyboardEventsToElement
)
513 .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing
)
514 .SetMethod("contextClick", &EventSenderBindings::ContextClick
)
515 .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn
)
516 .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut
)
517 .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn
)
518 .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut
)
519 .SetMethod("setPageZoomFactor", &EventSenderBindings::SetPageZoomFactor
)
520 .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints
)
521 .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint
)
522 .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint
)
523 .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint
)
524 .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier
)
525 .SetMethod("setTouchCancelable", &EventSenderBindings::SetTouchCancelable
)
526 .SetMethod("dumpFilenameBeingDragged",
527 &EventSenderBindings::DumpFilenameBeingDragged
)
528 .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel
)
529 .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart
)
530 .SetMethod("gestureScrollFirstPoint",
531 &EventSenderBindings::GestureScrollFirstPoint
)
532 .SetMethod("touchStart", &EventSenderBindings::TouchStart
)
533 .SetMethod("touchMove", &EventSenderBindings::TouchMove
)
534 .SetMethod("touchMoveCausingScrollIfUncanceled",
535 &EventSenderBindings::TouchMoveCausingScrollIfUncanceled
)
536 .SetMethod("touchCancel", &EventSenderBindings::TouchCancel
)
537 .SetMethod("touchEnd", &EventSenderBindings::TouchEnd
)
538 .SetMethod("leapForward", &EventSenderBindings::LeapForward
)
539 .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles
)
540 .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint
)
541 .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin
)
542 .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd
)
543 .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin
)
544 .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd
)
545 .SetMethod("gestureScrollUpdate",
546 &EventSenderBindings::GestureScrollUpdate
)
547 .SetMethod("gesturePinchBegin", &EventSenderBindings::GesturePinchBegin
)
548 .SetMethod("gesturePinchEnd", &EventSenderBindings::GesturePinchEnd
)
549 .SetMethod("gesturePinchUpdate", &EventSenderBindings::GesturePinchUpdate
)
550 .SetMethod("gestureTap", &EventSenderBindings::GestureTap
)
551 .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown
)
552 .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress
)
553 .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel
)
554 .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress
)
555 .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap
)
556 .SetMethod("gestureTwoFingerTap",
557 &EventSenderBindings::GestureTwoFingerTap
)
558 .SetMethod("continuousMouseScrollBy",
559 &EventSenderBindings::ContinuousMouseScrollBy
)
560 .SetMethod("keyDown", &EventSenderBindings::KeyDown
)
561 .SetMethod("mouseDown", &EventSenderBindings::MouseDown
)
562 .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo
)
563 .SetMethod("mouseLeave", &EventSenderBindings::MouseLeave
)
564 .SetMethod("trackpadScrollBegin",
565 &EventSenderBindings::TrackpadScrollBegin
)
566 .SetMethod("trackpadScroll", &EventSenderBindings::TrackpadScroll
)
567 .SetMethod("trackpadScrollEnd", &EventSenderBindings::TrackpadScrollEnd
)
568 .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy
)
569 .SetMethod("mouseUp", &EventSenderBindings::MouseUp
)
570 .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin
)
571 .SetMethod("mouseMomentumBegin2",
572 &EventSenderBindings::MouseMomentumBegin2
)
573 .SetMethod("mouseMomentumScrollBy",
574 &EventSenderBindings::MouseMomentumScrollBy
)
575 .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd
)
576 .SetMethod("scheduleAsynchronousClick",
577 &EventSenderBindings::ScheduleAsynchronousClick
)
578 .SetMethod("scheduleAsynchronousKeyDown",
579 &EventSenderBindings::ScheduleAsynchronousKeyDown
)
580 .SetProperty("forceLayoutOnEvents",
581 &EventSenderBindings::ForceLayoutOnEvents
,
582 &EventSenderBindings::SetForceLayoutOnEvents
)
583 .SetProperty("dragMode", &EventSenderBindings::IsDragMode
,
584 &EventSenderBindings::SetIsDragMode
)
586 .SetProperty("WM_KEYDOWN", &EventSenderBindings::WmKeyDown
,
587 &EventSenderBindings::SetWmKeyDown
)
588 .SetProperty("WM_KEYUP", &EventSenderBindings::WmKeyUp
,
589 &EventSenderBindings::SetWmKeyUp
)
590 .SetProperty("WM_CHAR", &EventSenderBindings::WmChar
,
591 &EventSenderBindings::SetWmChar
)
592 .SetProperty("WM_DEADCHAR", &EventSenderBindings::WmDeadChar
,
593 &EventSenderBindings::SetWmDeadChar
)
594 .SetProperty("WM_SYSKEYDOWN", &EventSenderBindings::WmSysKeyDown
,
595 &EventSenderBindings::SetWmSysKeyDown
)
596 .SetProperty("WM_SYSKEYUP", &EventSenderBindings::WmSysKeyUp
,
597 &EventSenderBindings::SetWmSysKeyUp
)
598 .SetProperty("WM_SYSCHAR", &EventSenderBindings::WmSysChar
,
599 &EventSenderBindings::SetWmSysChar
)
600 .SetProperty("WM_SYSDEADCHAR", &EventSenderBindings::WmSysDeadChar
,
601 &EventSenderBindings::SetWmSysDeadChar
);
607 void EventSenderBindings::EnableDOMUIEventLogging() {
609 sender_
->EnableDOMUIEventLogging();
612 void EventSenderBindings::FireKeyboardEventsToElement() {
614 sender_
->FireKeyboardEventsToElement();
617 void EventSenderBindings::ClearKillRing() {
619 sender_
->ClearKillRing();
622 std::vector
<std::string
> EventSenderBindings::ContextClick() {
624 return sender_
->ContextClick();
625 return std::vector
<std::string
>();
628 void EventSenderBindings::TextZoomIn() {
630 sender_
->TextZoomIn();
633 void EventSenderBindings::TextZoomOut() {
635 sender_
->TextZoomOut();
638 void EventSenderBindings::ZoomPageIn() {
640 sender_
->ZoomPageIn();
643 void EventSenderBindings::ZoomPageOut() {
645 sender_
->ZoomPageOut();
648 void EventSenderBindings::SetPageZoomFactor(double factor
) {
650 sender_
->SetPageZoomFactor(factor
);
653 void EventSenderBindings::ClearTouchPoints() {
655 sender_
->ClearTouchPoints();
658 void EventSenderBindings::ReleaseTouchPoint(unsigned index
) {
660 sender_
->ReleaseTouchPoint(index
);
663 void EventSenderBindings::UpdateTouchPoint(unsigned index
,
666 gin::Arguments
* args
) {
668 sender_
->UpdateTouchPoint(index
, static_cast<float>(x
),
669 static_cast<float>(y
), args
);
673 void EventSenderBindings::CancelTouchPoint(unsigned index
) {
675 sender_
->CancelTouchPoint(index
);
678 void EventSenderBindings::SetTouchModifier(const std::string
& key_name
,
681 sender_
->SetTouchModifier(key_name
, set_mask
);
684 void EventSenderBindings::SetTouchCancelable(bool cancelable
) {
686 sender_
->SetTouchCancelable(cancelable
);
689 void EventSenderBindings::DumpFilenameBeingDragged() {
691 sender_
->DumpFilenameBeingDragged();
694 void EventSenderBindings::GestureFlingCancel() {
696 sender_
->GestureFlingCancel();
699 void EventSenderBindings::GestureFlingStart(float x
,
703 gin::Arguments
* args
) {
705 sender_
->GestureFlingStart(x
, y
, velocity_x
, velocity_y
, args
);
708 void EventSenderBindings::GestureScrollFirstPoint(int x
, int y
) {
710 sender_
->GestureScrollFirstPoint(x
, y
);
713 void EventSenderBindings::TouchStart() {
715 sender_
->TouchStart();
718 void EventSenderBindings::TouchMove() {
720 sender_
->TouchMove();
723 void EventSenderBindings::TouchMoveCausingScrollIfUncanceled() {
725 sender_
->TouchMoveCausingScrollIfUncanceled();
728 void EventSenderBindings::TouchCancel() {
730 sender_
->TouchCancel();
733 void EventSenderBindings::TouchEnd() {
738 void EventSenderBindings::LeapForward(int milliseconds
) {
740 sender_
->LeapForward(milliseconds
);
743 void EventSenderBindings::BeginDragWithFiles(
744 const std::vector
<std::string
>& files
) {
746 sender_
->BeginDragWithFiles(files
);
749 void EventSenderBindings::AddTouchPoint(double x
,
751 gin::Arguments
* args
) {
753 sender_
->AddTouchPoint(static_cast<float>(x
), static_cast<float>(y
), args
);
756 void EventSenderBindings::MouseDragBegin() {
758 sender_
->MouseDragBegin();
761 void EventSenderBindings::MouseDragEnd() {
763 sender_
->MouseDragEnd();
766 void EventSenderBindings::GestureScrollBegin(gin::Arguments
* args
) {
768 sender_
->GestureScrollBegin(args
);
771 void EventSenderBindings::GestureScrollEnd(gin::Arguments
* args
) {
773 sender_
->GestureScrollEnd(args
);
776 void EventSenderBindings::GestureScrollUpdate(gin::Arguments
* args
) {
778 sender_
->GestureScrollUpdate(args
);
781 void EventSenderBindings::GesturePinchBegin(gin::Arguments
* args
) {
783 sender_
->GesturePinchBegin(args
);
786 void EventSenderBindings::GesturePinchEnd(gin::Arguments
* args
) {
788 sender_
->GesturePinchEnd(args
);
791 void EventSenderBindings::GesturePinchUpdate(gin::Arguments
* args
) {
793 sender_
->GesturePinchUpdate(args
);
796 void EventSenderBindings::GestureTap(gin::Arguments
* args
) {
798 sender_
->GestureTap(args
);
801 void EventSenderBindings::GestureTapDown(gin::Arguments
* args
) {
803 sender_
->GestureTapDown(args
);
806 void EventSenderBindings::GestureShowPress(gin::Arguments
* args
) {
808 sender_
->GestureShowPress(args
);
811 void EventSenderBindings::GestureTapCancel(gin::Arguments
* args
) {
813 sender_
->GestureTapCancel(args
);
816 void EventSenderBindings::GestureLongPress(gin::Arguments
* args
) {
818 sender_
->GestureLongPress(args
);
821 void EventSenderBindings::GestureLongTap(gin::Arguments
* args
) {
823 sender_
->GestureLongTap(args
);
826 void EventSenderBindings::GestureTwoFingerTap(gin::Arguments
* args
) {
828 sender_
->GestureTwoFingerTap(args
);
831 void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments
* args
) {
833 sender_
->ContinuousMouseScrollBy(args
);
836 void EventSenderBindings::MouseMoveTo(gin::Arguments
* args
) {
838 sender_
->MouseMoveTo(args
);
841 void EventSenderBindings::MouseLeave() {
843 sender_
->MouseLeave();
846 void EventSenderBindings::TrackpadScrollBegin() {
848 sender_
->TrackpadScrollBegin();
851 void EventSenderBindings::TrackpadScroll(gin::Arguments
* args
) {
853 sender_
->TrackpadScroll(args
);
856 void EventSenderBindings::TrackpadScrollEnd() {
858 sender_
->TrackpadScrollEnd();
861 void EventSenderBindings::MouseScrollBy(gin::Arguments
* args
) {
863 sender_
->MouseScrollBy(args
);
866 void EventSenderBindings::MouseMomentumBegin() {
868 sender_
->MouseMomentumBegin();
871 void EventSenderBindings::MouseMomentumBegin2(gin::Arguments
* args
) {
873 sender_
->MouseMomentumBegin2(args
);
876 void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments
* args
) {
878 sender_
->MouseMomentumScrollBy(args
);
881 void EventSenderBindings::MouseMomentumEnd() {
883 sender_
->MouseMomentumEnd();
886 void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments
* args
) {
890 int button_number
= 0;
892 if (!args
->PeekNext().IsEmpty()) {
893 args
->GetNext(&button_number
);
894 if (!args
->PeekNext().IsEmpty())
895 modifiers
= GetKeyModifiersFromV8(args
->isolate(), args
->PeekNext());
897 sender_
->ScheduleAsynchronousClick(button_number
, modifiers
);
900 void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments
* args
) {
904 std::string code_str
;
906 int location
= DOMKeyLocationStandard
;
907 args
->GetNext(&code_str
);
908 if (!args
->PeekNext().IsEmpty()) {
909 v8::Local
<v8::Value
> value
;
910 args
->GetNext(&value
);
911 modifiers
= GetKeyModifiersFromV8(args
->isolate(), value
);
912 if (!args
->PeekNext().IsEmpty())
913 args
->GetNext(&location
);
915 sender_
->ScheduleAsynchronousKeyDown(code_str
, modifiers
,
916 static_cast<KeyLocationCode
>(location
));
919 void EventSenderBindings::MouseDown(gin::Arguments
* args
) {
923 int button_number
= 0;
925 if (!args
->PeekNext().IsEmpty()) {
926 args
->GetNext(&button_number
);
927 if (!args
->PeekNext().IsEmpty())
928 modifiers
= GetKeyModifiersFromV8(args
->isolate(), args
->PeekNext());
930 sender_
->MouseDown(button_number
, modifiers
);
933 void EventSenderBindings::MouseUp(gin::Arguments
* args
) {
937 int button_number
= 0;
939 if (!args
->PeekNext().IsEmpty()) {
940 args
->GetNext(&button_number
);
941 if (!args
->PeekNext().IsEmpty())
942 modifiers
= GetKeyModifiersFromV8(args
->isolate(), args
->PeekNext());
944 sender_
->MouseUp(button_number
, modifiers
);
947 void EventSenderBindings::KeyDown(gin::Arguments
* args
) {
951 std::string code_str
;
953 int location
= DOMKeyLocationStandard
;
954 args
->GetNext(&code_str
);
955 if (!args
->PeekNext().IsEmpty()) {
956 v8::Local
<v8::Value
> value
;
957 args
->GetNext(&value
);
958 modifiers
= GetKeyModifiersFromV8(args
->isolate(), value
);
959 if (!args
->PeekNext().IsEmpty())
960 args
->GetNext(&location
);
962 sender_
->KeyDown(code_str
, modifiers
, static_cast<KeyLocationCode
>(location
));
965 bool EventSenderBindings::ForceLayoutOnEvents() const {
967 return sender_
->force_layout_on_events();
971 void EventSenderBindings::SetForceLayoutOnEvents(bool force
) {
973 sender_
->set_force_layout_on_events(force
);
976 bool EventSenderBindings::IsDragMode() const {
978 return sender_
->is_drag_mode();
982 void EventSenderBindings::SetIsDragMode(bool drag_mode
) {
984 sender_
->set_is_drag_mode(drag_mode
);
988 int EventSenderBindings::WmKeyDown() const {
990 return sender_
->wm_key_down();
994 void EventSenderBindings::SetWmKeyDown(int key_down
) {
996 sender_
->set_wm_key_down(key_down
);
999 int EventSenderBindings::WmKeyUp() const {
1001 return sender_
->wm_key_up();
1005 void EventSenderBindings::SetWmKeyUp(int key_up
) {
1007 sender_
->set_wm_key_up(key_up
);
1010 int EventSenderBindings::WmChar() const {
1012 return sender_
->wm_char();
1016 void EventSenderBindings::SetWmChar(int wm_char
) {
1018 sender_
->set_wm_char(wm_char
);
1021 int EventSenderBindings::WmDeadChar() const {
1023 return sender_
->wm_dead_char();
1027 void EventSenderBindings::SetWmDeadChar(int dead_char
) {
1029 sender_
->set_wm_dead_char(dead_char
);
1032 int EventSenderBindings::WmSysKeyDown() const {
1034 return sender_
->wm_sys_key_down();
1038 void EventSenderBindings::SetWmSysKeyDown(int key_down
) {
1040 sender_
->set_wm_sys_key_down(key_down
);
1043 int EventSenderBindings::WmSysKeyUp() const {
1045 return sender_
->wm_sys_key_up();
1049 void EventSenderBindings::SetWmSysKeyUp(int key_up
) {
1051 sender_
->set_wm_sys_key_up(key_up
);
1054 int EventSenderBindings::WmSysChar() const {
1056 return sender_
->wm_sys_char();
1060 void EventSenderBindings::SetWmSysChar(int sys_char
) {
1062 sender_
->set_wm_sys_char(sys_char
);
1065 int EventSenderBindings::WmSysDeadChar() const {
1067 return sender_
->wm_sys_dead_char();
1071 void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char
) {
1073 sender_
->set_wm_sys_dead_char(sys_dead_char
);
1077 // EventSender -----------------------------------------------------------------
1079 WebMouseEvent::Button
EventSender::pressed_button_
= WebMouseEvent::ButtonNone
;
1080 int EventSender::modifiers_
= 0;
1082 WebPoint
EventSender::last_mouse_pos_
;
1084 WebMouseEvent::Button
EventSender::last_button_type_
=
1085 WebMouseEvent::ButtonNone
;
1087 EventSender::SavedEvent::SavedEvent()
1088 : type(TYPE_UNSPECIFIED
),
1089 button_type(WebMouseEvent::ButtonNone
),
1093 EventSender::EventSender(TestInterfaces
* interfaces
)
1100 wm_sys_key_down_(0),
1103 wm_sys_dead_char_(0),
1105 interfaces_(interfaces
),
1108 force_layout_on_events_(false),
1109 is_drag_mode_(true),
1110 touch_modifiers_(0),
1111 touch_cancelable_(true),
1112 replaying_saved_events_(false),
1113 current_drag_effects_allowed_(blink::WebDragOperationNone
),
1114 last_click_time_sec_(0),
1115 current_drag_effect_(blink::WebDragOperationNone
),
1118 weak_factory_(this) {
1121 EventSender::~EventSender() {}
1123 void EventSender::Reset() {
1124 DCHECK(current_drag_data_
.isNull());
1125 current_drag_data_
.reset();
1126 current_drag_effect_
= blink::WebDragOperationNone
;
1127 current_drag_effects_allowed_
= blink::WebDragOperationNone
;
1128 if (view_
&& pressed_button_
!= WebMouseEvent::ButtonNone
)
1129 view_
->mouseCaptureLost();
1130 pressed_button_
= WebMouseEvent::ButtonNone
;
1131 is_drag_mode_
= true;
1132 force_layout_on_events_
= true;
1135 wm_key_down_
= WM_KEYDOWN
;
1136 wm_key_up_
= WM_KEYUP
;
1138 wm_dead_char_
= WM_DEADCHAR
;
1139 wm_sys_key_down_
= WM_SYSKEYDOWN
;
1140 wm_sys_key_up_
= WM_SYSKEYUP
;
1141 wm_sys_char_
= WM_SYSCHAR
;
1142 wm_sys_dead_char_
= WM_SYSDEADCHAR
;
1145 last_mouse_pos_
= WebPoint(0, 0);
1146 last_click_time_sec_
= 0;
1147 last_click_pos_
= WebPoint(0, 0);
1148 last_button_type_
= WebMouseEvent::ButtonNone
;
1149 touch_points_
.clear();
1150 last_context_menu_data_
.reset();
1151 task_list_
.RevokeAll();
1152 current_gesture_location_
= WebPoint(0, 0);
1153 mouse_event_queue_
.clear();
1155 time_offset_ms_
= 0;
1158 touch_modifiers_
= 0;
1159 touch_cancelable_
= true;
1160 touch_points_
.clear();
1163 void EventSender::Install(WebFrame
* frame
) {
1164 EventSenderBindings::Install(weak_factory_
.GetWeakPtr(), frame
);
1167 void EventSender::SetDelegate(WebTestDelegate
* delegate
) {
1168 delegate_
= delegate
;
1171 void EventSender::SetWebView(WebView
* view
) {
1175 void EventSender::SetContextMenuData(const WebContextMenuData
& data
) {
1176 last_context_menu_data_
.reset(new WebContextMenuData(data
));
1179 void EventSender::DoDragDrop(const WebDragData
& drag_data
,
1180 WebDragOperationsMask mask
) {
1181 WebMouseEvent event
;
1182 InitMouseEvent(WebInputEvent::MouseDown
,
1185 GetCurrentEventTimeSec(),
1189 WebPoint
client_point(event
.x
, event
.y
);
1190 WebPoint
screen_point(event
.globalX
, event
.globalY
);
1191 current_drag_data_
= drag_data
;
1192 current_drag_effects_allowed_
= mask
;
1193 current_drag_effect_
= view_
->dragTargetDragEnter(
1197 current_drag_effects_allowed_
,
1200 // Finish processing events.
1201 ReplaySavedEvents();
1204 void EventSender::MouseDown(int button_number
, int modifiers
) {
1205 if (force_layout_on_events_
)
1208 DCHECK_NE(-1, button_number
);
1210 WebMouseEvent::Button button_type
=
1211 GetButtonTypeFromButtonNumber(button_number
);
1213 UpdateClickCountForButton(button_type
);
1215 pressed_button_
= button_type
;
1216 modifiers_
= modifiers
;
1218 WebMouseEvent event
;
1219 InitMouseEvent(WebInputEvent::MouseDown
,
1222 GetCurrentEventTimeSec(),
1226 HandleInputEventOnViewOrPopup(event
);
1229 void EventSender::MouseUp(int button_number
, int modifiers
) {
1230 if (force_layout_on_events_
)
1233 DCHECK_NE(-1, button_number
);
1235 WebMouseEvent::Button button_type
=
1236 GetButtonTypeFromButtonNumber(button_number
);
1238 if (is_drag_mode_
&& !replaying_saved_events_
) {
1239 SavedEvent saved_event
;
1240 saved_event
.type
= SavedEvent::TYPE_MOUSE_UP
;
1241 saved_event
.button_type
= button_type
;
1242 saved_event
.modifiers
= modifiers
;
1243 mouse_event_queue_
.push_back(saved_event
);
1244 ReplaySavedEvents();
1246 WebMouseEvent event
;
1247 InitMouseEvent(WebInputEvent::MouseUp
,
1250 GetCurrentEventTimeSec(),
1258 void EventSender::KeyDown(const std::string
& code_str
,
1260 KeyLocationCode location
) {
1261 // FIXME: I'm not exactly sure how we should convert the string to a key
1262 // event. This seems to work in the cases I tested.
1263 // FIXME: Should we also generate a KEY_UP?
1265 bool generate_char
= false;
1267 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
1268 // Windows uses \r for "Enter".
1271 bool needs_shift_key_modifier
= false;
1272 std::string domString
;
1274 if ("\n" == code_str
) {
1275 generate_char
= true;
1276 text
= code
= ui::VKEY_RETURN
;
1277 domString
.assign("Enter");
1278 } else if ("rightArrow" == code_str
) {
1279 code
= ui::VKEY_RIGHT
;
1280 domString
.assign("ArrowRight");
1281 } else if ("downArrow" == code_str
) {
1282 code
= ui::VKEY_DOWN
;
1283 domString
.assign("ArrowDown");
1284 } else if ("leftArrow" == code_str
) {
1285 code
= ui::VKEY_LEFT
;
1286 domString
.assign("ArrowLeft");
1287 } else if ("upArrow" == code_str
) {
1289 domString
.assign("ArrowUp");
1290 } else if ("insert" == code_str
) {
1291 code
= ui::VKEY_INSERT
;
1292 domString
.assign("Insert");
1293 } else if ("delete" == code_str
) {
1294 code
= ui::VKEY_DELETE
;
1295 domString
.assign("Delete");
1296 } else if ("pageUp" == code_str
) {
1297 code
= ui::VKEY_PRIOR
;
1298 domString
.assign("PageUp");
1299 } else if ("pageDown" == code_str
) {
1300 code
= ui::VKEY_NEXT
;
1301 domString
.assign("PageDown");
1302 } else if ("home" == code_str
) {
1303 code
= ui::VKEY_HOME
;
1304 domString
.assign("Home");
1305 } else if ("end" == code_str
) {
1306 code
= ui::VKEY_END
;
1307 domString
.assign("End");
1308 } else if ("printScreen" == code_str
) {
1309 code
= ui::VKEY_SNAPSHOT
;
1310 domString
.assign("PrintScreen");
1311 } else if ("menu" == code_str
) {
1312 code
= ui::VKEY_APPS
;
1313 domString
.assign("ContextMenu");
1314 } else if ("leftControl" == code_str
) {
1315 code
= ui::VKEY_CONTROL
;
1316 domString
.assign("ControlLeft");
1317 location
= DOMKeyLocationLeft
;
1318 } else if ("rightControl" == code_str
) {
1319 code
= ui::VKEY_CONTROL
;
1320 domString
.assign("ControlRight");
1321 location
= DOMKeyLocationRight
;
1322 } else if ("leftShift" == code_str
) {
1323 code
= ui::VKEY_SHIFT
;
1324 domString
.assign("ShiftLeft");
1325 location
= DOMKeyLocationLeft
;
1326 } else if ("rightShift" == code_str
) {
1327 code
= ui::VKEY_SHIFT
;
1328 domString
.assign("ShiftRight");
1329 location
= DOMKeyLocationRight
;
1330 } else if ("leftAlt" == code_str
) {
1331 code
= ui::VKEY_MENU
;
1332 domString
.assign("AltLeft");
1333 location
= DOMKeyLocationLeft
;
1334 } else if ("rightAlt" == code_str
) {
1335 code
= ui::VKEY_MENU
;
1336 domString
.assign("AltRight");
1337 location
= DOMKeyLocationRight
;
1338 } else if ("numLock" == code_str
) {
1339 code
= ui::VKEY_NUMLOCK
;
1340 domString
.assign("NumLock");
1341 } else if ("backspace" == code_str
) {
1342 code
= ui::VKEY_BACK
;
1343 domString
.assign("Backspace");
1344 } else if ("escape" == code_str
) {
1345 code
= ui::VKEY_ESCAPE
;
1346 domString
.assign("Escape");
1348 // Compare the input string with the function-key names defined by the
1349 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
1350 // name, set its key code.
1351 for (int i
= 1; i
<= 24; ++i
) {
1352 std::string function_key_name
= base::StringPrintf("F%d", i
);
1353 if (function_key_name
== code_str
) {
1354 code
= ui::VKEY_F1
+ (i
- 1);
1355 domString
= function_key_name
;
1360 WebString web_code_str
=
1361 WebString::fromUTF8(code_str
.data(), code_str
.size());
1362 if (web_code_str
.length() != 1u) {
1363 v8::Isolate
* isolate
= blink::mainThreadIsolate();
1364 isolate
->ThrowException(v8::Exception::TypeError(
1365 gin::StringToV8(isolate
, "Invalid web code.")));
1368 text
= code
= web_code_str
.at(0);
1369 needs_shift_key_modifier
= NeedsShiftModifier(code
);
1370 if ((code
& 0xFF) >= 'a' && (code
& 0xFF) <= 'z')
1372 if ((code
>= 'A' && code
<= 'Z') || (code
>= 'a' && code
<= 'z')) {
1373 domString
.assign("Key");
1374 domString
.push_back(
1375 base::ToUpperASCII(static_cast<base::char16
>(code
)));
1376 } else if (code
>= '0' && code
<= '9') {
1377 domString
.assign("Digit");
1378 domString
.push_back(code
);
1379 } else if (code
== ' ') {
1380 domString
.assign("Space");
1381 } else if (code
== 9) {
1382 domString
.assign("Tab");
1384 generate_char
= true;
1387 if ("(" == code_str
) {
1389 needs_shift_key_modifier
= true;
1393 // For one generated keyboard event, we need to generate a keyDown/keyUp
1395 // On Windows, we might also need to generate a char event to mimic the
1396 // Windows event flow; on other platforms we create a merged event and test
1397 // the event flow that that platform provides.
1398 WebKeyboardEvent event_down
;
1399 event_down
.timeStampSeconds
= GetCurrentEventTimeSec();
1400 event_down
.type
= WebInputEvent::RawKeyDown
;
1401 event_down
.modifiers
= modifiers
;
1402 event_down
.windowsKeyCode
= code
;
1403 event_down
.domCode
= static_cast<int>(
1404 ui::KeycodeConverter::CodeStringToDomCode(domString
.c_str()));
1406 if (generate_char
) {
1407 event_down
.text
[0] = text
;
1408 event_down
.unmodifiedText
[0] = text
;
1411 event_down
.setKeyIdentifierFromWindowsKeyCode();
1413 if (event_down
.modifiers
!= 0)
1414 event_down
.isSystemKey
= IsSystemKeyEvent(event_down
);
1416 if (needs_shift_key_modifier
)
1417 event_down
.modifiers
|= WebInputEvent::ShiftKey
;
1419 // See if KeyLocation argument is given.
1421 case DOMKeyLocationStandard
:
1423 case DOMKeyLocationLeft
:
1424 event_down
.modifiers
|= WebInputEvent::IsLeft
;
1426 case DOMKeyLocationRight
:
1427 event_down
.modifiers
|= WebInputEvent::IsRight
;
1429 case DOMKeyLocationNumpad
:
1430 event_down
.modifiers
|= WebInputEvent::IsKeyPad
;
1434 WebKeyboardEvent event_up
;
1435 event_up
= event_down
;
1436 event_up
.type
= WebInputEvent::KeyUp
;
1437 // EventSender.m forces a layout here, with at least one
1438 // test (fast/forms/focus-control-to-page.html) relying on this.
1439 if (force_layout_on_events_
)
1442 // In the browser, if a keyboard event corresponds to an editor command,
1443 // the command will be dispatched to the renderer just before dispatching
1444 // the keyboard event, and then it will be executed in the
1445 // RenderView::handleCurrentKeyboardEvent() method.
1446 // We just simulate the same behavior here.
1447 std::string edit_command
;
1448 if (GetEditCommand(event_down
, &edit_command
))
1449 delegate_
->SetEditCommand(edit_command
, "");
1451 HandleInputEventOnViewOrPopup(event_down
);
1453 if (code
== ui::VKEY_ESCAPE
&& !current_drag_data_
.isNull()) {
1454 WebMouseEvent event
;
1455 InitMouseEvent(WebInputEvent::MouseDown
,
1458 GetCurrentEventTimeSec(),
1462 FinishDragAndDrop(event
, blink::WebDragOperationNone
);
1465 delegate_
->ClearEditCommand();
1467 if (generate_char
) {
1468 WebKeyboardEvent event_char
= event_up
;
1469 event_char
.type
= WebInputEvent::Char
;
1470 // keyIdentifier is an empty string, unless the Enter key was pressed.
1471 // This behavior is not standard (keyIdentifier itself is not even a
1472 // standard any more), but it matches the actual behavior in Blink.
1473 if (code
!= ui::VKEY_RETURN
)
1474 event_char
.keyIdentifier
[0] = '\0';
1475 HandleInputEventOnViewOrPopup(event_char
);
1478 HandleInputEventOnViewOrPopup(event_up
);
1481 void EventSender::EnableDOMUIEventLogging() {}
1483 void EventSender::FireKeyboardEventsToElement() {}
1485 void EventSender::ClearKillRing() {}
1487 std::vector
<std::string
> EventSender::ContextClick() {
1488 if (force_layout_on_events_
) {
1492 UpdateClickCountForButton(WebMouseEvent::ButtonRight
);
1494 // Clears last context menu data because we need to know if the context menu
1495 // be requested after following mouse events.
1496 last_context_menu_data_
.reset();
1498 // Generate right mouse down and up.
1499 WebMouseEvent event
;
1500 // This is a hack to work around only allowing a single pressed button since
1501 // we want to test the case where both the left and right mouse buttons are
1503 if (pressed_button_
== WebMouseEvent::ButtonNone
) {
1504 pressed_button_
= WebMouseEvent::ButtonRight
;
1506 InitMouseEvent(WebInputEvent::MouseDown
,
1507 WebMouseEvent::ButtonRight
,
1509 GetCurrentEventTimeSec(),
1513 HandleInputEventOnViewOrPopup(event
);
1516 InitMouseEvent(WebInputEvent::MouseUp
,
1517 WebMouseEvent::ButtonRight
,
1519 GetCurrentEventTimeSec(),
1523 HandleInputEventOnViewOrPopup(event
);
1525 pressed_button_
= WebMouseEvent::ButtonNone
;
1528 std::vector
<std::string
> menu_items
=
1529 MakeMenuItemStringsFor(last_context_menu_data_
.get(), delegate_
);
1530 last_context_menu_data_
.reset();
1534 void EventSender::TextZoomIn() {
1535 view_
->setTextZoomFactor(view_
->textZoomFactor() * 1.2f
);
1538 void EventSender::TextZoomOut() {
1539 view_
->setTextZoomFactor(view_
->textZoomFactor() / 1.2f
);
1542 void EventSender::ZoomPageIn() {
1543 const std::vector
<WebTestProxyBase
*>& window_list
=
1544 interfaces_
->GetWindowList();
1546 for (size_t i
= 0; i
< window_list
.size(); ++i
) {
1547 window_list
.at(i
)->GetWebView()->setZoomLevel(
1548 window_list
.at(i
)->GetWebView()->zoomLevel() + 1);
1552 void EventSender::ZoomPageOut() {
1553 const std::vector
<WebTestProxyBase
*>& window_list
=
1554 interfaces_
->GetWindowList();
1556 for (size_t i
= 0; i
< window_list
.size(); ++i
) {
1557 window_list
.at(i
)->GetWebView()->setZoomLevel(
1558 window_list
.at(i
)->GetWebView()->zoomLevel() - 1);
1562 void EventSender::SetPageZoomFactor(double zoom_factor
) {
1563 const std::vector
<WebTestProxyBase
*>& window_list
=
1564 interfaces_
->GetWindowList();
1566 for (size_t i
= 0; i
< window_list
.size(); ++i
) {
1567 window_list
.at(i
)->GetWebView()->setZoomLevel(
1568 std::log(zoom_factor
) / std::log(1.2));
1572 void EventSender::ClearTouchPoints() {
1573 touch_points_
.clear();
1576 void EventSender::ThrowTouchPointError() {
1577 v8::Isolate
* isolate
= blink::mainThreadIsolate();
1578 isolate
->ThrowException(v8::Exception::TypeError(
1579 gin::StringToV8(isolate
, "Invalid touch point.")));
1582 void EventSender::ReleaseTouchPoint(unsigned index
) {
1583 if (index
>= touch_points_
.size()) {
1584 ThrowTouchPointError();
1588 WebTouchPoint
* touch_point
= &touch_points_
[index
];
1589 touch_point
->state
= WebTouchPoint::StateReleased
;
1592 void EventSender::UpdateTouchPoint(unsigned index
,
1595 gin::Arguments
* args
) {
1596 if (index
>= touch_points_
.size()) {
1597 ThrowTouchPointError();
1601 WebTouchPoint
* touch_point
= &touch_points_
[index
];
1602 touch_point
->state
= WebTouchPoint::StateMoved
;
1603 touch_point
->position
= WebFloatPoint(x
, y
);
1604 touch_point
->screenPosition
= touch_point
->position
;
1606 InitPointerProperties(args
, touch_point
, &touch_point
->radiusX
,
1607 &touch_point
->radiusY
);
1610 void EventSender::CancelTouchPoint(unsigned index
) {
1611 if (index
>= touch_points_
.size()) {
1612 ThrowTouchPointError();
1616 WebTouchPoint
* touch_point
= &touch_points_
[index
];
1617 touch_point
->state
= WebTouchPoint::StateCancelled
;
1620 void EventSender::SetTouchModifier(const std::string
& key_name
,
1623 if (key_name
== "shift")
1624 mask
= WebInputEvent::ShiftKey
;
1625 else if (key_name
== "alt")
1626 mask
= WebInputEvent::AltKey
;
1627 else if (key_name
== "ctrl")
1628 mask
= WebInputEvent::ControlKey
;
1629 else if (key_name
== "meta")
1630 mask
= WebInputEvent::MetaKey
;
1633 touch_modifiers_
|= mask
;
1635 touch_modifiers_
&= ~mask
;
1638 void EventSender::SetTouchCancelable(bool cancelable
) {
1639 touch_cancelable_
= cancelable
;
1642 void EventSender::DumpFilenameBeingDragged() {
1643 if (current_drag_data_
.isNull())
1647 WebVector
<WebDragData::Item
> items
= current_drag_data_
.items();
1648 for (size_t i
= 0; i
< items
.size(); ++i
) {
1649 if (items
[i
].storageType
== WebDragData::Item::StorageTypeBinaryData
) {
1650 filename
= items
[i
].title
;
1654 delegate_
->PrintMessage(std::string("Filename being dragged: ") +
1655 filename
.utf8().data() + "\n");
1658 void EventSender::GestureFlingCancel() {
1659 WebGestureEvent event
;
1660 event
.type
= WebInputEvent::GestureFlingCancel
;
1661 event
.timeStampSeconds
= GetCurrentEventTimeSec();
1663 if (force_layout_on_events_
)
1666 HandleInputEventOnViewOrPopup(event
);
1669 void EventSender::GestureFlingStart(float x
,
1673 gin::Arguments
* args
) {
1674 WebGestureEvent event
;
1675 event
.type
= WebInputEvent::GestureFlingStart
;
1677 std::string device_string
;
1678 if (!args
->PeekNext().IsEmpty() && args
->PeekNext()->IsString())
1679 args
->GetNext(&device_string
);
1681 if (device_string
== kSourceDeviceStringTouchpad
) {
1682 event
.sourceDevice
= blink::WebGestureDeviceTouchpad
;
1683 } else if (device_string
== kSourceDeviceStringTouchscreen
) {
1684 event
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
1692 event
.globalX
= event
.x
;
1693 event
.globalY
= event
.y
;
1695 event
.data
.flingStart
.velocityX
= velocity_x
;
1696 event
.data
.flingStart
.velocityY
= velocity_y
;
1697 event
.timeStampSeconds
= GetCurrentEventTimeSec();
1699 if (force_layout_on_events_
)
1702 HandleInputEventOnViewOrPopup(event
);
1705 void EventSender::GestureScrollFirstPoint(int x
, int y
) {
1706 current_gesture_location_
= WebPoint(x
, y
);
1709 void EventSender::TouchStart() {
1710 SendCurrentTouchEvent(WebInputEvent::TouchStart
, false);
1713 void EventSender::TouchMove() {
1714 SendCurrentTouchEvent(WebInputEvent::TouchMove
, false);
1717 void EventSender::TouchMoveCausingScrollIfUncanceled() {
1718 SendCurrentTouchEvent(WebInputEvent::TouchMove
, true);
1721 void EventSender::TouchCancel() {
1722 SendCurrentTouchEvent(WebInputEvent::TouchCancel
, false);
1725 void EventSender::TouchEnd() {
1726 SendCurrentTouchEvent(WebInputEvent::TouchEnd
, false);
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
);
1737 DoLeapForward(milliseconds
);
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
;
1751 current_drag_data_
.setFilesystemId(
1752 delegate_
->RegisterIsolatedFileSystem(absolute_filenames
));
1753 current_drag_effects_allowed_
= blink::WebDragOperationCopy
;
1755 // Provide a drag source.
1756 view_
->dragTargetDragEnter(current_drag_data_
,
1759 current_drag_effects_allowed_
,
1761 // |is_drag_mode_| saves events and then replays them later. We don't
1763 is_drag_mode_
= false;
1765 // Make the rest of eventSender think a drag is in progress.
1766 pressed_button_
= WebMouseEvent::ButtonLeft
;
1769 void EventSender::AddTouchPoint(float x
, float y
, gin::Arguments
* args
) {
1770 WebTouchPoint touch_point
;
1771 touch_point
.state
= WebTouchPoint::StatePressed
;
1772 touch_point
.position
= WebFloatPoint(x
, y
);
1773 touch_point
.screenPosition
= touch_point
.position
;
1775 int highest_id
= -1;
1776 for (size_t i
= 0; i
< touch_points_
.size(); i
++) {
1777 if (touch_points_
[i
].id
> highest_id
)
1778 highest_id
= touch_points_
[i
].id
;
1780 touch_point
.id
= highest_id
+ 1;
1782 InitPointerProperties(args
, &touch_point
, &touch_point
.radiusX
,
1783 &touch_point
.radiusY
);
1785 touch_points_
.push_back(touch_point
);
1788 void EventSender::MouseDragBegin() {
1789 WebMouseWheelEvent event
;
1790 InitMouseEvent(WebInputEvent::MouseWheel
,
1791 WebMouseEvent::ButtonNone
,
1793 GetCurrentEventTimeSec(),
1797 event
.phase
= WebMouseWheelEvent::PhaseBegan
;
1798 event
.hasPreciseScrollingDeltas
= true;
1799 HandleInputEventOnViewOrPopup(event
);
1802 void EventSender::MouseDragEnd() {
1803 WebMouseWheelEvent event
;
1804 InitMouseEvent(WebInputEvent::MouseWheel
,
1805 WebMouseEvent::ButtonNone
,
1807 GetCurrentEventTimeSec(),
1811 event
.phase
= WebMouseWheelEvent::PhaseEnded
;
1812 event
.hasPreciseScrollingDeltas
= true;
1813 HandleInputEventOnViewOrPopup(event
);
1816 void EventSender::GestureScrollBegin(gin::Arguments
* args
) {
1817 GestureEvent(WebInputEvent::GestureScrollBegin
, args
);
1820 void EventSender::GestureScrollEnd(gin::Arguments
* args
) {
1821 GestureEvent(WebInputEvent::GestureScrollEnd
, args
);
1824 void EventSender::GestureScrollUpdate(gin::Arguments
* args
) {
1825 GestureEvent(WebInputEvent::GestureScrollUpdate
, args
);
1828 void EventSender::GesturePinchBegin(gin::Arguments
* args
) {
1829 GestureEvent(WebInputEvent::GesturePinchBegin
, args
);
1832 void EventSender::GesturePinchEnd(gin::Arguments
* args
) {
1833 GestureEvent(WebInputEvent::GesturePinchEnd
, args
);
1836 void EventSender::GesturePinchUpdate(gin::Arguments
* args
) {
1837 GestureEvent(WebInputEvent::GesturePinchUpdate
, args
);
1840 void EventSender::GestureTap(gin::Arguments
* args
) {
1841 GestureEvent(WebInputEvent::GestureTap
, args
);
1844 void EventSender::GestureTapDown(gin::Arguments
* args
) {
1845 GestureEvent(WebInputEvent::GestureTapDown
, args
);
1848 void EventSender::GestureShowPress(gin::Arguments
* args
) {
1849 GestureEvent(WebInputEvent::GestureShowPress
, args
);
1852 void EventSender::GestureTapCancel(gin::Arguments
* args
) {
1853 GestureEvent(WebInputEvent::GestureTapCancel
, args
);
1856 void EventSender::GestureLongPress(gin::Arguments
* args
) {
1857 GestureEvent(WebInputEvent::GestureLongPress
, args
);
1860 void EventSender::GestureLongTap(gin::Arguments
* args
) {
1861 GestureEvent(WebInputEvent::GestureLongTap
, args
);
1864 void EventSender::GestureTwoFingerTap(gin::Arguments
* args
) {
1865 GestureEvent(WebInputEvent::GestureTwoFingerTap
, args
);
1868 void EventSender::ContinuousMouseScrollBy(gin::Arguments
* args
) {
1869 WebMouseWheelEvent event
;
1870 InitMouseWheelEvent(args
, true, &event
);
1871 HandleInputEventOnViewOrPopup(event
);
1874 void EventSender::MouseMoveTo(gin::Arguments
* args
) {
1875 if (force_layout_on_events_
)
1880 if (!args
->GetNext(&x
) || !args
->GetNext(&y
)) {
1884 WebPoint
mouse_pos(static_cast<int>(x
), static_cast<int>(y
));
1887 if (!args
->PeekNext().IsEmpty())
1888 modifiers
= GetKeyModifiersFromV8(args
->isolate(), args
->PeekNext());
1890 if (is_drag_mode_
&& pressed_button_
== WebMouseEvent::ButtonLeft
&&
1891 !replaying_saved_events_
) {
1892 SavedEvent saved_event
;
1893 saved_event
.type
= SavedEvent::TYPE_MOUSE_MOVE
;
1894 saved_event
.pos
= mouse_pos
;
1895 saved_event
.modifiers
= modifiers
;
1896 mouse_event_queue_
.push_back(saved_event
);
1898 WebMouseEvent event
;
1899 InitMouseEvent(WebInputEvent::MouseMove
,
1902 GetCurrentEventTimeSec(),
1910 void EventSender::MouseLeave() {
1911 if (force_layout_on_events_
)
1914 WebMouseEvent event
;
1915 InitMouseEvent(WebInputEvent::MouseLeave
,
1916 WebMouseEvent::ButtonNone
,
1918 GetCurrentEventTimeSec(),
1922 view_
->handleInputEvent(event
);
1926 void EventSender::TrackpadScrollBegin() {
1927 WebMouseWheelEvent event
;
1928 InitMouseEvent(WebInputEvent::MouseWheel
,
1929 WebMouseEvent::ButtonNone
,
1931 GetCurrentEventTimeSec(),
1935 event
.phase
= blink::WebMouseWheelEvent::PhaseBegan
;
1936 event
.hasPreciseScrollingDeltas
= true;
1937 HandleInputEventOnViewOrPopup(event
);
1940 void EventSender::TrackpadScroll(gin::Arguments
* args
) {
1941 WebMouseWheelEvent event
;
1942 InitMouseWheelEvent(args
, true, &event
);
1943 event
.phase
= blink::WebMouseWheelEvent::PhaseChanged
;
1944 event
.hasPreciseScrollingDeltas
= true;
1945 HandleInputEventOnViewOrPopup(event
);
1948 void EventSender::TrackpadScrollEnd() {
1949 WebMouseWheelEvent event
;
1950 InitMouseEvent(WebInputEvent::MouseWheel
,
1951 WebMouseEvent::ButtonNone
,
1953 GetCurrentEventTimeSec(),
1957 event
.phase
= WebMouseWheelEvent::PhaseEnded
;
1958 event
.hasPreciseScrollingDeltas
= true;
1959 HandleInputEventOnViewOrPopup(event
);
1962 void EventSender::MouseScrollBy(gin::Arguments
* args
) {
1963 WebMouseWheelEvent event
;
1964 InitMouseWheelEvent(args
, false, &event
);
1965 HandleInputEventOnViewOrPopup(event
);
1968 void EventSender::MouseMomentumBegin() {
1969 WebMouseWheelEvent event
;
1970 InitMouseEvent(WebInputEvent::MouseWheel
,
1971 WebMouseEvent::ButtonNone
,
1973 GetCurrentEventTimeSec(),
1977 event
.momentumPhase
= WebMouseWheelEvent::PhaseBegan
;
1978 event
.hasPreciseScrollingDeltas
= true;
1979 HandleInputEventOnViewOrPopup(event
);
1982 void EventSender::MouseMomentumBegin2(gin::Arguments
* args
) {
1983 WebMouseWheelEvent event
;
1984 InitMouseWheelEvent(args
, true, &event
);
1985 event
.momentumPhase
= WebMouseWheelEvent::PhaseBegan
;
1986 event
.hasPreciseScrollingDeltas
= true;
1987 HandleInputEventOnViewOrPopup(event
);
1990 void EventSender::MouseMomentumScrollBy(gin::Arguments
* args
) {
1991 WebMouseWheelEvent event
;
1992 InitMouseWheelEvent(args
, true, &event
);
1993 event
.momentumPhase
= WebMouseWheelEvent::PhaseChanged
;
1994 event
.hasPreciseScrollingDeltas
= true;
1995 HandleInputEventOnViewOrPopup(event
);
1998 void EventSender::MouseMomentumEnd() {
1999 WebMouseWheelEvent event
;
2000 InitMouseEvent(WebInputEvent::MouseWheel
,
2001 WebMouseEvent::ButtonNone
,
2003 GetCurrentEventTimeSec(),
2007 event
.momentumPhase
= WebMouseWheelEvent::PhaseEnded
;
2008 event
.hasPreciseScrollingDeltas
= true;
2009 HandleInputEventOnViewOrPopup(event
);
2012 void EventSender::ScheduleAsynchronousClick(int button_number
, int modifiers
) {
2013 delegate_
->PostTask(new MouseDownTask(this, button_number
, modifiers
));
2014 delegate_
->PostTask(new MouseUpTask(this, button_number
, modifiers
));
2017 void EventSender::ScheduleAsynchronousKeyDown(const std::string
& code_str
,
2019 KeyLocationCode location
) {
2020 delegate_
->PostTask(new KeyDownTask(this, code_str
, modifiers
, location
));
2023 double EventSender::GetCurrentEventTimeSec() {
2024 return (delegate_
->GetCurrentTimeInMillisecond() + time_offset_ms_
) / 1000.0;
2027 void EventSender::DoLeapForward(int milliseconds
) {
2028 time_offset_ms_
+= milliseconds
;
2031 void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type
,
2032 bool causesScrollingIfUncanceled
) {
2033 DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap
),
2034 touch_points_
.size());
2035 if (force_layout_on_events_
)
2038 WebTouchEvent touch_event
;
2039 touch_event
.type
= type
;
2040 touch_event
.modifiers
= touch_modifiers_
;
2041 touch_event
.cancelable
= touch_cancelable_
;
2042 touch_event
.timeStampSeconds
= GetCurrentEventTimeSec();
2043 touch_event
.causesScrollingIfUncanceled
= causesScrollingIfUncanceled
;
2044 touch_event
.touchesLength
= touch_points_
.size();
2045 for (size_t i
= 0; i
< touch_points_
.size(); ++i
)
2046 touch_event
.touches
[i
] = touch_points_
[i
];
2047 HandleInputEventOnViewOrPopup(touch_event
);
2049 for (size_t i
= 0; i
< touch_points_
.size(); ++i
) {
2050 WebTouchPoint
* touch_point
= &touch_points_
[i
];
2051 if (touch_point
->state
== WebTouchPoint::StateReleased
2052 || touch_point
->state
== WebTouchPoint::StateCancelled
) {
2053 touch_points_
.erase(touch_points_
.begin() + i
);
2056 touch_point
->state
= WebTouchPoint::StateStationary
;
2060 void EventSender::GestureEvent(WebInputEvent::Type type
,
2061 gin::Arguments
* args
) {
2062 WebGestureEvent event
;
2065 // If the first argument is a string, it is to specify the device, otherwise
2066 // the device is assumed to be a touchscreen (since most tests were written
2068 event
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
2069 if (!args
->PeekNext().IsEmpty() && args
->PeekNext()->IsString()) {
2070 std::string device_string
;
2071 if (!args
->GetNext(&device_string
)) {
2075 if (device_string
== kSourceDeviceStringTouchpad
) {
2076 event
.sourceDevice
= blink::WebGestureDeviceTouchpad
;
2077 } else if (device_string
== kSourceDeviceStringTouchscreen
) {
2078 event
.sourceDevice
= blink::WebGestureDeviceTouchscreen
;
2087 if (!args
->GetNext(&x
) || !args
->GetNext(&y
)) {
2093 case WebInputEvent::GestureScrollUpdate
:
2095 bool preventPropagation
= false;
2096 if (!args
->PeekNext().IsEmpty()) {
2097 if (!args
->GetNext(&preventPropagation
)) {
2103 event
.data
.scrollUpdate
.deltaX
= static_cast<float>(x
);
2104 event
.data
.scrollUpdate
.deltaY
= static_cast<float>(y
);
2105 event
.data
.scrollUpdate
.preventPropagation
= preventPropagation
;
2106 event
.x
= current_gesture_location_
.x
;
2107 event
.y
= current_gesture_location_
.y
;
2108 current_gesture_location_
.x
=
2109 current_gesture_location_
.x
+ event
.data
.scrollUpdate
.deltaX
;
2110 current_gesture_location_
.y
=
2111 current_gesture_location_
.y
+ event
.data
.scrollUpdate
.deltaY
;
2114 case WebInputEvent::GestureScrollBegin
:
2115 current_gesture_location_
= WebPoint(x
, y
);
2116 event
.x
= current_gesture_location_
.x
;
2117 event
.y
= current_gesture_location_
.y
;
2119 case WebInputEvent::GestureScrollEnd
:
2120 case WebInputEvent::GestureFlingStart
:
2121 event
.x
= current_gesture_location_
.x
;
2122 event
.y
= current_gesture_location_
.y
;
2124 case WebInputEvent::GesturePinchBegin
:
2125 case WebInputEvent::GesturePinchEnd
:
2126 current_gesture_location_
= WebPoint(x
, y
);
2127 event
.x
= current_gesture_location_
.x
;
2128 event
.y
= current_gesture_location_
.y
;
2130 case WebInputEvent::GesturePinchUpdate
:
2133 if (!args
->PeekNext().IsEmpty()) {
2134 if (!args
->GetNext(&scale
)) {
2139 event
.data
.pinchUpdate
.scale
= scale
;
2140 current_gesture_location_
= WebPoint(x
, y
);
2141 event
.x
= current_gesture_location_
.x
;
2142 event
.y
= current_gesture_location_
.y
;
2145 case WebInputEvent::GestureTap
:
2147 float tap_count
= 1;
2150 if (!args
->PeekNext().IsEmpty()) {
2151 if (!args
->GetNext(&tap_count
)) {
2156 if (!args
->PeekNext().IsEmpty()) {
2157 if (!args
->GetNext(&width
)) {
2162 if (!args
->PeekNext().IsEmpty()) {
2163 if (!args
->GetNext(&height
)) {
2168 event
.data
.tap
.tapCount
= tap_count
;
2169 event
.data
.tap
.width
= width
;
2170 event
.data
.tap
.height
= height
;
2175 case WebInputEvent::GestureTapUnconfirmed
:
2176 if (!args
->PeekNext().IsEmpty()) {
2178 if (!args
->GetNext(&tap_count
)) {
2182 event
.data
.tap
.tapCount
= tap_count
;
2184 event
.data
.tap
.tapCount
= 1;
2189 case WebInputEvent::GestureTapDown
:
2193 if (!args
->PeekNext().IsEmpty()) {
2194 if (!args
->GetNext(&width
)) {
2199 if (!args
->PeekNext().IsEmpty()) {
2200 if (!args
->GetNext(&height
)) {
2207 event
.data
.tapDown
.width
= width
;
2208 event
.data
.tapDown
.height
= height
;
2211 case WebInputEvent::GestureShowPress
:
2215 if (!args
->PeekNext().IsEmpty()) {
2216 if (!args
->GetNext(&width
)) {
2220 if (!args
->PeekNext().IsEmpty()) {
2221 if (!args
->GetNext(&height
)) {
2229 event
.data
.showPress
.width
= width
;
2230 event
.data
.showPress
.height
= height
;
2233 case WebInputEvent::GestureTapCancel
:
2237 case WebInputEvent::GestureLongPress
:
2240 if (!args
->PeekNext().IsEmpty()) {
2242 if (!args
->GetNext(&width
)) {
2246 event
.data
.longPress
.width
= width
;
2247 if (!args
->PeekNext().IsEmpty()) {
2249 if (!args
->GetNext(&height
)) {
2253 event
.data
.longPress
.height
= height
;
2257 case WebInputEvent::GestureLongTap
:
2260 if (!args
->PeekNext().IsEmpty()) {
2262 if (!args
->GetNext(&width
)) {
2266 event
.data
.longPress
.width
= width
;
2267 if (!args
->PeekNext().IsEmpty()) {
2269 if (!args
->GetNext(&height
)) {
2273 event
.data
.longPress
.height
= height
;
2277 case WebInputEvent::GestureTwoFingerTap
:
2280 if (!args
->PeekNext().IsEmpty()) {
2281 float first_finger_width
;
2282 if (!args
->GetNext(&first_finger_width
)) {
2286 event
.data
.twoFingerTap
.firstFingerWidth
= first_finger_width
;
2287 if (!args
->PeekNext().IsEmpty()) {
2288 float first_finger_height
;
2289 if (!args
->GetNext(&first_finger_height
)) {
2293 event
.data
.twoFingerTap
.firstFingerHeight
= first_finger_height
;
2301 event
.globalX
= event
.x
;
2302 event
.globalY
= event
.y
;
2303 event
.timeStampSeconds
= GetCurrentEventTimeSec();
2305 if (force_layout_on_events_
)
2308 bool result
= HandleInputEventOnViewOrPopup(event
);
2310 // Long press might start a drag drop session. Complete it if so.
2311 if (type
== WebInputEvent::GestureLongPress
&& !current_drag_data_
.isNull()) {
2312 WebMouseEvent mouse_event
;
2313 InitMouseEvent(WebInputEvent::MouseDown
,
2316 GetCurrentEventTimeSec(),
2321 FinishDragAndDrop(mouse_event
, blink::WebDragOperationNone
);
2323 args
->Return(result
);
2326 void EventSender::UpdateClickCountForButton(
2327 WebMouseEvent::Button button_type
) {
2328 if ((GetCurrentEventTimeSec() - last_click_time_sec_
<
2329 kMultipleClickTimeSec
) &&
2330 (!OutsideMultiClickRadius(last_mouse_pos_
, last_click_pos_
)) &&
2331 (button_type
== last_button_type_
)) {
2335 last_button_type_
= button_type
;
2339 void EventSender::InitMouseWheelEvent(gin::Arguments
* args
,
2341 WebMouseWheelEvent
* event
) {
2342 // Force a layout here just to make sure every position has been
2343 // determined before we send events (as well as all the other methods
2344 // that send an event do).
2345 if (force_layout_on_events_
)
2349 if (!args
->GetNext(&horizontal
)) {
2354 if (!args
->GetNext(&vertical
)) {
2360 bool has_precise_scrolling_deltas
= false;
2362 bool can_scroll
= true;
2363 if (!args
->PeekNext().IsEmpty()) {
2364 args
->GetNext(&paged
);
2365 if (!args
->PeekNext().IsEmpty()) {
2366 args
->GetNext(&has_precise_scrolling_deltas
);
2367 if (!args
->PeekNext().IsEmpty()) {
2368 v8::Local
<v8::Value
> value
;
2369 args
->GetNext(&value
);
2370 modifiers
= GetKeyModifiersFromV8(args
->isolate(), value
);
2371 if (!args
->PeekNext().IsEmpty())
2372 args
->GetNext(&can_scroll
);
2377 InitMouseEvent(WebInputEvent::MouseWheel
,
2380 GetCurrentEventTimeSec(),
2384 event
->wheelTicksX
= static_cast<float>(horizontal
);
2385 event
->wheelTicksY
= static_cast<float>(vertical
);
2386 event
->deltaX
= event
->wheelTicksX
;
2387 event
->deltaY
= event
->wheelTicksY
;
2388 event
->scrollByPage
= paged
;
2389 event
->hasPreciseScrollingDeltas
= has_precise_scrolling_deltas
;
2390 event
->canScroll
= can_scroll
;
2392 event
->wheelTicksX
/= kScrollbarPixelsPerTick
;
2393 event
->wheelTicksY
/= kScrollbarPixelsPerTick
;
2395 event
->deltaX
*= kScrollbarPixelsPerTick
;
2396 event
->deltaY
*= kScrollbarPixelsPerTick
;
2400 // Radius fields radius_x and radius_y should eventually be moved to
2401 // WebPointerProperties.
2402 // TODO(e_hakkinen): Drop radius_{x,y}_pointer parameters once that happens.
2403 void EventSender::InitPointerProperties(gin::Arguments
* args
,
2404 blink::WebPointerProperties
* e
,
2405 float* radius_x_pointer
,
2406 float* radius_y_pointer
) {
2407 if (!args
->PeekNext().IsEmpty()) {
2409 if (!args
->GetNext(&radius_x
)) {
2414 double radius_y
= radius_x
;
2415 if (!args
->PeekNext().IsEmpty()) {
2416 if (!args
->GetNext(&radius_y
)) {
2422 *radius_x_pointer
= static_cast<float>(radius_x
);
2423 *radius_y_pointer
= static_cast<float>(radius_y
);
2426 if (!args
->PeekNext().IsEmpty()) {
2428 if (!args
->GetNext(&force
)) {
2432 e
->force
= static_cast<float>(force
);
2435 if (!args
->PeekNext().IsEmpty()) {
2437 if (!args
->GetNext(&tiltX
) || !args
->GetNext(&tiltY
)) {
2445 if (!args
->PeekNext().IsEmpty()) {
2446 std::string pointer_type_string
;
2447 if (!args
->GetNext(&pointer_type_string
)) {
2451 if (pointer_type_string
== kPointerTypeStringUnknown
) {
2452 e
->pointerType
= WebMouseEvent::PointerTypeUnknown
;
2453 } else if (pointer_type_string
== kPointerTypeStringMouse
) {
2454 e
->pointerType
= WebMouseEvent::PointerTypeMouse
;
2455 } else if (pointer_type_string
== kPointerTypeStringPen
) {
2456 e
->pointerType
= WebMouseEvent::PointerTypePen
;
2457 } else if (pointer_type_string
== kPointerTypeStringTouch
) {
2458 e
->pointerType
= WebMouseEvent::PointerTypeTouch
;
2466 void EventSender::FinishDragAndDrop(const WebMouseEvent
& e
,
2467 blink::WebDragOperation drag_effect
) {
2468 WebPoint
client_point(e
.x
, e
.y
);
2469 WebPoint
screen_point(e
.globalX
, e
.globalY
);
2470 current_drag_effect_
= drag_effect
;
2471 if (current_drag_effect_
) {
2472 // Specifically pass any keyboard modifiers to the drop method. This allows
2473 // tests to control the drop type (i.e. copy or move).
2474 view_
->dragTargetDrop(client_point
, screen_point
, e
.modifiers
);
2476 view_
->dragTargetDragLeave();
2478 view_
->dragSourceEndedAt(client_point
, screen_point
, current_drag_effect_
);
2479 view_
->dragSourceSystemDragEnded();
2481 current_drag_data_
.reset();
2484 void EventSender::DoMouseUp(const WebMouseEvent
& e
) {
2485 HandleInputEventOnViewOrPopup(e
);
2487 pressed_button_
= WebMouseEvent::ButtonNone
;
2488 last_click_time_sec_
= e
.timeStampSeconds
;
2489 last_click_pos_
= last_mouse_pos_
;
2491 // If we're in a drag operation, complete it.
2492 if (current_drag_data_
.isNull())
2495 WebPoint
client_point(e
.x
, e
.y
);
2496 WebPoint
screen_point(e
.globalX
, e
.globalY
);
2499 view_
->dragTargetDragOver(
2502 current_drag_effects_allowed_
,
2506 void EventSender::DoMouseMove(const WebMouseEvent
& e
) {
2507 last_mouse_pos_
= WebPoint(e
.x
, e
.y
);
2509 HandleInputEventOnViewOrPopup(e
);
2511 if (pressed_button_
== WebMouseEvent::ButtonNone
||
2512 current_drag_data_
.isNull()) {
2516 WebPoint
client_point(e
.x
, e
.y
);
2517 WebPoint
screen_point(e
.globalX
, e
.globalY
);
2518 current_drag_effect_
= view_
->dragTargetDragOver(
2519 client_point
, screen_point
, current_drag_effects_allowed_
, e
.modifiers
);
2522 void EventSender::ReplaySavedEvents() {
2523 replaying_saved_events_
= true;
2524 while (!mouse_event_queue_
.empty()) {
2525 SavedEvent e
= mouse_event_queue_
.front();
2526 mouse_event_queue_
.pop_front();
2529 case SavedEvent::TYPE_MOUSE_MOVE
: {
2530 WebMouseEvent event
;
2531 InitMouseEvent(WebInputEvent::MouseMove
,
2534 GetCurrentEventTimeSec(),
2541 case SavedEvent::TYPE_LEAP_FORWARD
:
2542 DoLeapForward(e
.milliseconds
);
2544 case SavedEvent::TYPE_MOUSE_UP
: {
2545 WebMouseEvent event
;
2546 InitMouseEvent(WebInputEvent::MouseUp
,
2549 GetCurrentEventTimeSec(),
2561 replaying_saved_events_
= false;
2564 bool EventSender::HandleInputEventOnViewOrPopup(const WebInputEvent
& event
) {
2565 if (WebPagePopup
* popup
= view_
->pagePopup()) {
2566 if (!WebInputEvent::isKeyboardEventType(event
.type
))
2567 return popup
->handleInputEvent(event
);
2569 return view_
->handleInputEvent(event
);
2572 } // namespace test_runner