Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / base / ime / remote_input_method_win_unittest.cc
blob75f6b500ed6958f5c9e1511034d1fdb8cde2e163
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 void SetCompositionText(const ui::CompositionText& composition) override {
90 ++call_count_set_composition_text_;
92 void InsertChar(base::char16 ch, int flags) override {
93 inserted_text_.append(1, ch);
94 ++call_count_insert_char_;
96 void InsertText(const base::string16& text) override {
97 inserted_text_.append(text);
98 ++call_count_insert_text_;
100 ui::TextInputType GetTextInputType() const override {
101 return text_input_type_;
103 ui::TextInputMode GetTextInputMode() const override {
104 return text_input_mode_;
106 gfx::Rect GetCaretBounds() const override { return caret_bounds_; }
107 bool GetCompositionCharacterBounds(uint32 index,
108 gfx::Rect* rect) const override {
109 // Emulate the situation of crbug.com/328237.
110 if (emulate_pepper_flash_)
111 return false;
112 if (!rect || composition_character_bounds_.size() <= index)
113 return false;
114 *rect = composition_character_bounds_[index];
115 return true;
117 bool HasCompositionText() const override {
118 return !composition_character_bounds_.empty();
120 bool GetCompositionTextRange(gfx::Range* range) const override {
121 if (composition_character_bounds_.empty())
122 return false;
123 *range = gfx::Range(0, composition_character_bounds_.size());
124 return true;
126 void OnCandidateWindowShown() override {
127 is_candidate_window_shown_called_ = true;
129 void OnCandidateWindowHidden() override {
130 is_candidate_window_hidden_called_ = true;
133 ui::TextInputType text_input_type_;
134 ui::TextInputMode text_input_mode_;
135 gfx::Rect caret_bounds_;
136 std::vector<gfx::Rect> composition_character_bounds_;
137 base::string16 inserted_text_;
138 size_t call_count_set_composition_text_;
139 size_t call_count_insert_char_;
140 size_t call_count_insert_text_;
141 bool emulate_pepper_flash_;
142 bool is_candidate_window_shown_called_;
143 bool is_candidate_window_hidden_called_;
144 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
147 class MockInputMethodDelegate : public internal::InputMethodDelegate {
148 public:
149 MockInputMethodDelegate() {}
151 const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
152 return fabricated_key_events_;
154 void Reset() {
155 fabricated_key_events_.clear();
158 private:
159 bool DispatchKeyEventPostIME(const ui::KeyEvent& event) override {
160 EXPECT_FALSE(event.HasNativeEvent());
161 fabricated_key_events_.push_back(event.key_code());
162 return true;
165 std::vector<ui::KeyboardCode> fabricated_key_events_;
166 DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
169 class MockRemoteInputMethodDelegateWin
170 : public internal::RemoteInputMethodDelegateWin {
171 public:
172 MockRemoteInputMethodDelegateWin()
173 : cancel_composition_called_(false),
174 text_input_client_updated_called_(false) {
177 bool cancel_composition_called() const {
178 return cancel_composition_called_;
180 bool text_input_client_updated_called() const {
181 return text_input_client_updated_called_;
183 const std::vector<int32>& input_scopes() const {
184 return input_scopes_;
186 const std::vector<gfx::Rect>& composition_character_bounds() const {
187 return composition_character_bounds_;
189 void Reset() {
190 cancel_composition_called_ = false;
191 text_input_client_updated_called_ = false;
192 input_scopes_.clear();
193 composition_character_bounds_.clear();
196 private:
197 void CancelComposition() override { cancel_composition_called_ = true; }
199 void OnTextInputClientUpdated(
200 const std::vector<int32>& input_scopes,
201 const std::vector<gfx::Rect>& composition_character_bounds) override {
202 text_input_client_updated_called_ = true;
203 input_scopes_ = input_scopes;
204 composition_character_bounds_ = composition_character_bounds;
207 bool cancel_composition_called_;
208 bool text_input_client_updated_called_;
209 std::vector<int32> input_scopes_;
210 std::vector<gfx::Rect> composition_character_bounds_;
211 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
214 class MockInputMethodObserver : public InputMethodObserver {
215 public:
216 MockInputMethodObserver()
217 : on_text_input_state_changed_(0),
218 on_input_method_destroyed_changed_(0) {
220 virtual ~MockInputMethodObserver() {
222 void Reset() {
223 on_text_input_state_changed_ = 0;
224 on_input_method_destroyed_changed_ = 0;
226 size_t on_text_input_state_changed() const {
227 return on_text_input_state_changed_;
229 size_t on_input_method_destroyed_changed() const {
230 return on_input_method_destroyed_changed_;
233 private:
234 // Overriden from InputMethodObserver.
235 void OnTextInputTypeChanged(const TextInputClient* client) override {}
236 void OnFocus() override {}
237 void OnBlur() override {}
238 void OnCaretBoundsChanged(const TextInputClient* client) override {}
239 void OnTextInputStateChanged(const TextInputClient* client) override {
240 ++on_text_input_state_changed_;
242 void OnInputMethodDestroyed(const InputMethod* client) override {
243 ++on_input_method_destroyed_changed_;
245 void OnShowImeIfNeeded() override {}
247 size_t on_text_input_state_changed_;
248 size_t on_input_method_destroyed_changed_;
249 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
252 typedef ScopedObserver<InputMethod, InputMethodObserver>
253 InputMethodScopedObserver;
255 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
256 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
258 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
259 RemoteInputMethodPrivateWin* kNull =
260 static_cast<RemoteInputMethodPrivateWin*>(NULL);
261 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
263 MockInputMethodDelegate delegate_;
264 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
265 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
267 InputMethod* dangling_ptr = input_method.get();
268 input_method.reset(NULL);
269 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
272 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
273 MockInputMethodDelegate delegate_;
274 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
275 RemoteInputMethodPrivateWin* private_ptr =
276 RemoteInputMethodPrivateWin::Get(input_method.get());
277 ASSERT_TRUE(private_ptr != NULL);
279 private_ptr->OnInputSourceChanged(
280 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
281 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
283 private_ptr->OnInputSourceChanged(
284 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
285 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
288 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
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 // Initial value
296 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
298 // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
299 // focused text input client is NULL.
300 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
301 private_ptr->OnCandidatePopupChanged(false);
302 private_ptr->OnCandidatePopupChanged(true);
304 MockTextInputClient mock_text_input_client;
305 input_method->SetFocusedTextInputClient(&mock_text_input_client);
307 ASSERT_FALSE(mock_text_input_client.is_candidate_window_shown_called());
308 ASSERT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
309 mock_text_input_client.Reset();
311 private_ptr->OnCandidatePopupChanged(true);
312 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
313 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
314 EXPECT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
316 private_ptr->OnCandidatePopupChanged(false);
317 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
318 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
319 EXPECT_TRUE(mock_text_input_client.is_candidate_window_hidden_called());
322 TEST(RemoteInputMethodWinTest, CancelComposition) {
323 MockInputMethodDelegate delegate_;
324 MockTextInputClient mock_text_input_client;
325 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
327 // This must not cause a crash.
328 input_method->CancelComposition(&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 input_method->CancelComposition(&mock_text_input_client);
337 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
339 input_method->SetFocusedTextInputClient(&mock_text_input_client);
340 input_method->CancelComposition(&mock_text_input_client);
341 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
344 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
345 MockInputMethodDelegate delegate_;
346 MockTextInputClient mock_text_input_client;
347 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
349 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
350 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
351 input_method->SetFocusedTextInputClient(&mock_text_input_client);
353 RemoteInputMethodPrivateWin* private_ptr =
354 RemoteInputMethodPrivateWin::Get(input_method.get());
355 ASSERT_TRUE(private_ptr != NULL);
356 MockRemoteInputMethodDelegateWin mock_remote_delegate;
357 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
359 // Initial state must be synced.
360 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
361 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
362 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
363 mock_remote_delegate.composition_character_bounds()[0]);
364 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
365 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
367 // State must be cleared by SetFocusedTextInputClient(NULL).
368 mock_remote_delegate.Reset();
369 input_method->SetFocusedTextInputClient(NULL);
370 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
371 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
372 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
375 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
376 MockInputMethodDelegate delegate_;
377 MockTextInputClient mock_text_input_client;
378 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
380 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
381 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
382 input_method->SetFocusedTextInputClient(&mock_text_input_client);
384 RemoteInputMethodPrivateWin* private_ptr =
385 RemoteInputMethodPrivateWin::Get(input_method.get());
386 ASSERT_TRUE(private_ptr != NULL);
387 MockRemoteInputMethodDelegateWin mock_remote_delegate;
388 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
390 // Initial state must be synced.
391 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
392 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
393 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
394 mock_remote_delegate.composition_character_bounds()[0]);
395 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
396 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
398 // State must be cleared by DetachTextInputClient
399 mock_remote_delegate.Reset();
400 input_method->DetachTextInputClient(&mock_text_input_client);
401 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
402 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
403 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
406 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
407 MockInputMethodDelegate delegate_;
408 MockTextInputClient mock_text_input_client;
409 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
411 // This must not cause a crash.
412 input_method->OnCaretBoundsChanged(&mock_text_input_client);
414 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
415 input_method->SetFocusedTextInputClient(&mock_text_input_client);
417 RemoteInputMethodPrivateWin* private_ptr =
418 RemoteInputMethodPrivateWin::Get(input_method.get());
419 ASSERT_TRUE(private_ptr != NULL);
420 MockRemoteInputMethodDelegateWin mock_remote_delegate;
421 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
423 // Initial state must be synced.
424 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
425 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
426 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
427 mock_remote_delegate.composition_character_bounds()[0]);
429 // Redundant OnCaretBoundsChanged must be ignored.
430 mock_remote_delegate.Reset();
431 input_method->OnCaretBoundsChanged(&mock_text_input_client);
432 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
434 // Check OnCaretBoundsChanged is handled. (w/o composition)
435 mock_remote_delegate.Reset();
436 mock_text_input_client.Reset();
437 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
438 input_method->OnCaretBoundsChanged(&mock_text_input_client);
439 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
440 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
441 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
442 mock_remote_delegate.composition_character_bounds()[0]);
444 // Check OnCaretBoundsChanged is handled. (w/ composition)
446 mock_remote_delegate.Reset();
447 mock_text_input_client.Reset();
449 std::vector<gfx::Rect> bounds;
450 bounds.push_back(gfx::Rect(10, 20, 30, 40));
451 bounds.push_back(gfx::Rect(40, 30, 20, 10));
452 mock_text_input_client.set_composition_character_bounds(bounds);
453 input_method->OnCaretBoundsChanged(&mock_text_input_client);
454 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
455 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
459 // Test case against crbug.com/328237.
460 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
461 MockInputMethodDelegate delegate_;
462 MockTextInputClient mock_text_input_client;
463 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
464 input_method->SetFocusedTextInputClient(&mock_text_input_client);
466 RemoteInputMethodPrivateWin* private_ptr =
467 RemoteInputMethodPrivateWin::Get(input_method.get());
468 ASSERT_TRUE(private_ptr != NULL);
469 MockRemoteInputMethodDelegateWin mock_remote_delegate;
470 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
472 mock_remote_delegate.Reset();
473 mock_text_input_client.Reset();
474 mock_text_input_client.set_emulate_pepper_flash(true);
476 std::vector<gfx::Rect> caret_bounds;
477 caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
478 mock_text_input_client.set_caret_bounds(caret_bounds[0]);
480 std::vector<gfx::Rect> composition_bounds;
481 composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
482 composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
483 mock_text_input_client.set_composition_character_bounds(composition_bounds);
484 input_method->OnCaretBoundsChanged(&mock_text_input_client);
485 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
486 // The caret bounds must be used when
487 // TextInputClient::GetCompositionCharacterBounds failed.
488 EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
491 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
492 MockInputMethodDelegate delegate_;
493 MockTextInputClient mock_text_input_client;
494 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
496 // This must not cause a crash.
497 input_method->OnCaretBoundsChanged(&mock_text_input_client);
499 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
500 input_method->SetFocusedTextInputClient(&mock_text_input_client);
502 RemoteInputMethodPrivateWin* private_ptr =
503 RemoteInputMethodPrivateWin::Get(input_method.get());
504 ASSERT_TRUE(private_ptr != NULL);
505 MockRemoteInputMethodDelegateWin mock_remote_delegate;
506 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
508 // Initial state must be synced.
509 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
510 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
511 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
513 // Check TEXT_INPUT_TYPE_NONE is handled.
514 mock_remote_delegate.Reset();
515 mock_text_input_client.Reset();
516 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
517 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
518 input_method->OnTextInputTypeChanged(&mock_text_input_client);
519 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
520 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
522 // Redundant OnTextInputTypeChanged must be ignored.
523 mock_remote_delegate.Reset();
524 input_method->OnTextInputTypeChanged(&mock_text_input_client);
525 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
527 mock_remote_delegate.Reset();
528 mock_text_input_client.Reset();
529 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
530 input_method->OnCaretBoundsChanged(&mock_text_input_client);
533 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
534 // Basically RemoteInputMethodWin does not handle native keydown event.
536 MockInputMethodDelegate delegate_;
537 MockTextInputClient mock_text_input_client;
538 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
540 const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
541 ui::KeyEvent native_keydown(wm_keydown);
543 // This must not cause a crash.
544 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
545 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
546 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
547 delegate_.Reset();
548 mock_text_input_client.Reset();
550 RemoteInputMethodPrivateWin* private_ptr =
551 RemoteInputMethodPrivateWin::Get(input_method.get());
552 ASSERT_TRUE(private_ptr != NULL);
553 MockRemoteInputMethodDelegateWin mock_remote_delegate;
554 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
556 // TextInputClient is not focused yet here.
558 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
559 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
560 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
561 delegate_.Reset();
562 mock_text_input_client.Reset();
564 input_method->SetFocusedTextInputClient(&mock_text_input_client);
566 // TextInputClient is now focused 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();
575 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
576 // RemoteInputMethodWin handles native char event if possible.
578 MockInputMethodDelegate delegate_;
579 MockTextInputClient mock_text_input_client;
580 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
582 const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
583 ui::KeyEvent native_char(wm_char);
585 // This must not cause a crash.
586 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
587 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
588 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
589 delegate_.Reset();
590 mock_text_input_client.Reset();
592 RemoteInputMethodPrivateWin* private_ptr =
593 RemoteInputMethodPrivateWin::Get(input_method.get());
594 ASSERT_TRUE(private_ptr != NULL);
595 MockRemoteInputMethodDelegateWin mock_remote_delegate;
596 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
598 // TextInputClient is not focused yet here.
600 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
601 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
602 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
603 delegate_.Reset();
604 mock_text_input_client.Reset();
606 input_method->SetFocusedTextInputClient(&mock_text_input_client);
608 // TextInputClient is now focused here.
610 EXPECT_TRUE(input_method->DispatchKeyEvent(native_char));
611 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
612 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
613 delegate_.Reset();
614 mock_text_input_client.Reset();
617 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
618 // Fabricated non-char event will be delegated to
619 // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
620 // delegate is installed.
622 MockInputMethodDelegate delegate_;
623 MockTextInputClient mock_text_input_client;
624 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
626 ui::KeyEvent fabricated_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
627 fabricated_keydown.set_character(L'A');
629 // This must not cause a crash.
630 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
631 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
632 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
633 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
634 delegate_.Reset();
635 mock_text_input_client.Reset();
637 RemoteInputMethodPrivateWin* private_ptr =
638 RemoteInputMethodPrivateWin::Get(input_method.get());
639 ASSERT_TRUE(private_ptr != NULL);
640 MockRemoteInputMethodDelegateWin mock_remote_delegate;
641 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
643 // TextInputClient is not focused yet here.
645 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
646 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
647 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
648 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
649 delegate_.Reset();
650 mock_text_input_client.Reset();
652 input_method->SetFocusedTextInputClient(&mock_text_input_client);
653 // TextInputClient is now focused 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->SetDelegate(NULL);
663 // RemoteInputMethodDelegateWin is no longer set here.
665 EXPECT_FALSE(input_method->DispatchKeyEvent(fabricated_keydown));
666 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
669 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
670 // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
671 // for fabricated character events.
673 MockInputMethodDelegate delegate_;
674 MockTextInputClient mock_text_input_client;
675 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
677 ui::KeyEvent fabricated_char(L'A', ui::VKEY_A, ui::EF_NONE);
679 // This must not cause a crash.
680 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
681 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
682 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
683 delegate_.Reset();
684 mock_text_input_client.Reset();
686 RemoteInputMethodPrivateWin* private_ptr =
687 RemoteInputMethodPrivateWin::Get(input_method.get());
688 ASSERT_TRUE(private_ptr != NULL);
689 MockRemoteInputMethodDelegateWin mock_remote_delegate;
690 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
692 // TextInputClient is not focused yet here.
694 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
695 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
696 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
697 delegate_.Reset();
698 mock_text_input_client.Reset();
700 input_method->SetFocusedTextInputClient(&mock_text_input_client);
702 // TextInputClient is now focused here.
704 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
705 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
706 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
707 delegate_.Reset();
708 mock_text_input_client.Reset();
711 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
712 MockInputMethodDelegate delegate_;
713 MockTextInputClient mock_text_input_client;
714 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
716 RemoteInputMethodPrivateWin* private_ptr =
717 RemoteInputMethodPrivateWin::Get(input_method.get());
718 ASSERT_TRUE(private_ptr != NULL);
719 MockRemoteInputMethodDelegateWin mock_remote_delegate;
720 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
722 CompositionText composition_text;
724 // TextInputClient is not focused yet here.
726 private_ptr->OnCompositionChanged(composition_text);
727 EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
728 delegate_.Reset();
729 mock_text_input_client.Reset();
731 input_method->SetFocusedTextInputClient(&mock_text_input_client);
733 // TextInputClient is now focused here.
735 private_ptr->OnCompositionChanged(composition_text);
736 EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
737 delegate_.Reset();
738 mock_text_input_client.Reset();
741 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
742 MockInputMethodDelegate delegate_;
743 MockTextInputClient mock_text_input_client;
744 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
746 RemoteInputMethodPrivateWin* private_ptr =
747 RemoteInputMethodPrivateWin::Get(input_method.get());
748 ASSERT_TRUE(private_ptr != NULL);
749 MockRemoteInputMethodDelegateWin mock_remote_delegate;
750 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
752 base::string16 committed_text = L"Hello";
754 // TextInputClient is not focused yet here.
756 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
757 private_ptr->OnTextCommitted(committed_text);
758 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
759 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
760 EXPECT_EQ(L"", mock_text_input_client.inserted_text());
761 delegate_.Reset();
762 mock_text_input_client.Reset();
764 input_method->SetFocusedTextInputClient(&mock_text_input_client);
766 // TextInputClient is now focused here.
768 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
769 private_ptr->OnTextCommitted(committed_text);
770 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
771 EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
772 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
773 delegate_.Reset();
774 mock_text_input_client.Reset();
776 // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
777 // should not be used.
778 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
779 private_ptr->OnTextCommitted(committed_text);
780 EXPECT_EQ(committed_text.size(),
781 mock_text_input_client.call_count_insert_char());
782 EXPECT_EQ(0, 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();
788 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
789 DummyTextInputClient text_input_client;
790 DummyTextInputClient text_input_client_the_other;
792 MockInputMethodObserver input_method_observer;
793 MockInputMethodDelegate delegate_;
794 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
795 InputMethodScopedObserver scoped_observer(&input_method_observer);
796 scoped_observer.Add(input_method.get());
798 input_method->SetFocusedTextInputClient(&text_input_client);
799 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
800 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
801 input_method_observer.Reset();
803 input_method->SetFocusedTextInputClient(&text_input_client);
804 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
805 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
806 input_method_observer.Reset();
808 input_method->SetFocusedTextInputClient(&text_input_client_the_other);
809 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
810 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
811 input_method_observer.Reset();
813 input_method->DetachTextInputClient(&text_input_client_the_other);
814 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
815 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
816 input_method_observer.Reset();
819 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
820 DummyTextInputClient text_input_client;
821 DummyTextInputClient text_input_client_the_other;
823 MockInputMethodObserver input_method_observer;
824 InputMethodScopedObserver scoped_observer(&input_method_observer);
826 MockInputMethodDelegate delegate_;
827 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
828 input_method->AddObserver(&input_method_observer);
830 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
831 input_method.reset();
832 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
835 } // namespace
836 } // namespace ui