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