Upstream version 11.40.277.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 int GetTextInputFlags() const override {
283     return 0;
284   }
285   virtual bool CanComposeInline() const override {
286     return can_compose_inline_;
287   }
288   virtual gfx::Rect GetCaretBounds() const override {
289     return caret_bounds_;
290   }
291   virtual bool GetCompositionCharacterBounds(uint32 index,
292                                              gfx::Rect* rect) const override {
293     return false;
294   }
295   virtual bool HasCompositionText() const override {
296     CompositionText empty;
297     return composition_text_ != empty;
298   }
299   virtual bool GetTextRange(gfx::Range* range) const override {
300     *range = text_range_;
301     return true;
302   }
303   virtual bool GetCompositionTextRange(gfx::Range* range) const override {
304     return false;
305   }
306   virtual bool GetSelectionRange(gfx::Range* range) const override {
307     *range = selection_range_;
308     return true;
309   }
310
311   virtual bool SetSelectionRange(const gfx::Range& range) override {
312     return false;
313   }
314   virtual bool DeleteRange(const gfx::Range& range) override { return false; }
315   virtual bool GetTextFromRange(const gfx::Range& range,
316                                 base::string16* text) const override {
317     *text = surrounding_text_.substr(range.GetMin(), range.length());
318     return true;
319   }
320   virtual void OnInputMethodChanged() override {
321     ++on_input_method_changed_call_count_;
322   }
323   virtual bool ChangeTextDirectionAndLayoutAlignment(
324       base::i18n::TextDirection direction) override { return false; }
325   virtual void ExtendSelectionAndDelete(size_t before,
326                                         size_t after) override {}
327   virtual void EnsureCaretInRect(const gfx::Rect& rect) override {}
328   virtual void OnCandidateWindowShown() override {}
329   virtual void OnCandidateWindowUpdated() override {}
330   virtual void OnCandidateWindowHidden() override {}
331   virtual bool IsEditingCommandEnabled(int command_id) override {
332     return false;
333   }
334   virtual void ExecuteEditingCommand(int command_id) override {}
335
336   bool HasNativeEvent() const {
337     return dispatched_key_event_.HasNativeEvent();
338   }
339
340   void ResetFlags() {
341     dispatched_key_event_ = ui::KeyEvent(ui::ET_UNKNOWN, ui::VKEY_UNKNOWN,
342                                          ui::EF_NONE);
343
344     composition_text_.Clear();
345     confirmed_text_.Clear();
346     inserted_text_.clear();
347     inserted_char_ = 0;
348     inserted_char_flags_ = 0;
349     on_input_method_changed_call_count_ = 0;
350
351     input_type_ = TEXT_INPUT_TYPE_NONE;
352     input_mode_ = TEXT_INPUT_MODE_DEFAULT;
353     can_compose_inline_ = true;
354     caret_bounds_ = gfx::Rect();
355   }
356
357   scoped_ptr<TestableInputMethodChromeOS> ime_;
358
359   // Copy of the dispatched key event.
360   ui::KeyEvent dispatched_key_event_;
361
362   // Variables for remembering the parameters that are passed to
363   // ui::TextInputClient functions.
364   CompositionText composition_text_;
365   CompositionText confirmed_text_;
366   base::string16 inserted_text_;
367   base::char16 inserted_char_;
368   unsigned int on_input_method_changed_call_count_;
369   int inserted_char_flags_;
370
371   // Variables that will be returned from the ui::TextInputClient functions.
372   TextInputType input_type_;
373   TextInputMode input_mode_;
374   bool can_compose_inline_;
375   gfx::Rect caret_bounds_;
376   gfx::Range text_range_;
377   gfx::Range selection_range_;
378   base::string16 surrounding_text_;
379
380   scoped_ptr<chromeos::MockIMEEngineHandler> mock_ime_engine_handler_;
381   scoped_ptr<chromeos::MockIMECandidateWindowHandler>
382       mock_ime_candidate_window_handler_;
383
384   DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSTest);
385 };
386
387 // Tests public APIs in ui::InputMethod first.
388
389 TEST_F(InputMethodChromeOSTest, GetInputLocale) {
390   // ui::InputMethodChromeOS does not support the API.
391   ime_->Init(true);
392   EXPECT_EQ("", ime_->GetInputLocale());
393 }
394
395 TEST_F(InputMethodChromeOSTest, IsActive) {
396   ime_->Init(true);
397   // ui::InputMethodChromeOS always returns true.
398   EXPECT_TRUE(ime_->IsActive());
399 }
400
401 TEST_F(InputMethodChromeOSTest, GetInputTextType) {
402   ime_->Init(true);
403   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
404   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
405   ime_->OnTextInputTypeChanged(this);
406   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
407   input_type_ = TEXT_INPUT_TYPE_TEXT;
408   ime_->OnTextInputTypeChanged(this);
409   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT, ime_->GetTextInputType());
410 }
411
412 TEST_F(InputMethodChromeOSTest, CanComposeInline) {
413   ime_->Init(true);
414   EXPECT_TRUE(ime_->CanComposeInline());
415   can_compose_inline_ = false;
416   ime_->OnTextInputTypeChanged(this);
417   EXPECT_FALSE(ime_->CanComposeInline());
418 }
419
420 TEST_F(InputMethodChromeOSTest, GetTextInputClient) {
421   ime_->Init(true);
422   EXPECT_EQ(this, ime_->GetTextInputClient());
423   if (switches::IsTextInputFocusManagerEnabled())
424     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
425   else
426     ime_->SetFocusedTextInputClient(NULL);
427   EXPECT_EQ(NULL, ime_->GetTextInputClient());
428 }
429
430 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedClient) {
431   ime_->Init(true);
432   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
433   if (switches::IsTextInputFocusManagerEnabled())
434     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
435   else
436     ime_->SetFocusedTextInputClient(NULL);
437   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
438   ime_->OnTextInputTypeChanged(this);
439   // The OnTextInputTypeChanged() call above should be ignored since |this| is
440   // not the current focused client.
441   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
442
443   if (switches::IsTextInputFocusManagerEnabled())
444     TextInputFocusManager::GetInstance()->FocusTextInputClient(this);
445   else
446     ime_->SetFocusedTextInputClient(this);
447   ime_->OnTextInputTypeChanged(this);
448   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
449 }
450
451 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedWindow) {
452   ime_->Init(true);
453   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
454   if (switches::IsTextInputFocusManagerEnabled())
455     TextInputFocusManager::GetInstance()->BlurTextInputClient(this);
456   else
457     ime_->OnBlur();
458   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
459   ime_->OnTextInputTypeChanged(this);
460   // The OnTextInputTypeChanged() call above should be ignored since the top-
461   // level window which the ime_ is attached to is not currently focused.
462   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
463
464   if (switches::IsTextInputFocusManagerEnabled())
465     TextInputFocusManager::GetInstance()->FocusTextInputClient(this);
466   else
467     ime_->OnFocus();
468   ime_->OnTextInputTypeChanged(this);
469   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
470 }
471
472 TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedWindow2) {
473   // We no longer support the case that |ime_->Init(false)| because no one
474   // actually uses it.
475   if (switches::IsTextInputFocusManagerEnabled())
476     return;
477
478   ime_->Init(false);  // the top-level is initially unfocused.
479   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
480   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
481   ime_->OnTextInputTypeChanged(this);
482   EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
483
484   ime_->OnFocus();
485   ime_->OnTextInputTypeChanged(this);
486   EXPECT_EQ(TEXT_INPUT_TYPE_PASSWORD, ime_->GetTextInputType());
487 }
488
489 // Confirm that IBusClient::FocusIn is called on "connected" if input_type_ is
490 // TEXT.
491 TEST_F(InputMethodChromeOSTest, FocusIn_Text) {
492   ime_->Init(true);
493   // A context shouldn't be created since the daemon is not running.
494   EXPECT_EQ(0U, on_input_method_changed_call_count_);
495   // Click a text input form.
496   input_type_ = TEXT_INPUT_TYPE_TEXT;
497   ime_->OnTextInputTypeChanged(this);
498   // Since a form has focus, IBusClient::FocusIn() should be called.
499   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
500   EXPECT_EQ(
501       1,
502       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
503   // ui::TextInputClient::OnInputMethodChanged() should be called when
504   // ui::InputMethodChromeOS connects/disconnects to/from ibus-daemon and the
505   // current text input type is not NONE.
506   EXPECT_EQ(1U, on_input_method_changed_call_count_);
507 }
508
509 // Confirm that InputMethodEngine::FocusIn is called on "connected" even if
510 // input_type_ is PASSWORD.
511 TEST_F(InputMethodChromeOSTest, FocusIn_Password) {
512   ime_->Init(true);
513   EXPECT_EQ(0U, on_input_method_changed_call_count_);
514   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
515   ime_->OnTextInputTypeChanged(this);
516   // InputMethodEngine::FocusIn() should be called even for password field.
517   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
518   EXPECT_EQ(1U, on_input_method_changed_call_count_);
519 }
520
521 // Confirm that IBusClient::FocusOut is called as expected.
522 TEST_F(InputMethodChromeOSTest, FocusOut_None) {
523   input_type_ = TEXT_INPUT_TYPE_TEXT;
524   ime_->Init(true);
525   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
526   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
527   input_type_ = TEXT_INPUT_TYPE_NONE;
528   ime_->OnTextInputTypeChanged(this);
529   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
530   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
531 }
532
533 // Confirm that IBusClient::FocusOut is called as expected.
534 TEST_F(InputMethodChromeOSTest, FocusOut_Password) {
535   input_type_ = TEXT_INPUT_TYPE_TEXT;
536   ime_->Init(true);
537   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
538   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
539   input_type_ = TEXT_INPUT_TYPE_PASSWORD;
540   ime_->OnTextInputTypeChanged(this);
541   EXPECT_EQ(2, mock_ime_engine_handler_->focus_in_call_count());
542   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
543 }
544
545 // FocusIn/FocusOut scenario test
546 TEST_F(InputMethodChromeOSTest, Focus_Scenario) {
547   ime_->Init(true);
548   // Confirm that both FocusIn and FocusOut are NOT called.
549   EXPECT_EQ(0, mock_ime_engine_handler_->focus_in_call_count());
550   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
551   EXPECT_EQ(TEXT_INPUT_TYPE_NONE,
552             mock_ime_engine_handler_->last_text_input_context().type);
553   EXPECT_EQ(TEXT_INPUT_MODE_DEFAULT,
554             mock_ime_engine_handler_->last_text_input_context().mode);
555
556   input_type_ = TEXT_INPUT_TYPE_TEXT;
557   input_mode_ = TEXT_INPUT_MODE_LATIN;
558   ime_->OnTextInputTypeChanged(this);
559   // Confirm that only FocusIn is called, the TextInputType is TEXT and the
560   // TextInputMode is LATIN..
561   EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
562   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
563   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
564             mock_ime_engine_handler_->last_text_input_context().type);
565   EXPECT_EQ(TEXT_INPUT_MODE_LATIN,
566             mock_ime_engine_handler_->last_text_input_context().mode);
567
568   input_mode_ = TEXT_INPUT_MODE_KANA;
569   ime_->OnTextInputTypeChanged(this);
570   // Confirm that both FocusIn and FocusOut are called for mode change.
571   EXPECT_EQ(2, mock_ime_engine_handler_->focus_in_call_count());
572   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
573   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
574             mock_ime_engine_handler_->last_text_input_context().type);
575   EXPECT_EQ(TEXT_INPUT_MODE_KANA,
576             mock_ime_engine_handler_->last_text_input_context().mode);
577
578   input_type_ = TEXT_INPUT_TYPE_URL;
579   ime_->OnTextInputTypeChanged(this);
580   // Confirm that both FocusIn and FocusOut are called and the TextInputType is
581   // changed to URL.
582   EXPECT_EQ(3, mock_ime_engine_handler_->focus_in_call_count());
583   EXPECT_EQ(2, mock_ime_engine_handler_->focus_out_call_count());
584   EXPECT_EQ(TEXT_INPUT_TYPE_URL,
585             mock_ime_engine_handler_->last_text_input_context().type);
586   EXPECT_EQ(TEXT_INPUT_MODE_KANA,
587             mock_ime_engine_handler_->last_text_input_context().mode);
588
589   // When IsTextInputFocusManagerEnabled, InputMethod::SetFocusedTextInputClient
590   // is not supported and it's no-op.
591   if (switches::IsTextInputFocusManagerEnabled())
592     return;
593   // Confirm that FocusOut is called when set focus to NULL client.
594   ime_->SetFocusedTextInputClient(NULL);
595   EXPECT_EQ(3, mock_ime_engine_handler_->focus_in_call_count());
596   EXPECT_EQ(3, mock_ime_engine_handler_->focus_out_call_count());
597   // Confirm that FocusIn is called when set focus to this client.
598   ime_->SetFocusedTextInputClient(this);
599   EXPECT_EQ(4, mock_ime_engine_handler_->focus_in_call_count());
600   EXPECT_EQ(3, mock_ime_engine_handler_->focus_out_call_count());
601 }
602
603 // Test if the new |caret_bounds_| is correctly sent to ibus-daemon.
604 TEST_F(InputMethodChromeOSTest, OnCaretBoundsChanged) {
605   input_type_ = TEXT_INPUT_TYPE_TEXT;
606   ime_->Init(true);
607   EXPECT_EQ(
608       1,
609       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
610   caret_bounds_ = gfx::Rect(1, 2, 3, 4);
611   ime_->OnCaretBoundsChanged(this);
612   EXPECT_EQ(
613       2,
614       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
615   caret_bounds_ = gfx::Rect(0, 2, 3, 4);
616   ime_->OnCaretBoundsChanged(this);
617   EXPECT_EQ(
618       3,
619       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
620   caret_bounds_ = gfx::Rect(0, 2, 3, 4);  // unchanged
621   ime_->OnCaretBoundsChanged(this);
622   // Current InputMethodChromeOS implementation performs the IPC
623   // regardless of the bounds are changed or not.
624   EXPECT_EQ(
625       4,
626       mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
627 }
628
629 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_NoAttribute) {
630   const base::string16 kSampleAsciiText = UTF8ToUTF16("Sample Text");
631   const uint32 kCursorPos = 2UL;
632
633   chromeos::CompositionText chromeos_composition_text;
634   chromeos_composition_text.set_text(kSampleAsciiText);
635
636   CompositionText composition_text;
637   ime_->ExtractCompositionText(
638       chromeos_composition_text, kCursorPos, &composition_text);
639   EXPECT_EQ(kSampleAsciiText, composition_text.text);
640   // If there is no selection, |selection| represents cursor position.
641   EXPECT_EQ(kCursorPos, composition_text.selection.start());
642   EXPECT_EQ(kCursorPos, composition_text.selection.end());
643   // If there is no underline, |underlines| contains one underline and it is
644   // whole text underline.
645   ASSERT_EQ(1UL, composition_text.underlines.size());
646   EXPECT_EQ(0UL, composition_text.underlines[0].start_offset);
647   EXPECT_EQ(kSampleAsciiText.size(), composition_text.underlines[0].end_offset);
648   EXPECT_FALSE(composition_text.underlines[0].thick);
649 }
650
651 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_SingleUnderline) {
652   const uint32 kCursorPos = 2UL;
653
654   // Set up chromeos composition text with one underline attribute.
655   chromeos::CompositionText chromeos_composition_text;
656   chromeos_composition_text.set_text(kSampleText);
657   chromeos::CompositionText::UnderlineAttribute underline;
658   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE;
659   underline.start_index = 1UL;
660   underline.end_index = 4UL;
661   chromeos_composition_text.mutable_underline_attributes()->push_back(
662       underline);
663
664   CompositionText composition_text;
665   ime_->ExtractCompositionText(
666       chromeos_composition_text, kCursorPos, &composition_text);
667   EXPECT_EQ(kSampleText, composition_text.text);
668   // If there is no selection, |selection| represents cursor position.
669   EXPECT_EQ(kCursorPos, composition_text.selection.start());
670   EXPECT_EQ(kCursorPos, composition_text.selection.end());
671   ASSERT_EQ(1UL, composition_text.underlines.size());
672   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
673             composition_text.underlines[0].start_offset);
674   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
675             composition_text.underlines[0].end_offset);
676   // Single underline represents as black thin line.
677   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
678   EXPECT_FALSE(composition_text.underlines[0].thick);
679   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
680             composition_text.underlines[0].background_color);
681 }
682
683 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_DoubleUnderline) {
684   const uint32 kCursorPos = 2UL;
685
686   // Set up chromeos composition text with one underline attribute.
687   chromeos::CompositionText chromeos_composition_text;
688   chromeos_composition_text.set_text(kSampleText);
689   chromeos::CompositionText::UnderlineAttribute underline;
690   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE;
691   underline.start_index = 1UL;
692   underline.end_index = 4UL;
693   chromeos_composition_text.mutable_underline_attributes()->push_back(
694       underline);
695
696   CompositionText composition_text;
697   ime_->ExtractCompositionText(
698       chromeos_composition_text, kCursorPos, &composition_text);
699   EXPECT_EQ(kSampleText, composition_text.text);
700   // If there is no selection, |selection| represents cursor position.
701   EXPECT_EQ(kCursorPos, composition_text.selection.start());
702   EXPECT_EQ(kCursorPos, composition_text.selection.end());
703   ASSERT_EQ(1UL, composition_text.underlines.size());
704   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
705             composition_text.underlines[0].start_offset);
706   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
707             composition_text.underlines[0].end_offset);
708   // Double underline represents as black thick line.
709   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
710   EXPECT_TRUE(composition_text.underlines[0].thick);
711   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
712             composition_text.underlines[0].background_color);
713 }
714
715 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_ErrorUnderline) {
716   const uint32 kCursorPos = 2UL;
717
718   // Set up chromeos composition text with one underline attribute.
719   chromeos::CompositionText chromeos_composition_text;
720   chromeos_composition_text.set_text(kSampleText);
721   chromeos::CompositionText::UnderlineAttribute underline;
722   underline.type = chromeos::CompositionText::COMPOSITION_TEXT_UNDERLINE_ERROR;
723   underline.start_index = 1UL;
724   underline.end_index = 4UL;
725   chromeos_composition_text.mutable_underline_attributes()->push_back(
726       underline);
727
728   CompositionText composition_text;
729   ime_->ExtractCompositionText(
730       chromeos_composition_text, kCursorPos, &composition_text);
731   EXPECT_EQ(kSampleText, composition_text.text);
732   EXPECT_EQ(kCursorPos, composition_text.selection.start());
733   EXPECT_EQ(kCursorPos, composition_text.selection.end());
734   ASSERT_EQ(1UL, composition_text.underlines.size());
735   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.start_index),
736             composition_text.underlines[0].start_offset);
737   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_index),
738             composition_text.underlines[0].end_offset);
739   // Error underline represents as red thin line.
740   EXPECT_EQ(SK_ColorRED, composition_text.underlines[0].color);
741   EXPECT_FALSE(composition_text.underlines[0].thick);
742 }
743
744 TEST_F(InputMethodChromeOSTest, ExtractCompositionTextTest_Selection) {
745   const uint32 kCursorPos = 2UL;
746
747   // Set up chromeos composition text with one underline attribute.
748   chromeos::CompositionText chromeos_composition_text;
749   chromeos_composition_text.set_text(kSampleText);
750   chromeos_composition_text.set_selection_start(1UL);
751   chromeos_composition_text.set_selection_end(4UL);
752
753   CompositionText composition_text;
754   ime_->ExtractCompositionText(
755       chromeos_composition_text, kCursorPos, &composition_text);
756   EXPECT_EQ(kSampleText, composition_text.text);
757   EXPECT_EQ(kCursorPos, composition_text.selection.start());
758   EXPECT_EQ(kCursorPos, composition_text.selection.end());
759   ASSERT_EQ(1UL, composition_text.underlines.size());
760   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
761                              chromeos_composition_text.selection_start()),
762             composition_text.underlines[0].start_offset);
763   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
764                              chromeos_composition_text.selection_end()),
765             composition_text.underlines[0].end_offset);
766   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
767   EXPECT_TRUE(composition_text.underlines[0].thick);
768   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
769             composition_text.underlines[0].background_color);
770 }
771
772 TEST_F(InputMethodChromeOSTest,
773        ExtractCompositionTextTest_SelectionStartWithCursor) {
774   const uint32 kCursorPos = 1UL;
775
776   // Set up chromeos composition text with one underline attribute.
777   chromeos::CompositionText chromeos_composition_text;
778   chromeos_composition_text.set_text(kSampleText);
779   chromeos_composition_text.set_selection_start(kCursorPos);
780   chromeos_composition_text.set_selection_end(4UL);
781
782   CompositionText composition_text;
783   ime_->ExtractCompositionText(
784       chromeos_composition_text, kCursorPos, &composition_text);
785   EXPECT_EQ(kSampleText, composition_text.text);
786   // If the cursor position is same as selection bounds, selection start
787   // position become opposit side of selection from cursor.
788   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
789                              chromeos_composition_text.selection_end()),
790             composition_text.selection.start());
791   EXPECT_EQ(GetOffsetInUTF16(kSampleText, kCursorPos),
792             composition_text.selection.end());
793   ASSERT_EQ(1UL, composition_text.underlines.size());
794   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
795                              chromeos_composition_text.selection_start()),
796             composition_text.underlines[0].start_offset);
797   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
798                              chromeos_composition_text.selection_end()),
799             composition_text.underlines[0].end_offset);
800   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
801   EXPECT_TRUE(composition_text.underlines[0].thick);
802   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
803             composition_text.underlines[0].background_color);
804 }
805
806 TEST_F(InputMethodChromeOSTest,
807        ExtractCompositionTextTest_SelectionEndWithCursor) {
808   const uint32 kCursorPos = 4UL;
809
810   // Set up chromeos composition text with one underline attribute.
811   chromeos::CompositionText chromeos_composition_text;
812   chromeos_composition_text.set_text(kSampleText);
813   chromeos_composition_text.set_selection_start(1UL);
814   chromeos_composition_text.set_selection_end(kCursorPos);
815
816   CompositionText composition_text;
817   ime_->ExtractCompositionText(
818       chromeos_composition_text, kCursorPos, &composition_text);
819   EXPECT_EQ(kSampleText, composition_text.text);
820   // If the cursor position is same as selection bounds, selection start
821   // position become opposit side of selection from cursor.
822   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
823                              chromeos_composition_text.selection_start()),
824             composition_text.selection.start());
825   EXPECT_EQ(GetOffsetInUTF16(kSampleText, kCursorPos),
826             composition_text.selection.end());
827   ASSERT_EQ(1UL, composition_text.underlines.size());
828   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
829                              chromeos_composition_text.selection_start()),
830             composition_text.underlines[0].start_offset);
831   EXPECT_EQ(GetOffsetInUTF16(kSampleText,
832                              chromeos_composition_text.selection_end()),
833             composition_text.underlines[0].end_offset);
834   EXPECT_EQ(SK_ColorBLACK, composition_text.underlines[0].color);
835   EXPECT_TRUE(composition_text.underlines[0].thick);
836   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
837             composition_text.underlines[0].background_color);
838 }
839
840 TEST_F(InputMethodChromeOSTest, SurroundingText_NoSelectionTest) {
841   ime_->Init(true);
842   // Click a text input form.
843   input_type_ = TEXT_INPUT_TYPE_TEXT;
844   ime_->OnTextInputTypeChanged(this);
845
846   // Set the TextInputClient behaviors.
847   surrounding_text_ = UTF8ToUTF16("abcdef");
848   text_range_ = gfx::Range(0, 6);
849   selection_range_ = gfx::Range(3, 3);
850
851   // Set the verifier for SetSurroundingText mock call.
852   SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 3, 3);
853
854
855   ime_->OnCaretBoundsChanged(this);
856
857   // Check the call count.
858   EXPECT_EQ(1,
859             mock_ime_engine_handler_->set_surrounding_text_call_count());
860   EXPECT_EQ(UTF16ToUTF8(surrounding_text_),
861             mock_ime_engine_handler_->last_set_surrounding_text());
862   EXPECT_EQ(3U,
863             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
864   EXPECT_EQ(3U,
865             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
866 }
867
868 TEST_F(InputMethodChromeOSTest, SurroundingText_SelectionTest) {
869   ime_->Init(true);
870   // Click a text input form.
871   input_type_ = TEXT_INPUT_TYPE_TEXT;
872   ime_->OnTextInputTypeChanged(this);
873
874   // Set the TextInputClient behaviors.
875   surrounding_text_ = UTF8ToUTF16("abcdef");
876   text_range_ = gfx::Range(0, 6);
877   selection_range_ = gfx::Range(2, 5);
878
879   // Set the verifier for SetSurroundingText mock call.
880   SetSurroundingTextVerifier verifier(UTF16ToUTF8(surrounding_text_), 2, 5);
881
882   ime_->OnCaretBoundsChanged(this);
883
884   // Check the call count.
885   EXPECT_EQ(1,
886             mock_ime_engine_handler_->set_surrounding_text_call_count());
887   EXPECT_EQ(UTF16ToUTF8(surrounding_text_),
888             mock_ime_engine_handler_->last_set_surrounding_text());
889   EXPECT_EQ(2U,
890             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
891   EXPECT_EQ(5U,
892             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
893 }
894
895 TEST_F(InputMethodChromeOSTest, SurroundingText_PartialText) {
896   ime_->Init(true);
897   // Click a text input form.
898   input_type_ = TEXT_INPUT_TYPE_TEXT;
899   ime_->OnTextInputTypeChanged(this);
900
901   // Set the TextInputClient behaviors.
902   surrounding_text_ = UTF8ToUTF16("abcdefghij");
903   text_range_ = gfx::Range(5, 10);
904   selection_range_ = gfx::Range(7, 9);
905
906   ime_->OnCaretBoundsChanged(this);
907
908   // Check the call count.
909   EXPECT_EQ(1,
910             mock_ime_engine_handler_->set_surrounding_text_call_count());
911   // Set the verifier for SetSurroundingText mock call.
912   // Here (2, 4) is selection range in expected surrounding text coordinates.
913   EXPECT_EQ("fghij",
914             mock_ime_engine_handler_->last_set_surrounding_text());
915   EXPECT_EQ(2U,
916             mock_ime_engine_handler_->last_set_surrounding_cursor_pos());
917   EXPECT_EQ(4U,
918             mock_ime_engine_handler_->last_set_surrounding_anchor_pos());
919 }
920
921 TEST_F(InputMethodChromeOSTest, SurroundingText_BecomeEmptyText) {
922   ime_->Init(true);
923   // Click a text input form.
924   input_type_ = TEXT_INPUT_TYPE_TEXT;
925   ime_->OnTextInputTypeChanged(this);
926
927   // Set the TextInputClient behaviors.
928   // If the surrounding text becomes empty, text_range become (0, 0) and
929   // selection range become invalid.
930   surrounding_text_ = UTF8ToUTF16("");
931   text_range_ = gfx::Range(0, 0);
932   selection_range_ = gfx::Range::InvalidRange();
933
934   ime_->OnCaretBoundsChanged(this);
935
936   // Check the call count.
937   EXPECT_EQ(0,
938             mock_ime_engine_handler_->set_surrounding_text_call_count());
939
940   // Should not be called twice with same condition.
941   ime_->OnCaretBoundsChanged(this);
942   EXPECT_EQ(0,
943             mock_ime_engine_handler_->set_surrounding_text_call_count());
944 }
945
946 class InputMethodChromeOSKeyEventTest : public InputMethodChromeOSTest {
947  public:
948   InputMethodChromeOSKeyEventTest() {}
949   virtual ~InputMethodChromeOSKeyEventTest() {}
950
951   virtual void SetUp() override {
952     InputMethodChromeOSTest::SetUp();
953     ime_->Init(true);
954   }
955
956   DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSKeyEventTest);
957 };
958
959 TEST_F(InputMethodChromeOSKeyEventTest, KeyEventDelayResponseTest) {
960   const int kFlags = ui::EF_SHIFT_DOWN;
961   ScopedXI2Event xevent;
962   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, kFlags);
963   const ui::KeyEvent event(xevent);
964
965   // Do key event.
966   input_type_ = TEXT_INPUT_TYPE_TEXT;
967   ime_->OnTextInputTypeChanged(this);
968   ime_->DispatchKeyEvent(event);
969
970   // Check before state.
971   const ui::KeyEvent* key_event =
972       mock_ime_engine_handler_->last_processed_key_event();
973   EXPECT_EQ(1, mock_ime_engine_handler_->process_key_event_call_count());
974   EXPECT_EQ(ui::VKEY_A, key_event->key_code());
975   EXPECT_EQ("KeyA", key_event->code());
976   EXPECT_EQ(kFlags, key_event->flags());
977   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
978
979   // Do callback.
980   mock_ime_engine_handler_->last_passed_callback().Run(true);
981
982   // Check the results
983   EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count());
984   const ui::KeyEvent* stored_event =
985       ime_->process_key_event_post_ime_args().event;
986   EXPECT_TRUE(stored_event->HasNativeEvent());
987   EXPECT_TRUE(IsEqualXKeyEvent(*xevent, *(stored_event->native_event())));
988   EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled);
989 }
990
991 TEST_F(InputMethodChromeOSKeyEventTest, MultiKeyEventDelayResponseTest) {
992   // Preparation
993   input_type_ = TEXT_INPUT_TYPE_TEXT;
994   ime_->OnTextInputTypeChanged(this);
995
996   const int kFlags = ui::EF_SHIFT_DOWN;
997   ScopedXI2Event xevent;
998   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_B, kFlags);
999   const ui::KeyEvent event(xevent);
1000
1001   // Do key event.
1002   ime_->DispatchKeyEvent(event);
1003   const ui::KeyEvent* key_event =
1004       mock_ime_engine_handler_->last_processed_key_event();
1005   EXPECT_EQ(ui::VKEY_B, key_event->key_code());
1006   EXPECT_EQ("KeyB", key_event->code());
1007   EXPECT_EQ(kFlags, key_event->flags());
1008
1009   KeyEventCallback first_callback =
1010       mock_ime_engine_handler_->last_passed_callback();
1011
1012   // Do key event again.
1013   ScopedXI2Event xevent2;
1014   xevent2.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_C, kFlags);
1015   const ui::KeyEvent event2(xevent2);
1016
1017   ime_->DispatchKeyEvent(event2);
1018   const ui::KeyEvent* key_event2 =
1019       mock_ime_engine_handler_->last_processed_key_event();
1020   EXPECT_EQ(ui::VKEY_C, key_event2->key_code());
1021   EXPECT_EQ("KeyC", key_event2->code());
1022   EXPECT_EQ(kFlags, key_event2->flags());
1023
1024   // Check before state.
1025   EXPECT_EQ(2,
1026             mock_ime_engine_handler_->process_key_event_call_count());
1027   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1028
1029   // Do callback for first key event.
1030   first_callback.Run(true);
1031
1032   // Check the results for first key event.
1033   EXPECT_EQ(1, ime_->process_key_event_post_ime_call_count());
1034   const ui::KeyEvent* stored_event =
1035       ime_->process_key_event_post_ime_args().event;
1036   EXPECT_TRUE(stored_event->HasNativeEvent());
1037   EXPECT_TRUE(IsEqualXKeyEvent(*xevent, *(stored_event->native_event())));
1038   EXPECT_TRUE(ime_->process_key_event_post_ime_args().handled);
1039
1040   // Do callback for second key event.
1041   mock_ime_engine_handler_->last_passed_callback().Run(false);
1042
1043   // Check the results for second key event.
1044   EXPECT_EQ(2, ime_->process_key_event_post_ime_call_count());
1045   stored_event = ime_->process_key_event_post_ime_args().event;
1046   EXPECT_TRUE(stored_event->HasNativeEvent());
1047   EXPECT_TRUE(IsEqualXKeyEvent(*xevent2, *(stored_event->native_event())));
1048   EXPECT_FALSE(ime_->process_key_event_post_ime_args().handled);
1049 }
1050
1051 TEST_F(InputMethodChromeOSKeyEventTest, KeyEventDelayResponseResetTest) {
1052   ScopedXI2Event xevent;
1053   xevent.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_SHIFT_DOWN);
1054   const ui::KeyEvent event(xevent);
1055
1056   // Do key event.
1057   input_type_ = TEXT_INPUT_TYPE_TEXT;
1058   ime_->OnTextInputTypeChanged(this);
1059   ime_->DispatchKeyEvent(event);
1060
1061   // Check before state.
1062   EXPECT_EQ(1, mock_ime_engine_handler_->process_key_event_call_count());
1063   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1064
1065   ime_->ResetContext();
1066
1067   // Do callback.
1068   mock_ime_engine_handler_->last_passed_callback().Run(true);
1069
1070   EXPECT_EQ(0, ime_->process_key_event_post_ime_call_count());
1071 }
1072 // TODO(nona): Introduce ProcessKeyEventPostIME tests(crbug.com/156593).
1073
1074 }  // namespace ui