Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Unified Diff: ppapi/tests/test_ime_input_event.cc

Issue 10391101: Test for Pepper IME events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments from kochi & merge master. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ppapi/tests/test_ime_input_event.h ('k') | ppapi/thunk/interfaces_ppb_public_dev.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ppapi/tests/test_ime_input_event.cc
diff --git a/ppapi/tests/test_ime_input_event.cc b/ppapi/tests/test_ime_input_event.cc
new file mode 100644
index 0000000000000000000000000000000000000000..804e17d7abed7a640ba72fba80e325e3e212f4cb
--- /dev/null
+++ b/ppapi/tests/test_ime_input_event.cc
@@ -0,0 +1,425 @@
+// Copyright (c) 2012 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_ime_input_event.h"
+
+#include "ppapi/c/dev/ppb_ime_input_event_dev.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/dev/ime_input_event_dev.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(ImeInputEvent);
+
+namespace {
+
+// Japanese Kanji letters meaning "a string" ('mo' 'ji' 'retsu' in Kanji)
+const char* kCompositionChar[] = {
+ "\xE6\x96\x87", "\xE5\xAD\x97", "\xE5\x88\x97"
+};
+
+const char kCompositionText[] = "\xE6\x96\x87\xE5\xAD\x97\xE5\x88\x97";
+
+#define FINISHED_WAITING_MESSAGE "TEST_IME_INPUT_EVENT_FINISHED_WAITING"
+
+} // namespace
+
+TestImeInputEvent::TestImeInputEvent(TestingInstance* instance)
+ : TestCase(instance),
+ input_event_interface_(NULL),
+ keyboard_input_event_interface_(NULL),
+ ime_input_event_interface_(NULL),
+ received_unexpected_event_(true),
+ received_finish_message_(false) {
+}
+
+TestImeInputEvent::~TestImeInputEvent() {
+ // 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;";
+ instance_->EvalScript(js_code);
+}
+
+void TestImeInputEvent::RunTests(const std::string& filter) {
+ RUN_TEST(ImeCommit, filter);
+ RUN_TEST(ImeCancel, filter);
+ RUN_TEST(ImeUnawareCommit, filter);
+ RUN_TEST(ImeUnawareCancel, filter);
+}
+
+bool TestImeInputEvent::Init() {
+ input_event_interface_ = static_cast<const PPB_InputEvent*>(
+ pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
+ keyboard_input_event_interface_ =
+ static_cast<const PPB_KeyboardInputEvent*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
+ ime_input_event_interface_ = static_cast<const PPB_IMEInputEvent_Dev*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_IME_INPUT_EVENT_DEV_INTERFACE));
+
+ bool success =
+ input_event_interface_ &&
+ keyboard_input_event_interface_ &&
+ ime_input_event_interface_ &&
+ CheckTestingInterface();
+
+ // Set up a listener for our message that signals that all input events have
+ // been received.
+ // 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.
+ std::string 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;";
+ instance_->EvalScript(js_code);
+
+ return success;
+}
+
+bool TestImeInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
+ // Check whether the IME related events comes in the expected order.
+ switch (input_event.GetType()) {
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
+ case PP_INPUTEVENT_TYPE_IME_TEXT:
+ case PP_INPUTEVENT_TYPE_CHAR:
+ if (expected_events_.empty()) {
+ received_unexpected_event_ = true;
+ } else {
+ received_unexpected_event_ =
+ !AreEquivalentEvents(input_event.pp_resource(),
+ expected_events_.front().pp_resource());
+ expected_events_.erase(expected_events_.begin());
+ }
+ break;
+
+ default:
+ // Don't care for any other input event types for this test.
+ break;
+ }
+
+ // Handle all input events.
+ return true;
+}
+
+void TestImeInputEvent::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 TestImeInputEvent::DidChangeView(const pp::View& view) {
+ view_rect_ = view.GetRect();
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionStartEvent() {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
+ 100, // time_stamp
+ pp::Var(""),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionUpdateEvent(
+ const std::string& text,
+ const std::vector<uint32_t>& segments,
+ int32_t target_segment,
+ const std::pair<uint32_t, uint32_t>& selection) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
+ 100, // time_stamp
+ text,
+ segments,
+ target_segment,
+ selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionEndEvent(
+ const std::string& text) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
+ 100, // time_stamp
+ pp::Var(text),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeTextEvent(const std::string& text) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_TEXT,
+ 100, // time_stamp
+ pp::Var(text),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateCharEvent(const std::string& text) {
+ return pp::KeyboardInputEvent(
+ instance_,
+ PP_INPUTEVENT_TYPE_CHAR,
+ 100, // time_stamp
+ 0, // modifiers
+ 0, // keycode
+ pp::Var(text));
+}
+
+void TestImeInputEvent::GetFocusBySimulatingMouseClick() {
+ // For receiving IME events, the plugin DOM node needs to be focused.
+ // The following code is for achieving that by simulating a mouse click event.
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_MOUSE);
+ SimulateInputEvent(pp::MouseInputEvent(
+ instance_,
+ PP_INPUTEVENT_TYPE_MOUSEDOWN,
+ 100, // time_stamp
+ 0, // modifiers
+ PP_INPUTEVENT_MOUSEBUTTON_LEFT,
+ pp::Point(
+ view_rect_.x() + view_rect_.width() / 2,
+ view_rect_.y() + view_rect_.height() / 2),
+ 1, // click count
+ pp::Point())); // movement
+}
+
+// Simulates the input event and calls PostMessage to let us know when
+// we have received all resulting events from the browser.
+bool TestImeInputEvent::SimulateInputEvent(const pp::InputEvent& input_event) {
+ received_unexpected_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_unexpected_event_;
+}
+
+bool TestImeInputEvent::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)
+ return false;
+
+ // Test event type-specific fields.
+ switch (received_type) {
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
+ // COMPOSITION_START does not convey further information.
+ break;
+
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
+ case PP_INPUTEVENT_TYPE_IME_TEXT:
+ // For COMPOSITION_END and TEXT, GetText() has meaning.
+ return pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(received)) ==
+ pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(expected));
+
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
+ // For COMPOSITION_UPDATE, all fields must be checked.
+ {
+ uint32_t received_segment_number =
+ ime_input_event_interface_->GetSegmentNumber(received);
+ uint32_t expected_segment_number =
+ ime_input_event_interface_->GetSegmentNumber(expected);
+ if (received_segment_number != expected_segment_number)
+ return false;
+
+ // The "<=" is not a bug. i-th segment is represented as the pair of
+ // i-th and (i+1)-th offsets in Pepper IME API.
+ for (uint32_t i = 0; i <= received_segment_number; ++i) {
+ if (ime_input_event_interface_->GetSegmentOffset(received, i) !=
+ ime_input_event_interface_->GetSegmentOffset(expected, i))
+ return false;
+ }
+
+ uint32_t received_selection_start = 0;
+ uint32_t received_selection_end = 0;
+ uint32_t expected_selection_start = 0;
+ uint32_t expected_selection_end = 0;
+ ime_input_event_interface_->GetSelection(
+ received, &received_selection_start, &received_selection_end);
+ ime_input_event_interface_->GetSelection(
+ expected, &expected_selection_start, &expected_selection_end);
+ if (received_selection_start != expected_selection_start ||
+ received_selection_end != expected_selection_end) {
+ return true;
+ }
+
+ return pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(received)) ==
+ pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(expected)) &&
+ ime_input_event_interface_->GetTargetSegment(received) ==
+ ime_input_event_interface_->GetTargetSegment(expected);
+ }
+
+ case PP_INPUTEVENT_TYPE_CHAR:
+ return
+ keyboard_input_event_interface_->GetKeyCode(received) ==
+ keyboard_input_event_interface_->GetKeyCode(expected) &&
+ pp::Var(pp::PASS_REF,
+ keyboard_input_event_interface_->GetCharacterText(received)) ==
+ pp::Var(pp::PASS_REF,
+ keyboard_input_event_interface_->GetCharacterText(expected));
+
+ default:
+ break;
+ }
+ return true;
+}
+
+std::string TestImeInputEvent::TestImeCommit() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_IME);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateImeCompositionStartEvent());
+ expected_events_.push_back(update_event);
+ expected_events_.push_back(CreateImeCompositionEndEvent(kCompositionText));
+ expected_events_.push_back(CreateImeTextEvent(kCompositionText));
+
+ // Simulate the case when IME successfully committed some text.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+std::string TestImeInputEvent::TestImeCancel() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_IME);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateImeCompositionStartEvent());
+ expected_events_.push_back(update_event);
+ expected_events_.push_back(CreateImeCompositionEndEvent(""));
+
+ // Simulate the case when IME canceled composition.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent("")));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+std::string TestImeInputEvent::TestImeUnawareCommit() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_IME);
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[0]));
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[1]));
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[2]));
+
+ // Test for IME-unaware plugins. Commit event is translated to char events.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+
+std::string TestImeInputEvent::TestImeUnawareCancel() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_IME);
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+
+ // Test for IME-unaware plugins. Cancel won't issue any events.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent("")));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
« no previous file with comments | « ppapi/tests/test_ime_input_event.h ('k') | ppapi/thunk/interfaces_ppb_public_dev.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698