diff options
17 files changed, 344 insertions, 146 deletions
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc index 4f7ef13..19ba748 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.cc +++ b/chrome/browser/chromeos/extensions/input_method_api.cc @@ -9,6 +9,7 @@ #include "chrome/browser/chromeos/extensions/input_method_event_router.h" #include "chrome/browser/extensions/api/input_ime/input_ime_api.h" #include "chrome/browser/extensions/event_names.h" +#include "chromeos/ime/extension_ime_util.h" #include "chromeos/ime/input_method_manager.h" #include "extensions/browser/extension_function_registry.h" #include "extensions/browser/extension_system.h" @@ -76,8 +77,11 @@ InputMethodAPI::~InputMethodAPI() { // static std::string InputMethodAPI::GetInputMethodForXkb(const std::string& xkb_id) { - size_t prefix_length = std::string(kXkbPrefix).length(); - DCHECK(xkb_id.substr(0, prefix_length) == kXkbPrefix); + std::string xkb_prefix = + chromeos::extension_ime_util::GetInputMethodIDByKeyboardLayout( + kXkbPrefix); + size_t prefix_length = xkb_prefix.length(); + DCHECK(xkb_id.substr(0, prefix_length) == xkb_prefix); return xkb_id.substr(prefix_length); } diff --git a/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc b/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc index a0b3f48..68e2bd6 100644 --- a/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc +++ b/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc @@ -11,6 +11,7 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/extensions/input_method_event_router.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/extensions/api/test/test_api.h" #include "chrome/common/chrome_switches.h" #include "chromeos/ime/extension_ime_util.h" @@ -27,6 +28,7 @@ const char kInitialInputMethodOnLoginScreen[] = "xkb:us::eng"; const char kNewInputMethod[] = "fr::fra"; const char kSetInputMethodMessage[] = "setInputMethod"; const char kSetInputMethodDone[] = "done"; +const char kBackgroundReady[] = "ready"; // Class that listens for the JS message then changes input method and replies // back. @@ -36,10 +38,6 @@ class SetInputMethodListener : public content::NotificationObserver { explicit SetInputMethodListener(int count) : count_(count) { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE, content::NotificationService::AllSources()); - std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back(kInitialInputMethodOnLoginScreen); - chromeos::input_method::InputMethodManager::Get()->EnableLoginLayouts( - kLoginScreenUILanguage, keyboard_layouts); } virtual ~SetInputMethodListener() { @@ -51,11 +49,27 @@ class SetInputMethodListener : public content::NotificationObserver { const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE { const std::string& content = *content::Details<std::string>(details).ptr(); + if (content == kBackgroundReady) { + // Initializes IMF for testing when receives ready message from + // background. + chromeos::input_method::InputMethodManager* manager = + chromeos::input_method::InputMethodManager::Get(); + manager->GetInputMethodUtil()->InitXkbInputMethodsForTesting(); + + std::vector<std::string> keyboard_layouts; + keyboard_layouts.push_back( + chromeos::extension_ime_util::GetInputMethodIDByKeyboardLayout( + kInitialInputMethodOnLoginScreen)); + manager->EnableLoginLayouts(kLoginScreenUILanguage, keyboard_layouts); + return; + } + const std::string expected_message = base::StringPrintf("%s:%s", kSetInputMethodMessage, kNewInputMethod); if (content == expected_message) { - chromeos::input_method::InputMethodManager::Get()-> - ChangeInputMethod(base::StringPrintf("xkb:%s", kNewInputMethod)); + chromeos::input_method::InputMethodManager::Get()->ChangeInputMethod( + chromeos::extension_ime_util::GetInputMethodIDByKeyboardLayout( + base::StringPrintf("xkb:%s", kNewInputMethod))); scoped_refptr<extensions::TestSendMessageFunction> function = content::Source<extensions::TestSendMessageFunction>( @@ -82,9 +96,6 @@ class ExtensionInputMethodApiTest : public ExtensionApiTest { } // namespace IN_PROC_BROWSER_TEST_F(ExtensionInputMethodApiTest, Basic) { - chromeos::extension_ime_util::ScopedUseExtensionKeyboardFlagForTesting - scoped_flag(false); - // Two test, two calls. See JS code for more info. SetInputMethodListener listener(2); diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index 8d3fcc6..4a8912e 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc @@ -112,7 +112,11 @@ void InputMethodManagerImpl::SetState(State new_state) { scoped_ptr<InputMethodDescriptors> InputMethodManagerImpl::GetSupportedInputMethods() const { - return whitelist_.GetSupportedInputMethods(); + scoped_ptr<InputMethodDescriptors> whitelist_imes = + whitelist_.GetSupportedInputMethods(); + if (!extension_ime_util::UseWrappedExtensionKeyboardLayouts()) + return whitelist_imes.Pass(); + return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass(); } scoped_ptr<InputMethodDescriptors> @@ -246,17 +250,12 @@ bool InputMethodManagerImpl::EnableInputMethodImpl( // Starts or stops the system input method framework as needed. void InputMethodManagerImpl::ReconfigureIMFramework() { - if (component_extension_ime_manager_->IsInitialized()) - LoadNecessaryComponentExtensions(); - - const bool need_engine = - !ContainsOnlyKeyboardLayout(active_input_method_ids_); + LoadNecessaryComponentExtensions(); // Initialize candidate window controller and widgets such as // candidate window, infolist and mode indicator. Note, mode // indicator is used by only keyboard layout input methods. - if (need_engine || active_input_method_ids_.size() > 1) - MaybeInitializeCandidateWindowController(); + MaybeInitializeCandidateWindowController(); } bool InputMethodManagerImpl::EnableInputMethod( @@ -352,7 +351,9 @@ bool InputMethodManagerImpl::ChangeInputMethodInternal( engine->Disable(); // Configure the next engine handler. - if (InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch)) { + if (InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch) && + !extension_ime_util::IsKeyboardLayoutExtension( + input_method_id_to_switch)) { IMEBridge::Get()->SetCurrentEngineHandler(NULL); } else { IMEEngineHandlerInterface* next_engine = @@ -425,9 +426,8 @@ void InputMethodManagerImpl::LoadNecessaryComponentExtensions() { // some component extension IMEs may have been removed from the Chrome OS // image. If specified component extension IME no longer exists, falling back // to an existing IME. - std::vector<std::string> unfiltered_input_method_ids = - active_input_method_ids_; - active_input_method_ids_.clear(); + std::vector<std::string> unfiltered_input_method_ids; + unfiltered_input_method_ids.swap(active_input_method_ids_); for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) { if (!extension_ime_util::IsComponentExtensionIME( unfiltered_input_method_ids[i])) { @@ -440,6 +440,8 @@ void InputMethodManagerImpl::LoadNecessaryComponentExtensions() { active_input_method_ids_.push_back(unfiltered_input_method_ids[i]); } } + // TODO(shuchen): move this call in ComponentExtensionIMEManager. + component_extension_ime_manager_->NotifyInitialized(); } void InputMethodManagerImpl::ActivateInputMethodMenuItem( @@ -835,15 +837,6 @@ bool InputMethodManagerImpl::InputMethodIsActivated( return Contains(active_input_method_ids_, input_method_id); } -bool InputMethodManagerImpl::ContainsOnlyKeyboardLayout( - const std::vector<std::string>& value) { - for (size_t i = 0; i < value.size(); ++i) { - if (!InputMethodUtil::IsKeyboardLayout(value[i])) - return false; - } - return true; -} - void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() { if (candidate_window_controller_.get()) return; diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc index 7fb81c4..0c9520d 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc @@ -94,13 +94,6 @@ class InputMethodManagerImplTest : public testing::Test { ext_xkb_engine_us.layouts.push_back("us"); ext_xkb.engines.push_back(ext_xkb_engine_us); - 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.push_back("en-US"); - ext_xkb_engine_dvorak.layouts.push_back("us(dvorak)"); - ext_xkb.engines.push_back(ext_xkb_engine_dvorak); - 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"; @@ -115,12 +108,12 @@ class InputMethodManagerImplTest : public testing::Test { ext_xkb_engine_altgr_intl.layouts.push_back("us(altgr-intl)"); ext_xkb.engines.push_back(ext_xkb_engine_altgr_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.push_back("fr"); - ext_xkb_engine_fr.layouts.push_back("fr"); - ext_xkb.engines.push_back(ext_xkb_engine_fr); + 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.push_back("en-US"); + ext_xkb_engine_dvorak.layouts.push_back("us(dvorak)"); + ext_xkb.engines.push_back(ext_xkb_engine_dvorak); ComponentExtensionEngine ext_xkb_engine_colemak; ext_xkb_engine_colemak.engine_id = "xkb:us:colemak:eng"; @@ -129,6 +122,13 @@ class InputMethodManagerImplTest : public testing::Test { ext_xkb_engine_colemak.layouts.push_back("us(colemak)"); ext_xkb.engines.push_back(ext_xkb_engine_colemak); + 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.push_back("fr"); + ext_xkb_engine_fr.layouts.push_back("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"; @@ -356,23 +356,27 @@ TEST_F(InputMethodManagerImplTest, TestObserver) { TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) { InitComponentExtension(); - scoped_ptr<InputMethodDescriptors> methods( - manager_->GetSupportedInputMethods()); - ASSERT_TRUE(methods.get()); + InputMethodDescriptors methods; + if (extension_ime_util::UseWrappedExtensionKeyboardLayouts()) { + methods = manager_->GetComponentExtensionIMEManager() + ->GetXkbIMEAsInputMethodDescriptor(); + } else { + methods = *(manager_->GetSupportedInputMethods()); + } // 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( kNaclMozcUsId); id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( - "xkb:us::eng"); - EXPECT_TRUE(Contain(*methods.get(), *id_to_find)); + XkbId("xkb:us::eng")); + EXPECT_TRUE(Contain(methods, *id_to_find)); id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( - "xkb:us:dvorak:eng"); - EXPECT_TRUE(Contain(*methods.get(), *id_to_find)); + XkbId("xkb:us:dvorak:eng")); + EXPECT_TRUE(Contain(methods, *id_to_find)); id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId( - "xkb:fr::fra"); - EXPECT_TRUE(Contain(*methods.get(), *id_to_find)); + XkbId("xkb:fr::fra")); + EXPECT_TRUE(Contain(methods, *id_to_find)); } TEST_F(InputMethodManagerImplTest, TestEnableLayouts) { @@ -393,7 +397,7 @@ TEST_F(InputMethodManagerImplTest, TestEnableLayouts) { TEST_F(InputMethodManagerImplTest, TestEnableLayoutsAndCurrentInputMethod) { // For http://crbug.com/329061 std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:se::swe"); + keyboard_layouts.push_back(XkbId("xkb:se::swe")); InitComponentExtension(); manager_->EnableLoginLayouts("en-US", keyboard_layouts); @@ -481,8 +485,8 @@ TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); - ids.push_back("xkb:us:colemak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); + ids.push_back(XkbId("xkb:us:colemak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(2U, manager_->GetNumActiveInputMethods()); // Since all the IDs added avobe are keyboard layouts, Start() should not be @@ -508,9 +512,9 @@ TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us::eng"); - ids.push_back("xkb:us:dvorak:eng"); - ids.push_back("xkb:us:colemak:eng"); + ids.push_back(XkbId("xkb:us::eng")); + ids.push_back(XkbId("xkb:us:dvorak:eng")); + ids.push_back(XkbId("xkb:us:colemak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(3U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(1, observer.input_method_changed_count_); @@ -539,7 +543,7 @@ TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); ids.push_back(kNaclMozcUsId); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(1, observer.input_method_changed_count_); @@ -565,7 +569,7 @@ TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); ids.push_back(kNaclMozcUsId); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(1, observer.input_method_changed_count_); @@ -620,8 +624,8 @@ TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us::eng"); - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us::eng")); + ids.push_back(XkbId("xkb:us:dvorak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(2U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(1, observer.input_method_changed_count_); @@ -661,7 +665,7 @@ TEST_F(InputMethodManagerImplTest, SwitchInputMethodTest) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); ids.push_back(kExt2Engine2Id); ids.push_back(kExt2Engine1Id); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); @@ -701,8 +705,8 @@ TEST_F(InputMethodManagerImplTest, TestXkbSetting) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); - ids.push_back("xkb:us:colemak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); + ids.push_back(XkbId("xkb:us:colemak:eng")); ids.push_back(kNaclMozcJpId); ids.push_back(kNaclMozcUsId); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); @@ -751,7 +755,7 @@ TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodProperties) { manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us::eng"); + ids.push_back(XkbId("xkb:us::eng")); ids.push_back(kNaclMozcUsId); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(2U, manager_->GetNumActiveInputMethods()); @@ -813,7 +817,7 @@ TEST_F(InputMethodManagerImplTest, TestNextInputMethod) { manager_->AddObserver(&observer); InitComponentExtension(); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:us::eng"); + keyboard_layouts.push_back(XkbId("xkb:us::eng")); // For http://crbug.com/19655#c11 - (1) manager_->EnableLoginLayouts("en-US", keyboard_layouts); EXPECT_EQ(5U, manager_->GetNumActiveInputMethods()); @@ -857,7 +861,7 @@ TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) { keyup_accelerator.set_type(ui::ET_KEY_RELEASED); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:us::eng"); + keyboard_layouts.push_back(XkbId("xkb:us::eng")); manager_->EnableLoginLayouts("en-US", keyboard_layouts); EXPECT_EQ(5U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(XkbId("xkb:us::eng"), manager_->GetCurrentInputMethod().id()); @@ -918,7 +922,7 @@ TEST_F(InputMethodManagerImplTest, keyup_accelerator.set_type(ui::ET_KEY_RELEASED); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(1U, manager_->GetNumActiveInputMethods()); @@ -936,7 +940,7 @@ TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) { manager_->AddObserver(&observer); InitComponentExtension(); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:us::eng"); + keyboard_layouts.push_back(XkbId("xkb:us::eng")); manager_->EnableLoginLayouts("en-US", keyboard_layouts); EXPECT_EQ(5U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(expect_id, manager_->GetCurrentInputMethod().id()); @@ -975,7 +979,7 @@ TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpLayout) { keyup_accelerator.set_type(ui::ET_KEY_RELEASED); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:us::eng"); + keyboard_layouts.push_back(XkbId("xkb:us::eng")); manager_->EnableLoginLayouts("ja", keyboard_layouts); EXPECT_EQ(2U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(XkbId("xkb:us::eng"), manager_->GetCurrentInputMethod().id()); @@ -1006,7 +1010,7 @@ TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:jp::jpn"); + ids.push_back(XkbId("xkb:jp::jpn")); ids.push_back(kNaclMozcJpId); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(XkbId("xkb:jp::jpn"), manager_->GetCurrentInputMethod().id()); @@ -1037,7 +1041,7 @@ TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) { EXPECT_EQ("jp", xkeyboard_->last_layout_); // Add Dvorak. - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(XkbId("xkb:jp::jpn"), manager_->GetCurrentInputMethod().id()); EXPECT_EQ("jp", xkeyboard_->last_layout_); @@ -1057,7 +1061,7 @@ TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) { InitComponentExtension(); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us:dvorak:eng"); + ids.push_back(XkbId("xkb:us:dvorak:eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(1U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(1, observer.input_method_changed_count_); @@ -1139,7 +1143,7 @@ TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) { manager_->AddObserver(&observer); manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN); std::vector<std::string> ids; - ids.push_back("xkb:us::eng"); + ids.push_back(XkbId("xkb:us::eng")); EXPECT_TRUE(manager_->ReplaceEnabledInputMethods(ids)); EXPECT_EQ(1U, manager_->GetNumActiveInputMethods()); EXPECT_EQ(1, observer.input_method_changed_count_); diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc index 920ff98..9f10471 100644 --- a/chrome/browser/chromeos/input_method/input_method_util.cc +++ b/chrome/browser/chromeos/input_method/input_method_util.cc @@ -20,6 +20,7 @@ // For SetHardwareKeyboardLayoutForTesting. #include "chromeos/ime/fake_input_method_delegate.h" #include "chromeos/ime/input_method_delegate.h" +#include "chromeos/ime/input_method_whitelist.h" // TODO(nona): move this header from this file. #include "grit/generated_resources.h" @@ -126,6 +127,61 @@ const struct { { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" }, }; +// The map from xkb layout to the indicator text. +// Refer to crbug.com/349829. +const char* const kXkbIndicators[][2] = {{"am", "AM"}, + {"be", "BE"}, + {"bg", "BG"}, + {"bg(phonetic)", "BG"}, + {"br", "BR"}, + {"by", "BY"}, + {"ca", "CA"}, + {"ca(eng)", "CA"}, + {"ca(multix)", "CA"}, + {"ch", "CH"}, + {"ch(fr)", "CH"}, + {"cz", "CZ"}, + {"cz(qwerty)", "CS"}, + {"de", "DE"}, + {"de(neo)", "NEO"}, + {"dk", "DK"}, + {"ee", "EE"}, + {"es", "ES"}, + {"es(cat)", "CAS"}, + {"fi", "FI"}, + {"fr", "FR"}, + {"gb(dvorak)", "DV"}, + {"gb(extd)", "GB"}, + {"ge", "GE"}, + {"gr", "GR"}, + {"hr", "HR"}, + {"hu", "HU"}, + {"il", "IL"}, + {"is", "IS"}, + {"it", "IT"}, + {"jp", "JA"}, + {"latam", "LA"}, + {"lt", "LT"}, + {"lv(apostrophe)", "LV"}, + {"mn", "MN"}, + {"no", "NO"}, + {"pl", "PL"}, + {"pt", "PT"}, + {"ro", "RO"}, + {"rs", "RS"}, + {"ru", "RU"}, + {"ru(phonetic)", "RU"}, + {"se", "SE"}, + {"si", "SI"}, + {"sk", "SK"}, + {"tr", "TR"}, + {"ua", "UA"}, + {"us", "US"}, + {"us(altgr-intl)", "EXTD"}, + {"us(colemak)", "CO"}, + {"us(dvorak)", "DV"}, + {"us(intl)", "INTL"}, }; + } // namespace namespace chromeos { @@ -291,6 +347,11 @@ InputMethodUtil::InputMethodUtil( scoped_ptr<InputMethodDescriptors> supported_input_methods) : supported_input_methods_(supported_input_methods.Pass()), delegate_(delegate) { + // Makes sure the supported input methods at least have the fallback ime. + // So that it won't cause massive test failures. + if (supported_input_methods_->empty()) + supported_input_methods_->push_back(GetFallbackInputMethodDescriptor()); + ReloadInternalMaps(); // Initialize a map from English string to Chrome string resource ID as well. @@ -301,6 +362,11 @@ InputMethodUtil::InputMethodUtil( DCHECK(result) << "Duplicated string is found: " << map_entry.english_string_from_ibus; } + + // Initialize the map from xkb layout to indicator text. + for (size_t i = 0; i < arraysize(kXkbIndicators); ++i) { + xkb_layout_to_indicator_[kXkbIndicators[i][0]] = kXkbIndicators[i][1]; + } } InputMethodUtil::~InputMethodUtil() { @@ -398,13 +464,11 @@ base::string16 InputMethodUtil::GetInputMethodShortName( } // Display the keyboard layout name when using a keyboard layout. - if (text.empty() && - IsKeyboardLayout(input_method.id())) { - const size_t kMaxKeyboardLayoutNameLen = 2; - const base::string16 keyboard_layout = - base::UTF8ToUTF16(GetKeyboardLayoutName(input_method.id())); - text = StringToUpperASCII(keyboard_layout).substr( - 0, kMaxKeyboardLayoutNameLen); + if (text.empty() && IsKeyboardLayout(input_method.id())) { + std::map<std::string, std::string>::const_iterator it = + xkb_layout_to_indicator_.find(GetKeyboardLayoutName(input_method.id())); + if (it != xkb_layout_to_indicator_.end()) + text = base::UTF8ToUTF16(it->second); } // TODO(yusukes): Some languages have two or more input methods. For example, @@ -481,21 +545,10 @@ base::string16 InputMethodUtil::GetInputMethodLongName( const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromId( const std::string& input_method_id) const { - InputMethodIdToDescriptorMap::const_iterator iter - = id_to_descriptor_.find(input_method_id); - if (iter == id_to_descriptor_.end()) { - // If failed to find the descriptor for given id, it may because of the id - // is a component extension xkb id (_comp_ime_...xkb:...). - // So try to convert it to legacy xkb id and find again. - // This hack is mainly for OOBE session, which requires a sync call to get - // the input method descriptor for extension xkb id. - // TODO(shuchen): need to support async wait for component extension - // loading in OOBE session. This hack won't be needed when it's been done. - iter = id_to_descriptor_.find( - extension_ime_util::MaybeGetLegacyXkbId(input_method_id)); - if (iter == id_to_descriptor_.end()) - return NULL; - } + InputMethodIdToDescriptorMap::const_iterator iter = + id_to_descriptor_.find(input_method_id); + if (iter == id_to_descriptor_.end()) + return NULL; return &(iter->second); } @@ -708,16 +761,49 @@ bool InputMethodUtil::IsLoginKeyboard(const std::string& input_method_id) void InputMethodUtil::SetComponentExtensions( const InputMethodDescriptors& imes) { - component_extension_ime_id_to_descriptor_.clear(); for (size_t i = 0; i < imes.size(); ++i) { - const InputMethodDescriptor& input_method = imes.at(i); + const InputMethodDescriptor& input_method = imes[i]; DCHECK(!input_method.language_codes().empty()); - const std::string language_code = input_method.language_codes().at(0); - id_to_language_code_.insert( - std::make_pair(input_method.id(), language_code)); - id_to_descriptor_.insert( - std::make_pair(input_method.id(), input_method)); + const std::vector<std::string>& language_codes = + input_method.language_codes(); + id_to_language_code_[input_method.id()] = language_codes[0]; + id_to_descriptor_[input_method.id()] = input_method; + + typedef LanguageCodeToIdsMap::const_iterator It; + for (size_t j = 0; j < language_codes.size(); ++j) { + std::pair<It, It> range = + language_code_to_ids_.equal_range(language_codes[j]); + It it = range.first; + for (; it != range.second; ++it) { + if (it->second == input_method.id()) + break; + } + if (it == range.second) + language_code_to_ids_.insert( + std::make_pair(language_codes[j], input_method.id())); + } + } +} + +void InputMethodUtil::InitXkbInputMethodsForTesting() { + if (!extension_ime_util::UseWrappedExtensionKeyboardLayouts()) + return; + scoped_ptr<InputMethodDescriptors> original_imes = + InputMethodWhitelist().GetSupportedInputMethods(); + InputMethodDescriptors whitelist_imes; + for (size_t i = 0; i < original_imes->size(); ++i) { + const InputMethodDescriptor& ime = (*original_imes)[i]; + whitelist_imes.push_back(InputMethodDescriptor( + extension_ime_util::GetInputMethodIDByKeyboardLayout(ime.id()), + "", + ime.indicator(), + ime.keyboard_layouts(), + ime.language_codes(), + ime.is_login_keyboard(), + ime.options_page_url(), + ime.input_view_url())); } + SetComponentExtensions(whitelist_imes); } InputMethodDescriptor InputMethodUtil::GetFallbackInputMethodDescriptor() { diff --git a/chrome/browser/chromeos/input_method/input_method_util.h b/chrome/browser/chromeos/input_method/input_method_util.h index eea2d9e..faa66b8 100644 --- a/chrome/browser/chromeos/input_method/input_method_util.h +++ b/chrome/browser/chromeos/input_method/input_method_util.h @@ -140,6 +140,9 @@ class InputMethodUtil { // Sets the list of component extension IMEs. void SetComponentExtensions(const InputMethodDescriptors& imes); + // Initializes the extension based xkb IMEs for testing. + void InitXkbInputMethodsForTesting(); + // Returns the fallback input method descriptor (the very basic US // keyboard). This function is mostly used for testing, but may be used // as the fallback, when there is no other choice. @@ -190,7 +193,7 @@ class InputMethodUtil { std::map<std::string, std::string> id_to_language_code_; InputMethodIdToDescriptorMap id_to_descriptor_; XkbIdToDescriptorMap xkb_id_to_descriptor_; - ComponentExtIMEMap component_extension_ime_id_to_descriptor_; + std::map<std::string, std::string> xkb_layout_to_indicator_; typedef base::hash_map<std::string, int> HashType; HashType english_to_resource_id_; diff --git a/chrome/browser/chromeos/input_method/mode_indicator_browsertest.cc b/chrome/browser/chromeos/input_method/mode_indicator_browsertest.cc index 46890cd..b8bf3b4 100644 --- a/chrome/browser/chromeos/input_method/mode_indicator_browsertest.cc +++ b/chrome/browser/chromeos/input_method/mode_indicator_browsertest.cc @@ -5,10 +5,13 @@ #include <algorithm> #include "ash/shell.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/input_method/mode_indicator_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "chromeos/ime/component_extension_ime_manager.h" +#include "chromeos/ime/extension_ime_util.h" #include "chromeos/ime/input_method_manager.h" +#include "chromeos/ime/input_method_whitelist.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -96,6 +99,9 @@ class ModeIndicatorBrowserTest : public InProcessBrowserTest { } void InitializeIMF() { + InputMethodManager::Get() + ->GetInputMethodUtil() + ->InitXkbInputMethodsForTesting(); // Make sure ComponentExtensionIMEManager is initialized. // ComponentExtensionIMEManagerImpl::InitializeAsync posts // ReadComponentExtensionsInfo to the FILE thread for the @@ -126,7 +132,8 @@ IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest, Bounds) { ASSERT_TRUE(imm); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:fr::fra"); + keyboard_layouts.push_back( + extension_ime_util::GetInputMethodIDByKeyboardLayout("xkb:fr::fra")); // Add keyboard layouts to enable the mode indicator. imm->EnableLoginLayouts("fr", keyboard_layouts); @@ -193,7 +200,8 @@ IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest, NumOfWidgets) { ASSERT_TRUE(imm); std::vector<std::string> keyboard_layouts; - keyboard_layouts.push_back("xkb:fr::fra"); + keyboard_layouts.push_back( + extension_ime_util::GetInputMethodIDByKeyboardLayout("xkb:fr::fra")); // Add keyboard layouts to enable the mode indicator. imm->EnableLoginLayouts("fr", keyboard_layouts); diff --git a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc index cc92f1a..f49e130 100644 --- a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc @@ -9,11 +9,15 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/customization_document.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/login/login_display_host_impl.h" #include "chrome/browser/chromeos/login/login_wizard.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/ime/extension_ime_util.h" +#include "chromeos/ime/input_method_manager.h" +#include "chromeos/ime/input_method_whitelist.h" #include "chromeos/system/statistics_provider.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" @@ -221,6 +225,24 @@ void OobeLocalizationTest::RunLocalizationTest( StartupCustomizationDocument::GetInstance()->Init( statistics_provider_.get()); + input_method::InputMethodManager::Get() + ->GetInputMethodUtil() + ->InitXkbInputMethodsForTesting(); + + std::string expected_keyboard_select = expected_keyboard_select_control; + if (extension_ime_util::UseWrappedExtensionKeyboardLayouts()) { + // Modifies the expected keyboard select control options for the new + // extension based xkb id. + size_t pos = 0; + std::string repl_old = "xkb:"; + std::string repl_new = "_comp_ime_fgoepimhcoialccpbmpnnblemnepkkaoxkb:"; + while ((pos = expected_keyboard_select.find(repl_old, pos)) != + std::string::npos) { + expected_keyboard_select.replace(pos, repl_old.length(), repl_new); + pos += repl_new.length(); + } + } + // Bring up the OOBE network screen. chromeos::ShowLoginWizard(chromeos::WizardController::kNetworkScreenName); content::WindowedNotificationObserver( @@ -233,15 +255,18 @@ void OobeLocalizationTest::RunLocalizationTest( VerifyInitialOptions(kLocaleSelect, expected_locale.c_str(), true); VerifyInitialOptions(kKeyboardSelect, - expected_keyboard_layout.c_str(), + extension_ime_util::GetInputMethodIDByKeyboardLayout( + expected_keyboard_layout).c_str(), false); // Make sure we have a fallback keyboard. - VerifyOptionExists(kKeyboardSelect, kUSLayout); + VerifyOptionExists( + kKeyboardSelect, + extension_ime_util::GetInputMethodIDByKeyboardLayout(kUSLayout).c_str()); // Note, that sort order is locale-specific, but is unlikely to change. // Especially for keyboard layouts. - EXPECT_EQ(expected_keyboard_select_control, DumpOptions(kKeyboardSelect)); + EXPECT_EQ(expected_keyboard_select, DumpOptions(kKeyboardSelect)); // Shut down the display host. chromeos::LoginDisplayHostImpl::default_host()->Finalize(); diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc index a976a37..7411af0 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc @@ -49,7 +49,7 @@ const char kJsApiNetworkOnLanguageChanged[] = "networkOnLanguageChanged"; const char kJsApiNetworkOnInputMethodChanged[] = "networkOnInputMethodChanged"; const char kJsApiNetworkOnTimezoneChanged[] = "networkOnTimezoneChanged"; -const char kUSlayout[] = "xkb:us::eng"; +const char kUSLayout[] = "xkb:us::eng"; const int kDerelectDetectionTimeoutSeconds = 8 * 60 * 60; // 8 hours. const int kDerelectIdleTimeoutSeconds = 5 * 60; // 5 minutes. @@ -85,11 +85,20 @@ NetworkScreenHandler::NetworkScreenHandler(CoreOobeActor* core_oobe_actor) weak_ptr_factory_(this) { DCHECK(core_oobe_actor_); SetupTimeouts(); + + input_method::InputMethodManager* manager = + input_method::InputMethodManager::Get(); + manager->SetInputMethodLoginDefault(); + manager->GetComponentExtensionIMEManager()->AddObserver(this); } NetworkScreenHandler::~NetworkScreenHandler() { if (screen_) screen_->OnActorDestroyed(this); + + input_method::InputMethodManager::Get() + ->GetComponentExtensionIMEManager() + ->RemoveObserver(this); } // NetworkScreenHandler, NetworkScreenActor implementation: -------------------- @@ -373,11 +382,17 @@ base::ListValue* NetworkScreenHandler::GetLanguageList() { const std::string app_locale = g_browser_process->GetApplicationLocale(); input_method::InputMethodManager* manager = input_method::InputMethodManager::Get(); - // GetSupportedInputMethods() never returns NULL. - scoped_ptr<input_method::InputMethodDescriptors> descriptors( - manager->GetSupportedInputMethods()); + ComponentExtensionIMEManager* comp_manager = + manager->GetComponentExtensionIMEManager(); + input_method::InputMethodDescriptors descriptors; + if (extension_ime_util::UseWrappedExtensionKeyboardLayouts()) { + if (comp_manager->IsInitialized()) + descriptors = comp_manager->GetXkbIMEAsInputMethodDescriptor(); + } else { + descriptors = *(manager->GetSupportedInputMethods()); + } base::ListValue* languages_list = - options::CrosLanguageOptionsHandler::GetUILanguageList(*descriptors); + options::CrosLanguageOptionsHandler::GetUILanguageList(descriptors); for (size_t i = 0; i < languages_list->GetSize(); ++i) { base::DictionaryValue* language_info = NULL; if (!languages_list->GetDictionary(i, &language_info)) @@ -422,23 +437,40 @@ base::DictionaryValue* CreateInputMethodsEntry( return input_method.release(); } +void NetworkScreenHandler::OnImeComponentExtensionInitialized() { + input_method::InputMethodManager::Get()->SetInputMethodLoginDefault(); + + // Refreshes the language and keyboard list once the component extension + // IMEs are initialized. + base::DictionaryValue localized_strings; + static_cast<OobeUI*>(this->web_ui()->GetController()) + ->GetLocalizedStrings(&localized_strings); + this->core_oobe_actor_->ReloadContent(localized_strings); + this->EnableContinue(this->is_continue_enabled_); +} + // static base::ListValue* NetworkScreenHandler::GetInputMethods() { base::ListValue* input_methods_list = new base::ListValue; input_method::InputMethodManager* manager = input_method::InputMethodManager::Get(); input_method::InputMethodUtil* util = manager->GetInputMethodUtil(); + if (extension_ime_util::UseWrappedExtensionKeyboardLayouts()) { + ComponentExtensionIMEManager* comp_manager = + manager->GetComponentExtensionIMEManager(); + if (!comp_manager->IsInitialized()) { + input_method::InputMethodDescriptor fallback = + util->GetFallbackInputMethodDescriptor(); + input_methods_list->Append( + CreateInputMethodsEntry(fallback, fallback.id())); + return input_methods_list; + } + } + scoped_ptr<input_method::InputMethodDescriptors> input_methods( manager->GetActiveInputMethods()); - // Uses extension_ime_util::MaybeGetLegacyXkbId() to make sure the input - // method id is in legacy xkb id format (e.g. xkb:us::eng), instead of - // extension based xkd id format (e.g. _comp_ime_...xkb:us::eng). - // Same for the rests. - // TODO(shuchen): support wait for component extension loading, and then show - // OOBE window. So that extension_ime_util::MaybeGetLegacyXkbId() can be - // removed. - std::string current_input_method_id = extension_ime_util::MaybeGetLegacyXkbId( - manager->GetCurrentInputMethod().id()); + const std::string& current_input_method_id = + manager->GetCurrentInputMethod().id(); const std::vector<std::string>& hardware_login_input_methods = util->GetHardwareLoginInputMethodIds(); std::set<std::string> input_methods_added; @@ -447,14 +479,12 @@ base::ListValue* NetworkScreenHandler::GetInputMethods() { hardware_login_input_methods.begin(); i != hardware_login_input_methods.end(); ++i) { - // Makes sure the id is in legacy xkb id format. - const std::string id = extension_ime_util::MaybeGetLegacyXkbId(*i); - input_methods_added.insert(id); const input_method::InputMethodDescriptor* ime = - util->GetInputMethodDescriptorFromId(id); + util->GetInputMethodDescriptorFromId(*i); DCHECK(ime != NULL); // Do not crash in case of misconfiguration. if (ime != NULL) { + input_methods_added.insert(*i); input_methods_list->Append( CreateInputMethodsEntry(*ime, current_input_method_id)); } @@ -463,8 +493,7 @@ base::ListValue* NetworkScreenHandler::GetInputMethods() { bool optgroup_added = false; for (size_t i = 0; i < input_methods->size(); ++i) { // Makes sure the id is in legacy xkb id format. - const std::string& ime_id = extension_ime_util::MaybeGetLegacyXkbId( - (*input_methods)[i].id()); + const std::string& ime_id = (*input_methods)[i].id(); if (!InsertString(ime_id, input_methods_added)) continue; if (!optgroup_added) { @@ -475,9 +504,11 @@ base::ListValue* NetworkScreenHandler::GetInputMethods() { CreateInputMethodsEntry((*input_methods)[i], current_input_method_id)); } // "xkb:us::eng" should always be in the list of available layouts. - if (input_methods_added.count(kUSlayout) == 0) { + const std::string& us_keyboard_id = + extension_ime_util::GetInputMethodIDByKeyboardLayout(kUSLayout); + if (input_methods_added.find(us_keyboard_id) == input_methods_added.end()) { const input_method::InputMethodDescriptor* us_eng_descriptor = - util->GetInputMethodDescriptorFromId(kUSlayout); + util->GetInputMethodDescriptorFromId(us_keyboard_id); DCHECK(us_eng_descriptor != NULL); if (!optgroup_added) { optgroup_added = true; diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h index 344f0fc..627af65 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h @@ -13,6 +13,7 @@ #include "chrome/browser/chromeos/login/screens/network_screen_actor.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" +#include "chromeos/ime/component_extension_ime_manager.h" #include "ui/gfx/point.h" class PrefRegistrySimple; @@ -27,7 +28,8 @@ struct NetworkScreenHandlerOnLanguageChangedCallbackData; // WebUI implementation of NetworkScreenActor. It is used to interact with // the welcome screen (part of the page) of the OOBE. class NetworkScreenHandler : public NetworkScreenActor, - public BaseScreenHandler { + public BaseScreenHandler, + public ComponentExtensionIMEManager::Observer { public: explicit NetworkScreenHandler(CoreOobeActor* core_oobe_actor); virtual ~NetworkScreenHandler(); @@ -51,6 +53,9 @@ class NetworkScreenHandler : public NetworkScreenActor, // WebUIMessageHandler implementation: virtual void RegisterMessages() OVERRIDE; + // ComponentExtensionIMEManager::Observer implementation: + virtual void OnImeComponentExtensionInitialized() OVERRIDE; + // Registers the preference for derelict state. static void RegisterPrefs(PrefRegistrySimple* registry); diff --git a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc index ce345e1..c753a73 100644 --- a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc @@ -450,7 +450,7 @@ void CrosLanguageOptionsHandler::InputMethodOptionsOpenCallback( web_contents->GetDelegate()->ActivateContents(web_contents); } -void CrosLanguageOptionsHandler::OnInitialized() { +void CrosLanguageOptionsHandler::OnImeComponentExtensionInitialized() { if (composition_extension_appended_ || !is_page_initialized_) { // If an option page is not ready to call JavaScript, appending component // extension IMEs will be done in InitializePage function later. diff --git a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h index 37a4cc0..70f77b2 100644 --- a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h +++ b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h @@ -95,7 +95,7 @@ class CrosLanguageOptionsHandler void InputMethodOptionsOpenCallback(const base::ListValue* args); // ComponentExtensionIMEManager::Observer override. - virtual void OnInitialized() OVERRIDE; + virtual void OnImeComponentExtensionInitialized() OVERRIDE; // Gets the list of languages with |descriptors| based on // |base_language_codes|. diff --git a/chrome/test/data/extensions/api_test/input_method/background.js b/chrome/test/data/extensions/api_test/input_method/background.js index ceebc03..2102fb3 100644 --- a/chrome/test/data/extensions/api_test/input_method/background.js +++ b/chrome/test/data/extensions/api_test/input_method/background.js @@ -11,7 +11,7 @@ function setAndGetTest() { chrome.test.assertEq('done', response); console.log('Getting current input method.'); chrome.inputMethodPrivate.get(function (inputMethod) { - chrome.test.assertEq(inputMethod, kNewInputMethod); + chrome.test.assertEq(kNewInputMethod, inputMethod); chrome.test.succeed(); } ); @@ -34,4 +34,5 @@ function setAndObserveTest() { ); } +chrome.test.sendMessage('ready'); chrome.test.runTests([setAndGetTest, setAndObserveTest]); diff --git a/chromeos/ime/component_extension_ime_manager.cc b/chromeos/ime/component_extension_ime_manager.cc index 3037326..e33ce3e 100644 --- a/chromeos/ime/component_extension_ime_manager.cc +++ b/chromeos/ime/component_extension_ime_manager.cc @@ -76,7 +76,7 @@ ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() { } ComponentExtensionIMEManager::ComponentExtensionIMEManager() - : is_initialized_(false) { + : is_initialized_(false), was_initialization_notified_(false) { for (size_t i = 0; i < arraysize(kLoginLayoutWhitelist); ++i) { login_layout_set_.insert(kLoginLayoutWhitelist[i]); } @@ -90,7 +90,14 @@ void ComponentExtensionIMEManager::Initialize( delegate_ = delegate.Pass(); component_extension_imes_ = delegate_->ListIME(); is_initialized_ = true; - FOR_EACH_OBSERVER(Observer, observers_, OnInitialized()); +} + +void ComponentExtensionIMEManager::NotifyInitialized() { + if (is_initialized_ && !was_initialization_notified_) { + FOR_EACH_OBSERVER( + Observer, observers_, OnImeComponentExtensionInitialized()); + was_initialization_notified_ = true; + } } bool ComponentExtensionIMEManager::IsInitialized() { @@ -203,6 +210,18 @@ input_method::InputMethodDescriptors return result; } +input_method::InputMethodDescriptors +ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() { + input_method::InputMethodDescriptors result; + const input_method::InputMethodDescriptors& descriptors = + GetAllIMEAsInputMethodDescriptor(); + for (size_t i = 0; i < descriptors.size(); ++i) { + if (extension_ime_util::IsKeyboardLayoutExtension(descriptors[i].id())) + result.push_back(descriptors[i]); + } + return result; +} + void ComponentExtensionIMEManager::AddObserver(Observer* observer) { observers_.AddObserver(observer); } diff --git a/chromeos/ime/component_extension_ime_manager.h b/chromeos/ime/component_extension_ime_manager.h index 8d79758..fad81d3 100644 --- a/chromeos/ime/component_extension_ime_manager.h +++ b/chromeos/ime/component_extension_ime_manager.h @@ -66,7 +66,7 @@ class CHROMEOS_EXPORT ComponentExtensionIMEManager { class Observer { public: // Called when the initialization is done. - virtual void OnInitialized() = 0; + virtual void OnImeComponentExtensionInitialized() = 0; }; ComponentExtensionIMEManager(); @@ -77,6 +77,9 @@ class CHROMEOS_EXPORT ComponentExtensionIMEManager { // be called before using any other function. void Initialize(scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate); + // Notifies the observers for the component extension IMEs are initialized. + void NotifyInitialized(); + // Returns true if the initialization is done, otherwise returns false. bool IsInitialized(); @@ -114,6 +117,9 @@ class CHROMEOS_EXPORT ComponentExtensionIMEManager { // Returns all IME as InputMethodDescriptors. input_method::InputMethodDescriptors GetAllIMEAsInputMethodDescriptor(); + // Returns all XKB keyboard IME as InputMethodDescriptors. + input_method::InputMethodDescriptors GetXkbIMEAsInputMethodDescriptor(); + void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -135,6 +141,8 @@ class CHROMEOS_EXPORT ComponentExtensionIMEManager { bool is_initialized_; + bool was_initialization_notified_; + std::set<std::string> login_layout_set_; DISALLOW_COPY_AND_ASSIGN(ComponentExtensionIMEManager); diff --git a/chromeos/ime/component_extension_ime_manager_unittest.cc b/chromeos/ime/component_extension_ime_manager_unittest.cc index d9182e0..98571d2 100644 --- a/chromeos/ime/component_extension_ime_manager_unittest.cc +++ b/chromeos/ime/component_extension_ime_manager_unittest.cc @@ -122,7 +122,7 @@ class ComponentExtensionIMEManagerTest : scoped_ptr<ComponentExtensionIMEManagerDelegate>( mock_delegate_).Pass()); EXPECT_TRUE(component_ext_mgr_->IsInitialized()); - + component_ext_mgr_->NotifyInitialized(); } virtual void TearDown() { @@ -136,7 +136,7 @@ class ComponentExtensionIMEManagerTest : std::vector<ComponentExtensionIME> ime_list_; private: - virtual void OnInitialized() OVERRIDE { + virtual void OnImeComponentExtensionInitialized() OVERRIDE { ++on_initialized_callcount_; } diff --git a/ui/base/ime/chromeos/ime_bridge.cc b/ui/base/ime/chromeos/ime_bridge.cc index 7f11528..3d5ea81 100644 --- a/ui/base/ime/chromeos/ime_bridge.cc +++ b/ui/base/ime/chromeos/ime_bridge.cc @@ -66,9 +66,9 @@ class IMEBridgeImpl : public IMEBridge { const std::string& engine_id) OVERRIDE { std::map<std::string, IMEEngineHandlerInterface*>::const_iterator itor = engine_handler_map_.find(engine_id); - // |engine_id| must be found unless it's empty, but if it's not found, fall - // back to NULL when non-debug build. - DCHECK(itor != engine_handler_map_.end() || engine_id.empty()); + // It is normal in that the engine is not found, because sometimes the + // extension based xkb id may be provided but the xkb component extension + // is not installed, for example, in browser_tests. if (itor == engine_handler_map_.end()) { engine_handler_ = NULL; return NULL; |