Commit 432b256b authored by Lan Wei's avatar Lan Wei Committed by Commit Bot

[ChromeDriver] Refactor ExecutePerformActions function

In ExecutePerformActions function, we dispatch key events first, mouse
events then touch events, but we should dispatch whatever actions come
first in the action sequence. This CL changes high level of structures
of processing actions and dispatching events in the action sequence,
and I still need to refactor some details when procession the actions
in a following CL.

Bug: 606367
Change-Id: I46e02e547d0e5d5c2ddcdc949efc6b141142ea2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1759855Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Commit-Queue: Lan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#688692}
parent d634937a
...@@ -23,8 +23,6 @@ MouseEvent::MouseEvent(MouseEventType type, ...@@ -23,8 +23,6 @@ MouseEvent::MouseEvent(MouseEventType type,
modifiers(modifiers), modifiers(modifiers),
buttons(buttons), buttons(buttons),
click_count(click_count), click_count(click_count),
origin(kViewPort),
element_id(std::string()),
pointer_type(kMouse) {} pointer_type(kMouse) {}
MouseEvent::MouseEvent(const MouseEvent& other) = default; MouseEvent::MouseEvent(const MouseEvent& other) = default;
...@@ -35,13 +33,11 @@ TouchEvent::TouchEvent(TouchEventType type, int x, int y) ...@@ -35,13 +33,11 @@ TouchEvent::TouchEvent(TouchEventType type, int x, int y)
: type(type), : type(type),
x(x), x(x),
y(y), y(y),
origin(kViewPort),
radiusX(1.0), radiusX(1.0),
radiusY(1.0), radiusY(1.0),
rotationAngle(0.0), rotationAngle(0.0),
force(1.0), force(1.0),
id(0), id(0),
element_id(std::string()),
dispatch(true) {} dispatch(true) {}
TouchEvent::TouchEvent(const TouchEvent& other) = default; TouchEvent::TouchEvent(const TouchEvent& other) = default;
......
...@@ -54,8 +54,6 @@ struct MouseEvent { ...@@ -54,8 +54,6 @@ struct MouseEvent {
int buttons; int buttons;
// |click_count| should not be negative. // |click_count| should not be negative.
int click_count; int click_count;
OriginType origin;
std::string element_id;
PointerType pointer_type; PointerType pointer_type;
}; };
...@@ -78,13 +76,11 @@ struct TouchEvent { ...@@ -78,13 +76,11 @@ struct TouchEvent {
TouchEventType type; TouchEventType type;
int x; int x;
int y; int y;
OriginType origin;
double radiusX; double radiusX;
double radiusY; double radiusY;
double rotationAngle; double rotationAngle;
double force; double force;
int id; int id;
std::string element_id;
bool dispatch; bool dispatch;
}; };
......
...@@ -617,7 +617,7 @@ Status ConvertKeysToKeyEvents(const base::string16& client_keys, ...@@ -617,7 +617,7 @@ Status ConvertKeysToKeyEvents(const base::string16& client_keys,
Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object, Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object,
base::DictionaryValue* input_state, base::DictionaryValue* input_state,
bool is_key_down, bool is_key_down,
std::vector<KeyEvent>* key_events) { std::list<KeyEvent>* key_events) {
std::string raw_key; std::string raw_key;
if (!action_object->GetString("value", &raw_key)) if (!action_object->GetString("value", &raw_key))
return Status(kUnknownError, "missing 'value'"); return Status(kUnknownError, "missing 'value'");
......
...@@ -28,6 +28,6 @@ Status ConvertKeysToKeyEvents(const base::string16& keys, ...@@ -28,6 +28,6 @@ Status ConvertKeysToKeyEvents(const base::string16& keys,
Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object, Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object,
base::DictionaryValue* input_state, base::DictionaryValue* input_state,
bool is_key_down, bool is_key_down,
std::vector<KeyEvent>* client_key_events); std::list<KeyEvent>* client_key_events);
#endif // CHROME_TEST_CHROMEDRIVER_KEY_CONVERTER_H_ #endif // CHROME_TEST_CHROMEDRIVER_KEY_CONVERTER_H_
...@@ -374,39 +374,6 @@ Status ProcessPauseAction(const base::DictionaryValue* action_item, ...@@ -374,39 +374,6 @@ Status ProcessPauseAction(const base::DictionaryValue* action_item,
return Status(kOk); return Status(kOk);
} }
// Implements "compute the tick duration" algorithm from W3C spec
// (https://w3c.github.io/webdriver/#dfn-computing-the-tick-duration).
// For convenience, this function computes durations of all ticks, while the
// original algorithm computes duration of one tick.
void ComputeTickDurations(std::vector<int>* tick_durations,
const base::ListValue& actions_list) {
for (size_t i = 0; i < actions_list.GetSize(); i++) {
const base::DictionaryValue* action_sequence = nullptr;
actions_list.GetDictionary(i, &action_sequence);
const base::ListValue* actions = nullptr;
action_sequence->GetList("actions", &actions);
std::string type;
action_sequence->GetString("sourceType", &type);
for (size_t j = 0; j < actions->GetSize(); j++) {
const base::DictionaryValue* action = nullptr;
actions->GetDictionary(j, &action);
std::string subtype;
action->GetString("subtype", &subtype);
if (subtype == "pause" ||
(type == "pointer" && subtype == "pointerMove")) {
if (j >= tick_durations->size())
tick_durations->resize(j + 1);
int duration = 0;
GetOptionalInt(action, "duration", &duration);
if (duration > (*tick_durations)[j])
(*tick_durations)[j] = duration;
}
}
}
}
Status ElementInViewCenter(Session* session, Status ElementInViewCenter(Session* session,
WebView* web_view, WebView* web_view,
std::string element_id, std::string element_id,
...@@ -1033,7 +1000,7 @@ Status ExecuteTouchScroll(Session* session, ...@@ -1033,7 +1000,7 @@ Status ExecuteTouchScroll(Session* session,
Status ProcessInputActionSequence( Status ProcessInputActionSequence(
Session* session, Session* session,
const base::DictionaryValue* action_sequence, const base::DictionaryValue* action_sequence,
std::unique_ptr<base::DictionaryValue>* action_sequence_result) { std::vector<std::unique_ptr<base::DictionaryValue>>* action_list) {
std::string id; std::string id;
std::string type; std::string type;
const base::DictionaryValue* source; const base::DictionaryValue* source;
...@@ -1062,9 +1029,6 @@ Status ProcessInputActionSequence( ...@@ -1062,9 +1029,6 @@ Status ProcessInputActionSequence(
pointer_type = "mouse"; pointer_type = "mouse";
} }
} }
(*action_sequence_result)->SetString("sourceType", type);
(*action_sequence_result)->SetString("pointerType", pointer_type);
(*action_sequence_result)->SetString("id", id);
bool found = false; bool found = false;
for (size_t i = 0; i < session->active_input_sources.GetSize(); i++) { for (size_t i = 0; i < session->active_input_sources.GetSize(); i++) {
...@@ -1135,6 +1099,7 @@ Status ProcessInputActionSequence( ...@@ -1135,6 +1099,7 @@ Status ProcessInputActionSequence(
std::unique_ptr<base::ListValue> actions_result(new base::ListValue); std::unique_ptr<base::ListValue> actions_result(new base::ListValue);
for (size_t i = 0; i < actions->GetSize(); i++) { for (size_t i = 0; i < actions->GetSize(); i++) {
std::unique_ptr<base::DictionaryValue> action(new base::DictionaryValue()); std::unique_ptr<base::DictionaryValue> action(new base::DictionaryValue());
const base::DictionaryValue* action_item; const base::DictionaryValue* action_item;
if (!actions->GetDictionary(i, &action_item)) if (!actions->GetDictionary(i, &action_item))
return Status( return Status(
...@@ -1188,6 +1153,7 @@ Status ProcessInputActionSequence( ...@@ -1188,6 +1153,7 @@ Status ProcessInputActionSequence(
action->SetString("value", key); action->SetString("value", key);
} }
} else if (type == "pointer") { } else if (type == "pointer") {
action->SetString("pointerType", pointer_type);
std::string subtype; std::string subtype;
if (!action_item->GetString("type", &subtype) || if (!action_item->GetString("type", &subtype) ||
(subtype != "pointerUp" && subtype != "pointerDown" && (subtype != "pointerUp" && subtype != "pointerDown" &&
...@@ -1258,9 +1224,8 @@ Status ProcessInputActionSequence( ...@@ -1258,9 +1224,8 @@ Status ProcessInputActionSequence(
return status; return status;
} }
} }
actions_result->Append(std::move(action)); action_list->push_back(std::move(action));
} }
(*action_sequence_result)->SetList("actions", std::move(actions_result));
return Status(kOk); return Status(kOk);
} }
...@@ -1276,242 +1241,182 @@ Status ExecutePerformActions(Session* session, ...@@ -1276,242 +1241,182 @@ Status ExecutePerformActions(Session* session,
return Status(kInvalidArgument, "'actions' must be an array"); return Status(kInvalidArgument, "'actions' must be an array");
// the processed actions // the processed actions
base::ListValue actions_list; std::vector<std::vector<std::unique_ptr<base::DictionaryValue>>> actions_list;
for (size_t i = 0; i < actions_input->GetSize(); i++) { for (size_t i = 0; i < actions_input->GetSize(); i++) {
std::unique_ptr<base::DictionaryValue> input_source_actions(
new base::DictionaryValue());
// proccess input action sequence // proccess input action sequence
const base::DictionaryValue* action_sequence; const base::DictionaryValue* action_sequence;
if (!actions_input->GetDictionary(i, &action_sequence)) if (!actions_input->GetDictionary(i, &action_sequence))
return Status(kInvalidArgument, "each argument must be a dictionary"); return Status(kInvalidArgument, "each argument must be a dictionary");
Status status = ProcessInputActionSequence(session, action_sequence,
&input_source_actions); std::vector<std::unique_ptr<base::DictionaryValue>> action_list;
Status status =
ProcessInputActionSequence(session, action_sequence, &action_list);
actions_list.push_back(std::move(action_list));
if (status.IsError()) if (status.IsError())
return Status(kInvalidArgument, status); return Status(kInvalidArgument, status);
actions_list.Append(std::move(input_source_actions));
} }
std::string input_pointer_type;
std::set<std::string> pointer_id_set; std::set<std::string> pointer_id_set;
std::string type; std::vector<base::DictionaryValue*> action_input_states;
std::vector<std::vector<MouseEvent>> mouse_events_list; std::map<std::string, gfx::Point> action_locations;
std::vector<base::DictionaryValue*> mouse_input_states; std::map<std::string, bool> has_touch_start;
std::vector<gfx::Point> mouse_locations; std::map<std::string, int> buttons;
std::vector<std::vector<TouchEvent>> touch_events_list; std::map<std::string, std::string> button_type;
std::vector<base::DictionaryValue*> touch_input_states; int viewport_width = 0, viewport_height = 0;
std::vector<gfx::Point> touch_locations; int init_x = 0, init_y = 0;
std::vector<std::vector<KeyEvent>> key_events_list;
std::vector<base::DictionaryValue*> key_input_states; size_t longest_action_list_size = 0;
size_t longest_mouse_list_size = 0; for (size_t i = 0; i < actions_list.size(); i++) {
size_t longest_touch_list_size = 0; longest_action_list_size =
size_t longest_key_list_size = 0; std::max(longest_action_list_size, actions_list[i].size());
for (size_t i = 0; i < actions_list.GetSize(); i++) { }
base::DictionaryValue* action_sequence;
actions_list.GetDictionary(i, &action_sequence); for (size_t i = 0; i < longest_action_list_size; i++) {
const base::ListValue* actions; // Implements "compute the tick duration" algorithm from W3C spec
action_sequence->GetList("actions", &actions); // (https://w3c.github.io/webdriver/#dfn-computing-the-tick-duration).
DCHECK(actions); // This is the duration for actions in one tick.
action_sequence->GetString("sourceType", &type); int tick_duration = 0;
for (size_t j = 0; j < actions_list.size(); j++) {
if (actions_list[j].size() > i) {
const base::DictionaryValue* action = actions_list[j][i].get();
std::string id; std::string id;
action_sequence->GetString("id", &id); std::string type;
std::string action_type;
action->GetString("id", &id);
base::DictionaryValue* input_state; base::DictionaryValue* input_state;
if (!session->input_state_table.GetDictionary(id, &input_state)) if (!session->input_state_table.GetDictionary(id, &input_state))
return Status(kUnknownError, "missing input state"); return Status(kUnknownError, "missing input state");
// key actions if (i == 0) {
if (pointer_id_set.find(id) != pointer_id_set.end())
return Status(kInvalidArgument, "'id' already exists");
pointer_id_set.insert(id);
action_input_states.push_back(input_state);
}
action->GetString("type", &type);
action->GetString("subtype", &action_type);
int duration = 0;
if (action_type == "pause") {
GetOptionalInt(action, "duration", &duration);
tick_duration = std::max(tick_duration, duration);
}
if (type == "key") { if (type == "key") {
std::list<KeyEvent> dispatch_key_events;
KeyEventBuilder builder; KeyEventBuilder builder;
std::vector<KeyEvent> key_events; if (action_type != "pause") {
for (size_t j = 0; j < actions->GetSize(); j++) { Status status = ConvertKeyActionToKeyEvent(action, input_state,
const base::DictionaryValue* action; action_type == "keyDown",
actions->GetDictionary(j, &action); &dispatch_key_events);
std::string subtype; if (status.IsError())
action->GetString("subtype", &subtype); return status;
if (subtype == "pause") { if (dispatch_key_events.size() > 0) {
key_events.push_back(builder.SetType(kPauseEventType)->Build()); const KeyEvent& event = dispatch_key_events.front();
} else { if (action_type == "keyDown") {
Status status = ConvertKeyActionToKeyEvent( session->input_cancel_list.emplace_back(
action, input_state, subtype == "keyDown", &key_events); action_input_states[j], nullptr, nullptr, &event);
session->sticky_modifiers |= KeyToKeyModifiers(event.key);
} else if (action_type == "keyUp") {
session->sticky_modifiers &= ~KeyToKeyModifiers(event.key);
}
Status status = web_view->DispatchKeyEvents(dispatch_key_events);
if (status.IsError()) if (status.IsError())
return status; return status;
} }
} }
longest_key_list_size =
std::max(key_events.size(), longest_key_list_size);
key_events_list.push_back(key_events);
key_input_states.push_back(input_state);
} else if (type == "pointer") { } else if (type == "pointer") {
std::string pointer_type; std::string pointer_type;
action_sequence->GetString("pointerType", &pointer_type); action->GetString("pointerType", &pointer_type);
if (i == 0) {
Status status = WindowViewportSize(
session, web_view, &viewport_width, &viewport_height);
if (status.IsError())
return status;
if (input_pointer_type.empty()) input_state->GetInteger("x", &init_x);
input_pointer_type = pointer_type; input_state->GetInteger("y", &init_y);
action_locations.insert(
std::make_pair(id, gfx::Point(init_x, init_y)));
if (input_pointer_type != pointer_type) { if (pointer_type == "mouse" || pointer_type == "pen")
return Status(kInvalidArgument, buttons[id] = input_state->FindKey("pressed")->GetInt();
"multiple input pointer types are not supported now"); else if (pointer_type == "touch")
has_touch_start[id] = false;
} }
std::string pointer_id; if (action_type != "pause") {
action_sequence->GetString("id", &pointer_id); std::list<MouseEvent> dispatch_mouse_events;
if (pointer_id_set.find(pointer_id) != pointer_id_set.end()) std::list<TouchEvent> dispatch_touch_events;
return Status(kInvalidArgument, "'id' already exists");
pointer_id_set.insert(pointer_id);
std::vector<MouseEvent> mouse_events;
std::vector<TouchEvent> touch_events;
double x = 0; double x = 0;
double y = 0; double y = 0;
bool has_touch_start = input_state->FindKey("pressed")->GetInt() != 0;
int buttons = input_state->FindKey("pressed")->GetInt(); OriginType origin = kViewPort;
std::string button_type; std::string element_id = "";
OriginType origin_type = kPointer;
std::string element_id;
for (size_t j = 0; j < actions->GetSize(); j++) {
const base::DictionaryValue* pointer_action;
actions->GetDictionary(j, &pointer_action);
std::string action_type;
pointer_action->GetString("subtype", &action_type);
if (action_type == "pointerMove") { if (action_type == "pointerMove") {
pointer_action->GetDouble("x", &x); action->GetDouble("x", &x);
pointer_action->GetDouble("y", &y); action->GetDouble("y", &y);
const base::DictionaryValue* origin_dict; const base::DictionaryValue* origin_dict;
origin_type = kViewPort; if (action->HasKey("origin")) {
element_id = ""; if (action->GetDictionary("origin", &origin_dict)) {
if (pointer_action->HasKey("origin")) { origin = kElement;
if (pointer_action->GetDictionary("origin", &origin_dict)) {
origin_type = kElement;
origin_dict->GetString(GetElementKey(), &element_id); origin_dict->GetString(GetElementKey(), &element_id);
} else { } else {
std::string origin; std::string origin_str;
pointer_action->GetString("origin", &origin); action->GetString("origin", &origin_str);
if (origin == "pointer") if (origin_str == "pointer")
origin_type = kPointer; origin = kPointer;
} }
} }
duration = 0;
GetOptionalInt(action, "duration", &duration);
tick_duration = std::max(tick_duration, duration);
} }
if (pointer_type == "mouse" || pointer_type == "pen") { if (pointer_type == "mouse" || pointer_type == "pen") {
int click_count = 0; int click_count = 0;
if (action_type == "pointerDown" || action_type == "pointerUp") { if (action_type == "pointerDown" || action_type == "pointerUp") {
pointer_action->GetString("button", &button_type); std::string button;
action->GetString("button", &button);
button_type[id] = button;
click_count = 1; click_count = 1;
} else if (buttons == 0) { } else if (buttons[id] == 0) {
button_type.clear(); button_type[id].clear();
} }
MouseEvent event(StringToMouseEventType(action_type), MouseEvent event(StringToMouseEventType(action_type),
StringToMouseButton(button_type), x, y, 0, buttons, StringToMouseButton(button_type[id]), x, y, 0,
click_count); buttons[id], click_count);
event.origin = origin_type;
event.element_id = element_id;
event.pointer_type = StringToPointerType(pointer_type); event.pointer_type = StringToPointerType(pointer_type);
mouse_events.push_back(event);
if (action_type == "pointerDown")
buttons |= StringToModifierMouseButton(button_type);
else if (action_type == "pointerUp")
buttons &= ~StringToModifierMouseButton(button_type);
} else if (pointer_type == "touch") {
if (action_type == "pointerDown") if (action_type == "pointerDown")
has_touch_start = true; buttons[id] |= StringToModifierMouseButton(button_type[id]);
else if (action_type == "pointerUp") else if (action_type == "pointerUp")
has_touch_start = false; buttons[id] &= ~StringToModifierMouseButton(button_type[id]);
TouchEvent event(StringToTouchEventType(action_type), x, y);
event.origin = origin_type;
event.element_id = element_id;
if (action_type == "pointerMove")
event.dispatch = has_touch_start;
touch_events.push_back(event);
}
}
int init_x = 0;
int init_y = 0;
input_state->GetInteger("x", &init_x);
input_state->GetInteger("y", &init_y);
if (pointer_type == "mouse" || pointer_type == "pen") {
longest_mouse_list_size =
std::max(mouse_events.size(), longest_mouse_list_size);
mouse_events_list.push_back(mouse_events);
mouse_input_states.push_back(input_state);
mouse_locations.emplace_back(init_x, init_y);
} else if (pointer_type == "touch") {
longest_touch_list_size =
std::max(touch_events.size(), longest_touch_list_size);
touch_events_list.push_back(touch_events);
touch_input_states.push_back(input_state);
touch_locations.emplace_back(init_x, init_y);
}
}
}
std::vector<int> tick_durations;
ComputeTickDurations(&tick_durations, actions_list);
int viewport_width = 0, viewport_height = 0;
if (mouse_events_list.size() > 0 || touch_events_list.size() > 0) {
Status status = WindowViewportSize(session, web_view, &viewport_width,
&viewport_height);
if (status.IsError())
return status;
}
size_t max_list_length =
std::max({longest_mouse_list_size, longest_touch_list_size,
longest_key_list_size, tick_durations.size()});
for (size_t i = 0; i < max_list_length; i++) {
std::list<KeyEvent> dispatch_key_events;
for (size_t j = 0; j < key_events_list.size(); j++) {
if (i < key_events_list[j].size() &&
key_events_list[j][i].type != kPauseEventType) {
const KeyEvent& event = key_events_list[j][i];
dispatch_key_events.push_back(event);
if (event.type == kKeyDownEventType) {
session->input_cancel_list.emplace_back(key_input_states[j], nullptr,
nullptr, &event);
session->sticky_modifiers |= KeyToKeyModifiers(event.key);
} else if (event.type == kKeyUpEventType) {
session->sticky_modifiers &= ~KeyToKeyModifiers(event.key);
}
}
}
if (dispatch_key_events.size() > 0) {
Status status = web_view->DispatchKeyEvents(dispatch_key_events);
if (status.IsError())
return status;
}
std::list<MouseEvent> dispatch_mouse_events;
for (size_t j = 0; j < mouse_events_list.size(); j++) {
if (i < mouse_events_list[j].size() &&
mouse_events_list[j][i].type != kPauseMouseEventType) {
MouseEvent event = mouse_events_list[j][i];
if (event.type == kMovedMouseEventType) { if (event.type == kMovedMouseEventType) {
if (event.origin == kPointer) { if (origin == kPointer) {
event.x += mouse_locations[j].x(); event.x += action_locations[id].x();
event.y += mouse_locations[j].y(); event.y += action_locations[id].y();
} else if (!event.element_id.empty()) { } else if (!element_id.empty()) {
int center_x = 0, center_y = 0; int center_x = 0, center_y = 0;
Status status = ElementInViewCenter( Status status = ElementInViewCenter(
session, web_view, event.element_id, &center_x, &center_y); session, web_view, element_id, &center_x, &center_y);
if (status.IsError()) if (status.IsError())
return status; return status;
event.x += center_x; event.x += center_x;
event.y += center_y; event.y += center_y;
} }
if (event.x < 0 || event.x > viewport_width || event.y < 0 || if (event.x < 0 || event.x > viewport_width || event.y < 0 ||
event.y > viewport_height) event.y > viewport_height) {
return Status(kMoveTargetOutOfBounds); return Status(kMoveTargetOutOfBounds);
mouse_locations[j] = gfx::Point(event.x, event.y); }
action_locations[id] = gfx::Point(event.x, event.y);
} else { } else {
event.x = mouse_locations[j].x(); event.x = action_locations[id].x();
event.y = mouse_locations[j].y(); event.y = action_locations[id].y();
} }
event.modifiers = session->sticky_modifiers; event.modifiers = session->sticky_modifiers;
if (event.type == kPressedMouseEventType) { if (event.type == kPressedMouseEventType) {
...@@ -1529,38 +1434,36 @@ Status ExecutePerformActions(Session* session, ...@@ -1529,38 +1434,36 @@ Status ExecutePerformActions(Session* session,
} }
dispatch_mouse_events.push_back(event); dispatch_mouse_events.push_back(event);
if (event.type == kPressedMouseEventType) { if (event.type == kPressedMouseEventType) {
session->input_cancel_list.emplace_back(mouse_input_states[j], &event, session->input_cancel_list.emplace_back(
nullptr, nullptr); action_input_states[j], &event, nullptr, nullptr);
mouse_input_states[j]->SetInteger( action_input_states[j]->SetInteger(
"pressed", mouse_input_states[j]->FindKey("pressed")->GetInt() | "pressed",
action_input_states[j]->FindKey("pressed")->GetInt() |
(1 << event.button)); (1 << event.button));
} else if (event.type == kReleasedMouseEventType) { } else if (event.type == kReleasedMouseEventType) {
mouse_input_states[j]->SetInteger( action_input_states[j]->SetInteger(
"pressed", mouse_input_states[j]->FindKey("pressed")->GetInt() & "pressed",
action_input_states[j]->FindKey("pressed")->GetInt() &
~(1 << event.button)); ~(1 << event.button));
} }
}
}
if (dispatch_mouse_events.size() > 0) {
Status status = web_view->DispatchMouseEvents( Status status = web_view->DispatchMouseEvents(
dispatch_mouse_events, session->GetCurrentFrameId()); dispatch_mouse_events, session->GetCurrentFrameId());
if (status.IsError()) if (status.IsError())
return status; return status;
} } else if (pointer_type == "touch") {
if (action_type == "pointerDown")
has_touch_start[id] = true;
std::list<TouchEvent> dispatch_touch_events; TouchEvent event(StringToTouchEventType(action_type), x, y);
for (size_t j = 0; j < touch_events_list.size(); j++) {
if (i < touch_events_list[j].size() &&
touch_events_list[j][i].type != kPause) {
TouchEvent event = touch_events_list[j][i];
if (event.type == kTouchMove) { if (event.type == kTouchMove) {
if (event.origin == kPointer) { if (origin == kPointer) {
event.x += touch_locations[j].x(); event.x += action_locations[id].x();
event.y += touch_locations[j].y(); event.y += action_locations[id].y();
} else if (!event.element_id.empty()) { } else if (!element_id.empty()) {
int center_x = 0, center_y = 0; int center_x = 0, center_y = 0;
Status status = ElementInViewCenter( Status status = ElementInViewCenter(
session, web_view, event.element_id, &center_x, &center_y); session, web_view, element_id, &center_x, &center_y);
if (status.IsError()) if (status.IsError())
return status; return status;
event.x += center_x; event.x += center_x;
...@@ -1569,41 +1472,39 @@ Status ExecutePerformActions(Session* session, ...@@ -1569,41 +1472,39 @@ Status ExecutePerformActions(Session* session,
if (event.x < 0 || event.x > viewport_width || event.y < 0 || if (event.x < 0 || event.x > viewport_width || event.y < 0 ||
event.y > viewport_height) event.y > viewport_height)
return Status(kMoveTargetOutOfBounds); return Status(kMoveTargetOutOfBounds);
touch_locations[j] = gfx::Point(event.x, event.y); action_locations[id] = gfx::Point(event.x, event.y);
} else { } else {
event.x = touch_locations[j].x(); event.x = action_locations[id].x();
event.y = touch_locations[j].y(); event.y = action_locations[id].y();
} }
if (event.dispatch)
dispatch_touch_events.push_back(event);
if (event.type == kTouchStart) { if (event.type == kTouchStart) {
session->input_cancel_list.emplace_back(touch_input_states[j], session->input_cancel_list.emplace_back(
nullptr, &event, nullptr); action_input_states[j], nullptr, &event, nullptr);
touch_input_states[j]->SetInteger("pressed", 1); action_input_states[j]->SetInteger("pressed", 1);
} else if (event.type == kTouchEnd) { } else if (event.type == kTouchEnd) {
touch_input_states[j]->SetInteger("pressed", 0); action_input_states[j]->SetInteger("pressed", 0);
}
}
} }
if (dispatch_touch_events.size() > 0) { if (has_touch_start[id]) {
Status status = web_view->DispatchTouchEvents(dispatch_touch_events); dispatch_touch_events.push_back(event);
Status status =
web_view->DispatchTouchEvents(dispatch_touch_events);
if (status.IsError()) if (status.IsError())
return status; return status;
} }
if (action_type == "pointerUp")
has_touch_start[id] = false;
}
}
action_input_states[j]->SetInteger("x", action_locations[id].x());
action_input_states[j]->SetInteger("y", action_locations[id].y());
}
if (i < tick_durations.size() && tick_durations[i] > 0) { if (tick_duration > 0) {
base::PlatformThread::Sleep( base::PlatformThread::Sleep(
base::TimeDelta::FromMilliseconds(tick_durations[i])); base::TimeDelta::FromMilliseconds(tick_duration));
} }
} }
for (size_t i = 0; i < mouse_events_list.size(); i++) {
mouse_input_states[i]->SetInteger("x", mouse_locations[i].x());
mouse_input_states[i]->SetInteger("y", mouse_locations[i].y());
} }
for (size_t i = 0; i < touch_events_list.size(); i++) {
touch_input_states[i]->SetInteger("x", touch_locations[i].x());
touch_input_states[i]->SetInteger("y", touch_locations[i].y());
} }
return Status(kOk); return Status(kOk);
......
...@@ -373,7 +373,7 @@ Status ExecutePerformActions(Session* session, ...@@ -373,7 +373,7 @@ Status ExecutePerformActions(Session* session,
Status ProcessInputActionSequence( Status ProcessInputActionSequence(
Session* session, Session* session,
const base::DictionaryValue* action_sequence, const base::DictionaryValue* action_sequence,
std::unique_ptr<base::DictionaryValue>* result); std::vector<std::unique_ptr<base::DictionaryValue>>* action_list);
Status ExecuteReleaseActions(Session* session, Status ExecuteReleaseActions(Session* session,
WebView* web_view, WebView* web_view,
......
...@@ -66,7 +66,7 @@ TEST(WindowCommandsTest, ExecuteResume) { ...@@ -66,7 +66,7 @@ TEST(WindowCommandsTest, ExecuteResume) {
TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) { TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) {
Session session("1"); Session session("1");
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); std::vector<std::unique_ptr<base::DictionaryValue>> action_list;
std::unique_ptr<base::DictionaryValue> action_sequence( std::unique_ptr<base::DictionaryValue> action_sequence(
new base::DictionaryValue()); new base::DictionaryValue());
std::unique_ptr<base::ListValue> actions(new base::ListValue()); std::unique_ptr<base::ListValue> actions(new base::ListValue());
...@@ -94,12 +94,10 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) { ...@@ -94,12 +94,10 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) {
action_sequence->SetList("actions", std::move(actions)); action_sequence->SetList("actions", std::move(actions));
const base::DictionaryValue* input_action_sequence = action_sequence.get(); const base::DictionaryValue* input_action_sequence = action_sequence.get();
Status status = Status status =
ProcessInputActionSequence(&session, input_action_sequence, &result); ProcessInputActionSequence(&session, input_action_sequence, &action_list);
ASSERT_TRUE(status.IsOk()); ASSERT_TRUE(status.IsOk());
// check resulting action dictionary // check resulting action dictionary
const base::ListValue* actions_result;
const base::DictionaryValue* action_result;
std::string pointer_type; std::string pointer_type;
std::string source_type; std::string source_type;
std::string id; std::string id;
...@@ -107,37 +105,49 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) { ...@@ -107,37 +105,49 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerMouse) {
int x, y; int x, y;
std::string button; std::string button;
result->GetString("sourceType", &source_type); ASSERT_EQ(3U, action_list.size());
result->GetString("pointerType", &pointer_type); const base::DictionaryValue* action1 = action_list[0].get();
result->GetString("id", &id); action1->GetString("type", &source_type);
action1->GetString("pointerType", &pointer_type);
action1->GetString("id", &id);
ASSERT_EQ("pointer", source_type); ASSERT_EQ("pointer", source_type);
ASSERT_EQ("mouse", pointer_type); ASSERT_EQ("mouse", pointer_type);
ASSERT_EQ("pointer1", id); ASSERT_EQ("pointer1", id);
action1->GetString("subtype", &action_type);
result->GetList("actions", &actions_result); action1->GetInteger("x", &x);
ASSERT_EQ(3U, actions_result->GetSize()); action1->GetInteger("y", &y);
actions_result->GetDictionary(0, &action_result);
action_result->GetString("subtype", &action_type);
action_result->GetInteger("x", &x);
action_result->GetInteger("y", &y);
ASSERT_EQ("pointerMove", action_type); ASSERT_EQ("pointerMove", action_type);
ASSERT_EQ(30, x); ASSERT_EQ(30, x);
ASSERT_EQ(60, y); ASSERT_EQ(60, y);
actions_result->GetDictionary(1, &action_result);
action_result->GetString("subtype", &action_type); const base::DictionaryValue* action2 = action_list[1].get();
action_result->GetString("button", &button); action2->GetString("type", &source_type);
action2->GetString("pointerType", &pointer_type);
action2->GetString("id", &id);
ASSERT_EQ("pointer", source_type);
ASSERT_EQ("mouse", pointer_type);
ASSERT_EQ("pointer1", id);
action2->GetString("subtype", &action_type);
action2->GetString("button", &button);
ASSERT_EQ("pointerDown", action_type); ASSERT_EQ("pointerDown", action_type);
ASSERT_EQ("left", button); ASSERT_EQ("left", button);
actions_result->GetDictionary(2, &action_result);
action_result->GetString("subtype", &action_type); const base::DictionaryValue* action3 = action_list[2].get();
action_result->GetString("button", &button); action3->GetString("type", &source_type);
action3->GetString("pointerType", &pointer_type);
action3->GetString("id", &id);
ASSERT_EQ("pointer", source_type);
ASSERT_EQ("mouse", pointer_type);
ASSERT_EQ("pointer1", id);
action3->GetString("subtype", &action_type);
action3->GetString("button", &button);
ASSERT_EQ("pointerUp", action_type); ASSERT_EQ("pointerUp", action_type);
ASSERT_EQ("left", button); ASSERT_EQ("left", button);
} }
TEST(WindowCommandsTest, ProcessInputActionSequencePointerTouch) { TEST(WindowCommandsTest, ProcessInputActionSequencePointerTouch) {
Session session("1"); Session session("1");
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); std::vector<std::unique_ptr<base::DictionaryValue>> action_list;
std::unique_ptr<base::DictionaryValue> action_sequence( std::unique_ptr<base::DictionaryValue> action_sequence(
new base::DictionaryValue()); new base::DictionaryValue());
std::unique_ptr<base::ListValue> actions(new base::ListValue()); std::unique_ptr<base::ListValue> actions(new base::ListValue());
...@@ -163,38 +173,48 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerTouch) { ...@@ -163,38 +173,48 @@ TEST(WindowCommandsTest, ProcessInputActionSequencePointerTouch) {
action_sequence->SetList("actions", std::move(actions)); action_sequence->SetList("actions", std::move(actions));
const base::DictionaryValue* input_action_sequence = action_sequence.get(); const base::DictionaryValue* input_action_sequence = action_sequence.get();
Status status = Status status =
ProcessInputActionSequence(&session, input_action_sequence, &result); ProcessInputActionSequence(&session, input_action_sequence, &action_list);
ASSERT_TRUE(status.IsOk()); ASSERT_TRUE(status.IsOk());
// check resulting action dictionary // check resulting action dictionary
const base::ListValue* actions_result;
const base::DictionaryValue* action_result;
std::string pointer_type; std::string pointer_type;
std::string source_type; std::string source_type;
std::string id; std::string id;
std::string action_type; std::string action_type;
int x, y; int x, y;
result->GetString("sourceType", &source_type); ASSERT_EQ(3U, action_list.size());
result->GetString("pointerType", &pointer_type); const base::DictionaryValue* action1 = action_list[0].get();
result->GetString("id", &id); action1->GetString("type", &source_type);
action1->GetString("pointerType", &pointer_type);
action1->GetString("id", &id);
ASSERT_EQ("pointer", source_type); ASSERT_EQ("pointer", source_type);
ASSERT_EQ("touch", pointer_type); ASSERT_EQ("touch", pointer_type);
ASSERT_EQ("pointer1", id); ASSERT_EQ("pointer1", id);
action1->GetString("subtype", &action_type);
result->GetList("actions", &actions_result); action1->GetInteger("x", &x);
ASSERT_EQ(3U, actions_result->GetSize()); action1->GetInteger("y", &y);
actions_result->GetDictionary(0, &action_result);
action_result->GetString("subtype", &action_type);
action_result->GetInteger("x", &x);
action_result->GetInteger("y", &y);
ASSERT_EQ("pointerMove", action_type); ASSERT_EQ("pointerMove", action_type);
ASSERT_EQ(30, x); ASSERT_EQ(30, x);
ASSERT_EQ(60, y); ASSERT_EQ(60, y);
actions_result->GetDictionary(1, &action_result);
action_result->GetString("subtype", &action_type); const base::DictionaryValue* action2 = action_list[1].get();
action2->GetString("type", &source_type);
action2->GetString("pointerType", &pointer_type);
action2->GetString("id", &id);
ASSERT_EQ("pointer", source_type);
ASSERT_EQ("touch", pointer_type);
ASSERT_EQ("pointer1", id);
action2->GetString("subtype", &action_type);
ASSERT_EQ("pointerDown", action_type); ASSERT_EQ("pointerDown", action_type);
actions_result->GetDictionary(2, &action_result);
action_result->GetString("subtype", &action_type); const base::DictionaryValue* action3 = action_list[2].get();
action3->GetString("type", &source_type);
action3->GetString("pointerType", &pointer_type);
action3->GetString("id", &id);
ASSERT_EQ("pointer", source_type);
ASSERT_EQ("touch", pointer_type);
ASSERT_EQ("pointer1", id);
action3->GetString("subtype", &action_type);
ASSERT_EQ("pointerUp", action_type); ASSERT_EQ("pointerUp", action_type);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment