Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / base / ime / remote_input_method_win_unittest.cc
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.
4
5 #include "ui/base/ime/remote_input_method_win.h"
6
7 #include <InputScope.h>
8
9 #include <vector>
10
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"
22
23 namespace ui {
24 namespace {
25
26 class MockTextInputClient : public DummyTextInputClient {
27  public:
28   MockTextInputClient()
29       : text_input_type_(TEXT_INPUT_TYPE_NONE),
30         text_input_mode_(TEXT_INPUT_MODE_DEFAULT),
31         call_count_set_composition_text_(0),
32         call_count_insert_char_(0),
33         call_count_insert_text_(0),
34         emulate_pepper_flash_(false),
35         is_candidate_window_shown_called_(false),
36         is_candidate_window_hidden_called_(false) {
37   }
38
39   size_t call_count_set_composition_text() const {
40     return call_count_set_composition_text_;
41   }
42   const base::string16& inserted_text() const {
43     return inserted_text_;
44   }
45   size_t call_count_insert_char() const {
46     return call_count_insert_char_;
47   }
48   size_t call_count_insert_text() const {
49     return call_count_insert_text_;
50   }
51   bool is_candidate_window_shown_called() const {
52     return is_candidate_window_shown_called_;
53   }
54   bool is_candidate_window_hidden_called() const {
55     return is_candidate_window_hidden_called_;
56   }
57   void Reset() {
58     text_input_type_ = TEXT_INPUT_TYPE_NONE;
59     text_input_mode_ = TEXT_INPUT_MODE_DEFAULT;
60     call_count_set_composition_text_ = 0;
61     inserted_text_.clear();
62     call_count_insert_char_ = 0;
63     call_count_insert_text_ = 0;
64     caret_bounds_ = gfx::Rect();
65     composition_character_bounds_.clear();
66     emulate_pepper_flash_ = false;
67     is_candidate_window_shown_called_ = false;
68     is_candidate_window_hidden_called_ = false;
69   }
70   void set_text_input_type(ui::TextInputType type) {
71     text_input_type_ = type;
72   }
73   void set_text_input_mode(ui::TextInputMode mode) {
74     text_input_mode_ = mode;
75   }
76   void set_caret_bounds(const gfx::Rect& caret_bounds) {
77     caret_bounds_ = caret_bounds;
78   }
79   void set_composition_character_bounds(
80       const std::vector<gfx::Rect>& composition_character_bounds) {
81     composition_character_bounds_ = composition_character_bounds;
82   }
83   void set_emulate_pepper_flash(bool enabled) {
84     emulate_pepper_flash_ = enabled;
85   }
86
87  private:
88   // Overriden from DummyTextInputClient.
89   virtual void SetCompositionText(
90       const ui::CompositionText& composition) OVERRIDE {
91     ++call_count_set_composition_text_;
92   }
93   virtual void InsertChar(base::char16 ch, int flags) OVERRIDE {
94     inserted_text_.append(1, ch);
95     ++call_count_insert_char_;
96   }
97   virtual void InsertText(const base::string16& text) OVERRIDE {
98     inserted_text_.append(text);
99     ++call_count_insert_text_;
100   }
101   virtual ui::TextInputType GetTextInputType() const OVERRIDE {
102     return text_input_type_;
103   }
104   virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
105     return text_input_mode_;
106   }
107   virtual gfx::Rect GetCaretBounds() const {
108     return caret_bounds_;
109   }
110   virtual bool GetCompositionCharacterBounds(uint32 index,
111                                              gfx::Rect* rect) const OVERRIDE {
112     // Emulate the situation of crbug.com/328237.
113     if (emulate_pepper_flash_)
114       return false;
115     if (!rect || composition_character_bounds_.size() <= index)
116       return false;
117     *rect = composition_character_bounds_[index];
118     return true;
119   }
120   virtual bool HasCompositionText() const OVERRIDE {
121     return !composition_character_bounds_.empty();
122   }
123   virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE {
124     if (composition_character_bounds_.empty())
125       return false;
126     *range = gfx::Range(0, composition_character_bounds_.size());
127     return true;
128   }
129   virtual void OnCandidateWindowShown() OVERRIDE {
130     is_candidate_window_shown_called_ = true;
131   }
132   virtual void OnCandidateWindowHidden() OVERRIDE {
133     is_candidate_window_hidden_called_ = true;
134   }
135
136   ui::TextInputType text_input_type_;
137   ui::TextInputMode text_input_mode_;
138   gfx::Rect caret_bounds_;
139   std::vector<gfx::Rect> composition_character_bounds_;
140   base::string16 inserted_text_;
141   size_t call_count_set_composition_text_;
142   size_t call_count_insert_char_;
143   size_t call_count_insert_text_;
144   bool emulate_pepper_flash_;
145   bool is_candidate_window_shown_called_;
146   bool is_candidate_window_hidden_called_;
147   DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
148 };
149
150 class MockInputMethodDelegate : public internal::InputMethodDelegate {
151  public:
152   MockInputMethodDelegate() {}
153
154   const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
155     return fabricated_key_events_;
156   }
157   void Reset() {
158     fabricated_key_events_.clear();
159   }
160
161  private:
162   virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
163     EXPECT_FALSE(event.HasNativeEvent());
164     fabricated_key_events_.push_back(event.key_code());
165     return true;
166   }
167
168   std::vector<ui::KeyboardCode> fabricated_key_events_;
169   DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
170 };
171
172 class MockRemoteInputMethodDelegateWin
173     : public internal::RemoteInputMethodDelegateWin {
174  public:
175   MockRemoteInputMethodDelegateWin()
176       : cancel_composition_called_(false),
177         text_input_client_updated_called_(false) {
178   }
179
180   bool cancel_composition_called() const {
181     return cancel_composition_called_;
182   }
183   bool text_input_client_updated_called() const {
184     return text_input_client_updated_called_;
185   }
186   const std::vector<int32>& input_scopes() const {
187     return input_scopes_;
188   }
189   const std::vector<gfx::Rect>& composition_character_bounds() const {
190     return composition_character_bounds_;
191   }
192   void Reset() {
193     cancel_composition_called_ = false;
194     text_input_client_updated_called_ = false;
195     input_scopes_.clear();
196     composition_character_bounds_.clear();
197   }
198
199  private:
200   virtual void CancelComposition() OVERRIDE {
201     cancel_composition_called_ = true;
202   }
203
204   virtual void OnTextInputClientUpdated(
205       const std::vector<int32>& input_scopes,
206       const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE {
207     text_input_client_updated_called_ = true;
208     input_scopes_ = input_scopes;
209     composition_character_bounds_ = composition_character_bounds;
210   }
211
212   bool cancel_composition_called_;
213   bool text_input_client_updated_called_;
214   std::vector<int32> input_scopes_;
215   std::vector<gfx::Rect> composition_character_bounds_;
216   DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
217 };
218
219 class MockInputMethodObserver : public InputMethodObserver {
220  public:
221   MockInputMethodObserver()
222       : on_text_input_state_changed_(0),
223         on_input_method_destroyed_changed_(0) {
224   }
225   virtual ~MockInputMethodObserver() {
226   }
227   void Reset() {
228     on_text_input_state_changed_ = 0;
229     on_input_method_destroyed_changed_ = 0;
230   }
231   size_t on_text_input_state_changed() const {
232     return on_text_input_state_changed_;
233   }
234   size_t on_input_method_destroyed_changed() const {
235     return on_input_method_destroyed_changed_;
236   }
237
238  private:
239   // Overriden from InputMethodObserver.
240   virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE {
241   }
242   virtual void OnFocus() OVERRIDE {
243   }
244   virtual void OnBlur() OVERRIDE {
245   }
246   virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE {
247   }
248   virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE {
249     ++on_text_input_state_changed_;
250   }
251   virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE {
252     ++on_input_method_destroyed_changed_;
253   }
254   virtual void OnShowImeIfNeeded() {
255   }
256
257   size_t on_text_input_state_changed_;
258   size_t on_input_method_destroyed_changed_;
259   DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
260 };
261
262 typedef ScopedObserver<InputMethod, InputMethodObserver>
263     InputMethodScopedObserver;
264
265 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
266   InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
267
268   // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
269   RemoteInputMethodPrivateWin* kNull =
270       static_cast<RemoteInputMethodPrivateWin*>(NULL);
271   EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
272
273   MockInputMethodDelegate delegate_;
274   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
275   EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
276
277   InputMethod* dangling_ptr = input_method.get();
278   input_method.reset(NULL);
279   EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
280 }
281
282 TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
283   MockInputMethodDelegate delegate_;
284   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
285   RemoteInputMethodPrivateWin* private_ptr =
286       RemoteInputMethodPrivateWin::Get(input_method.get());
287   ASSERT_TRUE(private_ptr != NULL);
288
289   private_ptr->OnInputSourceChanged(
290       MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
291   EXPECT_EQ("ja-JP", input_method->GetInputLocale());
292
293   private_ptr->OnInputSourceChanged(
294       MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
295   EXPECT_EQ("ar-QA", input_method->GetInputLocale());
296 }
297
298 TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
299   MockInputMethodDelegate delegate_;
300   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
301   RemoteInputMethodPrivateWin* private_ptr =
302       RemoteInputMethodPrivateWin::Get(input_method.get());
303   ASSERT_TRUE(private_ptr != NULL);
304
305   // Initial value
306   EXPECT_FALSE(input_method->IsCandidatePopupOpen());
307
308   // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
309   // focused text input client is NULL.
310   ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
311   private_ptr->OnCandidatePopupChanged(false);
312   private_ptr->OnCandidatePopupChanged(true);
313
314   MockTextInputClient mock_text_input_client;
315   input_method->SetFocusedTextInputClient(&mock_text_input_client);
316
317   ASSERT_FALSE(mock_text_input_client.is_candidate_window_shown_called());
318   ASSERT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
319   mock_text_input_client.Reset();
320
321   private_ptr->OnCandidatePopupChanged(true);
322   EXPECT_TRUE(input_method->IsCandidatePopupOpen());
323   EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
324   EXPECT_FALSE(mock_text_input_client.is_candidate_window_hidden_called());
325
326   private_ptr->OnCandidatePopupChanged(false);
327   EXPECT_FALSE(input_method->IsCandidatePopupOpen());
328   EXPECT_TRUE(mock_text_input_client.is_candidate_window_shown_called());
329   EXPECT_TRUE(mock_text_input_client.is_candidate_window_hidden_called());
330 }
331
332 TEST(RemoteInputMethodWinTest, CancelComposition) {
333   MockInputMethodDelegate delegate_;
334   MockTextInputClient mock_text_input_client;
335   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
336
337   // This must not cause a crash.
338   input_method->CancelComposition(&mock_text_input_client);
339
340   RemoteInputMethodPrivateWin* private_ptr =
341       RemoteInputMethodPrivateWin::Get(input_method.get());
342   ASSERT_TRUE(private_ptr != NULL);
343   MockRemoteInputMethodDelegateWin mock_remote_delegate;
344   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
345
346   input_method->CancelComposition(&mock_text_input_client);
347   EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
348
349   input_method->SetFocusedTextInputClient(&mock_text_input_client);
350   input_method->CancelComposition(&mock_text_input_client);
351   EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
352 }
353
354 TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
355   MockInputMethodDelegate delegate_;
356   MockTextInputClient mock_text_input_client;
357   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
358
359   mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
360   mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
361   input_method->SetFocusedTextInputClient(&mock_text_input_client);
362
363   RemoteInputMethodPrivateWin* private_ptr =
364       RemoteInputMethodPrivateWin::Get(input_method.get());
365   ASSERT_TRUE(private_ptr != NULL);
366   MockRemoteInputMethodDelegateWin mock_remote_delegate;
367   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
368
369   // Initial state must be synced.
370   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
371   ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
372   EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
373             mock_remote_delegate.composition_character_bounds()[0]);
374   ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
375   EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
376
377   // State must be cleared by SetFocusedTextInputClient(NULL).
378   mock_remote_delegate.Reset();
379   input_method->SetFocusedTextInputClient(NULL);
380   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
381   EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
382   EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
383 }
384
385 TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
386   MockInputMethodDelegate delegate_;
387   MockTextInputClient mock_text_input_client;
388   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
389
390   mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
391   mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
392   input_method->SetFocusedTextInputClient(&mock_text_input_client);
393
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);
399
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]);
405   ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
406   EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
407
408   // State must be cleared by DetachTextInputClient
409   mock_remote_delegate.Reset();
410   input_method->DetachTextInputClient(&mock_text_input_client);
411   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
412   EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
413   EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
414 }
415
416 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
417   MockInputMethodDelegate delegate_;
418   MockTextInputClient mock_text_input_client;
419   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
420
421   // This must not cause a crash.
422   input_method->OnCaretBoundsChanged(&mock_text_input_client);
423
424   mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
425   input_method->SetFocusedTextInputClient(&mock_text_input_client);
426
427   RemoteInputMethodPrivateWin* private_ptr =
428       RemoteInputMethodPrivateWin::Get(input_method.get());
429   ASSERT_TRUE(private_ptr != NULL);
430   MockRemoteInputMethodDelegateWin mock_remote_delegate;
431   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
432
433   // Initial state must be synced.
434   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
435   ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
436   EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
437       mock_remote_delegate.composition_character_bounds()[0]);
438
439   // Redundant OnCaretBoundsChanged must be ignored.
440   mock_remote_delegate.Reset();
441   input_method->OnCaretBoundsChanged(&mock_text_input_client);
442   EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
443
444   // Check OnCaretBoundsChanged is handled. (w/o composition)
445   mock_remote_delegate.Reset();
446   mock_text_input_client.Reset();
447   mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
448   input_method->OnCaretBoundsChanged(&mock_text_input_client);
449   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
450   ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
451   EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
452       mock_remote_delegate.composition_character_bounds()[0]);
453
454   // Check OnCaretBoundsChanged is handled. (w/ composition)
455   {
456     mock_remote_delegate.Reset();
457     mock_text_input_client.Reset();
458
459     std::vector<gfx::Rect> bounds;
460     bounds.push_back(gfx::Rect(10, 20, 30, 40));
461     bounds.push_back(gfx::Rect(40, 30, 20, 10));
462     mock_text_input_client.set_composition_character_bounds(bounds);
463     input_method->OnCaretBoundsChanged(&mock_text_input_client);
464     EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
465     EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
466   }
467 }
468
469 // Test case against crbug.com/328237.
470 TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
471   MockInputMethodDelegate delegate_;
472   MockTextInputClient mock_text_input_client;
473   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
474   input_method->SetFocusedTextInputClient(&mock_text_input_client);
475
476   RemoteInputMethodPrivateWin* private_ptr =
477       RemoteInputMethodPrivateWin::Get(input_method.get());
478   ASSERT_TRUE(private_ptr != NULL);
479   MockRemoteInputMethodDelegateWin mock_remote_delegate;
480   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
481
482   mock_remote_delegate.Reset();
483   mock_text_input_client.Reset();
484   mock_text_input_client.set_emulate_pepper_flash(true);
485
486   std::vector<gfx::Rect> caret_bounds;
487   caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
488   mock_text_input_client.set_caret_bounds(caret_bounds[0]);
489
490   std::vector<gfx::Rect> composition_bounds;
491   composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
492   composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
493   mock_text_input_client.set_composition_character_bounds(composition_bounds);
494   input_method->OnCaretBoundsChanged(&mock_text_input_client);
495   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
496   // The caret bounds must be used when
497   // TextInputClient::GetCompositionCharacterBounds failed.
498   EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
499 }
500
501 TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
502   MockInputMethodDelegate delegate_;
503   MockTextInputClient mock_text_input_client;
504   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
505
506   // This must not cause a crash.
507   input_method->OnCaretBoundsChanged(&mock_text_input_client);
508
509   mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
510   input_method->SetFocusedTextInputClient(&mock_text_input_client);
511
512   RemoteInputMethodPrivateWin* private_ptr =
513       RemoteInputMethodPrivateWin::Get(input_method.get());
514   ASSERT_TRUE(private_ptr != NULL);
515   MockRemoteInputMethodDelegateWin mock_remote_delegate;
516   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
517
518   // Initial state must be synced.
519   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
520   ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
521   EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
522
523   // Check TEXT_INPUT_TYPE_NONE is handled.
524   mock_remote_delegate.Reset();
525   mock_text_input_client.Reset();
526   mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
527   mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
528   input_method->OnTextInputTypeChanged(&mock_text_input_client);
529   EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
530   EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
531
532   // Redundant OnTextInputTypeChanged must be ignored.
533   mock_remote_delegate.Reset();
534   input_method->OnTextInputTypeChanged(&mock_text_input_client);
535   EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
536
537   mock_remote_delegate.Reset();
538   mock_text_input_client.Reset();
539   mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
540   input_method->OnCaretBoundsChanged(&mock_text_input_client);
541 }
542
543 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
544   // Basically RemoteInputMethodWin does not handle native keydown event.
545
546   MockInputMethodDelegate delegate_;
547   MockTextInputClient mock_text_input_client;
548   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
549
550   const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
551   ui::KeyEvent native_keydown(wm_keydown, false);
552
553   // This must not cause a crash.
554   EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
555   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
556   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
557   delegate_.Reset();
558   mock_text_input_client.Reset();
559
560   RemoteInputMethodPrivateWin* private_ptr =
561       RemoteInputMethodPrivateWin::Get(input_method.get());
562   ASSERT_TRUE(private_ptr != NULL);
563   MockRemoteInputMethodDelegateWin mock_remote_delegate;
564   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
565
566   // TextInputClient is not focused yet here.
567
568   EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
569   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
570   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
571   delegate_.Reset();
572   mock_text_input_client.Reset();
573
574   input_method->SetFocusedTextInputClient(&mock_text_input_client);
575
576   // TextInputClient is now focused here.
577
578   EXPECT_FALSE(input_method->DispatchKeyEvent(native_keydown));
579   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
580   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
581   delegate_.Reset();
582   mock_text_input_client.Reset();
583 }
584
585 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
586   // RemoteInputMethodWin handles native char event if possible.
587
588   MockInputMethodDelegate delegate_;
589   MockTextInputClient mock_text_input_client;
590   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
591
592   const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
593   ui::KeyEvent native_char(wm_char, true);
594
595   // This must not cause a crash.
596   EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
597   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
598   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
599   delegate_.Reset();
600   mock_text_input_client.Reset();
601
602   RemoteInputMethodPrivateWin* private_ptr =
603       RemoteInputMethodPrivateWin::Get(input_method.get());
604   ASSERT_TRUE(private_ptr != NULL);
605   MockRemoteInputMethodDelegateWin mock_remote_delegate;
606   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
607
608   // TextInputClient is not focused yet here.
609
610   EXPECT_FALSE(input_method->DispatchKeyEvent(native_char));
611   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
612   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
613   delegate_.Reset();
614   mock_text_input_client.Reset();
615
616   input_method->SetFocusedTextInputClient(&mock_text_input_client);
617
618   // TextInputClient is now focused here.
619
620   EXPECT_TRUE(input_method->DispatchKeyEvent(native_char));
621   EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
622   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
623   delegate_.Reset();
624   mock_text_input_client.Reset();
625 }
626
627 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
628   // Fabricated non-char event will be delegated to
629   // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
630   // delegate is installed.
631
632   MockInputMethodDelegate delegate_;
633   MockTextInputClient mock_text_input_client;
634   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
635
636   ui::KeyEvent fabricated_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, false);
637   fabricated_keydown.set_character(L'A');
638
639   // This must not cause a crash.
640   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
641   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
642   ASSERT_EQ(1, delegate_.fabricated_key_events().size());
643   EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
644   delegate_.Reset();
645   mock_text_input_client.Reset();
646
647   RemoteInputMethodPrivateWin* private_ptr =
648       RemoteInputMethodPrivateWin::Get(input_method.get());
649   ASSERT_TRUE(private_ptr != NULL);
650   MockRemoteInputMethodDelegateWin mock_remote_delegate;
651   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
652
653   // TextInputClient is not focused yet here.
654
655   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
656   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
657   ASSERT_EQ(1, delegate_.fabricated_key_events().size());
658   EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
659   delegate_.Reset();
660   mock_text_input_client.Reset();
661
662   input_method->SetFocusedTextInputClient(&mock_text_input_client);
663   // TextInputClient is now focused here.
664
665   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_keydown));
666   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
667   ASSERT_EQ(1, delegate_.fabricated_key_events().size());
668   EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
669   delegate_.Reset();
670   mock_text_input_client.Reset();
671
672   input_method->SetDelegate(NULL);
673   // RemoteInputMethodDelegateWin is no longer set here.
674
675   EXPECT_FALSE(input_method->DispatchKeyEvent(fabricated_keydown));
676   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
677 }
678
679 TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
680   // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
681   // for fabricated character events.
682
683   MockInputMethodDelegate delegate_;
684   MockTextInputClient mock_text_input_client;
685   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
686
687   ui::KeyEvent fabricated_char(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
688   fabricated_char.set_character(L'A');
689
690   // This must not cause a crash.
691   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
692   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
693   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
694   delegate_.Reset();
695   mock_text_input_client.Reset();
696
697   RemoteInputMethodPrivateWin* private_ptr =
698       RemoteInputMethodPrivateWin::Get(input_method.get());
699   ASSERT_TRUE(private_ptr != NULL);
700   MockRemoteInputMethodDelegateWin mock_remote_delegate;
701   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
702
703   // TextInputClient is not focused yet here.
704
705   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
706   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
707   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
708   delegate_.Reset();
709   mock_text_input_client.Reset();
710
711   input_method->SetFocusedTextInputClient(&mock_text_input_client);
712
713   // TextInputClient is now focused here.
714
715   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
716   EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
717   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
718   delegate_.Reset();
719   mock_text_input_client.Reset();
720 }
721
722 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
723   MockInputMethodDelegate delegate_;
724   MockTextInputClient mock_text_input_client;
725   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
726
727   RemoteInputMethodPrivateWin* private_ptr =
728       RemoteInputMethodPrivateWin::Get(input_method.get());
729   ASSERT_TRUE(private_ptr != NULL);
730   MockRemoteInputMethodDelegateWin mock_remote_delegate;
731   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
732
733   CompositionText composition_text;
734
735   // TextInputClient is not focused yet here.
736
737   private_ptr->OnCompositionChanged(composition_text);
738   EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
739   delegate_.Reset();
740   mock_text_input_client.Reset();
741
742   input_method->SetFocusedTextInputClient(&mock_text_input_client);
743
744   // TextInputClient is now focused here.
745
746   private_ptr->OnCompositionChanged(composition_text);
747   EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
748   delegate_.Reset();
749   mock_text_input_client.Reset();
750 }
751
752 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
753   MockInputMethodDelegate delegate_;
754   MockTextInputClient mock_text_input_client;
755   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
756
757   RemoteInputMethodPrivateWin* private_ptr =
758       RemoteInputMethodPrivateWin::Get(input_method.get());
759   ASSERT_TRUE(private_ptr != NULL);
760   MockRemoteInputMethodDelegateWin mock_remote_delegate;
761   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
762
763   base::string16 committed_text = L"Hello";
764
765   // TextInputClient is not focused yet here.
766
767   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
768   private_ptr->OnTextCommitted(committed_text);
769   EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
770   EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
771   EXPECT_EQ(L"", mock_text_input_client.inserted_text());
772   delegate_.Reset();
773   mock_text_input_client.Reset();
774
775   input_method->SetFocusedTextInputClient(&mock_text_input_client);
776
777   // TextInputClient is now focused here.
778
779   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
780   private_ptr->OnTextCommitted(committed_text);
781   EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
782   EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
783   EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
784   delegate_.Reset();
785   mock_text_input_client.Reset();
786
787   // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
788   // should not be used.
789   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
790   private_ptr->OnTextCommitted(committed_text);
791   EXPECT_EQ(committed_text.size(),
792             mock_text_input_client.call_count_insert_char());
793   EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
794   EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
795   delegate_.Reset();
796   mock_text_input_client.Reset();
797 }
798
799 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
800   DummyTextInputClient text_input_client;
801   DummyTextInputClient text_input_client_the_other;
802
803   MockInputMethodObserver input_method_observer;
804   MockInputMethodDelegate delegate_;
805   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
806   InputMethodScopedObserver scoped_observer(&input_method_observer);
807   scoped_observer.Add(input_method.get());
808
809   input_method->SetFocusedTextInputClient(&text_input_client);
810   ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
811   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
812   input_method_observer.Reset();
813
814   input_method->SetFocusedTextInputClient(&text_input_client);
815   ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
816   EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
817   input_method_observer.Reset();
818
819   input_method->SetFocusedTextInputClient(&text_input_client_the_other);
820   ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
821   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
822   input_method_observer.Reset();
823
824   input_method->DetachTextInputClient(&text_input_client_the_other);
825   ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
826   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
827   input_method_observer.Reset();
828 }
829
830 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
831   DummyTextInputClient text_input_client;
832   DummyTextInputClient text_input_client_the_other;
833
834   MockInputMethodObserver input_method_observer;
835   InputMethodScopedObserver scoped_observer(&input_method_observer);
836
837   MockInputMethodDelegate delegate_;
838   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
839   input_method->AddObserver(&input_method_observer);
840
841   EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
842   input_method.reset();
843   EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
844 }
845
846 }  // namespace
847 }  // namespace ui