Index: ppapi/tests/test_input_event.cc |
=================================================================== |
--- ppapi/tests/test_input_event.cc (revision 0) |
+++ ppapi/tests/test_input_event.cc (revision 0) |
@@ -0,0 +1,290 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ppapi/tests/test_input_event.h" |
+ |
+#include "ppapi/c/dev/ppb_testing_dev.h" |
+#include "ppapi/c/pp_errors.h" |
+#include "ppapi/c/ppb_input_event.h" |
+#include "ppapi/cpp/input_event.h" |
+#include "ppapi/cpp/module.h" |
+#include "ppapi/tests/test_utils.h" |
+#include "ppapi/tests/testing_instance.h" |
+ |
+REGISTER_TEST_CASE(InputEvent); |
+ |
+namespace { |
+ |
+const uint32_t kSpaceChar = 0x20; |
+const char* kSpaceString = " "; |
+ |
+#define FINISHED_WAITING_MESSAGE "TEST_INPUT_EVENT_FINISHED_WAITING" |
+ |
+pp::Point GetCenter(const pp::Rect& rect) { |
+ return pp::Point( |
+ rect.x() + rect.width() / 2, |
+ rect.y() + rect.height() / 2); |
+} |
+} |
+ |
+void TestInputEvent::RunTests(const std::string& filter) { |
+ RUN_TEST(Events, filter); |
+} |
+ |
+TestInputEvent::TestInputEvent(TestingInstance* instance) |
+ : TestCase(instance), |
+ input_event_interface_(NULL), |
+ mouse_input_event_interface_(NULL), |
+ wheel_input_event_interface_(NULL), |
+ keyboard_input_event_interface_(NULL), |
+ view_rect_(), |
+ expected_input_event_(0), |
+ received_expected_event_(false), |
+ received_finish_message_(false) { |
+} |
+ |
+TestInputEvent::~TestInputEvent() { |
+ // Remove the special listener that only responds to a |
+ // FINISHED_WAITING_MESSAGE string. See Init for where it gets added. |
+ std::string js_code; |
+ js_code += "var plugin = document.getElementById('plugin');" |
+ "plugin.removeEventListener('message'," |
+ " plugin.wait_for_messages_handler);" |
+ "delete plugin.wait_for_messages_handler;"; |
+ pp::Var exception; |
+ instance_->ExecuteScript(js_code, &exception); |
+} |
+ |
+bool TestInputEvent::Init() { |
+ input_event_interface_ = static_cast<PPB_InputEvent const*>( |
+ pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE)); |
+ mouse_input_event_interface_ = static_cast<PPB_MouseInputEvent const*>( |
+ pp::Module::Get()->GetBrowserInterface( |
+ PPB_MOUSE_INPUT_EVENT_INTERFACE)); |
+ wheel_input_event_interface_ = static_cast<PPB_WheelInputEvent const*>( |
+ pp::Module::Get()->GetBrowserInterface( |
+ PPB_WHEEL_INPUT_EVENT_INTERFACE)); |
+ keyboard_input_event_interface_ = static_cast<PPB_KeyboardInputEvent const*>( |
+ pp::Module::Get()->GetBrowserInterface( |
+ PPB_KEYBOARD_INPUT_EVENT_INTERFACE)); |
+ |
+ bool success = |
+ input_event_interface_ && |
+ mouse_input_event_interface_ && |
+ wheel_input_event_interface_ && |
+ keyboard_input_event_interface_ && |
+ InitTestingInterface(); |
+ |
+ // Set up a listener for our message that signals that all input events have |
+ // been received. |
+ std::string js_code; |
+ // Note the following code is dependent on some features of test_case.html. |
+ // E.g., it is assumed that the DOM element where the plugin is embedded has |
+ // an id of 'plugin', and there is a function 'IsTestingMessage' that allows |
+ // us to ignore the messages that are intended for use by the testing |
+ // framework itself. |
+ js_code += "var plugin = document.getElementById('plugin');" |
+ "var wait_for_messages_handler = function(message_event) {" |
+ " if (!IsTestingMessage(message_event.data) &&" |
+ " message_event.data === '" FINISHED_WAITING_MESSAGE "') {" |
+ " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');" |
+ " }" |
+ "};" |
+ "plugin.addEventListener('message', wait_for_messages_handler);" |
+ // Stash it on the plugin so we can remove it in the destructor. |
+ "plugin.wait_for_messages_handler = wait_for_messages_handler;"; |
+ pp::Var exception; |
+ instance_->ExecuteScript(js_code, &exception); |
+ success = success && exception.is_undefined(); |
+ |
+ return success; |
+} |
+ |
+pp::InputEvent TestInputEvent::CreateMouseEvent( |
+ PP_InputEvent_Type type, |
+ PP_InputEvent_MouseButton buttons) { |
+ return pp::MouseInputEvent( |
+ instance_, |
+ type, |
+ 100, // time_stamp |
+ 0, // modifiers |
+ buttons, |
+ GetCenter(view_rect_), |
+ 1, // click count |
+ pp::Point()); // movement |
+} |
+ |
+pp::InputEvent TestInputEvent::CreateWheelEvent() { |
+ return pp::WheelInputEvent( |
+ instance_, |
+ 100, // time_stamp |
+ 0, // modifiers |
+ pp::FloatPoint(1, 2), |
+ pp::FloatPoint(3, 4), |
+ PP_TRUE); // scroll_by_page |
+} |
+ |
+pp::InputEvent TestInputEvent::CreateKeyEvent(PP_InputEvent_Type type, |
+ uint32_t key_code) { |
+ return pp::KeyboardInputEvent( |
+ instance_, |
+ type, |
+ 100, // time_stamp |
+ 0, // modifiers |
+ key_code, |
+ pp::Var()); |
+} |
+ |
+pp::InputEvent TestInputEvent::CreateCharEvent(const std::string& text) { |
+ return pp::KeyboardInputEvent( |
+ instance_, |
+ PP_INPUTEVENT_TYPE_CHAR, |
+ 100, // time_stamp |
+ 0, // modifiers |
+ 0, // keycode |
+ pp::Var(text)); |
+} |
+ |
+// Simulates the input event and calls PostMessage to let us know when |
+// we have received all resulting events from the browser. |
+bool TestInputEvent::SimulateInputEvent( |
+ const pp::InputEvent& input_event) { |
+ expected_input_event_ = pp::InputEvent(input_event.pp_resource()); |
+ received_expected_event_ = false; |
+ received_finish_message_ = false; |
+ testing_interface_->SimulateInputEvent(instance_->pp_instance(), |
+ input_event.pp_resource()); |
+ instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); |
+ testing_interface_->RunMessageLoop(instance_->pp_instance()); |
+ return received_finish_message_ && received_expected_event_; |
+} |
+ |
+bool TestInputEvent::AreEquivalentEvents(PP_Resource received, |
+ PP_Resource expected) { |
+ if (!input_event_interface_->IsInputEvent(received) || |
+ !input_event_interface_->IsInputEvent(expected)) { |
+ return false; |
+ } |
+ |
+ // Test common fields, except modifiers and time stamp, which may be changed |
+ // by the browser. |
+ int32_t received_type = input_event_interface_->GetType(received); |
+ int32_t expected_type = input_event_interface_->GetType(expected); |
+ if (received_type != expected_type) { |
+ // Allow key down events to match "raw" key down events. |
+ if (expected_type != PP_INPUTEVENT_TYPE_KEYDOWN && |
+ received_type != PP_INPUTEVENT_TYPE_RAWKEYDOWN) { |
+ return false; |
+ } |
+ } |
+ |
+ // Test event type-specific fields. |
+ switch (input_event_interface_->GetType(received)) { |
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN: |
+ case PP_INPUTEVENT_TYPE_MOUSEUP: |
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: |
+ case PP_INPUTEVENT_TYPE_MOUSEENTER: |
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE: |
+ // Check mouse fields, except position and movement, which may be |
+ // modified by the renderer. |
+ return |
+ mouse_input_event_interface_->GetButton(received) == |
+ mouse_input_event_interface_->GetButton(expected) && |
+ mouse_input_event_interface_->GetClickCount(received) == |
+ mouse_input_event_interface_->GetClickCount(expected); |
+ |
+ case PP_INPUTEVENT_TYPE_WHEEL: |
+ return |
+ pp::FloatPoint(wheel_input_event_interface_->GetDelta(received)) == |
+ pp::FloatPoint(wheel_input_event_interface_->GetDelta(expected)) && |
+ pp::FloatPoint(wheel_input_event_interface_->GetTicks(received)) == |
+ pp::FloatPoint(wheel_input_event_interface_->GetTicks(expected)) && |
+ wheel_input_event_interface_->GetScrollByPage(received) == |
+ wheel_input_event_interface_->GetScrollByPage(expected); |
+ |
+ case PP_INPUTEVENT_TYPE_RAWKEYDOWN: |
+ case PP_INPUTEVENT_TYPE_KEYDOWN: |
+ case PP_INPUTEVENT_TYPE_KEYUP: |
+ return |
+ keyboard_input_event_interface_->GetKeyCode(received) == |
+ keyboard_input_event_interface_->GetKeyCode(expected); |
+ |
+ case PP_INPUTEVENT_TYPE_CHAR: |
+ return |
+ keyboard_input_event_interface_->GetKeyCode(received) == |
+ keyboard_input_event_interface_->GetKeyCode(expected) && |
+ pp::Var(pp::Var::PassRef(), |
+ keyboard_input_event_interface_->GetCharacterText(received)) == |
+ pp::Var(pp::Var::PassRef(), |
+ keyboard_input_event_interface_->GetCharacterText(expected)); |
+ |
+ default: |
+ break; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool TestInputEvent::HandleInputEvent(const pp::InputEvent& input_event) { |
+ // Some events may cause extra events to be generated, so look for the |
+ // first one that matches. |
+ if (!received_expected_event_) { |
+ received_expected_event_ = AreEquivalentEvents( |
+ input_event.pp_resource(), |
+ expected_input_event_.pp_resource()); |
+ } |
+ // Handle all input events. |
+ return true; |
+} |
+ |
+void TestInputEvent::HandleMessage(const pp::Var& message_data) { |
+ if (message_data.is_string() && |
+ (message_data.AsString() == FINISHED_WAITING_MESSAGE)) { |
+ testing_interface_->QuitMessageLoop(instance_->pp_instance()); |
+ received_finish_message_ = true; |
+ } |
+} |
+ |
+void TestInputEvent::DidChangeView(const pp::Rect& position, |
+ const pp::Rect& clip) { |
+ view_rect_ = position; |
+} |
+ |
+std::string TestInputEvent::TestEvents() { |
+ // Request all input event classes. |
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(), |
+ PP_INPUTEVENT_CLASS_MOUSE | |
+ PP_INPUTEVENT_CLASS_WHEEL | |
+ PP_INPUTEVENT_CLASS_KEYBOARD); |
+ // Send the events and check that we received them. |
+ ASSERT_TRUE( |
+ SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN, |
+ PP_INPUTEVENT_MOUSEBUTTON_LEFT))); |
+ ASSERT_TRUE( |
+ SimulateInputEvent(CreateWheelEvent())); |
+ ASSERT_TRUE( |
+ SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN, |
+ kSpaceChar))); |
+ ASSERT_TRUE( |
+ SimulateInputEvent(CreateCharEvent(kSpaceString))); |
+ |
+ // Request only mouse events. |
+ input_event_interface_->ClearInputEventRequest(instance_->pp_instance(), |
+ PP_INPUTEVENT_CLASS_WHEEL | |
+ PP_INPUTEVENT_CLASS_KEYBOARD); |
+ // Check that we only receive mouse events. |
+ ASSERT_TRUE( |
+ SimulateInputEvent(CreateMouseEvent(PP_INPUTEVENT_TYPE_MOUSEDOWN, |
+ PP_INPUTEVENT_MOUSEBUTTON_LEFT))); |
+ ASSERT_FALSE( |
+ SimulateInputEvent(CreateWheelEvent())); |
+ ASSERT_FALSE( |
+ SimulateInputEvent(CreateKeyEvent(PP_INPUTEVENT_TYPE_KEYDOWN, |
+ kSpaceChar))); |
+ ASSERT_FALSE( |
+ SimulateInputEvent(CreateCharEvent(kSpaceString))); |
+ |
+ PASS(); |
+} |
+ |