Chromium Code Reviews| Index: chrome/browser/chromeos/preferences.cc |
| diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc |
| index d0e04df2792ce1d2af8709b4bf1f57bad55f0e96..8c32670c3afd8a8c6f940de1bc91a323ce1347a4 100644 |
| --- a/chrome/browser/chromeos/preferences.cc |
| +++ b/chrome/browser/chromeos/preferences.cc |
| @@ -4,7 +4,7 @@ |
| #include "chrome/browser/chromeos/preferences.h" |
| -#include <vector> |
| +#include <algorithm> |
| #include "ash/autoclick/autoclick_controller.h" |
| #include "ash/magnifier/magnifier_constants.h" |
| @@ -32,6 +32,7 @@ |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/pref_names.h" |
| #include "chromeos/chromeos_switches.h" |
| +#include "chromeos/ime/component_extension_ime_manager.h" |
| #include "chromeos/ime/extension_ime_util.h" |
| #include "chromeos/ime/ime_keyboard.h" |
| #include "chromeos/ime/input_method_manager.h" |
| @@ -39,14 +40,102 @@ |
| #include "components/feedback/tracing_manager.h" |
| #include "components/pref_registry/pref_registry_syncable.h" |
| #include "third_party/icu/source/i18n/unicode/timezone.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| #include "ui/events/event_constants.h" |
| #include "ui/events/event_utils.h" |
| #include "url/gurl.h" |
| namespace chromeos { |
| +namespace { |
| + |
| static const char kFallbackInputMethodLocale[] = "en-US"; |
| +// Removes unsupported languages from |values|. |
| +void CheckLanguages(std::vector<std::string>& values) { |
| + std::vector<std::string>::iterator iter = values.begin(); |
| + while (iter != values.end()) { |
| + std::string locale = *iter; |
| + if (l10n_util::CheckAndResolveLocale(locale, &locale) && |
| + locale == *iter) |
| + ++iter; |
| + else |
| + iter = values.erase(iter); |
| + } |
| +} |
| + |
| +// Removes unsupported input method IDs from |values|. |
| +void CheckInputMethodIDs( |
| + std::vector<std::string>& values, |
| + const input_method::InputMethodDescriptors& supported) { |
| + // Convert legacay descriptors to input method extension IDs. |
| + std::vector<std::string> input_method_ids; |
| + for (size_t i = 0; i < input_method_ids.size(); i++) { |
| + input_method_ids.push_back( |
| + extension_ime_util::GetInputMethodIDByEngineID(supported[i].id())); |
| + } |
| + |
| + // Remove values that aren't in the list of input method IDs. |
| + std::vector<std::string>::iterator value_iter = values.begin(); |
| + while (value_iter != values.end()) { |
| + if (std::find(input_method_ids.begin(), |
| + input_method_ids.end(), |
| + *value_iter) != input_method_ids.end()) { |
| + ++value_iter; |
| + } else { |
| + value_iter = values.erase(value_iter); |
| + } |
| + } |
| +} |
| + |
| +// Returns the result of merging supported tokens from the CSV string |
| +// |new_value| into |old_value| for the given pref. Quadratic runtime; use only |
| +// for small lists. |
| +std::string MergeCSVPrefs(const std::string& old_value, |
| + const std::string& new_value, |
| + const std::string& pref_name) { |
| + std::vector<std::string> old_tokens; |
| + std::vector<std::string> new_tokens; |
| + |
| + base::SplitString(old_value, ',', &old_tokens); |
| + base::SplitString(new_value, ',', &new_tokens); |
| + |
| + if (pref_name == prefs::kLanguagePreferredLanguages) { |
| + CheckLanguages(new_tokens); |
| + } else if (pref_name == prefs::kLanguagePreloadEngines || |
| + pref_name == prefs::kLanguageEnabledExtensionImes) { |
| + input_method::InputMethodManager* manager = |
| + input_method::InputMethodManager::Get(); |
| + // Supported input methods. |
| + scoped_ptr<input_method::InputMethodDescriptors> descriptors; |
| + |
| + if (pref_name == prefs::kLanguagePreloadEngines) { |
| + // Set the known input methods. |
| + descriptors = manager->GetSupportedInputMethods(); |
| + // Add the available component extension IMEs. |
| + ComponentExtensionIMEManager* component_extension_manager = |
| + input_method::InputMethodManager::Get()-> |
| + GetComponentExtensionIMEManager(); |
| + if (component_extension_manager->IsInitialized()) { |
| + input_method::InputMethodDescriptors component_descriptors = |
| + component_extension_manager->GetAllIMEAsInputMethodDescriptor(); |
| + descriptors->insert(descriptors->end(), |
| + component_descriptors.begin(), |
| + component_descriptors.end()); |
| + } |
| + } else { |
| + descriptors.reset(new input_method::InputMethodDescriptors); |
| + manager->GetInputMethodExtensions(descriptors.get()); |
| + } |
| + CheckInputMethodIDs(new_tokens, *descriptors); |
| + } else { |
| + NOTREACHED() << "Attempting to merge an invalid preference."; |
| + } |
| + return JoinString(old_tokens, ','); |
| +} |
| + |
| +} // anonymous namespace |
| + |
| Preferences::Preferences() |
| : prefs_(NULL), |
| input_method_manager_(input_method::InputMethodManager::Get()), |
| @@ -213,21 +302,34 @@ void Preferences::RegisterProfilePrefs( |
| prefs::kLanguagePreviousInputMethod, |
| "", |
| user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| - // We don't sync the list of input methods and preferred languages since a |
| - // user might use two or more devices with different hardware keyboards. |
| - // crosbug.com/15181 |
| registry->RegisterStringPref( |
| prefs::kLanguagePreferredLanguages, |
| kFallbackInputMethodLocale, |
| user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| registry->RegisterStringPref( |
| + prefs::kLanguagePreferredLanguagesSyncable, |
| + "", |
| + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| + registry->RegisterStringPref( |
| prefs::kLanguagePreloadEngines, |
| hardware_keyboard_id, |
| user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| registry->RegisterStringPref( |
| + prefs::kLanguagePreloadEnginesSyncable, |
| + "", |
| + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| + registry->RegisterStringPref( |
| prefs::kLanguageEnabledExtensionImes, |
| "", |
| user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| + registry->RegisterStringPref( |
| + prefs::kLanguageEnabledExtensionImesSyncable, |
| + "", |
| + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| + registry->RegisterBooleanPref( |
| + prefs::kLanguageShouldMergeInputMethods, |
| + false, |
| + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| registry->RegisterIntegerPref( |
| prefs::kLanguageRemapSearchKeyTo, |
| @@ -329,9 +431,17 @@ void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { |
| prefs, callback); |
| touch_hud_projection_enabled_.Init(prefs::kTouchHudProjectionEnabled, |
| prefs, callback); |
| + preferred_languages_.Init(prefs::kLanguagePreferredLanguages, |
| + prefs, callback); |
| + preferred_languages_syncable_.Init(prefs::kLanguagePreferredLanguagesSyncable, |
| + prefs, callback); |
| preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, callback); |
| + preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable, |
| + prefs, callback); |
| enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes, |
| prefs, callback); |
| + enabled_extension_imes_syncable_.Init( |
| + prefs::kLanguageEnabledExtensionImesSyncable, prefs, callback); |
| current_input_method_.Init(prefs::kLanguageCurrentInputMethod, |
| prefs, callback); |
| previous_input_method_.Init(prefs::kLanguagePreviousInputMethod, |
| @@ -511,7 +621,9 @@ void Preferences::ApplyPreferences(ApplyReason reason, |
| pref_name == prefs::kTouchHudProjectionEnabled) { |
| if (user_is_active) { |
| const bool enabled = touch_hud_projection_enabled_.GetValue(); |
| - ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); |
| + // There may not be a shell, e.g., in some unit tests. |
| + if (ash::Shell::HasInstance()) |
| + ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); |
| } |
| } |
| @@ -531,25 +643,28 @@ void Preferences::ApplyPreferences(ApplyReason reason, |
| UpdateAutoRepeatRate(); |
| } |
| + if (reason == REASON_PREF_CHANGED && |
| + pref_name == prefs::kLanguagePreferredLanguages) |
| + SetSyncableInputMethodPrefs(); |
| + |
| if (reason != REASON_PREF_CHANGED && user_is_active) { |
| SetInputMethodList(); |
| - } else if (pref_name == prefs::kLanguagePreloadEngines && user_is_active) { |
| - SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, |
| - language_prefs::kPreloadEnginesConfigName, |
| - preload_engines_.GetValue()); |
| + } else if (pref_name == prefs::kLanguagePreloadEngines) { |
| + if (user_is_active) { |
| + SetLanguageConfigStringListAsCSV( |
| + language_prefs::kGeneralSectionName, |
| + language_prefs::kPreloadEnginesConfigName, |
| + preload_engines_.GetValue()); |
| + } |
| + SetSyncableInputMethodPrefs(); |
| } |
| if (reason != REASON_PREF_CHANGED || |
| pref_name == prefs::kLanguageEnabledExtensionImes) { |
| - if (user_is_active) { |
| - std::string value(enabled_extension_imes_.GetValue()); |
| - |
| - std::vector<std::string> split_values; |
| - if (!value.empty()) |
| - base::SplitString(value, ',', &split_values); |
| - |
| - input_method_manager_->SetEnabledExtensionImes(&split_values); |
| - } |
| + if (user_is_active) |
| + SetEnabledExtensionImes(); |
| + if (reason == REASON_PREF_CHANGED) |
| + SetSyncableInputMethodPrefs(); |
| } |
| if (user_is_active) { |
| @@ -562,6 +677,35 @@ void Preferences::ApplyPreferences(ApplyReason reason, |
| void Preferences::OnIsSyncingChanged() { |
| DVLOG(1) << "OnIsSyncingChanged"; |
| ForceNaturalScrollDefault(); |
| + |
| + if (prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods) && |
| + prefs_->IsSyncing()) { |
| + MergeSyncedInputMethods(); |
| + prefs_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, false); |
| + } |
| +} |
| + |
| +void Preferences::MergeSyncedInputMethods() { |
| + DCHECK(prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods)); |
| + |
| + preferred_languages_.SetValue( |
| + MergeCSVPrefs(preferred_languages_.GetValue(), |
| + preferred_languages_syncable_.GetValue(), |
| + prefs::kLanguagePreferredLanguages)); |
| + preload_engines_.SetValue( |
| + MergeCSVPrefs(preload_engines_.GetValue(), |
| + preload_engines_syncable_.GetValue(), |
| + prefs::kLanguagePreloadEngines)); |
| + enabled_extension_imes_.SetValue( |
| + MergeCSVPrefs(enabled_extension_imes_.GetValue(), |
| + enabled_extension_imes_syncable_.GetValue(), |
| + prefs::kLanguageEnabledExtensionImes)); |
| + |
| + SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, |
| + language_prefs::kPreloadEnginesConfigName, |
| + preload_engines_.GetValue()); |
| + SetEnabledExtensionImes(); |
| + SetSyncableInputMethodPrefs(); |
| } |
| void Preferences::ForceNaturalScrollDefault() { |
| @@ -621,6 +765,34 @@ void Preferences::SetInputMethodList() { |
| input_method_manager_->ChangeInputMethod(current_input_method_id); |
| } |
| +void Preferences::SetEnabledExtensionImes() { |
| + std::string value(enabled_extension_imes_.GetValue()); |
| + std::vector<std::string> split_values; |
| + if (!value.empty()) |
| + base::SplitString(value, ',', &split_values); |
| + input_method_manager_->SetEnabledExtensionImes(&split_values); |
| +} |
| + |
| +void Preferences::SetSyncableInputMethodPrefs() { |
| + // Set the language and input prefs at the same time. Otherwise, we may, |
| + // e.g., use a stale languages setting but push a new preload engines setting. |
| + if (!prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods)) { |
| + preferred_languages_syncable_.SetValue(preferred_languages_.GetValue()); |
| + enabled_extension_imes_syncable_.SetValue( |
| + enabled_extension_imes_.GetValue()); |
| + |
| + // For preload engines, use legacy xkb IDs so the preference can sync |
| + // across Chrome OS and Chromium OS. |
| + std::vector<std::string> engines; |
| + base::SplitString(preload_engines_.GetValue(), ',', &engines); |
| + std::transform(engines.begin(), engines.end(), engines.begin(), |
| + extension_ime_util::MaybeGetLegacyXkbId); |
|
Shu Chen
2014/06/11 03:54:55
extension_ime_util::MaybeGetLegacyXkbId to get eng
michaelpg
2014/06/28 05:25:28
Done.
|
| + /* for (int i = 0; i < engines.size(); i++) |
| + engines[i] = (engines[i]);*/ |
| + preload_engines_syncable_.SetValue(JoinString(engines, ',')); |
| + } |
| +} |
| + |
| void Preferences::UpdateAutoRepeatRate() { |
| input_method::AutoRepeatRate rate; |
| rate.initial_delay_in_ms = xkb_auto_repeat_delay_pref_.GetValue(); |