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, 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
    848