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

Side by Side 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: . 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "ppapi/tests/test_ime_input_event.h"
6
7 #include "ppapi/c/pp_errors.h"
8 #include "ppapi/c/ppb_input_event.h"
9 #include "ppapi/c/dev/ppb_ime_input_event_dev.h"
yzshen1 2012/05/15 18:03:48 sort this section, please.
kinaba 2012/05/16 10:13:57 Done.
10 #include "ppapi/c/dev/ppb_testing_dev.h"
11 #include "ppapi/cpp/input_event.h"
12 #include "ppapi/cpp/module.h"
13 #include "ppapi/cpp/dev/ime_input_event_dev.h"
14 #include "ppapi/tests/test_utils.h"
15 #include "ppapi/tests/testing_instance.h"
16
17 REGISTER_TEST_CASE(ImeInputEvent);
18
19 namespace {
20
21 const char *(kCompositionChar[]) = {
22 "\xE6\x96\x87", "\xE5\xAD\x97", "\xE5\x88\x97"
23 };
24
25 const char kCompositionText[] = "\xE6\x96\x87\xE5\xAD\x97\xE5\x88\x97";
26
27 #define FINISHED_WAITING_MESSAGE "TEST_IME_INPUT_EVENT_FINISHED_WAITING"
28
29 } // namespace
30
31 void TestImeInputEvent::RunTests(const std::string& filter) {
yzshen1 2012/05/15 18:03:48 Keep the definitions in the same order as the decl
kinaba 2012/05/16 10:13:57 Done.
32 RUN_TEST(ImeCommit, filter);
33 RUN_TEST(ImeCancel, filter);
34 RUN_TEST(ImeUnawareCommit, filter);
35 RUN_TEST(ImeUnawareCancel, filter);
36 }
37
38 TestImeInputEvent::TestImeInputEvent(TestingInstance* instance)
39 : TestCase(instance),
40 input_event_interface_(NULL),
41 keyboard_input_event_interface_(NULL),
42 ime_input_event_interface_(NULL) {
yzshen1 2012/05/15 18:03:48 Please also init those boolean members.
kinaba 2012/05/16 10:13:57 Done.
43 }
44
45 TestImeInputEvent::~TestImeInputEvent() {
46 // Remove the special listener that only responds to a
47 // FINISHED_WAITING_MESSAGE string. See Init for where it gets added.
48 std::string js_code;
49 js_code += "var plugin = document.getElementById('plugin');"
yzshen1 2012/05/15 18:03:48 Why do we need to do a '+=' here? (and line 81)
kinaba 2012/05/16 10:13:57 Done. We don't need it.
50 "plugin.removeEventListener('message',"
51 " plugin.wait_for_messages_handler);"
52 "delete plugin.wait_for_messages_handler;";
53 instance_->EvalScript(js_code);
54 }
55
56 bool TestImeInputEvent::Init() {
57 input_event_interface_ = static_cast<const PPB_InputEvent*>(
58 pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
59 keyboard_input_event_interface_ =
60 static_cast<const PPB_KeyboardInputEvent*>(
61 pp::Module::Get()->GetBrowserInterface(
62 PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
63 ime_input_event_interface_ = static_cast<const PPB_IMEInputEvent_Dev*>(
64 pp::Module::Get()->GetBrowserInterface(
65 PPB_IME_INPUT_EVENT_DEV_INTERFACE));
66
67 bool success =
68 input_event_interface_ &&
69 keyboard_input_event_interface_ &&
70 ime_input_event_interface_ &&
71 CheckTestingInterface();
72
73 // Set up a listener for our message that signals that all input events have
74 // been received.
75 std::string js_code;
76 // Note the following code is dependent on some features of test_case.html.
77 // E.g., it is assumed that the DOM element where the plugin is embedded has
78 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
79 // us to ignore the messages that are intended for use by the testing
80 // framework itself.
81 js_code += "var plugin = document.getElementById('plugin');"
82 "var wait_for_messages_handler = function(message_event) {"
83 " if (!IsTestingMessage(message_event.data) &&"
84 " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
85 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
86 " }"
87 "};"
88 "plugin.addEventListener('message', wait_for_messages_handler);"
89 // Stash it on the plugin so we can remove it in the destructor.
90 "plugin.wait_for_messages_handler = wait_for_messages_handler;";
91 instance_->EvalScript(js_code);
92
93 return success;
94 }
95
96 pp::InputEvent TestImeInputEvent::CreateImeCompositionStartEvent() {
97 return pp::IMEInputEvent_Dev(
98 instance_,
99 PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
100 100, // time_stamp
101 pp::Var(""),
102 std::vector<uint32_t>(),
103 -1, // target_segment
104 std::make_pair(0U, 0U) // selection
105 );
106 }
107
108 pp::InputEvent TestImeInputEvent::CreateImeCompositionUpdateEvent(
109 const std::string& text,
110 const std::vector<uint32_t>& segments,
111 int32_t target_segment,
112 const std::pair<uint32_t, uint32_t>& selection) {
113 return pp::IMEInputEvent_Dev(
114 instance_,
115 PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
116 100, // time_stamp
117 text,
118 segments,
119 target_segment,
120 selection
121 );
122 }
123
124 pp::InputEvent TestImeInputEvent::CreateImeCompositionEndEvent(
125 const std::string& text) {
126 return pp::IMEInputEvent_Dev(
127 instance_,
128 PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
129 100, // time_stamp
130 pp::Var(text),
131 std::vector<uint32_t>(),
132 -1, // target_segment
133 std::make_pair(0U, 0U) // selection
134 );
135 }
136
137 pp::InputEvent TestImeInputEvent::CreateImeTextEvent(const std::string& text) {
138 return pp::IMEInputEvent_Dev(
139 instance_,
140 PP_INPUTEVENT_TYPE_IME_TEXT,
141 100, // time_stamp
142 pp::Var(text),
143 std::vector<uint32_t>(),
144 -1, // target_segment
145 std::make_pair(0U, 0U) // selection
146 );
147 }
148
149 pp::InputEvent TestImeInputEvent::CreateCharEvent(const std::string& text) {
150 return pp::KeyboardInputEvent(
151 instance_,
152 PP_INPUTEVENT_TYPE_CHAR,
153 100, // time_stamp
154 0, // modifiers
155 0, // keycode
156 pp::Var(text));
157 }
158
159 void TestImeInputEvent::GetFocusBySimulatingMouseClick() {
160 // For receiving IME events, the plugin DOM node needs to be focused.
161 // The following code is for achieving that by simulating a mouse click event.
162 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
163 PP_INPUTEVENT_CLASS_MOUSE);
164 SimulateInputEvent(pp::MouseInputEvent(
165 instance_,
166 PP_INPUTEVENT_TYPE_MOUSEDOWN,
167 100, // time_stamp
168 0, // modifiers
169 PP_INPUTEVENT_MOUSEBUTTON_LEFT,
170 pp::Point(
171 view_rect_.x() + view_rect_.width() / 2,
172 view_rect_.y() + view_rect_.height() / 2),
173 1, // click count
174 pp::Point())); // movement
175 }
176
177 // Simulates the input event and calls PostMessage to let us know when
178 // we have received all resulting events from the browser.
179 bool TestImeInputEvent::SimulateInputEvent(const pp::InputEvent& input_event) {
180 received_unexpected_event_ = false;
181 received_finish_message_ = false;
182 testing_interface_->SimulateInputEvent(instance_->pp_instance(),
183 input_event.pp_resource());
184 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
185 testing_interface_->RunMessageLoop(instance_->pp_instance());
186 return received_finish_message_ && !received_unexpected_event_;
187 }
188
189 bool TestImeInputEvent::AreEquivalentEvents(PP_Resource received,
190 PP_Resource expected) {
191 if (!input_event_interface_->IsInputEvent(received) ||
192 !input_event_interface_->IsInputEvent(expected)) {
193 return false;
194 }
195
196 // Test common fields, except modifiers and time stamp, which may be changed
197 // by the browser.
198 int32_t received_type = input_event_interface_->GetType(received);
199 int32_t expected_type = input_event_interface_->GetType(expected);
200 if (received_type != expected_type)
201 return false;
202
203 // Test event type-specific fields.
204 switch (input_event_interface_->GetType(received)) {
yzshen1 2012/05/15 18:03:48 received_type?
kinaba 2012/05/16 10:13:57 Done.
205 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
206 // COMPOSITION_START does not convey further information.
207 break;
208
209 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
210 case PP_INPUTEVENT_TYPE_IME_TEXT:
211 // For COMPOSITION_END and TEXT, GetText() has meaning.
212 return pp::Var(pp::PASS_REF,
213 ime_input_event_interface_->GetText(received)) ==
214 pp::Var(pp::PASS_REF,
215 ime_input_event_interface_->GetText(expected));
216
217 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
218 // For COMPOSITION_UPDATE, all fields must be checked.
219 {
220 uint32_t receivedSegmentNumber =
yzshen1 2012/05/15 18:03:48 name_variables_this_way (and some other places).
kinaba 2012/05/16 10:13:57 Done.
221 ime_input_event_interface_->GetSegmentNumber(received);
222 uint32_t expectedSegmentNumber =
223 ime_input_event_interface_->GetSegmentNumber(received);
yzshen1 2012/05/15 18:03:48 expected?
kinaba 2012/05/16 10:13:57 Done. Good catch.
224 if (receivedSegmentNumber != expectedSegmentNumber)
225 return false;
226
227 // The "<=" is not a bug. i-th segment is represented as the pair of
228 // i-th and (i+1)-th offsets in Pepper IME API.
229 for (uint32_t i = 0; i <= receivedSegmentNumber; ++i) {
230 if (ime_input_event_interface_->GetSegmentOffset(received, i) !=
231 ime_input_event_interface_->GetSegmentOffset(expected, i))
232 return false;
233 }
234
235 uint32_t receivedSelectionStart;
236 uint32_t receivedSelectionEnd;
237 uint32_t expectedSelectionStart;
238 uint32_t expectedSelectionEnd;
239 ime_input_event_interface_->GetSelection(
240 received, &receivedSelectionStart, &receivedSelectionEnd);
241 ime_input_event_interface_->GetSelection(
242 expected, &expectedSelectionStart, &expectedSelectionEnd);
243 if (receivedSelectionStart != expectedSelectionStart ||
244 receivedSelectionEnd != expectedSelectionEnd) {
245 return true;
246 }
247
248 return pp::Var(pp::PASS_REF,
249 ime_input_event_interface_->GetText(received)) ==
250 pp::Var(pp::PASS_REF,
251 ime_input_event_interface_->GetText(expected)) &&
252 ime_input_event_interface_->GetTargetSegment(received) ==
253 ime_input_event_interface_->GetTargetSegment(received);
yzshen1 2012/05/15 18:03:48 expected? :)
kinaba 2012/05/16 10:13:57 Done. expected is expected.
254 }
255
256 case PP_INPUTEVENT_TYPE_CHAR:
257 return
258 keyboard_input_event_interface_->GetKeyCode(received) ==
259 keyboard_input_event_interface_->GetKeyCode(expected) &&
260 pp::Var(pp::PASS_REF,
261 keyboard_input_event_interface_->GetCharacterText(received)) ==
262 pp::Var(pp::PASS_REF,
263 keyboard_input_event_interface_->GetCharacterText(expected));
264
265 default:
266 break;
267 }
268 return true;
269 }
270
271 bool TestImeInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
272 // Check whether the IME related events comes in the expected order.
273 switch (input_event.GetType()) {
274 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
275 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
276 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
277 case PP_INPUTEVENT_TYPE_IME_TEXT:
278 case PP_INPUTEVENT_TYPE_CHAR:
279 if (expected_events_.empty()) {
280 received_unexpected_event_ = true;
281 } else {
282 received_unexpected_event_ =
283 !AreEquivalentEvents(input_event.pp_resource(),
284 expected_events_.front().pp_resource());
285 expected_events_.erase(expected_events_.begin());
286 }
287 break;
288
289 default:
290 break;
291 }
292
293 // Handle all input events.
294 return true;
295 }
296
297 void TestImeInputEvent::HandleMessage(const pp::Var& message_data) {
298 if (message_data.is_string() &&
299 (message_data.AsString() == FINISHED_WAITING_MESSAGE)) {
300 testing_interface_->QuitMessageLoop(instance_->pp_instance());
301 received_finish_message_ = true;
302 }
303 }
304
305 void TestImeInputEvent::DidChangeView(const pp::View& view) {
306 view_rect_ = view.GetRect();
307 }
308
309 std::string TestImeInputEvent::TestImeCommit() {
310 GetFocusBySimulatingMouseClick();
311
312 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
313 PP_INPUTEVENT_CLASS_KEYBOARD |
314 PP_INPUTEVENT_CLASS_IME);
315
316 std::vector<uint32_t> segments;
317 segments.push_back(0U);
318 segments.push_back(3U);
319 segments.push_back(6U);
320 segments.push_back(9U);
321 pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
322 kCompositionText, segments, 1, std::make_pair(3U, 6U));
323
324 expected_events_.clear();
325 expected_events_.push_back(CreateImeCompositionStartEvent());
326 expected_events_.push_back(update_event);
327 expected_events_.push_back(CreateImeCompositionEndEvent(kCompositionText));
328 expected_events_.push_back(CreateImeTextEvent(kCompositionText));
329
330 // Simulate the case when IME successfully committed some text.
331 ASSERT_TRUE(
332 SimulateInputEvent(update_event));
333 ASSERT_TRUE(
334 SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
335
336 ASSERT_TRUE(expected_events_.empty());
337 PASS();
338 }
339
340 std::string TestImeInputEvent::TestImeCancel() {
341 GetFocusBySimulatingMouseClick();
342
343 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
344 PP_INPUTEVENT_CLASS_KEYBOARD |
345 PP_INPUTEVENT_CLASS_IME);
346
347 std::vector<uint32_t> segments;
348 segments.push_back(0U);
349 segments.push_back(3U);
350 segments.push_back(6U);
351 segments.push_back(9U);
352 pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
353 kCompositionText, segments, 1, std::make_pair(3U, 6U));
354
355 expected_events_.clear();
356 expected_events_.push_back(CreateImeCompositionStartEvent());
357 expected_events_.push_back(update_event);
358 expected_events_.push_back(CreateImeCompositionEndEvent(""));
359
360 // Simulate the case when IME canceled composition.
361 ASSERT_TRUE(
362 SimulateInputEvent(update_event));
363 ASSERT_TRUE(
364 SimulateInputEvent(CreateImeCompositionEndEvent("")));
365
366 ASSERT_TRUE(expected_events_.empty());
367 PASS();
368 }
369
370 std::string TestImeInputEvent::TestImeUnawareCommit() {
371 GetFocusBySimulatingMouseClick();
372
373 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
374 PP_INPUTEVENT_CLASS_IME);
375 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
376 PP_INPUTEVENT_CLASS_KEYBOARD);
377
378 std::vector<uint32_t> segments;
379 segments.push_back(0U);
380 segments.push_back(3U);
381 segments.push_back(6U);
382 segments.push_back(9U);
383 pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
384 kCompositionText, segments, 1, std::make_pair(3U, 6U));
385
386 expected_events_.clear();
387 expected_events_.push_back(CreateCharEvent(kCompositionChar[0]));
388 expected_events_.push_back(CreateCharEvent(kCompositionChar[1]));
389 expected_events_.push_back(CreateCharEvent(kCompositionChar[2]));
390
391 // Test for IME-unaware plugins. Commit event is translated to char events.
392 ASSERT_TRUE(SimulateInputEvent(update_event));
393 ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
394
395 ASSERT_TRUE(expected_events_.empty());
396 PASS();
397 }
398
399
400 std::string TestImeInputEvent::TestImeUnawareCancel() {
401 GetFocusBySimulatingMouseClick();
402
403 input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
404 PP_INPUTEVENT_CLASS_IME);
405 input_event_interface_->RequestInputEvents(instance_->pp_instance(),
406 PP_INPUTEVENT_CLASS_KEYBOARD);
407
408 std::vector<uint32_t> segments;
409 segments.push_back(0U);
410 segments.push_back(3U);
411 segments.push_back(6U);
412 segments.push_back(9U);
413 pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
414 kCompositionText, segments, 1, std::make_pair(3U, 6U));
415
416 expected_events_.clear();
417
418 // Test for IME-unaware plugins. Cancel won't issue any events.
419 ASSERT_TRUE(SimulateInputEvent(update_event));
420 ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent("")));
421
422 ASSERT_TRUE(expected_events_.empty());
423 PASS();
424 }
425
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698