Fix build break
[chromium-blink-merge.git] / ppapi / tests / test_input_event.cc
blob8aa8340adab261159ddb3b71648f1197f6801401
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 view_rect_(),
55 expected_input_event_(0),
56 received_expected_event_(false),
57 received_finish_message_(false) {
60 TestInputEvent::~TestInputEvent() {
61 // Remove the special listener that only responds to a
62 // FINISHED_WAITING_MESSAGE string. See Init for where it gets added.
63 std::string js_code;
64 js_code += "var plugin = document.getElementById('plugin');"
65 "plugin.removeEventListener('message',"
66 " plugin.wait_for_messages_handler);"
67 "delete plugin.wait_for_messages_handler;";
68 instance_->EvalScript(js_code);
71 bool TestInputEvent::Init() {
72 input_event_interface_ = static_cast<const PPB_InputEvent*>(
73 pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
74 mouse_input_event_interface_ = static_cast<const PPB_MouseInputEvent*>(
75 pp::Module::Get()->GetBrowserInterface(
76 PPB_MOUSE_INPUT_EVENT_INTERFACE));
77 wheel_input_event_interface_ = static_cast<const PPB_WheelInputEvent*>(
78 pp::Module::Get()->GetBrowserInterface(
79 PPB_WHEEL_INPUT_EVENT_INTERFACE));
80 keyboard_input_event_interface_ = static_cast<const PPB_KeyboardInputEvent*>(
81 pp::Module::Get()->GetBrowserInterface(
82 PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
83 touch_input_event_interface_ = static_cast<const PPB_TouchInputEvent*>(
84 pp::Module::Get()->GetBrowserInterface(
85 PPB_TOUCH_INPUT_EVENT_INTERFACE));
87 bool success =
88 input_event_interface_ &&
89 mouse_input_event_interface_ &&
90 wheel_input_event_interface_ &&
91 keyboard_input_event_interface_ &&
92 touch_input_event_interface_ &&
93 CheckTestingInterface();
95 // Set up a listener for our message that signals that all input events have
96 // been received.
97 std::string js_code;
98 // Note the following code is dependent on some features of test_case.html.
99 // E.g., it is assumed that the DOM element where the plugin is embedded has
100 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
101 // us to ignore the messages that are intended for use by the testing
102 // framework itself.
103 js_code += "var plugin = document.getElementById('plugin');"
104 "var wait_for_messages_handler = function(message_event) {"
105 " if (!IsTestingMessage(message_event.data) &&"
106 " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
107 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
108 " }"
109 "};"
110 "plugin.addEventListener('message', wait_for_messages_handler);"
111 // Stash it on the plugin so we can remove it in the destructor.
112 "plugin.wait_for_messages_handler = wait_for_messages_handler;";
113 instance_->EvalScript(js_code);
115 return success;
118 pp::InputEvent TestInputEvent::CreateMouseEvent(
119 PP_InputEvent_Type type,
120 PP_InputEvent_MouseButton buttons) {
121 return pp::MouseInputEvent(
122 instance_,
123 type,
124 100, // time_stamp
125 0, // modifiers
126 buttons,
127 GetCenter(view_rect_),
128 1, // click count
129 pp::Point()); // movement
132 pp::InputEvent TestInputEvent::CreateWheelEvent() {
133 return pp::WheelInputEvent(
134 instance_,
135 100, // time_stamp
136 0, // modifiers
137 pp::FloatPoint(1, 2),
138 pp::FloatPoint(3, 4),
139 PP_TRUE); // scroll_by_page
142 pp::InputEvent TestInputEvent::CreateKeyEvent(PP_InputEvent_Type type,
143 uint32_t key_code) {
144 return pp::KeyboardInputEvent(
145 instance_,
146 type,
147 100, // time_stamp
148 0, // modifiers
149 key_code,
150 pp::Var());
153 pp::InputEvent TestInputEvent::CreateCharEvent(const std::string& text) {
154 return pp::KeyboardInputEvent(
155 instance_,
156 PP_INPUTEVENT_TYPE_CHAR,
157 100, // time_stamp
158 0, // modifiers
159 0, // keycode
160 pp::Var(text));
163 pp::InputEvent TestInputEvent::CreateTouchEvent(PP_InputEvent_Type type,
164 const pp::FloatPoint& point) {
165 PP_TouchPoint touch_point = PP_MakeTouchPoint();
166 touch_point.position = point;
168 pp::TouchInputEvent touch_event(instance_, type, 100, 0);
169 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_TOUCHES, touch_point);
170 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, touch_point);
171 touch_event.AddTouchPoint(PP_TOUCHLIST_TYPE_TARGETTOUCHES, touch_point);
173 return touch_event;
176 // Simulates the input event and calls PostMessage to let us know when
177 // we have received all resulting events from the browser.
178 bool TestInputEvent::SimulateInputEvent(
179 const pp::InputEvent& input_event) {
180 expected_input_event_ = pp::InputEvent(input_event.pp_resource());
181 received_expected_event_ = false;
182 received_finish_message_ = false;
183 testing_interface_->SimulateInputEvent(instance_->pp_instance(),
184 input_event.pp_resource());
185 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
186 testing_interface_->RunMessageLoop(instance_->pp_instance());
187 return received_finish_message_ && received_expected_event_;
190 bool TestInputEvent::AreEquivalentEvents(PP_Resource received,
191 PP_Resource expected) {
192 if (!input_event_interface_->IsInputEvent(received) ||
193 !input_event_interface_->IsInputEvent(expected)) {
194 return false;
197 // Test common fields, except modifiers and time stamp, which may be changed
198 // by the browser.
199 int32_t received_type = input_event_interface_->GetType(received);
200 int32_t expected_type = input_event_interface_->GetType(expected);
201 if (received_type != expected_type) {
202 // Allow key down events to match "raw" key down events.
203 if (expected_type != PP_INPUTEVENT_TYPE_KEYDOWN &&
204 received_type != PP_INPUTEVENT_TYPE_RAWKEYDOWN) {
205 return false;
209 // Test event type-specific fields.
210 switch (input_event_interface_->GetType(received)) {
211 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
212 case PP_INPUTEVENT_TYPE_MOUSEUP:
213 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
214 case PP_INPUTEVENT_TYPE_MOUSEENTER:
215 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
216 // Check mouse fields, except position and movement, which may be
217 // modified by the renderer.
218 return
219 mouse_input_event_interface_->GetButton(received) ==
220 mouse_input_event_interface_->GetButton(expected) &&
221 mouse_input_event_interface_->GetClickCount(received) ==
222 mouse_input_event_interface_->GetClickCount(expected);
224 case PP_INPUTEVENT_TYPE_WHEEL:
225 return
226 pp::FloatPoint(wheel_input_event_interface_->GetDelta(received)) ==
227 pp::FloatPoint(wheel_input_event_interface_->GetDelta(expected)) &&
228 pp::FloatPoint(wheel_input_event_interface_->GetTicks(received)) ==
229 pp::FloatPoint(wheel_input_event_interface_->GetTicks(expected)) &&
230 wheel_input_event_interface_->GetScrollByPage(received) ==
231 wheel_input_event_interface_->GetScrollByPage(expected);
233 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
234 case PP_INPUTEVENT_TYPE_KEYDOWN:
235 case PP_INPUTEVENT_TYPE_KEYUP:
236 return
237 keyboard_input_event_interface_->GetKeyCode(received) ==
238 keyboard_input_event_interface_->GetKeyCode(expected);
240 case PP_INPUTEVENT_TYPE_CHAR:
241 return
242 keyboard_input_event_interface_->GetKeyCode(received) ==
243 keyboard_input_event_interface_->GetKeyCode(expected) &&
244 pp::Var(pp::PASS_REF,
245 keyboard_input_event_interface_->GetCharacterText(received)) ==
246 pp::Var(pp::PASS_REF,
247 keyboard_input_event_interface_->GetCharacterText(expected));
249 case PP_INPUTEVENT_TYPE_TOUCHSTART:
250 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
251 case PP_INPUTEVENT_TYPE_TOUCHEND:
252 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: {
253 if (!touch_input_event_interface_->IsTouchInputEvent(received) ||
254 !touch_input_event_interface_->IsTouchInputEvent(expected))
255 return false;
257 uint32_t touch_count = touch_input_event_interface_->GetTouchCount(
258 received, PP_TOUCHLIST_TYPE_TOUCHES);
259 if (touch_count <= 0 ||
260 touch_count != touch_input_event_interface_->GetTouchCount(expected,
261 PP_TOUCHLIST_TYPE_TOUCHES))
262 return false;
264 for (uint32_t i = 0; i < touch_count; ++i) {
265 PP_TouchPoint expected_point = touch_input_event_interface_->
266 GetTouchByIndex(expected, PP_TOUCHLIST_TYPE_TOUCHES, i);
267 PP_TouchPoint received_point = touch_input_event_interface_->
268 GetTouchByIndex(received, PP_TOUCHLIST_TYPE_TOUCHES, i);
270 if (expected_point.id != received_point.id ||
271 expected_point.radius != received_point.radius ||
272 expected_point.rotation_angle != received_point.rotation_angle ||
273 expected_point.pressure != received_point.pressure)
274 return false;
276 if (expected_point.position.x != received_point.position.x ||
277 expected_point.position.y != received_point.position.y)
278 return false;
280 return true;
283 default:
284 break;
287 return false;
290 bool TestInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
291 // Some events may cause extra events to be generated, so look for the
292 // first one that matches.
293 if (!received_expected_event_) {
294 received_expected_event_ = AreEquivalentEvents(
295 input_event.pp_resource(),
296 expected_input_event_.pp_resource());
298 // Handle all input events.
299 return true;
302 void TestInputEvent::HandleMessage(const pp::Var& message_data) {
303 if (message_data.is_string() &&
304 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) {
305 testing_interface_->QuitMessageLoop(instance_->pp_instance());
306 received_finish_message_ = true;
310 void TestInputEvent::DidChangeView(const pp::View& view) {
311 view_rect_ = view.GetRect();
314 std::string TestInputEvent::TestEvents() {
315 // Request all input event classes.
316 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
317 PP_INPUTEVENT_CLASS_MOUSE |
318 PP_INPUTEVENT_CLASS_WHEEL |
319 PP_INPUTEVENT_CLASS_KEYBOARD |
320 PP_INPUTEVENT_CLASS_TOUCH);
321 // Send the events and check that we received them.
322 ASSERT_TRUE(
323 SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN,
324 PP_INPUTEVENT_MOUSEBUTTON_LEFT)));
325 ASSERT_TRUE(
326 SimulateInputEvent(CreateWheelEvent()));
327 ASSERT_TRUE(
328 SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN,
329 kSpaceChar)));
330 ASSERT_TRUE(
331 SimulateInputEvent(CreateCharEvent(kSpaceString)));
332 ASSERT_TRUE(SimulateInputEvent(CreateTouchEvent(PP_INPUTEVENT_TYPE_TOUCHSTART,
333 pp::FloatPoint(12, 23))));
334 // Request only mouse events.
335 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
336 PP_INPUTEVENT_CLASS_WHEEL |
337 PP_INPUTEVENT_CLASS_KEYBOARD);
338 // Check that we only receive mouse events.
339 ASSERT_TRUE(
340 SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN,
341 PP_INPUTEVENT_MOUSEBUTTON_LEFT)));
342 ASSERT_FALSE(
343 SimulateInputEvent(CreateWheelEvent()));
344 ASSERT_FALSE(
345 SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN,
346 kSpaceChar)));
347 ASSERT_FALSE(
348 SimulateInputEvent(CreateCharEvent(kSpaceString)));
350 PASS();
353 std::string TestInputEvent::TestAcceptTouchEvent_1() {
354 // The browser normally sends touch-events to the renderer only if the page
355 // has touch-event handlers. Since test-case.html does not have any
356 // touch-event handler, it would normally not receive any touch events from
357 // the browser. However, if a plugin in the page does accept touch events,
358 // then the browser should start sending touch-events to the page. In this
359 // test, the plugin simply registers for touch-events. The real test is to
360 // verify that the browser knows to send touch-events to the renderer.
361 // If the plugin is removed from the page, then there are no more touch-event
362 // handlers in the page, and browser stops sending touch-events. So to make
363 // it possible to test this properly, the plugin is not removed from the page
364 // at the end of the test.
365 instance_->set_remove_plugin(false);
366 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
367 PP_INPUTEVENT_CLASS_MOUSE |
368 PP_INPUTEVENT_CLASS_WHEEL |
369 PP_INPUTEVENT_CLASS_KEYBOARD |
370 PP_INPUTEVENT_CLASS_TOUCH);
371 PASS();
374 std::string TestInputEvent::TestAcceptTouchEvent_2() {
375 // See comment in TestAcceptTouchEvent_1.
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 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
383 PP_INPUTEVENT_CLASS_TOUCH);
384 PASS();
387 std::string TestInputEvent::TestAcceptTouchEvent_3() {
388 // See comment in TestAcceptTouchEvent_1.
389 instance_->set_remove_plugin(false);
390 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
391 PP_INPUTEVENT_CLASS_MOUSE |
392 PP_INPUTEVENT_CLASS_WHEEL |
393 PP_INPUTEVENT_CLASS_KEYBOARD);
394 input_event_interface_->RequestFilteringInputEvents(instance_->pp_instance(),
395 PP_INPUTEVENT_CLASS_TOUCH);
396 PASS();
399 std::string TestInputEvent::TestAcceptTouchEvent_4() {
400 // See comment in TestAcceptTouchEvent_1.
401 instance_->set_remove_plugin(false);
402 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
403 PP_INPUTEVENT_CLASS_MOUSE |
404 PP_INPUTEVENT_CLASS_WHEEL |
405 PP_INPUTEVENT_CLASS_KEYBOARD);
406 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
407 PP_INPUTEVENT_CLASS_TOUCH);
408 PASS();