| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/input_method/input_method_manager_impl.h" |
| |
| #include <stddef.h> |
| |
| #include <algorithm> |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| |
| #include "ash/public/cpp/ime_controller.h" |
| #include "base/compiler_specific.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/i18n/string_compare.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/task_environment.h" |
| #include "chrome/browser/ash/input_method/mock_candidate_window_controller.h" |
| #include "chrome/browser/ash/input_method/mock_input_method_engine.h" |
| #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/ash/ime_controller_client_impl.h" |
| #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h" |
| #include "chrome/browser/ui/ash/test_ime_controller.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "chromeos/components/kiosk/kiosk_test_utils.h" |
| #include "components/account_id/account_id.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/icu/source/common/unicode/uloc.h" |
| #include "third_party/icu/source/i18n/unicode/coll.h" |
| #include "ui/base/ime/ash/component_extension_ime_manager.h" |
| #include "ui/base/ime/ash/extension_ime_util.h" |
| #include "ui/base/ime/ash/fake_ime_keyboard.h" |
| #include "ui/base/ime/ash/fake_input_method_delegate.h" |
| #include "ui/base/ime/ash/ime_bridge.h" |
| #include "ui/base/ime/ash/mock_component_extension_ime_manager_delegate.h" |
| #include "ui/base/ime/ash/mock_ime_engine_handler.h" |
| #include "ui/base/ime/init/input_method_initializer.h" |
| #include "ui/base/ui_base_features.h" |
| |
| namespace ash { |
| namespace input_method { |
| namespace { |
| |
| const char kNaclMozcUsId[] = "nacl_mozc_us"; |
| const char kNaclMozcJpId[] = "nacl_mozc_jp"; |
| const char kExt2Engine1Id[] = "ext2_engine1-t-i0-engine_id"; |
| const char kExt2Engine2Id[] = "ext2_engine2-t-i0-engine_id"; |
| const char kPinyinImeId[] = "zh-t-i0-pinyin"; |
| const char kExtensionId1[] = "00000000000000000000000000000000"; |
| const char kExtensionId2[] = "11111111111111111111111111111111"; |
| |
| // Returns true if |descriptors| contain |target|. |
| bool Contain(const InputMethodDescriptors& descriptors, |
| const InputMethodDescriptor& target) { |
| for (const auto& descriptor : descriptors) { |
| if (descriptor.id() == target.id()) |
| return true; |
| } |
| return false; |
| } |
| |
| std::string ImeIdFromEngineId(const std::string& id) { |
| return extension_ime_util::GetInputMethodIDByEngineID(id); |
| } |
| |
| class TestObserver : public InputMethodManager::Observer, |
| public ui::ime::InputMethodMenuManager::Observer { |
| public: |
| TestObserver() |
| : input_method_changed_count_(0), |
| input_method_extension_added_count_(0), |
| input_method_extension_removed_count_(0), |
| input_method_menu_item_changed_count_(0), |
| last_show_message_(false) {} |
| |
| TestObserver(const TestObserver&) = delete; |
| TestObserver& operator=(const TestObserver&) = delete; |
| |
| ~TestObserver() override = default; |
| |
| void InputMethodChanged(InputMethodManager* manager, |
| Profile* /* profile */, |
| bool show_message) override { |
| ++input_method_changed_count_; |
| last_show_message_ = show_message; |
| } |
| |
| void OnInputMethodExtensionAdded(const std::string& id) override { |
| ++input_method_extension_added_count_; |
| } |
| |
| void OnInputMethodExtensionRemoved(const std::string& id) override { |
| ++input_method_extension_removed_count_; |
| } |
| |
| void InputMethodMenuItemChanged( |
| ui::ime::InputMethodMenuManager* manager) override { |
| ++input_method_menu_item_changed_count_; |
| } |
| |
| int input_method_changed_count_; |
| int input_method_extension_added_count_; |
| int input_method_extension_removed_count_; |
| int input_method_menu_item_changed_count_; |
| bool last_show_message_; |
| }; |
| |
| class TestCandidateWindowObserver |
| : public InputMethodManager::CandidateWindowObserver { |
| public: |
| TestCandidateWindowObserver() |
| : candidate_window_opened_count_(0), |
| candidate_window_closed_count_(0) { |
| } |
| |
| TestCandidateWindowObserver(const TestCandidateWindowObserver&) = delete; |
| TestCandidateWindowObserver& operator=(const TestCandidateWindowObserver&) = |
| delete; |
| |
| ~TestCandidateWindowObserver() override = default; |
| |
| void CandidateWindowOpened(InputMethodManager* manager) override { |
| ++candidate_window_opened_count_; |
| } |
| void CandidateWindowClosed(InputMethodManager* manager) override { |
| ++candidate_window_closed_count_; |
| } |
| |
| int candidate_window_opened_count_; |
| int candidate_window_closed_count_; |
| }; |
| } // namespace |
| |
| class InputMethodManagerImplTest : public BrowserWithTestWindowTest { |
| public: |
| InputMethodManagerImplTest() = default; |
| |
| InputMethodManagerImplTest(const InputMethodManagerImplTest&) = delete; |
| InputMethodManagerImplTest& operator=(const InputMethodManagerImplTest&) = |
| delete; |
| |
| ~InputMethodManagerImplTest() override = default; |
| |
| void SetUp() override { |
| std::vector<ComponentExtensionIME> ime_list; |
| InitImeList(ime_list); |
| |
| std::set<std::string> login_layout_set = {"us", |
| "us(intl)", |
| "us(altgr-intl)", |
| "us(dvorak)", |
| "us(dvp)", |
| "us(colemak)", |
| "us(workman)", |
| "us(workman-intl)", |
| "fr", |
| "se", |
| "jp", |
| "hu", |
| "de"}; |
| |
| auto mock_delegate = |
| std::make_unique<MockComponentExtensionIMEManagerDelegate>(); |
| mock_delegate->set_ime_list(ime_list); |
| mock_delegate->set_login_layout_set(login_layout_set); |
| |
| auto fake_keyboard = std::make_unique<FakeImeKeyboard>(); |
| keyboard_ = fake_keyboard.get(); |
| |
| manager_ = new InputMethodManagerImpl( |
| std::make_unique<FakeInputMethodDelegate>(), std::move(mock_delegate), |
| false, std::move(fake_keyboard)); |
| manager_->GetInputMethodUtil()->UpdateHardwareLayoutCache(); |
| candidate_window_controller_ = new MockCandidateWindowController; |
| manager_->SetCandidateWindowControllerForTesting( |
| candidate_window_controller_); |
| mock_engine_handler_ = std::make_unique<MockInputMethodEngine>(); |
| IMEBridge::Get()->SetCurrentEngineHandler(mock_engine_handler_.get()); |
| |
| menu_manager_ = ui::ime::InputMethodMenuManager::GetInstance(); |
| |
| // Let the global pointer own manager_. Components in ash need to be |
| // able to call InputMethodManager::Get() during initialization. Cleanup |
| // the pointer by calling ShutDown() in TearDown(). |
| InputMethodManager::Initialize(manager_); |
| BrowserWithTestWindowTest::SetUp(); |
| |
| // Needs ash::Shell keyboard to be created first. |
| chrome_keyboard_controller_client_test_helper_ = |
| ChromeKeyboardControllerClientTestHelper::InitializeForAsh(); |
| |
| // CreateNewState(nullptr) returns state with non-empty |
| // current_input_method. So SetState() triggers ChangeInputMethod(). |
| InputMethodDescriptors descriptors; |
| auto state = |
| manager_->CreateNewState(ProfileManager::GetActiveUserProfile()); |
| state->AddInputMethodExtension(extension_ime_util::kXkbExtensionId, |
| descriptors, mock_engine_handler_.get()); |
| state->AddInputMethodExtension(extension_ime_util::kMozcExtensionId, |
| descriptors, mock_engine_handler_.get()); |
| state->AddInputMethodExtension(extension_ime_util::kT13nExtensionId, |
| descriptors, mock_engine_handler_.get()); |
| manager_->SetState(state); |
| } |
| |
| void TearDown() override { |
| // Needs to destroyed before ash::Shell keyboard. |
| chrome_keyboard_controller_client_test_helper_.reset(); |
| |
| BrowserWithTestWindowTest::TearDown(); |
| |
| candidate_window_controller_ = nullptr; |
| keyboard_ = nullptr; |
| |
| // Cleanup the global manager and clear the member pointer. |
| InputMethodManager::Shutdown(); |
| manager_ = nullptr; |
| } |
| |
| private: |
| static void InitImeList(std::vector<ComponentExtensionIME>& ime_list) { |
| ime_list.clear(); |
| |
| ComponentExtensionIME ext_xkb; |
| ext_xkb.id = extension_ime_util::kXkbExtensionId; |
| ext_xkb.description = "ext_xkb_description"; |
| ext_xkb.path = base::FilePath("ext_xkb_file_path"); |
| |
| ComponentExtensionEngine ext_xkb_engine_us; |
| ext_xkb_engine_us.engine_id = "xkb:us::eng"; |
| ext_xkb_engine_us.display_name = "xkb:us::eng"; |
| ext_xkb_engine_us.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_us.layout = "us"; |
| ext_xkb.engines.push_back(ext_xkb_engine_us); |
| |
| ComponentExtensionEngine ext_xkb_engine_intl; |
| ext_xkb_engine_intl.engine_id = "xkb:us:intl:eng"; |
| ext_xkb_engine_intl.display_name = "xkb:us:intl:eng"; |
| ext_xkb_engine_intl.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_intl.layout = "us(intl)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_intl); |
| |
| ComponentExtensionEngine ext_xkb_engine_altgr_intl; |
| ext_xkb_engine_altgr_intl.engine_id = "xkb:us:altgr-intl:eng"; |
| ext_xkb_engine_altgr_intl.display_name = "xkb:us:altgr-intl:eng"; |
| ext_xkb_engine_altgr_intl.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_altgr_intl.layout = "us(altgr-intl)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_altgr_intl); |
| |
| ComponentExtensionEngine ext_xkb_engine_dvorak; |
| ext_xkb_engine_dvorak.engine_id = "xkb:us:dvorak:eng"; |
| ext_xkb_engine_dvorak.display_name = "xkb:us:dvorak:eng"; |
| ext_xkb_engine_dvorak.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_dvorak.layout = "us(dvorak)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_dvorak); |
| |
| ComponentExtensionEngine ext_xkb_engine_dvp; |
| ext_xkb_engine_dvp.engine_id = "xkb:us:dvp:eng"; |
| ext_xkb_engine_dvp.display_name = "xkb:us:dvp:eng"; |
| ext_xkb_engine_dvp.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_dvp.layout = "us(dvp)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_dvp); |
| |
| ComponentExtensionEngine ext_xkb_engine_colemak; |
| ext_xkb_engine_colemak.engine_id = "xkb:us:colemak:eng"; |
| ext_xkb_engine_colemak.display_name = "xkb:us:colemak:eng"; |
| ext_xkb_engine_colemak.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_colemak.layout = "us(colemak)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_colemak); |
| |
| ComponentExtensionEngine ext_xkb_engine_workman; |
| ext_xkb_engine_workman.engine_id = "xkb:us:workman:eng"; |
| ext_xkb_engine_workman.display_name = "xkb:us:workman:eng"; |
| ext_xkb_engine_workman.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_workman.layout = "us(workman)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_workman); |
| |
| ComponentExtensionEngine ext_xkb_engine_workman_intl; |
| ext_xkb_engine_workman_intl.engine_id = "xkb:us:workman-intl:eng"; |
| ext_xkb_engine_workman_intl.display_name = "xkb:us:workman-intl:eng"; |
| ext_xkb_engine_workman_intl.language_codes.emplace_back("en-US"); |
| ext_xkb_engine_workman_intl.layout = "us(workman-intl)"; |
| ext_xkb.engines.push_back(ext_xkb_engine_workman_intl); |
| |
| ComponentExtensionEngine ext_xkb_engine_fr; |
| ext_xkb_engine_fr.engine_id = "xkb:fr::fra"; |
| ext_xkb_engine_fr.display_name = "xkb:fr::fra"; |
| ext_xkb_engine_fr.language_codes.emplace_back("fr"); |
| ext_xkb_engine_fr.layout = "fr"; |
| ext_xkb.engines.push_back(ext_xkb_engine_fr); |
| |
| ComponentExtensionEngine ext_xkb_engine_se; |
| ext_xkb_engine_se.engine_id = "xkb:se::swe"; |
| ext_xkb_engine_se.display_name = "xkb:se::swe"; |
| ext_xkb_engine_se.language_codes.emplace_back("sv"); |
| ext_xkb_engine_se.layout = "se"; |
| ext_xkb.engines.push_back(ext_xkb_engine_se); |
| |
| ComponentExtensionEngine ext_xkb_engine_jp; |
| ext_xkb_engine_jp.engine_id = "xkb:jp::jpn"; |
| ext_xkb_engine_jp.display_name = "xkb:jp::jpn"; |
| ext_xkb_engine_jp.language_codes.emplace_back("ja"); |
| ext_xkb_engine_jp.layout = "jp"; |
| ext_xkb.engines.push_back(ext_xkb_engine_jp); |
| |
| ComponentExtensionEngine ext_xkb_engine_ru; |
| ext_xkb_engine_ru.engine_id = "xkb:ru::rus"; |
| ext_xkb_engine_ru.display_name = "xkb:ru::rus"; |
| ext_xkb_engine_ru.language_codes.emplace_back("ru"); |
| ext_xkb_engine_ru.layout = "ru"; |
| ext_xkb.engines.push_back(ext_xkb_engine_ru); |
| |
| ComponentExtensionEngine ext_xkb_engine_hu; |
| ext_xkb_engine_hu.engine_id = "xkb:hu::hun"; |
| ext_xkb_engine_hu.display_name = "xkb:hu::hun"; |
| ext_xkb_engine_hu.language_codes.emplace_back("hu"); |
| ext_xkb_engine_hu.layout = "hu"; |
| ext_xkb.engines.push_back(ext_xkb_engine_hu); |
| |
| ComponentExtensionEngine ext_xkb_engine_de; |
| ext_xkb_engine_de.engine_id = "xkb:de::ger"; |
| ext_xkb_engine_de.display_name = "xkb:de::ger"; |
| ext_xkb_engine_de.language_codes.emplace_back("de"); |
| ext_xkb_engine_de.layout = "de"; |
| ext_xkb.engines.push_back(ext_xkb_engine_de); |
| |
| ime_list.push_back(ext_xkb); |
| |
| ComponentExtensionIME ext1; |
| ext1.id = extension_ime_util::kMozcExtensionId; |
| ext1.description = "ext1_description"; |
| ext1.path = base::FilePath("ext1_file_path"); |
| |
| ComponentExtensionEngine ext1_engine1; |
| ext1_engine1.engine_id = "nacl_mozc_us"; |
| ext1_engine1.display_name = "ext1_engine_1_display_name"; |
| ext1_engine1.language_codes.emplace_back("ja"); |
| ext1_engine1.layout = "us"; |
| ext1.engines.push_back(ext1_engine1); |
| |
| ComponentExtensionEngine ext1_engine2; |
| ext1_engine2.engine_id = "nacl_mozc_jp"; |
| ext1_engine2.display_name = "ext1_engine_1_display_name"; |
| ext1_engine2.language_codes.emplace_back("ja"); |
| ext1_engine2.layout = "jp"; |
| ext1.engines.push_back(ext1_engine2); |
| |
| ime_list.push_back(ext1); |
| |
| ComponentExtensionIME ext2; |
| ext2.id = extension_ime_util::kT13nExtensionId; |
| ext2.description = "ext2_description"; |
| ext2.path = base::FilePath("ext2_file_path"); |
| |
| ComponentExtensionEngine ext2_engine1; |
| ext2_engine1.engine_id = kExt2Engine1Id; |
| ext2_engine1.display_name = "ext2_engine_1_display_name"; |
| ext2_engine1.language_codes.emplace_back("en"); |
| ext2_engine1.layout = "us"; |
| ext2.engines.push_back(ext2_engine1); |
| |
| ComponentExtensionEngine ext2_engine2; |
| ext2_engine2.engine_id = kExt2Engine2Id; |
| ext2_engine2.display_name = "ext2_engine_2_display_name"; |
| ext2_engine2.language_codes.emplace_back("en"); |
| ext2_engine2.layout = "us(dvorak)"; |
| ext2.engines.push_back(ext2_engine2); |
| |
| ime_list.push_back(ext2); |
| } |
| |
| protected: |
| std::unique_ptr<ChromeKeyboardControllerClientTestHelper> |
| chrome_keyboard_controller_client_test_helper_; |
| raw_ptr<InputMethodManagerImpl, DanglingUntriaged> manager_ = nullptr; |
| raw_ptr<MockCandidateWindowController> candidate_window_controller_ = nullptr; |
| std::unique_ptr<MockInputMethodEngine> mock_engine_handler_; |
| raw_ptr<FakeImeKeyboard> keyboard_ = nullptr; |
| raw_ptr<ui::ime::InputMethodMenuManager> menu_manager_; |
| }; |
| |
| TEST_F(InputMethodManagerImplTest, TestGetImeKeyboard) { |
| EXPECT_TRUE(manager_->GetImeKeyboard()); |
| EXPECT_EQ(keyboard_, manager_->GetImeKeyboard()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestCandidateWindowObserver) { |
| TestCandidateWindowObserver observer; |
| candidate_window_controller_->NotifyCandidateWindowOpened(); // nop |
| candidate_window_controller_->NotifyCandidateWindowClosed(); // nop |
| manager_->AddCandidateWindowObserver(&observer); |
| candidate_window_controller_->NotifyCandidateWindowOpened(); |
| EXPECT_EQ(1, observer.candidate_window_opened_count_); |
| candidate_window_controller_->NotifyCandidateWindowClosed(); |
| EXPECT_EQ(1, observer.candidate_window_closed_count_); |
| candidate_window_controller_->NotifyCandidateWindowOpened(); |
| EXPECT_EQ(2, observer.candidate_window_opened_count_); |
| candidate_window_controller_->NotifyCandidateWindowClosed(); |
| EXPECT_EQ(2, observer.candidate_window_closed_count_); |
| manager_->RemoveCandidateWindowObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestObserver) { |
| // For http://crbug.com/19655#c11 - (3). |
| std::vector<std::string> keyboard_layouts; |
| keyboard_layouts.emplace_back("xkb:us::eng"); |
| |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| menu_manager_->AddObserver(&observer); |
| EXPECT_EQ(0, observer.input_method_changed_count_); |
| EXPECT_EQ(0, observer.input_method_extension_added_count_); |
| EXPECT_EQ(0, observer.input_method_extension_removed_count_); |
| manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); |
| EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetEnabledInputMethods().size()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| // Menu change is triggered only if current input method was actually changed. |
| EXPECT_EQ(0, observer.input_method_menu_item_changed_count_); |
| manager_->GetActiveIMEState()->ChangeInputMethod( |
| ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */); |
| EXPECT_FALSE(observer.last_show_message_); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(1, observer.input_method_menu_item_changed_count_); |
| manager_->GetActiveIMEState()->ChangeInputMethod( |
| ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */); |
| EXPECT_FALSE(observer.last_show_message_); |
| |
| // The observer is always notified even when the same input method ID is |
| // passed to ChangeInputMethod() more than twice. |
| // TODO(komatsu): Revisit if this is necessary. |
| EXPECT_EQ(3, observer.input_method_changed_count_); |
| |
| // If the same input method ID is passed, PropertyChanged() is not |
| // notified. |
| EXPECT_EQ(1, observer.input_method_menu_item_changed_count_); |
| |
| // Add an ARC IME, remove it, then check the observer counts. |
| MockInputMethodEngine engine; |
| const std::string ime_id = |
| extension_ime_util::GetArcInputMethodID(kExtensionId1, "engine_id"); |
| InputMethodDescriptor descriptor( |
| ime_id, "arc ime", "AI", {"us"}, {"en-US"}, false /* is_login_keyboard */, |
| GURL(), GURL(), /*handwriting_language=*/std::nullopt); |
| manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, |
| {descriptor}, &engine); |
| EXPECT_EQ(1, observer.input_method_extension_added_count_); |
| EXPECT_EQ(0, observer.input_method_extension_removed_count_); |
| manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1); |
| EXPECT_EQ(1, observer.input_method_extension_added_count_); |
| EXPECT_EQ(1, observer.input_method_extension_removed_count_); |
| |
| manager_->RemoveObserver(&observer); |
| menu_manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) { |
| InputMethodDescriptors methods; |
| methods = manager_->GetComponentExtensionIMEManager() |
| ->GetXkbIMEAsInputMethodDescriptor(); |
| // Try to find random 4-5 layuts and IMEs to make sure the returned list is |
| // correct. |
| const InputMethodDescriptor* id_to_find = |
| manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId(kNaclMozcUsId)); |
| id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId("xkb:us::eng")); |
| EXPECT_TRUE(Contain(methods, *id_to_find)); |
| id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId("xkb:us:dvorak:eng")); |
| EXPECT_TRUE(Contain(methods, *id_to_find)); |
| id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId("xkb:fr::fra")); |
| EXPECT_TRUE(Contain(methods, *id_to_find)); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayouts) { |
| // Currently 8 keyboard layouts are supported for en-US, and 1 for ja. See |
| // ibus_input_method.txt. |
| std::vector<std::string> keyboard_layouts; |
| |
| manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); |
| EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // For http://crbug.com/19655#c11 - (5) |
| // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U. |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "ja", keyboard_layouts); // Japanese |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayoutsAndCurrentInputMethod) { |
| // For http://crbug.com/329061 |
| std::vector<std::string> keyboard_layouts; |
| keyboard_layouts.push_back(ImeIdFromEngineId("xkb:se::swe")); |
| |
| manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); |
| const std::string im_id = |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id(); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:se::swe"), im_id); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayoutsNonUsHardwareKeyboard) { |
| // The physical layout is French. |
| manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( |
| "xkb:fr::fra"); |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "en-US", |
| manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); |
| EXPECT_EQ(9U, |
| manager_->GetActiveIMEState() |
| ->GetNumEnabledInputMethods()); // 8 + French |
| // The physical layout is Japanese. |
| manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( |
| "xkb:jp::jpn"); |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "ja", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); |
| // "xkb:us::eng" is not needed, hence 1. |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // The physical layout is Russian. |
| manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( |
| "xkb:ru::rus"); |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); |
| // "xkb:us::eng" only. |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), |
| manager_->GetActiveIMEState()->GetEnabledInputMethodIds().front()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableMultipleHardwareKeyboardLayout) { |
| // The physical layouts are French and Hungarian. |
| manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( |
| "xkb:fr::fra,xkb:hu::hun"); |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "en-US", |
| manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); |
| // 8 + French + Hungarian |
| EXPECT_EQ(10U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, |
| TestEnableMultipleHardwareKeyboardLayout_NoLoginKeyboard) { |
| // The physical layouts are English (US) and Russian. |
| manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting( |
| "xkb:us::eng,xkb:ru::rus"); |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds()); |
| // xkb:us:eng |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnabledInputMethods) { |
| std::vector<std::string> keyboard_layouts; |
| manager_->GetActiveIMEState()->EnableLoginLayouts( |
| "ja", keyboard_layouts); // Japanese |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| InputMethodDescriptors methods = |
| manager_->GetActiveIMEState()->GetEnabledInputMethods(); |
| EXPECT_EQ(2U, methods.size()); |
| const InputMethodDescriptor* id_to_find = |
| manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId("xkb:us::eng")); |
| EXPECT_TRUE(id_to_find && Contain(methods, *id_to_find)); |
| id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( |
| ImeIdFromEngineId("xkb:jp::jpn")); |
| EXPECT_TRUE(id_to_find && Contain(methods, *id_to_find)); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) { |
| // For http://crbug.com/19655#c11 - (8), step 6. |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng")); |
| ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng")); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| // Since all the IDs added avobe are keyboard layouts, Start() should not be |
| // called. |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Disable Dvorak. |
| ids.erase(ids.begin()); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), // colemak |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(colemak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) { |
| // For http://crbug.com/19655#c11 - (9). |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::string us_id = ImeIdFromEngineId("xkb:us::eng"); |
| std::string us_dvorak_id = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::string us_colemak_id = ImeIdFromEngineId("xkb:us:colemak:eng"); |
| std::vector<std::string> ids{us_id, us_dvorak_id, us_colemak_id}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Switch to Dvorak. |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_dvorak_id, |
| /*show_message=*/false); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(us_dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Disable Dvorak. |
| ids.erase(ids.begin() + 1); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(3, observer.input_method_changed_count_); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) { |
| // For http://crbug.com/19655#c11 - (10). |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::string dvorak_id = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::string mozc_id = ImeIdFromEngineId(kNaclMozcUsId); |
| std::vector<std::string> ids{dvorak_id, mozc_id}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Switch to Mozc |
| manager_->GetActiveIMEState()->ChangeInputMethod(mozc_id, |
| /*show_message=*/false); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(mozc_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Disable Mozc. |
| ids.erase(ids.begin() + 1); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) { |
| // For http://crbug.com/19655#c11 - (11). |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng")); |
| ids.push_back(ImeIdFromEngineId(kNaclMozcUsId)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Disable Dvorak. |
| ids.erase(ids.begin()); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), // Mozc |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableImes) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId(kExt2Engine1Id)); |
| ids.emplace_back("mozc-dv"); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableUnknownIds) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.emplace_back("xkb:tl::tlh"); // Klingon, which is not supported. |
| ids.emplace_back("unknown-super-cool-ime"); |
| EXPECT_FALSE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| |
| // TODO(yusukes): Should we fall back to the hardware keyboard layout in this |
| // case? |
| EXPECT_EQ(0, observer.input_method_changed_count_); |
| |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) { |
| // For http://crbug.com/19655#c11 - (14). |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::string us_id = ImeIdFromEngineId("xkb:us::eng"); |
| std::string us_dvorak_id = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::vector<std::string> ids{us_id, us_dvorak_id}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Switch to Dvorak. |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_dvorak_id, |
| /*show_message=*/false); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(us_dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Lock screen |
| scoped_refptr<InputMethodManager::State> saved_ime_state = |
| manager_->GetActiveIMEState(); |
| manager_->SetState(saved_ime_state->Clone()); |
| manager_->GetActiveIMEState()->DisableNonLockScreenLayouts(); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(us_dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Switch back to Qwerty. |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_id, |
| /*show_message=*/false); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Unlock screen. The original state, Dvorak, is restored. |
| manager_->SetState(saved_ime_state); |
| EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(), |
| InputMethodManager::UIStyle::kNormal); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(us_dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, SwitchInputMethodTest) { |
| // For http://crbug.com/19655#c11 - (15). |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::string id1 = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::string id2 = ImeIdFromEngineId(kExt2Engine2Id); |
| std::string id3 = ImeIdFromEngineId(kExt2Engine1Id); |
| std::vector<std::string> ids{id1, id2, id3}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(id1, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Switch to id2. |
| manager_->GetActiveIMEState()->ChangeInputMethod(id2, /*show_message=*/false); |
| EXPECT_EQ(2, observer.input_method_changed_count_); |
| EXPECT_EQ(id2, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Lock screen |
| scoped_refptr<InputMethodManager::State> saved_ime_state = |
| manager_->GetActiveIMEState(); |
| manager_->SetState(saved_ime_state->Clone()); |
| manager_->GetActiveIMEState()->DisableNonLockScreenLayouts(); |
| EXPECT_EQ(2U, |
| manager_->GetActiveIMEState() |
| ->GetNumEnabledInputMethods()); // hardware layout + id1 |
| EXPECT_EQ(id1, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| std::string hardware_layout_ime_id = ImeIdFromEngineId("xkb:us::eng"); |
| manager_->GetActiveIMEState()->ChangeInputMethod(hardware_layout_ime_id, |
| /*show_message=*/false); |
| EXPECT_EQ(hardware_layout_ime_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Unlock screen. The original state is restored. |
| manager_->SetState(saved_ime_state); |
| EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(), |
| InputMethodManager::UIStyle::kNormal); |
| EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(id2, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestXkbSetting) { |
| // For http://crbug.com/19655#c11 - (8), step 7-11. |
| EXPECT_EQ(1, keyboard_->set_current_keyboard_layout_by_name_count_); |
| std::string dvorak_id = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::string colemak_id = ImeIdFromEngineId("xkb:us:colemak:eng"); |
| std::string mozc_jp_id = ImeIdFromEngineId(kNaclMozcJpId); |
| std::string mozc_us_id = ImeIdFromEngineId(kNaclMozcUsId); |
| std::vector<std::string> ids{dvorak_id, colemak_id, mozc_jp_id, mozc_us_id}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(4U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(2, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->GetActiveIMEState()->ChangeInputMethod(colemak_id, |
| /*show_message=*/false); |
| EXPECT_EQ(3, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("us(colemak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->GetActiveIMEState()->ChangeInputMethod(mozc_jp_id, |
| /*show_message=*/false); |
| EXPECT_EQ(4, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("jp", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->GetActiveIMEState()->ChangeInputMethod(mozc_us_id, |
| /*show_message=*/false); |
| EXPECT_EQ(5, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| manager_->GetActiveIMEState()->ChangeInputMethod(dvorak_id, |
| /*show_message=*/false); |
| EXPECT_EQ(6, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| // Disable Dvorak. |
| ids.erase(ids.begin()); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(7, keyboard_->set_current_keyboard_layout_by_name_count_); |
| EXPECT_EQ("us(colemak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestActivateInputMethodMenuItem) { |
| const std::string kKey = "key"; |
| ui::ime::InputMethodMenuItemList menu_list; |
| menu_list.push_back(ui::ime::InputMethodMenuItem(kKey, "label", false)); |
| menu_manager_->SetCurrentInputMethodMenuItemList(menu_list); |
| |
| manager_->ActivateInputMethodMenuItem(kKey); |
| EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property()); |
| |
| // Key2 is not registered, so activated property should not be changed. |
| manager_->ActivateInputMethodMenuItem("key2"); |
| EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodProperties) { |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| ids.push_back(ImeIdFromEngineId(kNaclMozcUsId)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| manager_->GetActiveIMEState()->ChangeInputMethod( |
| ImeIdFromEngineId(kNaclMozcUsId), false /* show_message */); |
| |
| ui::ime::InputMethodMenuItemList current_property_list; |
| current_property_list.push_back( |
| ui::ime::InputMethodMenuItem("key", "label", false)); |
| menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); |
| |
| ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); |
| EXPECT_EQ("key", |
| menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key); |
| |
| manager_->GetActiveIMEState()->ChangeInputMethod("xkb:us::eng", |
| false /* show_message */); |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodPropertiesTwoImes) { |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId(kNaclMozcUsId)); // Japanese |
| ids.push_back(ImeIdFromEngineId(kExt2Engine1Id)); // T-Chinese |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| |
| ui::ime::InputMethodMenuItemList current_property_list; |
| current_property_list.push_back( |
| ui::ime::InputMethodMenuItem("key-mozc", "label", false)); |
| menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); |
| |
| ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); |
| EXPECT_EQ("key-mozc", |
| menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key); |
| |
| manager_->GetActiveIMEState()->ChangeInputMethod( |
| ImeIdFromEngineId(kExt2Engine1Id), false /* show_message */); |
| // Since the IME is changed, the property for mozc Japanese should be hidden. |
| EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); |
| |
| // Asynchronous property update signal from mozc-chewing. |
| current_property_list.clear(); |
| current_property_list.push_back( |
| ui::ime::InputMethodMenuItem("key-chewing", "label", false)); |
| menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); |
| ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); |
| EXPECT_EQ("key-chewing", |
| menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, |
| TestGetEnabledInputMethodsSortedByDisplayNames) { |
| scoped_refptr<InputMethodManager::State> active_state = |
| manager_->GetActiveIMEState(); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:us::eng")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:fr::fra")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:se::swe")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:jp::jpn")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:ru::rus")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:hu::hun")); |
| active_state->EnableInputMethod(ImeIdFromEngineId("xkb:de::ger")); |
| |
| base::i18n::SetICUDefaultLocale("en-US"); |
| InputMethodDescriptors result = |
| active_state->GetEnabledInputMethodsSortedByLocalizedDisplayNames(); |
| ASSERT_FALSE(result.empty()); |
| |
| InputMethodUtil* util = manager_->GetInputMethodUtil(); |
| UErrorCode error_code = U_ZERO_ERROR; |
| std::unique_ptr<icu::Collator> collator( |
| icu::Collator::createInstance(error_code)); |
| |
| for (size_t i = 1; i < result.size(); ++i) { |
| std::string prev_name = util->GetLocalizedDisplayName(result.at(i - 1)); |
| std::string name = util->GetLocalizedDisplayName(result.at(i)); |
| ASSERT_EQ(UCOL_LESS, base::i18n::CompareString16WithCollator( |
| *collator, base::UTF8ToUTF16(prev_name), |
| base::UTF8ToUTF16(name))); |
| } |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestNextInputMethod) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> keyboard_layouts; |
| keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| |
| // For http://crbug.com/19655#c11 - (1) |
| manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); |
| EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| InputMethodDescriptors sorted_enabled_input_methods = |
| manager_->GetActiveIMEState() |
| ->GetEnabledInputMethodsSortedByLocalizedDisplayNames(); |
| InputMethodDescriptor current_input_method = |
| manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(0).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(1).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(2).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(3).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(4).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(5).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(6).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(7).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| current_input_method = manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(sorted_enabled_input_methods.at(0).id(), current_input_method.id()); |
| EXPECT_EQ(current_input_method.keyboard_layout(), |
| keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestLastUsedInputMethod) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| |
| std::string us_id = ImeIdFromEngineId("xkb:us::eng"); |
| std::string us_intl_id = ImeIdFromEngineId("xkb:us:intl:eng"); |
| std::string us_altgr_intl_id = ImeIdFromEngineId("xkb:us:altgr-intl:eng"); |
| std::vector<std::string> keyboard_layouts; |
| keyboard_layouts.push_back(us_id); |
| |
| manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts); |
| EXPECT_EQ(8U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_intl_id, |
| /*show_message=*/true); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_intl_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_intl_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_intl_id, |
| /*show_message=*/true); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_altgr_intl_id, |
| /*show_message=*/true); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_altgr_intl_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(altgr-intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_intl_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_TRUE(observer.last_show_message_); |
| EXPECT_EQ(us_altgr_intl_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(altgr-intl)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, CycleInputMethodForOneEnabledInputMethod) { |
| // Simulate a single input method. |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // Switching to next does nothing. |
| manager_->GetActiveIMEState()->SwitchToNextInputMethod(); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| |
| // Switching to last-used does nothing. |
| manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng")); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Add two Extension IMEs. |
| std::vector<std::string> languages; |
| languages.emplace_back("en-US"); |
| |
| const std::string ext1_id = |
| extension_ime_util::GetInputMethodID(kExtensionId1, "engine_id"); |
| const InputMethodDescriptor descriptor1( |
| ext1_id, "deadbeef input method", "DB", |
| "us", // layout |
| languages, |
| false, // is_login_keyboard |
| GURL(), GURL(), /*handwriting_language=*/std::nullopt); |
| MockInputMethodEngine engine; |
| InputMethodDescriptors descriptors; |
| descriptors.push_back(descriptor1); |
| manager_->GetActiveIMEState()->AddInputMethodExtension( |
| kExtensionId1, descriptors, &engine); |
| |
| // Extension IMEs are not enabled by default. |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| std::vector<std::string> extension_ime_ids; |
| extension_ime_ids.push_back(ext1_id); |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(extension_ime_ids); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| { |
| InputMethodDescriptors methods( |
| manager_->GetActiveIMEState()->GetEnabledInputMethods()); |
| ASSERT_EQ(2U, methods.size()); |
| // Ext IMEs should be at the end of the list. |
| EXPECT_EQ(ext1_id, methods.at(1).id()); |
| } |
| |
| const std::string ext2_id = |
| extension_ime_util::GetInputMethodID(kExtensionId2, "engine_id"); |
| const InputMethodDescriptor descriptor2( |
| ext2_id, "cafebabe input method", "CB", |
| "us", // layout |
| languages, |
| false, // is_login_keyboard |
| GURL(), GURL(), /*handwriting_language=*/std::nullopt); |
| descriptors.clear(); |
| descriptors.push_back(descriptor2); |
| MockInputMethodEngine engine2; |
| manager_->GetActiveIMEState()->AddInputMethodExtension( |
| kExtensionId2, descriptors, &engine2); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| extension_ime_ids.push_back(ext2_id); |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(extension_ime_ids); |
| EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| { |
| InputMethodDescriptors methods( |
| manager_->GetActiveIMEState()->GetEnabledInputMethods()); |
| ASSERT_EQ(3U, methods.size()); |
| // Ext IMEs should be at the end of the list. |
| EXPECT_EQ(ext1_id, methods.at(1).id()); |
| EXPECT_EQ(ext2_id, methods.at(2).id()); |
| } |
| |
| // Remove them. |
| manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId2); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) { |
| TestObserver observer; |
| manager_->AddObserver(&observer); |
| std::vector<std::string> ids; |
| ids.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| EXPECT_EQ(ImeIdFromEngineId(ids[0]), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Add an Extension IME |
| std::vector<std::string> languages; |
| languages.emplace_back("en-US"); |
| |
| const std::string ext_id = |
| extension_ime_util::GetInputMethodID(kExtensionId1, "engine_id"); |
| const InputMethodDescriptor descriptor(ext_id, "deadbeef input method", "DB", |
| "us(dvorak)", // layout |
| languages, |
| false, // is_login_keyboard |
| GURL(), GURL(), |
| /*handwriting_language=*/std::nullopt); |
| MockInputMethodEngine engine; |
| InputMethodDescriptors descriptors; |
| descriptors.push_back(descriptor); |
| manager_->GetActiveIMEState()->AddInputMethodExtension( |
| kExtensionId1, descriptors, &engine); |
| |
| // Extension IME is not enabled by default. |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(1, observer.input_method_changed_count_); |
| |
| std::vector<std::string> extension_ime_ids; |
| extension_ime_ids.push_back(ext_id); |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(extension_ime_ids); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // Switch to the IME. |
| manager_->GetActiveIMEState()->ChangeInputMethod(ext_id, |
| /*show_message=*/false); |
| EXPECT_EQ(3, observer.input_method_changed_count_); |
| EXPECT_EQ(ext_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Lock the screen. This is for crosbug.com/27049. |
| scoped_refptr<InputMethodManager::State> saved_ime_state = |
| manager_->GetActiveIMEState(); |
| manager_->SetState(saved_ime_state->Clone()); |
| manager_->GetActiveIMEState()->DisableNonLockScreenLayouts(); |
| EXPECT_EQ(1U, |
| manager_->GetActiveIMEState() |
| ->GetNumEnabledInputMethods()); // Qwerty. No Ext. IME |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| |
| // Unlock the screen. |
| manager_->SetState(saved_ime_state); |
| EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(), |
| InputMethodManager::UIStyle::kNormal); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(ext_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| { |
| // This is for crosbug.com/27052. |
| InputMethodDescriptors methods( |
| manager_->GetActiveIMEState()->GetEnabledInputMethods()); |
| ASSERT_EQ(2U, methods.size()); |
| // Ext. IMEs should be at the end of the list. |
| EXPECT_EQ(ext_id, methods.at(1).id()); |
| } |
| manager_->RemoveObserver(&observer); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionOneIME) { |
| const std::string ext_id = extension_ime_util::GetComponentInputMethodID( |
| extension_ime_util::kMozcExtensionId, "nacl_mozc_us"); |
| std::vector<std::string> ids; |
| ids.push_back(ext_id); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(ext_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, ChangeInputMethodComponentExtensionTwoIME) { |
| const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID( |
| extension_ime_util::kMozcExtensionId, "nacl_mozc_us"); |
| const std::string ext_id2 = extension_ime_util::GetComponentInputMethodID( |
| extension_ime_util::kT13nExtensionId, kExt2Engine1Id); |
| std::vector<std::string> ids; |
| ids.push_back(ext_id1); |
| ids.push_back(ext_id2); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| EXPECT_EQ(ext_id1, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| manager_->GetActiveIMEState()->ChangeInputMethod(ext_id2, |
| false /* show_message */); |
| EXPECT_EQ(ext_id2, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, GetMigratedInputMethodIDTest) { |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), |
| manager_->GetMigratedInputMethodID("xkb:us::eng")); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:fr::fra"), |
| manager_->GetMigratedInputMethodID("xkb:fr::fra")); |
| EXPECT_EQ( |
| "_comp_ime_asdf_invalid_pinyin", |
| manager_->GetMigratedInputMethodID("_comp_ime_asdf_invalid_pinyin")); |
| EXPECT_EQ(ImeIdFromEngineId("zh-t-i0-pinyin"), |
| manager_->GetMigratedInputMethodID("zh-t-i0-pinyin")); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, MigrateInputMethodsTest) { |
| std::vector<std::string> input_method_ids; |
| input_method_ids.emplace_back("xkb:us::eng"); |
| input_method_ids.emplace_back("xkb:fr::fra"); |
| input_method_ids.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| input_method_ids.emplace_back("xkb:fr::fra"); |
| input_method_ids.push_back(ImeIdFromEngineId("xkb:us::eng")); |
| input_method_ids.emplace_back("_comp_ime_asdf_pinyin"); |
| input_method_ids.push_back(ImeIdFromEngineId(kPinyinImeId)); |
| |
| manager_->GetMigratedInputMethodIDs(&input_method_ids); |
| |
| ASSERT_EQ(4U, input_method_ids.size()); |
| |
| EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), input_method_ids[0]); |
| EXPECT_EQ(ImeIdFromEngineId("xkb:fr::fra"), input_method_ids[1]); |
| EXPECT_EQ("_comp_ime_asdf_pinyin", input_method_ids[2]); |
| EXPECT_EQ(ImeIdFromEngineId("zh-t-i0-pinyin"), input_method_ids[3]); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, OverrideKeyboardUrlRefWithKeyset) { |
| // Create an input method with a input view URL for testing. |
| const GURL inputview_url( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty&language=en-US&passwordLayout=us." |
| "compact.qwerty&name=keyboard_us"); |
| |
| const auto ime_id = |
| extension_ime_util::GetInputMethodID(kExtensionId1, "test_engine_id"); |
| InputMethodDescriptors descriptors; |
| descriptors.push_back(InputMethodDescriptor( |
| ime_id, "test", "TE", {}, {}, /*is_login_keyboard=*/false, GURL(), |
| inputview_url, /*handwriting_language=*/std::nullopt)); |
| |
| MockInputMethodEngine engine; |
| std::vector<std::string> enabled_imes = {ime_id}; |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(enabled_imes); |
| manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, |
| descriptors, &engine); |
| manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false); |
| |
| manager_->GetActiveIMEState()->EnableInputView(); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(inputview_url.spec())); |
| |
| // Override the keyboard url ref with 'emoji'. |
| const GURL overridden_url_emoji( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty.emoji&language=en-US&passwordLayout=" |
| "us.compact.qwerty&name=keyboard_us"); |
| manager_->OverrideKeyboardKeyset(ImeKeyset::kEmoji); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(overridden_url_emoji.spec())); |
| |
| // Override the keyboard url ref with 'hwt'. |
| const GURL overridden_url_hwt( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty.hwt&language=en-US&passwordLayout=" |
| "us.compact.qwerty&name=keyboard_us"); |
| manager_->OverrideKeyboardKeyset(ImeKeyset::kHandwriting); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(overridden_url_hwt.spec())); |
| |
| // Override the keyboard url ref with 'voice'. |
| const GURL overridden_url_voice( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty.voice&language=en-US" |
| "&passwordLayout=us.compact.qwerty&name=keyboard_us"); |
| manager_->OverrideKeyboardKeyset(ImeKeyset::kVoice); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(overridden_url_voice.spec())); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, OverrideDefaultKeyboardUrlRef) { |
| const GURL default_url("chrome://inputview.html"); |
| |
| const auto ime_id = |
| extension_ime_util::GetInputMethodID(kExtensionId1, "test_engine_id"); |
| InputMethodDescriptors descriptors; |
| descriptors.push_back(InputMethodDescriptor( |
| ime_id, "test", "TE", {}, {}, /*is_login_keyboard=*/false, GURL(), |
| default_url, /*handwriting_language=*/std::nullopt)); |
| |
| MockInputMethodEngine engine; |
| std::vector<std::string> enabled_imes = {ime_id}; |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(enabled_imes); |
| manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, |
| descriptors, &engine); |
| manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false); |
| manager_->GetActiveIMEState()->EnableInputView(); |
| |
| manager_->OverrideKeyboardKeyset(ImeKeyset::kEmoji); |
| EXPECT_EQ(default_url, manager_->GetActiveIMEState()->GetInputViewUrl()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, DoesNotResetInputViewUrlWhenOverridden) { |
| // Create an input method with a input view URL for testing. |
| const GURL inputview_url( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty&language=en-US&passwordLayout=us." |
| "compact.qwerty&name=keyboard_us"); |
| |
| const auto ime_id = |
| extension_ime_util::GetInputMethodID(kExtensionId1, "test_engine_id"); |
| InputMethodDescriptors descriptors; |
| descriptors.push_back(InputMethodDescriptor( |
| ime_id, "test", "TE", {}, {}, /*is_login_keyboard=*/false, GURL(), |
| inputview_url, /*handwriting_language=*/std::nullopt)); |
| |
| MockInputMethodEngine engine; |
| std::vector<std::string> enabled_imes = {ime_id}; |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(enabled_imes); |
| manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, |
| descriptors, &engine); |
| manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, false); |
| manager_->GetActiveIMEState()->EnableInputView(); |
| |
| const GURL overridden_url_emoji( |
| "chrome-extension://" |
| "inputview.html#id=us.compact.qwerty.emoji&language=en-US&passwordLayout=" |
| "us.compact.qwerty&name=keyboard_us"); |
| |
| manager_->OverrideKeyboardKeyset(ImeKeyset::kEmoji); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(overridden_url_emoji.spec())); |
| |
| manager_->GetActiveIMEState()->EnableInputView(); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetInputViewUrl().spec(), |
| ::testing::StartsWith(overridden_url_emoji.spec())); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, AllowedInputMethodsValid) { |
| // First, setup xkb:fr::fra input method |
| std::string original_input_method(ImeIdFromEngineId("xkb:fr::fra")); |
| ASSERT_TRUE( |
| manager_->GetActiveIMEState()->EnableInputMethod(original_input_method)); |
| manager_->GetActiveIMEState()->ChangeInputMethod(original_input_method, |
| false); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| original_input_method); |
| |
| // Only allow xkb:us::eng |
| std::vector<std::string> allowed = {"xkb:us::eng"}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods( |
| manager_->GetActiveIMEState()->GetAllowedInputMethodIds())); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"))); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| ImeIdFromEngineId("xkb:us::eng")); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetAllowedInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"))); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, AllowedInputMethodsInvalid) { |
| // First, setup xkb:fr::fra input method |
| std::string original_input_method(ImeIdFromEngineId("xkb:fr::fra")); |
| ASSERT_TRUE( |
| manager_->GetActiveIMEState()->EnableInputMethod(original_input_method)); |
| manager_->GetActiveIMEState()->ChangeInputMethod(original_input_method, |
| false); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| original_input_method); |
| |
| // Only allow xkb:us::eng |
| std::vector<std::string> allowed = {"invalid_input_method"}; |
| EXPECT_FALSE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| original_input_method); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetAllowedInputMethodIds(), |
| testing::IsEmpty()); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, AllowedInputMethodsValidAndInvalid) { |
| // First, enable xkb:fr::fra and xkb:de::ger |
| std::string original_input_method_1(ImeIdFromEngineId("xkb:fr::fra")); |
| std::string original_input_method_2(ImeIdFromEngineId("xkb:de::ger")); |
| ASSERT_TRUE(manager_->GetActiveIMEState()->EnableInputMethod( |
| original_input_method_1)); |
| ASSERT_TRUE(manager_->GetActiveIMEState()->EnableInputMethod( |
| original_input_method_2)); |
| manager_->GetActiveIMEState()->ChangeInputMethod(original_input_method_1, |
| false); |
| |
| // Allow xkb:fr::fra and an invalid input method id. The invalid id should be |
| // ignored. |
| std::vector<std::string> allowed = {original_input_method_1, |
| "invalid_input_method"}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods( |
| manager_->GetActiveIMEState()->GetAllowedInputMethodIds())); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| original_input_method_1); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetAllowedInputMethodIds(), |
| testing::ElementsAre(original_input_method_1)); |
| |
| // Try to re-enable xkb:de::ger |
| EXPECT_FALSE(manager_->GetActiveIMEState()->EnableInputMethod( |
| original_input_method_2)); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, AllowedInputMethodsAndExtensions) { |
| EXPECT_TRUE(manager_->GetActiveIMEState()->EnableInputMethod( |
| ImeIdFromEngineId(kNaclMozcJpId))); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->EnableInputMethod( |
| ImeIdFromEngineId("xkb:fr::fra"))); |
| |
| std::vector<std::string> allowed = {"xkb:us::eng", kNaclMozcJpId}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods( |
| manager_->GetActiveIMEState()->GetAllowedInputMethodIds())); |
| |
| EXPECT_FALSE(manager_->GetActiveIMEState()->EnableInputMethod( |
| ImeIdFromEngineId(kNaclMozcUsId))); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"), |
| ImeIdFromEngineId(kNaclMozcJpId))); |
| } |
| |
| class InputMethodManagerImplKioskTest : public InputMethodManagerImplTest { |
| public: |
| void LogIn(const std::string& email) override { |
| chromeos::SetUpFakeKioskSession(email); |
| ash_test_helper()->test_session_controller_client()->AddUserSession( |
| email, user_manager::UserType::kKioskApp); |
| } |
| }; |
| |
| TEST_F(InputMethodManagerImplKioskTest, EnableAllowedInputMethods) { |
| // First, setup xkb:fr::fra input method |
| std::string original_input_method(ImeIdFromEngineId("xkb:fr::fra")); |
| ASSERT_TRUE( |
| manager_->GetActiveIMEState()->EnableInputMethod(original_input_method)); |
| manager_->GetActiveIMEState()->ChangeInputMethod(original_input_method, |
| false); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetCurrentInputMethod().id(), |
| original_input_method); |
| |
| // Also allow xkb:us::eng and xkb:de::ger. |
| std::vector<std::string> allowed = {"xkb:us::eng", "xkb:de::ger"}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| |
| // Fix enabled languages according to allowed languages filter. |
| manager_->GetActiveIMEState()->ReplaceEnabledInputMethods( |
| manager_->GetActiveIMEState()->GetEnabledInputMethodIds()); |
| |
| // Check that all allowed languages are enabled languages. |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"), |
| ImeIdFromEngineId("xkb:de::ger"))); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetAllowedInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"), |
| ImeIdFromEngineId("xkb:de::ger"))); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, SetLoginDefaultWithAllowedInputMethods) { |
| std::vector<std::string> allowed = {"xkb:us::eng", "xkb:de::ger", |
| "xkb:fr::fra"}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed)); |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods( |
| manager_->GetActiveIMEState()->GetAllowedInputMethodIds())); |
| manager_->GetActiveIMEState()->SetInputMethodLoginDefault(); |
| EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(), |
| testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"), |
| ImeIdFromEngineId("xkb:de::ger"), |
| ImeIdFromEngineId("xkb:fr::fra"))); |
| } |
| |
| // Verifies that the combination of InputMethodManagerImpl and |
| // ImeControllerClientImpl sends the correct data to ash. |
| TEST_F(InputMethodManagerImplTest, IntegrationWithAsh) { |
| TestImeController ime_controller; |
| ImeControllerClientImpl ime_controller_client(manager_); |
| ime_controller_client.Init(); |
| |
| // Setup 3 IMEs. |
| std::string id1 = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::string id2 = ImeIdFromEngineId(kExt2Engine2Id); |
| std::string id3 = ImeIdFromEngineId(kExt2Engine1Id); |
| std::vector<std::string> ids{id1, id2, id3}; |
| manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids); |
| |
| // Ash received the IMEs. |
| ASSERT_EQ(3u, ime_controller.available_imes_.size()); |
| EXPECT_EQ(id1, ime_controller.current_ime_id_); |
| |
| // Switch to another IME. |
| manager_->GetActiveIMEState()->ChangeInputMethod(id3, false); |
| EXPECT_EQ(id3, ime_controller.current_ime_id_); |
| |
| // Lock the screen. |
| scoped_refptr<InputMethodManager::State> saved_ime_state = |
| manager_->GetActiveIMEState(); |
| manager_->SetState(saved_ime_state->Clone()); |
| manager_->GetActiveIMEState()->DisableNonLockScreenLayouts(); |
| EXPECT_EQ(2u, ime_controller.available_imes_.size()); // id1, hardware layout |
| EXPECT_EQ(id1, ime_controller.current_ime_id_); |
| |
| std::string hardware_layout_ime_id = ImeIdFromEngineId("xkb:us::eng"); |
| manager_->GetActiveIMEState()->ChangeInputMethod(hardware_layout_ime_id, |
| false); |
| EXPECT_EQ(hardware_layout_ime_id, ime_controller.current_ime_id_); |
| |
| // Unlock screen. The original state is restored. |
| manager_->SetState(saved_ime_state); |
| EXPECT_EQ(manager_->GetActiveIMEState()->GetUIStyle(), |
| InputMethodManager::UIStyle::kNormal); |
| ASSERT_EQ(3u, ime_controller.available_imes_.size()); |
| EXPECT_EQ(id3, ime_controller.current_ime_id_); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, SetFeaturesDisabled) { |
| // All features are enabled by default. |
| EXPECT_TRUE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_ALL)); |
| EXPECT_TRUE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_EMOJI)); |
| EXPECT_TRUE(manager_->GetImeMenuFeatureEnabled( |
| InputMethodManager::FEATURE_HANDWRITING)); |
| EXPECT_TRUE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_VOICE)); |
| |
| // Sets emoji disabled and then enabled. |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_EMOJI, false); |
| EXPECT_FALSE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_EMOJI)); |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_EMOJI, true); |
| EXPECT_TRUE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_EMOJI)); |
| |
| // Sets voice disabled and then enabled. |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_VOICE, false); |
| EXPECT_FALSE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_VOICE)); |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_VOICE, true); |
| EXPECT_TRUE( |
| manager_->GetImeMenuFeatureEnabled(InputMethodManager::FEATURE_VOICE)); |
| |
| // Sets handwriting disabled and then enabled. |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_HANDWRITING, |
| false); |
| EXPECT_FALSE(manager_->GetImeMenuFeatureEnabled( |
| InputMethodManager::FEATURE_HANDWRITING)); |
| manager_->SetImeMenuFeatureEnabled(InputMethodManager::FEATURE_HANDWRITING, |
| true); |
| EXPECT_TRUE(manager_->GetImeMenuFeatureEnabled( |
| InputMethodManager::FEATURE_HANDWRITING)); |
| } |
| |
| TEST_F(InputMethodManagerImplTest, TestAddRemoveArcInputMethods) { |
| // There is one default IME |
| EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // Add an ARC IMEs. |
| std::vector<std::string> languages({"en-US"}); |
| |
| MockInputMethodEngine engine; |
| |
| const std::string ime_id = |
| extension_ime_util::GetArcInputMethodID(kExtensionId1, "engine_id"); |
| const InputMethodDescriptor descriptor( |
| ime_id, "arc ime", "AI", "us" /* layout */, languages, |
| false /* is_login_keyboard */, GURL(), GURL(), |
| /*handwriting_language=*/std::nullopt); |
| InputMethodDescriptors descriptors({descriptor}); |
| manager_->GetActiveIMEState()->AddInputMethodExtension(kExtensionId1, |
| descriptors, &engine); |
| |
| InputMethodDescriptors result; |
| manager_->GetActiveIMEState()->GetInputMethodExtensions(&result); |
| EXPECT_EQ(1u, result.size()); |
| EXPECT_EQ(ime_id, result[0].id()); |
| result.clear(); |
| |
| // The ARC IME is not enabled by default. |
| EXPECT_EQ(1u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // Enable it. |
| std::vector<std::string> extension_ime_ids({ime_id}); |
| manager_->GetActiveIMEState()->SetEnabledExtensionImes(extension_ime_ids); |
| EXPECT_EQ(2u, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| { |
| InputMethodDescriptors methods = |
| manager_->GetActiveIMEState()->GetEnabledInputMethods(); |
| EXPECT_EQ(2u, methods.size()); |
| EXPECT_EQ(ime_id, methods.at(1).id()); |
| } |
| |
| // Change to it. |
| manager_->GetActiveIMEState()->ChangeInputMethod(ime_id, |
| false /* show_message */); |
| InputMethodDescriptor current = |
| manager_->GetActiveIMEState()->GetCurrentInputMethod(); |
| EXPECT_EQ(ime_id, current.id()); |
| |
| // Remove it. |
| manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1); |
| manager_->GetActiveIMEState()->GetInputMethodExtensions(&result); |
| EXPECT_TRUE(result.empty()); |
| } |
| |
| // TODO(crbug.com/1179893): Remove once the feature is enabled permanently. |
| class InputMethodManagerImplPositionalTest : public InputMethodManagerImplTest { |
| public: |
| InputMethodManagerImplPositionalTest() = default; |
| ~InputMethodManagerImplPositionalTest() override = default; |
| |
| void SetUp() override { |
| scoped_feature_list_.InitAndEnableFeature( |
| ::features::kImprovedKeyboardShortcuts); |
| |
| InputMethodManagerImplTest::SetUp(); |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| TEST_F(InputMethodManagerImplPositionalTest, ValidatePositionalShortcutLayout) { |
| // Initialize with one positional (US) and one non-positional (US-dvorak) |
| // layout. |
| std::string us_id = ImeIdFromEngineId("xkb:us::eng"); |
| std::string us_dvorak_id = ImeIdFromEngineId("xkb:us:dvorak:eng"); |
| std::vector<std::string> ids{us_id, us_dvorak_id}; |
| EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids)); |
| EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumEnabledInputMethods()); |
| |
| // Verify the US layout is positional. |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| EXPECT_TRUE(manager_->ArePositionalShortcutsUsedByCurrentInputMethod()); |
| |
| // Switch to dvorak and verify it is non-positional. |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_dvorak_id, |
| /*show_message=*/false); |
| EXPECT_EQ(us_dvorak_id, |
| manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us(dvorak)", keyboard_->GetCurrentKeyboardLayoutName()); |
| EXPECT_FALSE(manager_->ArePositionalShortcutsUsedByCurrentInputMethod()); |
| |
| // Switch back to US and verify it is positional again. |
| manager_->GetActiveIMEState()->ChangeInputMethod(us_id, |
| /*show_message=*/false); |
| EXPECT_EQ(us_id, manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); |
| EXPECT_EQ("us", keyboard_->GetCurrentKeyboardLayoutName()); |
| EXPECT_TRUE(manager_->ArePositionalShortcutsUsedByCurrentInputMethod()); |
| } |
| |
| } // namespace input_method |
| } // namespace ash |