Home | History | Annotate | Download | only in input
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/common/input/touch_event_stream_validator.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/common/input/web_touch_event_traits.h"
      9 
     10 using blink::WebInputEvent;
     11 using blink::WebTouchEvent;
     12 using blink::WebTouchPoint;
     13 
     14 namespace content {
     15 namespace {
     16 
     17 const WebTouchPoint* FindTouchPoint(const WebTouchEvent& event, int id) {
     18   for (unsigned i = 0; i < event.touchesLength; ++i) {
     19     if (event.touches[i].id == id)
     20       return &event.touches[i];
     21   }
     22   return NULL;
     23 }
     24 
     25 }  // namespace
     26 
     27 TouchEventStreamValidator::TouchEventStreamValidator() {
     28 }
     29 
     30 TouchEventStreamValidator::~TouchEventStreamValidator() {
     31 }
     32 
     33 bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
     34                                          std::string* error_msg) {
     35   DCHECK(error_msg);
     36   error_msg->clear();
     37 
     38   WebTouchEvent previous_event = previous_event_;
     39   previous_event_ = event;
     40 
     41   // Allow "hard" restarting of touch stream validation. This is necessary
     42   // in cases where touch event forwarding ceases in response to the event ack
     43   // or removal of touch handlers.
     44   if (WebTouchEventTraits::IsTouchSequenceStart(event))
     45     previous_event = WebTouchEvent();
     46 
     47   // Unreleased points from the previous event should exist in the latest event.
     48   for (unsigned i = 0; i < previous_event.touchesLength; ++i) {
     49     const WebTouchPoint& previous_point = previous_event.touches[i];
     50     if (previous_point.state == WebTouchPoint::StateCancelled ||
     51         previous_point.state == WebTouchPoint::StateReleased)
     52       continue;
     53 
     54     const WebTouchPoint* point = FindTouchPoint(event, previous_point.id);
     55     if (!point)
     56       error_msg->append("Previously active touch point not in new event.\n");
     57   }
     58 
     59   for (unsigned i = 0; i < event.touchesLength; ++i) {
     60     const WebTouchPoint& point = event.touches[i];
     61     const WebTouchPoint* previous_point =
     62         FindTouchPoint(previous_event, point.id);
     63 
     64     // The point should exist in the previous event if it is not a new point.
     65     if (!previous_point) {
     66       if (point.state != WebTouchPoint::StatePressed)
     67         error_msg->append("Active touch point not found in previous event.\n");
     68     } else {
     69       if (point.state == WebTouchPoint::StatePressed &&
     70           previous_point->state != WebTouchPoint::StateCancelled &&
     71           previous_point->state != WebTouchPoint::StateReleased) {
     72         error_msg->append("Pressed touch point id already exists.\n");
     73       }
     74     }
     75 
     76     switch (point.state) {
     77       case WebTouchPoint::StateUndefined:
     78         error_msg->append("Undefined WebTouchPoint state.\n");
     79         break;
     80 
     81       case WebTouchPoint::StateReleased:
     82         if (event.type != WebInputEvent::TouchEnd)
     83           error_msg->append("Released touch point outside touchend.\n");
     84         break;
     85 
     86       case WebTouchPoint::StatePressed:
     87         if (event.type != WebInputEvent::TouchStart)
     88           error_msg->append("Pressed touch point outside touchstart.\n");
     89         break;
     90 
     91       case WebTouchPoint::StateMoved:
     92         if (event.type != WebInputEvent::TouchMove)
     93           error_msg->append("Moved touch point outside touchmove.\n");
     94         break;
     95 
     96       case WebTouchPoint::StateStationary:
     97         break;
     98 
     99       case WebTouchPoint::StateCancelled:
    100         if (event.type != WebInputEvent::TouchCancel)
    101           error_msg->append("Cancelled touch point outside touchcancel.\n");
    102         break;
    103     }
    104   }
    105   return error_msg->empty();
    106 }
    107 
    108 }  // namespace content
    109