summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/input_method/input_method_manager_impl.cc78
-rw-r--r--chrome/browser/chromeos/input_method/input_method_manager_impl.h21
-rw-r--r--chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc124
-rw-r--r--chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h67
-rw-r--r--chrome/browser/chromeos/input_method/input_method_persistence.cc63
-rw-r--r--chrome/browser/chromeos/input_method/mock_input_method_manager.cc15
-rw-r--r--chrome/browser/chromeos/input_method/mock_input_method_manager.h8
-rw-r--r--chrome/browser/prefs/browser_prefs.cc2
-rw-r--r--chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc101
-rw-r--r--chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h9
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/common/pref_names.cc4
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--chromeos/ime/input_method_manager.h13
-rw-r--r--chromeos/ime/input_methods.txt9
15 files changed, 493 insertions, 24 deletions
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 fcb8919..c0082d0 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -110,6 +110,12 @@ const struct MigrationHangulKeyboardToInputMethodID {
} // namespace
+bool InputMethodManagerImpl::IsFullLatinKeyboard(
+ const std::string& layout) const {
+ const std::string& lang = util_.GetLanguageCodeFromInputMethodId(layout);
+ return full_latin_keyboard_checker.IsFullLatinKeyboard(layout, lang);
+}
+
InputMethodManagerImpl::InputMethodManagerImpl(
scoped_ptr<InputMethodDelegate> delegate)
: delegate_(delegate.Pass()),
@@ -207,6 +213,11 @@ InputMethodManagerImpl::GetActiveInputMethods() const {
return result.Pass();
}
+const std::vector<std::string>&
+InputMethodManagerImpl::GetActiveInputMethodIds() const {
+ return active_input_method_ids_;
+}
+
size_t InputMethodManagerImpl::GetNumActiveInputMethods() const {
return active_input_method_ids_.size();
}
@@ -250,6 +261,46 @@ void InputMethodManagerImpl::EnableLayouts(const std::string& language_code,
ChangeInputMethod(initial_layout); // you can pass empty |initial_layout|.
}
+// Adds new input method to given list.
+bool InputMethodManagerImpl::EnableInputMethodImpl(
+ const std::string& input_method_id,
+ std::vector<std::string>& new_active_input_method_ids) const {
+ if (!util_.IsValidInputMethodId(input_method_id)) {
+ DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
+ return false;
+ }
+
+ if (!Contains(new_active_input_method_ids, input_method_id))
+ new_active_input_method_ids.push_back(input_method_id);
+
+ return true;
+}
+
+// Starts or stops the system input method framework as needed.
+void InputMethodManagerImpl::ReconfigureIMFramework() {
+ if (component_extension_ime_manager_->IsInitialized())
+ LoadNecessaryComponentExtensions();
+
+ if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
+ // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
+ // at crbug.com/27051.
+ // TODO(yusukes): We can safely call Stop(); here once crbug.com/26443
+ // is implemented.
+ } else {
+ MaybeInitializeCandidateWindowController();
+ IBusDaemonController::GetInstance()->Start();
+ }
+}
+
+bool InputMethodManagerImpl::EnableInputMethod(
+ const std::string& input_method_id) {
+ if (!EnableInputMethodImpl(input_method_id, active_input_method_ids_))
+ return false;
+
+ ReconfigureIMFramework();
+ return true;
+}
+
bool InputMethodManagerImpl::EnableInputMethods(
const std::vector<std::string>& new_active_input_method_ids) {
if (state_ == STATE_TERMINATING)
@@ -258,13 +309,9 @@ bool InputMethodManagerImpl::EnableInputMethods(
// Filter unknown or obsolete IDs.
std::vector<std::string> new_active_input_method_ids_filtered;
- for (size_t i = 0; i < new_active_input_method_ids.size(); ++i) {
- const std::string& input_method_id = new_active_input_method_ids[i];
- if (util_.IsValidInputMethodId(input_method_id))
- new_active_input_method_ids_filtered.push_back(input_method_id);
- else
- DVLOG(1) << "EnableInputMethods: Invalid ID: " << input_method_id;
- }
+ for (size_t i = 0; i < new_active_input_method_ids.size(); ++i)
+ EnableInputMethodImpl(new_active_input_method_ids[i],
+ new_active_input_method_ids_filtered);
if (new_active_input_method_ids_filtered.empty()) {
DVLOG(1) << "EnableInputMethods: No valid input method ID";
@@ -280,18 +327,7 @@ bool InputMethodManagerImpl::EnableInputMethods(
}
active_input_method_ids_.swap(new_active_input_method_ids_filtered);
- if (component_extension_ime_manager_->IsInitialized())
- LoadNecessaryComponentExtensions();
-
- if (ContainOnlyKeyboardLayout(active_input_method_ids_)) {
- // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
- // at crosbug.com/27051.
- // TODO(yusukes): We can safely call Stop(); here once crosbug.com/26443
- // is implemented.
- } else {
- MaybeInitializeCandidateWindowController();
- IBusDaemonController::GetInstance()->Start();
- }
+ ReconfigureIMFramework();
// If |current_input_method| is no longer in |active_input_method_ids_|,
// ChangeInputMethod() picks the first one in |active_input_method_ids_|.
@@ -564,7 +600,7 @@ void InputMethodManagerImpl::RemoveInputMethodExtension(const std::string& id) {
active_input_method_ids_.erase(i);
extra_input_methods_.erase(id);
- if (ContainOnlyKeyboardLayout(active_input_method_ids_)) {
+ if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
// Do NOT call ibus_controller_->Stop(); here to work around a crash issue
// at crosbug.com/27051.
// TODO(yusukes): We can safely call Stop(); here once crosbug.com/26443
@@ -918,7 +954,7 @@ bool InputMethodManagerImpl::InputMethodIsActivated(
return Contains(active_input_method_ids_, input_method_id);
}
-bool InputMethodManagerImpl::ContainOnlyKeyboardLayout(
+bool InputMethodManagerImpl::ContainsOnlyKeyboardLayout(
const std::vector<std::string>& value) {
for (size_t i = 0; i < value.size(); ++i) {
if (!InputMethodUtil::IsKeyboardLayout(value[i]))
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index 521e04a..16de674 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -14,6 +14,7 @@
#include "base/threading/thread_checker.h"
#include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
#include "chrome/browser/chromeos/input_method/ibus_controller.h"
+#include "chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chromeos/ime/ibus_daemon_controller.h"
#include "chromeos/ime/input_method_manager.h"
@@ -58,11 +59,15 @@ class InputMethodManagerImpl : public InputMethodManager,
GetSupportedInputMethods() const OVERRIDE;
virtual scoped_ptr<InputMethodDescriptors>
GetActiveInputMethods() const OVERRIDE;
+ virtual const std::vector<std::string>& GetActiveInputMethodIds() const
+ OVERRIDE;
virtual size_t GetNumActiveInputMethods() const OVERRIDE;
virtual void EnableLayouts(const std::string& language_code,
const std::string& initial_layout) OVERRIDE;
virtual bool EnableInputMethods(
const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
+ virtual bool EnableInputMethod(const std::string& new_active_input_method_id)
+ OVERRIDE;
virtual bool MigrateOldInputMethods(
std::vector<std::string>* input_method_ids) OVERRIDE;
virtual bool MigrateKoreanKeyboard(
@@ -95,6 +100,7 @@ class InputMethodManagerImpl : public InputMethodManager,
virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
virtual ComponentExtensionIMEManager*
GetComponentExtensionIMEManager() OVERRIDE;
+ virtual bool IsFullLatinKeyboard(const std::string& layout) const OVERRIDE;
// Sets |ibus_controller_|.
void SetIBusControllerForTesting(IBusController* ibus_controller);
@@ -135,7 +141,7 @@ class InputMethodManagerImpl : public InputMethodManager,
// Returns true if the given input method config value is a string list
// that only contains an input method ID of a keyboard layout.
- bool ContainOnlyKeyboardLayout(const std::vector<std::string>& value);
+ bool ContainsOnlyKeyboardLayout(const std::vector<std::string>& value);
// Returns true if the connection to ibus-daemon is established.
bool IsIBusConnectionAlive();
@@ -165,6 +171,15 @@ class InputMethodManagerImpl : public InputMethodManager,
// TODO(nona): Support dynamical unloading.
void LoadNecessaryComponentExtensions();
+ // Adds new input method to given list if possible
+ bool EnableInputMethodImpl(
+ const std::string& input_method_id,
+ std::vector<std::string>& new_active_input_method_ids) const;
+
+ // Starts or stops the system input method framework as needed.
+ // (after list of enabled input methods has been updated)
+ void ReconfigureIMFramework();
+
scoped_ptr<InputMethodDelegate> delegate_;
// The current browser status.
@@ -223,6 +238,10 @@ class InputMethodManagerImpl : public InputMethodManager,
base::WeakPtrFactory<InputMethodManagerImpl> weak_ptr_factory_;
+ // Check if input method id allows full latin input (for entering passwords on
+ // login screen)
+ FullLatinKeyboardLayoutChecker full_latin_keyboard_checker;
+
DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
};
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc
new file mode 100644
index 0000000..7bf850c
--- /dev/null
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h"
+
+#include <string.h>
+
+#include <limits>
+
+namespace chromeos {
+namespace input_method {
+
+struct KBDList {
+ const char* const* layouts;
+ size_t size;
+};
+
+namespace {
+
+// A language may have some special layout that allows full latin input.
+static const char* const kJPFullLatinKeyboardLayouts[] = {
+ "xkb:jp::jpn"
+};
+
+static const KBDList kJPFullLatinKeyboards = {
+ kJPFullLatinKeyboardLayouts, arraysize(kJPFullLatinKeyboardLayouts)
+};
+
+// A list of languages and their layouts having full 26 latin letter set on
+// keyboard.
+
+// If permitted_layouts is NULL, then all keyboard layouts for the
+// language are "Full Latin Input" and can be used to input passwords on
+// login screen.
+
+// If permitted_layouts is not NULL, it must contain all layouts for the
+// language, that can be used at login screen.
+//
+static const struct SomeLatinKeyboardLanguageList {
+ const char* lang;
+ const KBDList* permitted_layouts;
+} kHasLatinKeyboardLanguageList[] = {
+ {"ca" /* Catalan */, NULL},
+ {"cs" /* Czech */, NULL},
+ {"da" /* Danish */, NULL},
+ {"de" /* German */, NULL},
+ {"en" /* English */, NULL},
+ {"es" /* Spanish */, NULL},
+ {"et" /* Estonian */, NULL},
+ {"fi" /* Finnish */, NULL},
+ {"fr" /* French */, NULL},
+ {"ja" /* Japanese */, &kJPFullLatinKeyboards},
+ {"hr" /* Croatian */, NULL},
+ {"hu" /* Hungarian */, NULL},
+ {"is" /* Icelandic */, NULL},
+ {"it" /* Italian */, NULL},
+ {"lt" /* Lithuanian */, NULL},
+ {"lv" /* Latvian */, NULL},
+ {"nb" /* Norwegian (Bokmal) */, NULL},
+ {"nl" /* Dutch */, NULL},
+ {"pl" /* Polish */, NULL},
+ {"pt" /* Portuguese */, NULL},
+ {"ro" /* Romanian */, NULL},
+ {"sk" /* Slovak */, NULL},
+ {"sl" /* Slovenian */, NULL},
+ {"sv" /* Swedish */, NULL},
+ {"tr" /* Turkish */, NULL},
+};
+
+} // namespace
+
+bool FullLatinKeyboardLayoutChecker::IsFullLatinKeyboard(
+ const std::string& layout,
+ const std::string& lang) const {
+ if (lang.size() < 2) {
+ return false;
+ }
+
+ const TwoLetterLanguageCode ll(lang.c_str());
+ const std::vector<TwoLetterLanguageCode2KBDList>::const_iterator pos =
+ std::lower_bound(full_latin_keyboard_languages_.begin(),
+ full_latin_keyboard_languages_.end(),
+ ll);
+
+ if (pos == full_latin_keyboard_languages_.end())
+ return false;
+
+ if (pos->lang != ll)
+ return false;
+
+ const KBDList* kbdlist =
+ kHasLatinKeyboardLanguageList[pos->index].permitted_layouts;
+
+ if (kbdlist == NULL)
+ return true;
+
+ for (size_t i = 0; i < kbdlist->size; ++i)
+ if (strcmp(layout.c_str(), kbdlist->layouts[i]) == 0)
+ return true;
+
+ return false;
+}
+
+FullLatinKeyboardLayoutChecker::FullLatinKeyboardLayoutChecker() {
+ DCHECK(arraysize(kHasLatinKeyboardLanguageList) <
+ std::numeric_limits<uint16_t>::max());
+
+ full_latin_keyboard_languages_.reserve(
+ arraysize(kHasLatinKeyboardLanguageList));
+
+ for (size_t i = 0; i < arraysize(kHasLatinKeyboardLanguageList); ++i)
+ full_latin_keyboard_languages_.push_back(TwoLetterLanguageCode2KBDList(
+ kHasLatinKeyboardLanguageList[i].lang, i));
+
+ std::sort(full_latin_keyboard_languages_.begin(),
+ full_latin_keyboard_languages_.end());
+}
+
+FullLatinKeyboardLayoutChecker::~FullLatinKeyboardLayoutChecker() {
+}
+
+} // namespace input_method
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h
new file mode 100644
index 0000000..f670abc
--- /dev/null
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_ll.h
@@ -0,0 +1,67 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
+#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
+
+// "Latin Layout" checker: checks if given keyboard layout is "Full Latin Input"
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_util.h"
+
+namespace chromeos {
+namespace input_method {
+
+class TwoLetterLanguageCode {
+ public:
+ TwoLetterLanguageCode() : val(0) {}
+ explicit TwoLetterLanguageCode(const char* lang)
+ : val(base::ToLowerASCII(lang[0]) * 256 + base::ToLowerASCII(lang[1])) {}
+
+ bool operator<(const TwoLetterLanguageCode& r) const { return val < r.val; }
+ bool operator!=(const TwoLetterLanguageCode& r) const { return val != r.val; }
+
+ private:
+ uint16_t val;
+};
+
+// To keep index small, sizeof(TwoLetterLanguageCode2KBDList) = 4.
+class TwoLetterLanguageCode2KBDList {
+ public:
+ TwoLetterLanguageCode2KBDList() : index(0) {}
+ TwoLetterLanguageCode2KBDList(const char* l, const uint16_t i)
+ : lang(l), index(i) {}
+
+ bool operator<(const TwoLetterLanguageCode2KBDList& r) const {
+ return lang < r.lang;
+ }
+ bool operator<(const TwoLetterLanguageCode& r) const { return lang < r; }
+
+ TwoLetterLanguageCode lang;
+
+ // index in kHasLatinKeyboardLanguageList[]
+ uint16_t index;
+};
+
+// For fast lookup "whether this language and layout are among listed in
+// kHasLatinKeyboardLanguageList[] or not".
+class FullLatinKeyboardLayoutChecker {
+ public:
+ FullLatinKeyboardLayoutChecker();
+ ~FullLatinKeyboardLayoutChecker();
+
+ bool IsFullLatinKeyboard(const std::string& layout,
+ const std::string& lang) const;
+
+ private:
+ // Sorted vector for fast lookup.
+ std::vector<TwoLetterLanguageCode2KBDList> full_latin_keyboard_languages_;
+};
+
+} // namespace input_method
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_MANAGER_IMPL_LL_H_
diff --git a/chrome/browser/chromeos/input_method/input_method_persistence.cc b/chrome/browser/chromeos/input_method/input_method_persistence.cc
index 9562b23..49809fe 100644
--- a/chrome/browser/chromeos/input_method/input_method_persistence.cc
+++ b/chrome/browser/chromeos/input_method/input_method_persistence.cc
@@ -4,11 +4,13 @@
#include "chrome/browser/chromeos/input_method/input_method_persistence.h"
+#include "base/chromeos/chromeos_version.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
@@ -25,7 +27,62 @@ void PersistSystemInputMethod(const std::string& input_method) {
language_prefs::kPreferredKeyboardLayout, input_method);
}
-void PersistUserInputMethod(const std::string& input_method) {
+// Update user LRU keyboard layout for login screen
+static void SetUserLRUInputMethod(
+ const std::string& input_method,
+ const chromeos::input_method::InputMethodManager* const manager) {
+ // Skip if it's not a keyboard layout. Drop input methods including
+ // extension ones.
+ if (!InputMethodUtil::IsKeyboardLayout(input_method))
+ return;
+
+ PrefService* const local_state = g_browser_process->local_state();
+
+ Profile* const profile = ProfileManager::GetDefaultProfile();
+
+ if (profile == NULL)
+ return;
+
+ if (!manager->IsFullLatinKeyboard(input_method))
+ return;
+
+ const std::string username = profile->GetProfileName();
+ if (base::chromeos::IsRunningOnChromeOS() && !username.empty() &&
+ !local_state->ReadOnly()) {
+ bool update_succeed = false;
+ {
+ // Updater may have side-effects, therefore we do not replace
+ // entry while updater exists.
+ DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+ base::DictionaryValue* const users_lru_input_methods = updater.Get();
+ if (users_lru_input_methods) {
+ users_lru_input_methods->SetStringWithoutPathExpansion(username,
+ input_method);
+ update_succeed = true;
+ }
+ }
+ if (!update_succeed) {
+ // Somehow key kUsersLRUInputMethod has value of invalid type.
+ // Replace and retry.
+ local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue());
+
+ DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+ base::DictionaryValue* const users_lru_input_methods = updater.Get();
+ if (users_lru_input_methods) {
+ users_lru_input_methods->SetStringWithoutPathExpansion(username,
+ input_method);
+ update_succeed = true;
+ }
+ }
+ if (!update_succeed) {
+ DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '"
+ << prefs::kUsersLRUInputMethod << "' for '" << username << "'";
+ }
+ }
+}
+
+void PersistUserInputMethod(const std::string& input_method,
+ InputMethodManager* const manager) {
PrefService* user_prefs = NULL;
Profile* profile = ProfileManager::GetDefaultProfile();
if (profile)
@@ -33,6 +90,8 @@ void PersistUserInputMethod(const std::string& input_method) {
if (!user_prefs)
return;
+ SetUserLRUInputMethod(input_method, manager);
+
const std::string current_input_method_on_pref =
user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
if (current_input_method_on_pref == input_method)
@@ -73,7 +132,7 @@ void InputMethodPersistence::InputMethodChanged(
PersistSystemInputMethod(current_input_method);
return;
case InputMethodManager::STATE_BROWSER_SCREEN:
- PersistUserInputMethod(current_input_method);
+ PersistUserInputMethod(current_input_method, manager);
return;
case InputMethodManager::STATE_LOCK_SCREEN:
// We use a special set of input methods on the screen. Do not update.
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
index ad18c70..4e5cf82 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
@@ -11,6 +11,7 @@ MockInputMethodManager::MockInputMethodManager()
: add_observer_count_(0),
remove_observer_count_(0),
util_(&delegate_, whitelist_.GetSupportedInputMethods()) {
+ active_input_method_ids_.push_back("xkb:us::eng");
}
MockInputMethodManager::~MockInputMethodManager() {
@@ -50,6 +51,11 @@ MockInputMethodManager::GetActiveInputMethods() const {
return result.Pass();
}
+const std::vector<std::string>&
+MockInputMethodManager::GetActiveInputMethodIds() const {
+ return active_input_method_ids_;
+}
+
size_t MockInputMethodManager::GetNumActiveInputMethods() const {
return 1;
}
@@ -63,6 +69,11 @@ bool MockInputMethodManager::EnableInputMethods(
return true;
}
+bool MockInputMethodManager::EnableInputMethod(
+ const std::string& new_active_input_method_id) {
+ return true;
+}
+
bool MockInputMethodManager::MigrateOldInputMethods(
std::vector<std::string>* input_method_ids) {
return false;
@@ -162,5 +173,9 @@ void MockInputMethodManager::set_hardware_keyboard_layout(
delegate_.set_hardware_keyboard_layout(value);
}
+bool MockInputMethodManager::IsFullLatinKeyboard(
+ const std::string& layout) const {
+ return true;
+}
} // namespace input_method
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.h b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
index e373707..aa001c8 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.h
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
@@ -31,11 +31,15 @@ class MockInputMethodManager : public InputMethodManager {
GetSupportedInputMethods() const OVERRIDE;
virtual scoped_ptr<InputMethodDescriptors>
GetActiveInputMethods() const OVERRIDE;
+ virtual const std::vector<std::string>& GetActiveInputMethodIds() const
+ OVERRIDE;
virtual size_t GetNumActiveInputMethods() const OVERRIDE;
virtual void EnableLayouts(const std::string& language_code,
const std::string& initial_layout) OVERRIDE;
virtual bool EnableInputMethods(
const std::vector<std::string>& new_active_input_method_ids) OVERRIDE;
+ virtual bool EnableInputMethod(
+ const std::string& new_active_input_method_id) OVERRIDE;
virtual bool MigrateOldInputMethods(
std::vector<std::string>* input_method_ids) OVERRIDE;
virtual bool MigrateKoreanKeyboard(
@@ -68,6 +72,7 @@ class MockInputMethodManager : public InputMethodManager {
virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
virtual ComponentExtensionIMEManager*
GetComponentExtensionIMEManager() OVERRIDE;
+ virtual bool IsFullLatinKeyboard(const std::string& layout) const OVERRIDE;
// Sets an input method ID which will be returned by GetCurrentInputMethod().
void SetCurrentInputMethodId(const std::string& input_method_id) {
@@ -91,6 +96,9 @@ class MockInputMethodManager : public InputMethodManager {
InputMethodUtil util_;
MockXKeyboard xkeyboard_;
+ // The active input method ids cache (actually default only)
+ std::vector<std::string> active_input_method_ids_;
+
DISALLOW_COPY_AND_ASSIGN(MockInputMethodManager);
};
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 14cc6a7..5e90827 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -145,6 +145,7 @@
#include "chrome/browser/chromeos/status/data_promo_notification.h"
#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
#include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
+#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
#else
#include "chrome/browser/extensions/default_apps.h"
#endif
@@ -262,6 +263,7 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
chromeos::proxy_config::RegisterPrefs(registry);
chromeos::RegisterDisplayLocalStatePrefs(registry);
chromeos::ServicesCustomizationDocument::RegisterPrefs(registry);
+ chromeos::SigninScreenHandler::RegisterPrefs(registry);
chromeos::system::AutomaticRebootManager::RegisterPrefs(registry);
chromeos::UserImageManager::RegisterPrefs(registry);
chromeos::UserManager::RegisterPrefs(registry);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index adfeb11..55197bf 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -5,11 +5,13 @@
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
#include "base/callback.h"
+#include "base/chromeos/chromeos_version.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
@@ -20,6 +22,7 @@
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
#include "chrome/browser/chromeos/login/hwid_checker.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
@@ -32,6 +35,7 @@
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
@@ -103,6 +107,12 @@ void ClearDnsCache(IOThread* io_thread) {
io_thread->ClearHostCache();
}
+static bool Contains(const std::vector<std::string>& container,
+ const std::string& value) {
+ return std::find(container.begin(), container.end(), value) !=
+ container.end();
+}
+
} // namespace
namespace chromeos {
@@ -312,6 +322,59 @@ void RecordNetworkPortalDetectorStats(const std::string& service_path) {
}
}
+static bool SetUserInputMethodImpl(
+ const std::string& username,
+ chromeos::input_method::InputMethodManager* manager) {
+ PrefService* const local_state = g_browser_process->local_state();
+
+ const base::DictionaryValue* users_lru_input_methods =
+ local_state->GetDictionary(prefs::kUsersLRUInputMethod);
+
+ if (users_lru_input_methods == NULL) {
+ DLOG(WARNING) << "SetUserInputMethod('" << username
+ << "'): no kUsersLRUInputMethod";
+ return false;
+ }
+
+ std::string input_method;
+
+ if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
+ &input_method)) {
+ DLOG(INFO) << "SetUserInputMethod('" << username
+ << "'): no input method for this user";
+ return false;
+ }
+
+ if (input_method.empty())
+ return false;
+
+ if (!manager->IsFullLatinKeyboard(input_method)) {
+ LOG(WARNING) << "SetUserInputMethod('" << username
+ << "'): stored user LRU input method '" << input_method
+ << "' is no longer Full Latin Keyboard Language"
+ << " (entry dropped). Use hardware default instead.";
+
+ DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+
+ base::DictionaryValue* const users_lru_input_methods = updater.Get();
+ if (users_lru_input_methods != NULL) {
+ users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
+ }
+ return false;
+ }
+
+ if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
+ if (!manager->EnableInputMethod(input_method)) {
+ DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
+ << "'): user input method '" << input_method
+ << "' is not enabled and enabling failed (ignored!).";
+ }
+ }
+ manager->ChangeInputMethod(input_method);
+
+ return true;
+}
+
} // namespace
// SigninScreenHandler implementation ------------------------------------------
@@ -814,6 +877,10 @@ void SigninScreenHandler::RegisterMessages() {
&SigninScreenHandler::HandleUpdateOfflineLogin);
}
+void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
+}
+
void SigninScreenHandler::HandleGetUsers() {
SendUserList(false);
}
@@ -970,6 +1037,35 @@ void SigninScreenHandler::OnDnsCleared() {
ShowSigninScreenIfReady();
}
+void SigninScreenHandler::SetUserInputMethodHWDefault() {
+ chromeos::input_method::InputMethodManager* manager =
+ chromeos::input_method::InputMethodManager::Get();
+ manager->ChangeInputMethod(
+ manager->GetInputMethodUtil()->GetHardwareInputMethodId());
+}
+
+// Update keyboard layout to least recently used by the user.
+void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
+ chromeos::input_method::InputMethodManager* const manager =
+ chromeos::input_method::InputMethodManager::Get();
+
+ const chromeos::input_method::InputMethodUtil& ime_util =
+ *manager->GetInputMethodUtil();
+
+ const bool succeed = SetUserInputMethodImpl(username, manager);
+
+ // This is also a case when LRU layout is set only for a few local users,
+ // thus others need to be switched to default locale.
+ // Otherwise they will end up using another user's locale to log in.
+ if (!succeed) {
+ DLOG(INFO) << "SetUserInputMethod('" << username
+ << "'): failed to set user layout. Switching to default '"
+ << ime_util.GetHardwareInputMethodId() << "'";
+
+ SetUserInputMethodHWDefault();
+ }
+}
+
void SigninScreenHandler::ShowSigninScreenIfReady() {
if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
return;
@@ -991,6 +1087,10 @@ void SigninScreenHandler::ShowSigninScreenIfReady() {
else
delegate_->LoadWallpaper(email_);
+ // Set Least Recently Used input method for the user.
+ if (!email_.empty())
+ SetUserInputMethod(email_);
+
LoadAuthExtension(!gaia_silent_load_, false, false);
UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
@@ -1210,6 +1310,7 @@ void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
&SigninScreenHandler::ShowSigninScreenIfReady,
weak_factory_.GetWeakPtr()));
}
+ SetUserInputMethodHWDefault();
}
void SigninScreenHandler::HandleToggleEnrollmentScreen() {
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index aea2d03..5768ab2 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -193,6 +193,9 @@ class SigninScreenHandler
virtual void UpdateState(NetworkStateInformer::State state,
ErrorScreenActor::ErrorReason reason) OVERRIDE;
+ // Required Local State preferences.
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
private:
enum UIState {
UI_STATE_UNKNOWN = 0,
@@ -379,6 +382,12 @@ class SigninScreenHandler
// Attempts login for test.
void SubmitLoginFormForTest();
+ // Update current input method (namely keyboard layout) to LRU by this user.
+ void SetUserInputMethod(const std::string& username);
+
+ // Update current input method to HW default.
+ void SetUserInputMethodHWDefault();
+
// Current UI state of the signin screen.
UIState ui_state_;
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index c891274..08024d6 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -391,6 +391,8 @@
'browser/chromeos/input_method/input_method_engine.h',
'browser/chromeos/input_method/input_method_manager_impl.cc',
'browser/chromeos/input_method/input_method_manager_impl.h',
+ 'browser/chromeos/input_method/input_method_manager_impl_ll.cc',
+ 'browser/chromeos/input_method/input_method_manager_impl_ll.h',
'browser/chromeos/input_method/input_method_persistence.cc',
'browser/chromeos/input_method/input_method_persistence.h',
'browser/chromeos/input_method/input_method_util.cc',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 78702ba..1e8eaf7 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -2122,6 +2122,10 @@ const char kDeviceEnrollmentAutoStart[] = "enrollment.auto_start";
// Whether the user may exit enrollment.
const char kDeviceEnrollmentCanExit[] = "enrollment.can_exit";
+
+// Dictionary of per-user Least Recently Used input method (used at login
+// screen).
+extern const char kUsersLRUInputMethod[] = "UsersLRUInputMethod";
#endif
// Whether there is a Flash version installed that supports clearing LSO data.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 6d1d322..e128646 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -773,6 +773,7 @@ extern const char kDeviceRobotAnyApiRefreshToken[];
extern const char kDeviceEnrollmentRequisition[];
extern const char kDeviceEnrollmentAutoStart[];
extern const char kDeviceEnrollmentCanExit[];
+extern const char kUsersLRUInputMethod[];
#endif
extern const char kClearPluginLSODataEnabled[];
diff --git a/chromeos/ime/input_method_manager.h b/chromeos/ime/input_method_manager.h
index bfeacf6..e2d38dd 100644
--- a/chromeos/ime/input_method_manager.h
+++ b/chromeos/ime/input_method_manager.h
@@ -98,6 +98,11 @@ class CHROMEOS_EXPORT InputMethodManager {
// extension input methods.
virtual scoped_ptr<InputMethodDescriptors> GetActiveInputMethods() const = 0;
+ // Returns the list of input methods we can select (i.e. active) including
+ // extension input methods.
+ // The same as GetActiveInputMethods but returns reference to internal list.
+ virtual const std::vector<std::string>& GetActiveInputMethodIds() const = 0;
+
// Returns the number of active input methods including extension input
// methods.
virtual size_t GetNumActiveInputMethods() const = 0;
@@ -125,6 +130,11 @@ class CHROMEOS_EXPORT InputMethodManager {
virtual bool EnableInputMethods(
const std::vector<std::string>& new_active_input_method_ids) = 0;
+ // Adds one entry to the list of active input method IDs, and then starts or
+ // stops the system input method framework as needed.
+ virtual bool EnableInputMethod(
+ const std::string& new_active_input_method_id) = 0;
+
// Remaps old input methods like "mozc" to new input methods. Return true if
// at least one IME is migrated.
// TODO(nona): Remove this function after few milestones are passed.
@@ -185,6 +195,9 @@ class CHROMEOS_EXPORT InputMethodManager {
// Switches to an input method (or keyboard layout) which is associated with
// the |accelerator|.
virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) = 0;
+
+ // If keyboard layout can be uset at login screen
+ virtual bool IsFullLatinKeyboard(const std::string& layout) const = 0;
};
} // namespace input_method
diff --git a/chromeos/ime/input_methods.txt b/chromeos/ime/input_methods.txt
index 85ee9b93..213ea96 100644
--- a/chromeos/ime/input_methods.txt
+++ b/chromeos/ime/input_methods.txt
@@ -56,6 +56,15 @@
# XKB layout), you should also update IsMod3UsedByCurrentInputMethod() method
# in chrome/browser/ui/ash/event_rewriter.cc. Otherwise, Mod3Mask might be
# removed unexpectedly by the rewriter.
+#
+# If you add a new language such that some of its layouts can be used at
+# signin screen (e.g. it is "Full Latin Keyboard Layout" therefore allowing
+# input of gmail password), you should also update
+# kHasLatinKeyboardLanguageList[] in
+# chrome/browser/chromeos/input_method/input_method_manager_impl_ll.cc
+#
+# If you add a new keyboard layout for existing language, please ensure
+# that information in kHasLatinKeyboardLanguageList[] is still correct.
# U.S. English
xkb:us::eng us en-US