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/gesture_event_stream_validator.h" 6 7 #include "base/logging.h" 8 #include "base/strings/stringprintf.h" 9 #include "third_party/blink/public/common/input/web_gesture_event.h" 10 #include "third_party/blink/public/common/input/web_input_event.h" 11 #include "ui/events/blink/web_input_event_traits.h" 12 13 using blink::WebInputEvent; 14 15 namespace content { 16 GestureEventStreamValidator()17GestureEventStreamValidator::GestureEventStreamValidator() 18 : scrolling_(false), pinching_(false), waiting_for_tap_end_(false) { 19 } 20 ~GestureEventStreamValidator()21GestureEventStreamValidator::~GestureEventStreamValidator() { 22 } 23 Validate(const blink::WebGestureEvent & event,std::string * error_msg)24bool GestureEventStreamValidator::Validate( 25 const blink::WebGestureEvent& event, 26 std::string* error_msg) { 27 DCHECK(error_msg); 28 error_msg->clear(); 29 if (!WebInputEvent::IsGestureEventType(event.GetType())) { 30 error_msg->append(base::StringPrintf( 31 "Invalid gesture type: %s", WebInputEvent::GetName(event.GetType()))); 32 } 33 switch (event.GetType()) { 34 case WebInputEvent::kGestureScrollBegin: 35 if (scrolling_) 36 error_msg->append("Scroll begin during scroll\n"); 37 if (pinching_) 38 error_msg->append("Scroll begin during pinch\n"); 39 scrolling_ = true; 40 break; 41 case WebInputEvent::kGestureScrollUpdate: 42 if (!scrolling_) 43 error_msg->append("Scroll update outside of scroll\n"); 44 break; 45 case WebInputEvent::kGestureFlingStart: 46 if (event.SourceDevice() == blink::WebGestureDevice::kTouchscreen && 47 !event.data.fling_start.velocity_x && 48 !event.data.fling_start.velocity_y) { 49 error_msg->append("Zero velocity touchscreen fling\n"); 50 } 51 if (!scrolling_) 52 error_msg->append("Fling start outside of scroll\n"); 53 if (pinching_) 54 error_msg->append("Flinging while pinching\n"); 55 // Don't reset scrolling_ since the GSE sent by the fling_controller_ at 56 // the end of the fling resets it. 57 break; 58 case WebInputEvent::kGestureScrollEnd: 59 if (!scrolling_) 60 error_msg->append("Scroll end outside of scroll\n"); 61 if (pinching_) 62 error_msg->append("Ending scroll while pinching\n"); 63 scrolling_ = false; 64 break; 65 case WebInputEvent::kGesturePinchBegin: 66 if (pinching_) 67 error_msg->append("Pinch begin during pinch\n"); 68 pinching_ = true; 69 break; 70 case WebInputEvent::kGesturePinchUpdate: 71 if (!pinching_) 72 error_msg->append("Pinch update outside of pinch\n"); 73 break; 74 case WebInputEvent::kGesturePinchEnd: 75 if (!pinching_) 76 error_msg->append("Pinch end outside of pinch\n"); 77 pinching_ = false; 78 break; 79 case WebInputEvent::kGestureTapDown: 80 if (waiting_for_tap_end_) 81 error_msg->append("Missing tap ending event before TapDown\n"); 82 waiting_for_tap_end_ = true; 83 break; 84 case WebInputEvent::kGestureTapUnconfirmed: 85 if (!waiting_for_tap_end_) 86 error_msg->append("Missing TapDown event before TapUnconfirmed\n"); 87 break; 88 case WebInputEvent::kGestureTapCancel: 89 if (!waiting_for_tap_end_) 90 error_msg->append("Missing TapDown event before TapCancel\n"); 91 waiting_for_tap_end_ = false; 92 break; 93 case WebInputEvent::kGestureTap: 94 if (!waiting_for_tap_end_) 95 error_msg->append("Missing TapDown event before Tap\n"); 96 waiting_for_tap_end_ = false; 97 break; 98 case WebInputEvent::kGestureDoubleTap: 99 // DoubleTap gestures may be synthetically inserted, and do not require a 100 // preceding TapDown. 101 waiting_for_tap_end_ = false; 102 break; 103 default: 104 break; 105 } 106 // TODO(wjmaclean): At some future point we may wish to consider adding a 107 // 'continuity check', requiring that all events between an initial tap-down 108 // and whatever terminates the sequence to have the same source device type, 109 // and that touchpad gestures are only found on ScrollEvents. 110 if (event.SourceDevice() == blink::WebGestureDevice::kUninitialized) 111 error_msg->append("Gesture event source is uninitialized.\n"); 112 113 return error_msg->empty(); 114 } 115 116 } // namespace content 117