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