summaryrefslogtreecommitdiffstats
path: root/content/shell/renderer/test_runner
diff options
context:
space:
mode:
Diffstat (limited to 'content/shell/renderer/test_runner')
-rw-r--r--content/shell/renderer/test_runner/EventSender.cpp1465
-rw-r--r--content/shell/renderer/test_runner/EventSender.h188
-rw-r--r--content/shell/renderer/test_runner/TestInterfaces.cpp18
-rw-r--r--content/shell/renderer/test_runner/TestInterfaces.h6
-rw-r--r--content/shell/renderer/test_runner/WebTestProxy.cpp6
-rw-r--r--content/shell/renderer/test_runner/event_sender.cc2085
-rw-r--r--content/shell/renderer/test_runner/event_sender.h276
7 files changed, 2376 insertions, 1668 deletions
diff --git a/content/shell/renderer/test_runner/EventSender.cpp b/content/shell/renderer/test_runner/EventSender.cpp
deleted file mode 100644
index 3106396..0000000
--- a/content/shell/renderer/test_runner/EventSender.cpp
+++ /dev/null
@@ -1,1465 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains the definition for EventSender.
-//
-// Some notes about drag and drop handling:
-// Windows drag and drop goes through a system call to doDragDrop. At that
-// point, program control is given to Windows which then periodically makes
-// callbacks into the webview. This won't work for layout tests, so instead,
-// we queue up all the mouse move and mouse up events. When the test tries to
-// start a drag (by calling EvenSendingController::doDragDrop), we take the
-// events in the queue and replay them.
-// The behavior of queuing events and replaying them can be disabled by a
-// layout test by setting eventSender.dragMode to false.
-
-#include "content/shell/renderer/test_runner/EventSender.h"
-
-#include <deque>
-
-#include "content/shell/renderer/test_runner/KeyCodeMapping.h"
-#include "content/shell/renderer/test_runner/MockSpellCheck.h"
-#include "content/shell/renderer/test_runner/TestCommon.h"
-#include "content/shell/renderer/test_runner/TestInterfaces.h"
-#include "content/shell/renderer/test_runner/WebTestDelegate.h"
-#include "content/shell/renderer/test_runner/WebTestProxy.h"
-#include "third_party/WebKit/public/platform/WebDragData.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebContextMenuData.h"
-#include "third_party/WebKit/public/web/WebTouchPoint.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-#ifdef WIN32
-#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
-#elif __APPLE__
-#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
-#elif defined(ANDROID)
-#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
-#elif defined(TOOLKIT_GTK)
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
-#endif
-
-// FIXME: layout before each event?
-
-using namespace std;
-using namespace blink;
-
-namespace WebTestRunner {
-
-WebPoint EventSender::lastMousePos;
-WebMouseEvent::Button EventSender::pressedButton = WebMouseEvent::ButtonNone;
-WebMouseEvent::Button EventSender::lastButtonType = WebMouseEvent::ButtonNone;
-
-namespace {
-
-struct SavedEvent {
- enum SavedEventType {
- Unspecified,
- MouseUp,
- MouseMove,
- LeapForward
- };
-
- SavedEventType type;
- WebMouseEvent::Button buttonType; // For MouseUp.
- WebPoint pos; // For MouseMove.
- int milliseconds; // For LeapForward.
- int modifiers;
-
- SavedEvent()
- : type(Unspecified)
- , buttonType(WebMouseEvent::ButtonNone)
- , milliseconds(0)
- , modifiers(0) { }
-};
-
-WebDragData currentDragData;
-WebDragOperation currentDragEffect;
-WebDragOperationsMask currentDragEffectsAllowed;
-bool replayingSavedEvents = false;
-deque<SavedEvent> mouseEventQueue;
-int touchModifiers;
-vector<WebTouchPoint> touchPoints;
-
-// Time and place of the last mouse up event.
-double lastClickTimeSec = 0;
-WebPoint lastClickPos;
-int clickCount = 0;
-
-// maximum distance (in space and time) for a mouse click
-// to register as a double or triple click
-const double multipleClickTimeSec = 1;
-const int multipleClickRadiusPixels = 5;
-
-// How much we should scroll per event - the value here is chosen to
-// match the WebKit impl and layout test results.
-const float scrollbarPixelsPerTick = 40.0f;
-
-inline bool outsideMultiClickRadius(const WebPoint& a, const WebPoint& b)
-{
- return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
- multipleClickRadiusPixels * multipleClickRadiusPixels;
-}
-
-// Used to offset the time the event hander things an event happened. This is
-// done so tests can run without a delay, but bypass checks that are time
-// dependent (e.g., dragging has a timeout vs selection).
-uint32 timeOffsetMs = 0;
-
-double getCurrentEventTimeSec(WebTestDelegate* delegate)
-{
- return (delegate->getCurrentTimeInMillisecond() + timeOffsetMs) / 1000.0;
-}
-
-void advanceEventTime(int32_t deltaMs)
-{
- timeOffsetMs += deltaMs;
-}
-
-void initMouseEvent(WebInputEvent::Type t, WebMouseEvent::Button b, const WebPoint& pos, WebMouseEvent* e, double ts, int modifiers)
-{
- e->type = t;
- e->button = b;
- e->modifiers = modifiers;
- e->x = pos.x;
- e->y = pos.y;
- e->globalX = pos.x;
- e->globalY = pos.y;
- e->timeStampSeconds = ts;
- e->clickCount = clickCount;
-}
-
-int getKeyModifier(const string& modifierName)
-{
- const char* characters = modifierName.c_str();
- if (!strcmp(characters, "ctrlKey")
-#ifndef __APPLE__
- || !strcmp(characters, "addSelectionKey")
-#endif
- ) {
- return WebInputEvent::ControlKey;
- } else if (!strcmp(characters, "shiftKey") || !strcmp(characters, "rangeSelectionKey")) {
- return WebInputEvent::ShiftKey;
- } else if (!strcmp(characters, "altKey")) {
- return WebInputEvent::AltKey;
-#ifdef __APPLE__
- } else if (!strcmp(characters, "metaKey") || !strcmp(characters, "addSelectionKey")) {
- return WebInputEvent::MetaKey;
-#else
- } else if (!strcmp(characters, "metaKey")) {
- return WebInputEvent::MetaKey;
-#endif
- } else if (!strcmp(characters, "autoRepeat")) {
- return WebInputEvent::IsAutoRepeat;
- } else if (!strcmp(characters, "copyKey")) {
-#ifdef __APPLE__
- return WebInputEvent::AltKey;
-#else
- return WebInputEvent::ControlKey;
-#endif
- }
-
- return 0;
-}
-
-int getKeyModifiers(const CppVariant* argument)
-{
- int modifiers = 0;
- if (argument->isObject()) {
- vector<string> modifierNames = argument->toStringVector();
- for (vector<string>::const_iterator i = modifierNames.begin(); i != modifierNames.end(); ++i)
- modifiers |= getKeyModifier(*i);
- } else if (argument->isString()) {
- modifiers |= getKeyModifier(argument->toString());
- }
- return modifiers;
-}
-
-// Get the edit command corresponding to a keyboard event.
-// Returns true if the specified event corresponds to an edit command, the name
-// of the edit command will be stored in |*name|.
-bool getEditCommand(const WebKeyboardEvent& event, string* name)
-{
-#ifdef __APPLE__
- // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
- // modifiers. These key events correspond to some special movement and
- // selection editor commands, and was supposed to be handled in
- // WebKit/chromium/src/EditorClientImpl.cpp. But these keys will be marked
- // as system key, which prevents them from being handled. Thus they must be
- // handled specially.
- if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) != WebKeyboardEvent::MetaKey)
- return false;
-
- switch (event.windowsKeyCode) {
- case VKEY_LEFT:
- *name = "MoveToBeginningOfLine";
- break;
- case VKEY_RIGHT:
- *name = "MoveToEndOfLine";
- break;
- case VKEY_UP:
- *name = "MoveToBeginningOfDocument";
- break;
- case VKEY_DOWN:
- *name = "MoveToEndOfDocument";
- break;
- default:
- return false;
- }
-
- if (event.modifiers & WebKeyboardEvent::ShiftKey)
- name->append("AndModifySelection");
-
- return true;
-#else
- return false;
-#endif
-}
-
-// Key event location code introduced in DOM Level 3.
-// See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
-enum KeyLocationCode {
- DOMKeyLocationStandard = 0x00,
- DOMKeyLocationLeft = 0x01,
- DOMKeyLocationRight = 0x02,
- DOMKeyLocationNumpad = 0x03
-};
-
-}
-
-EventSender::EventSender(TestInterfaces* interfaces)
- : m_testInterfaces(interfaces)
- , m_delegate(0)
-{
- // Initialize the map that associates methods of this class with the names
- // they will use when called by JavaScript. The actual binding of those
- // names to their methods will be done by calling bindToJavaScript() (defined
- // by CppBoundClass, the parent to EventSender).
- bindMethod("addTouchPoint", &EventSender::addTouchPoint);
- bindMethod("beginDragWithFiles", &EventSender::beginDragWithFiles);
- bindMethod("cancelTouchPoint", &EventSender::cancelTouchPoint);
- bindMethod("clearKillRing", &EventSender::clearKillRing);
- bindMethod("clearTouchPoints", &EventSender::clearTouchPoints);
- bindMethod("contextClick", &EventSender::contextClick);
- bindMethod("continuousMouseScrollBy", &EventSender::continuousMouseScrollBy);
- bindMethod("dispatchMessage", &EventSender::dispatchMessage);
- bindMethod("dumpFilenameBeingDragged", &EventSender::dumpFilenameBeingDragged);
- bindMethod("enableDOMUIEventLogging", &EventSender::enableDOMUIEventLogging);
- bindMethod("fireKeyboardEventsToElement", &EventSender::fireKeyboardEventsToElement);
- bindMethod("keyDown", &EventSender::keyDown);
- bindMethod("leapForward", &EventSender::leapForward);
- bindMethod("mouseDown", &EventSender::mouseDown);
- bindMethod("mouseMoveTo", &EventSender::mouseMoveTo);
- bindMethod("mouseScrollBy", &EventSender::mouseScrollBy);
- bindMethod("mouseUp", &EventSender::mouseUp);
- bindMethod("mouseDragBegin", &EventSender::mouseDragBegin);
- bindMethod("mouseDragEnd", &EventSender::mouseDragEnd);
- bindMethod("mouseMomentumBegin", &EventSender::mouseMomentumBegin);
- bindMethod("mouseMomentumScrollBy", &EventSender::mouseMomentumScrollBy);
- bindMethod("mouseMomentumEnd", &EventSender::mouseMomentumEnd);
- bindMethod("releaseTouchPoint", &EventSender::releaseTouchPoint);
- bindMethod("scheduleAsynchronousClick", &EventSender::scheduleAsynchronousClick);
- bindMethod("scheduleAsynchronousKeyDown", &EventSender::scheduleAsynchronousKeyDown);
- bindMethod("setTouchModifier", &EventSender::setTouchModifier);
- bindMethod("textZoomIn", &EventSender::textZoomIn);
- bindMethod("textZoomOut", &EventSender::textZoomOut);
- bindMethod("touchCancel", &EventSender::touchCancel);
- bindMethod("touchEnd", &EventSender::touchEnd);
- bindMethod("touchMove", &EventSender::touchMove);
- bindMethod("touchStart", &EventSender::touchStart);
- bindMethod("updateTouchPoint", &EventSender::updateTouchPoint);
- bindMethod("gestureFlingCancel", &EventSender::gestureFlingCancel);
- bindMethod("gestureFlingStart", &EventSender::gestureFlingStart);
- bindMethod("gestureScrollBegin", &EventSender::gestureScrollBegin);
- bindMethod("gestureScrollEnd", &EventSender::gestureScrollEnd);
- bindMethod("gestureScrollFirstPoint", &EventSender::gestureScrollFirstPoint);
- bindMethod("gestureScrollUpdate", &EventSender::gestureScrollUpdate);
- bindMethod("gestureScrollUpdateWithoutPropagation", &EventSender::gestureScrollUpdateWithoutPropagation);
- bindMethod("gestureTap", &EventSender::gestureTap);
- bindMethod("gestureTapDown", &EventSender::gestureTapDown);
- bindMethod("gestureShowPress", &EventSender::gestureShowPress);
- bindMethod("gestureTapCancel", &EventSender::gestureTapCancel);
- bindMethod("gestureLongPress", &EventSender::gestureLongPress);
- bindMethod("gestureLongTap", &EventSender::gestureLongTap);
- bindMethod("gestureTwoFingerTap", &EventSender::gestureTwoFingerTap);
- bindMethod("zoomPageIn", &EventSender::zoomPageIn);
- bindMethod("zoomPageOut", &EventSender::zoomPageOut);
- bindMethod("setPageScaleFactor", &EventSender::setPageScaleFactor);
-
- bindProperty("forceLayoutOnEvents", &forceLayoutOnEvents);
-
- // When set to true (the default value), we batch mouse move and mouse up
- // events so we can simulate drag & drop.
- bindProperty("dragMode", &dragMode);
-#ifdef WIN32
- bindProperty("WM_KEYDOWN", &wmKeyDown);
- bindProperty("WM_KEYUP", &wmKeyUp);
- bindProperty("WM_CHAR", &wmChar);
- bindProperty("WM_DEADCHAR", &wmDeadChar);
- bindProperty("WM_SYSKEYDOWN", &wmSysKeyDown);
- bindProperty("WM_SYSKEYUP", &wmSysKeyUp);
- bindProperty("WM_SYSCHAR", &wmSysChar);
- bindProperty("WM_SYSDEADCHAR", &wmSysDeadChar);
-#endif
-}
-
-EventSender::~EventSender()
-{
-}
-
-void EventSender::setContextMenuData(const WebContextMenuData& contextMenuData)
-{
- m_lastContextMenuData = scoped_ptr<WebContextMenuData>(new WebContextMenuData(contextMenuData));
-}
-
-void EventSender::reset()
-{
- // The test should have finished a drag and the mouse button state.
- BLINK_ASSERT(currentDragData.isNull());
- currentDragData.reset();
- currentDragEffect = blink::WebDragOperationNone;
- currentDragEffectsAllowed = blink::WebDragOperationNone;
- if (webview() && pressedButton != WebMouseEvent::ButtonNone)
- webview()->mouseCaptureLost();
- pressedButton = WebMouseEvent::ButtonNone;
- dragMode.set(true);
- forceLayoutOnEvents.set(true);
-#ifdef WIN32
- wmKeyDown.set(WM_KEYDOWN);
- wmKeyUp.set(WM_KEYUP);
- wmChar.set(WM_CHAR);
- wmDeadChar.set(WM_DEADCHAR);
- wmSysKeyDown.set(WM_SYSKEYDOWN);
- wmSysKeyUp.set(WM_SYSKEYUP);
- wmSysChar.set(WM_SYSCHAR);
- wmSysDeadChar.set(WM_SYSDEADCHAR);
-#endif
- lastMousePos = WebPoint(0, 0);
- lastClickTimeSec = 0;
- lastClickPos = WebPoint(0, 0);
- clickCount = 0;
- lastButtonType = WebMouseEvent::ButtonNone;
- timeOffsetMs = 0;
- touchModifiers = 0;
- touchPoints.clear();
- m_taskList.revokeAll();
- m_currentGestureLocation = WebPoint(0, 0);
- mouseEventQueue.clear();
-}
-
-void EventSender::doDragDrop(const WebDragData& dragData, WebDragOperationsMask mask)
-{
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- WebPoint clientPoint(event.x, event.y);
- WebPoint screenPoint(event.globalX, event.globalY);
- currentDragData = dragData;
- currentDragEffectsAllowed = mask;
- currentDragEffect = webview()->dragTargetDragEnter(dragData, clientPoint, screenPoint, currentDragEffectsAllowed, 0);
-
- // Finish processing events.
- replaySavedEvents();
-}
-
-void EventSender::dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*)
-{
- WebString filename;
- WebVector<WebDragData::Item> items = currentDragData.items();
- for (size_t i = 0; i < items.size(); ++i) {
- if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
- filename = items[i].title;
- break;
- }
- }
- m_delegate->printMessage(std::string("Filename being dragged: ") + filename.utf8().data() + "\n");
-}
-
-WebMouseEvent::Button EventSender::getButtonTypeFromButtonNumber(int buttonCode)
-{
- if (!buttonCode)
- return WebMouseEvent::ButtonLeft;
- if (buttonCode == 2)
- return WebMouseEvent::ButtonRight;
- return WebMouseEvent::ButtonMiddle;
-}
-
-int EventSender::getButtonNumberFromSingleArg(const CppArgumentList& arguments)
-{
- int buttonCode = 0;
- if (arguments.size() > 0 && arguments[0].isNumber())
- buttonCode = arguments[0].toInt32();
- return buttonCode;
-}
-
-void EventSender::updateClickCountForButton(WebMouseEvent::Button buttonType)
-{
- if ((getCurrentEventTimeSec(m_delegate) - lastClickTimeSec < multipleClickTimeSec)
- && (!outsideMultiClickRadius(lastMousePos, lastClickPos))
- && (buttonType == lastButtonType))
- ++clickCount;
- else {
- clickCount = 1;
- lastButtonType = buttonType;
- }
-}
-
-//
-// Implemented javascript methods.
-//
-
-void EventSender::mouseDown(const CppArgumentList& arguments, CppVariant* result)
-{
- if (result) // Could be 0 if invoked asynchronously.
- result->setNull();
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- int buttonNumber = getButtonNumberFromSingleArg(arguments);
- BLINK_ASSERT(buttonNumber != -1);
-
- WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
-
- updateClickCountForButton(buttonType);
-
- WebMouseEvent event;
- pressedButton = buttonType;
- int modifiers = 0;
- if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
- modifiers = getKeyModifiers(&(arguments[1]));
- initMouseEvent(WebInputEvent::MouseDown, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
- webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseUp(const CppArgumentList& arguments, CppVariant* result)
-{
- if (result) // Could be 0 if invoked asynchronously.
- result->setNull();
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- int buttonNumber = getButtonNumberFromSingleArg(arguments);
- BLINK_ASSERT(buttonNumber != -1);
-
- WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
-
- int modifiers = 0;
- if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
- modifiers = getKeyModifiers(&(arguments[1]));
-
- if (isDragMode() && !replayingSavedEvents) {
- SavedEvent savedEvent;
- savedEvent.type = SavedEvent::MouseUp;
- savedEvent.buttonType = buttonType;
- savedEvent.modifiers = modifiers;
- mouseEventQueue.push_back(savedEvent);
- replaySavedEvents();
- } else {
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseUp, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
- doMouseUp(event);
- }
-}
-
-void EventSender::doMouseUp(const WebMouseEvent& e)
-{
- webview()->handleInputEvent(e);
-
- pressedButton = WebMouseEvent::ButtonNone;
- lastClickTimeSec = e.timeStampSeconds;
- lastClickPos = lastMousePos;
-
- // If we're in a drag operation, complete it.
- if (currentDragData.isNull())
- return;
-
- WebPoint clientPoint(e.x, e.y);
- WebPoint screenPoint(e.globalX, e.globalY);
- finishDragAndDrop(e, webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0));
-}
-
-void EventSender::finishDragAndDrop(const WebMouseEvent& e, blink::WebDragOperation dragEffect)
-{
- WebPoint clientPoint(e.x, e.y);
- WebPoint screenPoint(e.globalX, e.globalY);
- currentDragEffect = dragEffect;
- if (currentDragEffect) {
- // Specifically pass any keyboard modifiers to the drop
- // method. This allows tests to control the drop type
- // (i.e. copy or move).
- webview()->dragTargetDrop(clientPoint, screenPoint, e.modifiers);
- } else {
- webview()->dragTargetDragLeave();
- }
- webview()->dragSourceEndedAt(clientPoint, screenPoint, currentDragEffect);
- webview()->dragSourceSystemDragEnded();
-
- currentDragData.reset();
-}
-
-void EventSender::mouseMoveTo(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- WebPoint mousePos(arguments[0].toInt32(), arguments[1].toInt32());
-
- int modifiers = 0;
- if (arguments.size() >= 3 && (arguments[2].isObject() || arguments[2].isString()))
- modifiers = getKeyModifiers(&(arguments[2]));
-
- if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
- SavedEvent savedEvent;
- savedEvent.type = SavedEvent::MouseMove;
- savedEvent.pos = mousePos;
- savedEvent.modifiers = modifiers;
- mouseEventQueue.push_back(savedEvent);
- } else {
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseMove, pressedButton, mousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
- doMouseMove(event);
- }
-}
-
-void EventSender::doMouseMove(const WebMouseEvent& e)
-{
- lastMousePos = WebPoint(e.x, e.y);
-
- webview()->handleInputEvent(e);
-
- if (pressedButton == WebMouseEvent::ButtonNone || currentDragData.isNull())
- return;
- WebPoint clientPoint(e.x, e.y);
- WebPoint screenPoint(e.globalX, e.globalY);
- currentDragEffect = webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0);
-}
-
-void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
-{
- if (result)
- result->setNull();
- if (arguments.size() < 1 || !arguments[0].isString())
- return;
- bool generateChar = false;
-
- // FIXME: I'm not exactly sure how we should convert the string to a key
- // event. This seems to work in the cases I tested.
- // FIXME: Should we also generate a KEY_UP?
- string codeStr = arguments[0].toString();
-
- // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
- // Windows uses \r for "Enter".
- int code = 0;
- int text = 0;
- bool needsShiftKeyModifier = false;
- if ("\n" == codeStr) {
- generateChar = true;
- text = code = VKEY_RETURN;
- } else if ("rightArrow" == codeStr)
- code = VKEY_RIGHT;
- else if ("downArrow" == codeStr)
- code = VKEY_DOWN;
- else if ("leftArrow" == codeStr)
- code = VKEY_LEFT;
- else if ("upArrow" == codeStr)
- code = VKEY_UP;
- else if ("insert" == codeStr)
- code = VKEY_INSERT;
- else if ("delete" == codeStr)
- code = VKEY_DELETE;
- else if ("pageUp" == codeStr)
- code = VKEY_PRIOR;
- else if ("pageDown" == codeStr)
- code = VKEY_NEXT;
- else if ("home" == codeStr)
- code = VKEY_HOME;
- else if ("end" == codeStr)
- code = VKEY_END;
- else if ("printScreen" == codeStr)
- code = VKEY_SNAPSHOT;
- else if ("menu" == codeStr)
- code = VKEY_APPS;
- else if ("leftControl" == codeStr)
- code = VKEY_LCONTROL;
- else if ("rightControl" == codeStr)
- code = VKEY_RCONTROL;
- else if ("leftShift" == codeStr)
- code = VKEY_LSHIFT;
- else if ("rightShift" == codeStr)
- code = VKEY_RSHIFT;
- else if ("leftAlt" == codeStr)
- code = VKEY_LMENU;
- else if ("rightAlt" == codeStr)
- code = VKEY_RMENU;
- else if ("numLock" == codeStr)
- code = VKEY_NUMLOCK;
- else {
- // Compare the input string with the function-key names defined by the
- // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
- // name, set its key code.
- for (int i = 1; i <= 24; ++i) {
- char functionChars[10];
- snprintf(functionChars, 10, "F%d", i);
- string functionKeyName(functionChars);
- if (functionKeyName == codeStr) {
- code = VKEY_F1 + (i - 1);
- break;
- }
- }
- if (!code) {
- WebString webCodeStr = WebString::fromUTF8(codeStr.data(), codeStr.size());
- BLINK_ASSERT(webCodeStr.length() == 1);
- text = code = webCodeStr.at(0);
- needsShiftKeyModifier = needsShiftModifier(code);
- if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
- code -= 'a' - 'A';
- generateChar = true;
- }
-
- if ("(" == codeStr) {
- code = '9';
- needsShiftKeyModifier = true;
- }
- }
-
- // For one generated keyboard event, we need to generate a keyDown/keyUp
- // pair; refer to EventSender.cpp in Tools/DumpRenderTree/win.
- // On Windows, we might also need to generate a char event to mimic the
- // Windows event flow; on other platforms we create a merged event and test
- // the event flow that that platform provides.
- WebKeyboardEvent eventDown, eventChar, eventUp;
- eventDown.type = WebInputEvent::RawKeyDown;
- eventDown.modifiers = 0;
- eventDown.windowsKeyCode = code;
-#if defined(__linux__) && defined(TOOLKIT_GTK)
- eventDown.nativeKeyCode = NativeKeyCodeForWindowsKeyCode(code);
-#endif
-
- if (generateChar) {
- eventDown.text[0] = text;
- eventDown.unmodifiedText[0] = text;
- }
- eventDown.setKeyIdentifierFromWindowsKeyCode();
-
- if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString())) {
- eventDown.modifiers = getKeyModifiers(&(arguments[1]));
-#if WIN32 || __APPLE__ || defined(ANDROID) || defined(TOOLKIT_GTK)
- eventDown.isSystemKey = WebInputEventFactory::isSystemKeyEvent(eventDown);
-#endif
- }
-
- if (needsShiftKeyModifier)
- eventDown.modifiers |= WebInputEvent::ShiftKey;
-
- // See if KeyLocation argument is given.
- if (arguments.size() >= 3 && arguments[2].isNumber()) {
- int location = arguments[2].toInt32();
- if (location == DOMKeyLocationNumpad)
- eventDown.modifiers |= WebInputEvent::IsKeyPad;
- }
-
- eventChar = eventUp = eventDown;
- eventUp.type = WebInputEvent::KeyUp;
- // EventSender.m forces a layout here, with at least one
- // test (fast/forms/focus-control-to-page.html) relying on this.
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- // In the browser, if a keyboard event corresponds to an editor command,
- // the command will be dispatched to the renderer just before dispatching
- // the keyboard event, and then it will be executed in the
- // RenderView::handleCurrentKeyboardEvent() method, which is called from
- // third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp.
- // We just simulate the same behavior here.
- string editCommand;
- if (getEditCommand(eventDown, &editCommand))
- m_delegate->setEditCommand(editCommand, "");
-
- webview()->handleInputEvent(eventDown);
-
- if (code == VKEY_ESCAPE && !currentDragData.isNull()) {
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- finishDragAndDrop(event, blink::WebDragOperationNone);
- }
-
- m_delegate->clearEditCommand();
-
- if (generateChar) {
- eventChar.type = WebInputEvent::Char;
- eventChar.keyIdentifier[0] = '\0';
- webview()->handleInputEvent(eventChar);
- }
-
- webview()->handleInputEvent(eventUp);
-}
-
-void EventSender::dispatchMessage(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
-#ifdef WIN32
- if (arguments.size() == 3) {
- // Grab the message id to see if we need to dispatch it.
- int msg = arguments[0].toInt32();
-
- // WebKit's version of this function stuffs a MSG struct and uses
- // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
- // doesn't need to receive the DeadChar and SysDeadChar messages.
- if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
- return;
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- unsigned long lparam = static_cast<unsigned long>(arguments[2].toDouble());
- webview()->handleInputEvent(WebInputEventFactory::keyboardEvent(0, msg, arguments[1].toInt32(), lparam));
- } else
- BLINK_ASSERT_NOT_REACHED();
-#endif
-}
-
-bool EventSender::needsShiftModifier(int keyCode)
-{
- // If code is an uppercase letter, assign a SHIFT key to
- // eventDown.modifier, this logic comes from
- // Tools/DumpRenderTree/win/EventSender.cpp
- return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
-}
-
-void EventSender::leapForward(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() < 1 || !arguments[0].isNumber())
- return;
-
- int milliseconds = arguments[0].toInt32();
- if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
- SavedEvent savedEvent;
- savedEvent.type = SavedEvent::LeapForward;
- savedEvent.milliseconds = milliseconds;
- mouseEventQueue.push_back(savedEvent);
- } else
- doLeapForward(milliseconds);
-}
-
-void EventSender::doLeapForward(int milliseconds)
-{
- advanceEventTime(milliseconds);
-}
-
-// Apple's port of WebKit zooms by a factor of 1.2 (see
-// WebKit/WebView/WebView.mm)
-void EventSender::textZoomIn(const CppArgumentList&, CppVariant* result)
-{
- webview()->setTextZoomFactor(webview()->textZoomFactor() * 1.2f);
- result->setNull();
-}
-
-void EventSender::textZoomOut(const CppArgumentList&, CppVariant* result)
-{
- webview()->setTextZoomFactor(webview()->textZoomFactor() / 1.2f);
- result->setNull();
-}
-
-void EventSender::zoomPageIn(const CppArgumentList&, CppVariant* result)
-{
- const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
-
- for (size_t i = 0; i < windowList.size(); ++i)
- windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() + 1);
- result->setNull();
-}
-
-void EventSender::zoomPageOut(const CppArgumentList&, CppVariant* result)
-{
- const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
-
- for (size_t i = 0; i < windowList.size(); ++i)
- windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() - 1);
- result->setNull();
-}
-
-void EventSender::setPageScaleFactor(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumber() || !arguments[2].isNumber())
- return;
-
- float scaleFactor = static_cast<float>(arguments[0].toDouble());
- int x = arguments[1].toInt32();
- int y = arguments[2].toInt32();
- webview()->setPageScaleFactorLimits(scaleFactor, scaleFactor);
- webview()->setPageScaleFactor(scaleFactor, WebPoint(x, y));
- result->setNull();
-}
-
-void EventSender::mouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseWheelEvent(arguments, result, false, &event);
- webview()->handleInputEvent(event);
-}
-
-void EventSender::continuousMouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseWheelEvent(arguments, result, true, &event);
- webview()->handleInputEvent(event);
-}
-
-void EventSender::replaySavedEvents()
-{
- replayingSavedEvents = true;
- while (!mouseEventQueue.empty()) {
- SavedEvent e = mouseEventQueue.front();
- mouseEventQueue.pop_front();
-
- switch (e.type) {
- case SavedEvent::MouseMove: {
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseMove, pressedButton, e.pos, &event, getCurrentEventTimeSec(m_delegate), e.modifiers);
- doMouseMove(event);
- break;
- }
- case SavedEvent::LeapForward:
- doLeapForward(e.milliseconds);
- break;
- case SavedEvent::MouseUp: {
- WebMouseEvent event;
- initMouseEvent(WebInputEvent::MouseUp, e.buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), e.modifiers);
- doMouseUp(event);
- break;
- }
- default:
- BLINK_ASSERT_NOT_REACHED();
- }
- }
-
- replayingSavedEvents = false;
-}
-
-// Because actual context menu is implemented by the browser side,
-// this function does only what LayoutTests are expecting:
-// - Many test checks the count of items. So returning non-zero value makes sense.
-// - Some test compares the count before and after some action. So changing the count based on flags
-// also makes sense. This function is doing such for some flags.
-// - Some test even checks actual string content. So providing it would be also helpful.
-//
-static vector<WebString> makeMenuItemStringsFor(WebContextMenuData* contextMenu, WebTestDelegate* delegate)
-{
- // These constants are based on Safari's context menu because tests are made for it.
- static const char* nonEditableMenuStrings[] = { "Back", "Reload Page", "Open in Dashbaord", "<separator>", "View Source", "Save Page As", "Print Page", "Inspect Element", 0 };
- static const char* editableMenuStrings[] = { "Cut", "Copy", "<separator>", "Paste", "Spelling and Grammar", "Substitutions, Transformations", "Font", "Speech", "Paragraph Direction", "<separator>", 0 };
-
- // This is possible because mouse events are cancelleable.
- if (!contextMenu)
- return vector<WebString>();
-
- vector<WebString> strings;
-
- if (contextMenu->isEditable) {
- for (const char** item = editableMenuStrings; *item; ++item)
- strings.push_back(WebString::fromUTF8(*item));
- WebVector<WebString> suggestions;
- MockSpellCheck::fillSuggestionList(contextMenu->misspelledWord, &suggestions);
- for (size_t i = 0; i < suggestions.size(); ++i)
- strings.push_back(suggestions[i]);
- } else {
- for (const char** item = nonEditableMenuStrings; *item; ++item)
- strings.push_back(WebString::fromUTF8(*item));
- }
-
- return strings;
-}
-
-void EventSender::contextClick(const CppArgumentList& arguments, CppVariant* result)
-{
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- updateClickCountForButton(WebMouseEvent::ButtonRight);
-
- // Clears last context menu data because we need to know if the context menu be requested
- // after following mouse events.
- m_lastContextMenuData.reset();
-
- // Generate right mouse down and up.
- WebMouseEvent event;
- // This is a hack to work around only allowing a single pressed button since we want to
- // test the case where both the left and right mouse buttons are pressed.
- if (pressedButton == WebMouseEvent::ButtonNone)
- pressedButton = WebMouseEvent::ButtonRight;
- initMouseEvent(WebInputEvent::MouseDown, WebMouseEvent::ButtonRight, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- webview()->handleInputEvent(event);
-
-#ifdef WIN32
- initMouseEvent(WebInputEvent::MouseUp, WebMouseEvent::ButtonRight, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- webview()->handleInputEvent(event);
-
- pressedButton = WebMouseEvent::ButtonNone;
-#endif
-
- NPObject* resultArray = WebBindings::makeStringArray(makeMenuItemStringsFor(m_lastContextMenuData.get(), m_delegate));
- result->set(resultArray);
- WebBindings::releaseObject(resultArray);
-
- m_lastContextMenuData.reset();
-}
-
-class MouseDownTask: public WebMethodTask<EventSender> {
-public:
- MouseDownTask(EventSender* obj, const CppArgumentList& arg)
- : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
- virtual void runIfValid() OVERRIDE { m_object->mouseDown(m_arguments, 0); }
-
-private:
- CppArgumentList m_arguments;
-};
-
-class MouseUpTask: public WebMethodTask<EventSender> {
-public:
- MouseUpTask(EventSender* obj, const CppArgumentList& arg)
- : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
- virtual void runIfValid() OVERRIDE { m_object->mouseUp(m_arguments, 0); }
-
-private:
- CppArgumentList m_arguments;
-};
-
-void EventSender::scheduleAsynchronousClick(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- m_delegate->postTask(new MouseDownTask(this, arguments));
- m_delegate->postTask(new MouseUpTask(this, arguments));
-}
-
-class KeyDownTask : public WebMethodTask<EventSender> {
-public:
- KeyDownTask(EventSender* obj, const CppArgumentList& arg)
- : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
- virtual void runIfValid() OVERRIDE { m_object->keyDown(m_arguments, 0); }
-
-private:
- CppArgumentList m_arguments;
-};
-
-void EventSender::scheduleAsynchronousKeyDown(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- m_delegate->postTask(new KeyDownTask(this, arguments));
-}
-
-void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVariant* result)
-{
- currentDragData.initialize();
- vector<string> files = arguments[0].toStringVector();
- WebVector<WebString> absoluteFilenames(files.size());
- for (size_t i = 0; i < files.size(); ++i) {
- WebDragData::Item item;
- item.storageType = WebDragData::Item::StorageTypeFilename;
- item.filenameData = m_delegate->getAbsoluteWebStringFromUTF8Path(files[i]);
- currentDragData.addItem(item);
- absoluteFilenames[i] = item.filenameData;
- }
- currentDragData.setFilesystemId(m_delegate->registerIsolatedFileSystem(absoluteFilenames));
- currentDragEffectsAllowed = blink::WebDragOperationCopy;
-
- // Provide a drag source.
- webview()->dragTargetDragEnter(currentDragData, lastMousePos, lastMousePos, currentDragEffectsAllowed, 0);
-
- // dragMode saves events and then replays them later. We don't need/want that.
- dragMode.set(false);
-
- // Make the rest of eventSender think a drag is in progress.
- pressedButton = WebMouseEvent::ButtonLeft;
-
- result->setNull();
-}
-
-void EventSender::addTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- WebTouchPoint touchPoint;
- touchPoint.state = WebTouchPoint::StatePressed;
- touchPoint.position = WebFloatPoint(arguments[0].toInt32(), arguments[1].toInt32());
- touchPoint.screenPosition = touchPoint.position;
-
- if (arguments.size() > 2) {
- int radiusX = arguments[2].toInt32();
- int radiusY = radiusX;
- if (arguments.size() > 3)
- radiusY = arguments[3].toInt32();
-
- touchPoint.radiusX = radiusX;
- touchPoint.radiusY = radiusY;
- }
-
- int lowestId = 0;
- for (size_t i = 0; i < touchPoints.size(); i++) {
- if (touchPoints[i].id == lowestId)
- lowestId++;
- }
- touchPoint.id = lowestId;
- touchPoints.push_back(touchPoint);
-}
-
-void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
- touchPoints.clear();
-}
-
-void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- const unsigned index = arguments[0].toInt32();
- BLINK_ASSERT(index < touchPoints.size());
-
- WebTouchPoint* touchPoint = &touchPoints[index];
- touchPoint->state = WebTouchPoint::StateReleased;
-}
-
-void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- int mask = 0;
- const string keyName = arguments[0].toString();
- if (keyName == "shift")
- mask = WebInputEvent::ShiftKey;
- else if (keyName == "alt")
- mask = WebInputEvent::AltKey;
- else if (keyName == "ctrl")
- mask = WebInputEvent::ControlKey;
- else if (keyName == "meta")
- mask = WebInputEvent::MetaKey;
-
- if (arguments[1].toBoolean())
- touchModifiers |= mask;
- else
- touchModifiers &= ~mask;
-}
-
-void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- const unsigned index = arguments[0].toInt32();
- BLINK_ASSERT(index < touchPoints.size());
-
- WebTouchPoint* touchPoint = &touchPoints[index];
- touchPoint->state = WebTouchPoint::StateMoved;
- touchPoint->position = WebFloatPoint(arguments[1].toInt32(), arguments[2].toInt32());
- touchPoint->screenPosition = touchPoint->position;
-}
-
-void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- const unsigned index = arguments[0].toInt32();
- BLINK_ASSERT(index < touchPoints.size());
-
- WebTouchPoint* touchPoint = &touchPoints[index];
- touchPoint->state = WebTouchPoint::StateCancelled;
-}
-
-void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
-{
- BLINK_ASSERT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap) > touchPoints.size());
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- WebTouchEvent touchEvent;
- touchEvent.type = type;
- touchEvent.modifiers = touchModifiers;
- touchEvent.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
- touchEvent.touchesLength = touchPoints.size();
- for (unsigned i = 0; i < touchPoints.size(); ++i)
- touchEvent.touches[i] = touchPoints[i];
- webview()->handleInputEvent(touchEvent);
-
- for (unsigned i = 0; i < touchPoints.size(); ++i) {
- WebTouchPoint* touchPoint = &touchPoints[i];
- if (touchPoint->state == WebTouchPoint::StateReleased) {
- touchPoints.erase(touchPoints.begin() + i);
- --i;
- } else
- touchPoint->state = WebTouchPoint::StateStationary;
- }
-}
-
-void EventSender::mouseDragBegin(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- event.phase = WebMouseWheelEvent::PhaseBegan;
- event.hasPreciseScrollingDeltas = true;
- webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseDragEnd(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- event.phase = WebMouseWheelEvent::PhaseEnded;
- event.hasPreciseScrollingDeltas = true;
- webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumBegin(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
- event.hasPreciseScrollingDeltas = true;
- webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseWheelEvent(arguments, result, true, &event);
- event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
- event.hasPreciseScrollingDeltas = true;
- webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumEnd(const CppArgumentList& arguments, CppVariant* result)
-{
- WebMouseWheelEvent event;
- initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
- event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
- event.hasPreciseScrollingDeltas = true;
- webview()->handleInputEvent(event);
-}
-
-void EventSender::initMouseWheelEvent(const CppArgumentList& arguments, CppVariant* result, bool continuous, WebMouseWheelEvent* event)
-{
- result->setNull();
-
- if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- // Force a layout here just to make sure every position has been
- // determined before we send events (as well as all the other methods
- // that send an event do).
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- int horizontal = arguments[0].toInt32();
- int vertical = arguments[1].toInt32();
- int paged = false;
- int hasPreciseScrollingDeltas = false;
- int modifiers = 0;
-
- if (arguments.size() > 2 && arguments[2].isBool())
- paged = arguments[2].toBoolean();
-
- if (arguments.size() > 3 && arguments[3].isBool())
- hasPreciseScrollingDeltas = arguments[3].toBoolean();
-
- if (arguments.size() > 4 && (arguments[4].isObject() || arguments[4].isString()))
- modifiers = getKeyModifiers(&(arguments[4]));
-
- initMouseEvent(WebInputEvent::MouseWheel, pressedButton, lastMousePos, event, getCurrentEventTimeSec(m_delegate), modifiers);
- event->wheelTicksX = static_cast<float>(horizontal);
- event->wheelTicksY = static_cast<float>(vertical);
- event->deltaX = event->wheelTicksX;
- event->deltaY = event->wheelTicksY;
- event->scrollByPage = paged;
- event->hasPreciseScrollingDeltas = hasPreciseScrollingDeltas;
-
- if (continuous) {
- event->wheelTicksX /= scrollbarPixelsPerTick;
- event->wheelTicksY /= scrollbarPixelsPerTick;
- } else {
- event->deltaX *= scrollbarPixelsPerTick;
- event->deltaY *= scrollbarPixelsPerTick;
- }
-}
-
-void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
- sendCurrentTouchEvent(WebInputEvent::TouchEnd);
-}
-
-void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
- sendCurrentTouchEvent(WebInputEvent::TouchMove);
-}
-
-void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
- sendCurrentTouchEvent(WebInputEvent::TouchStart);
-}
-
-void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
- sendCurrentTouchEvent(WebInputEvent::TouchCancel);
-}
-
-void EventSender::gestureScrollBegin(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureScrollBegin, arguments);
-}
-
-void EventSender::gestureScrollEnd(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureScrollEnd, arguments);
-}
-
-void EventSender::gestureScrollUpdate(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureScrollUpdate, arguments);
-}
-
-void EventSender::gestureScrollUpdateWithoutPropagation(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, arguments);
-}
-
-void EventSender::gestureTap(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureTap, arguments);
-}
-
-void EventSender::gestureTapDown(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureTapDown, arguments);
-}
-
-void EventSender::gestureShowPress(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureShowPress, arguments);
-}
-
-void EventSender::gestureTapCancel(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureTapCancel, arguments);
-}
-
-void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureLongPress, arguments);
-}
-
-void EventSender::gestureLongTap(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureLongTap, arguments);
-}
-
-void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments);
-}
-
-void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
- m_currentGestureLocation = point;
-}
-
-void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& arguments)
-{
- if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
-
- WebGestureEvent event;
- event.type = type;
-
- switch (type) {
- case WebInputEvent::GestureScrollUpdate:
- case WebInputEvent::GestureScrollUpdateWithoutPropagation:
- event.data.scrollUpdate.deltaX = static_cast<float>(arguments[0].toDouble());
- event.data.scrollUpdate.deltaY = static_cast<float>(arguments[1].toDouble());
- event.x = m_currentGestureLocation.x;
- event.y = m_currentGestureLocation.y;
- m_currentGestureLocation.x = m_currentGestureLocation.x + event.data.scrollUpdate.deltaX;
- m_currentGestureLocation.y = m_currentGestureLocation.y + event.data.scrollUpdate.deltaY;
- break;
-
- case WebInputEvent::GestureScrollBegin:
- m_currentGestureLocation = WebPoint(point.x, point.y);
- event.x = m_currentGestureLocation.x;
- event.y = m_currentGestureLocation.y;
- break;
- case WebInputEvent::GestureScrollEnd:
- case WebInputEvent::GestureFlingStart:
- event.x = m_currentGestureLocation.x;
- event.y = m_currentGestureLocation.y;
- break;
- case WebInputEvent::GestureTap:
- if (arguments.size() >= 3)
- event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
- else
- event.data.tap.tapCount = 1;
- event.x = point.x;
- event.y = point.y;
- break;
- case WebInputEvent::GestureTapUnconfirmed:
- if (arguments.size() >= 3)
- event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
- else
- event.data.tap.tapCount = 1;
- event.x = point.x;
- event.y = point.y;
- break;
- case WebInputEvent::GestureTapDown:
- event.x = point.x;
- event.y = point.y;
- if (arguments.size() >= 4) {
- event.data.tapDown.width = static_cast<float>(arguments[2].toDouble());
- event.data.tapDown.height = static_cast<float>(arguments[3].toDouble());
- }
- break;
- case WebInputEvent::GestureShowPress:
- event.x = point.x;
- event.y = point.y;
- if (arguments.size() >= 4) {
- event.data.showPress.width = static_cast<float>(arguments[2].toDouble());
- event.data.showPress.height = static_cast<float>(arguments[3].toDouble());
- }
- break;
- case WebInputEvent::GestureTapCancel:
- event.x = point.x;
- event.y = point.y;
- break;
- case WebInputEvent::GestureLongPress:
- event.x = point.x;
- event.y = point.y;
- if (arguments.size() >= 4) {
- event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
- event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
- }
- break;
- case WebInputEvent::GestureLongTap:
- event.x = point.x;
- event.y = point.y;
- if (arguments.size() >= 4) {
- event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
- event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
- }
- break;
- case WebInputEvent::GestureTwoFingerTap:
- event.x = point.x;
- event.y = point.y;
- if (arguments.size() >= 4) {
- event.data.twoFingerTap.firstFingerWidth = static_cast<float>(arguments[2].toDouble());
- event.data.twoFingerTap.firstFingerHeight = static_cast<float>(arguments[3].toDouble());
- }
- break;
- default:
- BLINK_ASSERT_NOT_REACHED();
- }
-
- event.globalX = event.x;
- event.globalY = event.y;
- event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- webview()->handleInputEvent(event);
-
- // Long press might start a drag drop session. Complete it if so.
- if (type == WebInputEvent::GestureLongPress && !currentDragData.isNull()) {
- WebMouseEvent mouseEvent;
- initMouseEvent(WebInputEvent::MouseDown, pressedButton, point, &mouseEvent, getCurrentEventTimeSec(m_delegate), 0);
- finishDragAndDrop(mouseEvent, blink::WebDragOperationNone);
- }
-}
-
-void EventSender::gestureFlingCancel(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
-
- WebGestureEvent event;
- event.type = WebInputEvent::GestureFlingCancel;
- event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- webview()->handleInputEvent(event);
-}
-
-void EventSender::gestureFlingStart(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
- if (arguments.size() < 4)
- return;
-
- for (int i = 0; i < 4; i++)
- if (!arguments[i].isNumber())
- return;
-
- WebGestureEvent event;
- event.type = WebInputEvent::GestureFlingStart;
-
- event.x = static_cast<float>(arguments[0].toDouble());
- event.y = static_cast<float>(arguments[1].toDouble());
- event.globalX = event.x;
- event.globalY = event.y;
-
- event.data.flingStart.velocityX = static_cast<float>(arguments[2].toDouble());
- event.data.flingStart.velocityY = static_cast<float>(arguments[3].toDouble());
- event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
- if (shouldForceLayoutOnEvents())
- webview()->layout();
-
- webview()->handleInputEvent(event);
-}
-
-//
-// Unimplemented stubs
-//
-
-void EventSender::enableDOMUIEventLogging(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
-}
-
-void EventSender::fireKeyboardEventsToElement(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
-}
-
-void EventSender::clearKillRing(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
-}
-
-}
diff --git a/content/shell/renderer/test_runner/EventSender.h b/content/shell/renderer/test_runner/EventSender.h
deleted file mode 100644
index 1f5244f..0000000
--- a/content/shell/renderer/test_runner/EventSender.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
- EventSender class:
- Bound to a JavaScript window.eventSender object using
- CppBoundClass::bindToJavascript(), this allows layout tests to fire DOM events.
-*/
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/shell/renderer/test_runner/CppBoundClass.h"
-#include "content/shell/renderer/test_runner/WebTask.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/web/WebDragOperation.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace blink {
-class WebDragData;
-class WebView;
-struct WebContextMenuData;
-}
-
-namespace WebTestRunner {
-
-class TestInterfaces;
-class WebTestDelegate;
-
-class EventSender : public CppBoundClass {
-public:
- explicit EventSender(TestInterfaces*);
- virtual ~EventSender();
-
- void setDelegate(WebTestDelegate* delegate) { m_delegate = delegate; }
- void setWebView(blink::WebView* webView) { m_webView = webView; }
-
- void setContextMenuData(const blink::WebContextMenuData&);
-
- // Resets some static variable state.
- void reset();
-
- // Simulate drag&drop system call.
- void doDragDrop(const blink::WebDragData&, blink::WebDragOperationsMask);
-
- // Test helper for dragging out images.
- void dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*);
-
- // JS callback methods.
- void contextClick(const CppArgumentList&, CppVariant*);
- void mouseDown(const CppArgumentList&, CppVariant*);
- void mouseUp(const CppArgumentList&, CppVariant*);
- void mouseMoveTo(const CppArgumentList&, CppVariant*);
- void leapForward(const CppArgumentList&, CppVariant*);
- void keyDown(const CppArgumentList&, CppVariant*);
- void dispatchMessage(const CppArgumentList&, CppVariant*);
- // FIXME: These aren't really events. They should be moved to layout controller.
- void textZoomIn(const CppArgumentList&, CppVariant*);
- void textZoomOut(const CppArgumentList&, CppVariant*);
- void zoomPageIn(const CppArgumentList&, CppVariant*);
- void zoomPageOut(const CppArgumentList&, CppVariant*);
- void setPageScaleFactor(const CppArgumentList&, CppVariant*);
-
- void mouseDragBegin(const CppArgumentList&, CppVariant*);
- void mouseDragEnd(const CppArgumentList&, CppVariant*);
- void mouseMomentumBegin(const CppArgumentList&, CppVariant*);
- void mouseMomentumScrollBy(const CppArgumentList&, CppVariant*);
- void mouseMomentumEnd(const CppArgumentList&, CppVariant*);
- void mouseScrollBy(const CppArgumentList&, CppVariant*);
- void continuousMouseScrollBy(const CppArgumentList&, CppVariant*);
- void scheduleAsynchronousClick(const CppArgumentList&, CppVariant*);
- void scheduleAsynchronousKeyDown(const CppArgumentList&, CppVariant*);
- void beginDragWithFiles(const CppArgumentList&, CppVariant*);
- CppVariant dragMode;
-
- void addTouchPoint(const CppArgumentList&, CppVariant*);
- void cancelTouchPoint(const CppArgumentList&, CppVariant*);
- void clearTouchPoints(const CppArgumentList&, CppVariant*);
- void releaseTouchPoint(const CppArgumentList&, CppVariant*);
- void setTouchModifier(const CppArgumentList&, CppVariant*);
- void touchCancel(const CppArgumentList&, CppVariant*);
- void touchEnd(const CppArgumentList&, CppVariant*);
- void touchMove(const CppArgumentList&, CppVariant*);
- void touchStart(const CppArgumentList&, CppVariant*);
- void updateTouchPoint(const CppArgumentList&, CppVariant*);
-
- void gestureFlingCancel(const CppArgumentList&, CppVariant*);
- void gestureFlingStart(const CppArgumentList&, CppVariant*);
- void gestureScrollBegin(const CppArgumentList&, CppVariant*);
- void gestureScrollEnd(const CppArgumentList&, CppVariant*);
- void gestureScrollFirstPoint(const CppArgumentList&, CppVariant*);
- void gestureScrollUpdate(const CppArgumentList&, CppVariant*);
- void gestureScrollUpdateWithoutPropagation(const CppArgumentList&, CppVariant*);
- void gestureTap(const CppArgumentList&, CppVariant*);
- void gestureTapDown(const CppArgumentList&, CppVariant*);
- void gestureShowPress(const CppArgumentList&, CppVariant*);
- void gestureTapCancel(const CppArgumentList&, CppVariant*);
- void gestureLongPress(const CppArgumentList&, CppVariant*);
- void gestureLongTap(const CppArgumentList&, CppVariant*);
- void gestureTwoFingerTap(const CppArgumentList&, CppVariant*);
- void gestureEvent(blink::WebInputEvent::Type, const CppArgumentList&);
-
- // Setting this to false makes EventSender not force layout() calls.
- // This makes it possible to test the standard WebCore event dispatch.
- CppVariant forceLayoutOnEvents;
-
- // Unimplemented stubs
- void enableDOMUIEventLogging(const CppArgumentList&, CppVariant*);
- void fireKeyboardEventsToElement(const CppArgumentList&, CppVariant*);
- void clearKillRing(const CppArgumentList&, CppVariant*);
-
- // Properties used in layout tests.
-#if defined(OS_WIN)
- CppVariant wmKeyDown;
- CppVariant wmKeyUp;
- CppVariant wmChar;
- CppVariant wmDeadChar;
- CppVariant wmSysKeyDown;
- CppVariant wmSysKeyUp;
- CppVariant wmSysChar;
- CppVariant wmSysDeadChar;
-#endif
-
- WebTaskList* taskList() { return &m_taskList; }
-
-private:
- blink::WebView* webview() { return m_webView; }
-
- // Returns true if dragMode is true.
- bool isDragMode() { return dragMode.isBool() && dragMode.toBoolean(); }
-
- bool shouldForceLayoutOnEvents() const { return forceLayoutOnEvents.isBool() && forceLayoutOnEvents.toBoolean(); }
-
- // Sometimes we queue up mouse move and mouse up events for drag drop
- // handling purposes. These methods dispatch the event.
- void doMouseMove(const blink::WebMouseEvent&);
- void doMouseUp(const blink::WebMouseEvent&);
- static void doLeapForward(int milliseconds);
- void replaySavedEvents();
-
- // Helper to return the button type given a button code
- static blink::WebMouseEvent::Button getButtonTypeFromButtonNumber(int);
-
- // Helper to extract the button number from the optional argument in
- // mouseDown and mouseUp
- static int getButtonNumberFromSingleArg(const CppArgumentList&);
-
- // Returns true if the specified key code passed in needs a shift key
- // modifier to be passed into the generated event.
- bool needsShiftModifier(int);
-
- void finishDragAndDrop(const blink::WebMouseEvent&, blink::WebDragOperation);
- void updateClickCountForButton(blink::WebMouseEvent::Button);
-
- // Compose a touch event from the current touch points and send it.
- void sendCurrentTouchEvent(const blink::WebInputEvent::Type);
-
- // Init a mouse wheel event from the given args.
- void initMouseWheelEvent(const CppArgumentList&, CppVariant*, bool continuous, blink::WebMouseWheelEvent*);
-
- WebTaskList m_taskList;
-
- TestInterfaces* m_testInterfaces;
- WebTestDelegate* m_delegate;
- blink::WebView* m_webView;
-
- scoped_ptr<blink::WebContextMenuData> m_lastContextMenuData;
-
- // Location of the touch point that initiated a gesture.
- blink::WebPoint m_currentGestureLocation;
-
- // Location of last mouseMoveTo event.
- static blink::WebPoint lastMousePos;
-
- // Currently pressed mouse button (Left/Right/Middle or None)
- static blink::WebMouseEvent::Button pressedButton;
-
- // The last button number passed to mouseDown and mouseUp.
- // Used to determine whether the click count continues to
- // increment or not.
- static blink::WebMouseEvent::Button lastButtonType;
-};
-
-}
-
-#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
diff --git a/content/shell/renderer/test_runner/TestInterfaces.cpp b/content/shell/renderer/test_runner/TestInterfaces.cpp
index 5e08ac3..c7c4d2d 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.cpp
+++ b/content/shell/renderer/test_runner/TestInterfaces.cpp
@@ -7,9 +7,9 @@
#include <string>
#include "base/strings/stringprintf.h"
-#include "content/shell/renderer/test_runner/EventSender.h"
#include "content/shell/renderer/test_runner/WebTestProxy.h"
#include "content/shell/renderer/test_runner/accessibility_controller.h"
+#include "content/shell/renderer/test_runner/event_sender.h"
#include "content/shell/renderer/test_runner/gamepad_controller.h"
#include "content/shell/renderer/test_runner/text_input_controller.h"
#include "content/shell/renderer/test_runner/test_runner.h"
@@ -27,7 +27,7 @@ namespace WebTestRunner {
TestInterfaces::TestInterfaces()
: m_accessibilityController(new content::AccessibilityController())
- , m_eventSender(new EventSender(this))
+ , m_eventSender(new content::EventSender(this))
, m_gamepadController(new content::GamepadController())
, m_textInputController(new content::TextInputController())
, m_testRunner(new content::TestRunner(this))
@@ -44,13 +44,13 @@ TestInterfaces::TestInterfaces()
TestInterfaces::~TestInterfaces()
{
m_accessibilityController->SetWebView(0);
- m_eventSender->setWebView(0);
+ m_eventSender->SetWebView(0);
// m_gamepadController doesn't depend on WebView.
m_textInputController->SetWebView(NULL);
m_testRunner->SetWebView(0, 0);
m_accessibilityController->SetDelegate(0);
- m_eventSender->setDelegate(0);
+ m_eventSender->SetDelegate(0);
m_gamepadController->SetDelegate(0);
// m_textInputController doesn't depend on WebTestDelegate.
m_testRunner->SetDelegate(0);
@@ -60,7 +60,7 @@ void TestInterfaces::setWebView(WebView* webView, WebTestProxyBase* proxy)
{
m_proxy = proxy;
m_accessibilityController->SetWebView(webView);
- m_eventSender->setWebView(webView);
+ m_eventSender->SetWebView(webView);
// m_gamepadController doesn't depend on WebView.
m_textInputController->SetWebView(webView);
m_testRunner->SetWebView(webView, proxy);
@@ -69,7 +69,7 @@ void TestInterfaces::setWebView(WebView* webView, WebTestProxyBase* proxy)
void TestInterfaces::setDelegate(WebTestDelegate* delegate)
{
m_accessibilityController->SetDelegate(delegate);
- m_eventSender->setDelegate(delegate);
+ m_eventSender->SetDelegate(delegate);
m_gamepadController->SetDelegate(delegate);
// m_textInputController doesn't depend on WebTestDelegate.
m_testRunner->SetDelegate(delegate);
@@ -79,7 +79,7 @@ void TestInterfaces::setDelegate(WebTestDelegate* delegate)
void TestInterfaces::bindTo(WebFrame* frame)
{
m_accessibilityController->Install(frame);
- m_eventSender->bindToJavascript(frame, WebString::fromUTF8("eventSender"));
+ m_eventSender->Install(frame);
m_gamepadController->Install(frame);
m_textInputController->Install(frame);
m_testRunner->Install(frame);
@@ -88,7 +88,7 @@ void TestInterfaces::bindTo(WebFrame* frame)
void TestInterfaces::resetTestHelperControllers()
{
m_accessibilityController->Reset();
- m_eventSender->reset();
+ m_eventSender->Reset();
m_gamepadController->Reset();
// m_textInputController doesn't have any state to reset.
WebCache::clear();
@@ -157,7 +157,7 @@ content::AccessibilityController* TestInterfaces::accessibilityController()
return m_accessibilityController.get();
}
-EventSender* TestInterfaces::eventSender()
+content::EventSender* TestInterfaces::eventSender()
{
return m_eventSender.get();
}
diff --git a/content/shell/renderer/test_runner/TestInterfaces.h b/content/shell/renderer/test_runner/TestInterfaces.h
index 5e6ba1f..4bc50d9 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.h
+++ b/content/shell/renderer/test_runner/TestInterfaces.h
@@ -26,6 +26,7 @@ class WebView;
namespace content {
class AccessibilityController;
+class EventSender;
class GamepadController;
class TestRunner;
class TextInputController;
@@ -33,7 +34,6 @@ class TextInputController;
namespace WebTestRunner {
-class EventSender;
class WebTestDelegate;
class WebTestProxyBase;
@@ -54,7 +54,7 @@ public:
void windowClosed(WebTestProxyBase*);
content::AccessibilityController* accessibilityController();
- EventSender* eventSender();
+ content::EventSender* eventSender();
content::TestRunner* testRunner();
WebTestDelegate* delegate();
WebTestProxyBase* proxy();
@@ -63,7 +63,7 @@ public:
private:
scoped_ptr<content::AccessibilityController> m_accessibilityController;
- scoped_ptr<EventSender> m_eventSender;
+ scoped_ptr<content::EventSender> m_eventSender;
scoped_ptr<content::GamepadController> m_gamepadController;
scoped_ptr<content::TextInputController> m_textInputController;
scoped_ptr<content::TestRunner> m_testRunner;
diff --git a/content/shell/renderer/test_runner/WebTestProxy.cpp b/content/shell/renderer/test_runner/WebTestProxy.cpp
index 0b8ddd5..9d454a2 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.cpp
+++ b/content/shell/renderer/test_runner/WebTestProxy.cpp
@@ -6,7 +6,7 @@
#include <cctype>
-#include "content/shell/renderer/test_runner/EventSender.h"
+#include "content/shell/renderer/test_runner/event_sender.h"
#include "content/shell/renderer/test_runner/MockColorChooser.h"
#include "content/shell/renderer/test_runner/MockWebSpeechInputController.h"
#include "content/shell/renderer/test_runner/MockWebSpeechRecognizer.h"
@@ -875,7 +875,7 @@ void WebTestProxyBase::startDragging(WebFrame*, const WebDragData& data, WebDrag
{
// When running a test, we need to fake a drag drop operation otherwise
// Windows waits for real mouse events to know when the drag is over.
- m_testInterfaces->eventSender()->doDragDrop(data, mask);
+ m_testInterfaces->eventSender()->DoDragDrop(data, mask);
}
// The output from these methods in layout test mode should match that
@@ -924,7 +924,7 @@ void WebTestProxyBase::didStopLoading()
void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
{
- m_testInterfaces->eventSender()->setContextMenuData(contextMenuData);
+ m_testInterfaces->eventSender()->SetContextMenuData(contextMenuData);
}
WebUserMediaClient* WebTestProxyBase::userMediaClient()
diff --git a/content/shell/renderer/test_runner/event_sender.cc b/content/shell/renderer/test_runner/event_sender.cc
new file mode 100644
index 0000000..12063af
--- /dev/null
+++ b/content/shell/renderer/test_runner/event_sender.cc
@@ -0,0 +1,2085 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/renderer/test_runner/event_sender.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "content/shell/renderer/test_runner/KeyCodeMapping.h"
+#include "content/shell/renderer/test_runner/MockSpellCheck.h"
+#include "content/shell/renderer/test_runner/TestInterfaces.h"
+#include "content/shell/renderer/test_runner/WebTestDelegate.h"
+#include "content/shell/renderer/test_runner/WebTestProxy.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebContextMenuData.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+#if defined(OS_WIN)
+#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
+#elif defined(OS_MACOSX)
+#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
+#elif defined(OS_ANDROID)
+#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
+#elif defined(TOOLKIT_GTK)
+#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
+#endif
+
+using blink::WebContextMenuData;
+using blink::WebDragData;
+using blink::WebDragOperationsMask;
+using blink::WebFloatPoint;
+using blink::WebFrame;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebPoint;
+using blink::WebString;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using blink::WebVector;
+using blink::WebView;
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+ defined(TOOLKIT_GTK)
+using blink::WebInputEventFactory;
+#endif
+
+namespace content {
+
+namespace {
+
+void InitMouseEvent(WebInputEvent::Type t,
+ WebMouseEvent::Button b,
+ const WebPoint& pos,
+ double time_stamp,
+ int click_count,
+ int modifiers,
+ WebMouseEvent* e) {
+ e->type = t;
+ e->button = b;
+ e->modifiers = modifiers;
+ e->x = pos.x;
+ e->y = pos.y;
+ e->globalX = pos.x;
+ e->globalY = pos.y;
+ e->timeStampSeconds = time_stamp;
+ e->clickCount = click_count;
+}
+
+int GetKeyModifier(const std::string& modifier_name) {
+ const char* characters = modifier_name.c_str();
+ if (!strcmp(characters, "ctrlKey")
+#ifndef __APPLE__
+ || !strcmp(characters, "addSelectionKey")
+#endif
+ ) {
+ return WebInputEvent::ControlKey;
+ } else if (!strcmp(characters, "shiftKey") ||
+ !strcmp(characters, "rangeSelectionKey")) {
+ return WebInputEvent::ShiftKey;
+ } else if (!strcmp(characters, "altKey")) {
+ return WebInputEvent::AltKey;
+#ifdef __APPLE__
+ } else if (!strcmp(characters, "metaKey") ||
+ !strcmp(characters, "addSelectionKey")) {
+ return WebInputEvent::MetaKey;
+#else
+ } else if (!strcmp(characters, "metaKey")) {
+ return WebInputEvent::MetaKey;
+#endif
+ } else if (!strcmp(characters, "autoRepeat")) {
+ return WebInputEvent::IsAutoRepeat;
+ } else if (!strcmp(characters, "copyKey")) {
+#ifdef __APPLE__
+ return WebInputEvent::AltKey;
+#else
+ return WebInputEvent::ControlKey;
+#endif
+ }
+
+ return 0;
+}
+
+int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
+ int modifiers = 0;
+ for (std::vector<std::string>::const_iterator it = modifier_names.begin();
+ it != modifier_names.end(); ++it) {
+ modifiers |= GetKeyModifier(*it);
+ }
+ return modifiers;
+}
+
+int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
+ std::vector<std::string> modifier_names;
+ if (value->IsString()) {
+ modifier_names.push_back(gin::V8ToString(value));
+ } else if (value->IsArray()) {
+ gin::Converter<std::vector<std::string> >::FromV8(
+ NULL, value, &modifier_names);
+ }
+ return GetKeyModifiers(modifier_names);
+}
+
+// Maximum distance (in space and time) for a mouse click to register as a
+// double or triple click.
+const double kMultipleClickTimeSec = 1;
+const int kMultipleClickRadiusPixels = 5;
+
+bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
+ return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
+ kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
+}
+
+// Because actual context menu is implemented by the browser side,
+// this function does only what LayoutTests are expecting:
+// - Many test checks the count of items. So returning non-zero value makes
+// sense.
+// - Some test compares the count before and after some action. So changing the
+// count based on flags also makes sense. This function is doing such for some
+// flags.
+// - Some test even checks actual string content. So providing it would be also
+// helpful.
+std::vector<std::string> MakeMenuItemStringsFor(
+ WebContextMenuData* context_menu,
+ WebTestRunner::WebTestDelegate* delegate) {
+ // These constants are based on Safari's context menu because tests are made
+ // for it.
+ static const char* kNonEditableMenuStrings[] = {
+ "Back",
+ "Reload Page",
+ "Open in Dashbaord",
+ "<separator>",
+ "View Source",
+ "Save Page As",
+ "Print Page",
+ "Inspect Element",
+ 0
+ };
+ static const char* kEditableMenuStrings[] = {
+ "Cut",
+ "Copy",
+ "<separator>",
+ "Paste",
+ "Spelling and Grammar",
+ "Substitutions, Transformations",
+ "Font",
+ "Speech",
+ "Paragraph Direction",
+ "<separator>",
+ 0
+ };
+
+ // This is possible because mouse events are cancelleable.
+ if (!context_menu)
+ return std::vector<std::string>();
+
+ std::vector<std::string> strings;
+
+ if (context_menu->isEditable) {
+ for (const char** item = kEditableMenuStrings; *item; ++item) {
+ strings.push_back(*item);
+ }
+ WebVector<WebString> suggestions;
+ WebTestRunner::MockSpellCheck::fillSuggestionList(
+ context_menu->misspelledWord, &suggestions);
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ strings.push_back(suggestions[i].utf8());
+ }
+ } else {
+ for (const char** item = kNonEditableMenuStrings; *item; ++item) {
+ strings.push_back(*item);
+ }
+ }
+
+ return strings;
+}
+
+// How much we should scroll per event - the value here is chosen to match the
+// WebKit impl and layout test results.
+const float kScrollbarPixelsPerTick = 40.0f;
+
+WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
+ if (!button_code)
+ return WebMouseEvent::ButtonLeft;
+ if (button_code == 2)
+ return WebMouseEvent::ButtonRight;
+ return WebMouseEvent::ButtonMiddle;
+}
+
+class MouseDownTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+ MouseDownTask(EventSender* obj, int button_number, int modifiers)
+ : WebMethodTask<EventSender>(obj),
+ button_number_(button_number),
+ modifiers_(modifiers) {}
+
+ virtual void runIfValid() OVERRIDE {
+ m_object->MouseDown(button_number_, modifiers_);
+ }
+
+ private:
+ int button_number_;
+ int modifiers_;
+};
+
+class MouseUpTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+ MouseUpTask(EventSender* obj, int button_number, int modifiers)
+ : WebMethodTask<EventSender>(obj),
+ button_number_(button_number),
+ modifiers_(modifiers) {}
+
+ virtual void runIfValid() OVERRIDE {
+ m_object->MouseUp(button_number_, modifiers_);
+ }
+
+ private:
+ int button_number_;
+ int modifiers_;
+};
+
+class KeyDownTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+ KeyDownTask(EventSender* obj,
+ const std::string code_str,
+ int modifiers,
+ KeyLocationCode location)
+ : WebMethodTask<EventSender>(obj),
+ modifiers_(modifiers),
+ location_(location) {}
+
+ virtual void runIfValid() OVERRIDE {
+ m_object->KeyDown(code_str_, modifiers_, location_);
+ }
+
+ private:
+ std::string code_str_;
+ int modifiers_;
+ KeyLocationCode location_;
+};
+
+bool NeedsShiftModifier(int keyCode) {
+ // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
+ return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
+}
+
+// Get the edit command corresponding to a keyboard event.
+// Returns true if the specified event corresponds to an edit command, the name
+// of the edit command will be stored in |*name|.
+bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
+#if defined(OS_MACOSX)
+// We only cares about Left,Right,Up,Down keys with Command or Command+Shift
+// modifiers. These key events correspond to some special movement and
+// selection editor commands. These keys will be marked as system key, which
+// prevents them from being handled. Thus they must be handled specially.
+ if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
+ WebKeyboardEvent::MetaKey)
+ return false;
+
+ switch (event.windowsKeyCode) {
+ case WebTestRunner::VKEY_LEFT:
+ *name = "MoveToBeginningOfLine";
+ break;
+ case WebTestRunner::VKEY_RIGHT:
+ *name = "MoveToEndOfLine";
+ break;
+ case WebTestRunner::VKEY_UP:
+ *name = "MoveToBeginningOfDocument";
+ break;
+ case WebTestRunner::VKEY_DOWN:
+ *name = "MoveToEndOfDocument";
+ break;
+ default:
+ return false;
+ }
+
+ if (event.modifiers & WebKeyboardEvent::ShiftKey)
+ name->append("AndModifySelection");
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace
+
+class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
+ public:
+ static gin::WrapperInfo kWrapperInfo;
+
+ static void Install(base::WeakPtr<EventSender> sender,
+ blink::WebFrame* frame);
+
+ private:
+ explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
+ virtual ~EventSenderBindings();
+
+ // gin::Wrappable:
+ virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE;
+
+ // Bound methods:
+ void EnableDOMUIEventLogging();
+ void FireKeyboardEventsToElement();
+ void ClearKillRing();
+ std::vector<std::string> ContextClick();
+ void TextZoomIn();
+ void TextZoomOut();
+ void ZoomPageIn();
+ void ZoomPageOut();
+ void SetPageScaleFactor(float scale_factor, int x, int y);
+ void ClearTouchPoints();
+ void ReleaseTouchPoint(unsigned index);
+ void UpdateTouchPoint(unsigned index, int x, int y);
+ void CancelTouchPoint(unsigned index);
+ void SetTouchModifier(const std::string& key_name, bool set_mask);
+ void DumpFilenameBeingDragged();
+ void GestureFlingCancel();
+ void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
+ void GestureScrollFirstPoint(int x, int y);
+ void TouchStart();
+ void TouchMove();
+ void TouchCancel();
+ void TouchEnd();
+ void LeapForward(int milliseconds);
+ void BeginDragWithFiles(const std::vector<std::string>& files);
+ void AddTouchPoint(gin::Arguments* args);
+ void MouseDragBegin();
+ void MouseDragEnd();
+ void MouseMomentumBegin();
+ void GestureScrollBegin(gin::Arguments* args);
+ void GestureScrollEnd(gin::Arguments* args);
+ void GestureScrollUpdate(gin::Arguments* args);
+ void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
+ void GestureTap(gin::Arguments* args);
+ void GestureTapDown(gin::Arguments* args);
+ void GestureShowPress(gin::Arguments* args);
+ void GestureTapCancel(gin::Arguments* args);
+ void GestureLongPress(gin::Arguments* args);
+ void GestureLongTap(gin::Arguments* args);
+ void GestureTwoFingerTap(gin::Arguments* args);
+ void ContinuousMouseScrollBy(gin::Arguments* args);
+ void DispatchMessage(int msg, int wparam, int lparam);
+ void MouseMoveTo(gin::Arguments* args);
+ void MouseScrollBy(gin::Arguments* args);
+ void MouseMomentumScrollBy(gin::Arguments* args);
+ void MouseMomentumEnd();
+ void ScheduleAsynchronousClick(gin::Arguments* args);
+ void ScheduleAsynchronousKeyDown(gin::Arguments* args);
+ void MouseDown(gin::Arguments* args);
+ void MouseUp(gin::Arguments* args);
+ void KeyDown(gin::Arguments* args);
+
+ // Binding properties:
+ bool ForceLayoutOnEvents() const;
+ void SetForceLayoutOnEvents(bool force);
+ bool IsDragMode() const;
+ void SetIsDragMode(bool drag_mode);
+
+#if defined(OS_WIN)
+ int WmKeyDown() const;
+ void SetWmKeyDown(int key_down);
+
+ int WmKeyUp() const;
+ void SetWmKeyUp(int key_up);
+
+ int WmChar() const;
+ void SetWmChar(int wm_char);
+
+ int WmDeadChar() const;
+ void SetWmDeadChar(int dead_char);
+
+ int WmSysKeyDown() const;
+ void SetWmSysKeyDown(int key_down);
+
+ int WmSysKeyUp() const;
+ void SetWmSysKeyUp(int key_up);
+
+ int WmSysChar() const;
+ void SetWmSysChar(int sys_char);
+
+ int WmSysDeadChar() const;
+ void SetWmSysDeadChar(int sys_dead_char);
+#endif
+
+ base::WeakPtr<EventSender> sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
+};
+
+gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
+
+EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
+ : sender_(sender) {
+}
+
+EventSenderBindings::~EventSenderBindings() {}
+
+// static
+void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
+ WebFrame* frame) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope context_scope(context);
+
+ gin::Handle<EventSenderBindings> bindings =
+ gin::CreateHandle(isolate, new EventSenderBindings(sender));
+ v8::Handle<v8::Object> global = context->Global();
+ global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
+}
+
+gin::ObjectTemplateBuilder
+EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+ return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
+ .SetMethod("enableDOMUIEventLogging",
+ &EventSenderBindings::EnableDOMUIEventLogging)
+ .SetMethod("fireKeyboardEventsToElement",
+ &EventSenderBindings::FireKeyboardEventsToElement)
+ .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
+ .SetMethod("contextClick", &EventSenderBindings::ContextClick)
+ .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
+ .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
+ .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
+ .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
+ .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
+ .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
+ .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
+ .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
+ .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
+ .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
+ .SetMethod("dumpFilenameBeingDragged",
+ &EventSenderBindings::DumpFilenameBeingDragged)
+ .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
+ .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
+ .SetMethod("gestureScrollFirstPoint",
+ &EventSenderBindings::GestureScrollFirstPoint)
+ .SetMethod("touchStart", &EventSenderBindings::TouchStart)
+ .SetMethod("touchMove", &EventSenderBindings::TouchMove)
+ .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
+ .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
+ .SetMethod("leapForward", &EventSenderBindings::LeapForward)
+ .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
+ .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
+ .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
+ .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
+ .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
+ .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
+ .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
+ .SetMethod("gestureScrollUpdate",
+ &EventSenderBindings::GestureScrollUpdate)
+ .SetMethod("gestureScrollUpdateWithoutPropagation",
+ &EventSenderBindings::GestureScrollUpdateWithoutPropagation)
+ .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
+ .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
+ .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
+ .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
+ .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
+ .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
+ .SetMethod("gestureTwoFingerTap",
+ &EventSenderBindings::GestureTwoFingerTap)
+ .SetMethod("continuousMouseScrollBy",
+ &EventSenderBindings::ContinuousMouseScrollBy)
+ .SetMethod("dispatchMessage", &EventSenderBindings::DispatchMessage)
+ .SetMethod("keyDown", &EventSenderBindings::KeyDown)
+ .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
+ .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
+ .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
+ .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
+ .SetMethod("mouseMomentumScrollBy",
+ &EventSenderBindings::MouseMomentumScrollBy)
+ .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
+ .SetMethod("scheduleAsynchronousClick",
+ &EventSenderBindings::ScheduleAsynchronousClick)
+ .SetMethod("scheduleAsynchronousKeyDown",
+ &EventSenderBindings::ScheduleAsynchronousKeyDown)
+ .SetProperty("forceLayoutOnEvents",
+ &EventSenderBindings::ForceLayoutOnEvents,
+ &EventSenderBindings::SetForceLayoutOnEvents)
+ .SetProperty("dragMode",
+ &EventSenderBindings::IsDragMode,
+ &EventSenderBindings::SetIsDragMode)
+#if defined(OS_WIN)
+ .SetProperty("WM_KEYDOWN",
+ &EventSenderBindings::WmKeyDown,
+ &EventSenderBindings::SetWmKeyDown)
+ .SetProperty("WM_KEYUP",
+ &EventSenderBindings::WmKeyUp,
+ &EventSenderBindings::SetWmKeyUp)
+ .SetProperty("WM_CHAR",
+ &EventSenderBindings::WmChar,
+ &EventSenderBindings::SetWmChar)
+ .SetProperty("WM_DEADCHAR",
+ &EventSenderBindings::WmDeadChar,
+ &EventSenderBindings::SetWmDeadChar)
+ .SetProperty("WM_SYSKEYDOWN",
+ &EventSenderBindings::WmSysKeyDown,
+ &EventSenderBindings::SetWmSysKeyDown)
+ .SetProperty("WM_SYSKEYUP",
+ &EventSenderBindings::WmSysKeyUp,
+ &EventSenderBindings::SetWmSysKeyUp)
+ .SetProperty("WM_SYSCHAR",
+ &EventSenderBindings::WmSysChar,
+ &EventSenderBindings::SetWmSysChar)
+ .SetProperty("WM_SYSDEADCHAR",
+ &EventSenderBindings::WmSysDeadChar,
+ &EventSenderBindings::SetWmSysDeadChar);
+#else
+ ;
+#endif
+}
+
+void EventSenderBindings::EnableDOMUIEventLogging() {
+ if (sender_)
+ sender_->EnableDOMUIEventLogging();
+}
+
+void EventSenderBindings::FireKeyboardEventsToElement() {
+ if (sender_)
+ sender_->FireKeyboardEventsToElement();
+}
+
+void EventSenderBindings::ClearKillRing() {
+ if (sender_)
+ sender_->ClearKillRing();
+}
+
+std::vector<std::string> EventSenderBindings::ContextClick() {
+ if (sender_)
+ return sender_->ContextClick();
+ return std::vector<std::string>();
+}
+
+void EventSenderBindings::TextZoomIn() {
+ if (sender_)
+ sender_->TextZoomIn();
+}
+void EventSenderBindings::TextZoomOut() {
+ if (sender_)
+ sender_->TextZoomOut();
+}
+void EventSenderBindings::ZoomPageIn() {
+ if (sender_)
+ sender_->ZoomPageIn();
+}
+void EventSenderBindings::ZoomPageOut() {
+ if (sender_)
+ sender_->ZoomPageOut();
+}
+void EventSenderBindings::SetPageScaleFactor(float scale_factor, int x, int y) {
+ if (sender_)
+ sender_->SetPageScaleFactor(scale_factor, x, y);
+}
+void EventSenderBindings::ClearTouchPoints() {
+ if (sender_)
+ sender_->ClearTouchPoints();
+}
+void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
+ if (sender_)
+ sender_->ReleaseTouchPoint(index);
+}
+void EventSenderBindings::UpdateTouchPoint(unsigned index, int x, int y) {
+ if (sender_)
+ sender_->UpdateTouchPoint(index, x, y);
+}
+void EventSenderBindings::CancelTouchPoint(unsigned index) {
+ if (sender_)
+ sender_->CancelTouchPoint(index);
+}
+void EventSenderBindings::SetTouchModifier(const std::string& key_name,
+ bool set_mask) {
+ if (sender_)
+ sender_->SetTouchModifier(key_name, set_mask);
+}
+void EventSenderBindings::DumpFilenameBeingDragged() {
+ if (sender_)
+ sender_->DumpFilenameBeingDragged();
+}
+void EventSenderBindings::GestureFlingCancel() {
+ if (sender_)
+ sender_->GestureFlingCancel();
+}
+void EventSenderBindings::GestureFlingStart(float x,
+ float y,
+ float velocity_x,
+ float velocity_y) {
+ if (sender_)
+ sender_->GestureFlingStart(x, y, velocity_x, velocity_y);
+}
+void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
+ if (sender_)
+ sender_->GestureScrollFirstPoint(x, y);
+}
+void EventSenderBindings::TouchStart() {
+ if (sender_)
+ sender_->TouchStart();
+}
+void EventSenderBindings::TouchMove() {
+ if (sender_)
+ sender_->TouchMove();
+}
+void EventSenderBindings::TouchCancel() {
+ if (sender_)
+ sender_->TouchCancel();
+}
+void EventSenderBindings::TouchEnd() {
+ if (sender_)
+ sender_->TouchEnd();
+}
+void EventSenderBindings::LeapForward(int milliseconds) {
+ if (sender_)
+ sender_->LeapForward(milliseconds);
+}
+void EventSenderBindings::BeginDragWithFiles(
+ const std::vector<std::string>& files) {
+ if (sender_)
+ sender_->BeginDragWithFiles(files);
+}
+void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
+ if (sender_)
+ sender_->AddTouchPoint(args);
+}
+void EventSenderBindings::MouseDragBegin() {
+ if (sender_)
+ sender_->MouseDragBegin();
+}
+void EventSenderBindings::MouseDragEnd() {
+ if (sender_)
+ sender_->MouseDragEnd();
+}
+void EventSenderBindings::MouseMomentumBegin() {
+ if (sender_)
+ sender_->MouseMomentumBegin();
+}
+void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureScrollBegin(args);
+}
+void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureScrollEnd(args);
+}
+void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureScrollUpdate(args);
+}
+void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
+ gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureScrollUpdateWithoutPropagation(args);
+}
+void EventSenderBindings::GestureTap(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureTap(args);
+}
+void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureTapDown(args);
+}
+void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureShowPress(args);
+}
+void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureTapCancel(args);
+}
+void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureLongPress(args);
+}
+void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureLongTap(args);
+}
+void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
+ if (sender_)
+ sender_->GestureTwoFingerTap(args);
+}
+void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
+ if (sender_)
+ sender_->ContinuousMouseScrollBy(args);
+}
+void EventSenderBindings::DispatchMessage(int msg, int wparam, int lparam) {
+ if (sender_)
+ sender_->DispatchMessage(msg, wparam, lparam);
+}
+void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
+ if (sender_)
+ sender_->MouseMoveTo(args);
+}
+void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
+ if (sender_)
+ sender_->MouseScrollBy(args);
+}
+void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
+ if (sender_)
+ sender_->MouseMomentumScrollBy(args);
+}
+void EventSenderBindings::MouseMomentumEnd() {
+ if (sender_)
+ sender_->MouseMomentumEnd();
+}
+void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
+ if (!sender_)
+ return;
+
+ int button_number = 0;
+ int modifiers = 0;
+ if (!args->PeekNext().IsEmpty()) {
+ args->GetNext(&button_number);
+ if (!args->PeekNext().IsEmpty())
+ modifiers = GetKeyModifiersFromV8(args->PeekNext());
+ }
+ sender_->ScheduleAsynchronousClick(button_number, modifiers);
+}
+void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
+ if (!sender_)
+ return;
+
+ std::string code_str;
+ int modifiers = 0;
+ int location = DOMKeyLocationStandard;
+ args->GetNext(&code_str);
+ if (!args->PeekNext().IsEmpty()) {
+ v8::Handle<v8::Value> value;
+ args->GetNext(&value);
+ modifiers = GetKeyModifiersFromV8(value);
+ if (!args->PeekNext().IsEmpty())
+ args->GetNext(&location);
+ }
+ sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
+ static_cast<KeyLocationCode>(location));
+}
+void EventSenderBindings::MouseDown(gin::Arguments* args) {
+ if (!sender_)
+ return;
+
+ int button_number = 0;
+ int modifiers = 0;
+ if (!args->PeekNext().IsEmpty()) {
+ args->GetNext(&button_number);
+ if (!args->PeekNext().IsEmpty())
+ modifiers = GetKeyModifiersFromV8(args->PeekNext());
+ }
+ sender_->MouseDown(button_number, modifiers);
+}
+void EventSenderBindings::MouseUp(gin::Arguments* args) {
+ if (!sender_)
+ return;
+
+ int button_number = 0;
+ int modifiers = 0;
+ if (!args->PeekNext().IsEmpty()) {
+ args->GetNext(&button_number);
+ if (!args->PeekNext().IsEmpty())
+ modifiers = GetKeyModifiersFromV8(args->PeekNext());
+ }
+ sender_->MouseUp(button_number, modifiers);
+}
+void EventSenderBindings::KeyDown(gin::Arguments* args) {
+ if (!sender_)
+ return;
+
+ std::string code_str;
+ int modifiers = 0;
+ int location = DOMKeyLocationStandard;
+ args->GetNext(&code_str);
+ if (!args->PeekNext().IsEmpty()) {
+ v8::Handle<v8::Value> value;
+ args->GetNext(&value);
+ modifiers = GetKeyModifiersFromV8(value);
+ if (!args->PeekNext().IsEmpty())
+ args->GetNext(&location);
+ }
+ sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
+}
+bool EventSenderBindings::ForceLayoutOnEvents() const {
+ if (sender_)
+ return sender_->force_layout_on_events();
+ return false;
+}
+void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
+ if (sender_)
+ sender_->set_force_layout_on_events(force);
+}
+bool EventSenderBindings::IsDragMode() const {
+ if (sender_)
+ return sender_->is_drag_mode();
+ return false;
+}
+void EventSenderBindings::SetIsDragMode(bool drag_mode) {
+ if (sender_)
+ sender_->set_is_drag_mode(drag_mode);
+}
+
+#if defined(OS_WIN)
+int EventSenderBindings::WmKeyDown() const {
+ if (sender_)
+ return sender_->wm_key_down();
+ return 0;
+}
+void EventSenderBindings::SetWmKeyDown(int key_down) {
+ if (sender_)
+ sender_->set_wm_key_down(key_down);
+}
+
+int EventSenderBindings::WmKeyUp() const {
+ if (sender_)
+ return sender_->wm_key_up();
+ return 0;
+}
+void EventSenderBindings::SetWmKeyUp(int key_up) {
+ if (sender_)
+ sender_->set_wm_key_up(key_up);
+}
+
+int EventSenderBindings::WmChar() const {
+ if (sender_)
+ return sender_->wm_char();
+ return 0;
+}
+void EventSenderBindings::SetWmChar(int wm_char) {
+ if (sender_)
+ sender_->set_wm_char(wm_char);
+}
+
+int EventSenderBindings::WmDeadChar() const {
+ if (sender_)
+ return sender_->wm_dead_char();
+ return 0;
+}
+void EventSenderBindings::SetWmDeadChar(int dead_char) {
+ if (sender_)
+ sender_->set_wm_dead_char(dead_char);
+}
+
+int EventSenderBindings::WmSysKeyDown() const {
+ if (sender_)
+ return sender_->wm_sys_key_down();
+ return 0;
+}
+void EventSenderBindings::SetWmSysKeyDown(int key_down) {
+ if (sender_)
+ sender_->set_wm_sys_key_down(key_down);
+}
+
+int EventSenderBindings::WmSysKeyUp() const {
+ if (sender_)
+ return sender_->wm_sys_key_up();
+ return 0;
+}
+void EventSenderBindings::SetWmSysKeyUp(int key_up) {
+ if (sender_)
+ sender_->set_wm_sys_key_up(key_up);
+}
+
+int EventSenderBindings::WmSysChar() const {
+ if (sender_)
+ return sender_->wm_sys_char();
+ return 0;
+}
+void EventSenderBindings::SetWmSysChar(int sys_char) {
+ if (sender_)
+ sender_->set_wm_sys_char(sys_char);
+}
+
+int EventSenderBindings::WmSysDeadChar() const {
+ if (sender_)
+ return sender_->wm_sys_dead_char();
+ return 0;
+}
+void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
+ if (sender_)
+ sender_->set_wm_sys_dead_char(sys_dead_char);
+}
+#endif
+
+// EventSender -----------------------------------------------------------------
+
+WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
+
+WebPoint EventSender::last_mouse_pos_;
+
+WebMouseEvent::Button EventSender::last_button_type_ =
+ WebMouseEvent::ButtonNone;
+
+EventSender::SavedEvent::SavedEvent()
+ : type(TYPE_UNSPECIFIED),
+ button_type(WebMouseEvent::ButtonNone),
+ milliseconds(0),
+ modifiers(0) {}
+
+EventSender::EventSender(WebTestRunner::TestInterfaces* interfaces)
+ : interfaces_(interfaces),
+ delegate_(NULL),
+ view_(NULL),
+ force_layout_on_events_(false),
+ is_drag_mode_(true),
+ touch_modifiers_(0),
+ replaying_saved_events_(false),
+ current_drag_effects_allowed_(blink::WebDragOperationNone),
+ last_click_time_sec_(0),
+ current_drag_effect_(blink::WebDragOperationNone),
+ time_offset_ms_(0),
+ click_count_(0),
+#if defined(OS_WIN)
+ wm_key_down_(0),
+ wm_key_up_(0),
+ wm_char_(0),
+ wm_dead_char_(0),
+ wm_sys_key_down_(0),
+ wm_sys_key_up_(0),
+ wm_sys_char_(0),
+ wm_sys_dead_char_(0),
+#endif
+ weak_factory_(this) {}
+
+EventSender::~EventSender() {}
+
+void EventSender::Reset() {
+ DCHECK(current_drag_data_.isNull());
+ current_drag_data_.reset();
+ current_drag_effect_ = blink::WebDragOperationNone;
+ current_drag_effects_allowed_ = blink::WebDragOperationNone;
+ if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
+ view_->mouseCaptureLost();
+ pressed_button_ = WebMouseEvent::ButtonNone;
+ is_drag_mode_ = true;
+ force_layout_on_events_ = true;
+
+#if defined(OS_WIN)
+ wm_key_down_ = WM_KEYDOWN;
+ wm_key_up_ = WM_KEYUP;
+ wm_char_ = WM_CHAR;
+ wm_dead_char_ = WM_DEADCHAR;
+ wm_sys_key_down_ = WM_SYSKEYDOWN;
+ wm_sys_key_up_ = WM_SYSKEYUP;
+ wm_sys_char_ = WM_SYSCHAR;
+ wm_sys_dead_char_ = WM_SYSDEADCHAR;
+#endif
+
+ last_mouse_pos_ = WebPoint(0, 0);
+ last_click_time_sec_ = 0;
+ last_click_pos_ = WebPoint(0, 0);
+ last_button_type_ = WebMouseEvent::ButtonNone;
+ touch_points_.clear();
+ task_list_.revokeAll();
+ current_gesture_location_ = WebPoint(0, 0);
+ mouse_event_queue_.clear();
+
+ time_offset_ms_ = 0;
+ click_count_ = 0;
+}
+
+void EventSender::Install(WebFrame* frame) {
+ EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
+}
+
+void EventSender::SetDelegate(WebTestRunner::WebTestDelegate* delegate) {
+ delegate_ = delegate;
+}
+
+void EventSender::SetWebView(WebView* view) {
+ view_ = view;
+}
+
+void EventSender::SetContextMenuData(const WebContextMenuData& data) {
+ last_context_menu_data_.reset(new WebContextMenuData(data));
+}
+
+void EventSender::DoDragDrop(const WebDragData& drag_data,
+ WebDragOperationsMask mask) {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseDown,
+ pressed_button_,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ WebPoint client_point(event.x, event.y);
+ WebPoint screen_point(event.globalX, event.globalY);
+ current_drag_data_ = drag_data;
+ current_drag_effects_allowed_ = mask;
+ current_drag_effect_ = view_->dragTargetDragEnter(
+ drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
+
+ // Finish processing events.
+ ReplaySavedEvents();
+}
+
+void EventSender::MouseDown(int button_number, int modifiers) {
+ if (force_layout_on_events_)
+ view_->layout();
+
+ DCHECK_NE(-1, button_number);
+
+ WebMouseEvent::Button button_type =
+ GetButtonTypeFromButtonNumber(button_number);
+
+ UpdateClickCountForButton(button_type);
+
+ pressed_button_ = button_type;
+
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseDown,
+ button_type,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ modifiers,
+ &event);
+ view_->handleInputEvent(event);
+}
+
+void EventSender::MouseUp(int button_number, int modifiers) {
+ if (force_layout_on_events_)
+ view_->layout();
+
+ DCHECK_NE(-1, button_number);
+
+ WebMouseEvent::Button button_type =
+ GetButtonTypeFromButtonNumber(button_number);
+
+ if (is_drag_mode_ && !replaying_saved_events_) {
+ SavedEvent saved_event;
+ saved_event.type = SavedEvent::TYPE_MOUSE_UP;
+ saved_event.button_type = button_type;
+ saved_event.modifiers = modifiers;
+ mouse_event_queue_.push_back(saved_event);
+ ReplaySavedEvents();
+ } else {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseUp,
+ button_type,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ modifiers,
+ &event);
+ DoMouseUp(event);
+ }
+}
+
+void EventSender::KeyDown(const std::string& code_str,
+ int modifiers,
+ KeyLocationCode location) {
+ // FIXME: I'm not exactly sure how we should convert the string to a key
+ // event. This seems to work in the cases I tested.
+ // FIXME: Should we also generate a KEY_UP?
+
+ bool generate_char = false;
+
+ // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
+ // Windows uses \r for "Enter".
+ int code = 0;
+ int text = 0;
+ bool needs_shift_key_modifier = false;
+
+ if ("\n" == code_str) {
+ generate_char = true;
+ text = code = WebTestRunner::VKEY_RETURN;
+ } else if ("rightArrow" == code_str) {
+ code = WebTestRunner::VKEY_RIGHT;
+ } else if ("downArrow" == code_str) {
+ code = WebTestRunner::VKEY_DOWN;
+ } else if ("leftArrow" == code_str) {
+ code = WebTestRunner::VKEY_LEFT;
+ } else if ("upArrow" == code_str) {
+ code = WebTestRunner::VKEY_UP;
+ } else if ("insert" == code_str) {
+ code = WebTestRunner::VKEY_INSERT;
+ } else if ("delete" == code_str) {
+ code = WebTestRunner::VKEY_DELETE;
+ } else if ("pageUp" == code_str) {
+ code = WebTestRunner::VKEY_PRIOR;
+ } else if ("pageDown" == code_str) {
+ code = WebTestRunner::VKEY_NEXT;
+ } else if ("home" == code_str) {
+ code = WebTestRunner::VKEY_HOME;
+ } else if ("end" == code_str) {
+ code = WebTestRunner::VKEY_END;
+ } else if ("printScreen" == code_str) {
+ code = WebTestRunner::VKEY_SNAPSHOT;
+ } else if ("menu" == code_str) {
+ code = WebTestRunner::VKEY_APPS;
+ } else if ("leftControl" == code_str) {
+ code = WebTestRunner::VKEY_LCONTROL;
+ } else if ("rightControl" == code_str) {
+ code = WebTestRunner::VKEY_RCONTROL;
+ } else if ("leftShift" == code_str) {
+ code = WebTestRunner::VKEY_LSHIFT;
+ } else if ("rightShift" == code_str) {
+ code = WebTestRunner::VKEY_RSHIFT;
+ } else if ("leftAlt" == code_str) {
+ code = WebTestRunner::VKEY_LMENU;
+ } else if ("rightAlt" == code_str) {
+ code = WebTestRunner::VKEY_RMENU;
+ } else if ("numLock" == code_str) {
+ code = WebTestRunner::VKEY_NUMLOCK;
+ } else {
+ // Compare the input string with the function-key names defined by the
+ // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
+ // name, set its key code.
+ for (int i = 1; i <= 24; ++i) {
+ std::string function_key_name = base::StringPrintf("F%d", i);
+ if (function_key_name == code_str) {
+ code = WebTestRunner::VKEY_F1 + (i - 1);
+ break;
+ }
+ }
+ if (!code) {
+ WebString web_code_str =
+ WebString::fromUTF8(code_str.data(), code_str.size());
+ DCHECK_EQ(1u, web_code_str.length());
+ text = code = web_code_str.at(0);
+ needs_shift_key_modifier = NeedsShiftModifier(code);
+ if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
+ code -= 'a' - 'A';
+ generate_char = true;
+ }
+
+ if ("(" == code_str) {
+ code = '9';
+ needs_shift_key_modifier = true;
+ }
+ }
+
+ // For one generated keyboard event, we need to generate a keyDown/keyUp
+ // pair;
+ // On Windows, we might also need to generate a char event to mimic the
+ // Windows event flow; on other platforms we create a merged event and test
+ // the event flow that that platform provides.
+ WebKeyboardEvent event_down;
+ event_down.type = WebInputEvent::RawKeyDown;
+ event_down.modifiers = modifiers;
+ event_down.windowsKeyCode = code;
+
+#if defined(OS_LINUX) && defined(TOOLKIT_GTK)
+ event_down.nativeKeyCode = NativeKeyCodeForWindowsKeyCode(code);
+#endif
+
+ if (generate_char) {
+ event_down.text[0] = text;
+ event_down.unmodifiedText[0] = text;
+ }
+
+ event_down.setKeyIdentifierFromWindowsKeyCode();
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+ defined(TOOLKIT_GTK)
+ if (event_down.modifiers != 0)
+ event_down.isSystemKey = WebInputEventFactory::isSystemKeyEvent(event_down);
+#endif
+
+ if (needs_shift_key_modifier)
+ event_down.modifiers |= WebInputEvent::ShiftKey;
+
+ // See if KeyLocation argument is given.
+ if (location == DOMKeyLocationNumpad)
+ event_down.modifiers |= WebInputEvent::IsKeyPad;
+
+ WebKeyboardEvent event_up;
+ event_up = event_down;
+ event_up.type = WebInputEvent::KeyUp;
+ // EventSender.m forces a layout here, with at least one
+ // test (fast/forms/focus-control-to-page.html) relying on this.
+ if (force_layout_on_events_)
+ view_->layout();
+
+ // In the browser, if a keyboard event corresponds to an editor command,
+ // the command will be dispatched to the renderer just before dispatching
+ // the keyboard event, and then it will be executed in the
+ // RenderView::handleCurrentKeyboardEvent() method.
+ // We just simulate the same behavior here.
+ std::string edit_command;
+ if (GetEditCommand(event_down, &edit_command))
+ delegate_->setEditCommand(edit_command, "");
+
+ view_->handleInputEvent(event_down);
+
+ if (code == WebTestRunner::VKEY_ESCAPE && !current_drag_data_.isNull()) {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseDown,
+ pressed_button_,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ FinishDragAndDrop(event, blink::WebDragOperationNone);
+ }
+
+ delegate_->clearEditCommand();
+
+ if (generate_char) {
+ WebKeyboardEvent event_char = event_up;
+ event_char.type = WebInputEvent::Char;
+ event_char.keyIdentifier[0] = '\0';
+ view_->handleInputEvent(event_char);
+ }
+
+ view_->handleInputEvent(event_up);
+}
+
+void EventSender::EnableDOMUIEventLogging() {}
+
+void EventSender::FireKeyboardEventsToElement() {}
+
+void EventSender::ClearKillRing() {}
+
+std::vector<std::string> EventSender::ContextClick() {
+ if (force_layout_on_events_) {
+ view_->layout();
+ }
+
+ UpdateClickCountForButton(WebMouseEvent::ButtonRight);
+
+ // Clears last context menu data because we need to know if the context menu
+ // be requested after following mouse events.
+ last_context_menu_data_.reset();
+
+ // Generate right mouse down and up.
+ WebMouseEvent event;
+ // This is a hack to work around only allowing a single pressed button since
+ // we want to test the case where both the left and right mouse buttons are
+ // pressed.
+ if (pressed_button_ == WebMouseEvent::ButtonNone) {
+ pressed_button_ = WebMouseEvent::ButtonRight;
+ }
+ InitMouseEvent(WebInputEvent::MouseDown,
+ WebMouseEvent::ButtonRight,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ view_->handleInputEvent(event);
+
+#if defined(OS_WIN)
+ InitMouseEvent(WebInputEvent::MouseUp,
+ WebMouseEvent::ButtonRight,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ view_->handleInputEvent(event);
+
+ pressed_button_= WebMouseEvent::ButtonNone;
+#endif
+
+ return MakeMenuItemStringsFor(last_context_menu_data_.release(), delegate_);
+}
+
+void EventSender::TextZoomIn() {
+ view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
+}
+
+void EventSender::TextZoomOut() {
+ view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
+}
+
+void EventSender::ZoomPageIn() {
+ const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
+ interfaces_->windowList();
+
+ for (size_t i = 0; i < window_list.size(); ++i) {
+ window_list.at(i)->webView()->setZoomLevel(
+ window_list.at(i)->webView()->zoomLevel() + 1);
+ }
+}
+
+void EventSender::ZoomPageOut() {
+ const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
+ interfaces_->windowList();
+
+ for (size_t i = 0; i < window_list.size(); ++i) {
+ window_list.at(i)->webView()->setZoomLevel(
+ window_list.at(i)->webView()->zoomLevel() - 1);
+ }
+}
+
+void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
+ view_->setPageScaleFactorLimits(scale_factor, scale_factor);
+ view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
+}
+
+void EventSender::ClearTouchPoints() {
+ touch_points_.clear();
+}
+
+void EventSender::ReleaseTouchPoint(unsigned index) {
+ DCHECK_LT(index, touch_points_.size());
+
+ WebTouchPoint* touch_point = &touch_points_[index];
+ touch_point->state = WebTouchPoint::StateReleased;
+}
+
+void EventSender::UpdateTouchPoint(unsigned index, int x, int y) {
+ DCHECK_LT(index, touch_points_.size());
+
+ WebTouchPoint* touch_point = &touch_points_[index];
+ touch_point->state = WebTouchPoint::StateMoved;
+ touch_point->position = WebFloatPoint(x, y);
+ touch_point->screenPosition = touch_point->position;
+}
+
+void EventSender::CancelTouchPoint(unsigned index) {
+ DCHECK_LT(index, touch_points_.size());
+
+ WebTouchPoint* touch_point = &touch_points_[index];
+ touch_point->state = WebTouchPoint::StateCancelled;
+}
+
+void EventSender::SetTouchModifier(const std::string& key_name,
+ bool set_mask) {
+ int mask = 0;
+ if (key_name == "shift")
+ mask = WebInputEvent::ShiftKey;
+ else if (key_name == "alt")
+ mask = WebInputEvent::AltKey;
+ else if (key_name == "ctrl")
+ mask = WebInputEvent::ControlKey;
+ else if (key_name == "meta")
+ mask = WebInputEvent::MetaKey;
+
+ if (set_mask)
+ touch_modifiers_ |= mask;
+ else
+ touch_modifiers_ &= ~mask;
+}
+
+void EventSender::DumpFilenameBeingDragged() {
+ WebString filename;
+ WebVector<WebDragData::Item> items = current_drag_data_.items();
+ for (size_t i = 0; i < items.size(); ++i) {
+ if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
+ filename = items[i].title;
+ break;
+ }
+ }
+ delegate_->printMessage(std::string("Filename being dragged: ") +
+ filename.utf8().data() + "\n");
+}
+
+void EventSender::GestureFlingCancel() {
+ WebGestureEvent event;
+ event.type = WebInputEvent::GestureFlingCancel;
+ event.timeStampSeconds = GetCurrentEventTimeSec();
+
+ if (force_layout_on_events_)
+ view_->layout();
+
+ view_->handleInputEvent(event);
+}
+
+void EventSender::GestureFlingStart(float x,
+ float y,
+ float velocity_x,
+ float velocity_y) {
+ WebGestureEvent event;
+ event.type = WebInputEvent::GestureFlingStart;
+
+ event.x = x;
+ event.y = y;
+ event.globalX = event.x;
+ event.globalY = event.y;
+
+ event.data.flingStart.velocityX = velocity_x;
+ event.data.flingStart.velocityY = velocity_y;
+ event.timeStampSeconds = GetCurrentEventTimeSec();
+
+ if (force_layout_on_events_)
+ view_->layout();
+
+ view_->handleInputEvent(event);
+}
+
+void EventSender::GestureScrollFirstPoint(int x, int y) {
+ current_gesture_location_ = WebPoint(x, y);
+}
+
+void EventSender::TouchStart() {
+ SendCurrentTouchEvent(WebInputEvent::TouchStart);
+}
+
+void EventSender::TouchMove() {
+ SendCurrentTouchEvent(WebInputEvent::TouchMove);
+}
+
+void EventSender::TouchCancel() {
+ SendCurrentTouchEvent(WebInputEvent::TouchCancel);
+}
+
+void EventSender::TouchEnd() {
+ SendCurrentTouchEvent(WebInputEvent::TouchEnd);
+}
+
+void EventSender::LeapForward(int milliseconds) {
+ if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
+ !replaying_saved_events_) {
+ SavedEvent saved_event;
+ saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
+ saved_event.milliseconds = milliseconds;
+ mouse_event_queue_.push_back(saved_event);
+ } else {
+ DoLeapForward(milliseconds);
+ }
+}
+
+void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
+ current_drag_data_.initialize();
+ WebVector<WebString> absolute_filenames(files.size());
+ for (size_t i = 0; i < files.size(); ++i) {
+ WebDragData::Item item;
+ item.storageType = WebDragData::Item::StorageTypeFilename;
+ item.filenameData = delegate_->getAbsoluteWebStringFromUTF8Path(files[i]);
+ current_drag_data_.addItem(item);
+ absolute_filenames[i] = item.filenameData;
+ }
+ current_drag_data_.setFilesystemId(
+ delegate_->registerIsolatedFileSystem(absolute_filenames));
+ current_drag_effects_allowed_ = blink::WebDragOperationCopy;
+
+ // Provide a drag source.
+ view_->dragTargetDragEnter(current_drag_data_,
+ last_mouse_pos_,
+ last_mouse_pos_,
+ current_drag_effects_allowed_,
+ 0);
+ // |is_drag_mode_| saves events and then replays them later. We don't
+ // need/want that.
+ is_drag_mode_ = false;
+
+ // Make the rest of eventSender think a drag is in progress.
+ pressed_button_ = WebMouseEvent::ButtonLeft;
+}
+
+void EventSender::AddTouchPoint(gin::Arguments* args) {
+ int x;
+ int y;
+ args->GetNext(&x);
+ args->GetNext(&y);
+
+ WebTouchPoint touch_point;
+ touch_point.state = WebTouchPoint::StatePressed;
+ touch_point.position = WebFloatPoint(x, y);
+ touch_point.screenPosition = touch_point.position;
+
+ if (!args->PeekNext().IsEmpty()) {
+ int radius_x;
+ if (!args->GetNext(&radius_x)) {
+ args->ThrowError();
+ return;
+ }
+
+ int radius_y = radius_x;
+ if (!args->PeekNext().IsEmpty()) {
+ if (!args->GetNext(&radius_y)) {
+ args->ThrowError();
+ return;
+ }
+ }
+
+ touch_point.radiusX = radius_x;
+ touch_point.radiusY = radius_y;
+ }
+
+ int lowest_id = 0;
+ for (size_t i = 0; i < touch_points_.size(); i++) {
+ if (touch_points_[i].id == lowest_id)
+ lowest_id++;
+ }
+ touch_point.id = lowest_id;
+ touch_points_.push_back(touch_point);
+}
+
+void EventSender::MouseDragBegin() {
+ WebMouseWheelEvent event;
+ InitMouseEvent(WebInputEvent::MouseWheel,
+ WebMouseEvent::ButtonNone,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ event.phase = WebMouseWheelEvent::PhaseBegan;
+ event.hasPreciseScrollingDeltas = true;
+ view_->handleInputEvent(event);
+}
+
+void EventSender::MouseDragEnd() {
+ WebMouseWheelEvent event;
+ InitMouseEvent(WebInputEvent::MouseWheel,
+ WebMouseEvent::ButtonNone,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ event.phase = WebMouseWheelEvent::PhaseEnded;
+ event.hasPreciseScrollingDeltas = true;
+ view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumBegin() {
+ WebMouseWheelEvent event;
+ InitMouseEvent(WebInputEvent::MouseWheel,
+ WebMouseEvent::ButtonNone,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
+ event.hasPreciseScrollingDeltas = true;
+ view_->handleInputEvent(event);
+}
+
+void EventSender::GestureScrollBegin(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureScrollBegin, args);
+}
+
+void EventSender::GestureScrollEnd(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureScrollEnd, args);
+}
+
+void EventSender::GestureScrollUpdate(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureScrollUpdate, args);
+}
+
+void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
+}
+
+void EventSender::GestureTap(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureTap, args);
+}
+
+void EventSender::GestureTapDown(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureTapDown, args);
+}
+
+void EventSender::GestureShowPress(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureShowPress, args);
+}
+
+void EventSender::GestureTapCancel(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureTapCancel, args);
+}
+
+void EventSender::GestureLongPress(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureLongPress, args);
+}
+
+void EventSender::GestureLongTap(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureLongTap, args);
+}
+
+void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
+ GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
+}
+
+void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
+ WebMouseWheelEvent event;
+ InitMouseWheelEvent(args, true, &event);
+ view_->handleInputEvent(event);
+}
+
+void EventSender::DispatchMessage(int msg, int wparam, int lparam) {
+#if defined(OS_WIN)
+ // WebKit's version of this function stuffs a MSG struct and uses
+ // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
+ // doesn't need to receive the DeadChar and SysDeadChar messages.
+ if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
+ return;
+
+ if (force_layout_on_events_)
+ view_->layout();
+
+ view_->handleInputEvent(
+ WebInputEventFactory::keyboardEvent(0, msg, wparam, lparam));
+#endif
+}
+
+void EventSender::MouseMoveTo(gin::Arguments* args) {
+ if (force_layout_on_events_)
+ view_->layout();
+
+ int x;
+ int y;
+ args->GetNext(&x);
+ args->GetNext(&y);
+ WebPoint mouse_pos(x, y);
+
+ int modifiers = 0;
+ if (!args->PeekNext().IsEmpty())
+ modifiers = GetKeyModifiersFromV8(args->PeekNext());
+
+ if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
+ !replaying_saved_events_) {
+ SavedEvent saved_event;
+ saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
+ saved_event.pos = mouse_pos;
+ saved_event.modifiers = modifiers;
+ mouse_event_queue_.push_back(saved_event);
+ } else {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseMove,
+ pressed_button_,
+ mouse_pos,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ modifiers,
+ &event);
+ DoMouseMove(event);
+ }
+}
+
+void EventSender::MouseScrollBy(gin::Arguments* args) {
+ WebMouseWheelEvent event;
+ InitMouseWheelEvent(args, false, &event);
+ view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
+ WebMouseWheelEvent event;
+ InitMouseWheelEvent(args, true, &event);
+ event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
+ event.hasPreciseScrollingDeltas = true;
+ view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumEnd() {
+ WebMouseWheelEvent event;
+ InitMouseEvent(WebInputEvent::MouseWheel,
+ WebMouseEvent::ButtonNone,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &event);
+ event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
+ event.hasPreciseScrollingDeltas = true;
+ view_->handleInputEvent(event);
+}
+
+void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
+ delegate_->postTask(new MouseDownTask(this, button_number, modifiers));
+ delegate_->postTask(new MouseUpTask(this, button_number, modifiers));
+}
+
+void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
+ int modifiers,
+ KeyLocationCode location) {
+ delegate_->postTask(new KeyDownTask(this, code_str, modifiers, location));
+}
+
+double EventSender::GetCurrentEventTimeSec() {
+ return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
+}
+
+void EventSender::DoLeapForward(int milliseconds) {
+ time_offset_ms_ += milliseconds;
+}
+
+void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
+ DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
+ touch_points_.size());
+ if (force_layout_on_events_)
+ view_->layout();
+
+ WebTouchEvent touch_event;
+ touch_event.type = type;
+ touch_event.modifiers = touch_modifiers_;
+ touch_event.timeStampSeconds = GetCurrentEventTimeSec();
+ touch_event.touchesLength = touch_points_.size();
+ for (size_t i = 0; i < touch_points_.size(); ++i)
+ touch_event.touches[i] = touch_points_[i];
+ view_->handleInputEvent(touch_event);
+
+ for (size_t i = 0; i < touch_points_.size(); ++i) {
+ WebTouchPoint* touch_point = &touch_points_[i];
+ if (touch_point->state == WebTouchPoint::StateReleased) {
+ touch_points_.erase(touch_points_.begin() + i);
+ --i;
+ } else
+ touch_point->state = WebTouchPoint::StateStationary;
+ }
+}
+
+void EventSender::GestureEvent(WebInputEvent::Type type,
+ gin::Arguments* args) {
+ double x;
+ double y;
+ args->GetNext(&x);
+ args->GetNext(&y);
+ WebPoint point(x, y);
+
+ WebGestureEvent event;
+ event.type = type;
+
+ switch (type) {
+ case WebInputEvent::GestureScrollUpdate:
+ case WebInputEvent::GestureScrollUpdateWithoutPropagation:
+ event.data.scrollUpdate.deltaX = static_cast<float>(x);
+ event.data.scrollUpdate.deltaY = static_cast<float>(y);
+ event.x = current_gesture_location_.x;
+ event.y = current_gesture_location_.y;
+ current_gesture_location_.x =
+ current_gesture_location_.x + event.data.scrollUpdate.deltaX;
+ current_gesture_location_.y =
+ current_gesture_location_.y + event.data.scrollUpdate.deltaY;
+ break;
+ case WebInputEvent::GestureScrollBegin:
+ current_gesture_location_ = WebPoint(point.x, point.y);
+ event.x = current_gesture_location_.x;
+ event.y = current_gesture_location_.y;
+ break;
+ case WebInputEvent::GestureScrollEnd:
+ case WebInputEvent::GestureFlingStart:
+ event.x = current_gesture_location_.x;
+ event.y = current_gesture_location_.y;
+ break;
+ case WebInputEvent::GestureTap:
+ if (!args->PeekNext().IsEmpty()) {
+ float tap_count;
+ if (!args->GetNext(&tap_count)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.tap.tapCount = tap_count;
+ } else {
+ event.data.tap.tapCount = 1;
+ }
+
+ event.x = point.x;
+ event.y = point.y;
+ break;
+ case WebInputEvent::GestureTapUnconfirmed:
+ if (!args->PeekNext().IsEmpty()) {
+ float tap_count;
+ if (!args->GetNext(&tap_count)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.tap.tapCount = tap_count;
+ } else {
+ event.data.tap.tapCount = 1;
+ }
+ event.x = point.x;
+ event.y = point.y;
+ break;
+ case WebInputEvent::GestureTapDown:
+ event.x = point.x;
+ event.y = point.y;
+ if (!args->PeekNext().IsEmpty()) {
+ float width;
+ if (!args->GetNext(&width)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.tapDown.width = width;
+ }
+ if (!args->PeekNext().IsEmpty()) {
+ float height;
+ if (!args->GetNext(&height)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.tapDown.height = height;
+ }
+ break;
+ case WebInputEvent::GestureShowPress:
+ event.x = point.x;
+ event.y = point.y;
+ if (!args->PeekNext().IsEmpty()) {
+ float width;
+ if (!args->GetNext(&width)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.showPress.width = width;
+ if (!args->PeekNext().IsEmpty()) {
+ float height;
+ if (!args->GetNext(&height)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.showPress.height = height;
+ }
+ }
+ break;
+ case WebInputEvent::GestureTapCancel:
+ event.x = point.x;
+ event.y = point.y;
+ break;
+ case WebInputEvent::GestureLongPress:
+ event.x = point.x;
+ event.y = point.y;
+ if (!args->PeekNext().IsEmpty()) {
+ float width;
+ if (!args->GetNext(&width)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.longPress.width = width;
+ if (!args->PeekNext().IsEmpty()) {
+ float height;
+ if (!args->GetNext(&height)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.longPress.height = height;
+ }
+ }
+ break;
+ case WebInputEvent::GestureLongTap:
+ event.x = point.x;
+ event.y = point.y;
+ if (!args->PeekNext().IsEmpty()) {
+ float width;
+ if (!args->GetNext(&width)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.longPress.width = width;
+ if (!args->PeekNext().IsEmpty()) {
+ float height;
+ if (!args->GetNext(&height)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.longPress.height = height;
+ }
+ }
+ break;
+ case WebInputEvent::GestureTwoFingerTap:
+ event.x = point.x;
+ event.y = point.y;
+ if (!args->PeekNext().IsEmpty()) {
+ float first_finger_width;
+ if (!args->GetNext(&first_finger_width)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.twoFingerTap.firstFingerWidth = first_finger_width;
+ if (!args->PeekNext().IsEmpty()) {
+ float first_finger_height;
+ if (!args->GetNext(&first_finger_height)) {
+ args->ThrowError();
+ return;
+ }
+ event.data.twoFingerTap.firstFingerHeight = first_finger_height;
+ }
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ event.globalX = event.x;
+ event.globalY = event.y;
+ event.timeStampSeconds = GetCurrentEventTimeSec();
+
+ if (force_layout_on_events_)
+ view_->layout();
+
+ view_->handleInputEvent(event);
+
+ // Long press might start a drag drop session. Complete it if so.
+ if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
+ WebMouseEvent mouse_event;
+ InitMouseEvent(WebInputEvent::MouseDown,
+ pressed_button_,
+ point,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ 0,
+ &mouse_event);
+
+ FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
+ }
+}
+
+void EventSender::UpdateClickCountForButton(
+ WebMouseEvent::Button button_type) {
+ if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
+ kMultipleClickTimeSec) &&
+ (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
+ (button_type == last_button_type_)) {
+ ++click_count_;
+ } else {
+ click_count_ = 1;
+ last_button_type_ = button_type;
+ }
+}
+
+void EventSender::InitMouseWheelEvent(gin::Arguments* args,
+ bool continuous,
+ WebMouseWheelEvent* event) {
+ // Force a layout here just to make sure every position has been
+ // determined before we send events (as well as all the other methods
+ // that send an event do).
+ if (force_layout_on_events_)
+ view_->layout();
+
+ double horizontal;
+ if (!args->GetNext(&horizontal)) {
+ args->ThrowError();
+ return;
+ }
+ double vertical;
+ if (!args->GetNext(&vertical)) {
+ args->ThrowError();
+ return;
+ }
+
+ bool paged = false;
+ bool has_precise_scrolling_deltas = false;
+ int modifiers = 0;
+ if (!args->PeekNext().IsEmpty()) {
+ args->GetNext(&paged);
+ if (!args->PeekNext().IsEmpty()) {
+ args->GetNext(&has_precise_scrolling_deltas);
+ if (!args->PeekNext().IsEmpty())
+ modifiers = GetKeyModifiersFromV8(args->PeekNext());
+ }
+ }
+
+ InitMouseEvent(WebInputEvent::MouseWheel,
+ pressed_button_,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ modifiers,
+ event);
+ event->wheelTicksX = static_cast<float>(horizontal);
+ event->wheelTicksY = static_cast<float>(vertical);
+ event->deltaX = event->wheelTicksX;
+ event->deltaY = event->wheelTicksY;
+ event->scrollByPage = paged;
+ event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
+
+ if (continuous) {
+ event->wheelTicksX /= kScrollbarPixelsPerTick;
+ event->wheelTicksY /= kScrollbarPixelsPerTick;
+ } else {
+ event->deltaX *= kScrollbarPixelsPerTick;
+ event->deltaY *= kScrollbarPixelsPerTick;
+ }
+}
+
+void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
+ blink::WebDragOperation drag_effect) {
+ WebPoint client_point(e.x, e.y);
+ WebPoint screen_point(e.globalX, e.globalY);
+ current_drag_effect_ = drag_effect;
+ if (current_drag_effect_) {
+ // Specifically pass any keyboard modifiers to the drop method. This allows
+ // tests to control the drop type (i.e. copy or move).
+ view_->dragTargetDrop(client_point, screen_point, e.modifiers);
+ } else {
+ view_->dragTargetDragLeave();
+ }
+ view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
+ view_->dragSourceSystemDragEnded();
+
+ current_drag_data_.reset();
+}
+
+void EventSender::DoMouseUp(const WebMouseEvent& e) {
+ view_->handleInputEvent(e);
+
+ pressed_button_ = WebMouseEvent::ButtonNone;
+ last_click_time_sec_ = e.timeStampSeconds;
+ last_click_pos_ = last_mouse_pos_;
+
+ // If we're in a drag operation, complete it.
+ if (current_drag_data_.isNull())
+ return;
+
+ WebPoint client_point(e.x, e.y);
+ WebPoint screen_point(e.globalX, e.globalY);
+ FinishDragAndDrop(
+ e,
+ view_->dragTargetDragOver(
+ client_point, screen_point, current_drag_effects_allowed_, 0));
+}
+
+void EventSender::DoMouseMove(const WebMouseEvent& e) {
+ last_mouse_pos_ = WebPoint(e.x, e.y);
+
+ view_->handleInputEvent(e);
+
+ if (pressed_button_ == WebMouseEvent::ButtonNone ||
+ current_drag_data_.isNull()) {
+ return;
+ }
+
+ WebPoint client_point(e.x, e.y);
+ WebPoint screen_point(e.globalX, e.globalY);
+ current_drag_effect_ = view_->dragTargetDragOver(
+ client_point, screen_point, current_drag_effects_allowed_, 0);
+}
+
+void EventSender::ReplaySavedEvents() {
+ replaying_saved_events_ = true;
+ while (!mouse_event_queue_.empty()) {
+ SavedEvent e = mouse_event_queue_.front();
+ mouse_event_queue_.pop_front();
+
+ switch (e.type) {
+ case SavedEvent::TYPE_MOUSE_MOVE: {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseMove,
+ pressed_button_,
+ e.pos,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ e.modifiers,
+ &event);
+ DoMouseMove(event);
+ break;
+ }
+ case SavedEvent::TYPE_LEAP_FORWARD:
+ DoLeapForward(e.milliseconds);
+ break;
+ case SavedEvent::TYPE_MOUSE_UP: {
+ WebMouseEvent event;
+ InitMouseEvent(WebInputEvent::MouseUp,
+ e.button_type,
+ last_mouse_pos_,
+ GetCurrentEventTimeSec(),
+ click_count_,
+ e.modifiers,
+ &event);
+ DoMouseUp(event);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ }
+
+ replaying_saved_events_ = false;
+}
+
+} // namespace content
diff --git a/content/shell/renderer/test_runner/event_sender.h b/content/shell/renderer/test_runner/event_sender.h
new file mode 100644
index 0000000..e1423a5
--- /dev/null
+++ b/content/shell/renderer/test_runner/event_sender.h
@@ -0,0 +1,276 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_
+#define CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "content/shell/renderer/test_runner/WebTask.h"
+#include "third_party/WebKit/public/platform/WebDragData.h"
+#include "third_party/WebKit/public/platform/WebPoint.h"
+#include "third_party/WebKit/public/web/WebDragOperation.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebTouchPoint.h"
+
+namespace blink {
+class WebFrame;
+class WebView;
+struct WebContextMenuData;
+}
+
+namespace gin {
+class Arguments;
+}
+
+namespace WebTestRunner {
+class TestInterfaces;
+class WebTestDelegate;
+}
+
+namespace content {
+
+// Key event location code introduced in DOM Level 3.
+// See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
+enum KeyLocationCode {
+ DOMKeyLocationStandard = 0x00,
+ DOMKeyLocationLeft = 0x01,
+ DOMKeyLocationRight = 0x02,
+ DOMKeyLocationNumpad = 0x03
+};
+
+class EventSender : public base::SupportsWeakPtr<EventSender> {
+ public:
+ explicit EventSender(WebTestRunner::TestInterfaces*);
+ virtual ~EventSender();
+
+ void Reset();
+ void Install(blink::WebFrame*);
+ void SetDelegate(WebTestRunner::WebTestDelegate*);
+ void SetWebView(blink::WebView*);
+
+ void SetContextMenuData(const blink::WebContextMenuData&);
+
+ void DoDragDrop(const blink::WebDragData&, blink::WebDragOperationsMask);
+
+ void MouseDown(int button_number, int modifiers);
+ void MouseUp(int button_number, int modifiers);
+ void KeyDown(const std::string& code_str,
+ int modifiers,
+ KeyLocationCode location);
+
+ WebTestRunner::WebTaskList* taskList() { return &task_list_; }
+
+ private:
+ friend class EventSenderBindings;
+
+ struct SavedEvent {
+ enum SavedEventType {
+ TYPE_UNSPECIFIED,
+ TYPE_MOUSE_UP,
+ TYPE_MOUSE_MOVE,
+ TYPE_LEAP_FORWARD
+ };
+
+ SavedEvent();
+
+ SavedEventType type;
+ blink::WebMouseEvent::Button button_type; // For MouseUp.
+ blink::WebPoint pos; // For MouseMove.
+ int milliseconds; // For LeapForward.
+ int modifiers;
+ };
+
+ void EnableDOMUIEventLogging();
+ void FireKeyboardEventsToElement();
+ void ClearKillRing();
+
+ std::vector<std::string> ContextClick();
+
+ void TextZoomIn();
+ void TextZoomOut();
+
+ void ZoomPageIn();
+ void ZoomPageOut();
+
+ void SetPageScaleFactor(float scale_factor, int x, int y);
+
+ void ClearTouchPoints();
+ void ReleaseTouchPoint(unsigned index);
+ void UpdateTouchPoint(unsigned index, int x, int y);
+ void CancelTouchPoint(unsigned index);
+ void SetTouchModifier(const std::string& key_name, bool set_mask);
+
+ void DumpFilenameBeingDragged();
+
+ void GestureFlingCancel();
+ void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
+ void GestureScrollFirstPoint(int x, int y);
+
+ void TouchStart();
+ void TouchMove();
+ void TouchCancel();
+ void TouchEnd();
+
+ void LeapForward(int milliseconds);
+
+ void BeginDragWithFiles(const std::vector<std::string>& files);
+
+ void AddTouchPoint(gin::Arguments* args);
+
+ void MouseDragBegin();
+ void MouseDragEnd();
+ void MouseMomentumBegin();
+
+ void GestureScrollBegin(gin::Arguments* args);
+ void GestureScrollEnd(gin::Arguments* args);
+ void GestureScrollUpdate(gin::Arguments* args);
+ void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
+ void GestureTap(gin::Arguments* args);
+ void GestureTapDown(gin::Arguments* args);
+ void GestureShowPress(gin::Arguments* args);
+ void GestureTapCancel(gin::Arguments* args);
+ void GestureLongPress(gin::Arguments* args);
+ void GestureLongTap(gin::Arguments* args);
+ void GestureTwoFingerTap(gin::Arguments* args);
+
+ void ContinuousMouseScrollBy(gin::Arguments* args);
+ void DispatchMessage(int msg, int wparam, int lparam);
+ void MouseMoveTo(gin::Arguments* args);
+ void MouseScrollBy(gin::Arguments* args);
+ void MouseMomentumScrollBy(gin::Arguments* args);
+ void MouseMomentumEnd();
+ void ScheduleAsynchronousClick(int button_number, int modifiers);
+ void ScheduleAsynchronousKeyDown(const std::string& code_str,
+ int modifiers,
+ KeyLocationCode location);
+
+ double GetCurrentEventTimeSec();
+
+ void DoLeapForward(int milliseconds);
+
+ void SendCurrentTouchEvent(blink::WebInputEvent::Type);
+
+ void GestureEvent(blink::WebInputEvent::Type, gin::Arguments*);
+
+ void UpdateClickCountForButton(blink::WebMouseEvent::Button);
+
+ void InitMouseWheelEvent(gin::Arguments* args,
+ bool continuous,
+ blink::WebMouseWheelEvent* event);
+
+ void FinishDragAndDrop(const blink::WebMouseEvent&, blink::WebDragOperation);
+
+ void DoMouseUp(const blink::WebMouseEvent&);
+ void DoMouseMove(const blink::WebMouseEvent&);
+ void ReplaySavedEvents();
+
+ bool force_layout_on_events() const { return force_layout_on_events_; }
+ void set_force_layout_on_events(bool force) {
+ force_layout_on_events_ = force;
+ }
+
+ bool is_drag_mode() const { return is_drag_mode_; }
+ void set_is_drag_mode(bool drag_mode) { is_drag_mode_ = drag_mode; }
+
+#if defined(OS_WIN)
+ int wm_key_down() const { return wm_key_down_; }
+ void set_wm_key_down(int key_down) { wm_key_down_ = key_down; }
+
+ int wm_key_up() const { return wm_key_up_; }
+ void set_wm_key_up(int key_up) { wm_key_up_ = key_up; }
+
+ int wm_char() const { return wm_char_; }
+ void set_wm_char(int wm_char) { wm_char_ = wm_char; }
+
+ int wm_dead_char() const { return wm_dead_char_; }
+ void set_wm_dead_char(int dead_char) {
+ wm_dead_char_ = dead_char;
+ }
+
+ int wm_sys_key_down() const { return wm_sys_key_down_; }
+ void set_wm_sys_key_down(int key_down) { wm_sys_key_down_ = key_down; }
+
+ int wm_sys_key_up() const { return wm_sys_key_up_; }
+ void set_wm_sys_key_up(int key_up) { wm_sys_key_up_ = key_up; }
+
+ int wm_sys_char() const { return wm_sys_char_; }
+ void set_wm_sys_char(int sys_char) { wm_sys_char_ = sys_char; }
+
+ int wm_sys_dead_char() const { return wm_sys_dead_char_; }
+ void set_wm_sys_dead_char(int sys_dead_char) {
+ wm_sys_dead_char_ = sys_dead_char;
+ }
+
+ int wm_key_down_;
+ int wm_key_up_;
+ int wm_char_;
+ int wm_dead_char_;
+ int wm_sys_key_down_;
+ int wm_sys_key_up_;
+ int wm_sys_char_;
+ int wm_sys_dead_char_;
+#endif
+
+ WebTestRunner::WebTaskList task_list_;
+
+ WebTestRunner::TestInterfaces* interfaces_;
+ WebTestRunner::WebTestDelegate* delegate_;
+ blink::WebView* view_;
+
+ bool force_layout_on_events_;
+
+ // When set to true (the default value), we batch mouse move and mouse up
+ // events so we can simulate drag & drop.
+ bool is_drag_mode_;
+
+ int touch_modifiers_;
+ std::vector<blink::WebTouchPoint> touch_points_;
+
+ scoped_ptr<blink::WebContextMenuData> last_context_menu_data_;
+
+ blink::WebDragData current_drag_data_;
+
+ // Location of the touch point that initiated a gesture.
+ blink::WebPoint current_gesture_location_;
+
+ // Currently pressed mouse button (Left/Right/Middle or None).
+ static blink::WebMouseEvent::Button pressed_button_;
+
+ bool replaying_saved_events_;
+
+ std::deque<SavedEvent> mouse_event_queue_;
+
+ blink::WebDragOperationsMask current_drag_effects_allowed_;
+
+ // Location of last mouseMoveTo event.
+ static blink::WebPoint last_mouse_pos_;
+
+ // Time and place of the last mouse up event.
+ double last_click_time_sec_;
+ blink::WebPoint last_click_pos_;
+
+ // The last button number passed to mouseDown and mouseUp.
+ // Used to determine whether the click count continues to increment or not.
+ static blink::WebMouseEvent::Button last_button_type_;
+
+ blink::WebDragOperation current_drag_effect_;
+
+ uint32 time_offset_ms_;
+ int click_count_;
+
+ base::WeakPtrFactory<EventSender> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventSender);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_