[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / content / common / input / touch_event_stream_validator.cc
blob4c7598901dd2b1b145eeeaed55d014a5b956dc78
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/input/touch_event_stream_validator.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "content/common/input/web_input_event_traits.h"
10 #include "content/common/input/web_touch_event_traits.h"
12 using base::StringPrintf;
13 using blink::WebInputEvent;
14 using blink::WebTouchEvent;
15 using blink::WebTouchPoint;
17 namespace content {
18 namespace {
20 const WebTouchPoint* FindTouchPoint(const WebTouchEvent& event, int id) {
21 for (unsigned i = 0; i < event.touchesLength; ++i) {
22 if (event.touches[i].id == id)
23 return &event.touches[i];
25 return NULL;
28 std::string TouchPointIdsToString(const WebTouchEvent& event) {
29 std::stringstream ss;
30 for (unsigned i = 0; i < event.touchesLength; ++i) {
31 if (i)
32 ss << ",";
33 ss << event.touches[i].id;
35 return ss.str();
38 } // namespace
40 TouchEventStreamValidator::TouchEventStreamValidator() {
43 TouchEventStreamValidator::~TouchEventStreamValidator() {
46 bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
47 std::string* error_msg) {
48 DCHECK(error_msg);
49 error_msg->clear();
51 WebTouchEvent previous_event = previous_event_;
52 previous_event_ = event;
54 if (!event.touchesLength) {
55 error_msg->append("Touch event is empty.\n");
56 return false;
59 if (!WebInputEvent::isTouchEventType(event.type)) {
60 error_msg->append(StringPrintf("Touch event has invalid type: %s\n",
61 WebInputEventTraits::GetName(event.type)));
64 // Allow "hard" restarting of touch stream validation. This is necessary
65 // in cases where touch event forwarding ceases in response to the event ack
66 // or removal of touch handlers.
67 if (WebTouchEventTraits::IsTouchSequenceStart(event))
68 previous_event = WebTouchEvent();
70 // Unreleased points from the previous event should exist in the latest event.
71 for (unsigned i = 0; i < previous_event.touchesLength; ++i) {
72 const WebTouchPoint& previous_point = previous_event.touches[i];
73 if (previous_point.state == WebTouchPoint::StateCancelled ||
74 previous_point.state == WebTouchPoint::StateReleased)
75 continue;
77 const WebTouchPoint* point = FindTouchPoint(event, previous_point.id);
78 if (!point) {
79 error_msg->append(StringPrintf(
80 "Previously active touch point (id=%d) not in new event (ids=%s).\n",
81 previous_point.id, TouchPointIdsToString(event).c_str()));
85 bool found_valid_state_for_type = false;
86 for (unsigned i = 0; i < event.touchesLength; ++i) {
87 const WebTouchPoint& point = event.touches[i];
88 const WebTouchPoint* previous_point =
89 FindTouchPoint(previous_event, point.id);
91 // The point should exist in the previous event if it is not a new point.
92 if (!previous_point) {
93 if (point.state != WebTouchPoint::StatePressed)
94 error_msg->append(StringPrintf(
95 "Active touch point (id=%d) not in previous event (ids=%s).\n",
96 point.id, TouchPointIdsToString(previous_event).c_str()));
97 } else {
98 if (point.state == WebTouchPoint::StatePressed &&
99 previous_point->state != WebTouchPoint::StateCancelled &&
100 previous_point->state != WebTouchPoint::StateReleased) {
101 error_msg->append(StringPrintf(
102 "Pressed touch point (id=%d) already exists in previous event "
103 "(ids=%s).\n",
104 point.id, TouchPointIdsToString(previous_event).c_str()));
108 switch (point.state) {
109 case WebTouchPoint::StateUndefined:
110 error_msg->append(
111 StringPrintf("Undefined touch point state (id=%d).\n", point.id));
112 break;
114 case WebTouchPoint::StateReleased:
115 if (event.type != WebInputEvent::TouchEnd) {
116 error_msg->append(StringPrintf(
117 "Released touch point (id=%d) outside touchend.\n", point.id));
118 } else {
119 found_valid_state_for_type = true;
121 break;
123 case WebTouchPoint::StatePressed:
124 if (event.type != WebInputEvent::TouchStart) {
125 error_msg->append(StringPrintf(
126 "Pressed touch point (id=%d) outside touchstart.\n", point.id));
127 } else {
128 found_valid_state_for_type = true;
130 break;
132 case WebTouchPoint::StateMoved:
133 if (event.type != WebInputEvent::TouchMove) {
134 error_msg->append(StringPrintf(
135 "Moved touch point (id=%d) outside touchmove.\n", point.id));
136 } else {
137 found_valid_state_for_type = true;
139 break;
141 case WebTouchPoint::StateStationary:
142 break;
144 case WebTouchPoint::StateCancelled:
145 if (event.type != WebInputEvent::TouchCancel) {
146 error_msg->append(StringPrintf(
147 "Cancelled touch point (id=%d) outside touchcancel.\n",
148 point.id));
149 } else {
150 found_valid_state_for_type = true;
152 break;
156 if (!found_valid_state_for_type) {
157 error_msg->append(
158 StringPrintf("No valid touch point corresponding to event type: %s\n",
159 WebInputEventTraits::GetName(event.type)));
162 return error_msg->empty();
165 } // namespace content