1// Copyright 2013 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/renderer/render_widget.h" 6 7#include <vector> 8 9#include "content/common/input/synthetic_web_input_event_builders.h" 10#include "content/common/input_messages.h" 11#include "content/public/test/mock_render_thread.h" 12#include "content/test/mock_render_process.h" 13#include "ipc/ipc_test_sink.h" 14#include "testing/gtest/include/gtest/gtest.h" 15#include "third_party/WebKit/public/web/WebInputEvent.h" 16#include "ui/gfx/rect.h" 17 18namespace content { 19 20class RenderWidgetUnittest : public testing::Test { 21 public: 22 RenderWidgetUnittest() {} 23 virtual ~RenderWidgetUnittest() {} 24 25 private: 26 MockRenderProcess render_process_; 27 MockRenderThread render_thread_; 28 29 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest); 30}; 31 32class TouchableRenderWidget : public RenderWidget { 33 public: 34 TouchableRenderWidget() : RenderWidget(blink::WebPopupTypeNone, 35 blink::WebScreenInfo(), 36 false, 37 false) {} 38 39 void SetTouchRegion(const std::vector<gfx::Rect>& rects) { 40 rects_ = rects; 41 } 42 43 void SendInputEvent(const blink::WebInputEvent& event) { 44 OnHandleInputEvent(&event, ui::LatencyInfo(), false); 45 } 46 47 IPC::TestSink* sink() { return &sink_; } 48 49 protected: 50 virtual ~TouchableRenderWidget() {} 51 52 // Overridden from RenderWidget: 53 virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE { 54 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin(); 55 iter != rects_.end(); ++iter) { 56 if ((*iter).Contains(point)) 57 return true; 58 } 59 return false; 60 } 61 62 virtual bool Send(IPC::Message* msg) OVERRIDE { 63 sink_.OnMessageReceived(*msg); 64 delete msg; 65 return true; 66 } 67 68 private: 69 std::vector<gfx::Rect> rects_; 70 IPC::TestSink sink_; 71 72 DISALLOW_COPY_AND_ASSIGN(TouchableRenderWidget); 73}; 74 75TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) { 76 scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); 77 78 blink::WebInputEvent::Type type; 79 InputEventAckState ack_state; 80 ui::LatencyInfo latency; 81 82 SyntheticWebTouchEvent touch; 83 touch.PressPoint(10, 10); 84 85 widget->SendInputEvent(touch); 86 ASSERT_EQ(1u, widget->sink()->message_count()); 87 88 // Since there's currently no touch-event handling region, the response should 89 // be 'no consumer exists'. 90 const IPC::Message* message = widget->sink()->GetMessageAt(0); 91 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 92 InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); 93 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); 94 widget->sink()->ClearMessages(); 95 96 std::vector<gfx::Rect> rects; 97 rects.push_back(gfx::Rect(0, 0, 20, 20)); 98 rects.push_back(gfx::Rect(25, 0, 10, 10)); 99 widget->SetTouchRegion(rects); 100 101 widget->SendInputEvent(touch); 102 ASSERT_EQ(1u, widget->sink()->message_count()); 103 message = widget->sink()->GetMessageAt(0); 104 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 105 InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); 106 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 107 widget->sink()->ClearMessages(); 108} 109 110TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) { 111 scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); 112 std::vector<gfx::Rect> rects; 113 rects.push_back(gfx::Rect(0, 0, 20, 20)); 114 rects.push_back(gfx::Rect(25, 0, 10, 10)); 115 widget->SetTouchRegion(rects); 116 117 blink::WebInputEvent::Type type; 118 InputEventAckState ack_state; 119 ui::LatencyInfo latency; 120 121 SyntheticWebTouchEvent touch; 122 touch.PressPoint(25, 25); 123 124 widget->SendInputEvent(touch); 125 ASSERT_EQ(1u, widget->sink()->message_count()); 126 127 // Since there's currently no touch-event handling region, the response should 128 // be 'no consumer exists'. 129 const IPC::Message* message = widget->sink()->GetMessageAt(0); 130 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 131 InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); 132 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); 133 widget->sink()->ClearMessages(); 134 135 // Press a second touch point. This time, on a touch-handling region. 136 touch.PressPoint(10, 10); 137 widget->SendInputEvent(touch); 138 ASSERT_EQ(1u, widget->sink()->message_count()); 139 message = widget->sink()->GetMessageAt(0); 140 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 141 InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); 142 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 143 widget->sink()->ClearMessages(); 144} 145 146} // namespace content 147