Home | History | Annotate | Download | only in ime
      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);
    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);
    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, ui::EF_NONE);
    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(L'A', ui::VKEY_A, ui::EF_NONE);
    688 
    689   // This must not cause a crash.
    690   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
    691   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
    692   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
    693   delegate_.Reset();
    694   mock_text_input_client.Reset();
    695 
    696   RemoteInputMethodPrivateWin* private_ptr =
    697       RemoteInputMethodPrivateWin::Get(input_method.get());
    698   ASSERT_TRUE(private_ptr != NULL);
    699   MockRemoteInputMethodDelegateWin mock_remote_delegate;
    700   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
    701 
    702   // TextInputClient is not focused yet here.
    703 
    704   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
    705   EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
    706   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
    707   delegate_.Reset();
    708   mock_text_input_client.Reset();
    709 
    710   input_method->SetFocusedTextInputClient(&mock_text_input_client);
    711 
    712   // TextInputClient is now focused here.
    713 
    714   EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char));
    715   EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
    716   EXPECT_TRUE(delegate_.fabricated_key_events().empty());
    717   delegate_.Reset();
    718   mock_text_input_client.Reset();
    719 }
    720 
    721 TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
    722   MockInputMethodDelegate delegate_;
    723   MockTextInputClient mock_text_input_client;
    724   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
    725 
    726   RemoteInputMethodPrivateWin* private_ptr =
    727       RemoteInputMethodPrivateWin::Get(input_method.get());
    728   ASSERT_TRUE(private_ptr != NULL);
    729   MockRemoteInputMethodDelegateWin mock_remote_delegate;
    730   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
    731 
    732   CompositionText composition_text;
    733 
    734   // TextInputClient is not focused yet here.
    735 
    736   private_ptr->OnCompositionChanged(composition_text);
    737   EXPECT_EQ(0, mock_text_input_client.call_count_set_composition_text());
    738   delegate_.Reset();
    739   mock_text_input_client.Reset();
    740 
    741   input_method->SetFocusedTextInputClient(&mock_text_input_client);
    742 
    743   // TextInputClient is now focused here.
    744 
    745   private_ptr->OnCompositionChanged(composition_text);
    746   EXPECT_EQ(1, mock_text_input_client.call_count_set_composition_text());
    747   delegate_.Reset();
    748   mock_text_input_client.Reset();
    749 }
    750 
    751 TEST(RemoteInputMethodWinTest, OnTextCommitted) {
    752   MockInputMethodDelegate delegate_;
    753   MockTextInputClient mock_text_input_client;
    754   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
    755 
    756   RemoteInputMethodPrivateWin* private_ptr =
    757       RemoteInputMethodPrivateWin::Get(input_method.get());
    758   ASSERT_TRUE(private_ptr != NULL);
    759   MockRemoteInputMethodDelegateWin mock_remote_delegate;
    760   private_ptr->SetRemoteDelegate(&mock_remote_delegate);
    761 
    762   base::string16 committed_text = L"Hello";
    763 
    764   // TextInputClient is not focused yet here.
    765 
    766   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
    767   private_ptr->OnTextCommitted(committed_text);
    768   EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
    769   EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
    770   EXPECT_EQ(L"", mock_text_input_client.inserted_text());
    771   delegate_.Reset();
    772   mock_text_input_client.Reset();
    773 
    774   input_method->SetFocusedTextInputClient(&mock_text_input_client);
    775 
    776   // TextInputClient is now focused here.
    777 
    778   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
    779   private_ptr->OnTextCommitted(committed_text);
    780   EXPECT_EQ(0, mock_text_input_client.call_count_insert_char());
    781   EXPECT_EQ(1, mock_text_input_client.call_count_insert_text());
    782   EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
    783   delegate_.Reset();
    784   mock_text_input_client.Reset();
    785 
    786   // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
    787   // should not be used.
    788   mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
    789   private_ptr->OnTextCommitted(committed_text);
    790   EXPECT_EQ(committed_text.size(),
    791             mock_text_input_client.call_count_insert_char());
    792   EXPECT_EQ(0, mock_text_input_client.call_count_insert_text());
    793   EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
    794   delegate_.Reset();
    795   mock_text_input_client.Reset();
    796 }
    797 
    798 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
    799   DummyTextInputClient text_input_client;
    800   DummyTextInputClient text_input_client_the_other;
    801 
    802   MockInputMethodObserver input_method_observer;
    803   MockInputMethodDelegate delegate_;
    804   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
    805   InputMethodScopedObserver scoped_observer(&input_method_observer);
    806   scoped_observer.Add(input_method.get());
    807 
    808   input_method->SetFocusedTextInputClient(&text_input_client);
    809   ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
    810   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
    811   input_method_observer.Reset();
    812 
    813   input_method->SetFocusedTextInputClient(&text_input_client);
    814   ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
    815   EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
    816   input_method_observer.Reset();
    817 
    818   input_method->SetFocusedTextInputClient(&text_input_client_the_other);
    819   ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
    820   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
    821   input_method_observer.Reset();
    822 
    823   input_method->DetachTextInputClient(&text_input_client_the_other);
    824   ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
    825   EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
    826   input_method_observer.Reset();
    827 }
    828 
    829 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
    830   DummyTextInputClient text_input_client;
    831   DummyTextInputClient text_input_client_the_other;
    832 
    833   MockInputMethodObserver input_method_observer;
    834   InputMethodScopedObserver scoped_observer(&input_method_observer);
    835 
    836   MockInputMethodDelegate delegate_;
    837   scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
    838   input_method->AddObserver(&input_method_observer);
    839 
    840   EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
    841   input_method.reset();
    842   EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
    843 }
    844 
    845 }  // namespace
    846 }  // namespace ui
    847