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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/preferences.h" 6 7 #include "ash/magnifier/magnifier_constants.h" 8 #include "ash/shell.h" 9 #include "base/chromeos/chromeos_version.h" 10 #include "base/command_line.h" 11 #include "base/i18n/time_formatting.h" 12 #include "base/metrics/histogram.h" 13 #include "base/prefs/pref_member.h" 14 #include "base/prefs/pref_registry_simple.h" 15 #include "base/strings/string_split.h" 16 #include "base/strings/string_util.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/chrome_notification_types.h" 20 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" 21 #include "chrome/browser/chromeos/drive/file_system_util.h" 22 #include "chrome/browser/chromeos/input_method/input_method_util.h" 23 #include "chrome/browser/chromeos/login/login_utils.h" 24 #include "chrome/browser/chromeos/login/user_manager.h" 25 #include "chrome/browser/chromeos/system/input_device_settings.h" 26 #include "chrome/browser/chromeos/system/statistics_provider.h" 27 #include "chrome/browser/download/download_util.h" 28 #include "chrome/browser/feedback/tracing_manager.h" 29 #include "chrome/browser/prefs/pref_service_syncable.h" 30 #include "chrome/browser/prefs/scoped_user_pref_update.h" 31 #include "chrome/common/chrome_switches.h" 32 #include "chrome/common/pref_names.h" 33 #include "chromeos/chromeos_switches.h" 34 #include "chromeos/ime/input_method_manager.h" 35 #include "chromeos/ime/xkeyboard.h" 36 #include "components/user_prefs/pref_registry_syncable.h" 37 #include "third_party/icu/source/i18n/unicode/timezone.h" 38 #include "ui/base/events/event_constants.h" 39 #include "ui/base/events/event_utils.h" 40 #include "url/gurl.h" 41 42 namespace chromeos { 43 44 static const char kFallbackInputMethodLocale[] = "en-US"; 45 46 // TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. 47 static const char kEnableTouchpadThreeFingerSwipe[] = 48 "settings.touchpad.enable_three_finger_swipe"; 49 50 Preferences::Preferences() 51 : prefs_(NULL), 52 input_method_manager_(input_method::InputMethodManager::Get()) { 53 // Do not observe shell, if there is no shell instance; e.g., in some unit 54 // tests. 55 if (ash::Shell::HasInstance()) 56 ash::Shell::GetInstance()->AddShellObserver(this); 57 } 58 59 Preferences::Preferences(input_method::InputMethodManager* input_method_manager) 60 : prefs_(NULL), 61 input_method_manager_(input_method_manager) { 62 // Do not observe shell, if there is no shell instance; e.g., in some unit 63 // tests. 64 if (ash::Shell::HasInstance()) 65 ash::Shell::GetInstance()->AddShellObserver(this); 66 } 67 68 Preferences::~Preferences() { 69 prefs_->RemoveObserver(this); 70 // If shell instance is destoryed before this preferences instance, there is 71 // no need to remove this shell observer. 72 if (ash::Shell::HasInstance()) 73 ash::Shell::GetInstance()->RemoveShellObserver(this); 74 } 75 76 // static 77 void Preferences::RegisterPrefs(PrefRegistrySimple* registry) { 78 registry->RegisterBooleanPref(prefs::kOwnerPrimaryMouseButtonRight, false); 79 registry->RegisterBooleanPref(prefs::kOwnerTapToClickEnabled, true); 80 registry->RegisterBooleanPref(prefs::kVirtualKeyboardEnabled, false); 81 } 82 83 // static 84 void Preferences::RegisterProfilePrefs( 85 user_prefs::PrefRegistrySyncable* registry) { 86 std::string hardware_keyboard_id; 87 // TODO(yusukes): Remove the runtime hack. 88 if (base::chromeos::IsRunningOnChromeOS()) { 89 input_method::InputMethodManager* manager = 90 input_method::InputMethodManager::Get(); 91 if (manager) { 92 hardware_keyboard_id = 93 manager->GetInputMethodUtil()->GetHardwareInputMethodId(); 94 } 95 } else { 96 hardware_keyboard_id = "xkb:us::eng"; // only for testing. 97 } 98 99 registry->RegisterBooleanPref( 100 prefs::kPerformanceTracingEnabled, 101 false, 102 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 103 104 registry->RegisterBooleanPref( 105 prefs::kTapToClickEnabled, 106 true, 107 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 108 registry->RegisterBooleanPref( 109 prefs::kTapDraggingEnabled, 110 false, 111 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 112 registry->RegisterBooleanPref( 113 prefs::kEnableTouchpadThreeFingerClick, 114 false, 115 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 116 registry->RegisterBooleanPref( 117 prefs::kNaturalScroll, 118 CommandLine::ForCurrentProcess()->HasSwitch( 119 switches::kNaturalScrollDefault), 120 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 121 registry->RegisterBooleanPref( 122 prefs::kPrimaryMouseButtonRight, 123 false, 124 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 125 registry->RegisterBooleanPref( 126 prefs::kLabsMediaplayerEnabled, 127 false, 128 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 129 registry->RegisterBooleanPref( 130 prefs::kLabsAdvancedFilesystemEnabled, 131 false, 132 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 133 registry->RegisterBooleanPref( 134 prefs::kStickyKeysEnabled, 135 false, 136 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 137 registry->RegisterBooleanPref( 138 prefs::kLargeCursorEnabled, 139 false, 140 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 141 registry->RegisterBooleanPref( 142 prefs::kSpokenFeedbackEnabled, 143 false, 144 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 145 registry->RegisterBooleanPref( 146 prefs::kHighContrastEnabled, 147 false, 148 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 149 registry->RegisterBooleanPref( 150 prefs::kScreenMagnifierEnabled, 151 false, 152 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 153 registry->RegisterIntegerPref( 154 prefs::kScreenMagnifierType, 155 ash::kDefaultMagnifierType, 156 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 157 registry->RegisterDoublePref( 158 prefs::kScreenMagnifierScale, 159 std::numeric_limits<double>::min(), 160 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 161 registry->RegisterBooleanPref( 162 prefs::kShouldAlwaysShowAccessibilityMenu, 163 false, 164 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 165 registry->RegisterIntegerPref( 166 prefs::kMouseSensitivity, 167 3, 168 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 169 registry->RegisterIntegerPref( 170 prefs::kTouchpadSensitivity, 171 3, 172 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 173 registry->RegisterBooleanPref( 174 prefs::kUse24HourClock, 175 base::GetHourClockType() == base::k24HourClock, 176 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 177 registry->RegisterBooleanPref( 178 prefs::kDisableDrive, 179 false, 180 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 181 registry->RegisterBooleanPref( 182 prefs::kDisableDriveOverCellular, 183 true, 184 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 185 registry->RegisterBooleanPref( 186 prefs::kDisableDriveHostedFiles, 187 false, 188 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 189 // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod 190 // because they're just used to track the logout state of the device. 191 registry->RegisterStringPref( 192 prefs::kLanguageCurrentInputMethod, 193 "", 194 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 195 registry->RegisterStringPref( 196 prefs::kLanguagePreviousInputMethod, 197 "", 198 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 199 // We don't sync the list of input methods and preferred languages since a 200 // user might use two or more devices with different hardware keyboards. 201 // crosbug.com/15181 202 registry->RegisterStringPref( 203 prefs::kLanguagePreferredLanguages, 204 kFallbackInputMethodLocale, 205 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 206 registry->RegisterStringPref( 207 prefs::kLanguagePreloadEngines, 208 hardware_keyboard_id, 209 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 210 registry->RegisterStringPref( 211 prefs::kLanguageEnabledExtensionImes, 212 "", 213 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 214 for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) { 215 registry->RegisterBooleanPref( 216 language_prefs::kChewingBooleanPrefs[i].pref_name, 217 language_prefs::kChewingBooleanPrefs[i].default_pref_value, 218 language_prefs::kChewingBooleanPrefs[i].sync_status); 219 } 220 for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) { 221 registry->RegisterStringPref( 222 language_prefs::kChewingMultipleChoicePrefs[i].pref_name, 223 language_prefs::kChewingMultipleChoicePrefs[i].default_pref_value, 224 language_prefs::kChewingMultipleChoicePrefs[i].sync_status); 225 } 226 registry->RegisterIntegerPref( 227 language_prefs::kChewingHsuSelKeyType.pref_name, 228 language_prefs::kChewingHsuSelKeyType.default_pref_value, 229 language_prefs::kChewingHsuSelKeyType.sync_status); 230 231 for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) { 232 registry->RegisterIntegerPref( 233 language_prefs::kChewingIntegerPrefs[i].pref_name, 234 language_prefs::kChewingIntegerPrefs[i].default_pref_value, 235 language_prefs::kChewingIntegerPrefs[i].sync_status); 236 } 237 registry->RegisterStringPref( 238 prefs::kLanguageHangulKeyboard, 239 language_prefs::kHangulKeyboardNameIDPairs[0].keyboard_id, 240 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 241 registry->RegisterStringPref( 242 prefs::kLanguageHangulHanjaBindingKeys, 243 language_prefs::kHangulHanjaBindingKeys, 244 // Don't sync the pref as it's not user-configurable 245 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 246 for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) { 247 registry->RegisterBooleanPref( 248 language_prefs::kPinyinBooleanPrefs[i].pref_name, 249 language_prefs::kPinyinBooleanPrefs[i].default_pref_value, 250 language_prefs::kPinyinBooleanPrefs[i].sync_status); 251 } 252 for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) { 253 registry->RegisterIntegerPref( 254 language_prefs::kPinyinIntegerPrefs[i].pref_name, 255 language_prefs::kPinyinIntegerPrefs[i].default_pref_value, 256 language_prefs::kPinyinIntegerPrefs[i].sync_status); 257 } 258 registry->RegisterIntegerPref( 259 language_prefs::kPinyinDoublePinyinSchema.pref_name, 260 language_prefs::kPinyinDoublePinyinSchema.default_pref_value, 261 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 262 263 for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) { 264 registry->RegisterBooleanPref( 265 language_prefs::kMozcBooleanPrefs[i].pref_name, 266 language_prefs::kMozcBooleanPrefs[i].default_pref_value, 267 language_prefs::kMozcBooleanPrefs[i].sync_status); 268 } 269 for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) { 270 registry->RegisterStringPref( 271 language_prefs::kMozcMultipleChoicePrefs[i].pref_name, 272 language_prefs::kMozcMultipleChoicePrefs[i].default_pref_value, 273 language_prefs::kMozcMultipleChoicePrefs[i].sync_status); 274 } 275 for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) { 276 registry->RegisterIntegerPref( 277 language_prefs::kMozcIntegerPrefs[i].pref_name, 278 language_prefs::kMozcIntegerPrefs[i].default_pref_value, 279 language_prefs::kMozcIntegerPrefs[i].sync_status); 280 } 281 registry->RegisterIntegerPref( 282 prefs::kLanguageRemapSearchKeyTo, 283 input_method::kSearchKey, 284 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 285 registry->RegisterIntegerPref( 286 prefs::kLanguageRemapControlKeyTo, 287 input_method::kControlKey, 288 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 289 registry->RegisterIntegerPref( 290 prefs::kLanguageRemapAltKeyTo, 291 input_method::kAltKey, 292 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 293 // We don't sync the CapsLock remapping pref, since the UI hides this pref 294 // on certain devices, so syncing a non-default value to a device that 295 // doesn't allow changing the pref would be odd. http://crbug.com/167237 296 registry->RegisterIntegerPref( 297 prefs::kLanguageRemapCapsLockKeyTo, 298 input_method::kCapsLockKey, 299 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 300 registry->RegisterIntegerPref( 301 prefs::kLanguageRemapDiamondKeyTo, 302 input_method::kControlKey, 303 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 304 // We don't sync the following keyboard prefs since they are not user- 305 // configurable. 306 registry->RegisterBooleanPref( 307 prefs::kLanguageXkbAutoRepeatEnabled, 308 true, 309 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 310 registry->RegisterIntegerPref( 311 prefs::kLanguageXkbAutoRepeatDelay, 312 language_prefs::kXkbAutoRepeatDelayInMs, 313 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 314 registry->RegisterIntegerPref( 315 prefs::kLanguageXkbAutoRepeatInterval, 316 language_prefs::kXkbAutoRepeatIntervalInMs, 317 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 318 319 // Mobile plan notifications default to on. 320 registry->RegisterBooleanPref( 321 prefs::kShowPlanNotifications, 322 true, 323 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 324 325 // 3G first-time usage promo will be shown at least once. 326 registry->RegisterBooleanPref( 327 prefs::kShow3gPromoNotification, 328 true, 329 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 330 331 // Initially all existing users would see "What's new" for current version 332 // after update. 333 registry->RegisterStringPref(prefs::kChromeOSReleaseNotesVersion, 334 "0.0.0.0", 335 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 336 337 registry->RegisterBooleanPref( 338 prefs::kExternalStorageDisabled, 339 false, 340 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 341 342 registry->RegisterStringPref( 343 prefs::kTermsOfServiceURL, 344 "", 345 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 346 347 // TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. 348 registry->RegisterBooleanPref( 349 kEnableTouchpadThreeFingerSwipe, 350 false, 351 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 352 353 registry->RegisterBooleanPref( 354 prefs::kTouchHudProjectionEnabled, 355 false, 356 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 357 } 358 359 void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { 360 prefs_ = prefs; 361 362 BooleanPrefMember::NamedChangeCallback callback = 363 base::Bind(&Preferences::OnPreferenceChanged, base::Unretained(this)); 364 365 performance_tracing_enabled_.Init(prefs::kPerformanceTracingEnabled, 366 prefs, callback); 367 tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, prefs, callback); 368 tap_dragging_enabled_.Init(prefs::kTapDraggingEnabled, prefs, callback); 369 three_finger_click_enabled_.Init(prefs::kEnableTouchpadThreeFingerClick, 370 prefs, callback); 371 natural_scroll_.Init(prefs::kNaturalScroll, prefs, callback); 372 a11y_spoken_feedback_enabled_.Init(prefs::kSpokenFeedbackEnabled, 373 prefs, callback); 374 a11y_high_contrast_enabled_.Init(prefs::kHighContrastEnabled, 375 prefs, callback); 376 a11y_screen_magnifier_enabled_.Init(prefs::kScreenMagnifierEnabled, 377 prefs, callback); 378 a11y_screen_magnifier_type_.Init(prefs::kScreenMagnifierType, 379 prefs, callback); 380 a11y_screen_magnifier_scale_.Init(prefs::kScreenMagnifierScale, 381 prefs, callback); 382 mouse_sensitivity_.Init(prefs::kMouseSensitivity, prefs, callback); 383 touchpad_sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, callback); 384 use_24hour_clock_.Init(prefs::kUse24HourClock, prefs, callback); 385 disable_drive_.Init(prefs::kDisableDrive, prefs, callback); 386 disable_drive_over_cellular_.Init(prefs::kDisableDriveOverCellular, 387 prefs, callback); 388 disable_drive_hosted_files_.Init(prefs::kDisableDriveHostedFiles, 389 prefs, callback); 390 download_default_directory_.Init(prefs::kDownloadDefaultDirectory, 391 prefs, callback); 392 select_file_last_directory_.Init(prefs::kSelectFileLastDirectory, 393 prefs, callback); 394 save_file_default_directory_.Init(prefs::kSaveFileDefaultDirectory, 395 prefs, callback); 396 touch_hud_projection_enabled_.Init(prefs::kTouchHudProjectionEnabled, 397 prefs, callback); 398 primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, 399 prefs, callback); 400 preferred_languages_.Init(prefs::kLanguagePreferredLanguages, 401 prefs, callback); 402 preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, callback); 403 enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes, 404 prefs, callback); 405 current_input_method_.Init(prefs::kLanguageCurrentInputMethod, 406 prefs, callback); 407 previous_input_method_.Init(prefs::kLanguagePreviousInputMethod, 408 prefs, callback); 409 410 for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) { 411 chewing_boolean_prefs_[i].Init( 412 language_prefs::kChewingBooleanPrefs[i].pref_name, prefs, callback); 413 } 414 for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) { 415 chewing_multiple_choice_prefs_[i].Init( 416 language_prefs::kChewingMultipleChoicePrefs[i].pref_name, 417 prefs, callback); 418 } 419 chewing_hsu_sel_key_type_.Init( 420 language_prefs::kChewingHsuSelKeyType.pref_name, prefs, callback); 421 for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) { 422 chewing_integer_prefs_[i].Init( 423 language_prefs::kChewingIntegerPrefs[i].pref_name, prefs, callback); 424 } 425 hangul_keyboard_.Init(prefs::kLanguageHangulKeyboard, prefs, callback); 426 hangul_hanja_binding_keys_.Init( 427 prefs::kLanguageHangulHanjaBindingKeys, prefs, callback); 428 for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) { 429 pinyin_boolean_prefs_[i].Init( 430 language_prefs::kPinyinBooleanPrefs[i].pref_name, prefs, callback); 431 } 432 for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) { 433 pinyin_int_prefs_[i].Init( 434 language_prefs::kPinyinIntegerPrefs[i].pref_name, prefs, callback); 435 } 436 pinyin_double_pinyin_schema_.Init( 437 language_prefs::kPinyinDoublePinyinSchema.pref_name, prefs, callback); 438 for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) { 439 mozc_boolean_prefs_[i].Init( 440 language_prefs::kMozcBooleanPrefs[i].pref_name, prefs, callback); 441 } 442 for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) { 443 mozc_multiple_choice_prefs_[i].Init( 444 language_prefs::kMozcMultipleChoicePrefs[i].pref_name, prefs, callback); 445 } 446 for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) { 447 mozc_integer_prefs_[i].Init( 448 language_prefs::kMozcIntegerPrefs[i].pref_name, prefs, callback); 449 } 450 xkb_auto_repeat_enabled_.Init( 451 prefs::kLanguageXkbAutoRepeatEnabled, prefs, callback); 452 xkb_auto_repeat_delay_pref_.Init( 453 prefs::kLanguageXkbAutoRepeatDelay, prefs, callback); 454 xkb_auto_repeat_interval_pref_.Init( 455 prefs::kLanguageXkbAutoRepeatInterval, prefs, callback); 456 457 // TODO(achuith): Remove deprecated pref in M31. crbug.com/223480. 458 prefs->ClearPref(kEnableTouchpadThreeFingerSwipe); 459 } 460 461 void Preferences::Init(PrefServiceSyncable* prefs) { 462 InitUserPrefs(prefs); 463 464 // This causes OnIsSyncingChanged to be called when the value of 465 // PrefService::IsSyncing() changes. 466 prefs->AddObserver(this); 467 468 // Initialize preferences to currently saved state. 469 NotifyPrefChanged(NULL); 470 471 // If a guest is logged in, initialize the prefs as if this is the first 472 // login. 473 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) { 474 LoginUtils::Get()->SetFirstLoginPrefs(prefs); 475 } 476 } 477 478 void Preferences::InitUserPrefsForTesting(PrefServiceSyncable* prefs) { 479 InitUserPrefs(prefs); 480 } 481 482 void Preferences::SetInputMethodListForTesting() { 483 SetInputMethodList(); 484 } 485 486 void Preferences::OnPreferenceChanged(const std::string& pref_name) { 487 NotifyPrefChanged(&pref_name); 488 } 489 490 void Preferences::NotifyPrefChanged(const std::string* pref_name) { 491 if (!pref_name || *pref_name == prefs::kPerformanceTracingEnabled) { 492 const bool enabled = performance_tracing_enabled_.GetValue(); 493 if (enabled) 494 tracing_manager_ = TracingManager::Create(); 495 else 496 tracing_manager_.reset(); 497 } 498 if (!pref_name || *pref_name == prefs::kTapToClickEnabled) { 499 const bool enabled = tap_to_click_enabled_.GetValue(); 500 system::touchpad_settings::SetTapToClick(enabled); 501 if (pref_name) 502 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Changed", enabled); 503 else 504 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Started", enabled); 505 506 // Save owner preference in local state to use on login screen. 507 if (chromeos::UserManager::Get()->IsCurrentUserOwner()) { 508 PrefService* prefs = g_browser_process->local_state(); 509 if (prefs->GetBoolean(prefs::kOwnerTapToClickEnabled) != enabled) 510 prefs->SetBoolean(prefs::kOwnerTapToClickEnabled, enabled); 511 } 512 } 513 if (!pref_name || *pref_name == prefs::kTapDraggingEnabled) { 514 const bool enabled = tap_dragging_enabled_.GetValue(); 515 system::touchpad_settings::SetTapDragging(enabled); 516 if (pref_name) 517 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Changed", enabled); 518 else 519 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Started", enabled); 520 } 521 if (!pref_name || *pref_name == prefs::kEnableTouchpadThreeFingerClick) { 522 const bool enabled = three_finger_click_enabled_.GetValue(); 523 system::touchpad_settings::SetThreeFingerClick(enabled); 524 if (pref_name) 525 UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Changed", enabled); 526 else 527 UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Started", enabled); 528 } 529 if (!pref_name || *pref_name == prefs::kNaturalScroll) { 530 // Force natural scroll default if we've sync'd and if the cmd line arg is 531 // set. 532 ForceNaturalScrollDefault(); 533 534 const bool enabled = natural_scroll_.GetValue(); 535 DVLOG(1) << "Natural scroll set to " << enabled; 536 ui::SetNaturalScroll(enabled); 537 if (pref_name) 538 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Changed", enabled); 539 else 540 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Started", enabled); 541 } 542 if (!pref_name || *pref_name == prefs::kMouseSensitivity) { 543 const int sensitivity = mouse_sensitivity_.GetValue(); 544 system::mouse_settings::SetSensitivity(sensitivity); 545 if (pref_name) { 546 UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Changed", 547 sensitivity, 548 system::kMaxPointerSensitivity + 1); 549 } else { 550 UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Started", 551 sensitivity, 552 system::kMaxPointerSensitivity + 1); 553 } 554 } 555 if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) { 556 const int sensitivity = touchpad_sensitivity_.GetValue(); 557 system::touchpad_settings::SetSensitivity(sensitivity); 558 if (pref_name) { 559 UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Changed", 560 sensitivity, 561 system::kMaxPointerSensitivity + 1); 562 } else { 563 UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Started", 564 sensitivity, 565 system::kMaxPointerSensitivity + 1); 566 } 567 } 568 if (!pref_name || *pref_name == prefs::kPrimaryMouseButtonRight) { 569 const bool right = primary_mouse_button_right_.GetValue(); 570 system::mouse_settings::SetPrimaryButtonRight(right); 571 if (pref_name) 572 UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Changed", right); 573 else 574 UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Started", right); 575 576 // Save owner preference in local state to use on login screen. 577 if (chromeos::UserManager::Get()->IsCurrentUserOwner()) { 578 PrefService* prefs = g_browser_process->local_state(); 579 if (prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight) != right) 580 prefs->SetBoolean(prefs::kOwnerPrimaryMouseButtonRight, right); 581 } 582 } 583 if (!pref_name || *pref_name == prefs::kDownloadDefaultDirectory) { 584 const base::FilePath pref_path = download_default_directory_.GetValue(); 585 // TODO(haruki): Remove this when migration completes. crbug.com/229304. 586 if (drive::util::NeedsNamespaceMigration(pref_path)) { 587 prefs_->SetFilePath(prefs::kDownloadDefaultDirectory, 588 drive::util::ConvertToMyDriveNamespace(pref_path)); 589 } 590 591 const bool default_download_to_drive = drive::util::IsUnderDriveMountPoint( 592 download_default_directory_.GetValue()); 593 if (pref_name) 594 UMA_HISTOGRAM_BOOLEAN( 595 "FileBrowser.DownloadDestination.IsGoogleDrive.Changed", 596 default_download_to_drive); 597 else 598 UMA_HISTOGRAM_BOOLEAN( 599 "FileBrowser.DownloadDestination.IsGoogleDrive.Started", 600 default_download_to_drive); 601 } 602 if (!pref_name || *pref_name == prefs::kSelectFileLastDirectory) { 603 const base::FilePath pref_path = select_file_last_directory_.GetValue(); 604 // This pref can contain a Drive path, which needs to be updated due to 605 // namespaces introduced by crbug.com/174233. 606 // TODO(haruki): Remove this when migration completes. crbug.com/229304. 607 if (drive::util::NeedsNamespaceMigration(pref_path)) { 608 prefs_->SetFilePath(prefs::kSelectFileLastDirectory, 609 drive::util::ConvertToMyDriveNamespace(pref_path)); 610 } 611 } 612 if (!pref_name || *pref_name == prefs::kSaveFileDefaultDirectory) { 613 const base::FilePath pref_path = save_file_default_directory_.GetValue(); 614 // This pref can contain a Drive path, which needs to be updated due to 615 // namespaces introduced by crbug.com/174233. 616 // TODO(haruki): Remove this when migration completes. crbug.com/229304. 617 if (drive::util::NeedsNamespaceMigration(pref_path)) { 618 prefs_->SetFilePath(prefs::kSaveFileDefaultDirectory, 619 drive::util::ConvertToMyDriveNamespace(pref_path)); 620 } 621 } 622 if (!pref_name || *pref_name == prefs::kTouchHudProjectionEnabled) { 623 const bool enabled = touch_hud_projection_enabled_.GetValue(); 624 ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); 625 } 626 627 if (!pref_name || *pref_name == prefs::kLanguagePreferredLanguages) { 628 // Unlike kLanguagePreloadEngines and some other input method 629 // preferencs, we don't need to send this to ibus-daemon. 630 } 631 632 if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { 633 const bool enabled = xkb_auto_repeat_enabled_.GetValue(); 634 input_method::XKeyboard::SetAutoRepeatEnabled(enabled); 635 } 636 if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) || 637 (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) { 638 UpdateAutoRepeatRate(); 639 } 640 641 if (!pref_name) { 642 SetInputMethodList(); 643 } else if (*pref_name == prefs::kLanguagePreloadEngines) { 644 SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, 645 language_prefs::kPreloadEnginesConfigName, 646 preload_engines_.GetValue()); 647 } 648 649 if (!pref_name || *pref_name == prefs::kLanguageEnabledExtensionImes) { 650 std::string value(enabled_extension_imes_.GetValue()); 651 652 std::vector<std::string> split_values; 653 if (!value.empty()) 654 base::SplitString(value, ',', &split_values); 655 656 input_method_manager_->SetEnabledExtensionImes(&split_values); 657 } 658 659 // Do not check |*pref_name| of the prefs for remembering current/previous 660 // input methods here. We're only interested in initial values of the prefs. 661 662 // TODO(nona): remove all IME preference entries. crbug.com/256102 663 for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) { 664 if (!pref_name || 665 *pref_name == language_prefs::kChewingBooleanPrefs[i].pref_name) { 666 SetLanguageConfigBoolean( 667 language_prefs::kChewingSectionName, 668 language_prefs::kChewingBooleanPrefs[i].ibus_config_name, 669 chewing_boolean_prefs_[i].GetValue()); 670 } 671 } 672 for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) { 673 if (!pref_name || 674 *pref_name == 675 language_prefs::kChewingMultipleChoicePrefs[i].pref_name) { 676 SetLanguageConfigString( 677 language_prefs::kChewingSectionName, 678 language_prefs::kChewingMultipleChoicePrefs[i].ibus_config_name, 679 chewing_multiple_choice_prefs_[i].GetValue()); 680 } 681 } 682 if (!pref_name || 683 *pref_name == language_prefs::kChewingHsuSelKeyType.pref_name) { 684 SetLanguageConfigInteger( 685 language_prefs::kChewingSectionName, 686 language_prefs::kChewingHsuSelKeyType.ibus_config_name, 687 chewing_hsu_sel_key_type_.GetValue()); 688 } 689 for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) { 690 if (!pref_name || 691 *pref_name == language_prefs::kChewingIntegerPrefs[i].pref_name) { 692 SetLanguageConfigInteger( 693 language_prefs::kChewingSectionName, 694 language_prefs::kChewingIntegerPrefs[i].ibus_config_name, 695 chewing_integer_prefs_[i].GetValue()); 696 } 697 } 698 if (!pref_name || 699 *pref_name == prefs::kLanguageHangulKeyboard) { 700 std::vector<std::string> new_input_method_ids; 701 if (input_method_manager_->MigrateKoreanKeyboard( 702 hangul_keyboard_.GetValue(), 703 &new_input_method_ids)) { 704 preload_engines_.SetValue(JoinString(new_input_method_ids, ',')); 705 hangul_keyboard_.SetValue("dummy_value_already_migrated"); 706 } 707 } 708 if (!pref_name || *pref_name == prefs::kLanguageHangulHanjaBindingKeys) { 709 SetLanguageConfigString(language_prefs::kHangulSectionName, 710 language_prefs::kHangulHanjaBindingKeysConfigName, 711 hangul_hanja_binding_keys_.GetValue()); 712 } 713 for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) { 714 if (!pref_name || 715 *pref_name == language_prefs::kPinyinBooleanPrefs[i].pref_name) { 716 SetLanguageConfigBoolean( 717 language_prefs::kPinyinSectionName, 718 language_prefs::kPinyinBooleanPrefs[i].ibus_config_name, 719 pinyin_boolean_prefs_[i].GetValue()); 720 } 721 } 722 for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) { 723 if (!pref_name || 724 *pref_name == language_prefs::kPinyinIntegerPrefs[i].pref_name) { 725 SetLanguageConfigInteger( 726 language_prefs::kPinyinSectionName, 727 language_prefs::kPinyinIntegerPrefs[i].ibus_config_name, 728 pinyin_int_prefs_[i].GetValue()); 729 } 730 } 731 if (!pref_name || 732 *pref_name == language_prefs::kPinyinDoublePinyinSchema.pref_name) { 733 SetLanguageConfigInteger( 734 language_prefs::kPinyinSectionName, 735 language_prefs::kPinyinDoublePinyinSchema.ibus_config_name, 736 pinyin_double_pinyin_schema_.GetValue()); 737 } 738 for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) { 739 if (!pref_name || 740 *pref_name == language_prefs::kMozcBooleanPrefs[i].pref_name) { 741 SetLanguageConfigBoolean( 742 language_prefs::kMozcSectionName, 743 language_prefs::kMozcBooleanPrefs[i].ibus_config_name, 744 mozc_boolean_prefs_[i].GetValue()); 745 } 746 } 747 for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) { 748 if (!pref_name || 749 *pref_name == language_prefs::kMozcMultipleChoicePrefs[i].pref_name) { 750 SetLanguageConfigString( 751 language_prefs::kMozcSectionName, 752 language_prefs::kMozcMultipleChoicePrefs[i].ibus_config_name, 753 mozc_multiple_choice_prefs_[i].GetValue()); 754 } 755 } 756 for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) { 757 if (!pref_name || 758 *pref_name == language_prefs::kMozcIntegerPrefs[i].pref_name) { 759 SetLanguageConfigInteger( 760 language_prefs::kMozcSectionName, 761 language_prefs::kMozcIntegerPrefs[i].ibus_config_name, 762 mozc_integer_prefs_[i].GetValue()); 763 } 764 } 765 766 // Change the download directory to the default value if a Drive directory is 767 // selected and Drive is disabled. 768 if (!pref_name || *pref_name == prefs::kDisableDrive) { 769 if (disable_drive_.GetValue()) { 770 if (drive::util::IsUnderDriveMountPoint( 771 download_default_directory_.GetValue())) { 772 prefs_->SetFilePath(prefs::kDownloadDefaultDirectory, 773 download_util::GetDefaultDownloadDirectory()); 774 } 775 } 776 } 777 } 778 779 void Preferences::OnIsSyncingChanged() { 780 DVLOG(1) << "OnIsSyncingChanged"; 781 ForceNaturalScrollDefault(); 782 } 783 784 void Preferences::ForceNaturalScrollDefault() { 785 DVLOG(1) << "ForceNaturalScrollDefault"; 786 if (CommandLine::ForCurrentProcess()->HasSwitch( 787 switches::kNaturalScrollDefault) && 788 prefs_->IsSyncing() && 789 !prefs_->GetUserPrefValue(prefs::kNaturalScroll)) { 790 DVLOG(1) << "Natural scroll forced to true"; 791 natural_scroll_.SetValue(true); 792 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Forced", true); 793 } 794 } 795 796 void Preferences::SetLanguageConfigBoolean(const char* section, 797 const char* name, 798 bool value) { 799 input_method::InputMethodConfigValue config; 800 config.type = input_method::InputMethodConfigValue::kValueTypeBool; 801 config.bool_value = value; 802 input_method_manager_->SetInputMethodConfig(section, name, config); 803 } 804 805 void Preferences::SetLanguageConfigInteger(const char* section, 806 const char* name, 807 int value) { 808 input_method::InputMethodConfigValue config; 809 config.type = input_method::InputMethodConfigValue::kValueTypeInt; 810 config.int_value = value; 811 input_method_manager_->SetInputMethodConfig(section, name, config); 812 } 813 814 void Preferences::SetLanguageConfigString(const char* section, 815 const char* name, 816 const std::string& value) { 817 input_method::InputMethodConfigValue config; 818 config.type = input_method::InputMethodConfigValue::kValueTypeString; 819 config.string_value = value; 820 input_method_manager_->SetInputMethodConfig(section, name, config); 821 } 822 823 void Preferences::SetLanguageConfigStringList( 824 const char* section, 825 const char* name, 826 const std::vector<std::string>& values) { 827 input_method::InputMethodConfigValue config; 828 config.type = input_method::InputMethodConfigValue::kValueTypeStringList; 829 for (size_t i = 0; i < values.size(); ++i) 830 config.string_list_value.push_back(values[i]); 831 832 input_method_manager_->SetInputMethodConfig(section, name, config); 833 } 834 835 void Preferences::SetLanguageConfigStringListAsCSV(const char* section, 836 const char* name, 837 const std::string& value) { 838 VLOG(1) << "Setting " << name << " to '" << value << "'"; 839 840 std::vector<std::string> split_values; 841 if (!value.empty()) 842 base::SplitString(value, ',', &split_values); 843 844 if (section == std::string(language_prefs::kGeneralSectionName) && 845 name == std::string(language_prefs::kPreloadEnginesConfigName)) { 846 // TODO(nona): Remove this function after few milestones are passed. 847 // (http://crbug.com/236747) 848 if (input_method_manager_->MigrateOldInputMethods(&split_values)) 849 preload_engines_.SetValue(JoinString(split_values, ',')); 850 input_method_manager_->EnableInputMethods(split_values); 851 return; 852 } 853 854 // We should call the cros API even when |value| is empty, to disable default 855 // config. 856 SetLanguageConfigStringList(section, name, split_values); 857 } 858 859 void Preferences::SetInputMethodList() { 860 // When |preload_engines_| are set, InputMethodManager::ChangeInputMethod() 861 // might be called to change the current input method to the first one in the 862 // |preload_engines_| list. This also updates previous/current input method 863 // prefs. That's why GetValue() calls are placed before the 864 // SetLanguageConfigStringListAsCSV() call below. 865 const std::string previous_input_method_id = 866 previous_input_method_.GetValue(); 867 const std::string current_input_method_id = current_input_method_.GetValue(); 868 SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, 869 language_prefs::kPreloadEnginesConfigName, 870 preload_engines_.GetValue()); 871 872 // ChangeInputMethod() has to be called AFTER the value of |preload_engines_| 873 // is sent to the InputMethodManager. Otherwise, the ChangeInputMethod request 874 // might be ignored as an invalid input method ID. The ChangeInputMethod() 875 // calls are also necessary to restore the previous/current input method prefs 876 // which could have been modified by the SetLanguageConfigStringListAsCSV call 877 // above to the original state. 878 if (!previous_input_method_id.empty()) 879 input_method_manager_->ChangeInputMethod(previous_input_method_id); 880 if (!current_input_method_id.empty()) 881 input_method_manager_->ChangeInputMethod(current_input_method_id); 882 } 883 884 void Preferences::UpdateAutoRepeatRate() { 885 // Avoid setting repeat rate on desktop dev environment. 886 if (!base::chromeos::IsRunningOnChromeOS()) 887 return; 888 889 input_method::AutoRepeatRate rate; 890 rate.initial_delay_in_ms = xkb_auto_repeat_delay_pref_.GetValue(); 891 rate.repeat_interval_in_ms = xkb_auto_repeat_interval_pref_.GetValue(); 892 DCHECK(rate.initial_delay_in_ms > 0); 893 DCHECK(rate.repeat_interval_in_ms > 0); 894 input_method::XKeyboard::SetAutoRepeatRate(rate); 895 } 896 897 void Preferences::OnTouchHudProjectionToggled(bool enabled) { 898 if (touch_hud_projection_enabled_.GetValue() == enabled) 899 return; 900 901 touch_hud_projection_enabled_.SetValue(enabled); 902 } 903 904 } // namespace chromeos 905