Commit 372ba214 authored by shuchen@chromium.org's avatar shuchen@chromium.org

[IME] Removes the duplicated IMEs in chrome://settings/languages, and support...

[IME] Removes the duplicated IMEs in chrome://settings/languages, and support async component IMEs loading in oobe network screen, and fix the wrong indicator issue.

BUG=345604,349829
TEST=None
TBR=nona@chromium.org

Review URL: https://codereview.chromium.org/190033005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255879 0039d316-1c4b-4281-b951-d872f2087c98
parent 0f8f5b47
......@@ -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);
}
......
......@@ -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);
......
......@@ -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,16 +250,11 @@ 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_);
// 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();
}
......@@ -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;
......
......@@ -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));
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() {
......
......@@ -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_;
......
......@@ -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);
......
......@@ -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();
......
......@@ -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;
......
......@@ -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);
......
......@@ -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.
......
......@@ -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|.
......
......@@ -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]);
......@@ -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);
}
......
......@@ -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);
......
......@@ -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_;
}
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment