Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / base / ime / remote_input_method_win_unittest.cc
blobf92029d4c1b59a594114451de9fc85852dc2985a
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 ~MockInputMethodObserver() override {}
221 void Reset() {
222 on_text_input_state_changed_ = 0;
223 on_input_method_destroyed_changed_ = 0;
225 size_t on_text_input_state_changed() const {
226 return on_text_input_state_changed_;
228 size_t on_input_method_destroyed_changed() const {
229 return on_input_method_destroyed_changed_;
232 private:
233 // Overriden from InputMethodObserver.
234 void OnTextInputTypeChanged(const TextInputClient* client) override {}
235 void OnFocus() override {}
236 void OnBlur() override {}
237 void OnCaretBoundsChanged(const TextInputClient* client) override {}
238 void OnTextInputStateChanged(const TextInputClient* client) override {
239 ++on_text_input_state_changed_;
241 void OnInputMethodDestroyed(const InputMethod* client) override {
242 ++on_input_method_destroyed_changed_;
244 void OnShowImeIfNeeded() override {}
246 size_t on_text_input_state_changed_;
247 size_t on_input_method_destroyed_changed_;
248 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
251 typedef ScopedObserver<InputMethod, InputMethodObserver>
252 InputMethodScopedObserver;
254 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
255 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
257 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
258 RemoteInputMethodPrivateWin* kNull =
259 static_cast<RemoteInputMethodPrivateWin*>(NULL);
260 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
262 MockInputMethodDelegate delegate_;
263 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
264 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
266 InputMethod* dangling_ptr = input_method.get();
267 input_method.reset(NULL);
268 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
271 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
272 MockInputMethodDelegate delegate_;
273 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
274 RemoteInputMethodPrivateWin* private_ptr =
275 RemoteInputMethodPrivateWin::Get(input_method.get());
276 ASSERT_TRUE(private_ptr != NULL);
278 private_ptr->OnInputSourceChanged(
279 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
280 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
282 private_ptr->OnInputSourceChanged(
283 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
284 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
287 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
288 MockInputMethodDelegate delegate_;
289 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
290 RemoteInputMethodPrivateWin* private_ptr =
291 RemoteInputMethodPrivateWin::Get(input_method.get());
292 ASSERT_TRUE(private_ptr != NULL);
294 // Initial value
295 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
297 // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
298 // focused text input client is NULL.
299 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
300 private_ptr->OnCandidatePopupChanged(false);
301 private_ptr->OnCandidatePopupChanged(true);
303 MockTextInputClient mock_text_input_client;
304 input_method->SetFocusedTextInputClient(&mock_text_input_client);
306 ASSERT_FALSE(mock_text_input_client.is_candidate_window_shown_called());
307 ASSERT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
308 mock_text_input_client.Reset();
310 private_ptr->OnCandidatePopupChanged(true);
311 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
312 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
313 EXPECT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
315 private_ptr->OnCandidatePopupChanged(false);
316 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
317 EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
318 EXPECT_TRUE(mock_text_input_client.is_candidate_window_hidden_called());
321 TEST(RemoteInputMethodWinTest, CancelComposition) {
322 MockInputMethodDelegate delegate_;
323 MockTextInputClient mock_text_input_client;
324 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
326 // This must not cause a crash.
327 input_method->CancelComposition(&mock_text_input_client);
329 RemoteInputMethodPrivateWin* private_ptr =
330 RemoteInputMethodPrivateWin::Get(input_method.get());
331 ASSERT_TRUE(private_ptr != NULL);
332 MockRemoteInputMethodDelegateWin mock_remote_delegate;
333 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
335 input_method->CancelComposition(&mock_text_input_client);
336 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
338 input_method->SetFocusedTextInputClient(&mock_text_input_client);
339 input_method->CancelComposition(&mock_text_input_client);
340 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
343 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
344 MockInputMethodDelegate delegate_;
345 MockTextInputClient mock_text_input_client;
346 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
348 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
349 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
350 input_method->SetFocusedTextInputClient(&mock_text_input_client);
352 RemoteInputMethodPrivateWin* private_ptr =
353 RemoteInputMethodPrivateWin::Get(input_method.get());
354 ASSERT_TRUE(private_ptr != NULL);
355 MockRemoteInputMethodDelegateWin mock_remote_delegate;
356 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
358 // Initial state must be synced.
359 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
360 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
361 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
362 mock_remote_delegate.composition_character_bounds()[0]);
363 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
364 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
366 // State must be cleared by SetFocusedTextInputClient(NULL).
367 mock_remote_delegate.Reset();
368 input_method->SetFocusedTextInputClient(NULL);
369 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
370 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
371 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
374 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
375 MockInputMethodDelegate delegate_;
376 MockTextInputClient mock_text_input_client;
377 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
379 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
380 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
381 input_method->SetFocusedTextInputClient(&mock_text_input_client);
383 RemoteInputMethodPrivateWin* private_ptr =
384 RemoteInputMethodPrivateWin::Get(input_method.get());
385 ASSERT_TRUE(private_ptr != NULL);
386 MockRemoteInputMethodDelegateWin mock_remote_delegate;
387 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
389 // Initial state must be synced.
390 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
391 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
392 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
393 mock_remote_delegate.composition_character_bounds()[0]);
394 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
395 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
397 // State must be cleared by DetachTextInputClient
398 mock_remote_delegate.Reset();
399 input_method->DetachTextInputClient(&mock_text_input_client);
400 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
401 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
402 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
405 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
406 MockInputMethodDelegate delegate_;
407 MockTextInputClient mock_text_input_client;
408 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
410 // This must not cause a crash.
411 input_method->OnCaretBoundsChanged(&mock_text_input_client);
413 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
414 input_method->SetFocusedTextInputClient(&mock_text_input_client);
416 RemoteInputMethodPrivateWin* private_ptr =
417 RemoteInputMethodPrivateWin::Get(input_method.get());
418 ASSERT_TRUE(private_ptr != NULL);
419 MockRemoteInputMethodDelegateWin mock_remote_delegate;
420 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
422 // Initial state must be synced.
423 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
424 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
425 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
426 mock_remote_delegate.composition_character_bounds()[0]);
428 // Redundant OnCaretBoundsChanged must be ignored.
429 mock_remote_delegate.Reset();
430 input_method->OnCaretBoundsChanged(&mock_text_input_client);
431 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
433 // Check OnCaretBoundsChanged is handled. (w/o composition)
434 mock_remote_delegate.Reset();
435 mock_text_input_client.Reset();
436 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
437 input_method->OnCaretBoundsChanged(&mock_text_input_client);
438 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
439 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
440 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
441 mock_remote_delegate.composition_character_bounds()[0]);
443 // Check OnCaretBoundsChanged is handled. (w/ composition)
445 mock_remote_delegate.Reset();
446 mock_text_input_client.Reset();
448 std::vector<gfx::Rect> bounds;
449 bounds.push_back(gfx::Rect(10, 20, 30, 40));
450 bounds.push_back(gfx::Rect(40, 30, 20, 10));
451 mock_text_input_client.set_composition_character_bounds(bounds);
452 input_method->OnCaretBoundsChanged(&mock_text_input_client);
453 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
454 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
458 // Test case against crbug.com/328237.
459 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
460 MockInputMethodDelegate delegate_;
461 MockTextInputClient mock_text_input_client;
462 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
463 input_method->SetFocusedTextInputClient(&mock_text_input_client);
465 RemoteInputMethodPrivateWin* private_ptr =
466 RemoteInputMethodPrivateWin::Get(input_method.get());
467 ASSERT_TRUE(private_ptr != NULL);
468 MockRemoteInputMethodDelegateWin mock_remote_delegate;
469 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
471 mock_remote_delegate.Reset();
472 mock_text_input_client.Reset();
473 mock_text_input_client.set_emulate_pepper_flash(true);
475 std::vector<gfx::Rect> caret_bounds;
476 caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
477 mock_text_input_client.set_caret_bounds(caret_bounds[0]);
479 std::vector<gfx::Rect> composition_bounds;
480 composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
481 composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
482 mock_text_input_client.set_composition_character_bounds(composition_bounds);
483 input_method->OnCaretBoundsChanged(&mock_text_input_client);
484 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
485 // The caret bounds must be used when
486 // TextInputClient::GetCompositionCharacterBounds failed.
487 EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
490 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
491 MockInputMethodDelegate delegate_;
492 MockTextInputClient mock_text_input_client;
493 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
495 // This must not cause a crash.
496 input_method->OnCaretBoundsChanged(&mock_text_input_client);
498 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
499 input_method->SetFocusedTextInputClient(&mock_text_input_client);
501 RemoteInputMethodPrivateWin* private_ptr =
502 RemoteInputMethodPrivateWin::Get(input_method.get());
503 ASSERT_TRUE(private_ptr != NULL);
504 MockRemoteInputMethodDelegateWin mock_remote_delegate;
505 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
507 // Initial state must be synced.
508 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
509 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
510 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
512 // Check TEXT_INPUT_TYPE_NONE is handled.
513 mock_remote_delegate.Reset();
514 mock_text_input_client.Reset();
515 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
516 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
517 input_method->OnTextInputTypeChanged(&mock_text_input_client);
518 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
519 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
521 // Redundant OnTextInputTypeChanged must be ignored.
522 mock_remote_delegate.Reset();
523 input_method->OnTextInputTypeChanged(&mock_text_input_client);
524 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
526 mock_remote_delegate.Reset();
527 mock_text_input_client.Reset();
528 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
529 input_method->OnCaretBoundsChanged(&mock_text_input_client);
532 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
533 // Basically RemoteInputMethodWin does not handle native keydown event.
535 MockInputMethodDelegate delegate_;
536 MockTextInputClient mock_text_input_client;
537 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
539 const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
540 ui::KeyEvent native_keydown(wm_keydown);
542 // This must not cause a crash.
543 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
544 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
545 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
546 delegate_.Reset();
547 mock_text_input_client.Reset();
549 RemoteInputMethodPrivateWin* private_ptr =
550 RemoteInputMethodPrivateWin::Get(input_method.get());
551 ASSERT_TRUE(private_ptr != NULL);
552 MockRemoteInputMethodDelegateWin mock_remote_delegate;
553 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
555 // TextInputClient is not focused yet here.
557 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
558 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
559 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
560 delegate_.Reset();
561 mock_text_input_client.Reset();
563 input_method->SetFocusedTextInputClient(&mock_text_input_client);
565 // TextInputClient is now focused here.
567 EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
568 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
569 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
570 delegate_.Reset();
571 mock_text_input_client.Reset();
574 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
575 // RemoteInputMethodWin handles native char event if possible.
577 MockInputMethodDelegate delegate_;
578 MockTextInputClient mock_text_input_client;
579 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
581 const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
582 ui::KeyEvent native_char(wm_char);
584 // This must not cause a crash.
585 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
586 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
587 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
588 delegate_.Reset();
589 mock_text_input_client.Reset();
591 RemoteInputMethodPrivateWin* private_ptr =
592 RemoteInputMethodPrivateWin::Get(input_method.get());
593 ASSERT_TRUE(private_ptr != NULL);
594 MockRemoteInputMethodDelegateWin mock_remote_delegate;
595 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
597 // TextInputClient is not focused yet here.
599 EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
600 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
601 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
602 delegate_.Reset();
603 mock_text_input_client.Reset();
605 input_method->SetFocusedTextInputClient(&mock_text_input_client);
607 // TextInputClient is now focused here.
609 EXPECT_TRUE(input_method->DispatchKeyEvent(native_char));
610 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
611 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
612 delegate_.Reset();
613 mock_text_input_client.Reset();
616 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
617 // Fabricated non-char event will be delegated to
618 // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
619 // delegate is installed.
621 MockInputMethodDelegate delegate_;
622 MockTextInputClient mock_text_input_client;
623 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
625 ui::KeyEvent fabricated_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
626 fabricated_keydown.set_character(L'A');
628 // This must not cause a crash.
629 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
630 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
631 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
632 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
633 delegate_.Reset();
634 mock_text_input_client.Reset();
636 RemoteInputMethodPrivateWin* private_ptr =
637 RemoteInputMethodPrivateWin::Get(input_method.get());
638 ASSERT_TRUE(private_ptr != NULL);
639 MockRemoteInputMethodDelegateWin mock_remote_delegate;
640 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
642 // TextInputClient is not focused yet here.
644 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
645 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
646 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
647 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
648 delegate_.Reset();
649 mock_text_input_client.Reset();
651 input_method->SetFocusedTextInputClient(&mock_text_input_client);
652 // TextInputClient is now focused here.
654 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
655 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
656 ASSERT_EQ(1, delegate_.fabricated_key_events().size());
657 EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
658 delegate_.Reset();
659 mock_text_input_client.Reset();
661 input_method->SetDelegate(NULL);
662 // RemoteInputMethodDelegateWin is no longer set here.
664 EXPECT_FALSE(input_method->DispatchKeyEvent(fabricated_keydown));
665 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
668 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
669 // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
670 // for fabricated character events.
672 MockInputMethodDelegate delegate_;
673 MockTextInputClient mock_text_input_client;
674 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
676 ui::KeyEvent fabricated_char(L'A', ui::VKEY_A, ui::EF_NONE);
678 // This must not cause a crash.
679 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
680 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
681 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
682 delegate_.Reset();
683 mock_text_input_client.Reset();
685 RemoteInputMethodPrivateWin* private_ptr =
686 RemoteInputMethodPrivateWin::Get(input_method.get());
687 ASSERT_TRUE(private_ptr != NULL);
688 MockRemoteInputMethodDelegateWin mock_remote_delegate;
689 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
691 // TextInputClient is not focused yet here.
693 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
694 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
695 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
696 delegate_.Reset();
697 mock_text_input_client.Reset();
699 input_method->SetFocusedTextInputClient(&mock_text_input_client);
701 // TextInputClient is now focused here.
703 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
704 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
705 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
706 delegate_.Reset();
707 mock_text_input_client.Reset();
710 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
711 MockInputMethodDelegate delegate_;
712 MockTextInputClient mock_text_input_client;
713 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
715 RemoteInputMethodPrivateWin* private_ptr =
716 RemoteInputMethodPrivateWin::Get(input_method.get());
717 ASSERT_TRUE(private_ptr != NULL);
718 MockRemoteInputMethodDelegateWin mock_remote_delegate;
719 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
721 CompositionText composition_text;
723 // TextInputClient is not focused yet here.
725 private_ptr->OnCompositionChanged(composition_text);
726 EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
727 delegate_.Reset();
728 mock_text_input_client.Reset();
730 input_method->SetFocusedTextInputClient(&mock_text_input_client);
732 // TextInputClient is now focused here.
734 private_ptr->OnCompositionChanged(composition_text);
735 EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
736 delegate_.Reset();
737 mock_text_input_client.Reset();
740 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
741 MockInputMethodDelegate delegate_;
742 MockTextInputClient mock_text_input_client;
743 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
745 RemoteInputMethodPrivateWin* private_ptr =
746 RemoteInputMethodPrivateWin::Get(input_method.get());
747 ASSERT_TRUE(private_ptr != NULL);
748 MockRemoteInputMethodDelegateWin mock_remote_delegate;
749 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
751 base::string16 committed_text = L"Hello";
753 // TextInputClient is not focused yet here.
755 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
756 private_ptr->OnTextCommitted(committed_text);
757 EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
758 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
759 EXPECT_EQ(L"", mock_text_input_client.inserted_text());
760 delegate_.Reset();
761 mock_text_input_client.Reset();
763 input_method->SetFocusedTextInputClient(&mock_text_input_client);
765 // TextInputClient is now focused 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(1, mock_text_input_client.call_count_insert_text());
771 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
772 delegate_.Reset();
773 mock_text_input_client.Reset();
775 // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
776 // should not be used.
777 mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
778 private_ptr->OnTextCommitted(committed_text);
779 EXPECT_EQ(committed_text.size(),
780 mock_text_input_client.call_count_insert_char());
781 EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
782 EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
783 delegate_.Reset();
784 mock_text_input_client.Reset();
787 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
788 DummyTextInputClient text_input_client;
789 DummyTextInputClient text_input_client_the_other;
791 MockInputMethodObserver input_method_observer;
792 MockInputMethodDelegate delegate_;
793 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
794 InputMethodScopedObserver scoped_observer(&input_method_observer);
795 scoped_observer.Add(input_method.get());
797 input_method->SetFocusedTextInputClient(&text_input_client);
798 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
799 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
800 input_method_observer.Reset();
802 input_method->SetFocusedTextInputClient(&text_input_client);
803 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
804 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
805 input_method_observer.Reset();
807 input_method->SetFocusedTextInputClient(&text_input_client_the_other);
808 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
809 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
810 input_method_observer.Reset();
812 input_method->DetachTextInputClient(&text_input_client_the_other);
813 ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
814 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
815 input_method_observer.Reset();
818 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
819 DummyTextInputClient text_input_client;
820 DummyTextInputClient text_input_client_the_other;
822 MockInputMethodObserver input_method_observer;
823 InputMethodScopedObserver scoped_observer(&input_method_observer);
825 MockInputMethodDelegate delegate_;
826 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
827 input_method->AddObserver(&input_method_observer);
829 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
830 input_method.reset();
831 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
834 } // namespace
835 } // namespace ui