Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / base / ime / input_method_chromeos_unittest.cc
1 // Copyright 2014 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.
4
5 #include "ui/base/ime/input_method_chromeos.h"
6
7 #include <X11/Xlib.h>
8 #undef Bool
9 #undef FocusIn
10 #undef FocusOut
11 #undef None
12
13 #include <cstring>
14
15 #include "base/i18n/char_iterator.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chromeos/ime/composition_text.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/base/ime/chromeos/ime_bridge.h"
21 #include "ui/base/ime/chromeos/mock_ime_candidate_window_handler.h"
22 #include "ui/base/ime/chromeos/mock_ime_engine_handler.h"
23 #include "ui/base/ime/input_method_delegate.h"
24 #include "ui/base/ime/text_input_client.h"
25 #include "ui/base/ime/text_input_focus_manager.h"
26 #include "ui/base/ui_base_switches_util.h"
27 #include "ui/events/event.h"
28 #include "ui/events/test/events_test_utils_x11.h"
29 #include "ui/gfx/geometry/rect.h"
30
31 using base::UTF8ToUTF16;
32 using base::UTF16ToUTF8;
33
34 namespace ui {
35 namespace {
36
37 const base::string16 kSampleText = base::UTF8ToUTF16(
38     "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
39
40 typedef chromeos::IMEEngineHandlerInterface::KeyEventDoneCallback
41     KeyEventCallback;
42
43 uint32 GetOffsetInUTF16(
44     const base::string16& utf16_string, uint32 utf8_offset) {
45   DCHECK_LT(utf8_offset, utf16_string.size());
46   base::i18n::UTF16CharIterator char_iterator(&utf16_string);
47   for (size_t i = 0; i < utf8_offset; ++i)
48     char_iterator.Advance();
49   return char_iterator.array_pos();
50 }
51
52 bool IsEqualXKeyEvent(const XEvent& e1, const XEvent& e2) {
53   if ((e1.type == KeyPress && e2.type == KeyPress) ||
54       (e1.type == KeyRelease && e2.type == KeyRelease)) {
55     return !std::memcmp(&e1.xkey, &e2.xkey, sizeof(XKeyEvent));
56   }
57   return false;
58 }
59
60 enum KeyEventHandlerBehavior {
61   KEYEVENT_CONSUME,
62   KEYEVENT_NOT_CONSUME,
63 };
64
65 }  // namespace
66
67
68 class TestableInputMethodChromeOS : public InputMethodChromeOS {
69  public:
70   explicit TestableInputMethodChromeOS(internal::InputMethodDelegate* delegate)
71       : InputMethodChromeOS(delegate),
72         process_key_event_post_ime_call_count_(0) {
73   }
74
75   struct ProcessKeyEventPostIMEArgs {
76     ProcessKeyEventPostIMEArgs() : event(NULL), handled(false) {}
77     const ui::KeyEvent* event;
78     bool handled;
79   };
80
81   // Overridden from InputMethodChromeOS:
82   virtual void ProcessKeyEventPostIME(const ui::KeyEvent& key_event,
83                                       bool handled) OVERRIDE {
84     process_key_event_post_ime_args_.event = &key_event;
85     process_key_event_post_ime_args_.handled = handled;
86     ++process_key_event_post_ime_call_count_;
87   }
88
89   void ResetCallCount() {
90     process_key_event_post_ime_call_count_ = 0;
91   }
92
93   const ProcessKeyEventPostIMEArgs& process_key_event_post_ime_args() const {
94     return process_key_event_post_ime_args_;
95   }
96
97   int process_key_event_post_ime_call_count() const {
98     return process_key_event_post_ime_call_count_;
99   }
100
101   // Change access rights for testing.
102   using InputMethodChromeOS::ExtractCompositionText;
103   using InputMethodChromeOS::ResetContext;
104
105  private:
106   ProcessKeyEventPostIMEArgs process_key_event_post_ime_args_;
107   int process_key_event_post_ime_call_count_;
108 };
109
110 class SynchronousKeyEventHandler {
111  public:
112   SynchronousKeyEventHandler(uint32 expected_keyval,
113                              uint32 expected_keycode,
114                              uint32 expected_state,
115                              KeyEventHandlerBehavior behavior)
116       : expected_keyval_(expected_keyval),
117         expected_keycode_(expected_keycode),
118         expected_state_(expected_state),
119         behavior_(behavior) {}
120
121   virtual ~SynchronousKeyEventHandler() {}
122
123   void Run(uint32 keyval,
124            uint32 keycode,
125            uint32 state,
126            const KeyEventCallback& callback) {
127     EXPECT_EQ(expected_keyval_, keyval);
128     EXPECT_EQ(expected_keycode_, keycode);
129     EXPECT_EQ(expected_state_, state);
130     callback.Run(behavior_ == KEYEVENT_CONSUME);
131   }
132
133  private:
134   const uint32 expected_keyval_;
135   const uint32 expected_keycode_;
136   const uint32 expected_state_;
137   const KeyEventHandlerBehavior behavior_;
138
139   DISALLOW_COPY_AND_ASSIGN(SynchronousKeyEventHandler);
140 };
141
142 class AsynchronousKeyEventHandler {
143  public:
144   AsynchronousKeyEventHandler(uint32 expected_keyval,
145                               uint32 expected_keycode,
146                               uint32 expected_state)
147       : expected_keyval_(expected_keyval),
148         expected_keycode_(expected_keycode),
149         expected_state_(expected_state) {}
150
151   virtual ~AsynchronousKeyEventHandler() {}
152
153   void Run(uint32 keyval,
154            uint32 keycode,
155            uint32 state,
156            const KeyEventCallback& callback) {
157     EXPECT_EQ(expected_keyval_, keyval);
158     EXPECT_EQ(expected_keycode_, keycode);
159     EXPECT_EQ(expected_state_, state);
160     callback_ = callback;
161   }
162
163   void RunCallback(KeyEventHandlerBehavior behavior) {
164     callback_.Run(behavior == KEYEVENT_CONSUME);
165   }
166
167  private:
168   const uint32 expected_keyval_;
169   const uint32 expected_keycode_;
170   const uint32 expected_state_;
171   KeyEventCallback callback_;
172
173   DISALLOW_COPY_AND_ASSIGN(AsynchronousKeyEventHandler);
174 };
175
176 class SetSurroundingTextVerifier {
177  public:
178   SetSurroundingTextVerifier(const std::string& expected_surrounding_text,
179                              uint32 expected_cursor_position,
180                              uint32 expected_anchor_position)
181       : expected_surrounding_text_(expected_surrounding_text),
182         expected_cursor_position_(expected_cursor_position),
183         expected_anchor_position_(expected_anchor_position) {}
184
185   void Verify(const std::string& text,
186               uint32 cursor_pos,
187               uint32 anchor_pos) {
188     EXPECT_EQ(expected_surrounding_text_, text);
189     EXPECT_EQ(expected_cursor_position_, cursor_pos);
190     EXPECT_EQ(expected_anchor_position_, anchor_pos);
191   }
192
193  private:
194   const std::string expected_surrounding_text_;
195   const uint32 expected_cursor_position_;
196   const uint32 expected_anchor_position_;
197
198   DISALLOW_COPY_AND_ASSIGN(SetSurroundingTextVerifier);
199 };
200
201 class InputMethodChromeOSTest : public internal::InputMethodDelegate,
202                                 public testing::Test,
203                                 public TextInputClient {
204  public:
205   InputMethodChromeOSTest()
206       : dispatched_key_event_(ui::ET_UNKNOWN, ui::VKEY_UNKNOWN, ui::EF_NONE) {
207     ResetFlags();
208   }
209
210   virtual ~InputMethodChromeOSTest() {
211   }
212
213   virtual void SetUp() OVERRIDE {
214     chromeos::IMEBridge::Initialize();
215
216     mock_ime_engine_handler_.reset(
217         new chromeos::MockIMEEngineHandler());
218     chromeos::IMEBridge::Get()->SetCurrentEngineHandler(
219         mock_ime_engine_handler_.get());
220
221     mock_ime_candidate_window_handler_.reset(
222         new chromeos::MockIMECandidateWindowHandler());
223     chromeos::IMEBridge::Get()->SetCandidateWindowHandler(
224         mock_ime_candidate_window_handler_.get());
225
226     ime_.reset(new TestableInputMethodChromeOS(this));
227     if (switches::IsTextInputFocusManagerEnabled())
228       TextInputFocusManager::GetInstance()->FocusTextInputClient(this);
229     else
230       ime_->SetFocusedTextInputClient(this);
231   }
232
233   virtual void TearDown() OVERRIDE {
234     if (ime_.get()) {
235       if (switches::IsTextInputFocusManagerEnabled())
236         TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
237       else
238         ime_->SetFocusedTextInputClient(NULL);
239     }
240     ime_.reset();
241     chromeos::IMEBridge::Get()->SetCurrentEngineHandler(NULL);
242     chromeos::IMEBridge::Get()->SetCandidateWindowHandler(NULL);
243     mock_ime_engine_handler_.reset();
244     mock_ime_candidate_window_handler_.reset();
245     chromeos::IMEBridge::Shutdown();
246   }
247
248   // Overridden from ui::internal::InputMethodDelegate:
249   virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
250     dispatched_key_event_ = event;
251     return false;
252   }
253
254   // Overridden from ui::TextInputClient:
255   virtual void SetCompositionText(
256       const CompositionText& composition) OVERRIDE {
257     composition_text_ = composition;
258   }
259   virtual void ConfirmCompositionText() OVERRIDE {
260     confirmed_text_ = composition_text_;
261     composition_text_.Clear();
262   }
263   virtual void ClearCompositionText() OVERRIDE {
264     composition_text_.Clear();
265   }
266   virtual void InsertText(const base::string16& text) OVERRIDE {
267     inserted_text_ = text;
268   }
269   virtual void InsertChar(base::char16 ch, int flags) OVERRIDE {
270     inserted_char_ = ch;
271     inserted_char_flags_ = flags;
272   }
273   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE {
274     return static_cast<gfx::NativeWindow>(NULL);
275   }
276   virtual TextInputType GetTextInputType() const OVERRIDE {
277     return input_type_;
278   }
279   virtual TextInputMode GetTextInputMode() const OVERRIDE {
280     return input_mode_;
281   }
282   virtual bool CanComposeInline() const OVERRIDE {
283     return can_compose_inline_;
284   }
285   virtual gfx::Rect GetCaretBounds() const OVERRIDE {
286     return caret_bounds_;
287   }
288   virtual bool GetCompositionCharacterBounds(uint32 index,
289                                              gfx::Rect* rect) const OVERRIDE {
290     return false;
291   }
292   virtual bool HasCompositionText() const OVERRIDE {
293     CompositionText empty;
294     return composition_text_ != empty;
295   }
296   virtual bool GetTextRange(gfx::Range* range) const OVERRIDE {
297     *range = text_range_;
298     return true;
299   }
300   virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE {
301     return false;
302   }
303   virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE {
304     *range = selection_range_;
305     return true;
306   }
307
308   virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE {
309     return false;
310   }
311   virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; }
312   virtual bool GetTextFromRange(const gfx::Range& range,
313                                 base::string16* text) const OVERRIDE {
314     *text = surrounding_text_.substr(range.GetMin(), range.length());
315     return true;
316   }
317   virtual void OnInputMethodChanged() OVERRIDE {
318     ++on_input_method_changed_call_count_;
319   }
320   virtual bool ChangeTextDirectionAndLayoutAlignment(
321       base::i18n::TextDirection direction) OVERRIDE { return false; }
322   virtual void ExtendSelectionAndDelete(size_t before,
323                                         size_t after) OVERRIDE {}
324   virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE {}
325   virtual void OnCandidateWindowShown() OVERRIDE {}
326   virtual void OnCandidateWindowUpdated() OVERRIDE {}
327   virtual void OnCandidateWindowHidden() OVERRIDE {}
328   virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE {
329     return false;
330   }
331   virtual void ExecuteEditingCommand(int command_id) OVERRIDE {}
332
333   bool HasNativeEvent() const {
334     return dispatched_key_event_.HasNativeEvent();
335   }
336
337   void ResetFlags() {
338     dispatched_key_event_ = ui::KeyEvent(ui::ET_UNKNOWN, ui::VKEY_UNKNOWN,
339                                          ui::EF_NONE);
340
341     composition_text_.Clear();
342     confirmed_text_.Clear();
343     inserted_text_.clear();
344     inserted_char_ = 0;
345     inserted_char_flags_ = 0;
346     on_input_method_changed_call_count_ = 0;
347
348     input_type_ = TEXT_INPUT_TYPE_NONE;
349     input_mode_ = TEXT_INPUT_MODE_DEFAULT;
350     can_compose_inline_ = true;
351     caret_bounds_ = gfx::Rect();
352   }
353
354   scoped_ptr<TestableInputMethodChromeOS> ime_;
355
356   // Copy of the dispatched key event.
357   ui::KeyEvent dispatched_key_event_;
358
359   // Variables for remembering the parameters that are passed to
360   // ui::TextInputClient functions.
361   CompositionText composition_text_;
362   CompositionText confirmed_text_;
363   base::string16 inserted_text_;
364   base::char16 inserted_char_;
365   unsigned int on_input_method_changed_call_count_;
366   int inserted_char_flags_;
367
368   // Variables that will be returned from the ui::TextInputClient functions.
369   TextInputType input_type_;
370   TextInputMode input_mode_;
371   bool can_compose_inline_;
372   gfx::Rect caret_bounds_;
373   gfx::Range text_range_;
374   gfx::Range selection_range_;
375   base::string16 surrounding_text_;
376
377   scoped_ptr<chromeos::MockIMEEngineHandler> mock_ime_engine_handler_;
378   scoped_ptr<chromeos::MockIMECandidateWindowHandler>
379       mock_ime_candidate_window_handler_;
380
381   DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSTest);
382 };
383
384 // Tests public APIs in ui::InputMethod first.
385
386 TEST_F(InputMethodChromeOSTest, GetInputLocale) {
387   // ui::InputMethodChromeOS does not support the API.
388   ime_->Init(true);
389   EXPECT_EQ("", ime_->GetInputLocale());
390 }
391
392 TEST_F(InputMethodChromeOSTest, IsActive) {
393   ime_->Init(true);
394   // ui::InputMethodChromeOS always returns true.
395   EXPECT_TRUE(ime_->IsActive());
396 }
397
398 TEST_F(InputMethodChromeOSTest, GetInputTextType) {
399   ime_->Init(true);
400   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
401   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
402   ime_->OnTextInputTypeChanged(this);
403   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
404   input_type_ = TEXT_INPUT_TYPE_TEXT;
405   ime_->OnTextInputTypeChanged(this);
406   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT, ime_->GetTextInputType());
407 }
408
409 TEST_F(InputMethodChromeOSTest, CanComposeInline) {
410   ime_->Init(true);
411   EXPECT_TRUE(ime_->CanComposeInline());
412   can_compose_inline_ = false;
413   ime_->OnTextInputTypeChanged(this);
414   EXPECT_FALSE(ime_->CanComposeInline());
415 }
416
417 TEST_F(InputMethodChromeOSTest, GetTextInputClient) {
418   ime_->Init(true);
419   EXPECT_EQ(this, ime_->GetTextInputClient());
420   if (switches::IsTextInputFocusManagerEnabled())
421     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
422   else
423     ime_->SetFocusedTextInputClient(NULL);
424   EXPECT_EQ(NULL, ime_->GetTextInputClient());
425 }
426
427 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedClient) {
428   ime_->Init(true);
429   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
430   if (switches::IsTextInputFocusManagerEnabled())
431     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
432   else
433     ime_->SetFocusedTextInputClient(NULL);
434   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
435   ime_->OnTextInputTypeChanged(this);
436   // The OnTextInputTypeChanged() call above should be ignored since |this| is
437   // not the current focused client.
438   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
439
440   if (switches::IsTextInputFocusManagerEnabled())
441     TextInputFocusManager::GetInstance()->FocusTextInputClient(this);
442   else
443     ime_->SetFocusedTextInputClient(this);
444   ime_->OnTextInputTypeChanged(this);
445   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
446 }
447
448 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedWindow) {
449   ime_->Init(true);
450   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
451   if (switches::IsTextInputFocusManagerEnabled())
452     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
453   else
454     ime_->OnBlur();
455   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
456   ime_->OnTextInputTypeChanged(this);
457   // The OnTextInputTypeChanged() call above should be ignored since the top-
458   // level window which the ime_ is attached to is not currently focused.
459   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
460
461   if (switches::IsTextInputFocusManagerEnabled())
462     TextInputFocusManager::GetInstance()->FocusTextInputClient(this);
463   else
464     ime_->OnFocus();
465   ime_->OnTextInputTypeChanged(this);
466   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
467 }
468
469 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedWindow2) {
470   // We no longer support the case that |ime_->Init(false)| because no one
471   // actually uses it.
472   if (switches::IsTextInputFocusManagerEnabled())
473     return;
474
475   ime_->Init(false);  // the top-level is initially unfocused.
476   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
477   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
478   ime_->OnTextInputTypeChanged(this);
479   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
480
481   ime_->OnFocus();
482   ime_->OnTextInputTypeChanged(this);
483   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
484 }
485
486 // Confirm that IBusClient::FocusIn is called on "connected" if input_type_ is
487 // TEXT.
488 TEST_F(InputMethodChromeOSTest, FocusIn_Text) {
489   ime_->Init(true);
490   // A context shouldn't be created since the daemon is not running.
491   EXPECT_EQ(0U, on_input_method_changed_call_count_);
492   // Click a text input form.
493   input_type_ = TEXT_INPUT_TYPE_TEXT;
494   ime_->OnTextInputTypeChanged(this);
495   // Since a form has focus, IBusClient::FocusIn() should be called.
496   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
497   EXPECT_EQ(
498       1,
499       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
500   // ui::TextInputClient::OnInputMethodChanged() should be called when
501   // ui::InputMethodChromeOS connects/disconnects to/from ibus-daemon and the
502   // current text input type is not NONE.
503   EXPECT_EQ(1U, on_input_method_changed_call_count_);
504 }
505
506 // Confirm that InputMethodEngine::FocusIn is called on "connected" even if
507 // input_type_ is PASSWORD.
508 TEST_F(InputMethodChromeOSTest, FocusIn_Password) {
509   ime_->Init(true);
510   EXPECT_EQ(0U, on_input_method_changed_call_count_);
511   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
512   ime_->OnTextInputTypeChanged(this);
513   // InputMethodEngine::FocusIn() should be called even for password field.
514   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
515   EXPECT_EQ(1U, on_input_method_changed_call_count_);
516 }
517
518 // Confirm that IBusClient::FocusOut is called as expected.
519 TEST_F(InputMethodChromeOSTest, FocusOut_None) {
520   input_type_ = TEXT_INPUT_TYPE_TEXT;
521   ime_->Init(true);
522   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
523   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
524   input_type_ = TEXT_INPUT_TYPE_NONE;
525   ime_->OnTextInputTypeChanged(this);
526   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
527   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
528 }
529
530 // Confirm that IBusClient::FocusOut is called as expected.
531 TEST_F(InputMethodChromeOSTest, FocusOut_Password) {
532   input_type_ = TEXT_INPUT_TYPE_TEXT;
533   ime_->Init(true);
534   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
535   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
536   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
537   ime_->OnTextInputTypeChanged(this);
538   EXPECT_EQ(2, mock_ime_engine_handler_->focus_in_call_count());
539   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
540 }
541
542 // FocusIn/FocusOut scenario test
543 TEST_F(InputMethodChromeOSTest, Focus_Scenario) {
544   ime_->Init(true);
545   // Confirm that both FocusIn and FocusOut are NOT called.
546   EXPECT_EQ(0, mock_ime_engine_handler_->focus_in_call_count());
547   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
548   EXPECT_EQ(TEXT_INPUT_TYPE_NONE,
549             mock_ime_engine_handler_->last_text_input_context().type);
550   EXPECT_EQ(TEXT_INPUT_MODE_DEFAULT,
551             mock_ime_engine_handler_->last_text_input_context().mode);
552
553   input_type_ = TEXT_INPUT_TYPE_TEXT;
554   input_mode_ = TEXT_INPUT_MODE_LATIN;
555   ime_->OnTextInputTypeChanged(this);
556   // Confirm that only FocusIn is called, the TextInputType is TEXT and the
557   // TextInputMode is LATIN..
558   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
559   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
560   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
561             mock_ime_engine_handler_->last_text_input_context().type);
562   EXPECT_EQ(TEXT_INPUT_MODE_LATIN,
563             mock_ime_engine_handler_->last_text_input_context().mode);
564
565   input_mode_ = TEXT_INPUT_MODE_KANA;
566   ime_->OnTextInputTypeChanged(this);
567   // Confirm that both FocusIn and FocusOut are called for mode change.
568   EXPECT_EQ(2, mock_ime_engine_handler_->focus_in_call_count());
569   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
570   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
571             mock_ime_engine_handler_->last_text_input_context().type);
572   EXPECT_EQ(TEXT_INPUT_MODE_KANA,
573             mock_ime_engine_handler_->last_text_input_context().mode);
574
575   input_type_ = TEXT_INPUT_TYPE_URL;
576   ime_->OnTextInputTypeChanged(this);
577   // Confirm that both FocusIn and FocusOut are called and the TextInputType is
578   // changed to URL.
579   EXPECT_EQ(3, mock_ime_engine_handler_->focus_in_call_count());
580   EXPECT_EQ(2, mock_ime_engine_handler_->focus_out_call_count());
581   EXPECT_EQ(TEXT_INPUT_TYPE_URL,
582             mock_ime_engine_handler_->last_text_input_context().type);
583   EXPECT_EQ(TEXT_INPUT_MODE_KANA,
584             mock_ime_engine_handler_->last_text_input_context().mode);
585
586   // When IsTextInputFocusManagerEnabled, InputMethod::SetFocusedTextInputClient
587   // is not supported and it's no-op.
588   if (switches::IsTextInputFocusManagerEnabled())
589     return;
590   // Confirm that FocusOut is called when set focus to NULL client.
591   ime_->SetFocusedTextInputClient(NULL);
592   EXPECT_EQ(3, mock_ime_engine_handler_->focus_in_call_count());
593   EXPECT_EQ(3, mock_ime_engine_handler_->focus_out_call_count());
594   // Confirm that FocusIn is called when set focus to this client.
595   ime_->SetFocusedTextInputClient(this);
596   EXPECT_EQ(4, mock_ime_engine_handler_->focus_in_call_count());
597   EXPECT_EQ(3, mock_ime_engine_handler_->focus_out_call_count());
598 }
599
600 // Test if the new |caret_bounds_| is correctly sent to ibus-daemon.
601 TEST_F(InputMethodChromeOSTest, OnCaretBoundsChanged) {
602   input_type_ = TEXT_INPUT_TYPE_TEXT;
603   ime_->Init(true);
604   EXPECT_EQ(
605       1,
606       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
607   caret_bounds_ = gfx::Rect(1, 2, 3, 4);
608   ime_->OnCaretBoundsChanged(this);
609   EXPECT_EQ(
610       2,
611       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
612   caret_bounds_ = gfx::Rect(0, 2, 3, 4);
613   ime_->OnCaretBoundsChanged(this);
614   EXPECT_EQ(
615       3,
616       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
617   caret_bounds_ = gfx::Rect(0, 2, 3, 4);  // unchanged
618   ime_->OnCaretBoundsChanged(this);
619   // Current InputMethodChromeOS implementation performs the IPC
620   // regardless of the bounds are changed or not.
621   EXPECT_EQ(
622       4,
623       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
624 }
625
626 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_NoAttribute) {
627   const base::string16 kSampleAsciiText = UTF8ToUTF16("Sample Text");
628   const uint32 kCursorPos = 2UL;
629
630   chromeos::CompositionText chromeos_composition_text;
631   chromeos_composition_text.set_text(kSampleAsciiText);
632
633   CompositionText composition_text;
634   ime_->ExtractCompositionText(
635       chromeos_composition_text, kCursorPos, &composition_text);
636   EXPECT_EQ(kSampleAsciiText, composition_text.text);
637   // If there is no selection, |selection| represents cursor position.
638   EXPECT_EQ(kCursorPos, composition_text.selection.start());
639   EXPECT_EQ(kCursorPos, composition_text.selection.end());
640   // If there is no underline, |underlines| contains one underline and it is
641   // whole text underline.
642   ASSERT_EQ(1UL, composition_text.underlines.size());
643   EXPECT_EQ(0UL, composition_text.underlines[0].start_offset);
644   EXPECT_EQ(kSampleAsciiText.size(), composition_text.underlines[0].end_offset);
645   EXPECT_FALSE(composition_text.underlines[0].thick);
646 }
647
648 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_SingleUnderline) {
649   const uint32 kCursorPos = 2UL;
650
651   // Set up chromeos composition text with one underline attribute.
652   chromeos::CompositionText chromeos_composition_text;
653   chromeos_composition_text.set_text(kSampleText);
654   chromeos::CompositionText::UnderlineAttribute underline;
655   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE;
656   underline.start_index = 1UL;
657   underline.end_index = 4UL;
658   chromeos_composition_text.mutable_underline_attributes()->push_back(
659       underline);
660
661   CompositionText composition_text;
662   ime_->ExtractCompositionText(
663       chromeos_composition_text, kCursorPos, &composition_text);
664   EXPECT_EQ(kSampleText, composition_text.text);
665   // If there is no selection, |selection| represents cursor position.
666   EXPECT_EQ(kCursorPos, composition_text.selection.start());
667   EXPECT_EQ(kCursorPos, composition_text.selection.end());
668   ASSERT_EQ(1UL, composition_text.underlines.size());
669   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
670             composition_text.underlines[0].start_offset);
671   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
672             composition_text.underlines[0].end_offset);
673   // Single underline represents as black thin line.
674   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
675   EXPECT_FALSE(composition_text.underlines[0].thick);
676   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
677             composition_text.underlines[0].background_color);
678 }
679
680 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_DoubleUnderline) {
681   const uint32 kCursorPos = 2UL;
682
683   // Set up chromeos composition text with one underline attribute.
684   chromeos::CompositionText chromeos_composition_text;
685   chromeos_composition_text.set_text(kSampleText);
686   chromeos::CompositionText::UnderlineAttribute underline;
687   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE;
688   underline.start_index = 1UL;
689   underline.end_index = 4UL;
690   chromeos_composition_text.mutable_underline_attributes()->push_back(
691       underline);
692
693   CompositionText composition_text;
694   ime_->ExtractCompositionText(
695       chromeos_composition_text, kCursorPos, &composition_text);
696   EXPECT_EQ(kSampleText, composition_text.text);
697   // If there is no selection, |selection| represents cursor position.
698   EXPECT_EQ(kCursorPos, composition_text.selection.start());
699   EXPECT_EQ(kCursorPos, composition_text.selection.end());
700   ASSERT_EQ(1UL, composition_text.underlines.size());
701   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
702             composition_text.underlines[0].start_offset);
703   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
704             composition_text.underlines[0].end_offset);
705   // Double underline represents as black thick line.
706   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
707   EXPECT_TRUE(composition_text.underlines[0].thick);
708   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
709             composition_text.underlines[0].background_color);
710 }
711
712 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_ErrorUnderline) {
713   const uint32 kCursorPos = 2UL;
714
715   // Set up chromeos composition text with one underline attribute.
716   chromeos::CompositionText chromeos_composition_text;
717   chromeos_composition_text.set_text(kSampleText);
718   chromeos::CompositionText::UnderlineAttribute underline;
719   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_ERROR;
720   underline.start_index = 1UL;
721   underline.end_index = 4UL;
722   chromeos_composition_text.mutable_underline_attributes()->push_back(
723       underline);
724
725   CompositionText composition_text;
726   ime_->ExtractCompositionText(
727       chromeos_composition_text, kCursorPos, &composition_text);
728   EXPECT_EQ(kSampleText, composition_text.text);
729   EXPECT_EQ(kCursorPos, composition_text.selection.start());
730   EXPECT_EQ(kCursorPos, composition_text.selection.end());
731   ASSERT_EQ(1UL, composition_text.underlines.size());
732   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
733             composition_text.underlines[0].start_offset);
734   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
735             composition_text.underlines[0].end_offset);
736   // Error underline represents as red thin line.
737   EXPECT_EQ(SK_ColorRED, composition_text.underlines[0].color);
738   EXPECT_FALSE(composition_text.underlines[0].thick);
739 }
740
741 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_Selection) {
742   const uint32 kCursorPos = 2UL;
743
744   // Set up chromeos composition text with one underline attribute.
745   chromeos::CompositionText chromeos_composition_text;
746   chromeos_composition_text.set_text(kSampleText);
747   chromeos_composition_text.set_selection_start(1UL);
748   chromeos_composition_text.set_selection_end(4UL);
749
750   CompositionText composition_text;
751   ime_->ExtractCompositionText(
752       chromeos_composition_text, kCursorPos, &composition_text);
753   EXPECT_EQ(kSampleText, composition_text.text);
754   EXPECT_EQ(kCursorPos, composition_text.selection.start());
755   EXPECT_EQ(kCursorPos, composition_text.selection.end());
756   ASSERT_EQ(1UL, composition_text.underlines.size());
757   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
758                              chromeos_composition_text.selection_start()),
759             composition_text.underlines[0].start_offset);
760   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
761                              chromeos_composition_text.selection_end()),
762             composition_text.underlines[0].end_offset);
763   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
764   EXPECT_TRUE(composition_text.underlines[0].thick);
765   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
766             composition_text.underlines[0].background_color);
767 }
768
769 TEST_F(InputMethodChromeOSTest,
770        ExtractCompositionTextTest_SelectionStartWithCursor) {
771   const uint32 kCursorPos = 1UL;
772
773   // Set up chromeos composition text with one underline attribute.
774   chromeos::CompositionText chromeos_composition_text;
775   chromeos_composition_text.set_text(kSampleText);
776   chromeos_composition_text.set_selection_start(kCursorPos);
777   chromeos_composition_text.set_selection_end(4UL);
778
779   CompositionText composition_text;
780   ime_->ExtractCompositionText(
781       chromeos_composition_text, kCursorPos, &composition_text);
782   EXPECT_EQ(kSampleText, composition_text.text);
783   // If the cursor position is same as selection bounds, selection start
784   // position become opposit side of selection from cursor.
785   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
786                              chromeos_composition_text.selection_end()),
787             composition_text.selection.start());
788   EXPECT_EQ(GetOffsetInUTF16(kSampleText, kCursorPos),
789             composition_text.selection.end());
790   ASSERT_EQ(1UL, composition_text.underlines.size());
791   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
792                              chromeos_composition_text.selection_start()),
793             composition_text.underlines[0].start_offset);
794   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
795                              chromeos_composition_text.selection_end()),
796             composition_text.underlines[0].end_offset);
797   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
798   EXPECT_TRUE(composition_text.underlines[0].thick);
799   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
800             composition_text.underlines[0].background_color);
801 }
802
803 TEST_F(InputMethodChromeOSTest,
804        ExtractCompositionTextTest_SelectionEndWithCursor) {
805   const uint32 kCursorPos = 4UL;
806
807   // Set up chromeos composition text with one underline attribute.
808   chromeos::CompositionText chromeos_composition_text;
809   chromeos_composition_text.set_text(kSampleText);
810   chromeos_composition_text.set_selection_start(1UL);
811   chromeos_composition_text.set_selection_end(kCursorPos);
812
813   CompositionText composition_text;
814   ime_->ExtractCompositionText(
815       chromeos_composition_text, kCursorPos, &composition_text);
816   EXPECT_EQ(kSampleText, composition_text.text);
817   // If the cursor position is same as selection bounds, selection start
818   // position become opposit side of selection from cursor.
819   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
820                              chromeos_composition_text.selection_start()),
821             composition_text.selection.start());
822   EXPECT_EQ(GetOffsetInUTF16(kSampleText, kCursorPos),
823             composition_text.selection.end());
824   ASSERT_EQ(1UL, composition_text.underlines.size());
825   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
826                              chromeos_composition_text.selection_start()),
827             composition_text.underlines[0].start_offset);
828   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
829                              chromeos_composition_text.selection_end()),
830             composition_text.underlines[0].end_offset);
831   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
832   EXPECT_TRUE(composition_text.underlines[0].thick);
833   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
834             composition_text.underlines[0].background_color);
835 }
836
837 TEST_F(InputMethodChromeOSTest, SurroundingText_NoSelectionTest) {
838   ime_->Init(true);
839   // Click a text input form.
840   input_type_ = TEXT_INPUT_TYPE_TEXT;
841   ime_->OnTextInputTypeChanged(this);
842
843   // Set the TextInputClient behaviors.
844   surrounding_text_ = UTF8ToUTF16("abcdef");
845   text_range_ = gfx::Range(0, 6);
846   selection_range_ = gfx::Range(3, 3);
847
848   // Set the verifier for SetSurroundingText mock call.
849   SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 3, 3);
850
851
852   ime_->OnCaretBoundsChanged(this);
853
854   // Check the call count.
855   EXPECT_EQ(1,
856             mock_ime_engine_handler_->set_surrounding_text_call_count());
857   EXPECT_EQ(UTF16ToUTF8(surrounding_text_),
858             mock_ime_engine_handler_->last_set_surrounding_text());
859   EXPECT_EQ(3U,
860             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
861   EXPECT_EQ(3U,
862             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
863 }
864
865 TEST_F(InputMethodChromeOSTest, SurroundingText_SelectionTest) {
866   ime_->Init(true);
867   // Click a text input form.
868   input_type_ = TEXT_INPUT_TYPE_TEXT;
869   ime_->OnTextInputTypeChanged(this);
870
871   // Set the TextInputClient behaviors.
872   surrounding_text_ = UTF8ToUTF16("abcdef");
873   text_range_ = gfx::Range(0, 6);
874   selection_range_ = gfx::Range(2, 5);
875
876   // Set the verifier for SetSurroundingText mock call.
877   SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 2, 5);
878
879   ime_->OnCaretBoundsChanged(this);
880
881   // Check the call count.
882   EXPECT_EQ(1,
883             mock_ime_engine_handler_->set_surrounding_text_call_count());
884   EXPECT_EQ(UTF16ToUTF8(surrounding_text_),
885             mock_ime_engine_handler_->last_set_surrounding_text());
886   EXPECT_EQ(2U,
887             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
888   EXPECT_EQ(5U,
889             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
890 }
891
892 TEST_F(InputMethodChromeOSTest, SurroundingText_PartialText) {
893   ime_->Init(true);
894   // Click a text input form.
895   input_type_ = TEXT_INPUT_TYPE_TEXT;
896   ime_->OnTextInputTypeChanged(this);
897
898   // Set the TextInputClient behaviors.
899   surrounding_text_ = UTF8ToUTF16("abcdefghij");
900   text_range_ = gfx::Range(5, 10);
901   selection_range_ = gfx::Range(7, 9);
902
903   ime_->OnCaretBoundsChanged(this);
904
905   // Check the call count.
906   EXPECT_EQ(1,
907             mock_ime_engine_handler_->set_surrounding_text_call_count());
908   // Set the verifier for SetSurroundingText mock call.
909   // Here (2, 4) is selection range in expected surrounding text coordinates.
910   EXPECT_EQ("fghij",
911             mock_ime_engine_handler_->last_set_surrounding_text());
912   EXPECT_EQ(2U,
913             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
914   EXPECT_EQ(4U,
915             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
916 }
917
918 TEST_F(InputMethodChromeOSTest, SurroundingText_BecomeEmptyText) {
919   ime_->Init(true);
920   // Click a text input form.
921   input_type_ = TEXT_INPUT_TYPE_TEXT;
922   ime_->OnTextInputTypeChanged(this);
923
924   // Set the TextInputClient behaviors.
925   // If the surrounding text becomes empty, text_range become (0, 0) and
926   // selection range become invalid.
927   surrounding_text_ = UTF8ToUTF16("");
928   text_range_ = gfx::Range(0, 0);
929   selection_range_ = gfx::Range::InvalidRange();
930
931   ime_->OnCaretBoundsChanged(this);
932
933   // Check the call count.
934   EXPECT_EQ(0,
935             mock_ime_engine_handler_->set_surrounding_text_call_count());
936
937   // Should not be called twice with same condition.
938   ime_->OnCaretBoundsChanged(this);
939   EXPECT_EQ(0,
940             mock_ime_engine_handler_->set_surrounding_text_call_count());
941 }
942
943 class InputMethodChromeOSKeyEventTest : public InputMethodChromeOSTest {
944  public:
945   InputMethodChromeOSKeyEventTest() {}
946   virtual ~InputMethodChromeOSKeyEventTest() {}
947
948   virtual void SetUp() OVERRIDE {
949     InputMethodChromeOSTest::SetUp();
950     ime_->Init(true);
951   }
952
953   DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSKeyEventTest);
954 };
955
956 TEST_F(InputMethodChromeOSKeyEventTest, KeyEventDelayResponseTest) {
957   const int kFlags = ui::EF_SHIFT_DOWN;
958   ScopedXI2Event xevent;
959   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, kFlags);
960   const ui::KeyEvent event(xevent);
961
962   // Do key event.
963   input_type_ = TEXT_INPUT_TYPE_TEXT;
964   ime_->OnTextInputTypeChanged(this);
965   ime_->DispatchKeyEvent(event);
966
967   // Check before state.
968   const ui::KeyEvent* key_event =
969       mock_ime_engine_handler_->last_processed_key_event();
970   EXPECT_EQ(1, mock_ime_engine_handler_->process_key_event_call_count());
971   EXPECT_EQ(ui::VKEY_A, key_event->key_code());
972   EXPECT_EQ("KeyA", key_event->code());
973   EXPECT_EQ(kFlags, key_event->flags());
974   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
975
976   // Do callback.
977   mock_ime_engine_handler_->last_passed_callback().Run(true);
978
979   // Check the results
980   EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count());
981   const ui::KeyEvent* stored_event =
982       ime_->process_key_event_post_ime_args().event;
983   EXPECT_TRUE(stored_event->HasNativeEvent());
984   EXPECT_TRUE(IsEqualXKeyEvent(*xevent, *(stored_event->native_event())));
985   EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled);
986 }
987
988 TEST_F(InputMethodChromeOSKeyEventTest, MultiKeyEventDelayResponseTest) {
989   // Preparation
990   input_type_ = TEXT_INPUT_TYPE_TEXT;
991   ime_->OnTextInputTypeChanged(this);
992
993   const int kFlags = ui::EF_SHIFT_DOWN;
994   ScopedXI2Event xevent;
995   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_B, kFlags);
996   const ui::KeyEvent event(xevent);
997
998   // Do key event.
999   ime_->DispatchKeyEvent(event);
1000   const ui::KeyEvent* key_event =
1001       mock_ime_engine_handler_->last_processed_key_event();
1002   EXPECT_EQ(ui::VKEY_B, key_event->key_code());
1003   EXPECT_EQ("KeyB", key_event->code());
1004   EXPECT_EQ(kFlags, key_event->flags());
1005
1006   KeyEventCallback first_callback =
1007       mock_ime_engine_handler_->last_passed_callback();
1008
1009   // Do key event again.
1010   ScopedXI2Event xevent2;
1011   xevent2.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_C, kFlags);
1012   const ui::KeyEvent event2(xevent2);
1013
1014   ime_->DispatchKeyEvent(event2);
1015   const ui::KeyEvent* key_event2 =
1016       mock_ime_engine_handler_->last_processed_key_event();
1017   EXPECT_EQ(ui::VKEY_C, key_event2->key_code());
1018   EXPECT_EQ("KeyC", key_event2->code());
1019   EXPECT_EQ(kFlags, key_event2->flags());
1020
1021   // Check before state.
1022   EXPECT_EQ(2,
1023             mock_ime_engine_handler_->process_key_event_call_count());
1024   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1025
1026   // Do callback for first key event.
1027   first_callback.Run(true);
1028
1029   // Check the results for first key event.
1030   EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count());
1031   const ui::KeyEvent* stored_event =
1032       ime_->process_key_event_post_ime_args().event;
1033   EXPECT_TRUE(stored_event->HasNativeEvent());
1034   EXPECT_TRUE(IsEqualXKeyEvent(*xevent, *(stored_event->native_event())));
1035   EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled);
1036
1037   // Do callback for second key event.
1038   mock_ime_engine_handler_->last_passed_callback().Run(false);
1039
1040   // Check the results for second key event.
1041   EXPECT_EQ(2, ime_->process_key_event_post_ime_call_count());
1042   stored_event = ime_->process_key_event_post_ime_args().event;
1043   EXPECT_TRUE(stored_event->HasNativeEvent());
1044   EXPECT_TRUE(IsEqualXKeyEvent(*xevent2, *(stored_event->native_event())));
1045   EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled);
1046 }
1047
1048 TEST_F(InputMethodChromeOSKeyEventTest, KeyEventDelayResponseResetTest) {
1049   ScopedXI2Event xevent;
1050   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_SHIFT_DOWN);
1051   const ui::KeyEvent event(xevent);
1052
1053   // Do key event.
1054   input_type_ = TEXT_INPUT_TYPE_TEXT;
1055   ime_->OnTextInputTypeChanged(this);
1056   ime_->DispatchKeyEvent(event);
1057
1058   // Check before state.
1059   EXPECT_EQ(1, mock_ime_engine_handler_->process_key_event_call_count());
1060   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1061
1062   ime_->ResetContext();
1063
1064   // Do callback.
1065   mock_ime_engine_handler_->last_passed_callback().Run(true);
1066
1067   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1068 }
1069 // TODO(nona): Introduce ProcessKeyEventPostIME tests(crbug.com/156593).
1070
1071 }  // namespace ui