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