Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / ui / base / ime / remote_input_method_win_unittest.cc
blob3fa8be0cf32d813e6695fc000436041ee6e064b7
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(const ui::KeyEvent& event) OVERRIDE {
163 EXPECT_FALSE(event.HasNativeEvent());
164 fabricated_key_events_.push_back(event.key_code());
165 return true;
168 std::vector<ui::KeyboardCode> fabricated_key_events_;
169 DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
172 class MockRemoteInputMethodDelegateWin
173 : public internal::RemoteInputMethodDelegateWin {
174 public:
175 MockRemoteInputMethodDelegateWin()
176 : cancel_composition_called_(false),
177 text_input_client_updated_called_(false) {
180 bool cancel_composition_called() const {
181 return cancel_composition_called_;
183 bool text_input_client_updated_called() const {
184 return text_input_client_updated_called_;
186 const std::vector<int32>& input_scopes() const {
187 return input_scopes_;
189 const std::vector<gfx::Rect>& composition_character_bounds() const {
190 return composition_character_bounds_;
192 void Reset() {
193 cancel_composition_called_ = false;
194 text_input_client_updated_called_ = false;
195 input_scopes_.clear();
196 composition_character_bounds_.clear();
199 private:
200 virtual void CancelComposition() OVERRIDE {
201 cancel_composition_called_ = true;
204 virtual void OnTextInputClientUpdated(
205 const std::vector<int32>& input_scopes,
206 const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE {
207 text_input_client_updated_called_ = true;
208 input_scopes_ = input_scopes;
209 composition_character_bounds_ = composition_character_bounds;
212 bool cancel_composition_called_;
213 bool text_input_client_updated_called_;
214 std::vector<int32> input_scopes_;
215 std::vector<gfx::Rect> composition_character_bounds_;
216 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
219 class MockInputMethodObserver : public InputMethodObserver {
220 public:
221 MockInputMethodObserver()
222 : on_text_input_state_changed_(0),
223 on_input_method_destroyed_changed_(0) {
225 virtual ~MockInputMethodObserver() {
227 void Reset() {
228 on_text_input_state_changed_ = 0;
229 on_input_method_destroyed_changed_ = 0;
231 size_t on_text_input_state_changed() const {
232 return on_text_input_state_changed_;
234 size_t on_input_method_destroyed_changed() const {
235 return on_input_method_destroyed_changed_;
238 private:
239 // Overriden from InputMethodObserver.
240 virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE {
242 virtual void OnFocus() OVERRIDE {
244 virtual void OnBlur() OVERRIDE {
246 virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE {
248 virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE {
249 ++on_text_input_state_changed_;
251 virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE {
252 ++on_input_method_destroyed_changed_;
254 virtual void OnShowImeIfNeeded() {
257 size_t on_text_input_state_changed_;
258 size_t on_input_method_destroyed_changed_;
259 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
262 typedef ScopedObserver<InputMethod, InputMethodObserver>
263 InputMethodScopedObserver;
265 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
266 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
268 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
269 RemoteInputMethodPrivateWin* kNull =
270 static_cast<RemoteInputMethodPrivateWin*>(NULL);
271 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
273 MockInputMethodDelegate delegate_;
274 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
275 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
277 InputMethod* dangling_ptr = input_method.get();
278 input_method.reset(NULL);
279 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
282 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
283 MockInputMethodDelegate delegate_;
284 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
285 RemoteInputMethodPrivateWin* private_ptr =
286 RemoteInputMethodPrivateWin::Get(input_method.get());
287 ASSERT_TRUE(private_ptr != NULL);
289 private_ptr->OnInputSourceChanged(
290 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
291 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
293 private_ptr->OnInputSourceChanged(
294 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
295 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
298 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
299 MockInputMethodDelegate delegate_;
300 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
301 RemoteInputMethodPrivateWin* private_ptr =
302 RemoteInputMethodPrivateWin::Get(input_method.get());
303 ASSERT_TRUE(private_ptr != NULL);
305 // Initial value
306 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
308 // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
309 // focused text input client is NULL.
310 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
311 private_ptr->OnCandidatePopupChanged(false);
312 private_ptr->OnCandidatePopupChanged(true);
314 MockTextInputClient mock_text_input_client;
315 input_method->SetFocusedTextInputClient(&mock_text_input_client);
317 ASSERT_FALSE(mock_text_input_client.is_candidate_window_shown_called());
318 ASSERT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
319 mock_text_input_client.Reset();
321 private_ptr->OnCandidatePopupChanged(true);
322 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
323 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
324 EXPECT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
326 private_ptr->OnCandidatePopupChanged(false);
327 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
328 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
329 EXPECT_TRUE(mock_text_input_client.is_candidate_window_hidden_called());
332 TEST(RemoteInputMethodWinTest, CancelComposition) {
333 MockInputMethodDelegate delegate_;
334 MockTextInputClient mock_text_input_client;
335 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
337 // This must not cause a crash.
338 input_method->CancelComposition(&mock_text_input_client);
340 RemoteInputMethodPrivateWin* private_ptr =
341 RemoteInputMethodPrivateWin::Get(input_method.get());
342 ASSERT_TRUE(private_ptr != NULL);
343 MockRemoteInputMethodDelegateWin mock_remote_delegate;
344 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
346 input_method->CancelComposition(&mock_text_input_client);
347 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
349 input_method->SetFocusedTextInputClient(&mock_text_input_client);
350 input_method->CancelComposition(&mock_text_input_client);
351 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
354 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
355 MockInputMethodDelegate delegate_;
356 MockTextInputClient mock_text_input_client;
357 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
359 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
360 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
361 input_method->SetFocusedTextInputClient(&mock_text_input_client);
363 RemoteInputMethodPrivateWin* private_ptr =
364 RemoteInputMethodPrivateWin::Get(input_method.get());
365 ASSERT_TRUE(private_ptr != NULL);
366 MockRemoteInputMethodDelegateWin mock_remote_delegate;
367 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
369 // Initial state must be synced.
370 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
371 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
372 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
373 mock_remote_delegate.composition_character_bounds()[0]);
374 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
375 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
377 // State must be cleared by SetFocusedTextInputClient(NULL).
378 mock_remote_delegate.Reset();
379 input_method->SetFocusedTextInputClient(NULL);
380 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
381 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
382 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
385 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
386 MockInputMethodDelegate delegate_;
387 MockTextInputClient mock_text_input_client;
388 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
390 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
391 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
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]);
405 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
406 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
408 // State must be cleared by DetachTextInputClient
409 mock_remote_delegate.Reset();
410 input_method->DetachTextInputClient(&mock_text_input_client);
411 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
412 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
413 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
416 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
417 MockInputMethodDelegate delegate_;
418 MockTextInputClient mock_text_input_client;
419 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
421 // This must not cause a crash.
422 input_method->OnCaretBoundsChanged(&mock_text_input_client);
424 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
425 input_method->SetFocusedTextInputClient(&mock_text_input_client);
427 RemoteInputMethodPrivateWin* private_ptr =
428 RemoteInputMethodPrivateWin::Get(input_method.get());
429 ASSERT_TRUE(private_ptr != NULL);
430 MockRemoteInputMethodDelegateWin mock_remote_delegate;
431 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
433 // Initial state must be synced.
434 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
435 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
436 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
437 mock_remote_delegate.composition_character_bounds()[0]);
439 // Redundant OnCaretBoundsChanged must be ignored.
440 mock_remote_delegate.Reset();
441 input_method->OnCaretBoundsChanged(&mock_text_input_client);
442 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
444 // Check OnCaretBoundsChanged is handled. (w/o composition)
445 mock_remote_delegate.Reset();
446 mock_text_input_client.Reset();
447 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
448 input_method->OnCaretBoundsChanged(&mock_text_input_client);
449 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
450 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
451 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
452 mock_remote_delegate.composition_character_bounds()[0]);
454 // Check OnCaretBoundsChanged is handled. (w/ composition)
456 mock_remote_delegate.Reset();
457 mock_text_input_client.Reset();
459 std::vector<gfx::Rect> bounds;
460 bounds.push_back(gfx::Rect(10, 20, 30, 40));
461 bounds.push_back(gfx::Rect(40, 30, 20, 10));
462 mock_text_input_client.set_composition_character_bounds(bounds);
463 input_method->OnCaretBoundsChanged(&mock_text_input_client);
464 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
465 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
469 // Test case against crbug.com/328237.
470 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
471 MockInputMethodDelegate delegate_;
472 MockTextInputClient mock_text_input_client;
473 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
474 input_method->SetFocusedTextInputClient(&mock_text_input_client);
476 RemoteInputMethodPrivateWin* private_ptr =
477 RemoteInputMethodPrivateWin::Get(input_method.get());
478 ASSERT_TRUE(private_ptr != NULL);
479 MockRemoteInputMethodDelegateWin mock_remote_delegate;
480 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
482 mock_remote_delegate.Reset();
483 mock_text_input_client.Reset();
484 mock_text_input_client.set_emulate_pepper_flash(true);
486 std::vector<gfx::Rect> caret_bounds;
487 caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
488 mock_text_input_client.set_caret_bounds(caret_bounds[0]);
490 std::vector<gfx::Rect> composition_bounds;
491 composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
492 composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
493 mock_text_input_client.set_composition_character_bounds(composition_bounds);
494 input_method->OnCaretBoundsChanged(&mock_text_input_client);
495 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
496 // The caret bounds must be used when
497 // TextInputClient::GetCompositionCharacterBounds failed.
498 EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
501 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
502 MockInputMethodDelegate delegate_;
503 MockTextInputClient mock_text_input_client;
504 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
506 // This must not cause a crash.
507 input_method->OnCaretBoundsChanged(&mock_text_input_client);
509 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
510 input_method->SetFocusedTextInputClient(&mock_text_input_client);
512 RemoteInputMethodPrivateWin* private_ptr =
513 RemoteInputMethodPrivateWin::Get(input_method.get());
514 ASSERT_TRUE(private_ptr != NULL);
515 MockRemoteInputMethodDelegateWin mock_remote_delegate;
516 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
518 // Initial state must be synced.
519 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
520 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
521 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
523 // Check TEXT_INPUT_TYPE_NONE is handled.
524 mock_remote_delegate.Reset();
525 mock_text_input_client.Reset();
526 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
527 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
528 input_method->OnTextInputTypeChanged(&mock_text_input_client);
529 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
530 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
532 // Redundant OnTextInputTypeChanged must be ignored.
533 mock_remote_delegate.Reset();
534 input_method->OnTextInputTypeChanged(&mock_text_input_client);
535 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
537 mock_remote_delegate.Reset();
538 mock_text_input_client.Reset();
539 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
540 input_method->OnCaretBoundsChanged(&mock_text_input_client);
543 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
544 // Basically RemoteInputMethodWin does not handle native keydown event.
546 MockInputMethodDelegate delegate_;
547 MockTextInputClient mock_text_input_client;
548 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
550 const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
551 ui::KeyEvent native_keydown(wm_keydown, false);
553 // This must not cause a crash.
554 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
555 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
556 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
557 delegate_.Reset();
558 mock_text_input_client.Reset();
560 RemoteInputMethodPrivateWin* private_ptr =
561 RemoteInputMethodPrivateWin::Get(input_method.get());
562 ASSERT_TRUE(private_ptr != NULL);
563 MockRemoteInputMethodDelegateWin mock_remote_delegate;
564 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
566 // TextInputClient is not focused yet here.
568 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
569 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
570 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
571 delegate_.Reset();
572 mock_text_input_client.Reset();
574 input_method->SetFocusedTextInputClient(&mock_text_input_client);
576 // TextInputClient is now focused here.
578 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
579 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
580 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
581 delegate_.Reset();
582 mock_text_input_client.Reset();
585 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
586 // RemoteInputMethodWin handles native char event if possible.
588 MockInputMethodDelegate delegate_;
589 MockTextInputClient mock_text_input_client;
590 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
592 const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
593 ui::KeyEvent native_char(wm_char, true);
595 // This must not cause a crash.
596 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
597 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
598 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
599 delegate_.Reset();
600 mock_text_input_client.Reset();
602 RemoteInputMethodPrivateWin* private_ptr =
603 RemoteInputMethodPrivateWin::Get(input_method.get());
604 ASSERT_TRUE(private_ptr != NULL);
605 MockRemoteInputMethodDelegateWin mock_remote_delegate;
606 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
608 // TextInputClient is not focused yet here.
610 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
611 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
612 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
613 delegate_.Reset();
614 mock_text_input_client.Reset();
616 input_method->SetFocusedTextInputClient(&mock_text_input_client);
618 // TextInputClient is now focused here.
620 EXPECT_TRUE(input_method->DispatchKeyEvent(native_char));
621 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
622 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
623 delegate_.Reset();
624 mock_text_input_client.Reset();
627 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
628 // Fabricated non-char event will be delegated to
629 // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
630 // delegate is installed.
632 MockInputMethodDelegate delegate_;
633 MockTextInputClient mock_text_input_client;
634 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
636 ui::KeyEvent fabricated_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
637 fabricated_keydown.set_character(L'A');
639 // This must not cause a crash.
640 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
641 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
642 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
643 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
644 delegate_.Reset();
645 mock_text_input_client.Reset();
647 RemoteInputMethodPrivateWin* private_ptr =
648 RemoteInputMethodPrivateWin::Get(input_method.get());
649 ASSERT_TRUE(private_ptr != NULL);
650 MockRemoteInputMethodDelegateWin mock_remote_delegate;
651 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
653 // TextInputClient is not focused yet here.
655 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
656 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
657 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
658 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
659 delegate_.Reset();
660 mock_text_input_client.Reset();
662 input_method->SetFocusedTextInputClient(&mock_text_input_client);
663 // TextInputClient is now focused here.
665 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
666 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
667 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
668 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
669 delegate_.Reset();
670 mock_text_input_client.Reset();
672 input_method->SetDelegate(NULL);
673 // RemoteInputMethodDelegateWin is no longer set here.
675 EXPECT_FALSE(input_method->DispatchKeyEvent(fabricated_keydown));
676 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
679 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
680 // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
681 // for fabricated character events.
683 MockInputMethodDelegate delegate_;
684 MockTextInputClient mock_text_input_client;
685 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
687 ui::KeyEvent fabricated_char(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
688 fabricated_char.set_character(L'A');
690 // This must not cause a crash.
691 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
692 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
693 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
694 delegate_.Reset();
695 mock_text_input_client.Reset();
697 RemoteInputMethodPrivateWin* private_ptr =
698 RemoteInputMethodPrivateWin::Get(input_method.get());
699 ASSERT_TRUE(private_ptr != NULL);
700 MockRemoteInputMethodDelegateWin mock_remote_delegate;
701 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
703 // TextInputClient is not focused yet here.
705 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
706 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
707 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
708 delegate_.Reset();
709 mock_text_input_client.Reset();
711 input_method->SetFocusedTextInputClient(&mock_text_input_client);
713 // TextInputClient is now focused here.
715 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
716 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
717 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
718 delegate_.Reset();
719 mock_text_input_client.Reset();
722 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
723 MockInputMethodDelegate delegate_;
724 MockTextInputClient mock_text_input_client;
725 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
727 RemoteInputMethodPrivateWin* private_ptr =
728 RemoteInputMethodPrivateWin::Get(input_method.get());
729 ASSERT_TRUE(private_ptr != NULL);
730 MockRemoteInputMethodDelegateWin mock_remote_delegate;
731 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
733 CompositionText composition_text;
735 // TextInputClient is not focused yet here.
737 private_ptr->OnCompositionChanged(composition_text);
738 EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
739 delegate_.Reset();
740 mock_text_input_client.Reset();
742 input_method->SetFocusedTextInputClient(&mock_text_input_client);
744 // TextInputClient is now focused here.
746 private_ptr->OnCompositionChanged(composition_text);
747 EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
748 delegate_.Reset();
749 mock_text_input_client.Reset();
752 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
753 MockInputMethodDelegate delegate_;
754 MockTextInputClient mock_text_input_client;
755 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
757 RemoteInputMethodPrivateWin* private_ptr =
758 RemoteInputMethodPrivateWin::Get(input_method.get());
759 ASSERT_TRUE(private_ptr != NULL);
760 MockRemoteInputMethodDelegateWin mock_remote_delegate;
761 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
763 base::string16 committed_text = L"Hello";
765 // TextInputClient is not focused yet here.
767 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
768 private_ptr->OnTextCommitted(committed_text);
769 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
770 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
771 EXPECT_EQ(L"", mock_text_input_client.inserted_text());
772 delegate_.Reset();
773 mock_text_input_client.Reset();
775 input_method->SetFocusedTextInputClient(&mock_text_input_client);
777 // TextInputClient is now focused here.
779 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
780 private_ptr->OnTextCommitted(committed_text);
781 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
782 EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
783 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
784 delegate_.Reset();
785 mock_text_input_client.Reset();
787 // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
788 // should not be used.
789 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
790 private_ptr->OnTextCommitted(committed_text);
791 EXPECT_EQ(committed_text.size(),
792 mock_text_input_client.call_count_insert_char());
793 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
794 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
795 delegate_.Reset();
796 mock_text_input_client.Reset();
799 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
800 DummyTextInputClient text_input_client;
801 DummyTextInputClient text_input_client_the_other;
803 MockInputMethodObserver input_method_observer;
804 MockInputMethodDelegate delegate_;
805 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
806 InputMethodScopedObserver scoped_observer(&input_method_observer);
807 scoped_observer.Add(input_method.get());
809 input_method->SetFocusedTextInputClient(&text_input_client);
810 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
811 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
812 input_method_observer.Reset();
814 input_method->SetFocusedTextInputClient(&text_input_client);
815 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
816 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
817 input_method_observer.Reset();
819 input_method->SetFocusedTextInputClient(&text_input_client_the_other);
820 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
821 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
822 input_method_observer.Reset();
824 input_method->DetachTextInputClient(&text_input_client_the_other);
825 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
826 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
827 input_method_observer.Reset();
830 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
831 DummyTextInputClient text_input_client;
832 DummyTextInputClient text_input_client_the_other;
834 MockInputMethodObserver input_method_observer;
835 InputMethodScopedObserver scoped_observer(&input_method_observer);
837 MockInputMethodDelegate delegate_;
838 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
839 input_method->AddObserver(&input_method_observer);
841 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
842 input_method.reset();
843 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
846 } // namespace
847 } // namespace ui