| Index: content/common/input/touch_event_stream_validator.cc
|
| diff --git a/content/common/input/touch_event_stream_validator.cc b/content/common/input/touch_event_stream_validator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..85bc469443315e516f26d4b362b75fdbd1146903
|
| --- /dev/null
|
| +++ b/content/common/input/touch_event_stream_validator.cc
|
| @@ -0,0 +1,108 @@
|
| +// 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/common/input/touch_event_stream_validator.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "content/common/input/web_touch_event_traits.h"
|
| +
|
| +using blink::WebInputEvent;
|
| +using blink::WebTouchEvent;
|
| +using blink::WebTouchPoint;
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +const WebTouchPoint* FindTouchPoint(const WebTouchEvent& event, int id) {
|
| + for (unsigned i = 0; i < event.touchesLength; ++i) {
|
| + if (event.touches[i].id == id)
|
| + return &event.touches[i];
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +TouchEventStreamValidator::TouchEventStreamValidator() {
|
| +}
|
| +
|
| +TouchEventStreamValidator::~TouchEventStreamValidator() {
|
| +}
|
| +
|
| +bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
|
| + std::string* error_msg) {
|
| + DCHECK(error_msg);
|
| + error_msg->clear();
|
| +
|
| + WebTouchEvent previous_event = previous_event_;
|
| + previous_event_ = event;
|
| +
|
| + // Allow "hard" restarting of touch stream validation. This is necessary
|
| + // in cases where touch event forwarding ceases in response to the event ack
|
| + // or removal of touch handlers.
|
| + if (WebTouchEventTraits::IsTouchSequenceStart(event))
|
| + previous_event = WebTouchEvent();
|
| +
|
| + // Unreleased points from the previous event should exist in the latest event.
|
| + for (unsigned i = 0; i < previous_event.touchesLength; ++i) {
|
| + const WebTouchPoint& previous_point = previous_event.touches[i];
|
| + if (previous_point.state == WebTouchPoint::StateCancelled ||
|
| + previous_point.state == WebTouchPoint::StateReleased)
|
| + continue;
|
| +
|
| + const WebTouchPoint* point = FindTouchPoint(event, previous_point.id);
|
| + if (!point)
|
| + error_msg->append("Previously active touch point not in new event.\n");
|
| + }
|
| +
|
| + for (unsigned i = 0; i < event.touchesLength; ++i) {
|
| + const WebTouchPoint& point = event.touches[i];
|
| + const WebTouchPoint* previous_point =
|
| + FindTouchPoint(previous_event, point.id);
|
| +
|
| + // The point should exist in the previous event if it is not a new point.
|
| + if (!previous_point) {
|
| + if (point.state != WebTouchPoint::StatePressed)
|
| + error_msg->append("Active touch point not found in previous event.\n");
|
| + } else {
|
| + if (point.state == WebTouchPoint::StatePressed &&
|
| + previous_point->state != WebTouchPoint::StateCancelled &&
|
| + previous_point->state != WebTouchPoint::StateReleased) {
|
| + error_msg->append("Pressed touch point id already exists.\n");
|
| + }
|
| + }
|
| +
|
| + switch (point.state) {
|
| + case WebTouchPoint::StateUndefined:
|
| + error_msg->append("Undefined WebTouchPoint state.\n");
|
| + break;
|
| +
|
| + case WebTouchPoint::StateReleased:
|
| + if (event.type != WebInputEvent::TouchEnd)
|
| + error_msg->append("Released touch point outside touchend.\n");
|
| + break;
|
| +
|
| + case WebTouchPoint::StatePressed:
|
| + if (event.type != WebInputEvent::TouchStart)
|
| + error_msg->append("Pressed touch point outside touchstart.\n");
|
| + break;
|
| +
|
| + case WebTouchPoint::StateMoved:
|
| + if (event.type != WebInputEvent::TouchMove)
|
| + error_msg->append("Moved touch point outside touchmove.\n");
|
| + break;
|
| +
|
| + case WebTouchPoint::StateStationary:
|
| + break;
|
| +
|
| + case WebTouchPoint::StateCancelled:
|
| + if (event.type != WebInputEvent::TouchCancel)
|
| + error_msg->append("Cancelled touch point outside touchcancel.\n");
|
| + break;
|
| + }
|
| + }
|
| + return error_msg->empty();
|
| +}
|
| +
|
| +} // namespace content
|
|
|