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