Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/preferences.h" | 5 #include "chrome/browser/chromeos/preferences.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <vector> | 8 #include <vector> |
| 8 | 9 |
| 9 #include "ash/autoclick/autoclick_controller.h" | 10 #include "ash/autoclick/autoclick_controller.h" |
| 10 #include "ash/magnifier/magnifier_constants.h" | 11 #include "ash/magnifier/magnifier_constants.h" |
| 11 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 13 #include "base/i18n/time_formatting.h" | 14 #include "base/i18n/time_formatting.h" |
| 14 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 15 #include "base/prefs/pref_member.h" | 16 #include "base/prefs/pref_member.h" |
| 16 #include "base/prefs/pref_registry_simple.h" | 17 #include "base/prefs/pref_registry_simple.h" |
| 17 #include "base/prefs/scoped_user_pref_update.h" | 18 #include "base/prefs/scoped_user_pref_update.h" |
| 18 #include "base/strings/string_split.h" | 19 #include "base/strings/string_split.h" |
| 19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
| 22 #include "chrome/browser/browser_process.h" | 23 #include "chrome/browser/browser_process.h" |
| 23 #include "chrome/browser/chrome_notification_types.h" | 24 #include "chrome/browser/chrome_notification_types.h" |
| 24 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" | 25 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" |
| 25 #include "chrome/browser/chromeos/drive/file_system_util.h" | 26 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| 26 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 27 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 27 #include "chrome/browser/chromeos/login/session/user_session_manager.h" | 28 #include "chrome/browser/chromeos/login/session/user_session_manager.h" |
| 28 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 29 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 29 #include "chrome/browser/chromeos/system/input_device_settings.h" | 30 #include "chrome/browser/chromeos/system/input_device_settings.h" |
| 30 #include "chrome/browser/download/download_prefs.h" | 31 #include "chrome/browser/download/download_prefs.h" |
| 31 #include "chrome/browser/prefs/pref_service_syncable.h" | 32 #include "chrome/browser/prefs/pref_service_syncable.h" |
| 32 #include "chrome/common/chrome_switches.h" | 33 #include "chrome/common/chrome_switches.h" |
| 33 #include "chrome/common/pref_names.h" | 34 #include "chrome/common/pref_names.h" |
| 34 #include "chromeos/chromeos_switches.h" | 35 #include "chromeos/chromeos_switches.h" |
| 36 #include "chromeos/ime/component_extension_ime_manager.h" | |
| 35 #include "chromeos/ime/extension_ime_util.h" | 37 #include "chromeos/ime/extension_ime_util.h" |
| 36 #include "chromeos/ime/ime_keyboard.h" | 38 #include "chromeos/ime/ime_keyboard.h" |
| 37 #include "chromeos/ime/input_method_manager.h" | 39 #include "chromeos/ime/input_method_manager.h" |
| 38 #include "chromeos/system/statistics_provider.h" | 40 #include "chromeos/system/statistics_provider.h" |
| 39 #include "components/feedback/tracing_manager.h" | 41 #include "components/feedback/tracing_manager.h" |
| 40 #include "components/pref_registry/pref_registry_syncable.h" | 42 #include "components/pref_registry/pref_registry_syncable.h" |
| 41 #include "components/user_manager/user.h" | 43 #include "components/user_manager/user.h" |
| 44 #include "content/public/browser/browser_thread.h" | |
| 42 #include "third_party/icu/source/i18n/unicode/timezone.h" | 45 #include "third_party/icu/source/i18n/unicode/timezone.h" |
| 46 #include "ui/base/l10n/l10n_util.h" | |
| 43 #include "ui/events/event_constants.h" | 47 #include "ui/events/event_constants.h" |
| 44 #include "ui/events/event_utils.h" | 48 #include "ui/events/event_utils.h" |
| 45 #include "url/gurl.h" | 49 #include "url/gurl.h" |
| 46 | 50 |
| 47 namespace chromeos { | 51 namespace chromeos { |
| 52 namespace { | |
| 48 | 53 |
| 49 static const char kFallbackInputMethodLocale[] = "en-US"; | 54 static const char kFallbackInputMethodLocale[] = "en-US"; |
| 50 | 55 |
| 56 // Checks input method IDs, converting engine IDs to input method IDs and | |
| 57 // removing unsupported IDs from |values|. | |
| 58 void CheckAndResolveInputMethodIDs( | |
| 59 std::vector<std::string>* values, | |
| 60 const input_method::InputMethodDescriptors& supported_descriptors) { | |
|
Alexander Alekseev
2014/10/28 15:11:00
Input arguments should go first.
michaelpg
2014/11/18 03:47:39
Done.
| |
| 61 // Extract the supported input method IDs into a set. | |
| 62 std::set<std::string> supported_input_method_ids; | |
| 63 for (size_t i = 0; i < supported_descriptors.size(); i++) | |
| 64 supported_input_method_ids.insert(supported_descriptors[i].id()); | |
| 65 | |
| 66 // Convert engine IDs to input method extension IDs. | |
| 67 std::transform(values->begin(), values->end(), values->begin(), | |
| 68 extension_ime_util::GetInputMethodIDByEngineID); | |
| 69 | |
| 70 // Remove values that aren't found in the set of supported input method IDs. | |
| 71 std::vector<std::string>::iterator it = values->begin(); | |
| 72 while (it != values->end()) { | |
| 73 if (it->size() && std::find(supported_input_method_ids.begin(), | |
| 74 supported_input_method_ids.end(), | |
| 75 *it) != supported_input_method_ids.end()) { | |
|
Alexander Alekseev
2014/10/28 15:11:00
Maybe a bit shorter:
supported_input_method_ids.f
michaelpg
2014/11/18 03:47:39
Done.
| |
| 76 ++it; | |
| 77 } else { | |
| 78 it = values->erase(it); | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 // Checks whether each language is supported, replacing locales with variants | |
| 84 // if they are available. Must be called on a thread that allows IO. | |
| 85 void CheckAndResolveLocales(std::string* languages) { | |
|
Alexander Alekseev
2014/10/28 15:11:00
DCHECK(BrowserThread::GetBlockingPool()->RunsTasks
michaelpg
2014/11/18 03:47:39
Done.
| |
| 86 if (languages->empty()) | |
| 87 return; | |
| 88 std::vector<std::string> values; | |
| 89 base::SplitString(*languages, ',', &values); | |
| 90 | |
| 91 const std::string app_locale = g_browser_process->GetApplicationLocale(); | |
| 92 | |
| 93 std::vector<std::string> accept_language_codes; | |
| 94 l10n_util::GetAcceptLanguagesForLocale(app_locale, &accept_language_codes); | |
| 95 | |
| 96 // Remove unsupported language values. | |
| 97 std::vector<std::string>::iterator value_iter = values.begin(); | |
| 98 while (value_iter != values.end()) { | |
| 99 if (std::find(accept_language_codes.begin(), accept_language_codes.end(), | |
|
Alexander Alekseev
2014/10/28 15:11:00
You traverse accept_language_codes linearly twice
michaelpg
2014/11/18 03:47:39
Done.
| |
| 100 *value_iter) != accept_language_codes.end()) { | |
| 101 ++value_iter; | |
| 102 continue; | |
| 103 } | |
| 104 | |
| 105 // If a language code resolves to a supported backup locale, replace it | |
| 106 // with the resolved locale. | |
| 107 std::string resolved_locale; | |
| 108 if (l10n_util::CheckAndResolveLocale(*value_iter, &resolved_locale)) { | |
| 109 if (std::find(accept_language_codes.begin(), accept_language_codes.end(), | |
| 110 resolved_locale) != accept_language_codes.end()) { | |
| 111 *value_iter = resolved_locale; | |
| 112 ++value_iter; | |
| 113 continue; | |
| 114 } | |
| 115 } | |
| 116 value_iter = values.erase(value_iter); | |
| 117 } | |
| 118 | |
| 119 *languages = JoinString(values, ','); | |
| 120 } | |
| 121 | |
| 122 // Appends tokens from |src| that are not in |dest| to |dest|. Quadratic | |
| 123 // runtime; use only for small lists. | |
| 124 void MergeLists(std::vector<std::string>* dest, | |
| 125 const std::vector<std::string>& src) { | |
| 126 for (size_t i = 0; i < src.size(); i++) { | |
|
dzhioev (left Google)
2014/11/06 16:29:07
nit: for (const std::string& token: src)
michaelpg
2014/11/18 03:47:39
Done.
| |
| 127 // Skip token if it's already in |dest|. | |
| 128 if (std::find(dest->begin(), dest->end(), src[i]) == dest->end()) | |
| 129 dest->push_back(src[i]); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 // Helper class to handle syncing of language and input method preferences. | |
| 134 // Changes to local preferences are handed up to the sync server. But Chrome OS | |
| 135 // should not locally apply the corresponding preferences from the sync server, | |
| 136 // except once: when the user first logs into the device. | |
| 137 // Thus, the user's most recent changes to language and input method preferences | |
| 138 // will be brought down when signing in to a new device but not in future syncs. | |
| 139 class InputMethodSyncer : public PrefServiceSyncableObserver { | |
|
Nikita (slow)
2014/10/21 11:45:56
I wonder if this class should be extracted into a
Alexander Alekseev
2014/10/28 15:11:00
+1
michaelpg
2014/11/18 03:47:39
Done.
| |
| 140 public: | |
| 141 InputMethodSyncer( | |
| 142 PrefServiceSyncable* prefs, | |
| 143 scoped_refptr<input_method::InputMethodManager::State> ime_state); | |
| 144 | |
| 145 // Registers the syncable input method prefs. | |
| 146 static void RegisterProfilePrefs( | |
| 147 user_prefs::PrefRegistrySyncable* registry); | |
| 148 | |
| 149 // Must be called after InputMethodSyncer is created. | |
| 150 void Initialize(); | |
| 151 | |
| 152 private: | |
| 153 // Adds the input methods from the syncable prefs to the device-local prefs. | |
| 154 // This should only be called once (after user's first sync) and only adds | |
| 155 // to, not removes from, the user's input method prefs. | |
| 156 void MergeSyncedPrefs(); | |
| 157 | |
| 158 // For the given input method pref, adds unique values from |synced_pref| to | |
| 159 // values in |pref|. The new values are converted from legacy engine IDs to | |
| 160 // input method IDs if necessary. | |
| 161 std::string AddSupportedInputMethodValues( | |
| 162 const std::string& pref, | |
| 163 const std::string& synced_pref, | |
| 164 const char* pref_name); | |
| 165 | |
| 166 // Sets prefs::kLanguagePreferredLanguages and sets |merging_| to false. | |
| 167 void FinishMerge(scoped_ptr<std::string> languages); | |
| 168 | |
| 169 // Callback method for preference changes. Updates the syncable prefs using | |
| 170 // the local pref values. | |
| 171 void OnPreferenceChanged(const std::string& pref_name); | |
| 172 | |
| 173 // PrefServiceSyncableObserver implementation. | |
| 174 virtual void OnIsSyncingChanged() override; | |
| 175 | |
| 176 StringPrefMember preferred_languages_; | |
| 177 StringPrefMember preload_engines_; | |
| 178 StringPrefMember enabled_extension_imes_; | |
| 179 // These are syncable variants which don't change the device settings. We can | |
| 180 // set these to keep track of the user's most recent choices. That way, after | |
| 181 // the initial sync, we can add the user's synced choices to the values that | |
| 182 // have already been chosen at OOBE. | |
| 183 StringPrefMember preferred_languages_syncable_; | |
| 184 StringPrefMember preload_engines_syncable_; | |
| 185 StringPrefMember enabled_extension_imes_syncable_; | |
| 186 | |
| 187 PrefServiceSyncable* prefs_; | |
| 188 scoped_refptr<input_method::InputMethodManager::State> ime_state_; | |
| 189 | |
| 190 // Used to ignore PrefChanged events while InputMethodManager is merging. | |
| 191 bool merging_; | |
| 192 | |
| 193 base::WeakPtrFactory<InputMethodSyncer> weak_factory_; | |
| 194 }; | |
| 195 | |
| 196 InputMethodSyncer::InputMethodSyncer( | |
| 197 PrefServiceSyncable* prefs, | |
| 198 scoped_refptr<input_method::InputMethodManager::State> ime_state) | |
| 199 : prefs_(prefs), | |
| 200 ime_state_(ime_state), | |
| 201 merging_(false), | |
| 202 weak_factory_(this) { | |
| 203 } | |
| 204 | |
| 205 // static | |
| 206 void InputMethodSyncer::RegisterProfilePrefs( | |
| 207 user_prefs::PrefRegistrySyncable* registry) { | |
| 208 registry->RegisterStringPref( | |
| 209 prefs::kLanguagePreferredLanguagesSyncable, | |
| 210 "", | |
| 211 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
| 212 registry->RegisterStringPref( | |
| 213 prefs::kLanguagePreloadEnginesSyncable, | |
| 214 "", | |
| 215 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
| 216 registry->RegisterStringPref( | |
| 217 prefs::kLanguageEnabledExtensionImesSyncable, | |
| 218 "", | |
| 219 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
| 220 registry->RegisterBooleanPref( | |
| 221 prefs::kLanguageShouldMergeInputMethods, | |
| 222 false, | |
| 223 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
| 224 } | |
| 225 | |
| 226 void InputMethodSyncer::Initialize() { | |
| 227 // This causes OnIsSyncingChanged to be called when the value of | |
| 228 // PrefService::IsSyncing() changes. | |
| 229 prefs_->AddObserver(this); | |
| 230 | |
| 231 preferred_languages_syncable_.Init(prefs::kLanguagePreferredLanguagesSyncable, | |
| 232 prefs_); | |
| 233 preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable, | |
| 234 prefs_); | |
| 235 enabled_extension_imes_syncable_.Init( | |
| 236 prefs::kLanguageEnabledExtensionImesSyncable, prefs_); | |
| 237 | |
| 238 BooleanPrefMember::NamedChangeCallback callback = | |
| 239 base::Bind(&InputMethodSyncer::OnPreferenceChanged, | |
| 240 base::Unretained(this)); | |
| 241 preferred_languages_.Init(prefs::kLanguagePreferredLanguages, | |
| 242 prefs_, callback); | |
|
dzhioev (left Google)
2014/11/06 16:11:06
nit: fix indentation.
michaelpg
2014/11/18 03:47:39
Done.
| |
| 243 preload_engines_.Init(prefs::kLanguagePreloadEngines, | |
| 244 prefs_, callback); | |
|
dzhioev (left Google)
2014/11/06 16:11:06
nit: fix indentation.
michaelpg
2014/11/18 03:47:39
Done.
| |
| 245 enabled_extension_imes_.Init( | |
| 246 prefs::kLanguageEnabledExtensionImes, prefs_, callback); | |
| 247 | |
| 248 // If we have already synced but haven't merged input methods yet, do so now. | |
| 249 if (prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods) && | |
| 250 !(preferred_languages_syncable_.GetValue().empty() && | |
| 251 preload_engines_syncable_.GetValue().empty() && | |
| 252 enabled_extension_imes_syncable_.GetValue().empty())) { | |
| 253 MergeSyncedPrefs(); | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 void InputMethodSyncer::MergeSyncedPrefs() { | |
| 258 // This should only be done after the first ever sync. | |
| 259 DCHECK(prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods)); | |
| 260 prefs_->SetBoolean(prefs::kLanguageShouldMergeInputMethods, false); | |
| 261 merging_ = true; | |
| 262 | |
| 263 std::string preferred_languages_syncable = | |
| 264 preferred_languages_syncable_.GetValue(); | |
| 265 std::string preload_engines_syncable = | |
| 266 preload_engines_syncable_.GetValue(); | |
| 267 std::string enabled_extension_imes_syncable = | |
| 268 enabled_extension_imes_syncable_.GetValue(); | |
| 269 | |
| 270 std::vector<std::string> synced_tokens; | |
| 271 std::vector<std::string> new_tokens; | |
| 272 | |
| 273 // First, set the syncable prefs to the union of the local and synced prefs. | |
| 274 base::SplitString( | |
| 275 preferred_languages_syncable_.GetValue(), ',', &synced_tokens); | |
| 276 base::SplitString(preferred_languages_.GetValue(), ',', &new_tokens); | |
| 277 | |
| 278 // Append the synced values to the current values. | |
| 279 MergeLists(&new_tokens, synced_tokens); | |
| 280 preferred_languages_syncable_.SetValue(JoinString(new_tokens, ',')); | |
| 281 | |
| 282 base::SplitString( | |
| 283 enabled_extension_imes_syncable_.GetValue(), ',', &synced_tokens); | |
| 284 base::SplitString(enabled_extension_imes_.GetValue(), ',', &new_tokens); | |
| 285 | |
| 286 MergeLists(&new_tokens, synced_tokens); | |
| 287 enabled_extension_imes_syncable_.SetValue(JoinString(new_tokens, ',')); | |
| 288 | |
| 289 // Revert preload engines to legacy component IDs. | |
| 290 base::SplitString(preload_engines_.GetValue(), ',', &new_tokens); | |
| 291 std::transform(new_tokens.begin(), new_tokens.end(), new_tokens.begin(), | |
| 292 extension_ime_util::GetComponentIDByInputMethodID); | |
| 293 base::SplitString( | |
| 294 preload_engines_syncable_.GetValue(), ',', &synced_tokens); | |
| 295 | |
| 296 MergeLists(&new_tokens, synced_tokens); | |
| 297 preload_engines_syncable_.SetValue(JoinString(new_tokens, ',')); | |
| 298 | |
| 299 // Second, set the local prefs, incorporating new values from the sync server. | |
| 300 preload_engines_.SetValue( | |
| 301 AddSupportedInputMethodValues(preload_engines_.GetValue(), | |
| 302 preload_engines_syncable, | |
| 303 prefs::kLanguagePreloadEngines)); | |
| 304 enabled_extension_imes_.SetValue( | |
| 305 AddSupportedInputMethodValues(enabled_extension_imes_.GetValue(), | |
| 306 enabled_extension_imes_syncable, | |
| 307 prefs::kLanguageEnabledExtensionImes)); | |
| 308 | |
| 309 // Remove unsupported locales before updating the local languages preference. | |
| 310 scoped_ptr<std::string> languages(new std::string( | |
| 311 AddSupportedInputMethodValues(preferred_languages_.GetValue(), | |
| 312 preferred_languages_syncable, | |
| 313 prefs::kLanguagePreferredLanguages))); | |
| 314 content::BrowserThread::PostTaskAndReply( | |
| 315 content::BrowserThread::FILE, | |
|
Alexander Alekseev
2014/10/28 15:11:00
AFAIK, FILE thread is deprecated.
BrowserThread::
michaelpg
2014/11/18 03:47:39
Done.
| |
| 316 FROM_HERE, | |
| 317 base::Bind(&CheckAndResolveLocales, languages.get()), | |
| 318 base::Bind(&InputMethodSyncer::FinishMerge, | |
| 319 weak_factory_.GetWeakPtr(), | |
| 320 base::Passed(&languages))); | |
| 321 } | |
| 322 | |
| 323 std::string InputMethodSyncer::AddSupportedInputMethodValues( | |
| 324 const std::string& pref, | |
| 325 const std::string& synced_pref, | |
| 326 const char* pref_name) { | |
| 327 std::vector<std::string> old_tokens; | |
| 328 std::vector<std::string> new_tokens; | |
| 329 base::SplitString(pref, ',', &old_tokens); | |
| 330 base::SplitString(synced_pref, ',', &new_tokens); | |
| 331 | |
| 332 // Check and convert the new tokens. | |
| 333 if (pref_name == prefs::kLanguagePreloadEngines || | |
| 334 pref_name == prefs::kLanguageEnabledExtensionImes) { | |
| 335 input_method::InputMethodManager* manager = | |
| 336 input_method::InputMethodManager::Get(); | |
| 337 scoped_ptr<input_method::InputMethodDescriptors> supported_descriptors; | |
| 338 | |
| 339 if (pref_name == prefs::kLanguagePreloadEngines) { | |
| 340 // Set the known input methods. | |
| 341 supported_descriptors = manager->GetSupportedInputMethods(); | |
| 342 // Add the available component extension IMEs. | |
| 343 ComponentExtensionIMEManager* component_extension_manager = | |
| 344 manager->GetComponentExtensionIMEManager(); | |
| 345 input_method::InputMethodDescriptors component_descriptors = | |
| 346 component_extension_manager->GetAllIMEAsInputMethodDescriptor(); | |
| 347 supported_descriptors->insert(supported_descriptors->end(), | |
| 348 component_descriptors.begin(), | |
| 349 component_descriptors.end()); | |
| 350 } else { | |
| 351 supported_descriptors.reset(new input_method::InputMethodDescriptors); | |
| 352 ime_state_->GetInputMethodExtensions(supported_descriptors.get()); | |
| 353 } | |
| 354 CheckAndResolveInputMethodIDs(&new_tokens, *supported_descriptors); | |
| 355 } else if (pref_name != prefs::kLanguagePreferredLanguages) { | |
| 356 NOTREACHED() << "Attempting to merge an invalid preference."; | |
| 357 // kLanguagePreferredLanguages is checked in CheckAndResolveLocales(). | |
| 358 } | |
| 359 | |
| 360 // Do the actual merging. | |
| 361 MergeLists(&old_tokens, new_tokens); | |
| 362 return JoinString(old_tokens, ','); | |
| 363 } | |
| 364 | |
| 365 void InputMethodSyncer::FinishMerge( | |
| 366 scoped_ptr<std::string> languages) { | |
| 367 // Since the merge only removed locales that are unsupported on this system, | |
| 368 // we don't need to update the syncable prefs. If the local preference changes | |
| 369 // later, the sync server will lose the values we dropped. That's okay since | |
| 370 // the values from this device should then become the new defaults anyway. | |
| 371 preferred_languages_.SetValue(*languages); | |
| 372 | |
| 373 // We've finished merging. | |
| 374 merging_ = false; | |
| 375 } | |
| 376 | |
| 377 void InputMethodSyncer::OnPreferenceChanged(const std::string& pref_name) { | |
| 378 DCHECK(pref_name == prefs::kLanguagePreferredLanguages || | |
| 379 pref_name == prefs::kLanguagePreloadEngines || | |
| 380 pref_name == prefs::kLanguageEnabledExtensionImes); | |
| 381 | |
| 382 if (merging_ || prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods)) | |
| 383 return; | |
| 384 | |
| 385 // Set the language and input prefs at the same time. Otherwise we may, | |
| 386 // e.g., use a stale languages setting but push a new preload engines setting. | |
| 387 preferred_languages_syncable_.SetValue(preferred_languages_.GetValue()); | |
| 388 enabled_extension_imes_syncable_.SetValue(enabled_extension_imes_.GetValue()); | |
| 389 | |
| 390 // For preload engines, use legacy xkb IDs so the preference can sync | |
| 391 // across Chrome OS and Chromium OS. | |
| 392 std::vector<std::string> engines; | |
| 393 base::SplitString(preload_engines_.GetValue(), ',', &engines); | |
| 394 std::transform(engines.begin(), engines.end(), engines.begin(), | |
| 395 extension_ime_util::GetComponentIDByInputMethodID); | |
| 396 preload_engines_syncable_.SetValue(JoinString(engines, ',')); | |
| 397 } | |
| 398 | |
| 399 void InputMethodSyncer::OnIsSyncingChanged() { | |
| 400 if (prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods) && | |
| 401 prefs_->IsSyncing()) { | |
| 402 MergeSyncedPrefs(); | |
| 403 } | |
| 404 } | |
| 405 | |
| 406 } // anonymous namespace | |
| 407 | |
| 51 Preferences::Preferences() | 408 Preferences::Preferences() |
| 52 : prefs_(NULL), | 409 : prefs_(NULL), |
| 53 input_method_manager_(input_method::InputMethodManager::Get()), | 410 input_method_manager_(input_method::InputMethodManager::Get()), |
| 54 user_(NULL), | 411 user_(NULL), |
| 55 user_is_primary_(false) { | 412 user_is_primary_(false) { |
| 56 // Do not observe shell, if there is no shell instance; e.g., in some unit | 413 // Do not observe shell, if there is no shell instance; e.g., in some unit |
| 57 // tests. | 414 // tests. |
| 58 if (ash::Shell::HasInstance()) | 415 if (ash::Shell::HasInstance()) |
| 59 ash::Shell::GetInstance()->AddShellObserver(this); | 416 ash::Shell::GetInstance()->AddShellObserver(this); |
| 60 } | 417 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod | 565 // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod |
| 209 // because they're just used to track the logout state of the device. | 566 // because they're just used to track the logout state of the device. |
| 210 registry->RegisterStringPref( | 567 registry->RegisterStringPref( |
| 211 prefs::kLanguageCurrentInputMethod, | 568 prefs::kLanguageCurrentInputMethod, |
| 212 "", | 569 "", |
| 213 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 570 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 214 registry->RegisterStringPref( | 571 registry->RegisterStringPref( |
| 215 prefs::kLanguagePreviousInputMethod, | 572 prefs::kLanguagePreviousInputMethod, |
| 216 "", | 573 "", |
| 217 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 574 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 218 // We don't sync the list of input methods and preferred languages since a | |
| 219 // user might use two or more devices with different hardware keyboards. | |
| 220 // crosbug.com/15181 | |
| 221 registry->RegisterStringPref( | 575 registry->RegisterStringPref( |
| 222 prefs::kLanguagePreferredLanguages, | 576 prefs::kLanguagePreferredLanguages, |
| 223 kFallbackInputMethodLocale, | 577 kFallbackInputMethodLocale, |
| 224 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 578 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 225 registry->RegisterStringPref( | 579 registry->RegisterStringPref( |
| 226 prefs::kLanguagePreloadEngines, | 580 prefs::kLanguagePreloadEngines, |
| 227 hardware_keyboard_id, | 581 hardware_keyboard_id, |
| 228 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 582 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 229 registry->RegisterStringPref( | 583 registry->RegisterStringPref( |
| 230 prefs::kLanguageEnabledExtensionImes, | 584 prefs::kLanguageEnabledExtensionImes, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 | 658 |
| 305 registry->RegisterBooleanPref( | 659 registry->RegisterBooleanPref( |
| 306 prefs::kTouchHudProjectionEnabled, | 660 prefs::kTouchHudProjectionEnabled, |
| 307 false, | 661 false, |
| 308 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 662 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 309 | 663 |
| 310 registry->RegisterBooleanPref( | 664 registry->RegisterBooleanPref( |
| 311 prefs::kTouchVirtualKeyboardEnabled, | 665 prefs::kTouchVirtualKeyboardEnabled, |
| 312 false, | 666 false, |
| 313 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 667 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 668 | |
| 669 InputMethodSyncer::RegisterProfilePrefs(registry); | |
| 314 } | 670 } |
| 315 | 671 |
| 316 void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { | 672 void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { |
| 317 prefs_ = prefs; | 673 prefs_ = prefs; |
| 318 | 674 |
| 319 BooleanPrefMember::NamedChangeCallback callback = | 675 BooleanPrefMember::NamedChangeCallback callback = |
| 320 base::Bind(&Preferences::OnPreferenceChanged, base::Unretained(this)); | 676 base::Bind(&Preferences::OnPreferenceChanged, base::Unretained(this)); |
| 321 | 677 |
| 322 performance_tracing_enabled_.Init(prefs::kPerformanceTracingEnabled, | 678 performance_tracing_enabled_.Init(prefs::kPerformanceTracingEnabled, |
| 323 prefs, callback); | 679 prefs, callback); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 347 xkb_auto_repeat_delay_pref_.Init( | 703 xkb_auto_repeat_delay_pref_.Init( |
| 348 prefs::kLanguageXkbAutoRepeatDelay, prefs, callback); | 704 prefs::kLanguageXkbAutoRepeatDelay, prefs, callback); |
| 349 xkb_auto_repeat_interval_pref_.Init( | 705 xkb_auto_repeat_interval_pref_.Init( |
| 350 prefs::kLanguageXkbAutoRepeatInterval, prefs, callback); | 706 prefs::kLanguageXkbAutoRepeatInterval, prefs, callback); |
| 351 } | 707 } |
| 352 | 708 |
| 353 void Preferences::Init(Profile* profile, const user_manager::User* user) { | 709 void Preferences::Init(Profile* profile, const user_manager::User* user) { |
| 354 DCHECK(profile); | 710 DCHECK(profile); |
| 355 DCHECK(user); | 711 DCHECK(user); |
| 356 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile); | 712 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile); |
| 713 // This causes OnIsSyncingChanged to be called when the value of | |
| 714 // PrefService::IsSyncing() changes. | |
| 715 prefs->AddObserver(this); | |
| 357 user_ = user; | 716 user_ = user; |
| 358 user_is_primary_ = | 717 user_is_primary_ = |
| 359 user_manager::UserManager::Get()->GetPrimaryUser() == user_; | 718 user_manager::UserManager::Get()->GetPrimaryUser() == user_; |
| 360 InitUserPrefs(prefs); | 719 InitUserPrefs(prefs); |
| 361 | 720 |
| 362 user_manager::UserManager::Get()->AddSessionStateObserver(this); | 721 user_manager::UserManager::Get()->AddSessionStateObserver(this); |
| 363 | 722 |
| 364 // This causes OnIsSyncingChanged to be called when the value of | |
| 365 // PrefService::IsSyncing() changes. | |
| 366 prefs->AddObserver(this); | |
| 367 | |
| 368 UserSessionManager* session_manager = UserSessionManager::GetInstance(); | 723 UserSessionManager* session_manager = UserSessionManager::GetInstance(); |
| 369 DCHECK(session_manager); | 724 DCHECK(session_manager); |
| 370 ime_state_ = session_manager->GetDefaultIMEState(profile); | 725 ime_state_ = session_manager->GetDefaultIMEState(profile); |
| 371 input_method_manager_->SetState(ime_state_); | 726 input_method_manager_->SetState(ime_state_); |
| 372 | 727 |
| 373 // Initialize preferences to currently saved state. | 728 // Initialize preferences to currently saved state. |
| 374 ApplyPreferences(REASON_INITIALIZATION, ""); | 729 ApplyPreferences(REASON_INITIALIZATION, ""); |
| 730 input_method_syncer_.reset( | |
| 731 new InputMethodSyncer(prefs, ime_state_)); | |
| 732 input_method_syncer_->Initialize(); | |
| 375 | 733 |
| 376 // If a guest is logged in, initialize the prefs as if this is the first | 734 // If a guest is logged in, initialize the prefs as if this is the first |
| 377 // login. For a regular user this is done in | 735 // login. For a regular user this is done in |
| 378 // UserSessionManager::InitProfilePreferences(). | 736 // UserSessionManager::InitProfilePreferences(). |
| 379 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) | 737 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) |
| 380 session_manager->SetFirstLoginPrefs(profile, std::string(), std::string()); | 738 session_manager->SetFirstLoginPrefs(profile, std::string(), std::string()); |
| 381 } | 739 } |
| 382 | 740 |
| 383 void Preferences::InitUserPrefsForTesting( | 741 void Preferences::InitUserPrefsForTesting( |
| 384 PrefServiceSyncable* prefs, | 742 PrefServiceSyncable* prefs, |
| 385 const user_manager::User* user, | 743 const user_manager::User* user, |
| 386 scoped_refptr<input_method::InputMethodManager::State> ime_state) { | 744 scoped_refptr<input_method::InputMethodManager::State> ime_state) { |
| 387 user_ = user; | 745 user_ = user; |
| 388 ime_state_ = ime_state; | 746 ime_state_ = ime_state; |
| 389 | 747 |
| 390 if (ime_state.get()) | 748 if (ime_state.get()) |
| 391 input_method_manager_->SetState(ime_state); | 749 input_method_manager_->SetState(ime_state); |
| 392 | 750 |
| 393 InitUserPrefs(prefs); | 751 InitUserPrefs(prefs); |
| 752 | |
| 753 input_method_syncer_.reset( | |
| 754 new InputMethodSyncer(prefs, ime_state_)); | |
| 755 input_method_syncer_->Initialize(); | |
| 394 } | 756 } |
| 395 | 757 |
| 396 void Preferences::SetInputMethodListForTesting() { | 758 void Preferences::SetInputMethodListForTesting() { |
| 397 SetInputMethodList(); | 759 SetInputMethodList(); |
| 398 } | 760 } |
| 399 | 761 |
| 400 void Preferences::OnPreferenceChanged(const std::string& pref_name) { | 762 void Preferences::OnPreferenceChanged(const std::string& pref_name) { |
| 401 ApplyPreferences(REASON_PREF_CHANGED, pref_name); | 763 ApplyPreferences(REASON_PREF_CHANGED, pref_name); |
| 402 } | 764 } |
| 403 | 765 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 else if (reason == REASON_INITIALIZATION) | 887 else if (reason == REASON_INITIALIZATION) |
| 526 UMA_HISTOGRAM_BOOLEAN( | 888 UMA_HISTOGRAM_BOOLEAN( |
| 527 "FileBrowser.DownloadDestination.IsGoogleDrive.Started", | 889 "FileBrowser.DownloadDestination.IsGoogleDrive.Started", |
| 528 default_download_to_drive); | 890 default_download_to_drive); |
| 529 } | 891 } |
| 530 if (reason != REASON_PREF_CHANGED || | 892 if (reason != REASON_PREF_CHANGED || |
| 531 pref_name == prefs::kTouchHudProjectionEnabled) { | 893 pref_name == prefs::kTouchHudProjectionEnabled) { |
| 532 #if !defined(USE_ATHENA) | 894 #if !defined(USE_ATHENA) |
| 533 if (user_is_active) { | 895 if (user_is_active) { |
| 534 const bool enabled = touch_hud_projection_enabled_.GetValue(); | 896 const bool enabled = touch_hud_projection_enabled_.GetValue(); |
| 535 ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); | 897 // There may not be a shell, e.g., in some unit tests. |
| 898 if (ash::Shell::HasInstance()) | |
| 899 ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); | |
| 536 } | 900 } |
| 537 #endif | 901 #endif |
| 538 } | 902 } |
| 539 | 903 |
| 540 if (reason != REASON_PREF_CHANGED || | 904 if (reason != REASON_PREF_CHANGED || |
| 541 pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { | 905 pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { |
| 542 if (user_is_active) { | 906 if (user_is_active) { |
| 543 const bool enabled = xkb_auto_repeat_enabled_.GetValue(); | 907 const bool enabled = xkb_auto_repeat_enabled_.GetValue(); |
| 544 input_method::InputMethodManager::Get() | 908 input_method::InputMethodManager::Get() |
| 545 ->GetImeKeyboard() | 909 ->GetImeKeyboard() |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 touch_hud_projection_enabled_.SetValue(enabled); | 1029 touch_hud_projection_enabled_.SetValue(enabled); |
| 666 } | 1030 } |
| 667 | 1031 |
| 668 void Preferences::ActiveUserChanged(const user_manager::User* active_user) { | 1032 void Preferences::ActiveUserChanged(const user_manager::User* active_user) { |
| 669 if (active_user != user_) | 1033 if (active_user != user_) |
| 670 return; | 1034 return; |
| 671 ApplyPreferences(REASON_ACTIVE_USER_CHANGED, ""); | 1035 ApplyPreferences(REASON_ACTIVE_USER_CHANGED, ""); |
| 672 } | 1036 } |
| 673 | 1037 |
| 674 } // namespace chromeos | 1038 } // namespace chromeos |
| OLD | NEW |