Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / base / ime / remote_input_method_win_unittest.cc
blob686937b2ecac28690019b1c2a4f34609347964f5
1 // Copyright 2013 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 "ui/base/ime/remote_input_method_win.h"
7 #include <InputScope.h>
9 #include <vector>
11 #include "base/memory/scoped_ptr.h"
12 #include "base/scoped_observer.h"
13 #include "base/strings/string16.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/ime/composition_text.h"
16 #include "ui/base/ime/dummy_text_input_client.h"
17 #include "ui/base/ime/input_method.h"
18 #include "ui/base/ime/input_method_delegate.h"
19 #include "ui/base/ime/input_method_observer.h"
20 #include "ui/base/ime/remote_input_method_delegate_win.h"
21 #include "ui/events/event.h"
23 namespace ui {
24 namespace {
26 class MockTextInputClient : public DummyTextInputClient {
27 public:
28 MockTextInputClient()
29 : text_input_type_(TEXT_INPUT_TYPE_NONE),
30 text_input_mode_(TEXT_INPUT_MODE_DEFAULT),
31 call_count_set_composition_text_(0),
32 call_count_insert_char_(0),
33 call_count_insert_text_(0),
34 emulate_pepper_flash_(false) {
37 size_t call_count_set_composition_text() const {
38 return call_count_set_composition_text_;
40 const base::string16& inserted_text() const {
41 return inserted_text_;
43 size_t call_count_insert_char() const {
44 return call_count_insert_char_;
46 size_t call_count_insert_text() const {
47 return call_count_insert_text_;
49 void Reset() {
50 text_input_type_ = TEXT_INPUT_TYPE_NONE;
51 text_input_mode_ = TEXT_INPUT_MODE_DEFAULT;
52 call_count_set_composition_text_ = 0;
53 inserted_text_.clear();
54 call_count_insert_char_ = 0;
55 call_count_insert_text_ = 0;
56 caret_bounds_ = gfx::Rect();
57 composition_character_bounds_.clear();
58 emulate_pepper_flash_ = false;
60 void set_text_input_type(ui::TextInputType type) {
61 text_input_type_ = type;
63 void set_text_input_mode(ui::TextInputMode mode) {
64 text_input_mode_ = mode;
66 void set_caret_bounds(const gfx::Rect& caret_bounds) {
67 caret_bounds_ = caret_bounds;
69 void set_composition_character_bounds(
70 const std::vector<gfx::Rect>& composition_character_bounds) {
71 composition_character_bounds_ = composition_character_bounds;
73 void set_emulate_pepper_flash(bool enabled) {
74 emulate_pepper_flash_ = enabled;
77 private:
78 // Overriden from DummyTextInputClient.
79 void SetCompositionText(const ui::CompositionText& composition) override {
80 ++call_count_set_composition_text_;
82 void InsertChar(base::char16 ch, int flags) override {
83 inserted_text_.append(1, ch);
84 ++call_count_insert_char_;
86 void InsertText(const base::string16& text) override {
87 inserted_text_.append(text);
88 ++call_count_insert_text_;
90 ui::TextInputType GetTextInputType() const override {
91 return text_input_type_;
93 ui::TextInputMode GetTextInputMode() const override {
94 return text_input_mode_;
96 gfx::Rect GetCaretBounds() const override { return caret_bounds_; }
97 bool GetCompositionCharacterBounds(uint32 index,
98 gfx::Rect* rect) const override {
99 // Emulate the situation of crbug.com/328237.
100 if (emulate_pepper_flash_)
101 return false;
102 if (!rect || composition_character_bounds_.size() <= index)
103 return false;
104 *rect = composition_character_bounds_[index];
105 return true;
107 bool HasCompositionText() const override {
108 return !composition_character_bounds_.empty();
110 bool GetCompositionTextRange(gfx::Range* range) const override {
111 if (composition_character_bounds_.empty())
112 return false;
113 *range = gfx::Range(0, composition_character_bounds_.size());
114 return true;
117 ui::TextInputType text_input_type_;
118 ui::TextInputMode text_input_mode_;
119 gfx::Rect caret_bounds_;
120 std::vector<gfx::Rect> composition_character_bounds_;
121 base::string16 inserted_text_;
122 size_t call_count_set_composition_text_;
123 size_t call_count_insert_char_;
124 size_t call_count_insert_text_;
125 bool emulate_pepper_flash_;
126 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
129 class MockInputMethodDelegate : public internal::InputMethodDelegate {
130 public:
131 MockInputMethodDelegate() {}
133 const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
134 return fabricated_key_events_;
136 void Reset() {
137 fabricated_key_events_.clear();
140 private:
141 ui::EventDispatchDetails DispatchKeyEventPostIME(
142 ui::KeyEvent* event) override {
143 EXPECT_FALSE(event->HasNativeEvent());
144 fabricated_key_events_.push_back(event->key_code());
145 event->SetHandled();
146 return ui::EventDispatchDetails();
149 std::vector<ui::KeyboardCode> fabricated_key_events_;
150 DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
153 class MockRemoteInputMethodDelegateWin
154 : public internal::RemoteInputMethodDelegateWin {
155 public:
156 MockRemoteInputMethodDelegateWin()
157 : cancel_composition_called_(false),
158 text_input_client_updated_called_(false) {
161 bool cancel_composition_called() const {
162 return cancel_composition_called_;
164 bool text_input_client_updated_called() const {
165 return text_input_client_updated_called_;
167 const std::vector<int32>& input_scopes() const {
168 return input_scopes_;
170 const std::vector<gfx::Rect>& composition_character_bounds() const {
171 return composition_character_bounds_;
173 void Reset() {
174 cancel_composition_called_ = false;
175 text_input_client_updated_called_ = false;
176 input_scopes_.clear();
177 composition_character_bounds_.clear();
180 private:
181 void CancelComposition() override { cancel_composition_called_ = true; }
183 void OnTextInputClientUpdated(
184 const std::vector<int32>& input_scopes,
185 const std::vector<gfx::Rect>& composition_character_bounds) override {
186 text_input_client_updated_called_ = true;
187 input_scopes_ = input_scopes;
188 composition_character_bounds_ = composition_character_bounds;
191 bool cancel_composition_called_;
192 bool text_input_client_updated_called_;
193 std::vector<int32> input_scopes_;
194 std::vector<gfx::Rect> composition_character_bounds_;
195 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
198 class MockInputMethodObserver : public InputMethodObserver {
199 public:
200 MockInputMethodObserver()
201 : on_text_input_state_changed_(0),
202 on_input_method_destroyed_changed_(0) {
204 ~MockInputMethodObserver() override {}
205 void Reset() {
206 on_text_input_state_changed_ = 0;
207 on_input_method_destroyed_changed_ = 0;
209 size_t on_text_input_state_changed() const {
210 return on_text_input_state_changed_;
212 size_t on_input_method_destroyed_changed() const {
213 return on_input_method_destroyed_changed_;
216 private:
217 // Overriden from InputMethodObserver.
218 void OnTextInputTypeChanged(const TextInputClient* client) override {}
219 void OnFocus() override {}
220 void OnBlur() override {}
221 void OnCaretBoundsChanged(const TextInputClient* client) override {}
222 void OnTextInputStateChanged(const TextInputClient* client) override {
223 ++on_text_input_state_changed_;
225 void OnInputMethodDestroyed(const InputMethod* client) override {
226 ++on_input_method_destroyed_changed_;
228 void OnShowImeIfNeeded() override {}
230 size_t on_text_input_state_changed_;
231 size_t on_input_method_destroyed_changed_;
232 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
235 typedef ScopedObserver<InputMethod, InputMethodObserver>
236 InputMethodScopedObserver;
238 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
239 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
241 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
242 RemoteInputMethodPrivateWin* kNull =
243 static_cast<RemoteInputMethodPrivateWin*>(NULL);
244 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
246 MockInputMethodDelegate delegate_;
247 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
248 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
250 InputMethod* dangling_ptr = input_method.get();
251 input_method.reset(NULL);
252 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
255 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
256 MockInputMethodDelegate delegate_;
257 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
258 RemoteInputMethodPrivateWin* private_ptr =
259 RemoteInputMethodPrivateWin::Get(input_method.get());
260 ASSERT_TRUE(private_ptr != NULL);
262 private_ptr->OnInputSourceChanged(
263 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
264 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
266 private_ptr->OnInputSourceChanged(
267 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
268 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
271 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
272 MockInputMethodDelegate delegate_;
273 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
274 RemoteInputMethodPrivateWin* private_ptr =
275 RemoteInputMethodPrivateWin::Get(input_method.get());
276 ASSERT_TRUE(private_ptr != NULL);
278 // Initial value
279 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
281 // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
282 // focused text input client is NULL.
283 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
284 private_ptr->OnCandidatePopupChanged(false);
285 private_ptr->OnCandidatePopupChanged(true);
287 MockTextInputClient mock_text_input_client;
288 input_method->SetFocusedTextInputClient(&mock_text_input_client);
290 mock_text_input_client.Reset();
292 private_ptr->OnCandidatePopupChanged(true);
293 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
295 private_ptr->OnCandidatePopupChanged(false);
296 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
299 TEST(RemoteInputMethodWinTest, CancelComposition) {
300 MockInputMethodDelegate delegate_;
301 MockTextInputClient mock_text_input_client;
302 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
304 // This must not cause a crash.
305 input_method->CancelComposition(&mock_text_input_client);
307 RemoteInputMethodPrivateWin* private_ptr =
308 RemoteInputMethodPrivateWin::Get(input_method.get());
309 ASSERT_TRUE(private_ptr != NULL);
310 MockRemoteInputMethodDelegateWin mock_remote_delegate;
311 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
313 input_method->CancelComposition(&mock_text_input_client);
314 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
316 input_method->SetFocusedTextInputClient(&mock_text_input_client);
317 input_method->CancelComposition(&mock_text_input_client);
318 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
321 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
322 MockInputMethodDelegate delegate_;
323 MockTextInputClient mock_text_input_client;
324 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
326 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
327 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
328 input_method->SetFocusedTextInputClient(&mock_text_input_client);
330 RemoteInputMethodPrivateWin* private_ptr =
331 RemoteInputMethodPrivateWin::Get(input_method.get());
332 ASSERT_TRUE(private_ptr != NULL);
333 MockRemoteInputMethodDelegateWin mock_remote_delegate;
334 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
336 // Initial state must be synced.
337 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
338 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
339 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
340 mock_remote_delegate.composition_character_bounds()[0]);
341 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
342 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
344 // State must be cleared by SetFocusedTextInputClient(NULL).
345 mock_remote_delegate.Reset();
346 input_method->SetFocusedTextInputClient(NULL);
347 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
348 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
349 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
352 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
353 MockInputMethodDelegate delegate_;
354 MockTextInputClient mock_text_input_client;
355 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
357 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
358 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
359 input_method->SetFocusedTextInputClient(&mock_text_input_client);
361 RemoteInputMethodPrivateWin* private_ptr =
362 RemoteInputMethodPrivateWin::Get(input_method.get());
363 ASSERT_TRUE(private_ptr != NULL);
364 MockRemoteInputMethodDelegateWin mock_remote_delegate;
365 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
367 // Initial state must be synced.
368 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
369 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
370 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
371 mock_remote_delegate.composition_character_bounds()[0]);
372 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
373 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
375 // State must be cleared by DetachTextInputClient
376 mock_remote_delegate.Reset();
377 input_method->DetachTextInputClient(&mock_text_input_client);
378 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
379 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
380 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
383 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
384 MockInputMethodDelegate delegate_;
385 MockTextInputClient mock_text_input_client;
386 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
388 // This must not cause a crash.
389 input_method->OnCaretBoundsChanged(&mock_text_input_client);
391 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
392 input_method->SetFocusedTextInputClient(&mock_text_input_client);
394 RemoteInputMethodPrivateWin* private_ptr =
395 RemoteInputMethodPrivateWin::Get(input_method.get());
396 ASSERT_TRUE(private_ptr != NULL);
397 MockRemoteInputMethodDelegateWin mock_remote_delegate;
398 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
400 // Initial state must be synced.
401 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
402 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
403 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
404 mock_remote_delegate.composition_character_bounds()[0]);
406 // Redundant OnCaretBoundsChanged must be ignored.
407 mock_remote_delegate.Reset();
408 input_method->OnCaretBoundsChanged(&mock_text_input_client);
409 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
411 // Check OnCaretBoundsChanged is handled. (w/o composition)
412 mock_remote_delegate.Reset();
413 mock_text_input_client.Reset();
414 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
415 input_method->OnCaretBoundsChanged(&mock_text_input_client);
416 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
417 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
418 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
419 mock_remote_delegate.composition_character_bounds()[0]);
421 // Check OnCaretBoundsChanged is handled. (w/ composition)
423 mock_remote_delegate.Reset();
424 mock_text_input_client.Reset();
426 std::vector<gfx::Rect> bounds;
427 bounds.push_back(gfx::Rect(10, 20, 30, 40));
428 bounds.push_back(gfx::Rect(40, 30, 20, 10));
429 mock_text_input_client.set_composition_character_bounds(bounds);
430 input_method->OnCaretBoundsChanged(&mock_text_input_client);
431 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
432 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
436 // Test case against crbug.com/328237.
437 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
438 MockInputMethodDelegate delegate_;
439 MockTextInputClient mock_text_input_client;
440 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
441 input_method->SetFocusedTextInputClient(&mock_text_input_client);
443 RemoteInputMethodPrivateWin* private_ptr =
444 RemoteInputMethodPrivateWin::Get(input_method.get());
445 ASSERT_TRUE(private_ptr != NULL);
446 MockRemoteInputMethodDelegateWin mock_remote_delegate;
447 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
449 mock_remote_delegate.Reset();
450 mock_text_input_client.Reset();
451 mock_text_input_client.set_emulate_pepper_flash(true);
453 std::vector<gfx::Rect> caret_bounds;
454 caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
455 mock_text_input_client.set_caret_bounds(caret_bounds[0]);
457 std::vector<gfx::Rect> composition_bounds;
458 composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
459 composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
460 mock_text_input_client.set_composition_character_bounds(composition_bounds);
461 input_method->OnCaretBoundsChanged(&mock_text_input_client);
462 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
463 // The caret bounds must be used when
464 // TextInputClient::GetCompositionCharacterBounds failed.
465 EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
468 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
469 MockInputMethodDelegate delegate_;
470 MockTextInputClient mock_text_input_client;
471 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
473 // This must not cause a crash.
474 input_method->OnCaretBoundsChanged(&mock_text_input_client);
476 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
477 input_method->SetFocusedTextInputClient(&mock_text_input_client);
479 RemoteInputMethodPrivateWin* private_ptr =
480 RemoteInputMethodPrivateWin::Get(input_method.get());
481 ASSERT_TRUE(private_ptr != NULL);
482 MockRemoteInputMethodDelegateWin mock_remote_delegate;
483 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
485 // Initial state must be synced.
486 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
487 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
488 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
490 // Check TEXT_INPUT_TYPE_NONE is handled.
491 mock_remote_delegate.Reset();
492 mock_text_input_client.Reset();
493 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
494 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
495 input_method->OnTextInputTypeChanged(&mock_text_input_client);
496 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
497 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
499 // Redundant OnTextInputTypeChanged must be ignored.
500 mock_remote_delegate.Reset();
501 input_method->OnTextInputTypeChanged(&mock_text_input_client);
502 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
504 mock_remote_delegate.Reset();
505 mock_text_input_client.Reset();
506 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
507 input_method->OnCaretBoundsChanged(&mock_text_input_client);
510 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
511 // Basically RemoteInputMethodWin does not handle native keydown event.
513 MockInputMethodDelegate delegate_;
514 MockTextInputClient mock_text_input_client;
515 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
517 const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
518 ui::KeyEvent new_keydown(wm_keydown);
519 ui::KeyEvent native_keydown(new_keydown);
521 // This must not cause a crash.
522 input_method->DispatchKeyEvent(&native_keydown);
523 EXPECT_FALSE(native_keydown.handled());
524 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
525 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
526 delegate_.Reset();
527 mock_text_input_client.Reset();
529 RemoteInputMethodPrivateWin* private_ptr =
530 RemoteInputMethodPrivateWin::Get(input_method.get());
531 ASSERT_TRUE(private_ptr != NULL);
532 MockRemoteInputMethodDelegateWin mock_remote_delegate;
533 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
535 // TextInputClient is not focused yet here.
536 native_keydown = new_keydown;
537 input_method->DispatchKeyEvent(&native_keydown);
538 EXPECT_FALSE(native_keydown.handled());
539 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
540 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
541 delegate_.Reset();
542 mock_text_input_client.Reset();
544 input_method->SetFocusedTextInputClient(&mock_text_input_client);
546 // TextInputClient is now focused here.
547 native_keydown = new_keydown;
548 input_method->DispatchKeyEvent(&native_keydown);
549 EXPECT_FALSE(native_keydown.handled());
550 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
551 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
552 delegate_.Reset();
553 mock_text_input_client.Reset();
556 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
557 // RemoteInputMethodWin handles native char event if possible.
559 MockInputMethodDelegate delegate_;
560 MockTextInputClient mock_text_input_client;
561 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
563 const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
564 ui::KeyEvent new_char(wm_char);
565 ui::KeyEvent native_char(new_char);
567 // This must not cause a crash.
568 input_method->DispatchKeyEvent(&native_char);
569 EXPECT_FALSE(native_char.handled());
570 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
571 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
572 delegate_.Reset();
573 mock_text_input_client.Reset();
575 RemoteInputMethodPrivateWin* private_ptr =
576 RemoteInputMethodPrivateWin::Get(input_method.get());
577 ASSERT_TRUE(private_ptr != NULL);
578 MockRemoteInputMethodDelegateWin mock_remote_delegate;
579 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
581 // TextInputClient is not focused yet here.
582 native_char = new_char;
583 input_method->DispatchKeyEvent(&native_char);
584 EXPECT_FALSE(native_char.handled());
585 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
586 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
587 delegate_.Reset();
588 mock_text_input_client.Reset();
590 input_method->SetFocusedTextInputClient(&mock_text_input_client);
592 // TextInputClient is now focused here.
593 native_char = new_char;
594 input_method->DispatchKeyEvent(&native_char);
595 EXPECT_TRUE(native_char.handled());
596 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
597 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
598 delegate_.Reset();
599 mock_text_input_client.Reset();
602 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
603 // Fabricated non-char event will be delegated to
604 // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
605 // delegate is installed.
607 MockInputMethodDelegate delegate_;
608 MockTextInputClient mock_text_input_client;
609 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
611 ui::KeyEvent new_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
612 new_keydown.set_character(L'A');
613 ui::KeyEvent fabricated_keydown(new_keydown);
615 // This must not cause a crash.
616 input_method->DispatchKeyEvent(&fabricated_keydown);
617 EXPECT_TRUE(fabricated_keydown.handled());
618 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
619 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
620 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
621 delegate_.Reset();
622 mock_text_input_client.Reset();
624 RemoteInputMethodPrivateWin* private_ptr =
625 RemoteInputMethodPrivateWin::Get(input_method.get());
626 ASSERT_TRUE(private_ptr != NULL);
627 MockRemoteInputMethodDelegateWin mock_remote_delegate;
628 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
630 // TextInputClient is not focused yet here.
631 fabricated_keydown = new_keydown;
632 input_method->DispatchKeyEvent(&fabricated_keydown);
633 EXPECT_TRUE(fabricated_keydown.handled());
634 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
635 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
636 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
637 delegate_.Reset();
638 mock_text_input_client.Reset();
640 input_method->SetFocusedTextInputClient(&mock_text_input_client);
641 // TextInputClient is now focused here.
642 fabricated_keydown = new_keydown;
643 input_method->DispatchKeyEvent(&fabricated_keydown);
644 EXPECT_TRUE(fabricated_keydown.handled());
645 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
646 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
647 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
648 delegate_.Reset();
649 mock_text_input_client.Reset();
651 input_method->SetDelegate(NULL);
652 // RemoteInputMethodDelegateWin is no longer set here.
653 fabricated_keydown = new_keydown;
654 input_method->DispatchKeyEvent(&fabricated_keydown);
655 EXPECT_FALSE(fabricated_keydown.handled());
656 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
659 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
660 // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
661 // for fabricated character events.
663 MockInputMethodDelegate delegate_;
664 MockTextInputClient mock_text_input_client;
665 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
667 ui::KeyEvent new_char(L'A', ui::VKEY_A, ui::EF_NONE);
668 ui::KeyEvent fabricated_char(new_char);
670 // This must not cause a crash.
671 input_method->DispatchKeyEvent(&fabricated_char);
672 EXPECT_TRUE(fabricated_char.handled());
673 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
674 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
675 delegate_.Reset();
676 mock_text_input_client.Reset();
678 RemoteInputMethodPrivateWin* private_ptr =
679 RemoteInputMethodPrivateWin::Get(input_method.get());
680 ASSERT_TRUE(private_ptr != NULL);
681 MockRemoteInputMethodDelegateWin mock_remote_delegate;
682 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
684 // TextInputClient is not focused yet here.
685 fabricated_char = new_char;
686 input_method->DispatchKeyEvent(&fabricated_char);
687 EXPECT_TRUE(fabricated_char.handled());
688 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
689 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
690 delegate_.Reset();
691 mock_text_input_client.Reset();
693 input_method->SetFocusedTextInputClient(&mock_text_input_client);
695 // TextInputClient is now focused here.
696 fabricated_char = new_char;
697 input_method->DispatchKeyEvent(&fabricated_char);
698 EXPECT_TRUE(fabricated_char.handled());
699 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
700 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
701 delegate_.Reset();
702 mock_text_input_client.Reset();
705 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
706 MockInputMethodDelegate delegate_;
707 MockTextInputClient mock_text_input_client;
708 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
710 RemoteInputMethodPrivateWin* private_ptr =
711 RemoteInputMethodPrivateWin::Get(input_method.get());
712 ASSERT_TRUE(private_ptr != NULL);
713 MockRemoteInputMethodDelegateWin mock_remote_delegate;
714 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
716 CompositionText composition_text;
718 // TextInputClient is not focused yet here.
720 private_ptr->OnCompositionChanged(composition_text);
721 EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
722 delegate_.Reset();
723 mock_text_input_client.Reset();
725 input_method->SetFocusedTextInputClient(&mock_text_input_client);
727 // TextInputClient is now focused here.
729 private_ptr->OnCompositionChanged(composition_text);
730 EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
731 delegate_.Reset();
732 mock_text_input_client.Reset();
735 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
736 MockInputMethodDelegate delegate_;
737 MockTextInputClient mock_text_input_client;
738 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
740 RemoteInputMethodPrivateWin* private_ptr =
741 RemoteInputMethodPrivateWin::Get(input_method.get());
742 ASSERT_TRUE(private_ptr != NULL);
743 MockRemoteInputMethodDelegateWin mock_remote_delegate;
744 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
746 base::string16 committed_text = L"Hello";
748 // TextInputClient is not focused yet here.
750 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
751 private_ptr->OnTextCommitted(committed_text);
752 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
753 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
754 EXPECT_EQ(L"", mock_text_input_client.inserted_text());
755 delegate_.Reset();
756 mock_text_input_client.Reset();
758 input_method->SetFocusedTextInputClient(&mock_text_input_client);
760 // TextInputClient is now focused here.
762 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
763 private_ptr->OnTextCommitted(committed_text);
764 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
765 EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
766 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
767 delegate_.Reset();
768 mock_text_input_client.Reset();
770 // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
771 // should not be used.
772 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
773 private_ptr->OnTextCommitted(committed_text);
774 EXPECT_EQ(committed_text.size(),
775 mock_text_input_client.call_count_insert_char());
776 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
777 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
778 delegate_.Reset();
779 mock_text_input_client.Reset();
782 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
783 DummyTextInputClient text_input_client;
784 DummyTextInputClient text_input_client_the_other;
786 MockInputMethodObserver input_method_observer;
787 MockInputMethodDelegate delegate_;
788 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
789 InputMethodScopedObserver scoped_observer(&input_method_observer);
790 scoped_observer.Add(input_method.get());
792 input_method->SetFocusedTextInputClient(&text_input_client);
793 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
794 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
795 input_method_observer.Reset();
797 input_method->SetFocusedTextInputClient(&text_input_client);
798 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
799 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
800 input_method_observer.Reset();
802 input_method->SetFocusedTextInputClient(&text_input_client_the_other);
803 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
804 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
805 input_method_observer.Reset();
807 input_method->DetachTextInputClient(&text_input_client_the_other);
808 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
809 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
810 input_method_observer.Reset();
813 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
814 DummyTextInputClient text_input_client;
815 DummyTextInputClient text_input_client_the_other;
817 MockInputMethodObserver input_method_observer;
818 InputMethodScopedObserver scoped_observer(&input_method_observer);
820 MockInputMethodDelegate delegate_;
821 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
822 input_method->AddObserver(&input_method_observer);
824 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
825 input_method.reset();
826 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
829 } // namespace
830 } // namespace ui