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

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