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() 35 : RenderWidget(blink::WebPopupTypeNone, 36 blink::WebScreenInfo(), 37 false, 38 false, 39 false) {} 40 41 void SetTouchRegion(const std::vector<gfx::Rect>& rects) { 42 rects_ = rects; 43 } 44 45 void SendInputEvent(const blink::WebInputEvent& event) { 46 OnHandleInputEvent(&event, ui::LatencyInfo(), false); 47 } 48 49 IPC::TestSink* sink() { return &sink_; } 50 51 protected: 52 virtual ~TouchableRenderWidget() {} 53 54 // Overridden from RenderWidget: 55 virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE { 56 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin(); 57 iter != rects_.end(); ++iter) { 58 if ((*iter).Contains(point)) 59 return true; 60 } 61 return false; 62 } 63 64 virtual bool Send(IPC::Message* msg) OVERRIDE { 65 sink_.OnMessageReceived(*msg); 66 delete msg; 67 return true; 68 } 69 70 private: 71 std::vector<gfx::Rect> rects_; 72 IPC::TestSink sink_; 73 74 DISALLOW_COPY_AND_ASSIGN(TouchableRenderWidget); 75}; 76 77TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) { 78 scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); 79 80 SyntheticWebTouchEvent touch; 81 touch.PressPoint(10, 10); 82 83 widget->SendInputEvent(touch); 84 ASSERT_EQ(1u, widget->sink()->message_count()); 85 86 // Since there's currently no touch-event handling region, the response should 87 // be 'no consumer exists'. 88 const IPC::Message* message = widget->sink()->GetMessageAt(0); 89 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 90 InputHostMsg_HandleInputEvent_ACK::Param params; 91 InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms); 92 InputEventAckState ack_state = params.a.state; 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, ¶ms); 106 ack_state = params.a.state; 107 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 108 widget->sink()->ClearMessages(); 109} 110 111TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) { 112 scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); 113 std::vector<gfx::Rect> rects; 114 rects.push_back(gfx::Rect(0, 0, 20, 20)); 115 rects.push_back(gfx::Rect(25, 0, 10, 10)); 116 widget->SetTouchRegion(rects); 117 118 SyntheticWebTouchEvent touch; 119 touch.PressPoint(25, 25); 120 121 widget->SendInputEvent(touch); 122 ASSERT_EQ(1u, widget->sink()->message_count()); 123 124 // Since there's currently no touch-event handling region, the response should 125 // be 'no consumer exists'. 126 const IPC::Message* message = widget->sink()->GetMessageAt(0); 127 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 128 InputHostMsg_HandleInputEvent_ACK::Param params; 129 InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms); 130 InputEventAckState ack_state = params.a.state; 131 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); 132 widget->sink()->ClearMessages(); 133 134 // Press a second touch point. This time, on a touch-handling region. 135 touch.PressPoint(10, 10); 136 widget->SendInputEvent(touch); 137 ASSERT_EQ(1u, widget->sink()->message_count()); 138 message = widget->sink()->GetMessageAt(0); 139 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 140 InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms); 141 ack_state = params.a.state; 142 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 143 widget->sink()->ClearMessages(); 144} 145 146} // namespace content 147