Android: Remove unneeded Compositor::SetNeedsRedraw()
[chromium-blink-merge.git] / ppapi / tests / test_input_event.cc
blob9b138fff3055d2e810bc26537021c1fbc021e834
1 // Copyright (c) 2012 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.
5 #include "ppapi/tests/test_input_event.h"
7 #include "ppapi/c/dev/ppb_testing_dev.h"
8 #include "ppapi/c/pp_errors.h"
9 #include "ppapi/c/ppb_input_event.h"
10 #include "ppapi/cpp/input_event.h"
11 #include "ppapi/cpp/module.h"
12 #include "ppapi/tests/test_utils.h"
13 #include "ppapi/tests/testing_instance.h"
15 REGISTER_TEST_CASE(InputEvent);
17 namespace {
19 const uint32_t kSpaceChar = 0x20;
20 const char* kSpaceString = " ";
22 #define FINISHED_WAITING_MESSAGE "TEST_INPUT_EVENT_FINISHED_WAITING"
24 pp::Point GetCenter(const pp::Rect& rect) {
25 return pp::Point(
26 rect.x() + rect.width() / 2,
27 rect.y() + rect.height() / 2);
30 } // namespace
32 void TestInputEvent::RunTests(const std::string& filter) {
33 RUN_TEST(Events, filter);
35 // The AcceptTouchEvent_N tests should not be run when the filter is empty;
36 // they can only be run one at a time.
37 // TODO(dmichael): Figure out a way to make these run in the same test fixture
38 // instance.
39 if (!ShouldRunAllTests(filter)) {
40 RUN_TEST(AcceptTouchEvent_1, filter);
41 RUN_TEST(AcceptTouchEvent_2, filter);
42 RUN_TEST(AcceptTouchEvent_3, filter);
43 RUN_TEST(AcceptTouchEvent_4, filter);
47 TestInputEvent::TestInputEvent(TestingInstance* instance)
48 : TestCase(instance),
49 input_event_interface_(NULL),
50 mouse_input_event_interface_(NULL),
51 wheel_input_event_interface_(NULL),
52 keyboard_input_event_interface_(NULL),
53 touch_input_event_interface_(NULL),
54 nested_event_(instance->pp_instance()),
55 view_rect_(),
56 expected_input_event_(0),
57 received_expected_event_(false),
58 received_finish_message_(false) {
61 TestInputEvent::~TestInputEvent() {
62 // Remove the special listener that only responds to a
63 // FINISHED_WAITING_MESSAGE string. See Init for where it gets added.
64 std::string js_code;
65 js_code += "var plugin = document.getElementById('plugin');"
66 "plugin.removeEventListener('message',"
67 " plugin.wait_for_messages_handler);"
68 "delete plugin.wait_for_messages_handler;";
69 instance_->EvalScript(js_code);
72 bool TestInputEvent::Init() {
73 input_event_interface_ = static_cast<const PPB_InputEvent*>(
74 pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
75 mouse_input_event_interface_ = static_cast<const PPB_MouseInputEvent*>(
76 pp::Module::Get()->GetBrowserInterface(
77 PPB_MOUSE_INPUT_EVENT_INTERFACE));
78 wheel_input_event_interface_ = static_cast<const PPB_WheelInputEvent*>(
79 pp::Module::Get()->GetBrowserInterface(
80 PPB_WHEEL_INPUT_EVENT_INTERFACE));
81 keyboard_input_event_interface_ = static_cast<const PPB_KeyboardInputEvent*>(
82 pp::Module::Get()->GetBrowserInterface(
83 PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
84 touch_input_event_interface_ = static_cast<const PPB_TouchInputEvent*>(
85 pp::Module::Get()->GetBrowserInterface(
86 PPB_TOUCH_INPUT_EVENT_INTERFACE));
88 bool success =
89 input_event_interface_ &&
90 mouse_input_event_interface_ &&
91 wheel_input_event_interface_ &&
92 keyboard_input_event_interface_ &&
93 touch_input_event_interface_ &&
94 CheckTestingInterface();
96 // Set up a listener for our message that signals that all input events have
97 // been received.
98 std::string js_code;
99 // Note the following code is dependent on some features of test_case.html.
100 // E.g., it is assumed that the DOM element where the plugin is embedded has
101 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
102 // us to ignore the messages that are intended for use by the testing
103 // framework itself.
104 js_code += "var plugin = document.getElementById('plugin');"
105 "var wait_for_messages_handler = function(message_event) {"
106 " if (!IsTestingMessage(message_event.data) &&"
107 " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
108 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
109 " }"
110 "};"
111 "plugin.addEventListener('message', wait_for_messages_handler);"
112 // Stash it on the plugin so we can remove it in the destructor.
113 "plugin.wait_for_messages_handler = wait_for_messages_handler;";
114 instance_->EvalScript(js_code);
116 return success;
119 pp::InputEvent TestInputEvent::CreateMouseEvent(
120 PP_InputEvent_Type type,
121 PP_InputEvent_MouseButton buttons) {
122 return pp::MouseInputEvent(
123 instance_,
124 type,
125 100, // time_stamp
126 0, // modifiers
127 buttons,
128 GetCenter(view_rect_),
129 1, // click count
130 pp::Point()); // movement
133 pp::InputEvent TestInputEvent::CreateWheelEvent() {
134 return pp::WheelInputEvent(
135 instance_,
136 100, // time_stamp
137 0, // modifiers
138 pp::FloatPoint(1, 2),
139 pp::FloatPoint(3, 4),
140 PP_TRUE); // scroll_by_page
143 pp::InputEvent TestInputEvent::CreateKeyEvent(PP_InputEvent_Type type,
144 uint32_t key_code) {
145 return pp::KeyboardInputEvent(
146 instance_,
147 type,
148 100, // time_stamp
149 0, // modifiers
150 key_code,
151 pp::Var());
154 pp::InputEvent TestInputEvent::CreateCharEvent(const std::string& text) {
155 return pp::KeyboardInputEvent(
156 instance_,
157 PP_INPUTEVENT_TYPE_CHAR,
158 100, // time_stamp
159 0, // modifiers
160 0, // keycode
161 pp::Var(text));
164 pp::InputEvent TestInputEvent::CreateTouchEvent(PP_InputEvent_Type type,
165 const pp::FloatPoint& point) {
166 PP_TouchPoint touch_point = PP_MakeTouchPoint();
167 touch_point.position = point;
169 pp::TouchInputEvent touch_event(instance_, type, 100, 0);
170 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_TOUCHES, touch_point);
171 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, touch_point);
172 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_TARGETTOUCHES, touch_point);
174 return touch_event;
177 void TestInputEvent::PostMessageBarrier() {
178 received_finish_message_ = false;
179 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
180 testing_interface_->RunMessageLoop(instance_->pp_instance());
181 nested_event_.Wait();
184 // Simulates the input event and calls PostMessage to let us know when
185 // we have received all resulting events from the browser.
186 bool TestInputEvent::SimulateInputEvent(
187 const pp::InputEvent& input_event) {
188 expected_input_event_ = pp::InputEvent(input_event.pp_resource());
189 received_expected_event_ = false;
190 testing_interface_->SimulateInputEvent(instance_->pp_instance(),
191 input_event.pp_resource());
192 PostMessageBarrier();
193 return received_expected_event_;
196 bool TestInputEvent::AreEquivalentEvents(PP_Resource received,
197 PP_Resource expected) {
198 if (!input_event_interface_->IsInputEvent(received) ||
199 !input_event_interface_->IsInputEvent(expected)) {
200 return false;
203 // Test common fields, except modifiers and time stamp, which may be changed
204 // by the browser.
205 int32_t received_type = input_event_interface_->GetType(received);
206 int32_t expected_type = input_event_interface_->GetType(expected);
207 if (received_type != expected_type) {
208 // Allow key down events to match "raw" key down events.
209 if (expected_type != PP_INPUTEVENT_TYPE_KEYDOWN &&
210 received_type != PP_INPUTEVENT_TYPE_RAWKEYDOWN) {
211 return false;
215 // Test event type-specific fields.
216 switch (input_event_interface_->GetType(received)) {
217 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
218 case PP_INPUTEVENT_TYPE_MOUSEUP:
219 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
220 case PP_INPUTEVENT_TYPE_MOUSEENTER:
221 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
222 // Check mouse fields, except position and movement, which may be
223 // modified by the renderer.
224 return
225 mouse_input_event_interface_->GetButton(received) ==
226 mouse_input_event_interface_->GetButton(expected) &&
227 mouse_input_event_interface_->GetClickCount(received) ==
228 mouse_input_event_interface_->GetClickCount(expected);
230 case PP_INPUTEVENT_TYPE_WHEEL:
231 return
232 pp::FloatPoint(wheel_input_event_interface_->GetDelta(received)) ==
233 pp::FloatPoint(wheel_input_event_interface_->GetDelta(expected)) &&
234 pp::FloatPoint(wheel_input_event_interface_->GetTicks(received)) ==
235 pp::FloatPoint(wheel_input_event_interface_->GetTicks(expected)) &&
236 wheel_input_event_interface_->GetScrollByPage(received) ==
237 wheel_input_event_interface_->GetScrollByPage(expected);
239 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
240 case PP_INPUTEVENT_TYPE_KEYDOWN:
241 case PP_INPUTEVENT_TYPE_KEYUP:
242 return
243 keyboard_input_event_interface_->GetKeyCode(received) ==
244 keyboard_input_event_interface_->GetKeyCode(expected);
246 case PP_INPUTEVENT_TYPE_CHAR:
247 return
248 keyboard_input_event_interface_->GetKeyCode(received) ==
249 keyboard_input_event_interface_->GetKeyCode(expected) &&
250 pp::Var(pp::PASS_REF,
251 keyboard_input_event_interface_->GetCharacterText(received)) ==
252 pp::Var(pp::PASS_REF,
253 keyboard_input_event_interface_->GetCharacterText(expected));
255 case PP_INPUTEVENT_TYPE_TOUCHSTART:
256 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
257 case PP_INPUTEVENT_TYPE_TOUCHEND:
258 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: {
259 if (!touch_input_event_interface_->IsTouchInputEvent(received) ||
260 !touch_input_event_interface_->IsTouchInputEvent(expected))
261 return false;
263 uint32_t touch_count = touch_input_event_interface_->GetTouchCount(
264 received, PP_TOUCHLIST_TYPE_TOUCHES);
265 if (touch_count <= 0 ||
266 touch_count != touch_input_event_interface_->GetTouchCount(expected,
267 PP_TOUCHLIST_TYPE_TOUCHES))
268 return false;
270 for (uint32_t i = 0; i < touch_count; ++i) {
271 PP_TouchPoint expected_point = touch_input_event_interface_->
272 GetTouchByIndex(expected, PP_TOUCHLIST_TYPE_TOUCHES, i);
273 PP_TouchPoint received_point = touch_input_event_interface_->
274 GetTouchByIndex(received, PP_TOUCHLIST_TYPE_TOUCHES, i);
276 if (expected_point.id != received_point.id ||
277 expected_point.radius != received_point.radius ||
278 expected_point.rotation_angle != received_point.rotation_angle ||
279 expected_point.pressure != received_point.pressure)
280 return false;
282 if (expected_point.position.x != received_point.position.x ||
283 expected_point.position.y != received_point.position.y)
284 return false;
286 return true;
289 default:
290 break;
293 return false;
296 bool TestInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
297 // Some events may cause extra events to be generated, so look for the
298 // first one that matches.
299 if (!received_expected_event_) {
300 received_expected_event_ = AreEquivalentEvents(
301 input_event.pp_resource(),
302 expected_input_event_.pp_resource());
304 // Handle all input events.
305 return true;
308 void TestInputEvent::HandleMessage(const pp::Var& message_data) {
309 if (message_data.is_string() &&
310 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) {
311 testing_interface_->QuitMessageLoop(instance_->pp_instance());
312 received_finish_message_ = true;
313 nested_event_.Signal();
317 void TestInputEvent::DidChangeView(const pp::View& view) {
318 view_rect_ = view.GetRect();
321 std::string TestInputEvent::TestEvents() {
322 // Request all input event classes.
323 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
324 PP_INPUTEVENT_CLASS_MOUSE |
325 PP_INPUTEVENT_CLASS_WHEEL |
326 PP_INPUTEVENT_CLASS_KEYBOARD |
327 PP_INPUTEVENT_CLASS_TOUCH);
328 PostMessageBarrier();
330 // Send the events and check that we received them.
331 ASSERT_TRUE(
332 SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN,
333 PP_INPUTEVENT_MOUSEBUTTON_LEFT)));
334 ASSERT_TRUE(
335 SimulateInputEvent(CreateWheelEvent()));
336 ASSERT_TRUE(
337 SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN,
338 kSpaceChar)));
339 ASSERT_TRUE(
340 SimulateInputEvent(CreateCharEvent(kSpaceString)));
341 ASSERT_TRUE(SimulateInputEvent(CreateTouchEvent(PP_INPUTEVENT_TYPE_TOUCHSTART,
342 pp::FloatPoint(12, 23))));
343 // Request only mouse events.
344 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
345 PP_INPUTEVENT_CLASS_WHEEL |
346 PP_INPUTEVENT_CLASS_KEYBOARD);
347 PostMessageBarrier();
349 // Check that we only receive mouse events.
350 ASSERT_TRUE(
351 SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN,
352 PP_INPUTEVENT_MOUSEBUTTON_LEFT)));
353 ASSERT_FALSE(
354 SimulateInputEvent(CreateWheelEvent()));
355 ASSERT_FALSE(
356 SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN,
357 kSpaceChar)));
358 ASSERT_FALSE(
359 SimulateInputEvent(CreateCharEvent(kSpaceString)));
361 PASS();
364 std::string TestInputEvent::TestAcceptTouchEvent_1() {
365 // The browser normally sends touch-events to the renderer only if the page
366 // has touch-event handlers. Since test-case.html does not have any
367 // touch-event handler, it would normally not receive any touch events from
368 // the browser. However, if a plugin in the page does accept touch events,
369 // then the browser should start sending touch-events to the page. In this
370 // test, the plugin simply registers for touch-events. The real test is to
371 // verify that the browser knows to send touch-events to the renderer.
372 // If the plugin is removed from the page, then there are no more touch-event
373 // handlers in the page, and browser stops sending touch-events. So to make
374 // it possible to test this properly, the plugin is not removed from the page
375 // at the end of the test.
376 instance_->set_remove_plugin(false);
377 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
378 PP_INPUTEVENT_CLASS_MOUSE |
379 PP_INPUTEVENT_CLASS_WHEEL |
380 PP_INPUTEVENT_CLASS_KEYBOARD |
381 PP_INPUTEVENT_CLASS_TOUCH);
382 PASS();
385 std::string TestInputEvent::TestAcceptTouchEvent_2() {
386 // See comment in TestAcceptTouchEvent_1.
387 instance_->set_remove_plugin(false);
388 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
389 PP_INPUTEVENT_CLASS_MOUSE |
390 PP_INPUTEVENT_CLASS_WHEEL |
391 PP_INPUTEVENT_CLASS_KEYBOARD |
392 PP_INPUTEVENT_CLASS_TOUCH);
393 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
394 PP_INPUTEVENT_CLASS_TOUCH);
395 PASS();
398 std::string TestInputEvent::TestAcceptTouchEvent_3() {
399 // See comment in TestAcceptTouchEvent_1.
400 instance_->set_remove_plugin(false);
401 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
402 PP_INPUTEVENT_CLASS_MOUSE |
403 PP_INPUTEVENT_CLASS_WHEEL |
404 PP_INPUTEVENT_CLASS_KEYBOARD);
405 input_event_interface_->RequestFilteringInputEvents(instance_->pp_instance(),
406 PP_INPUTEVENT_CLASS_TOUCH);
407 PASS();
410 std::string TestInputEvent::TestAcceptTouchEvent_4() {
411 // See comment in TestAcceptTouchEvent_1.
412 instance_->set_remove_plugin(false);
413 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
414 PP_INPUTEVENT_CLASS_MOUSE |
415 PP_INPUTEVENT_CLASS_WHEEL |
416 PP_INPUTEVENT_CLASS_KEYBOARD);
417 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
418 PP_INPUTEVENT_CLASS_TOUCH);
419 PASS();