Home | History | Annotate | Download | only in input_method
      1 // Copyright (c) 2012 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 "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/compiler_specific.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "chrome/browser/chromeos/input_method/mock_candidate_window_controller.h"
     15 #include "chrome/browser/chromeos/input_method/mock_ibus_controller.h"
     16 #include "chromeos/dbus/ibus/mock_ibus_client.h"
     17 #include "chromeos/dbus/ibus/mock_ibus_input_context_client.h"
     18 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
     19 #include "chromeos/ime/extension_ime_util.h"
     20 #include "chromeos/ime/fake_input_method_delegate.h"
     21 #include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
     22 #include "chromeos/ime/mock_ibus_daemon_controller.h"
     23 #include "chromeos/ime/mock_xkeyboard.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "ui/base/accelerators/accelerator.h"
     26 #include "ui/base/keycodes/keyboard_codes.h"
     27 
     28 namespace chromeos {
     29 
     30 namespace input_method {
     31 namespace {
     32 
     33 const char nacl_mozc_us_id[] =
     34     "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us";
     35 const char nacl_mozc_jp_id[] =
     36     "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp";
     37 
     38 // Returns true if |descriptors| contain |target|.
     39 bool Contain(const InputMethodDescriptors& descriptors,
     40              const InputMethodDescriptor& target) {
     41   for (size_t i = 0; i < descriptors.size(); ++i) {
     42     if (descriptors[i].id() == target.id())
     43       return true;
     44   }
     45   return false;
     46 }
     47 
     48 class InputMethodManagerImplTest :  public testing::Test {
     49  public:
     50   InputMethodManagerImplTest()
     51       : delegate_(NULL),
     52         controller_(NULL),
     53         candidate_window_controller_(NULL),
     54         xkeyboard_(NULL) {
     55   }
     56   virtual ~InputMethodManagerImplTest() {}
     57 
     58   virtual void SetUp() OVERRIDE {
     59     mock_ibus_daemon_controller_ = new chromeos::MockIBusDaemonController();
     60     chromeos::IBusDaemonController::InitializeForTesting(
     61         mock_ibus_daemon_controller_);
     62     mock_dbus_thread_manager_ =
     63         new chromeos::MockDBusThreadManagerWithoutGMock();
     64     chromeos::DBusThreadManager::InitializeForTesting(
     65         mock_dbus_thread_manager_);
     66     delegate_ = new FakeInputMethodDelegate();
     67     manager_.reset(new InputMethodManagerImpl(
     68         scoped_ptr<InputMethodDelegate>(delegate_)));
     69     controller_ = new MockIBusController;
     70     manager_->SetIBusControllerForTesting(controller_);
     71     candidate_window_controller_ = new MockCandidateWindowController;
     72     manager_->SetCandidateWindowControllerForTesting(
     73         candidate_window_controller_);
     74     xkeyboard_ = new MockXKeyboard;
     75     manager_->SetXKeyboardForTesting(xkeyboard_);
     76 
     77     ime_list_.clear();
     78 
     79     ComponentExtensionIME ext1;
     80     ext1.id = "fpfbhcjppmaeaijcidgiibchfbnhbelj";
     81     ext1.description = "ext1_description";
     82     ext1.path = base::FilePath("ext1_file_path");
     83 
     84     ComponentExtensionEngine ext1_engine1;
     85     ext1_engine1.engine_id = "nacl_mozc_us";
     86     ext1_engine1.display_name = "ext1_engine_1_display_name";
     87     ext1_engine1.language_codes.push_back("ja");
     88     ext1_engine1.layouts.push_back("us");
     89     ext1.engines.push_back(ext1_engine1);
     90 
     91     ComponentExtensionEngine ext1_engine2;
     92     ext1_engine2.engine_id = "nacl_mozc_jp";
     93     ext1_engine2.display_name = "ext1_engine_1_display_name";
     94     ext1_engine2.language_codes.push_back("ja");
     95     ext1_engine2.layouts.push_back("jp");
     96     ext1.engines.push_back(ext1_engine2);
     97 
     98     ime_list_.push_back(ext1);
     99 
    100     ComponentExtensionIME ext2;
    101     ext2.id = "nmblnjkfdkabgdofidlkienfnnbjhnab";
    102     ext2.description = "ext2_description";
    103     ext2.path = base::FilePath("ext2_file_path");
    104 
    105     ComponentExtensionEngine ext2_engine1;
    106     ext2_engine1.engine_id = "ext2_engine1_engine_id";
    107     ext2_engine1.display_name = "ext2_engine_1_display_name";
    108     ext2_engine1.language_codes.push_back("en");
    109     ext2_engine1.layouts.push_back("us");
    110     ext2.engines.push_back(ext2_engine1);
    111 
    112     ComponentExtensionEngine ext2_engine2;
    113     ext2_engine2.engine_id = "ext2_engine2_engine_id";
    114     ext2_engine2.display_name = "ext2_engine_2_display_name";
    115     ext2_engine2.language_codes.push_back("en");
    116     ext2_engine2.layouts.push_back("us(dvorak)");
    117     ext2.engines.push_back(ext2_engine2);
    118 
    119     ime_list_.push_back(ext2);
    120 
    121     mock_ibus_daemon_controller_->EmulateConnect();
    122   }
    123 
    124   virtual void TearDown() OVERRIDE {
    125     mock_ibus_daemon_controller_->EmulateDisconnect();
    126     delegate_ = NULL;
    127     controller_ = NULL;
    128     candidate_window_controller_ = NULL;
    129     xkeyboard_ = NULL;
    130     manager_.reset();
    131     chromeos::DBusThreadManager::Shutdown();
    132     chromeos::IBusDaemonController::Shutdown();
    133   }
    134 
    135  protected:
    136   // Helper function to initialize component extension stuff for testing.
    137   void InitComponentExtension() {
    138     mock_delegate_ = new MockComponentExtIMEManagerDelegate();
    139     mock_delegate_->set_ime_list(ime_list_);
    140     scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(mock_delegate_);
    141     manager_->InitializeComponentExtensionForTesting(delegate.Pass());
    142   }
    143 
    144   // Helper function to initialize IBus bus connection for testing. Do not use
    145   // ibus related mocks before calling this function.
    146   void InitIBusBus() {
    147     mock_dbus_thread_manager_->InitIBusBus("dummy address",
    148                                            base::Bind(&base::DoNothing));
    149     mock_ibus_client_ = mock_dbus_thread_manager_->mock_ibus_client();
    150     mock_ibus_input_context_client_ =
    151         mock_dbus_thread_manager_->mock_ibus_input_context_client();
    152     mock_ibus_daemon_controller_->EmulateConnect();
    153   }
    154 
    155   scoped_ptr<InputMethodManagerImpl> manager_;
    156   FakeInputMethodDelegate* delegate_;
    157   MockIBusController* controller_;
    158   MockCandidateWindowController* candidate_window_controller_;
    159   MockIBusDaemonController* mock_ibus_daemon_controller_;
    160   MockIBusInputContextClient* mock_ibus_input_context_client_;
    161   MockIBusClient* mock_ibus_client_;
    162   MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_;
    163   MockXKeyboard* xkeyboard_;
    164   base::MessageLoop message_loop_;
    165   MockComponentExtIMEManagerDelegate* mock_delegate_;
    166   std::vector<ComponentExtensionIME> ime_list_;
    167 
    168  private:
    169   DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImplTest);
    170 };
    171 
    172 class TestableComponentExtensionIMEManager
    173     : public ComponentExtensionIMEManager {
    174  public:
    175   using ComponentExtensionIMEManager::GetComponentExtensionIMEId;
    176 };
    177 
    178 class TestObserver : public InputMethodManager::Observer {
    179  public:
    180   TestObserver()
    181       : input_method_changed_count_(0),
    182         input_method_property_changed_count_(0),
    183         last_show_message_(false) {
    184   }
    185   virtual ~TestObserver() {}
    186 
    187   virtual void InputMethodChanged(InputMethodManager* manager,
    188                                   bool show_message) OVERRIDE {
    189     ++input_method_changed_count_;
    190     last_show_message_ = show_message;
    191   }
    192   virtual void InputMethodPropertyChanged(
    193       InputMethodManager* manager) OVERRIDE {
    194     ++input_method_property_changed_count_;
    195   }
    196 
    197   int input_method_changed_count_;
    198   int input_method_property_changed_count_;
    199   bool last_show_message_;
    200 
    201  private:
    202   DISALLOW_COPY_AND_ASSIGN(TestObserver);
    203 };
    204 
    205 class TestCandidateWindowObserver
    206     : public InputMethodManager::CandidateWindowObserver {
    207  public:
    208   TestCandidateWindowObserver()
    209       : candidate_window_opened_count_(0),
    210         candidate_window_closed_count_(0) {
    211   }
    212   virtual ~TestCandidateWindowObserver() {}
    213 
    214   virtual void CandidateWindowOpened(InputMethodManager* manager) OVERRIDE {
    215     ++candidate_window_opened_count_;
    216   }
    217   virtual void CandidateWindowClosed(InputMethodManager* manager) OVERRIDE {
    218     ++candidate_window_closed_count_;
    219   }
    220 
    221   int candidate_window_opened_count_;
    222   int candidate_window_closed_count_;
    223 
    224  private:
    225   DISALLOW_COPY_AND_ASSIGN(TestCandidateWindowObserver);
    226 };
    227 
    228 }  // namespace
    229 
    230 TEST_F(InputMethodManagerImplTest, TestGetXKeyboard) {
    231   EXPECT_TRUE(manager_->GetXKeyboard());
    232   EXPECT_EQ(xkeyboard_, manager_->GetXKeyboard());
    233 }
    234 
    235 TEST_F(InputMethodManagerImplTest, TestCandidateWindowObserver) {
    236   TestCandidateWindowObserver observer;
    237   candidate_window_controller_->NotifyCandidateWindowOpened();  // nop
    238   candidate_window_controller_->NotifyCandidateWindowClosed();  // nop
    239   manager_->AddCandidateWindowObserver(&observer);
    240   candidate_window_controller_->NotifyCandidateWindowOpened();
    241   EXPECT_EQ(1, observer.candidate_window_opened_count_);
    242   candidate_window_controller_->NotifyCandidateWindowClosed();
    243   EXPECT_EQ(1, observer.candidate_window_closed_count_);
    244   candidate_window_controller_->NotifyCandidateWindowOpened();
    245   EXPECT_EQ(2, observer.candidate_window_opened_count_);
    246   candidate_window_controller_->NotifyCandidateWindowClosed();
    247   EXPECT_EQ(2, observer.candidate_window_closed_count_);
    248   manager_->RemoveCandidateWindowObserver(&observer);
    249 }
    250 
    251 TEST_F(InputMethodManagerImplTest, TestObserver) {
    252   // For http://crbug.com/19655#c11 - (3). browser_state_monitor_unittest.cc is
    253   // also for the scenario.
    254   TestObserver observer;
    255   InitComponentExtension();
    256   InitIBusBus();
    257   manager_->AddObserver(&observer);
    258   EXPECT_EQ(0, observer.input_method_changed_count_);
    259   manager_->EnableLayouts("en-US", "xkb:us::eng");
    260   EXPECT_EQ(1, observer.input_method_changed_count_);
    261   EXPECT_EQ(1, observer.input_method_property_changed_count_);
    262   manager_->ChangeInputMethod("xkb:us:dvorak:eng");
    263   EXPECT_FALSE(observer.last_show_message_);
    264   EXPECT_EQ(2, observer.input_method_changed_count_);
    265   EXPECT_EQ(2, observer.input_method_property_changed_count_);
    266   manager_->ChangeInputMethod("xkb:us:dvorak:eng");
    267   EXPECT_FALSE(observer.last_show_message_);
    268   // The observer is always notified even when the same input method ID is
    269   // passed to ChangeInputMethod() more than twice.
    270   EXPECT_EQ(3, observer.input_method_changed_count_);
    271   EXPECT_EQ(3, observer.input_method_property_changed_count_);
    272 
    273   controller_->NotifyPropertyChangedForTesting();
    274   EXPECT_EQ(4, observer.input_method_property_changed_count_);
    275   controller_->NotifyPropertyChangedForTesting();
    276   EXPECT_EQ(5, observer.input_method_property_changed_count_);
    277   manager_->RemoveObserver(&observer);
    278 }
    279 
    280 TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) {
    281   InitComponentExtension();
    282   InitIBusBus();
    283   scoped_ptr<InputMethodDescriptors> methods(
    284       manager_->GetSupportedInputMethods());
    285   ASSERT_TRUE(methods.get());
    286   // Try to find random 4-5 layuts and IMEs to make sure the returned list is
    287   // correct.
    288   const InputMethodDescriptor* id_to_find =
    289       manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    290           nacl_mozc_us_id);
    291   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    292       "xkb:us::eng");
    293   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
    294   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    295       "xkb:us:dvorak:eng");
    296   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
    297   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    298       "xkb:fr::fra");
    299   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
    300 }
    301 
    302 TEST_F(InputMethodManagerImplTest, TestEnableLayouts) {
    303   // Currently 5 keyboard layouts are supported for en-US, and 1 for ja. See
    304   // ibus_input_method.txt.
    305   InitComponentExtension();
    306   InitIBusBus();
    307   manager_->EnableLayouts("en-US", "");
    308   EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
    309   for (size_t i = 0; i < manager_->GetActiveInputMethodIds().size(); ++i)
    310     LOG(ERROR) << manager_->GetActiveInputMethodIds().at(i);
    311   // For http://crbug.com/19655#c11 - (2)
    312   EXPECT_EQ(0, mock_ibus_daemon_controller_->start_count());
    313 
    314   // For http://crbug.com/19655#c11 - (5)
    315   // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U.
    316   manager_->EnableLayouts("ja", "");  // Japanese
    317   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    318   EXPECT_EQ(0, mock_ibus_daemon_controller_->start_count());
    319 }
    320 
    321 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsNonUsHardwareKeyboard) {
    322   // The physical layout is French.
    323   delegate_->set_hardware_keyboard_layout("xkb:fr::fra");
    324   manager_->EnableLayouts("en-US", "");
    325   EXPECT_EQ(6U, manager_->GetNumActiveInputMethods());  // 5 + French
    326   // The physical layout is Japanese.
    327   delegate_->set_hardware_keyboard_layout("xkb:jp::jpn");
    328   manager_->EnableLayouts("ja", "");
    329   // "xkb:us::eng" is not needed, hence 1.
    330   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    331 }
    332 
    333 TEST_F(InputMethodManagerImplTest, TestActiveInputMethods) {
    334   manager_->EnableLayouts("ja", "");  // Japanese
    335   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    336   scoped_ptr<InputMethodDescriptors> methods(
    337       manager_->GetActiveInputMethods());
    338   ASSERT_TRUE(methods.get());
    339   EXPECT_EQ(2U, methods->size());
    340   const InputMethodDescriptor* id_to_find =
    341       manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    342           "xkb:us::eng");
    343   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
    344   id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
    345       "xkb:jp::jpn");
    346   EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
    347 }
    348 
    349 TEST_F(InputMethodManagerImplTest, TestSetInputMethodConfig) {
    350   InputMethodConfigValue config;
    351   config.type = InputMethodConfigValue::kValueTypeString;
    352   config.string_value = "string";
    353   EXPECT_EQ(0, controller_->set_input_method_config_internal_count_);
    354   EXPECT_TRUE(manager_->SetInputMethodConfig("section", "name", config));
    355   EXPECT_EQ(1, controller_->set_input_method_config_internal_count_);
    356   EXPECT_EQ("section",
    357             controller_->set_input_method_config_internal_key_.first);
    358   EXPECT_EQ("name",
    359             controller_->set_input_method_config_internal_key_.second);
    360   EXPECT_EQ(config.type,
    361             controller_->set_input_method_config_internal_value_.type);
    362   EXPECT_EQ(config.string_value,
    363             controller_->set_input_method_config_internal_value_.string_value);
    364 
    365   // SetInputMethodConfig should be no-op in STATE_TERMINATING.
    366   manager_->SetState(InputMethodManager::STATE_TERMINATING);
    367   EXPECT_FALSE(manager_->SetInputMethodConfig("section", "name", config));
    368   EXPECT_EQ(1, controller_->set_input_method_config_internal_count_);
    369 }
    370 
    371 TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) {
    372   // For http://crbug.com/19655#c11 - (8), step 6.
    373   TestObserver observer;
    374   manager_->AddObserver(&observer);
    375   InitComponentExtension();
    376   InitIBusBus();
    377   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    378   std::vector<std::string> ids;
    379   ids.push_back("xkb:us:dvorak:eng");
    380   ids.push_back("xkb:us:colemak:eng");
    381   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    382   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    383   // Since all the IDs added avobe are keyboard layouts, Start() should not be
    384   // called.
    385   EXPECT_EQ(0, mock_ibus_daemon_controller_->start_count());
    386   EXPECT_EQ(1, observer.input_method_changed_count_);
    387   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    388   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    389   // Disable Dvorak.
    390   ids.erase(ids.begin());
    391   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    392   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    393   EXPECT_EQ(2, observer.input_method_changed_count_);
    394   EXPECT_EQ(ids[0],  // colemak
    395             manager_->GetCurrentInputMethod().id());
    396   EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
    397   manager_->RemoveObserver(&observer);
    398 }
    399 
    400 TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) {
    401   // For http://crbug.com/19655#c11 - (9).
    402   TestObserver observer;
    403   manager_->AddObserver(&observer);
    404   InitComponentExtension();
    405   InitIBusBus();
    406   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    407   std::vector<std::string> ids;
    408   ids.push_back("xkb:us::eng");
    409   ids.push_back("xkb:us:dvorak:eng");
    410   ids.push_back("xkb:us:colemak:eng");
    411   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    412   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
    413   EXPECT_EQ(1, observer.input_method_changed_count_);
    414   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    415   EXPECT_EQ("us", xkeyboard_->last_layout_);
    416   // Switch to Dvorak.
    417   manager_->SwitchToNextInputMethod();
    418   EXPECT_EQ(2, observer.input_method_changed_count_);
    419   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    420   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    421   // Disable Dvorak.
    422   ids.erase(ids.begin() + 1);
    423   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    424   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    425   EXPECT_EQ(3, observer.input_method_changed_count_);
    426   EXPECT_EQ(ids[0],  // US Qwerty
    427             manager_->GetCurrentInputMethod().id());
    428   EXPECT_EQ("us", xkeyboard_->last_layout_);
    429   manager_->RemoveObserver(&observer);
    430 }
    431 
    432 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) {
    433   // For http://crbug.com/19655#c11 - (10).
    434   TestObserver observer;
    435   manager_->AddObserver(&observer);
    436   InitComponentExtension();
    437   InitIBusBus();
    438   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    439   std::vector<std::string> ids;
    440   ids.push_back("xkb:us:dvorak:eng");
    441   ids.push_back(nacl_mozc_us_id);
    442   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    443   EXPECT_EQ(1, mock_ibus_daemon_controller_->start_count());
    444   EXPECT_EQ(1, observer.input_method_changed_count_);
    445   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    446   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    447   // Switch to Mozc
    448   manager_->SwitchToNextInputMethod();
    449   EXPECT_EQ(2, observer.input_method_changed_count_);
    450   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    451   EXPECT_EQ("us", xkeyboard_->last_layout_);
    452   // Disable Mozc.
    453   ids.erase(ids.begin() + 1);
    454   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    455   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    456   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    457   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    458   // Currently, to work around  a crash issue at crosbug.com/27051,
    459   // controller_->Stop(); is NOT called when all IMEs are disabled
    460   // or on shutdown.
    461   EXPECT_EQ(0, mock_ibus_daemon_controller_->stop_count());
    462 
    463   manager_->SetState(InputMethodManager::STATE_TERMINATING);
    464   EXPECT_EQ(0, mock_ibus_daemon_controller_->stop_count());
    465   manager_->RemoveObserver(&observer);
    466 }
    467 
    468 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) {
    469   // For http://crbug.com/19655#c11 - (11).
    470   TestObserver observer;
    471   manager_->AddObserver(&observer);
    472   InitComponentExtension();
    473   InitIBusBus();
    474   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    475   std::vector<std::string> ids;
    476   ids.push_back("xkb:us:dvorak:eng");
    477   ids.push_back(nacl_mozc_us_id);
    478   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    479   EXPECT_EQ(1, mock_ibus_daemon_controller_->start_count());
    480   EXPECT_EQ(1, observer.input_method_changed_count_);
    481   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    482   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    483 
    484   // Disable Dvorak.
    485   ids.erase(ids.begin());
    486   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    487   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    488   EXPECT_EQ(ids[0],  // Mozc
    489             manager_->GetCurrentInputMethod().id());
    490   EXPECT_EQ("us", xkeyboard_->last_layout_);
    491   manager_->RemoveObserver(&observer);
    492 }
    493 
    494 TEST_F(InputMethodManagerImplTest, TestEnableImes) {
    495   TestObserver observer;
    496   manager_->AddObserver(&observer);
    497   InitComponentExtension();
    498   InitIBusBus();
    499   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    500   std::vector<std::string> ids;
    501   ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
    502   ids.push_back("mozc-dv");
    503   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    504   EXPECT_EQ(1, mock_ibus_daemon_controller_->start_count());
    505   EXPECT_EQ(1, observer.input_method_changed_count_);
    506   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    507   EXPECT_EQ("us", xkeyboard_->last_layout_);
    508   manager_->RemoveObserver(&observer);
    509 }
    510 
    511 TEST_F(InputMethodManagerImplTest, TestEnableUnknownIds) {
    512   TestObserver observer;
    513   manager_->AddObserver(&observer);
    514   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    515   std::vector<std::string> ids;
    516   ids.push_back("xkb:tl::tlh");  // Klingon, which is not supported.
    517   ids.push_back("unknown-super-cool-ime");
    518   EXPECT_FALSE(manager_->EnableInputMethods(ids));
    519 
    520   // TODO(yusukes): Should we fall back to the hardware keyboard layout in this
    521   // case?
    522   EXPECT_EQ(0, observer.input_method_changed_count_);
    523 
    524   manager_->RemoveObserver(&observer);
    525 }
    526 
    527 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) {
    528   // For http://crbug.com/19655#c11 - (14).
    529   TestObserver observer;
    530   manager_->AddObserver(&observer);
    531   InitComponentExtension();
    532   InitIBusBus();
    533   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    534   std::vector<std::string> ids;
    535   ids.push_back("xkb:us::eng");
    536   ids.push_back("xkb:us:dvorak:eng");
    537   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    538   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    539   EXPECT_EQ(1, observer.input_method_changed_count_);
    540   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    541   EXPECT_EQ("us", xkeyboard_->last_layout_);
    542 
    543   // Switch to Dvorak.
    544   manager_->SwitchToNextInputMethod();
    545   EXPECT_EQ(2, observer.input_method_changed_count_);
    546   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    547   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    548 
    549   // Lock screen
    550   manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
    551   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    552   EXPECT_EQ(ids[1],  // still Dvorak
    553             manager_->GetCurrentInputMethod().id());
    554   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    555   // Switch back to Qwerty.
    556   manager_->SwitchToNextInputMethod();
    557   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    558   EXPECT_EQ("us", xkeyboard_->last_layout_);
    559 
    560   // Unlock screen. The original state, Dvorak, is restored.
    561   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    562   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    563   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    564   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    565 
    566   manager_->RemoveObserver(&observer);
    567 }
    568 
    569 TEST_F(InputMethodManagerImplTest, SwithchInputMethodTest) {
    570   // For http://crbug.com/19655#c11 - (15).
    571   TestObserver observer;
    572   manager_->AddObserver(&observer);
    573   InitComponentExtension();
    574   InitIBusBus();
    575   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    576   std::vector<std::string> ids;
    577   ids.push_back("xkb:us:dvorak:eng");
    578   ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine2_engine_id");
    579   ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
    580   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    581   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
    582   EXPECT_EQ(1, observer.input_method_changed_count_);
    583   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
    584   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    585 
    586   // Switch to Mozc.
    587   manager_->SwitchToNextInputMethod();
    588   EXPECT_EQ(2, observer.input_method_changed_count_);
    589   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    590   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    591 
    592   // Lock screen
    593   manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
    594   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());  // Qwerty+Dvorak.
    595   EXPECT_EQ("xkb:us:dvorak:eng",
    596             manager_->GetCurrentInputMethod().id());
    597   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    598   // controller_->Stop() should never be called when the screen is locked even
    599   // after crosbug.com/27051 is fixed.
    600   EXPECT_EQ(0, mock_ibus_daemon_controller_->stop_count());
    601   manager_->SwitchToNextInputMethod();
    602   EXPECT_EQ("xkb:us::eng",  // The hardware keyboard layout.
    603             manager_->GetCurrentInputMethod().id());
    604   EXPECT_EQ("us", xkeyboard_->last_layout_);
    605 
    606   // Unlock screen. The original state, pinyin-dv, is restored.
    607   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    608   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());  // Dvorak and 2 IMEs.
    609   EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
    610   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    611 
    612   manager_->RemoveObserver(&observer);
    613 }
    614 
    615 TEST_F(InputMethodManagerImplTest, TestXkbSetting) {
    616   // For http://crbug.com/19655#c11 - (8), step 7-11.
    617   InitComponentExtension();
    618   InitIBusBus();
    619   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    620   std::vector<std::string> ids;
    621   ids.push_back("xkb:us:dvorak:eng");
    622   ids.push_back("xkb:us:colemak:eng");
    623   ids.push_back(nacl_mozc_jp_id);
    624   ids.push_back(nacl_mozc_us_id);
    625   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    626   EXPECT_EQ(4U, manager_->GetNumActiveInputMethods());
    627   EXPECT_EQ(1, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    628   // See input_methods.txt for an expected XKB layout name.
    629   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    630   manager_->SwitchToNextInputMethod();
    631   EXPECT_EQ(2, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    632   EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
    633   manager_->SwitchToNextInputMethod();
    634   EXPECT_EQ(3, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    635   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    636   manager_->SwitchToNextInputMethod();
    637   EXPECT_EQ(4, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    638   EXPECT_EQ("us", xkeyboard_->last_layout_);
    639   manager_->SwitchToNextInputMethod();
    640   EXPECT_EQ(5, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    641   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    642   // Disable Dvorak.
    643   ids.erase(ids.begin());
    644   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    645   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
    646   EXPECT_EQ(6, xkeyboard_->set_current_keyboard_layout_by_name_count_);
    647   EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
    648 }
    649 
    650 TEST_F(InputMethodManagerImplTest, TestActivateInputMethodProperty) {
    651   manager_->ActivateInputMethodProperty("key");
    652   EXPECT_EQ(1, controller_->activate_input_method_property_count_);
    653   EXPECT_EQ("key", controller_->activate_input_method_property_key_);
    654   manager_->ActivateInputMethodProperty("key2");
    655   EXPECT_EQ(2, controller_->activate_input_method_property_count_);
    656   EXPECT_EQ("key2", controller_->activate_input_method_property_key_);
    657 }
    658 
    659 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodProperties) {
    660   InitComponentExtension();
    661   InitIBusBus();
    662   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    663 
    664   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    665   std::vector<std::string> ids;
    666   ids.push_back("xkb:us::eng");
    667   ids.push_back(nacl_mozc_us_id);
    668   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    669   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    670   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    671   manager_->ChangeInputMethod(nacl_mozc_us_id);
    672 
    673   InputMethodPropertyList current_property_list;
    674   current_property_list.push_back(InputMethodProperty("key",
    675                                                       "label",
    676                                                       false,
    677                                                       false));
    678   controller_->SetCurrentPropertiesForTesting(current_property_list);
    679   controller_->NotifyPropertyChangedForTesting();
    680 
    681   ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
    682   EXPECT_EQ("key", manager_->GetCurrentInputMethodProperties().at(0).key);
    683 
    684   manager_->ChangeInputMethod("xkb:us::eng");
    685   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    686 
    687   // Delayed asynchronous property update signal from the Mozc IME.
    688   controller_->NotifyPropertyChangedForTesting();
    689   // When XKB layout is in use, GetCurrentInputMethodProperties() should always
    690   // return an empty list.
    691   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    692 }
    693 
    694 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodPropertiesTwoImes) {
    695   InitComponentExtension();
    696   InitIBusBus();
    697   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    698 
    699   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    700   std::vector<std::string> ids;
    701   ids.push_back(nacl_mozc_us_id);  // Japanese
    702   ids.push_back("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");  // T-Chinese
    703   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    704   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    705   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    706 
    707   InputMethodPropertyList current_property_list;
    708   current_property_list.push_back(InputMethodProperty("key-mozc",
    709                                                       "label",
    710                                                       false,
    711                                                       false));
    712   controller_->SetCurrentPropertiesForTesting(current_property_list);
    713   controller_->NotifyPropertyChangedForTesting();
    714 
    715   ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
    716   EXPECT_EQ("key-mozc", manager_->GetCurrentInputMethodProperties().at(0).key);
    717 
    718   manager_->ChangeInputMethod("_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id");
    719   // Since the IME is changed, the property for mozc Japanese should be hidden.
    720   EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
    721 
    722   // Asynchronous property update signal from mozc-chewing.
    723   current_property_list.clear();
    724   current_property_list.push_back(InputMethodProperty("key-chewing",
    725                                                       "label",
    726                                                       false,
    727                                                       false));
    728   controller_->SetCurrentPropertiesForTesting(current_property_list);
    729   controller_->NotifyPropertyChangedForTesting();
    730   ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
    731   EXPECT_EQ("key-chewing",
    732             manager_->GetCurrentInputMethodProperties().at(0).key);
    733 }
    734 
    735 TEST_F(InputMethodManagerImplTest, TestNextInputMethod) {
    736   TestObserver observer;
    737   manager_->AddObserver(&observer);
    738   InitComponentExtension();
    739   InitIBusBus();
    740   // For http://crbug.com/19655#c11 - (1)
    741   manager_->EnableLayouts("en-US", "xkb:us::eng");
    742   EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
    743   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    744   EXPECT_EQ("us", xkeyboard_->last_layout_);
    745   manager_->SwitchToNextInputMethod();
    746   EXPECT_TRUE(observer.last_show_message_);
    747   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
    748   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
    749   manager_->SwitchToNextInputMethod();
    750   EXPECT_TRUE(observer.last_show_message_);
    751   EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
    752   EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
    753   manager_->SwitchToNextInputMethod();
    754   EXPECT_TRUE(observer.last_show_message_);
    755   EXPECT_EQ("xkb:us:dvorak:eng", manager_->GetCurrentInputMethod().id());
    756   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    757   manager_->SwitchToNextInputMethod();
    758   EXPECT_TRUE(observer.last_show_message_);
    759   EXPECT_EQ("xkb:us:colemak:eng", manager_->GetCurrentInputMethod().id());
    760   EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
    761   manager_->SwitchToNextInputMethod();
    762   EXPECT_TRUE(observer.last_show_message_);
    763   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    764   EXPECT_EQ("us", xkeyboard_->last_layout_);
    765 
    766   manager_->RemoveObserver(&observer);
    767 }
    768 
    769 TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) {
    770   TestObserver observer;
    771   manager_->AddObserver(&observer);
    772   InitComponentExtension();
    773   InitIBusBus();
    774 
    775   ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    776   keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
    777   ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    778   keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
    779 
    780   manager_->EnableLayouts("en-US", "xkb:us::eng");
    781   EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
    782   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    783   EXPECT_EQ("us", xkeyboard_->last_layout_);
    784   EXPECT_TRUE(manager_->SwitchToNextInputMethod());
    785   EXPECT_TRUE(observer.last_show_message_);
    786   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
    787   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
    788   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    789   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    790   EXPECT_TRUE(observer.last_show_message_);
    791   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    792   EXPECT_EQ("us", xkeyboard_->last_layout_);
    793   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    794   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    795   EXPECT_TRUE(observer.last_show_message_);
    796   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
    797   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
    798   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    799   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    800   EXPECT_TRUE(observer.last_show_message_);
    801   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    802   EXPECT_EQ("us", xkeyboard_->last_layout_);
    803   EXPECT_TRUE(manager_->SwitchToNextInputMethod());
    804   EXPECT_TRUE(observer.last_show_message_);
    805   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
    806   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
    807   EXPECT_TRUE(manager_->SwitchToNextInputMethod());
    808   EXPECT_TRUE(observer.last_show_message_);
    809   EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
    810   EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
    811   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    812   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    813   EXPECT_TRUE(observer.last_show_message_);
    814   EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
    815   EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
    816   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    817   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    818   EXPECT_TRUE(observer.last_show_message_);
    819   EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
    820   EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
    821 
    822   manager_->RemoveObserver(&observer);
    823 }
    824 
    825 TEST_F(InputMethodManagerImplTest,
    826        TestSwitchToPreviousInputMethodForOneActiveInputMethod) {
    827   TestObserver observer;
    828   manager_->AddObserver(&observer);
    829   InitComponentExtension();
    830   InitIBusBus();
    831 
    832   ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    833   keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
    834   ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    835   keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
    836 
    837   std::vector<std::string> ids;
    838   ids.push_back("xkb:us:dvorak:eng");
    839   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    840   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    841 
    842   // Ctrl+Space accelerator should not be consumed if there is only one active
    843   // input method.
    844   EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    845   EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    846 
    847   manager_->RemoveObserver(&observer);
    848 }
    849 
    850 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) {
    851   TestObserver observer;
    852   manager_->AddObserver(&observer);
    853   InitComponentExtension();
    854   InitIBusBus();
    855   manager_->EnableLayouts("en-US", "xkb:us::eng");
    856   EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
    857   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    858   EXPECT_EQ("us", xkeyboard_->last_layout_);
    859 
    860   // Henkan, Muhenkan, ZenkakuHankaku should be ignored when no Japanese IMEs
    861   // and keyboards are enabled.
    862   EXPECT_FALSE(manager_->SwitchInputMethod(
    863       ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
    864   EXPECT_FALSE(observer.last_show_message_);
    865   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    866   EXPECT_EQ("us", xkeyboard_->last_layout_);
    867   EXPECT_FALSE(manager_->SwitchInputMethod(
    868       ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
    869   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    870   EXPECT_EQ("us", xkeyboard_->last_layout_);
    871   EXPECT_FALSE(manager_->SwitchInputMethod(
    872       ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
    873   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    874   EXPECT_EQ("us", xkeyboard_->last_layout_);
    875   EXPECT_FALSE(manager_->SwitchInputMethod(
    876       ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
    877   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    878   EXPECT_EQ("us", xkeyboard_->last_layout_);
    879 
    880   manager_->RemoveObserver(&observer);
    881 }
    882 
    883 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpLayout) {
    884   // Enable "xkb:jp::jpn" and press Muhenkan/ZenkakuHankaku.
    885   InitComponentExtension();
    886   InitIBusBus();
    887 
    888   ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    889   keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
    890   ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
    891   keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
    892 
    893   manager_->EnableLayouts("ja", "xkb:us::eng");
    894   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
    895   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    896   EXPECT_EQ("us", xkeyboard_->last_layout_);
    897   EXPECT_TRUE(manager_->SwitchInputMethod(
    898       ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
    899   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    900   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    901   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    902   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    903   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    904   EXPECT_EQ("us", xkeyboard_->last_layout_);
    905   EXPECT_TRUE(manager_->SwitchInputMethod(
    906       ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
    907   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    908   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    909   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
    910   EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
    911   EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
    912   EXPECT_EQ("us", xkeyboard_->last_layout_);
    913   EXPECT_TRUE(manager_->SwitchInputMethod(
    914       ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
    915   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    916   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    917 }
    918 
    919 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) {
    920   InitComponentExtension();
    921   InitIBusBus();
    922   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    923   std::vector<std::string> ids;
    924   ids.push_back("xkb:jp::jpn");
    925   ids.push_back(nacl_mozc_jp_id);
    926   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    927   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    928   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    929   EXPECT_TRUE(manager_->SwitchInputMethod(
    930       ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
    931   EXPECT_EQ(nacl_mozc_jp_id, manager_->GetCurrentInputMethod().id());
    932   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    933   EXPECT_TRUE(manager_->SwitchInputMethod(
    934       ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
    935   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    936   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    937   EXPECT_TRUE(manager_->SwitchInputMethod(
    938       ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
    939   EXPECT_EQ(nacl_mozc_jp_id, manager_->GetCurrentInputMethod().id());
    940   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    941   EXPECT_TRUE(manager_->SwitchInputMethod(
    942       ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
    943   EXPECT_EQ(nacl_mozc_jp_id, manager_->GetCurrentInputMethod().id());
    944   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    945   EXPECT_TRUE(manager_->SwitchInputMethod(
    946       ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
    947   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    948   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    949   EXPECT_TRUE(manager_->SwitchInputMethod(
    950       ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
    951   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    952   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    953 
    954   // Add Dvorak.
    955   ids.push_back("xkb:us:dvorak:eng");
    956   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    957   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    958   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    959   EXPECT_TRUE(manager_->SwitchInputMethod(
    960       ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
    961   EXPECT_EQ(nacl_mozc_jp_id, manager_->GetCurrentInputMethod().id());
    962   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    963   EXPECT_TRUE(manager_->SwitchInputMethod(
    964       ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
    965   EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
    966   EXPECT_EQ("jp", xkeyboard_->last_layout_);
    967 }
    968 
    969 TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) {
    970   TestObserver observer;
    971   manager_->AddObserver(&observer);
    972   InitComponentExtension();
    973   InitIBusBus();
    974   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
    975   std::vector<std::string> ids;
    976   ids.push_back("xkb:us:dvorak:eng");
    977   EXPECT_TRUE(manager_->EnableInputMethods(ids));
    978   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
    979   EXPECT_EQ(0, mock_ibus_daemon_controller_->start_count());
    980   EXPECT_EQ(1, observer.input_method_changed_count_);
    981   EXPECT_EQ(ids[0],
    982             manager_->GetCurrentInputMethod().id());
    983   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
    984 
    985   // Add two Extension IMEs.
    986   std::vector<std::string> layouts;
    987   layouts.push_back("us");
    988   std::vector<std::string> languages;
    989   languages.push_back("en-US");
    990   manager_->AddInputMethodExtension(
    991       extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
    992       "deadbeef input method",
    993       layouts,
    994       languages,
    995       GURL(),
    996       NULL);
    997 
    998   // Extension IMEs are not enabled by default.
    999   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1000 
   1001   std::vector<std::string> extension_ime_ids;
   1002   extension_ime_ids.push_back(
   1003       extension_ime_util::GetInputMethodID("deadbeef", "engine_id"));
   1004   manager_->SetEnabledExtensionImes(&extension_ime_ids);
   1005   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1006 
   1007   // should be started.
   1008   EXPECT_EQ(1, mock_ibus_daemon_controller_->start_count());
   1009   {
   1010     scoped_ptr<InputMethodDescriptors> methods(
   1011         manager_->GetActiveInputMethods());
   1012     ASSERT_EQ(2U, methods->size());
   1013     EXPECT_EQ(extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1014               // Ext IMEs should be at the end of the list.
   1015               methods->at(1).id());
   1016   }
   1017   manager_->AddInputMethodExtension(
   1018       extension_ime_util::GetInputMethodID("cafebabe", "engine_id"),
   1019       "cafebabe input method",
   1020       layouts,
   1021       languages,
   1022       GURL(),
   1023       NULL);
   1024   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1025 
   1026   extension_ime_ids.push_back(
   1027       extension_ime_util::GetInputMethodID("cafebabe", "engine_id"));
   1028   manager_->SetEnabledExtensionImes(&extension_ime_ids);
   1029   EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
   1030   {
   1031     scoped_ptr<InputMethodDescriptors> methods(
   1032         manager_->GetActiveInputMethods());
   1033     ASSERT_EQ(3U, methods->size());
   1034     EXPECT_EQ(extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1035               // Ext IMEs should be at the end of the list.
   1036               methods->at(1).id());
   1037   }
   1038 
   1039   // Remove them.
   1040   manager_->RemoveInputMethodExtension(
   1041       extension_ime_util::GetInputMethodID("deadbeef", "engine_id"));
   1042   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1043   manager_->RemoveInputMethodExtension(
   1044       extension_ime_util::GetInputMethodID("cafebabe", "engine_id"));
   1045   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1046   // Currently, to work around  a crash issue at crosbug.com/27051,
   1047   // controller_->Stop(); is NOT called when all (extension) IMEs are disabled.
   1048   EXPECT_EQ(0, mock_ibus_daemon_controller_->stop_count());
   1049 
   1050   manager_->RemoveObserver(&observer);
   1051 }
   1052 
   1053 TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) {
   1054   TestObserver observer;
   1055   InitComponentExtension();
   1056   InitIBusBus();
   1057   manager_->AddObserver(&observer);
   1058   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1059   std::vector<std::string> ids;
   1060   ids.push_back("xkb:us::eng");
   1061   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1062   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1063   EXPECT_EQ(1, observer.input_method_changed_count_);
   1064   EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
   1065   EXPECT_EQ("us", xkeyboard_->last_layout_);
   1066 
   1067   // Add an Extension IME.
   1068   std::vector<std::string> layouts;
   1069   layouts.push_back("us(dvorak)");
   1070   std::vector<std::string> languages;
   1071   languages.push_back("en-US");
   1072   manager_->AddInputMethodExtension(
   1073       extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1074       "deadbeef input method",
   1075       layouts,
   1076       languages,
   1077       GURL(),
   1078       NULL);
   1079   // Extension IME is not enabled by default.
   1080   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1081   EXPECT_EQ(1, observer.input_method_changed_count_);
   1082 
   1083   std::vector<std::string> extension_ime_ids;
   1084   extension_ime_ids.push_back(
   1085       extension_ime_util::GetInputMethodID("deadbeef", "engine_id"));
   1086   manager_->SetEnabledExtensionImes(&extension_ime_ids);
   1087   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1088 
   1089   // Switch to the IME.
   1090   manager_->SwitchToNextInputMethod();
   1091   EXPECT_EQ(3, observer.input_method_changed_count_);
   1092   EXPECT_EQ(extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1093             manager_->GetCurrentInputMethod().id());
   1094   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
   1095 
   1096   // Lock the screen. This is for crosbug.com/27049.
   1097   manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
   1098   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());  // Qwerty. No Ext. IME
   1099   EXPECT_EQ("xkb:us::eng",
   1100             manager_->GetCurrentInputMethod().id());
   1101   EXPECT_EQ("us", xkeyboard_->last_layout_);
   1102   EXPECT_EQ(0, mock_ibus_daemon_controller_->stop_count());
   1103 
   1104   // Unlock the screen.
   1105   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1106   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1107   EXPECT_EQ(extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1108             manager_->GetCurrentInputMethod().id());
   1109   EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
   1110   {
   1111     // This is for crosbug.com/27052.
   1112     scoped_ptr<InputMethodDescriptors> methods(
   1113         manager_->GetActiveInputMethods());
   1114     ASSERT_EQ(2U, methods->size());
   1115     EXPECT_EQ(extension_ime_util::GetInputMethodID("deadbeef", "engine_id"),
   1116               // Ext. IMEs should be at the end of the list.
   1117               methods->at(1).id());
   1118   }
   1119   manager_->RemoveObserver(&observer);
   1120 }
   1121 
   1122 TEST_F(InputMethodManagerImplTest, TestReset) {
   1123   InitComponentExtension();
   1124   InitIBusBus();
   1125   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1126   std::vector<std::string> ids;
   1127   ids.push_back("xkb:us::eng");
   1128   ids.push_back(nacl_mozc_us_id);
   1129   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1130   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1131   EXPECT_EQ(1, mock_ibus_input_context_client_->reset_call_count());
   1132   manager_->ChangeInputMethod(nacl_mozc_us_id);
   1133   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1134   EXPECT_EQ(nacl_mozc_us_id, mock_ibus_client_->latest_global_engine_name());
   1135   EXPECT_EQ(1, mock_ibus_input_context_client_->reset_call_count());
   1136   manager_->ChangeInputMethod("xkb:us::eng");
   1137   EXPECT_EQ(2, mock_ibus_client_->set_global_engine_call_count());
   1138   EXPECT_EQ(nacl_mozc_us_id, mock_ibus_client_->latest_global_engine_name());
   1139   EXPECT_EQ(1, mock_ibus_input_context_client_->reset_call_count());
   1140 }
   1141 
   1142 TEST_F(InputMethodManagerImplTest,
   1143        ChangeInputMethodBeforeComponentExtensionInitialization_OneIME) {
   1144   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1145   std::vector<std::string> ids;
   1146   ids.push_back(nacl_mozc_us_id);
   1147   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1148   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1149   manager_->ChangeInputMethod(nacl_mozc_us_id);
   1150 
   1151   InitIBusBus();
   1152   InitComponentExtension();
   1153   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1154   EXPECT_EQ(nacl_mozc_us_id, mock_ibus_client_->latest_global_engine_name());
   1155 }
   1156 
   1157 TEST_F(InputMethodManagerImplTest,
   1158        ChangeInputMethodBeforeComponentExtensionInitialization_TwoIME) {
   1159   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1160   std::vector<std::string> ids;
   1161   ids.push_back(nacl_mozc_us_id);
   1162   ids.push_back(nacl_mozc_jp_id);
   1163   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1164   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1165   manager_->ChangeInputMethod(nacl_mozc_us_id);
   1166   manager_->ChangeInputMethod(nacl_mozc_jp_id);
   1167 
   1168   InitComponentExtension();
   1169   InitIBusBus();
   1170   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1171   EXPECT_EQ(nacl_mozc_jp_id, mock_ibus_client_->latest_global_engine_name());
   1172 }
   1173 
   1174 TEST_F(InputMethodManagerImplTest,
   1175        ChangeInputMethodBeforeComponentExtensionInitialization_CompOneIME) {
   1176   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1177   const std::string ext_id =
   1178       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1179           ime_list_[0].id,
   1180           ime_list_[0].engines[0].engine_id);
   1181   std::vector<std::string> ids;
   1182   ids.push_back(ext_id);
   1183   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1184   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1185   manager_->ChangeInputMethod(ext_id);
   1186 
   1187   InitComponentExtension();
   1188   InitIBusBus();
   1189   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1190   EXPECT_EQ(ext_id, mock_ibus_client_->latest_global_engine_name());
   1191 }
   1192 
   1193 TEST_F(InputMethodManagerImplTest,
   1194        ChangeInputMethodBeforeComponentExtensionInitialization_CompTwoIME) {
   1195   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1196   const std::string ext_id1 =
   1197       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1198           ime_list_[0].id,
   1199           ime_list_[0].engines[0].engine_id);
   1200   const std::string ext_id2 =
   1201       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1202           ime_list_[1].id,
   1203           ime_list_[1].engines[0].engine_id);
   1204   std::vector<std::string> ids;
   1205   ids.push_back(ext_id1);
   1206   ids.push_back(ext_id2);
   1207   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1208   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1209   manager_->ChangeInputMethod(ext_id1);
   1210   manager_->ChangeInputMethod(ext_id2);
   1211 
   1212   InitComponentExtension();
   1213   InitIBusBus();
   1214   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1215   EXPECT_EQ(ext_id2, mock_ibus_client_->latest_global_engine_name());
   1216 }
   1217 
   1218 TEST_F(InputMethodManagerImplTest,
   1219        ChangeInputMethod_ComponenteExtensionOneIME) {
   1220   InitComponentExtension();
   1221   InitIBusBus();
   1222   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1223   const std::string ext_id =
   1224       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1225           ime_list_[0].id,
   1226           ime_list_[0].engines[0].engine_id);
   1227   std::vector<std::string> ids;
   1228   ids.push_back(ext_id);
   1229   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1230   EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
   1231   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1232   EXPECT_EQ(ext_id, mock_ibus_client_->latest_global_engine_name());
   1233 }
   1234 
   1235 TEST_F(InputMethodManagerImplTest,
   1236        ChangeInputMethod_ComponenteExtensionTwoIME) {
   1237   InitComponentExtension();
   1238   InitIBusBus();
   1239   manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
   1240   const std::string ext_id1 =
   1241       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1242           ime_list_[0].id,
   1243           ime_list_[0].engines[0].engine_id);
   1244   const std::string ext_id2 =
   1245       TestableComponentExtensionIMEManager::GetComponentExtensionIMEId(
   1246           ime_list_[1].id,
   1247           ime_list_[1].engines[0].engine_id);
   1248   std::vector<std::string> ids;
   1249   ids.push_back(ext_id1);
   1250   ids.push_back(ext_id2);
   1251   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1252   EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
   1253   EXPECT_EQ(1, mock_ibus_client_->set_global_engine_call_count());
   1254   EXPECT_EQ(ext_id1, mock_ibus_client_->latest_global_engine_name());
   1255   manager_->ChangeInputMethod(ext_id2);
   1256   EXPECT_EQ(2, mock_ibus_client_->set_global_engine_call_count());
   1257   EXPECT_EQ(ext_id2, mock_ibus_client_->latest_global_engine_name());
   1258 }
   1259 
   1260 TEST_F(InputMethodManagerImplTest,
   1261        MigrateOldInputMethodTest) {
   1262   std::vector<std::string> input_method_ids;
   1263   input_method_ids.push_back("mozc");
   1264   input_method_ids.push_back("mozc-jp");
   1265   input_method_ids.push_back("xkb:us::eng");
   1266   input_method_ids.push_back(nacl_mozc_us_id);
   1267 
   1268   manager_->MigrateOldInputMethods(&input_method_ids);
   1269 
   1270   ASSERT_EQ(4U, input_method_ids.size());
   1271   EXPECT_EQ(input_method_ids.end(),
   1272             std::find(input_method_ids.begin(), input_method_ids.end(),
   1273                       "mozc"));
   1274   EXPECT_EQ(input_method_ids.end(),
   1275             std::find(input_method_ids.begin(), input_method_ids.end(),
   1276                       "mozc-jp"));
   1277   EXPECT_NE(input_method_ids.end(),
   1278             std::find(input_method_ids.begin(), input_method_ids.end(),
   1279                       "xkb:us::eng"));
   1280   EXPECT_NE(input_method_ids.end(),
   1281             std::find(input_method_ids.begin(), input_method_ids.end(),
   1282                       nacl_mozc_us_id));
   1283 
   1284 }
   1285 
   1286 TEST_F(InputMethodManagerImplTest,
   1287        AsyncComponentExtentionInitializeBeforeIBusDaemonConnection) {
   1288   const std::string xkb_id = "xkb:cz::cze";
   1289   const std::string ime_id = nacl_mozc_us_id;
   1290   const std::string fallback_id = "xkb:us::eng";
   1291   std::vector<std::string> ids;
   1292   ids.push_back(xkb_id);
   1293   ids.push_back(ime_id);
   1294   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1295 
   1296   // If component extension IME is not initialized, even XKB layout cannot be
   1297   // enabled.
   1298   manager_->ChangeInputMethod(xkb_id);
   1299   EXPECT_EQ(fallback_id, manager_->GetCurrentInputMethod().id());
   1300 
   1301   // After component extension IME is initialized, previous input method should
   1302   // be automatically enabled.
   1303   InitComponentExtension();
   1304   EXPECT_EQ(xkb_id, manager_->GetCurrentInputMethod().id());
   1305 
   1306   // However input method should not be enabled before establishment of
   1307   // connection with ibus-daemon.
   1308   manager_->ChangeInputMethod(ime_id);
   1309   // TODO(nona): Write expectation, GetCurrentInputMethod returns |ime_id| even
   1310   //             the actual input method is not changed.
   1311 
   1312   // After connection with ibus-daemon is established, previous specified input
   1313   // method should be enabled automatically.
   1314   InitIBusBus();
   1315   EXPECT_EQ(ime_id, manager_->GetCurrentInputMethod().id());
   1316 }
   1317 
   1318 TEST_F(InputMethodManagerImplTest,
   1319        AsyncComponentExtentionInitializeAfterIBusDaemonConnection) {
   1320   const std::string xkb_id = "xkb:cz::cze";
   1321   const std::string ime_id = nacl_mozc_us_id;
   1322   const std::string fallback_id = "xkb:us::eng";
   1323   std::vector<std::string> ids;
   1324   ids.push_back(xkb_id);
   1325   ids.push_back(ime_id);
   1326   EXPECT_TRUE(manager_->EnableInputMethods(ids));
   1327 
   1328   // If component extension IME is not initialized, even XKB layout cannot be
   1329   // enabled.
   1330   manager_->ChangeInputMethod(xkb_id);
   1331   EXPECT_EQ(fallback_id, manager_->GetCurrentInputMethod().id());
   1332 
   1333   // Even after connection with ibus-daemon is established, ChangeInputMethod do
   1334   // nothing without component extension IME initialization.
   1335   InitIBusBus();
   1336   EXPECT_EQ(fallback_id, manager_->GetCurrentInputMethod().id());
   1337 
   1338   // After component extension IME is initialized, previous specified input
   1339   // method should be automatically enabled.
   1340   InitComponentExtension();
   1341   EXPECT_EQ(xkb_id, manager_->GetCurrentInputMethod().id());
   1342 }
   1343 
   1344 }  // namespace input_method
   1345 }  // namespace chromeos
   1346