Limit display of the virtual keyboard to state changes triggered from a user gesture.
[chromium-blink-merge.git] / ui / base / ime / remote_input_method_win_unittest.cc
blob568a8061297e2393ee97343ec8ef9de97041061e
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),
35 is_candidate_window_shown_called_(false),
36 is_candidate_window_hidden_called_(false) {
39 size_t call_count_set_composition_text() const {
40 return call_count_set_composition_text_;
42 const base::string16& inserted_text() const {
43 return inserted_text_;
45 size_t call_count_insert_char() const {
46 return call_count_insert_char_;
48 size_t call_count_insert_text() const {
49 return call_count_insert_text_;
51 bool is_candidate_window_shown_called() const {
52 return is_candidate_window_shown_called_;
54 bool is_candidate_window_hidden_called() const {
55 return is_candidate_window_hidden_called_;
57 void Reset() {
58 text_input_type_ = TEXT_INPUT_TYPE_NONE;
59 text_input_mode_ = TEXT_INPUT_MODE_DEFAULT;
60 call_count_set_composition_text_ = 0;
61 inserted_text_.clear();
62 call_count_insert_char_ = 0;
63 call_count_insert_text_ = 0;
64 caret_bounds_ = gfx::Rect();
65 composition_character_bounds_.clear();
66 emulate_pepper_flash_ = false;
67 is_candidate_window_shown_called_ = false;
68 is_candidate_window_hidden_called_ = false;
70 void set_text_input_type(ui::TextInputType type) {
71 text_input_type_ = type;
73 void set_text_input_mode(ui::TextInputMode mode) {
74 text_input_mode_ = mode;
76 void set_caret_bounds(const gfx::Rect& caret_bounds) {
77 caret_bounds_ = caret_bounds;
79 void set_composition_character_bounds(
80 const std::vector<gfx::Rect>& composition_character_bounds) {
81 composition_character_bounds_ = composition_character_bounds;
83 void set_emulate_pepper_flash(bool enabled) {
84 emulate_pepper_flash_ = enabled;
87 private:
88 // Overriden from DummyTextInputClient.
89 virtual void SetCompositionText(
90 const ui::CompositionText& composition) OVERRIDE {
91 ++call_count_set_composition_text_;
93 virtual void InsertChar(base::char16 ch, int flags) OVERRIDE {
94 inserted_text_.append(1, ch);
95 ++call_count_insert_char_;
97 virtual void InsertText(const base::string16& text) OVERRIDE {
98 inserted_text_.append(text);
99 ++call_count_insert_text_;
101 virtual ui::TextInputType GetTextInputType() const OVERRIDE {
102 return text_input_type_;
104 virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
105 return text_input_mode_;
107 virtual gfx::Rect GetCaretBounds() const {
108 return caret_bounds_;
110 virtual bool GetCompositionCharacterBounds(uint32 index,
111 gfx::Rect* rect) const OVERRIDE {
112 // Emulate the situation of crbug.com/328237.
113 if (emulate_pepper_flash_)
114 return false;
115 if (!rect || composition_character_bounds_.size() <= index)
116 return false;
117 *rect = composition_character_bounds_[index];
118 return true;
120 virtual bool HasCompositionText() const OVERRIDE {
121 return !composition_character_bounds_.empty();
123 virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE {
124 if (composition_character_bounds_.empty())
125 return false;
126 *range = gfx::Range(0, composition_character_bounds_.size());
127 return true;
129 virtual void OnCandidateWindowShown() OVERRIDE {
130 is_candidate_window_shown_called_ = true;
132 virtual void OnCandidateWindowHidden() OVERRIDE {
133 is_candidate_window_hidden_called_ = true;
136 ui::TextInputType text_input_type_;
137 ui::TextInputMode text_input_mode_;
138 gfx::Rect caret_bounds_;
139 std::vector<gfx::Rect> composition_character_bounds_;
140 base::string16 inserted_text_;
141 size_t call_count_set_composition_text_;
142 size_t call_count_insert_char_;
143 size_t call_count_insert_text_;
144 bool emulate_pepper_flash_;
145 bool is_candidate_window_shown_called_;
146 bool is_candidate_window_hidden_called_;
147 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
150 class MockInputMethodDelegate : public internal::InputMethodDelegate {
151 public:
152 MockInputMethodDelegate() {}
154 const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
155 return fabricated_key_events_;
157 void Reset() {
158 fabricated_key_events_.clear();
161 private:
162 virtual bool DispatchKeyEventPostIME(
163 const base::NativeEvent& native_key_event) OVERRIDE {
164 EXPECT_TRUE(false) << "Not reach here";
165 return true;
167 virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type,
168 ui::KeyboardCode key_code,
169 int flags) OVERRIDE {
170 fabricated_key_events_.push_back(key_code);
171 return true;
174 std::vector<ui::KeyboardCode> fabricated_key_events_;
175 DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
178 class MockRemoteInputMethodDelegateWin
179 : public internal::RemoteInputMethodDelegateWin {
180 public:
181 MockRemoteInputMethodDelegateWin()
182 : cancel_composition_called_(false),
183 text_input_client_updated_called_(false) {
186 bool cancel_composition_called() const {
187 return cancel_composition_called_;
189 bool text_input_client_updated_called() const {
190 return text_input_client_updated_called_;
192 const std::vector<int32>& input_scopes() const {
193 return input_scopes_;
195 const std::vector<gfx::Rect>& composition_character_bounds() const {
196 return composition_character_bounds_;
198 void Reset() {
199 cancel_composition_called_ = false;
200 text_input_client_updated_called_ = false;
201 input_scopes_.clear();
202 composition_character_bounds_.clear();
205 private:
206 virtual void CancelComposition() OVERRIDE {
207 cancel_composition_called_ = true;
210 virtual void OnTextInputClientUpdated(
211 const std::vector<int32>& input_scopes,
212 const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE {
213 text_input_client_updated_called_ = true;
214 input_scopes_ = input_scopes;
215 composition_character_bounds_ = composition_character_bounds;
218 bool cancel_composition_called_;
219 bool text_input_client_updated_called_;
220 std::vector<int32> input_scopes_;
221 std::vector<gfx::Rect> composition_character_bounds_;
222 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
225 class MockInputMethodObserver : public InputMethodObserver {
226 public:
227 MockInputMethodObserver()
228 : on_text_input_state_changed_(0),
229 on_input_method_destroyed_changed_(0) {
231 virtual ~MockInputMethodObserver() {
233 void Reset() {
234 on_text_input_state_changed_ = 0;
235 on_input_method_destroyed_changed_ = 0;
237 size_t on_text_input_state_changed() const {
238 return on_text_input_state_changed_;
240 size_t on_input_method_destroyed_changed() const {
241 return on_input_method_destroyed_changed_;
244 private:
245 // Overriden from InputMethodObserver.
246 virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE {
248 virtual void OnFocus() OVERRIDE {
250 virtual void OnBlur() OVERRIDE {
252 virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE {
254 virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE {
255 ++on_text_input_state_changed_;
257 virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE {
258 ++on_input_method_destroyed_changed_;
260 virtual void OnShowImeIfNeeded() {
263 size_t on_text_input_state_changed_;
264 size_t on_input_method_destroyed_changed_;
265 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
268 typedef ScopedObserver<InputMethod, InputMethodObserver>
269 InputMethodScopedObserver;
271 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
272 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
274 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
275 RemoteInputMethodPrivateWin* kNull =
276 static_cast<RemoteInputMethodPrivateWin*>(NULL);
277 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
279 MockInputMethodDelegate delegate_;
280 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
281 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
283 InputMethod* dangling_ptr = input_method.get();
284 input_method.reset(NULL);
285 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
288 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
289 MockInputMethodDelegate delegate_;
290 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
291 RemoteInputMethodPrivateWin* private_ptr =
292 RemoteInputMethodPrivateWin::Get(input_method.get());
293 ASSERT_TRUE(private_ptr != NULL);
295 private_ptr->OnInputSourceChanged(
296 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
297 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
299 private_ptr->OnInputSourceChanged(
300 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
301 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
304 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
305 MockInputMethodDelegate delegate_;
306 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
307 RemoteInputMethodPrivateWin* private_ptr =
308 RemoteInputMethodPrivateWin::Get(input_method.get());
309 ASSERT_TRUE(private_ptr != NULL);
311 // Initial value
312 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
314 // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
315 // focused text input client is NULL.
316 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
317 private_ptr->OnCandidatePopupChanged(false);
318 private_ptr->OnCandidatePopupChanged(true);
320 MockTextInputClient mock_text_input_client;
321 input_method->SetFocusedTextInputClient(&mock_text_input_client);
323 ASSERT_FALSE(mock_text_input_client.is_candidate_window_shown_called());
324 ASSERT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
325 mock_text_input_client.Reset();
327 private_ptr->OnCandidatePopupChanged(true);
328 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
329 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
330 EXPECT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
332 private_ptr->OnCandidatePopupChanged(false);
333 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
334 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
335 EXPECT_TRUE(mock_text_input_client.is_candidate_window_hidden_called());
338 TEST(RemoteInputMethodWinTest, CancelComposition) {
339 MockInputMethodDelegate delegate_;
340 MockTextInputClient mock_text_input_client;
341 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
343 // This must not cause a crash.
344 input_method->CancelComposition(&mock_text_input_client);
346 RemoteInputMethodPrivateWin* private_ptr =
347 RemoteInputMethodPrivateWin::Get(input_method.get());
348 ASSERT_TRUE(private_ptr != NULL);
349 MockRemoteInputMethodDelegateWin mock_remote_delegate;
350 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
352 input_method->CancelComposition(&mock_text_input_client);
353 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
355 input_method->SetFocusedTextInputClient(&mock_text_input_client);
356 input_method->CancelComposition(&mock_text_input_client);
357 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
360 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
361 MockInputMethodDelegate delegate_;
362 MockTextInputClient mock_text_input_client;
363 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
365 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
366 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
367 input_method->SetFocusedTextInputClient(&mock_text_input_client);
369 RemoteInputMethodPrivateWin* private_ptr =
370 RemoteInputMethodPrivateWin::Get(input_method.get());
371 ASSERT_TRUE(private_ptr != NULL);
372 MockRemoteInputMethodDelegateWin mock_remote_delegate;
373 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
375 // Initial state must be synced.
376 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
377 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
378 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
379 mock_remote_delegate.composition_character_bounds()[0]);
380 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
381 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
383 // State must be cleared by SetFocusedTextInputClient(NULL).
384 mock_remote_delegate.Reset();
385 input_method->SetFocusedTextInputClient(NULL);
386 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
387 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
388 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
391 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
392 MockInputMethodDelegate delegate_;
393 MockTextInputClient mock_text_input_client;
394 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
396 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
397 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
398 input_method->SetFocusedTextInputClient(&mock_text_input_client);
400 RemoteInputMethodPrivateWin* private_ptr =
401 RemoteInputMethodPrivateWin::Get(input_method.get());
402 ASSERT_TRUE(private_ptr != NULL);
403 MockRemoteInputMethodDelegateWin mock_remote_delegate;
404 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
406 // Initial state must be synced.
407 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
408 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
409 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
410 mock_remote_delegate.composition_character_bounds()[0]);
411 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
412 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
414 // State must be cleared by DetachTextInputClient
415 mock_remote_delegate.Reset();
416 input_method->DetachTextInputClient(&mock_text_input_client);
417 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
418 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
419 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
422 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
423 MockInputMethodDelegate delegate_;
424 MockTextInputClient mock_text_input_client;
425 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
427 // This must not cause a crash.
428 input_method->OnCaretBoundsChanged(&mock_text_input_client);
430 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
431 input_method->SetFocusedTextInputClient(&mock_text_input_client);
433 RemoteInputMethodPrivateWin* private_ptr =
434 RemoteInputMethodPrivateWin::Get(input_method.get());
435 ASSERT_TRUE(private_ptr != NULL);
436 MockRemoteInputMethodDelegateWin mock_remote_delegate;
437 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
439 // Initial state must be synced.
440 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
441 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
442 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
443 mock_remote_delegate.composition_character_bounds()[0]);
445 // Redundant OnCaretBoundsChanged must be ignored.
446 mock_remote_delegate.Reset();
447 input_method->OnCaretBoundsChanged(&mock_text_input_client);
448 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
450 // Check OnCaretBoundsChanged is handled. (w/o composition)
451 mock_remote_delegate.Reset();
452 mock_text_input_client.Reset();
453 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
454 input_method->OnCaretBoundsChanged(&mock_text_input_client);
455 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
456 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
457 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
458 mock_remote_delegate.composition_character_bounds()[0]);
460 // Check OnCaretBoundsChanged is handled. (w/ composition)
462 mock_remote_delegate.Reset();
463 mock_text_input_client.Reset();
465 std::vector<gfx::Rect> bounds;
466 bounds.push_back(gfx::Rect(10, 20, 30, 40));
467 bounds.push_back(gfx::Rect(40, 30, 20, 10));
468 mock_text_input_client.set_composition_character_bounds(bounds);
469 input_method->OnCaretBoundsChanged(&mock_text_input_client);
470 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
471 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
475 // Test case against crbug.com/328237.
476 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
477 MockInputMethodDelegate delegate_;
478 MockTextInputClient mock_text_input_client;
479 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
480 input_method->SetFocusedTextInputClient(&mock_text_input_client);
482 RemoteInputMethodPrivateWin* private_ptr =
483 RemoteInputMethodPrivateWin::Get(input_method.get());
484 ASSERT_TRUE(private_ptr != NULL);
485 MockRemoteInputMethodDelegateWin mock_remote_delegate;
486 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
488 mock_remote_delegate.Reset();
489 mock_text_input_client.Reset();
490 mock_text_input_client.set_emulate_pepper_flash(true);
492 std::vector<gfx::Rect> caret_bounds;
493 caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
494 mock_text_input_client.set_caret_bounds(caret_bounds[0]);
496 std::vector<gfx::Rect> composition_bounds;
497 composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
498 composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
499 mock_text_input_client.set_composition_character_bounds(composition_bounds);
500 input_method->OnCaretBoundsChanged(&mock_text_input_client);
501 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
502 // The caret bounds must be used when
503 // TextInputClient::GetCompositionCharacterBounds failed.
504 EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
507 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
508 MockInputMethodDelegate delegate_;
509 MockTextInputClient mock_text_input_client;
510 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
512 // This must not cause a crash.
513 input_method->OnCaretBoundsChanged(&mock_text_input_client);
515 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
516 input_method->SetFocusedTextInputClient(&mock_text_input_client);
518 RemoteInputMethodPrivateWin* private_ptr =
519 RemoteInputMethodPrivateWin::Get(input_method.get());
520 ASSERT_TRUE(private_ptr != NULL);
521 MockRemoteInputMethodDelegateWin mock_remote_delegate;
522 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
524 // Initial state must be synced.
525 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
526 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
527 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
529 // Check TEXT_INPUT_TYPE_NONE is handled.
530 mock_remote_delegate.Reset();
531 mock_text_input_client.Reset();
532 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
533 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
534 input_method->OnTextInputTypeChanged(&mock_text_input_client);
535 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
536 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
538 // Redundant OnTextInputTypeChanged must be ignored.
539 mock_remote_delegate.Reset();
540 input_method->OnTextInputTypeChanged(&mock_text_input_client);
541 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
543 mock_remote_delegate.Reset();
544 mock_text_input_client.Reset();
545 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
546 input_method->OnCaretBoundsChanged(&mock_text_input_client);
549 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
550 // Basically RemoteInputMethodWin does not handle native keydown event.
552 MockInputMethodDelegate delegate_;
553 MockTextInputClient mock_text_input_client;
554 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
556 const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
557 ui::KeyEvent native_keydown(wm_keydown, false);
559 // This must not cause a crash.
560 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
561 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
562 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
563 delegate_.Reset();
564 mock_text_input_client.Reset();
566 RemoteInputMethodPrivateWin* private_ptr =
567 RemoteInputMethodPrivateWin::Get(input_method.get());
568 ASSERT_TRUE(private_ptr != NULL);
569 MockRemoteInputMethodDelegateWin mock_remote_delegate;
570 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
572 // TextInputClient is not focused yet here.
574 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
575 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
576 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
577 delegate_.Reset();
578 mock_text_input_client.Reset();
580 input_method->SetFocusedTextInputClient(&mock_text_input_client);
582 // TextInputClient is now focused here.
584 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
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();
591 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
592 // RemoteInputMethodWin handles native char event if possible.
594 MockInputMethodDelegate delegate_;
595 MockTextInputClient mock_text_input_client;
596 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
598 const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
599 ui::KeyEvent native_char(wm_char, true);
601 // This must not cause a crash.
602 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
603 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
604 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
605 delegate_.Reset();
606 mock_text_input_client.Reset();
608 RemoteInputMethodPrivateWin* private_ptr =
609 RemoteInputMethodPrivateWin::Get(input_method.get());
610 ASSERT_TRUE(private_ptr != NULL);
611 MockRemoteInputMethodDelegateWin mock_remote_delegate;
612 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
614 // TextInputClient is not focused yet here.
616 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
617 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
618 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
619 delegate_.Reset();
620 mock_text_input_client.Reset();
622 input_method->SetFocusedTextInputClient(&mock_text_input_client);
624 // TextInputClient is now focused here.
626 EXPECT_TRUE(input_method->DispatchKeyEvent(native_char));
627 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
628 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
629 delegate_.Reset();
630 mock_text_input_client.Reset();
633 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
634 // Fabricated non-char event will be delegated to
635 // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
636 // delegate is installed.
638 MockInputMethodDelegate delegate_;
639 MockTextInputClient mock_text_input_client;
640 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
642 ui::KeyEvent fabricated_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
643 fabricated_keydown.set_character(L'A');
645 // This must not cause a crash.
646 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
647 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
648 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
649 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
650 delegate_.Reset();
651 mock_text_input_client.Reset();
653 RemoteInputMethodPrivateWin* private_ptr =
654 RemoteInputMethodPrivateWin::Get(input_method.get());
655 ASSERT_TRUE(private_ptr != NULL);
656 MockRemoteInputMethodDelegateWin mock_remote_delegate;
657 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
659 // TextInputClient is not focused yet here.
661 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
662 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
663 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
664 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
665 delegate_.Reset();
666 mock_text_input_client.Reset();
668 input_method->SetFocusedTextInputClient(&mock_text_input_client);
669 // TextInputClient is now focused here.
671 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
672 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
673 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
674 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
675 delegate_.Reset();
676 mock_text_input_client.Reset();
678 input_method->SetDelegate(NULL);
679 // RemoteInputMethodDelegateWin is no longer set here.
681 EXPECT_FALSE(input_method->DispatchKeyEvent(fabricated_keydown));
682 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
685 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
686 // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
687 // for fabricated character events.
689 MockInputMethodDelegate delegate_;
690 MockTextInputClient mock_text_input_client;
691 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
693 ui::KeyEvent fabricated_char(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
694 fabricated_char.set_character(L'A');
696 // This must not cause a crash.
697 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
698 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
699 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
700 delegate_.Reset();
701 mock_text_input_client.Reset();
703 RemoteInputMethodPrivateWin* private_ptr =
704 RemoteInputMethodPrivateWin::Get(input_method.get());
705 ASSERT_TRUE(private_ptr != NULL);
706 MockRemoteInputMethodDelegateWin mock_remote_delegate;
707 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
709 // TextInputClient is not focused yet here.
711 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
712 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
713 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
714 delegate_.Reset();
715 mock_text_input_client.Reset();
717 input_method->SetFocusedTextInputClient(&mock_text_input_client);
719 // TextInputClient is now focused here.
721 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
722 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
723 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
724 delegate_.Reset();
725 mock_text_input_client.Reset();
728 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
729 MockInputMethodDelegate delegate_;
730 MockTextInputClient mock_text_input_client;
731 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
733 RemoteInputMethodPrivateWin* private_ptr =
734 RemoteInputMethodPrivateWin::Get(input_method.get());
735 ASSERT_TRUE(private_ptr != NULL);
736 MockRemoteInputMethodDelegateWin mock_remote_delegate;
737 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
739 CompositionText composition_text;
741 // TextInputClient is not focused yet here.
743 private_ptr->OnCompositionChanged(composition_text);
744 EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
745 delegate_.Reset();
746 mock_text_input_client.Reset();
748 input_method->SetFocusedTextInputClient(&mock_text_input_client);
750 // TextInputClient is now focused here.
752 private_ptr->OnCompositionChanged(composition_text);
753 EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
754 delegate_.Reset();
755 mock_text_input_client.Reset();
758 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
759 MockInputMethodDelegate delegate_;
760 MockTextInputClient mock_text_input_client;
761 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
763 RemoteInputMethodPrivateWin* private_ptr =
764 RemoteInputMethodPrivateWin::Get(input_method.get());
765 ASSERT_TRUE(private_ptr != NULL);
766 MockRemoteInputMethodDelegateWin mock_remote_delegate;
767 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
769 base::string16 committed_text = L"Hello";
771 // TextInputClient is not focused yet here.
773 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
774 private_ptr->OnTextCommitted(committed_text);
775 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
776 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
777 EXPECT_EQ(L"", mock_text_input_client.inserted_text());
778 delegate_.Reset();
779 mock_text_input_client.Reset();
781 input_method->SetFocusedTextInputClient(&mock_text_input_client);
783 // TextInputClient is now focused here.
785 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
786 private_ptr->OnTextCommitted(committed_text);
787 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
788 EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
789 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
790 delegate_.Reset();
791 mock_text_input_client.Reset();
793 // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
794 // should not be used.
795 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
796 private_ptr->OnTextCommitted(committed_text);
797 EXPECT_EQ(committed_text.size(),
798 mock_text_input_client.call_count_insert_char());
799 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
800 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
801 delegate_.Reset();
802 mock_text_input_client.Reset();
805 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
806 DummyTextInputClient text_input_client;
807 DummyTextInputClient text_input_client_the_other;
809 MockInputMethodObserver input_method_observer;
810 MockInputMethodDelegate delegate_;
811 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
812 InputMethodScopedObserver scoped_observer(&input_method_observer);
813 scoped_observer.Add(input_method.get());
815 input_method->SetFocusedTextInputClient(&text_input_client);
816 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
817 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
818 input_method_observer.Reset();
820 input_method->SetFocusedTextInputClient(&text_input_client);
821 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
822 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
823 input_method_observer.Reset();
825 input_method->SetFocusedTextInputClient(&text_input_client_the_other);
826 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
827 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
828 input_method_observer.Reset();
830 input_method->DetachTextInputClient(&text_input_client_the_other);
831 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
832 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
833 input_method_observer.Reset();
836 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
837 DummyTextInputClient text_input_client;
838 DummyTextInputClient text_input_client_the_other;
840 MockInputMethodObserver input_method_observer;
841 InputMethodScopedObserver scoped_observer(&input_method_observer);
843 MockInputMethodDelegate delegate_;
844 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
845 input_method->AddObserver(&input_method_observer);
847 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
848 input_method.reset();
849 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
852 } // namespace
853 } // namespace ui