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