blob: d4cdd5d1f7ce5cf0d071a03ec68b7217dd340dd5 [file] [log] [blame]
[email protected]3db130e2014-03-27 08:14:481// 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/stringprintf.h"
[email protected]3db130e2014-03-27 08:14:4810#include "content/shell/renderer/test_runner/MockSpellCheck.h"
11#include "content/shell/renderer/test_runner/TestInterfaces.h"
12#include "content/shell/renderer/test_runner/WebTestDelegate.h"
13#include "content/shell/renderer/test_runner/WebTestProxy.h"
[email protected]f423182e2014-04-05 08:02:1814#include "content/shell/renderer/test_runner/key_code_mapping.h"
[email protected]3db130e2014-03-27 08:14:4815#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/WebView.h"
24#include "v8/include/v8.h"
25
26#if defined(OS_WIN)
27#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
28#elif defined(OS_MACOSX)
29#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
30#elif defined(OS_ANDROID)
31#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
[email protected]3db130e2014-03-27 08:14:4832#endif
33
34using blink::WebContextMenuData;
35using blink::WebDragData;
36using blink::WebDragOperationsMask;
37using blink::WebFloatPoint;
38using blink::WebFrame;
39using blink::WebGestureEvent;
40using blink::WebInputEvent;
41using blink::WebKeyboardEvent;
42using blink::WebMouseEvent;
43using blink::WebMouseWheelEvent;
44using blink::WebPoint;
45using blink::WebString;
46using blink::WebTouchEvent;
47using blink::WebTouchPoint;
48using blink::WebVector;
49using blink::WebView;
50
[email protected]c997bc42014-04-11 18:25:5851#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID)
[email protected]3db130e2014-03-27 08:14:4852using blink::WebInputEventFactory;
53#endif
54
55namespace content {
56
57namespace {
58
59void InitMouseEvent(WebInputEvent::Type t,
60 WebMouseEvent::Button b,
61 const WebPoint& pos,
62 double time_stamp,
63 int click_count,
64 int modifiers,
65 WebMouseEvent* e) {
66 e->type = t;
67 e->button = b;
68 e->modifiers = modifiers;
69 e->x = pos.x;
70 e->y = pos.y;
71 e->globalX = pos.x;
72 e->globalY = pos.y;
73 e->timeStampSeconds = time_stamp;
74 e->clickCount = click_count;
75}
76
77int GetKeyModifier(const std::string& modifier_name) {
78 const char* characters = modifier_name.c_str();
79 if (!strcmp(characters, "ctrlKey")
80#ifndef __APPLE__
81 || !strcmp(characters, "addSelectionKey")
82#endif
83 ) {
84 return WebInputEvent::ControlKey;
85 } else if (!strcmp(characters, "shiftKey") ||
86 !strcmp(characters, "rangeSelectionKey")) {
87 return WebInputEvent::ShiftKey;
88 } else if (!strcmp(characters, "altKey")) {
89 return WebInputEvent::AltKey;
90#ifdef __APPLE__
91 } else if (!strcmp(characters, "metaKey") ||
92 !strcmp(characters, "addSelectionKey")) {
93 return WebInputEvent::MetaKey;
94#else
95 } else if (!strcmp(characters, "metaKey")) {
96 return WebInputEvent::MetaKey;
97#endif
98 } else if (!strcmp(characters, "autoRepeat")) {
99 return WebInputEvent::IsAutoRepeat;
100 } else if (!strcmp(characters, "copyKey")) {
101#ifdef __APPLE__
102 return WebInputEvent::AltKey;
103#else
104 return WebInputEvent::ControlKey;
105#endif
106 }
107
108 return 0;
109}
110
111int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
112 int modifiers = 0;
113 for (std::vector<std::string>::const_iterator it = modifier_names.begin();
114 it != modifier_names.end(); ++it) {
115 modifiers |= GetKeyModifier(*it);
116 }
117 return modifiers;
118}
119
120int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
121 std::vector<std::string> modifier_names;
122 if (value->IsString()) {
123 modifier_names.push_back(gin::V8ToString(value));
124 } else if (value->IsArray()) {
125 gin::Converter<std::vector<std::string> >::FromV8(
126 NULL, value, &modifier_names);
127 }
128 return GetKeyModifiers(modifier_names);
129}
130
131// Maximum distance (in space and time) for a mouse click to register as a
132// double or triple click.
133const double kMultipleClickTimeSec = 1;
134const int kMultipleClickRadiusPixels = 5;
135
136bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
137 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
138 kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
139}
140
141// Because actual context menu is implemented by the browser side,
142// this function does only what LayoutTests are expecting:
143// - Many test checks the count of items. So returning non-zero value makes
144// sense.
145// - Some test compares the count before and after some action. So changing the
146// count based on flags also makes sense. This function is doing such for some
147// flags.
148// - Some test even checks actual string content. So providing it would be also
149// helpful.
150std::vector<std::string> MakeMenuItemStringsFor(
151 WebContextMenuData* context_menu,
152 WebTestRunner::WebTestDelegate* delegate) {
153 // These constants are based on Safari's context menu because tests are made
154 // for it.
155 static const char* kNonEditableMenuStrings[] = {
156 "Back",
157 "Reload Page",
158 "Open in Dashbaord",
159 "<separator>",
160 "View Source",
161 "Save Page As",
162 "Print Page",
163 "Inspect Element",
164 0
165 };
166 static const char* kEditableMenuStrings[] = {
167 "Cut",
168 "Copy",
169 "<separator>",
170 "Paste",
171 "Spelling and Grammar",
172 "Substitutions, Transformations",
173 "Font",
174 "Speech",
175 "Paragraph Direction",
176 "<separator>",
177 0
178 };
179
180 // This is possible because mouse events are cancelleable.
181 if (!context_menu)
182 return std::vector<std::string>();
183
184 std::vector<std::string> strings;
185
186 if (context_menu->isEditable) {
187 for (const char** item = kEditableMenuStrings; *item; ++item) {
188 strings.push_back(*item);
189 }
190 WebVector<WebString> suggestions;
191 WebTestRunner::MockSpellCheck::fillSuggestionList(
192 context_menu->misspelledWord, &suggestions);
193 for (size_t i = 0; i < suggestions.size(); ++i) {
194 strings.push_back(suggestions[i].utf8());
195 }
196 } else {
197 for (const char** item = kNonEditableMenuStrings; *item; ++item) {
198 strings.push_back(*item);
199 }
200 }
201
202 return strings;
203}
204
205// How much we should scroll per event - the value here is chosen to match the
206// WebKit impl and layout test results.
207const float kScrollbarPixelsPerTick = 40.0f;
208
209WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
210 if (!button_code)
211 return WebMouseEvent::ButtonLeft;
212 if (button_code == 2)
213 return WebMouseEvent::ButtonRight;
214 return WebMouseEvent::ButtonMiddle;
215}
216
217class MouseDownTask : public WebTestRunner::WebMethodTask<EventSender> {
218 public:
219 MouseDownTask(EventSender* obj, int button_number, int modifiers)
220 : WebMethodTask<EventSender>(obj),
221 button_number_(button_number),
222 modifiers_(modifiers) {}
223
224 virtual void runIfValid() OVERRIDE {
225 m_object->MouseDown(button_number_, modifiers_);
226 }
227
228 private:
229 int button_number_;
230 int modifiers_;
231};
232
233class MouseUpTask : public WebTestRunner::WebMethodTask<EventSender> {
234 public:
235 MouseUpTask(EventSender* obj, int button_number, int modifiers)
236 : WebMethodTask<EventSender>(obj),
237 button_number_(button_number),
238 modifiers_(modifiers) {}
239
240 virtual void runIfValid() OVERRIDE {
241 m_object->MouseUp(button_number_, modifiers_);
242 }
243
244 private:
245 int button_number_;
246 int modifiers_;
247};
248
249class KeyDownTask : public WebTestRunner::WebMethodTask<EventSender> {
250 public:
251 KeyDownTask(EventSender* obj,
252 const std::string code_str,
253 int modifiers,
254 KeyLocationCode location)
255 : WebMethodTask<EventSender>(obj),
256 code_str_(code_str),
257 modifiers_(modifiers),
258 location_(location) {}
259
260 virtual void runIfValid() OVERRIDE {
261 m_object->KeyDown(code_str_, modifiers_, location_);
262 }
263
264 private:
265 std::string code_str_;
266 int modifiers_;
267 KeyLocationCode location_;
268};
269
270bool NeedsShiftModifier(int keyCode) {
271 // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
272 return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
273}
274
275// Get the edit command corresponding to a keyboard event.
276// Returns true if the specified event corresponds to an edit command, the name
277// of the edit command will be stored in |*name|.
278bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
279#if defined(OS_MACOSX)
280// We only cares about Left,Right,Up,Down keys with Command or Command+Shift
281// modifiers. These key events correspond to some special movement and
282// selection editor commands. These keys will be marked as system key, which
283// prevents them from being handled. Thus they must be handled specially.
284 if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
285 WebKeyboardEvent::MetaKey)
286 return false;
287
288 switch (event.windowsKeyCode) {
[email protected]f423182e2014-04-05 08:02:18289 case VKEY_LEFT:
[email protected]3db130e2014-03-27 08:14:48290 *name = "MoveToBeginningOfLine";
291 break;
[email protected]f423182e2014-04-05 08:02:18292 case VKEY_RIGHT:
[email protected]3db130e2014-03-27 08:14:48293 *name = "MoveToEndOfLine";
294 break;
[email protected]f423182e2014-04-05 08:02:18295 case VKEY_UP:
[email protected]3db130e2014-03-27 08:14:48296 *name = "MoveToBeginningOfDocument";
297 break;
[email protected]f423182e2014-04-05 08:02:18298 case VKEY_DOWN:
[email protected]3db130e2014-03-27 08:14:48299 *name = "MoveToEndOfDocument";
300 break;
301 default:
302 return false;
303 }
304
305 if (event.modifiers & WebKeyboardEvent::ShiftKey)
306 name->append("AndModifySelection");
307
308 return true;
309#else
310 return false;
311#endif
312}
313
314} // namespace
315
316class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
317 public:
318 static gin::WrapperInfo kWrapperInfo;
319
320 static void Install(base::WeakPtr<EventSender> sender,
321 blink::WebFrame* frame);
322
323 private:
324 explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
325 virtual ~EventSenderBindings();
326
327 // gin::Wrappable:
328 virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
329 v8::Isolate* isolate) OVERRIDE;
330
331 // Bound methods:
332 void EnableDOMUIEventLogging();
333 void FireKeyboardEventsToElement();
334 void ClearKillRing();
335 std::vector<std::string> ContextClick();
336 void TextZoomIn();
337 void TextZoomOut();
338 void ZoomPageIn();
339 void ZoomPageOut();
340 void SetPageScaleFactor(gin::Arguments* args);
341 void ClearTouchPoints();
342 void ReleaseTouchPoint(unsigned index);
[email protected]f53eba122014-04-16 11:30:01343 void UpdateTouchPoint(unsigned index, double x, double y);
[email protected]3db130e2014-03-27 08:14:48344 void CancelTouchPoint(unsigned index);
345 void SetTouchModifier(const std::string& key_name, bool set_mask);
346 void DumpFilenameBeingDragged();
347 void GestureFlingCancel();
348 void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
349 void GestureScrollFirstPoint(int x, int y);
350 void TouchStart();
351 void TouchMove();
352 void TouchCancel();
353 void TouchEnd();
354 void LeapForward(int milliseconds);
355 void BeginDragWithFiles(const std::vector<std::string>& files);
356 void AddTouchPoint(gin::Arguments* args);
357 void MouseDragBegin();
358 void MouseDragEnd();
359 void MouseMomentumBegin();
360 void GestureScrollBegin(gin::Arguments* args);
361 void GestureScrollEnd(gin::Arguments* args);
362 void GestureScrollUpdate(gin::Arguments* args);
363 void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
364 void GestureTap(gin::Arguments* args);
365 void GestureTapDown(gin::Arguments* args);
366 void GestureShowPress(gin::Arguments* args);
367 void GestureTapCancel(gin::Arguments* args);
368 void GestureLongPress(gin::Arguments* args);
369 void GestureLongTap(gin::Arguments* args);
370 void GestureTwoFingerTap(gin::Arguments* args);
371 void ContinuousMouseScrollBy(gin::Arguments* args);
372 void DispatchMessage(int msg, int wparam, int lparam);
373 void MouseMoveTo(gin::Arguments* args);
374 void MouseScrollBy(gin::Arguments* args);
375 void MouseMomentumScrollBy(gin::Arguments* args);
376 void MouseMomentumEnd();
377 void ScheduleAsynchronousClick(gin::Arguments* args);
378 void ScheduleAsynchronousKeyDown(gin::Arguments* args);
379 void MouseDown(gin::Arguments* args);
380 void MouseUp(gin::Arguments* args);
381 void KeyDown(gin::Arguments* args);
382
383 // Binding properties:
384 bool ForceLayoutOnEvents() const;
385 void SetForceLayoutOnEvents(bool force);
386 bool IsDragMode() const;
387 void SetIsDragMode(bool drag_mode);
388
389#if defined(OS_WIN)
390 int WmKeyDown() const;
391 void SetWmKeyDown(int key_down);
392
393 int WmKeyUp() const;
394 void SetWmKeyUp(int key_up);
395
396 int WmChar() const;
397 void SetWmChar(int wm_char);
398
399 int WmDeadChar() const;
400 void SetWmDeadChar(int dead_char);
401
402 int WmSysKeyDown() const;
403 void SetWmSysKeyDown(int key_down);
404
405 int WmSysKeyUp() const;
406 void SetWmSysKeyUp(int key_up);
407
408 int WmSysChar() const;
409 void SetWmSysChar(int sys_char);
410
411 int WmSysDeadChar() const;
412 void SetWmSysDeadChar(int sys_dead_char);
413#endif
414
415 base::WeakPtr<EventSender> sender_;
416
417 DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
418};
419
420gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
421
422EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
423 : sender_(sender) {
424}
425
426EventSenderBindings::~EventSenderBindings() {}
427
428// static
429void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
430 WebFrame* frame) {
431 v8::Isolate* isolate = blink::mainThreadIsolate();
432 v8::HandleScope handle_scope(isolate);
433 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
434 if (context.IsEmpty())
435 return;
436
437 v8::Context::Scope context_scope(context);
438
439 gin::Handle<EventSenderBindings> bindings =
440 gin::CreateHandle(isolate, new EventSenderBindings(sender));
441 v8::Handle<v8::Object> global = context->Global();
442 global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
443}
444
445gin::ObjectTemplateBuilder
446EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
447 return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
448 .SetMethod("enableDOMUIEventLogging",
449 &EventSenderBindings::EnableDOMUIEventLogging)
450 .SetMethod("fireKeyboardEventsToElement",
451 &EventSenderBindings::FireKeyboardEventsToElement)
452 .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
453 .SetMethod("contextClick", &EventSenderBindings::ContextClick)
454 .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
455 .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
456 .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
457 .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
458 .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
459 .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
460 .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
461 .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
462 .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
463 .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
464 .SetMethod("dumpFilenameBeingDragged",
465 &EventSenderBindings::DumpFilenameBeingDragged)
466 .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
467 .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
468 .SetMethod("gestureScrollFirstPoint",
469 &EventSenderBindings::GestureScrollFirstPoint)
470 .SetMethod("touchStart", &EventSenderBindings::TouchStart)
471 .SetMethod("touchMove", &EventSenderBindings::TouchMove)
472 .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
473 .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
474 .SetMethod("leapForward", &EventSenderBindings::LeapForward)
475 .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
476 .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
477 .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
478 .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
479 .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
480 .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
481 .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
482 .SetMethod("gestureScrollUpdate",
483 &EventSenderBindings::GestureScrollUpdate)
484 .SetMethod("gestureScrollUpdateWithoutPropagation",
485 &EventSenderBindings::GestureScrollUpdateWithoutPropagation)
486 .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
487 .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
488 .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
489 .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
490 .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
491 .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
492 .SetMethod("gestureTwoFingerTap",
493 &EventSenderBindings::GestureTwoFingerTap)
494 .SetMethod("continuousMouseScrollBy",
495 &EventSenderBindings::ContinuousMouseScrollBy)
496 .SetMethod("dispatchMessage", &EventSenderBindings::DispatchMessage)
497 .SetMethod("keyDown", &EventSenderBindings::KeyDown)
498 .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
499 .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
500 .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
501 .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
502 .SetMethod("mouseMomentumScrollBy",
503 &EventSenderBindings::MouseMomentumScrollBy)
504 .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
505 .SetMethod("scheduleAsynchronousClick",
506 &EventSenderBindings::ScheduleAsynchronousClick)
507 .SetMethod("scheduleAsynchronousKeyDown",
508 &EventSenderBindings::ScheduleAsynchronousKeyDown)
509 .SetProperty("forceLayoutOnEvents",
510 &EventSenderBindings::ForceLayoutOnEvents,
511 &EventSenderBindings::SetForceLayoutOnEvents)
512 .SetProperty("dragMode",
513 &EventSenderBindings::IsDragMode,
514 &EventSenderBindings::SetIsDragMode)
515#if defined(OS_WIN)
516 .SetProperty("WM_KEYDOWN",
517 &EventSenderBindings::WmKeyDown,
518 &EventSenderBindings::SetWmKeyDown)
519 .SetProperty("WM_KEYUP",
520 &EventSenderBindings::WmKeyUp,
521 &EventSenderBindings::SetWmKeyUp)
522 .SetProperty("WM_CHAR",
523 &EventSenderBindings::WmChar,
524 &EventSenderBindings::SetWmChar)
525 .SetProperty("WM_DEADCHAR",
526 &EventSenderBindings::WmDeadChar,
527 &EventSenderBindings::SetWmDeadChar)
528 .SetProperty("WM_SYSKEYDOWN",
529 &EventSenderBindings::WmSysKeyDown,
530 &EventSenderBindings::SetWmSysKeyDown)
531 .SetProperty("WM_SYSKEYUP",
532 &EventSenderBindings::WmSysKeyUp,
533 &EventSenderBindings::SetWmSysKeyUp)
534 .SetProperty("WM_SYSCHAR",
535 &EventSenderBindings::WmSysChar,
536 &EventSenderBindings::SetWmSysChar)
537 .SetProperty("WM_SYSDEADCHAR",
538 &EventSenderBindings::WmSysDeadChar,
539 &EventSenderBindings::SetWmSysDeadChar);
540#else
541 ;
542#endif
543}
544
545void EventSenderBindings::EnableDOMUIEventLogging() {
546 if (sender_)
547 sender_->EnableDOMUIEventLogging();
548}
549
550void EventSenderBindings::FireKeyboardEventsToElement() {
551 if (sender_)
552 sender_->FireKeyboardEventsToElement();
553}
554
555void EventSenderBindings::ClearKillRing() {
556 if (sender_)
557 sender_->ClearKillRing();
558}
559
560std::vector<std::string> EventSenderBindings::ContextClick() {
561 if (sender_)
562 return sender_->ContextClick();
563 return std::vector<std::string>();
564}
565
566void EventSenderBindings::TextZoomIn() {
567 if (sender_)
568 sender_->TextZoomIn();
569}
570
571void EventSenderBindings::TextZoomOut() {
572 if (sender_)
573 sender_->TextZoomOut();
574}
575
576void EventSenderBindings::ZoomPageIn() {
577 if (sender_)
578 sender_->ZoomPageIn();
579}
580
581void EventSenderBindings::ZoomPageOut() {
582 if (sender_)
583 sender_->ZoomPageOut();
584}
585
586void EventSenderBindings::SetPageScaleFactor(gin::Arguments* args) {
587 if (!sender_)
588 return;
589 float scale_factor;
[email protected]f53eba122014-04-16 11:30:01590 double x;
591 double y;
[email protected]3db130e2014-03-27 08:14:48592 if (args->PeekNext().IsEmpty())
593 return;
594 args->GetNext(&scale_factor);
595 if (args->PeekNext().IsEmpty())
596 return;
597 args->GetNext(&x);
598 if (args->PeekNext().IsEmpty())
599 return;
600 args->GetNext(&y);
[email protected]f53eba122014-04-16 11:30:01601 sender_->SetPageScaleFactor(scale_factor,
602 static_cast<int>(x), static_cast<int>(y));
[email protected]3db130e2014-03-27 08:14:48603}
604
605void EventSenderBindings::ClearTouchPoints() {
606 if (sender_)
607 sender_->ClearTouchPoints();
608}
609
610void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
611 if (sender_)
612 sender_->ReleaseTouchPoint(index);
613}
614
[email protected]f53eba122014-04-16 11:30:01615void EventSenderBindings::UpdateTouchPoint(unsigned index, double x, double y) {
[email protected]3db130e2014-03-27 08:14:48616 if (sender_)
[email protected]f53eba122014-04-16 11:30:01617 sender_->UpdateTouchPoint(index, static_cast<int>(x), static_cast<int>(y));
[email protected]3db130e2014-03-27 08:14:48618}
619
620void EventSenderBindings::CancelTouchPoint(unsigned index) {
621 if (sender_)
622 sender_->CancelTouchPoint(index);
623}
624
625void EventSenderBindings::SetTouchModifier(const std::string& key_name,
626 bool set_mask) {
627 if (sender_)
628 sender_->SetTouchModifier(key_name, set_mask);
629}
630
631void EventSenderBindings::DumpFilenameBeingDragged() {
632 if (sender_)
633 sender_->DumpFilenameBeingDragged();
634}
635
636void EventSenderBindings::GestureFlingCancel() {
637 if (sender_)
638 sender_->GestureFlingCancel();
639}
640
641void EventSenderBindings::GestureFlingStart(float x,
642 float y,
643 float velocity_x,
644 float velocity_y) {
645 if (sender_)
646 sender_->GestureFlingStart(x, y, velocity_x, velocity_y);
647}
648
649void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
650 if (sender_)
651 sender_->GestureScrollFirstPoint(x, y);
652}
653
654void EventSenderBindings::TouchStart() {
655 if (sender_)
656 sender_->TouchStart();
657}
658
659void EventSenderBindings::TouchMove() {
660 if (sender_)
661 sender_->TouchMove();
662}
663
664void EventSenderBindings::TouchCancel() {
665 if (sender_)
666 sender_->TouchCancel();
667}
668
669void EventSenderBindings::TouchEnd() {
670 if (sender_)
671 sender_->TouchEnd();
672}
673
674void EventSenderBindings::LeapForward(int milliseconds) {
675 if (sender_)
676 sender_->LeapForward(milliseconds);
677}
678
679void EventSenderBindings::BeginDragWithFiles(
680 const std::vector<std::string>& files) {
681 if (sender_)
682 sender_->BeginDragWithFiles(files);
683}
684
685void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
686 if (sender_)
687 sender_->AddTouchPoint(args);
688}
689
690void EventSenderBindings::MouseDragBegin() {
691 if (sender_)
692 sender_->MouseDragBegin();
693}
694
695void EventSenderBindings::MouseDragEnd() {
696 if (sender_)
697 sender_->MouseDragEnd();
698}
699
700void EventSenderBindings::MouseMomentumBegin() {
701 if (sender_)
702 sender_->MouseMomentumBegin();
703}
704
705void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
706 if (sender_)
707 sender_->GestureScrollBegin(args);
708}
709
710void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
711 if (sender_)
712 sender_->GestureScrollEnd(args);
713}
714
715void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
716 if (sender_)
717 sender_->GestureScrollUpdate(args);
718}
719
720void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
721 gin::Arguments* args) {
722 if (sender_)
723 sender_->GestureScrollUpdateWithoutPropagation(args);
724}
725
726void EventSenderBindings::GestureTap(gin::Arguments* args) {
727 if (sender_)
728 sender_->GestureTap(args);
729}
730
731void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
732 if (sender_)
733 sender_->GestureTapDown(args);
734}
735
736void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
737 if (sender_)
738 sender_->GestureShowPress(args);
739}
740
741void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
742 if (sender_)
743 sender_->GestureTapCancel(args);
744}
745
746void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
747 if (sender_)
748 sender_->GestureLongPress(args);
749}
750
751void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
752 if (sender_)
753 sender_->GestureLongTap(args);
754}
755
756void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
757 if (sender_)
758 sender_->GestureTwoFingerTap(args);
759}
760
761void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
762 if (sender_)
763 sender_->ContinuousMouseScrollBy(args);
764}
765
766void EventSenderBindings::DispatchMessage(int msg, int wparam, int lparam) {
767 if (sender_)
768 sender_->DispatchMessage(msg, wparam, lparam);
769}
770
771void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
772 if (sender_)
773 sender_->MouseMoveTo(args);
774}
775
776void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
777 if (sender_)
778 sender_->MouseScrollBy(args);
779}
780
781void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
782 if (sender_)
783 sender_->MouseMomentumScrollBy(args);
784}
785
786void EventSenderBindings::MouseMomentumEnd() {
787 if (sender_)
788 sender_->MouseMomentumEnd();
789}
790
791void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
792 if (!sender_)
793 return;
794
795 int button_number = 0;
796 int modifiers = 0;
797 if (!args->PeekNext().IsEmpty()) {
798 args->GetNext(&button_number);
799 if (!args->PeekNext().IsEmpty())
800 modifiers = GetKeyModifiersFromV8(args->PeekNext());
801 }
802 sender_->ScheduleAsynchronousClick(button_number, modifiers);
803}
804
805void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
806 if (!sender_)
807 return;
808
809 std::string code_str;
810 int modifiers = 0;
811 int location = DOMKeyLocationStandard;
812 args->GetNext(&code_str);
813 if (!args->PeekNext().IsEmpty()) {
814 v8::Handle<v8::Value> value;
815 args->GetNext(&value);
816 modifiers = GetKeyModifiersFromV8(value);
817 if (!args->PeekNext().IsEmpty())
818 args->GetNext(&location);
819 }
820 sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
821 static_cast<KeyLocationCode>(location));
822}
823
824void EventSenderBindings::MouseDown(gin::Arguments* args) {
825 if (!sender_)
826 return;
827
828 int button_number = 0;
829 int modifiers = 0;
830 if (!args->PeekNext().IsEmpty()) {
831 args->GetNext(&button_number);
832 if (!args->PeekNext().IsEmpty())
833 modifiers = GetKeyModifiersFromV8(args->PeekNext());
834 }
835 sender_->MouseDown(button_number, modifiers);
836}
837
838void EventSenderBindings::MouseUp(gin::Arguments* args) {
839 if (!sender_)
840 return;
841
842 int button_number = 0;
843 int modifiers = 0;
844 if (!args->PeekNext().IsEmpty()) {
845 args->GetNext(&button_number);
846 if (!args->PeekNext().IsEmpty())
847 modifiers = GetKeyModifiersFromV8(args->PeekNext());
848 }
849 sender_->MouseUp(button_number, modifiers);
850}
851
852void EventSenderBindings::KeyDown(gin::Arguments* args) {
853 if (!sender_)
854 return;
855
856 std::string code_str;
857 int modifiers = 0;
858 int location = DOMKeyLocationStandard;
859 args->GetNext(&code_str);
860 if (!args->PeekNext().IsEmpty()) {
861 v8::Handle<v8::Value> value;
862 args->GetNext(&value);
863 modifiers = GetKeyModifiersFromV8(value);
864 if (!args->PeekNext().IsEmpty())
865 args->GetNext(&location);
866 }
867 sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
868}
869
870bool EventSenderBindings::ForceLayoutOnEvents() const {
871 if (sender_)
872 return sender_->force_layout_on_events();
873 return false;
874}
875
876void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
877 if (sender_)
878 sender_->set_force_layout_on_events(force);
879}
880
881bool EventSenderBindings::IsDragMode() const {
882 if (sender_)
883 return sender_->is_drag_mode();
884 return true;
885}
886
887void EventSenderBindings::SetIsDragMode(bool drag_mode) {
888 if (sender_)
889 sender_->set_is_drag_mode(drag_mode);
890}
891
892#if defined(OS_WIN)
893int EventSenderBindings::WmKeyDown() const {
894 if (sender_)
895 return sender_->wm_key_down();
896 return 0;
897}
898
899void EventSenderBindings::SetWmKeyDown(int key_down) {
900 if (sender_)
901 sender_->set_wm_key_down(key_down);
902}
903
904int EventSenderBindings::WmKeyUp() const {
905 if (sender_)
906 return sender_->wm_key_up();
907 return 0;
908}
909
910void EventSenderBindings::SetWmKeyUp(int key_up) {
911 if (sender_)
912 sender_->set_wm_key_up(key_up);
913}
914
915int EventSenderBindings::WmChar() const {
916 if (sender_)
917 return sender_->wm_char();
918 return 0;
919}
920
921void EventSenderBindings::SetWmChar(int wm_char) {
922 if (sender_)
923 sender_->set_wm_char(wm_char);
924}
925
926int EventSenderBindings::WmDeadChar() const {
927 if (sender_)
928 return sender_->wm_dead_char();
929 return 0;
930}
931
932void EventSenderBindings::SetWmDeadChar(int dead_char) {
933 if (sender_)
934 sender_->set_wm_dead_char(dead_char);
935}
936
937int EventSenderBindings::WmSysKeyDown() const {
938 if (sender_)
939 return sender_->wm_sys_key_down();
940 return 0;
941}
942
943void EventSenderBindings::SetWmSysKeyDown(int key_down) {
944 if (sender_)
945 sender_->set_wm_sys_key_down(key_down);
946}
947
948int EventSenderBindings::WmSysKeyUp() const {
949 if (sender_)
950 return sender_->wm_sys_key_up();
951 return 0;
952}
953
954void EventSenderBindings::SetWmSysKeyUp(int key_up) {
955 if (sender_)
956 sender_->set_wm_sys_key_up(key_up);
957}
958
959int EventSenderBindings::WmSysChar() const {
960 if (sender_)
961 return sender_->wm_sys_char();
962 return 0;
963}
964
965void EventSenderBindings::SetWmSysChar(int sys_char) {
966 if (sender_)
967 sender_->set_wm_sys_char(sys_char);
968}
969
970int EventSenderBindings::WmSysDeadChar() const {
971 if (sender_)
972 return sender_->wm_sys_dead_char();
973 return 0;
974}
975
976void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
977 if (sender_)
978 sender_->set_wm_sys_dead_char(sys_dead_char);
979}
980#endif
981
982// EventSender -----------------------------------------------------------------
983
984WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
985
986WebPoint EventSender::last_mouse_pos_;
987
988WebMouseEvent::Button EventSender::last_button_type_ =
989 WebMouseEvent::ButtonNone;
990
991EventSender::SavedEvent::SavedEvent()
992 : type(TYPE_UNSPECIFIED),
993 button_type(WebMouseEvent::ButtonNone),
994 milliseconds(0),
995 modifiers(0) {}
996
997EventSender::EventSender(WebTestRunner::TestInterfaces* interfaces)
998 : interfaces_(interfaces),
999 delegate_(NULL),
1000 view_(NULL),
1001 force_layout_on_events_(false),
1002 is_drag_mode_(true),
1003 touch_modifiers_(0),
1004 replaying_saved_events_(false),
1005 current_drag_effects_allowed_(blink::WebDragOperationNone),
1006 last_click_time_sec_(0),
1007 current_drag_effect_(blink::WebDragOperationNone),
1008 time_offset_ms_(0),
1009 click_count_(0),
1010#if defined(OS_WIN)
1011 wm_key_down_(0),
1012 wm_key_up_(0),
1013 wm_char_(0),
1014 wm_dead_char_(0),
1015 wm_sys_key_down_(0),
1016 wm_sys_key_up_(0),
1017 wm_sys_char_(0),
1018 wm_sys_dead_char_(0),
1019#endif
1020 weak_factory_(this) {}
1021
1022EventSender::~EventSender() {}
1023
1024void EventSender::Reset() {
1025 DCHECK(current_drag_data_.isNull());
1026 current_drag_data_.reset();
1027 current_drag_effect_ = blink::WebDragOperationNone;
1028 current_drag_effects_allowed_ = blink::WebDragOperationNone;
1029 if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
1030 view_->mouseCaptureLost();
1031 pressed_button_ = WebMouseEvent::ButtonNone;
1032 is_drag_mode_ = true;
1033 force_layout_on_events_ = true;
1034
1035#if defined(OS_WIN)
1036 wm_key_down_ = WM_KEYDOWN;
1037 wm_key_up_ = WM_KEYUP;
1038 wm_char_ = WM_CHAR;
1039 wm_dead_char_ = WM_DEADCHAR;
1040 wm_sys_key_down_ = WM_SYSKEYDOWN;
1041 wm_sys_key_up_ = WM_SYSKEYUP;
1042 wm_sys_char_ = WM_SYSCHAR;
1043 wm_sys_dead_char_ = WM_SYSDEADCHAR;
1044#endif
1045
1046 last_mouse_pos_ = WebPoint(0, 0);
1047 last_click_time_sec_ = 0;
1048 last_click_pos_ = WebPoint(0, 0);
1049 last_button_type_ = WebMouseEvent::ButtonNone;
1050 touch_points_.clear();
[email protected]644616d2014-03-27 16:14:471051 last_context_menu_data_.reset();
[email protected]3db130e2014-03-27 08:14:481052 task_list_.revokeAll();
1053 current_gesture_location_ = WebPoint(0, 0);
1054 mouse_event_queue_.clear();
1055
1056 time_offset_ms_ = 0;
1057 click_count_ = 0;
1058}
1059
1060void EventSender::Install(WebFrame* frame) {
1061 EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
1062}
1063
1064void EventSender::SetDelegate(WebTestRunner::WebTestDelegate* delegate) {
1065 delegate_ = delegate;
1066}
1067
1068void EventSender::SetWebView(WebView* view) {
1069 view_ = view;
1070}
1071
1072void EventSender::SetContextMenuData(const WebContextMenuData& data) {
1073 last_context_menu_data_.reset(new WebContextMenuData(data));
1074}
1075
1076void EventSender::DoDragDrop(const WebDragData& drag_data,
1077 WebDragOperationsMask mask) {
1078 WebMouseEvent event;
1079 InitMouseEvent(WebInputEvent::MouseDown,
1080 pressed_button_,
1081 last_mouse_pos_,
1082 GetCurrentEventTimeSec(),
1083 click_count_,
1084 0,
1085 &event);
1086 WebPoint client_point(event.x, event.y);
1087 WebPoint screen_point(event.globalX, event.globalY);
1088 current_drag_data_ = drag_data;
1089 current_drag_effects_allowed_ = mask;
1090 current_drag_effect_ = view_->dragTargetDragEnter(
1091 drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
1092
1093 // Finish processing events.
1094 ReplaySavedEvents();
1095}
1096
1097void EventSender::MouseDown(int button_number, int modifiers) {
1098 if (force_layout_on_events_)
1099 view_->layout();
1100
1101 DCHECK_NE(-1, button_number);
1102
1103 WebMouseEvent::Button button_type =
1104 GetButtonTypeFromButtonNumber(button_number);
1105
1106 UpdateClickCountForButton(button_type);
1107
1108 pressed_button_ = button_type;
1109
1110 WebMouseEvent event;
1111 InitMouseEvent(WebInputEvent::MouseDown,
1112 button_type,
1113 last_mouse_pos_,
1114 GetCurrentEventTimeSec(),
1115 click_count_,
1116 modifiers,
1117 &event);
1118 view_->handleInputEvent(event);
1119}
1120
1121void EventSender::MouseUp(int button_number, int modifiers) {
1122 if (force_layout_on_events_)
1123 view_->layout();
1124
1125 DCHECK_NE(-1, button_number);
1126
1127 WebMouseEvent::Button button_type =
1128 GetButtonTypeFromButtonNumber(button_number);
1129
1130 if (is_drag_mode_ && !replaying_saved_events_) {
1131 SavedEvent saved_event;
1132 saved_event.type = SavedEvent::TYPE_MOUSE_UP;
1133 saved_event.button_type = button_type;
1134 saved_event.modifiers = modifiers;
1135 mouse_event_queue_.push_back(saved_event);
1136 ReplaySavedEvents();
1137 } else {
1138 WebMouseEvent event;
1139 InitMouseEvent(WebInputEvent::MouseUp,
1140 button_type,
1141 last_mouse_pos_,
1142 GetCurrentEventTimeSec(),
1143 click_count_,
1144 modifiers,
1145 &event);
1146 DoMouseUp(event);
1147 }
1148}
1149
1150void EventSender::KeyDown(const std::string& code_str,
1151 int modifiers,
1152 KeyLocationCode location) {
1153 // FIXME: I'm not exactly sure how we should convert the string to a key
1154 // event. This seems to work in the cases I tested.
1155 // FIXME: Should we also generate a KEY_UP?
1156
1157 bool generate_char = false;
1158
1159 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
1160 // Windows uses \r for "Enter".
1161 int code = 0;
1162 int text = 0;
1163 bool needs_shift_key_modifier = false;
1164
1165 if ("\n" == code_str) {
1166 generate_char = true;
[email protected]f423182e2014-04-05 08:02:181167 text = code = VKEY_RETURN;
[email protected]3db130e2014-03-27 08:14:481168 } else if ("rightArrow" == code_str) {
[email protected]f423182e2014-04-05 08:02:181169 code = VKEY_RIGHT;
[email protected]3db130e2014-03-27 08:14:481170 } else if ("downArrow" == code_str) {
[email protected]f423182e2014-04-05 08:02:181171 code = VKEY_DOWN;
[email protected]3db130e2014-03-27 08:14:481172 } else if ("leftArrow" == code_str) {
[email protected]f423182e2014-04-05 08:02:181173 code = VKEY_LEFT;
[email protected]3db130e2014-03-27 08:14:481174 } else if ("upArrow" == code_str) {
[email protected]f423182e2014-04-05 08:02:181175 code = VKEY_UP;
[email protected]3db130e2014-03-27 08:14:481176 } else if ("insert" == code_str) {
[email protected]f423182e2014-04-05 08:02:181177 code = VKEY_INSERT;
[email protected]3db130e2014-03-27 08:14:481178 } else if ("delete" == code_str) {
[email protected]f423182e2014-04-05 08:02:181179 code = VKEY_DELETE;
[email protected]3db130e2014-03-27 08:14:481180 } else if ("pageUp" == code_str) {
[email protected]f423182e2014-04-05 08:02:181181 code = VKEY_PRIOR;
[email protected]3db130e2014-03-27 08:14:481182 } else if ("pageDown" == code_str) {
[email protected]f423182e2014-04-05 08:02:181183 code = VKEY_NEXT;
[email protected]3db130e2014-03-27 08:14:481184 } else if ("home" == code_str) {
[email protected]f423182e2014-04-05 08:02:181185 code = VKEY_HOME;
[email protected]3db130e2014-03-27 08:14:481186 } else if ("end" == code_str) {
[email protected]f423182e2014-04-05 08:02:181187 code = VKEY_END;
[email protected]3db130e2014-03-27 08:14:481188 } else if ("printScreen" == code_str) {
[email protected]f423182e2014-04-05 08:02:181189 code = VKEY_SNAPSHOT;
[email protected]3db130e2014-03-27 08:14:481190 } else if ("menu" == code_str) {
[email protected]f423182e2014-04-05 08:02:181191 code = VKEY_APPS;
[email protected]3db130e2014-03-27 08:14:481192 } else if ("leftControl" == code_str) {
[email protected]f423182e2014-04-05 08:02:181193 code = VKEY_LCONTROL;
[email protected]3db130e2014-03-27 08:14:481194 } else if ("rightControl" == code_str) {
[email protected]f423182e2014-04-05 08:02:181195 code = VKEY_RCONTROL;
[email protected]3db130e2014-03-27 08:14:481196 } else if ("leftShift" == code_str) {
[email protected]f423182e2014-04-05 08:02:181197 code = VKEY_LSHIFT;
[email protected]3db130e2014-03-27 08:14:481198 } else if ("rightShift" == code_str) {
[email protected]f423182e2014-04-05 08:02:181199 code = VKEY_RSHIFT;
[email protected]3db130e2014-03-27 08:14:481200 } else if ("leftAlt" == code_str) {
[email protected]f423182e2014-04-05 08:02:181201 code = VKEY_LMENU;
[email protected]3db130e2014-03-27 08:14:481202 } else if ("rightAlt" == code_str) {
[email protected]f423182e2014-04-05 08:02:181203 code = VKEY_RMENU;
[email protected]3db130e2014-03-27 08:14:481204 } else if ("numLock" == code_str) {
[email protected]f423182e2014-04-05 08:02:181205 code = VKEY_NUMLOCK;
[email protected]3db130e2014-03-27 08:14:481206 } else {
1207 // Compare the input string with the function-key names defined by the
1208 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
1209 // name, set its key code.
1210 for (int i = 1; i <= 24; ++i) {
1211 std::string function_key_name = base::StringPrintf("F%d", i);
1212 if (function_key_name == code_str) {
[email protected]f423182e2014-04-05 08:02:181213 code = VKEY_F1 + (i - 1);
[email protected]3db130e2014-03-27 08:14:481214 break;
1215 }
1216 }
1217 if (!code) {
1218 WebString web_code_str =
1219 WebString::fromUTF8(code_str.data(), code_str.size());
1220 DCHECK_EQ(1u, web_code_str.length());
1221 text = code = web_code_str.at(0);
1222 needs_shift_key_modifier = NeedsShiftModifier(code);
1223 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
1224 code -= 'a' - 'A';
1225 generate_char = true;
1226 }
1227
1228 if ("(" == code_str) {
1229 code = '9';
1230 needs_shift_key_modifier = true;
1231 }
1232 }
1233
1234 // For one generated keyboard event, we need to generate a keyDown/keyUp
1235 // pair;
1236 // On Windows, we might also need to generate a char event to mimic the
1237 // Windows event flow; on other platforms we create a merged event and test
1238 // the event flow that that platform provides.
1239 WebKeyboardEvent event_down;
1240 event_down.type = WebInputEvent::RawKeyDown;
1241 event_down.modifiers = modifiers;
1242 event_down.windowsKeyCode = code;
1243
[email protected]3db130e2014-03-27 08:14:481244 if (generate_char) {
1245 event_down.text[0] = text;
1246 event_down.unmodifiedText[0] = text;
1247 }
1248
1249 event_down.setKeyIdentifierFromWindowsKeyCode();
1250
[email protected]c997bc42014-04-11 18:25:581251#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID)
[email protected]3db130e2014-03-27 08:14:481252 if (event_down.modifiers != 0)
1253 event_down.isSystemKey = WebInputEventFactory::isSystemKeyEvent(event_down);
1254#endif
1255
1256 if (needs_shift_key_modifier)
1257 event_down.modifiers |= WebInputEvent::ShiftKey;
1258
1259 // See if KeyLocation argument is given.
1260 if (location == DOMKeyLocationNumpad)
1261 event_down.modifiers |= WebInputEvent::IsKeyPad;
1262
1263 WebKeyboardEvent event_up;
1264 event_up = event_down;
1265 event_up.type = WebInputEvent::KeyUp;
1266 // EventSender.m forces a layout here, with at least one
1267 // test (fast/forms/focus-control-to-page.html) relying on this.
1268 if (force_layout_on_events_)
1269 view_->layout();
1270
1271 // In the browser, if a keyboard event corresponds to an editor command,
1272 // the command will be dispatched to the renderer just before dispatching
1273 // the keyboard event, and then it will be executed in the
1274 // RenderView::handleCurrentKeyboardEvent() method.
1275 // We just simulate the same behavior here.
1276 std::string edit_command;
1277 if (GetEditCommand(event_down, &edit_command))
1278 delegate_->setEditCommand(edit_command, "");
1279
1280 view_->handleInputEvent(event_down);
1281
[email protected]f423182e2014-04-05 08:02:181282 if (code == VKEY_ESCAPE && !current_drag_data_.isNull()) {
[email protected]3db130e2014-03-27 08:14:481283 WebMouseEvent event;
1284 InitMouseEvent(WebInputEvent::MouseDown,
1285 pressed_button_,
1286 last_mouse_pos_,
1287 GetCurrentEventTimeSec(),
1288 click_count_,
1289 0,
1290 &event);
1291 FinishDragAndDrop(event, blink::WebDragOperationNone);
1292 }
1293
1294 delegate_->clearEditCommand();
1295
1296 if (generate_char) {
1297 WebKeyboardEvent event_char = event_up;
1298 event_char.type = WebInputEvent::Char;
1299 event_char.keyIdentifier[0] = '\0';
1300 view_->handleInputEvent(event_char);
1301 }
1302
1303 view_->handleInputEvent(event_up);
1304}
1305
1306void EventSender::EnableDOMUIEventLogging() {}
1307
1308void EventSender::FireKeyboardEventsToElement() {}
1309
1310void EventSender::ClearKillRing() {}
1311
1312std::vector<std::string> EventSender::ContextClick() {
1313 if (force_layout_on_events_) {
1314 view_->layout();
1315 }
1316
1317 UpdateClickCountForButton(WebMouseEvent::ButtonRight);
1318
1319 // Clears last context menu data because we need to know if the context menu
1320 // be requested after following mouse events.
1321 last_context_menu_data_.reset();
1322
1323 // Generate right mouse down and up.
1324 WebMouseEvent event;
1325 // This is a hack to work around only allowing a single pressed button since
1326 // we want to test the case where both the left and right mouse buttons are
1327 // pressed.
1328 if (pressed_button_ == WebMouseEvent::ButtonNone) {
1329 pressed_button_ = WebMouseEvent::ButtonRight;
1330 }
1331 InitMouseEvent(WebInputEvent::MouseDown,
1332 WebMouseEvent::ButtonRight,
1333 last_mouse_pos_,
1334 GetCurrentEventTimeSec(),
1335 click_count_,
1336 0,
1337 &event);
1338 view_->handleInputEvent(event);
1339
1340#if defined(OS_WIN)
1341 InitMouseEvent(WebInputEvent::MouseUp,
1342 WebMouseEvent::ButtonRight,
1343 last_mouse_pos_,
1344 GetCurrentEventTimeSec(),
1345 click_count_,
1346 0,
1347 &event);
1348 view_->handleInputEvent(event);
1349
1350 pressed_button_= WebMouseEvent::ButtonNone;
1351#endif
1352
1353 return MakeMenuItemStringsFor(last_context_menu_data_.release(), delegate_);
1354}
1355
1356void EventSender::TextZoomIn() {
1357 view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
1358}
1359
1360void EventSender::TextZoomOut() {
1361 view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
1362}
1363
1364void EventSender::ZoomPageIn() {
1365 const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
1366 interfaces_->windowList();
1367
1368 for (size_t i = 0; i < window_list.size(); ++i) {
1369 window_list.at(i)->webView()->setZoomLevel(
1370 window_list.at(i)->webView()->zoomLevel() + 1);
1371 }
1372}
1373
1374void EventSender::ZoomPageOut() {
1375 const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
1376 interfaces_->windowList();
1377
1378 for (size_t i = 0; i < window_list.size(); ++i) {
1379 window_list.at(i)->webView()->setZoomLevel(
1380 window_list.at(i)->webView()->zoomLevel() - 1);
1381 }
1382}
1383
1384void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
1385 view_->setPageScaleFactorLimits(scale_factor, scale_factor);
1386 view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
1387}
1388
1389void EventSender::ClearTouchPoints() {
1390 touch_points_.clear();
1391}
1392
1393void EventSender::ReleaseTouchPoint(unsigned index) {
1394 DCHECK_LT(index, touch_points_.size());
1395
1396 WebTouchPoint* touch_point = &touch_points_[index];
1397 touch_point->state = WebTouchPoint::StateReleased;
1398}
1399
1400void EventSender::UpdateTouchPoint(unsigned index, int x, int y) {
1401 DCHECK_LT(index, touch_points_.size());
1402
1403 WebTouchPoint* touch_point = &touch_points_[index];
1404 touch_point->state = WebTouchPoint::StateMoved;
1405 touch_point->position = WebFloatPoint(x, y);
1406 touch_point->screenPosition = touch_point->position;
1407}
1408
1409void EventSender::CancelTouchPoint(unsigned index) {
1410 DCHECK_LT(index, touch_points_.size());
1411
1412 WebTouchPoint* touch_point = &touch_points_[index];
1413 touch_point->state = WebTouchPoint::StateCancelled;
1414}
1415
1416void EventSender::SetTouchModifier(const std::string& key_name,
1417 bool set_mask) {
1418 int mask = 0;
1419 if (key_name == "shift")
1420 mask = WebInputEvent::ShiftKey;
1421 else if (key_name == "alt")
1422 mask = WebInputEvent::AltKey;
1423 else if (key_name == "ctrl")
1424 mask = WebInputEvent::ControlKey;
1425 else if (key_name == "meta")
1426 mask = WebInputEvent::MetaKey;
1427
1428 if (set_mask)
1429 touch_modifiers_ |= mask;
1430 else
1431 touch_modifiers_ &= ~mask;
1432}
1433
1434void EventSender::DumpFilenameBeingDragged() {
1435 WebString filename;
1436 WebVector<WebDragData::Item> items = current_drag_data_.items();
1437 for (size_t i = 0; i < items.size(); ++i) {
1438 if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
1439 filename = items[i].title;
1440 break;
1441 }
1442 }
1443 delegate_->printMessage(std::string("Filename being dragged: ") +
1444 filename.utf8().data() + "\n");
1445}
1446
1447void EventSender::GestureFlingCancel() {
1448 WebGestureEvent event;
1449 event.type = WebInputEvent::GestureFlingCancel;
1450 event.timeStampSeconds = GetCurrentEventTimeSec();
1451
1452 if (force_layout_on_events_)
1453 view_->layout();
1454
1455 view_->handleInputEvent(event);
1456}
1457
1458void EventSender::GestureFlingStart(float x,
1459 float y,
1460 float velocity_x,
1461 float velocity_y) {
1462 WebGestureEvent event;
1463 event.type = WebInputEvent::GestureFlingStart;
1464
1465 event.x = x;
1466 event.y = y;
1467 event.globalX = event.x;
1468 event.globalY = event.y;
1469
1470 event.data.flingStart.velocityX = velocity_x;
1471 event.data.flingStart.velocityY = velocity_y;
1472 event.timeStampSeconds = GetCurrentEventTimeSec();
1473
1474 if (force_layout_on_events_)
1475 view_->layout();
1476
1477 view_->handleInputEvent(event);
1478}
1479
1480void EventSender::GestureScrollFirstPoint(int x, int y) {
1481 current_gesture_location_ = WebPoint(x, y);
1482}
1483
1484void EventSender::TouchStart() {
1485 SendCurrentTouchEvent(WebInputEvent::TouchStart);
1486}
1487
1488void EventSender::TouchMove() {
1489 SendCurrentTouchEvent(WebInputEvent::TouchMove);
1490}
1491
1492void EventSender::TouchCancel() {
1493 SendCurrentTouchEvent(WebInputEvent::TouchCancel);
1494}
1495
1496void EventSender::TouchEnd() {
1497 SendCurrentTouchEvent(WebInputEvent::TouchEnd);
1498}
1499
1500void EventSender::LeapForward(int milliseconds) {
1501 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1502 !replaying_saved_events_) {
1503 SavedEvent saved_event;
1504 saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
1505 saved_event.milliseconds = milliseconds;
1506 mouse_event_queue_.push_back(saved_event);
1507 } else {
1508 DoLeapForward(milliseconds);
1509 }
1510}
1511
1512void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
1513 current_drag_data_.initialize();
1514 WebVector<WebString> absolute_filenames(files.size());
1515 for (size_t i = 0; i < files.size(); ++i) {
1516 WebDragData::Item item;
1517 item.storageType = WebDragData::Item::StorageTypeFilename;
1518 item.filenameData = delegate_->getAbsoluteWebStringFromUTF8Path(files[i]);
1519 current_drag_data_.addItem(item);
1520 absolute_filenames[i] = item.filenameData;
1521 }
1522 current_drag_data_.setFilesystemId(
1523 delegate_->registerIsolatedFileSystem(absolute_filenames));
1524 current_drag_effects_allowed_ = blink::WebDragOperationCopy;
1525
1526 // Provide a drag source.
1527 view_->dragTargetDragEnter(current_drag_data_,
1528 last_mouse_pos_,
1529 last_mouse_pos_,
1530 current_drag_effects_allowed_,
1531 0);
1532 // |is_drag_mode_| saves events and then replays them later. We don't
1533 // need/want that.
1534 is_drag_mode_ = false;
1535
1536 // Make the rest of eventSender think a drag is in progress.
1537 pressed_button_ = WebMouseEvent::ButtonLeft;
1538}
1539
1540void EventSender::AddTouchPoint(gin::Arguments* args) {
[email protected]f53eba122014-04-16 11:30:011541 double x;
1542 double y;
[email protected]3db130e2014-03-27 08:14:481543 args->GetNext(&x);
1544 args->GetNext(&y);
1545
1546 WebTouchPoint touch_point;
1547 touch_point.state = WebTouchPoint::StatePressed;
[email protected]f53eba122014-04-16 11:30:011548 touch_point.position = WebFloatPoint(static_cast<int>(x),
1549 static_cast<int>(y));
[email protected]3db130e2014-03-27 08:14:481550 touch_point.screenPosition = touch_point.position;
1551
1552 if (!args->PeekNext().IsEmpty()) {
[email protected]f53eba122014-04-16 11:30:011553 double radius_x;
[email protected]3db130e2014-03-27 08:14:481554 if (!args->GetNext(&radius_x)) {
1555 args->ThrowError();
1556 return;
1557 }
1558
[email protected]f53eba122014-04-16 11:30:011559 double radius_y = radius_x;
[email protected]3db130e2014-03-27 08:14:481560 if (!args->PeekNext().IsEmpty()) {
1561 if (!args->GetNext(&radius_y)) {
1562 args->ThrowError();
1563 return;
1564 }
1565 }
1566
[email protected]f53eba122014-04-16 11:30:011567 touch_point.radiusX = static_cast<int>(radius_x);
1568 touch_point.radiusY = static_cast<int>(radius_y);
[email protected]3db130e2014-03-27 08:14:481569 }
1570
1571 int lowest_id = 0;
1572 for (size_t i = 0; i < touch_points_.size(); i++) {
1573 if (touch_points_[i].id == lowest_id)
1574 lowest_id++;
1575 }
1576 touch_point.id = lowest_id;
1577 touch_points_.push_back(touch_point);
1578}
1579
1580void EventSender::MouseDragBegin() {
1581 WebMouseWheelEvent event;
1582 InitMouseEvent(WebInputEvent::MouseWheel,
1583 WebMouseEvent::ButtonNone,
1584 last_mouse_pos_,
1585 GetCurrentEventTimeSec(),
1586 click_count_,
1587 0,
1588 &event);
1589 event.phase = WebMouseWheelEvent::PhaseBegan;
1590 event.hasPreciseScrollingDeltas = true;
1591 view_->handleInputEvent(event);
1592}
1593
1594void EventSender::MouseDragEnd() {
1595 WebMouseWheelEvent event;
1596 InitMouseEvent(WebInputEvent::MouseWheel,
1597 WebMouseEvent::ButtonNone,
1598 last_mouse_pos_,
1599 GetCurrentEventTimeSec(),
1600 click_count_,
1601 0,
1602 &event);
1603 event.phase = WebMouseWheelEvent::PhaseEnded;
1604 event.hasPreciseScrollingDeltas = true;
1605 view_->handleInputEvent(event);
1606}
1607
1608void EventSender::MouseMomentumBegin() {
1609 WebMouseWheelEvent event;
1610 InitMouseEvent(WebInputEvent::MouseWheel,
1611 WebMouseEvent::ButtonNone,
1612 last_mouse_pos_,
1613 GetCurrentEventTimeSec(),
1614 click_count_,
1615 0,
1616 &event);
1617 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1618 event.hasPreciseScrollingDeltas = true;
1619 view_->handleInputEvent(event);
1620}
1621
1622void EventSender::GestureScrollBegin(gin::Arguments* args) {
1623 GestureEvent(WebInputEvent::GestureScrollBegin, args);
1624}
1625
1626void EventSender::GestureScrollEnd(gin::Arguments* args) {
1627 GestureEvent(WebInputEvent::GestureScrollEnd, args);
1628}
1629
1630void EventSender::GestureScrollUpdate(gin::Arguments* args) {
1631 GestureEvent(WebInputEvent::GestureScrollUpdate, args);
1632}
1633
1634void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
1635 GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
1636}
1637
1638void EventSender::GestureTap(gin::Arguments* args) {
1639 GestureEvent(WebInputEvent::GestureTap, args);
1640}
1641
1642void EventSender::GestureTapDown(gin::Arguments* args) {
1643 GestureEvent(WebInputEvent::GestureTapDown, args);
1644}
1645
1646void EventSender::GestureShowPress(gin::Arguments* args) {
1647 GestureEvent(WebInputEvent::GestureShowPress, args);
1648}
1649
1650void EventSender::GestureTapCancel(gin::Arguments* args) {
1651 GestureEvent(WebInputEvent::GestureTapCancel, args);
1652}
1653
1654void EventSender::GestureLongPress(gin::Arguments* args) {
1655 GestureEvent(WebInputEvent::GestureLongPress, args);
1656}
1657
1658void EventSender::GestureLongTap(gin::Arguments* args) {
1659 GestureEvent(WebInputEvent::GestureLongTap, args);
1660}
1661
1662void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
1663 GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
1664}
1665
1666void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
1667 WebMouseWheelEvent event;
1668 InitMouseWheelEvent(args, true, &event);
1669 view_->handleInputEvent(event);
1670}
1671
1672void EventSender::DispatchMessage(int msg, int wparam, int lparam) {
1673#if defined(OS_WIN)
1674 // WebKit's version of this function stuffs a MSG struct and uses
1675 // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
1676 // doesn't need to receive the DeadChar and SysDeadChar messages.
1677 if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
1678 return;
1679
1680 if (force_layout_on_events_)
1681 view_->layout();
1682
1683 view_->handleInputEvent(
1684 WebInputEventFactory::keyboardEvent(0, msg, wparam, lparam));
1685#endif
1686}
1687
1688void EventSender::MouseMoveTo(gin::Arguments* args) {
1689 if (force_layout_on_events_)
1690 view_->layout();
1691
[email protected]f53eba122014-04-16 11:30:011692 double x;
1693 double y;
[email protected]3db130e2014-03-27 08:14:481694 args->GetNext(&x);
1695 args->GetNext(&y);
[email protected]f53eba122014-04-16 11:30:011696 WebPoint mouse_pos(static_cast<int>(x), static_cast<int>(y));
[email protected]3db130e2014-03-27 08:14:481697
1698 int modifiers = 0;
1699 if (!args->PeekNext().IsEmpty())
1700 modifiers = GetKeyModifiersFromV8(args->PeekNext());
1701
1702 if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
1703 !replaying_saved_events_) {
1704 SavedEvent saved_event;
1705 saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
1706 saved_event.pos = mouse_pos;
1707 saved_event.modifiers = modifiers;
1708 mouse_event_queue_.push_back(saved_event);
1709 } else {
1710 WebMouseEvent event;
1711 InitMouseEvent(WebInputEvent::MouseMove,
1712 pressed_button_,
1713 mouse_pos,
1714 GetCurrentEventTimeSec(),
1715 click_count_,
1716 modifiers,
1717 &event);
1718 DoMouseMove(event);
1719 }
1720}
1721
1722void EventSender::MouseScrollBy(gin::Arguments* args) {
1723 WebMouseWheelEvent event;
1724 InitMouseWheelEvent(args, false, &event);
1725 view_->handleInputEvent(event);
1726}
1727
1728void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
1729 WebMouseWheelEvent event;
1730 InitMouseWheelEvent(args, true, &event);
1731 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1732 event.hasPreciseScrollingDeltas = true;
1733 view_->handleInputEvent(event);
1734}
1735
1736void EventSender::MouseMomentumEnd() {
1737 WebMouseWheelEvent event;
1738 InitMouseEvent(WebInputEvent::MouseWheel,
1739 WebMouseEvent::ButtonNone,
1740 last_mouse_pos_,
1741 GetCurrentEventTimeSec(),
1742 click_count_,
1743 0,
1744 &event);
1745 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1746 event.hasPreciseScrollingDeltas = true;
1747 view_->handleInputEvent(event);
1748}
1749
1750void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
1751 delegate_->postTask(new MouseDownTask(this, button_number, modifiers));
1752 delegate_->postTask(new MouseUpTask(this, button_number, modifiers));
1753}
1754
1755void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
1756 int modifiers,
1757 KeyLocationCode location) {
1758 delegate_->postTask(new KeyDownTask(this, code_str, modifiers, location));
1759}
1760
1761double EventSender::GetCurrentEventTimeSec() {
1762 return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
1763}
1764
1765void EventSender::DoLeapForward(int milliseconds) {
1766 time_offset_ms_ += milliseconds;
1767}
1768
1769void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
1770 DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
1771 touch_points_.size());
1772 if (force_layout_on_events_)
1773 view_->layout();
1774
1775 WebTouchEvent touch_event;
1776 touch_event.type = type;
1777 touch_event.modifiers = touch_modifiers_;
1778 touch_event.timeStampSeconds = GetCurrentEventTimeSec();
1779 touch_event.touchesLength = touch_points_.size();
1780 for (size_t i = 0; i < touch_points_.size(); ++i)
1781 touch_event.touches[i] = touch_points_[i];
1782 view_->handleInputEvent(touch_event);
1783
1784 for (size_t i = 0; i < touch_points_.size(); ++i) {
1785 WebTouchPoint* touch_point = &touch_points_[i];
1786 if (touch_point->state == WebTouchPoint::StateReleased) {
1787 touch_points_.erase(touch_points_.begin() + i);
1788 --i;
1789 } else
1790 touch_point->state = WebTouchPoint::StateStationary;
1791 }
1792}
1793
1794void EventSender::GestureEvent(WebInputEvent::Type type,
1795 gin::Arguments* args) {
1796 double x;
1797 double y;
1798 args->GetNext(&x);
1799 args->GetNext(&y);
1800 WebPoint point(x, y);
1801
1802 WebGestureEvent event;
1803 event.type = type;
1804
1805 switch (type) {
1806 case WebInputEvent::GestureScrollUpdate:
1807 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
1808 event.data.scrollUpdate.deltaX = static_cast<float>(x);
1809 event.data.scrollUpdate.deltaY = static_cast<float>(y);
1810 event.x = current_gesture_location_.x;
1811 event.y = current_gesture_location_.y;
1812 current_gesture_location_.x =
1813 current_gesture_location_.x + event.data.scrollUpdate.deltaX;
1814 current_gesture_location_.y =
1815 current_gesture_location_.y + event.data.scrollUpdate.deltaY;
1816 break;
1817 case WebInputEvent::GestureScrollBegin:
1818 current_gesture_location_ = WebPoint(point.x, point.y);
1819 event.x = current_gesture_location_.x;
1820 event.y = current_gesture_location_.y;
1821 break;
1822 case WebInputEvent::GestureScrollEnd:
1823 case WebInputEvent::GestureFlingStart:
1824 event.x = current_gesture_location_.x;
1825 event.y = current_gesture_location_.y;
1826 break;
1827 case WebInputEvent::GestureTap:
1828 if (!args->PeekNext().IsEmpty()) {
1829 float tap_count;
1830 if (!args->GetNext(&tap_count)) {
1831 args->ThrowError();
1832 return;
1833 }
1834 event.data.tap.tapCount = tap_count;
1835 } else {
1836 event.data.tap.tapCount = 1;
1837 }
1838
1839 event.x = point.x;
1840 event.y = point.y;
1841 break;
1842 case WebInputEvent::GestureTapUnconfirmed:
1843 if (!args->PeekNext().IsEmpty()) {
1844 float tap_count;
1845 if (!args->GetNext(&tap_count)) {
1846 args->ThrowError();
1847 return;
1848 }
1849 event.data.tap.tapCount = tap_count;
1850 } else {
1851 event.data.tap.tapCount = 1;
1852 }
1853 event.x = point.x;
1854 event.y = point.y;
1855 break;
1856 case WebInputEvent::GestureTapDown:
1857 event.x = point.x;
1858 event.y = point.y;
1859 if (!args->PeekNext().IsEmpty()) {
1860 float width;
1861 if (!args->GetNext(&width)) {
1862 args->ThrowError();
1863 return;
1864 }
1865 event.data.tapDown.width = width;
1866 }
1867 if (!args->PeekNext().IsEmpty()) {
1868 float height;
1869 if (!args->GetNext(&height)) {
1870 args->ThrowError();
1871 return;
1872 }
1873 event.data.tapDown.height = height;
1874 }
1875 break;
1876 case WebInputEvent::GestureShowPress:
1877 event.x = point.x;
1878 event.y = point.y;
1879 if (!args->PeekNext().IsEmpty()) {
1880 float width;
1881 if (!args->GetNext(&width)) {
1882 args->ThrowError();
1883 return;
1884 }
1885 event.data.showPress.width = width;
1886 if (!args->PeekNext().IsEmpty()) {
1887 float height;
1888 if (!args->GetNext(&height)) {
1889 args->ThrowError();
1890 return;
1891 }
1892 event.data.showPress.height = height;
1893 }
1894 }
1895 break;
1896 case WebInputEvent::GestureTapCancel:
1897 event.x = point.x;
1898 event.y = point.y;
1899 break;
1900 case WebInputEvent::GestureLongPress:
1901 event.x = point.x;
1902 event.y = point.y;
1903 if (!args->PeekNext().IsEmpty()) {
1904 float width;
1905 if (!args->GetNext(&width)) {
1906 args->ThrowError();
1907 return;
1908 }
1909 event.data.longPress.width = width;
1910 if (!args->PeekNext().IsEmpty()) {
1911 float height;
1912 if (!args->GetNext(&height)) {
1913 args->ThrowError();
1914 return;
1915 }
1916 event.data.longPress.height = height;
1917 }
1918 }
1919 break;
1920 case WebInputEvent::GestureLongTap:
1921 event.x = point.x;
1922 event.y = point.y;
1923 if (!args->PeekNext().IsEmpty()) {
1924 float width;
1925 if (!args->GetNext(&width)) {
1926 args->ThrowError();
1927 return;
1928 }
1929 event.data.longPress.width = width;
1930 if (!args->PeekNext().IsEmpty()) {
1931 float height;
1932 if (!args->GetNext(&height)) {
1933 args->ThrowError();
1934 return;
1935 }
1936 event.data.longPress.height = height;
1937 }
1938 }
1939 break;
1940 case WebInputEvent::GestureTwoFingerTap:
1941 event.x = point.x;
1942 event.y = point.y;
1943 if (!args->PeekNext().IsEmpty()) {
1944 float first_finger_width;
1945 if (!args->GetNext(&first_finger_width)) {
1946 args->ThrowError();
1947 return;
1948 }
1949 event.data.twoFingerTap.firstFingerWidth = first_finger_width;
1950 if (!args->PeekNext().IsEmpty()) {
1951 float first_finger_height;
1952 if (!args->GetNext(&first_finger_height)) {
1953 args->ThrowError();
1954 return;
1955 }
1956 event.data.twoFingerTap.firstFingerHeight = first_finger_height;
1957 }
1958 }
1959 break;
1960 default:
1961 NOTREACHED();
1962 }
1963
1964 event.globalX = event.x;
1965 event.globalY = event.y;
1966 event.timeStampSeconds = GetCurrentEventTimeSec();
1967
1968 if (force_layout_on_events_)
1969 view_->layout();
1970
1971 view_->handleInputEvent(event);
1972
1973 // Long press might start a drag drop session. Complete it if so.
1974 if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
1975 WebMouseEvent mouse_event;
1976 InitMouseEvent(WebInputEvent::MouseDown,
1977 pressed_button_,
1978 point,
1979 GetCurrentEventTimeSec(),
1980 click_count_,
1981 0,
1982 &mouse_event);
1983
1984 FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
1985 }
1986}
1987
1988void EventSender::UpdateClickCountForButton(
1989 WebMouseEvent::Button button_type) {
1990 if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
1991 kMultipleClickTimeSec) &&
1992 (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
1993 (button_type == last_button_type_)) {
1994 ++click_count_;
1995 } else {
1996 click_count_ = 1;
1997 last_button_type_ = button_type;
1998 }
1999}
2000
2001void EventSender::InitMouseWheelEvent(gin::Arguments* args,
2002 bool continuous,
2003 WebMouseWheelEvent* event) {
2004 // Force a layout here just to make sure every position has been
2005 // determined before we send events (as well as all the other methods
2006 // that send an event do).
2007 if (force_layout_on_events_)
2008 view_->layout();
2009
2010 double horizontal;
2011 if (!args->GetNext(&horizontal)) {
2012 args->ThrowError();
2013 return;
2014 }
2015 double vertical;
2016 if (!args->GetNext(&vertical)) {
2017 args->ThrowError();
2018 return;
2019 }
2020
2021 bool paged = false;
2022 bool has_precise_scrolling_deltas = false;
2023 int modifiers = 0;
2024 if (!args->PeekNext().IsEmpty()) {
2025 args->GetNext(&paged);
2026 if (!args->PeekNext().IsEmpty()) {
2027 args->GetNext(&has_precise_scrolling_deltas);
2028 if (!args->PeekNext().IsEmpty())
2029 modifiers = GetKeyModifiersFromV8(args->PeekNext());
2030 }
2031 }
2032
2033 InitMouseEvent(WebInputEvent::MouseWheel,
2034 pressed_button_,
2035 last_mouse_pos_,
2036 GetCurrentEventTimeSec(),
2037 click_count_,
2038 modifiers,
2039 event);
2040 event->wheelTicksX = static_cast<float>(horizontal);
2041 event->wheelTicksY = static_cast<float>(vertical);
2042 event->deltaX = event->wheelTicksX;
2043 event->deltaY = event->wheelTicksY;
2044 event->scrollByPage = paged;
2045 event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
2046
2047 if (continuous) {
2048 event->wheelTicksX /= kScrollbarPixelsPerTick;
2049 event->wheelTicksY /= kScrollbarPixelsPerTick;
2050 } else {
2051 event->deltaX *= kScrollbarPixelsPerTick;
2052 event->deltaY *= kScrollbarPixelsPerTick;
2053 }
2054}
2055
2056void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
2057 blink::WebDragOperation drag_effect) {
2058 WebPoint client_point(e.x, e.y);
2059 WebPoint screen_point(e.globalX, e.globalY);
2060 current_drag_effect_ = drag_effect;
2061 if (current_drag_effect_) {
2062 // Specifically pass any keyboard modifiers to the drop method. This allows
2063 // tests to control the drop type (i.e. copy or move).
2064 view_->dragTargetDrop(client_point, screen_point, e.modifiers);
2065 } else {
2066 view_->dragTargetDragLeave();
2067 }
2068 view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
2069 view_->dragSourceSystemDragEnded();
2070
2071 current_drag_data_.reset();
2072}
2073
2074void EventSender::DoMouseUp(const WebMouseEvent& e) {
2075 view_->handleInputEvent(e);
2076
2077 pressed_button_ = WebMouseEvent::ButtonNone;
2078 last_click_time_sec_ = e.timeStampSeconds;
2079 last_click_pos_ = last_mouse_pos_;
2080
2081 // If we're in a drag operation, complete it.
2082 if (current_drag_data_.isNull())
2083 return;
2084
2085 WebPoint client_point(e.x, e.y);
2086 WebPoint screen_point(e.globalX, e.globalY);
2087 FinishDragAndDrop(
2088 e,
2089 view_->dragTargetDragOver(
2090 client_point, screen_point, current_drag_effects_allowed_, 0));
2091}
2092
2093void EventSender::DoMouseMove(const WebMouseEvent& e) {
2094 last_mouse_pos_ = WebPoint(e.x, e.y);
2095
2096 view_->handleInputEvent(e);
2097
2098 if (pressed_button_ == WebMouseEvent::ButtonNone ||
2099 current_drag_data_.isNull()) {
2100 return;
2101 }
2102
2103 WebPoint client_point(e.x, e.y);
2104 WebPoint screen_point(e.globalX, e.globalY);
2105 current_drag_effect_ = view_->dragTargetDragOver(
2106 client_point, screen_point, current_drag_effects_allowed_, 0);
2107}
2108
2109void EventSender::ReplaySavedEvents() {
2110 replaying_saved_events_ = true;
2111 while (!mouse_event_queue_.empty()) {
2112 SavedEvent e = mouse_event_queue_.front();
2113 mouse_event_queue_.pop_front();
2114
2115 switch (e.type) {
2116 case SavedEvent::TYPE_MOUSE_MOVE: {
2117 WebMouseEvent event;
2118 InitMouseEvent(WebInputEvent::MouseMove,
2119 pressed_button_,
2120 e.pos,
2121 GetCurrentEventTimeSec(),
2122 click_count_,
2123 e.modifiers,
2124 &event);
2125 DoMouseMove(event);
2126 break;
2127 }
2128 case SavedEvent::TYPE_LEAP_FORWARD:
2129 DoLeapForward(e.milliseconds);
2130 break;
2131 case SavedEvent::TYPE_MOUSE_UP: {
2132 WebMouseEvent event;
2133 InitMouseEvent(WebInputEvent::MouseUp,
2134 e.button_type,
2135 last_mouse_pos_,
2136 GetCurrentEventTimeSec(),
2137 click_count_,
2138 e.modifiers,
2139 &event);
2140 DoMouseUp(event);
2141 break;
2142 }
2143 default:
2144 NOTREACHED();
2145 }
2146 }
2147
2148 replaying_saved_events_ = false;
2149}
2150
2151} // namespace content