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