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 <vector> 8 9 #include "ash/autoclick/autoclick_controller.h" 10 #include "ash/magnifier/magnifier_constants.h" 11 #include "ash/shell.h" 12 #include "base/command_line.h" 13 #include "base/i18n/time_formatting.h" 14 #include "base/metrics/histogram.h" 15 #include "base/prefs/pref_member.h" 16 #include "base/prefs/pref_registry_simple.h" 17 #include "base/prefs/scoped_user_pref_update.h" 18 #include "base/strings/string_split.h" 19 #include "base/strings/string_util.h" 20 #include "base/strings/utf_string_conversions.h" 21 #include "base/sys_info.h" 22 #include "chrome/browser/browser_process.h" 23 #include "chrome/browser/chrome_notification_types.h" 24 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" 25 #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/login/session/user_session_manager.h" 28 #include "chrome/browser/chromeos/profiles/profile_helper.h" 29 #include "chrome/browser/chromeos/system/input_device_settings.h" 30 #include "chrome/browser/download/download_prefs.h" 31 #include "chrome/browser/prefs/pref_service_syncable.h" 32 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/pref_names.h" 34 #include "chromeos/chromeos_switches.h" 35 #include "chromeos/ime/extension_ime_util.h" 36 #include "chromeos/ime/ime_keyboard.h" 37 #include "chromeos/ime/input_method_manager.h" 38 #include "chromeos/system/statistics_provider.h" 39 #include "components/feedback/tracing_manager.h" 40 #include "components/pref_registry/pref_registry_syncable.h" 41 #include "components/user_manager/user.h" 42 #include "third_party/icu/source/i18n/unicode/timezone.h" 43 #include "ui/events/event_constants.h" 44 #include "ui/events/event_utils.h" 45 #include "url/gurl.h" 46 47 namespace chromeos { 48 49 static const char kFallbackInputMethodLocale[] = "en-US"; 50 51 Preferences::Preferences() 52 : prefs_(NULL), 53 input_method_manager_(input_method::InputMethodManager::Get()), 54 user_(NULL), 55 user_is_primary_(false) { 56 // Do not observe shell, if there is no shell instance; e.g., in some unit 57 // tests. 58 if (ash::Shell::HasInstance()) 59 ash::Shell::GetInstance()->AddShellObserver(this); 60 } 61 62 Preferences::Preferences(input_method::InputMethodManager* input_method_manager) 63 : prefs_(NULL), 64 input_method_manager_(input_method_manager), 65 user_(NULL), 66 user_is_primary_(false) { 67 // Do not observe shell, if there is no shell instance; e.g., in some unit 68 // tests. 69 if (ash::Shell::HasInstance()) 70 ash::Shell::GetInstance()->AddShellObserver(this); 71 } 72 73 Preferences::~Preferences() { 74 prefs_->RemoveObserver(this); 75 user_manager::UserManager::Get()->RemoveSessionStateObserver(this); 76 // If shell instance is destoryed before this preferences instance, there is 77 // no need to remove this shell observer. 78 if (ash::Shell::HasInstance()) 79 ash::Shell::GetInstance()->RemoveShellObserver(this); 80 } 81 82 // static 83 void Preferences::RegisterPrefs(PrefRegistrySimple* registry) { 84 registry->RegisterBooleanPref(prefs::kOwnerPrimaryMouseButtonRight, false); 85 registry->RegisterBooleanPref(prefs::kOwnerTapToClickEnabled, true); 86 registry->RegisterBooleanPref(prefs::kAccessibilityVirtualKeyboardEnabled, 87 false); 88 registry->RegisterStringPref(prefs::kLogoutStartedLast, std::string()); 89 } 90 91 // static 92 void Preferences::RegisterProfilePrefs( 93 user_prefs::PrefRegistrySyncable* registry) { 94 std::string hardware_keyboard_id; 95 // TODO(yusukes): Remove the runtime hack. 96 if (base::SysInfo::IsRunningOnChromeOS()) { 97 DCHECK(g_browser_process); 98 PrefService* local_state = g_browser_process->local_state(); 99 DCHECK(local_state); 100 hardware_keyboard_id = 101 local_state->GetString(prefs::kHardwareKeyboardLayout); 102 } else { 103 hardware_keyboard_id = "xkb:us::eng"; // only for testing. 104 } 105 106 registry->RegisterBooleanPref( 107 prefs::kPerformanceTracingEnabled, 108 false, 109 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 110 111 registry->RegisterBooleanPref( 112 prefs::kTapToClickEnabled, 113 true, 114 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 115 registry->RegisterBooleanPref( 116 prefs::kTapDraggingEnabled, 117 false, 118 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 119 registry->RegisterBooleanPref( 120 prefs::kEnableTouchpadThreeFingerClick, 121 false, 122 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 123 registry->RegisterBooleanPref( 124 prefs::kNaturalScroll, 125 CommandLine::ForCurrentProcess()->HasSwitch( 126 switches::kNaturalScrollDefault), 127 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 128 registry->RegisterBooleanPref( 129 prefs::kPrimaryMouseButtonRight, 130 false, 131 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 132 registry->RegisterBooleanPref( 133 prefs::kLabsMediaplayerEnabled, 134 false, 135 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 136 registry->RegisterBooleanPref( 137 prefs::kLabsAdvancedFilesystemEnabled, 138 false, 139 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 140 registry->RegisterBooleanPref( 141 prefs::kAccessibilityStickyKeysEnabled, 142 false, 143 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 144 registry->RegisterBooleanPref( 145 prefs::kAccessibilityLargeCursorEnabled, 146 false, 147 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 148 registry->RegisterBooleanPref( 149 prefs::kAccessibilitySpokenFeedbackEnabled, 150 false, 151 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 152 registry->RegisterBooleanPref( 153 prefs::kAccessibilityHighContrastEnabled, 154 false, 155 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 156 registry->RegisterBooleanPref( 157 prefs::kAccessibilityScreenMagnifierEnabled, 158 false, 159 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 160 registry->RegisterIntegerPref( 161 prefs::kAccessibilityScreenMagnifierType, 162 ash::kDefaultMagnifierType, 163 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 164 registry->RegisterDoublePref( 165 prefs::kAccessibilityScreenMagnifierScale, 166 std::numeric_limits<double>::min(), 167 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 168 registry->RegisterBooleanPref( 169 prefs::kAccessibilityAutoclickEnabled, 170 false, 171 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 172 registry->RegisterIntegerPref( 173 prefs::kAccessibilityAutoclickDelayMs, 174 ash::AutoclickController::kDefaultAutoclickDelayMs, 175 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 176 registry->RegisterBooleanPref( 177 prefs::kAccessibilityVirtualKeyboardEnabled, 178 false, 179 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 180 registry->RegisterBooleanPref( 181 prefs::kShouldAlwaysShowAccessibilityMenu, 182 false, 183 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 184 registry->RegisterIntegerPref( 185 prefs::kMouseSensitivity, 186 3, 187 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 188 registry->RegisterIntegerPref( 189 prefs::kTouchpadSensitivity, 190 3, 191 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 192 registry->RegisterBooleanPref( 193 prefs::kUse24HourClock, 194 base::GetHourClockType() == base::k24HourClock, 195 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 196 registry->RegisterBooleanPref( 197 prefs::kDisableDrive, 198 false, 199 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 200 registry->RegisterBooleanPref( 201 prefs::kDisableDriveOverCellular, 202 true, 203 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 204 registry->RegisterBooleanPref( 205 prefs::kDisableDriveHostedFiles, 206 false, 207 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 208 // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod 209 // because they're just used to track the logout state of the device. 210 registry->RegisterStringPref( 211 prefs::kLanguageCurrentInputMethod, 212 "", 213 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 214 registry->RegisterStringPref( 215 prefs::kLanguagePreviousInputMethod, 216 "", 217 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( 222 prefs::kLanguagePreferredLanguages, 223 kFallbackInputMethodLocale, 224 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 225 registry->RegisterStringPref( 226 prefs::kLanguagePreloadEngines, 227 hardware_keyboard_id, 228 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 229 registry->RegisterStringPref( 230 prefs::kLanguageEnabledExtensionImes, 231 "", 232 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 233 234 registry->RegisterIntegerPref( 235 prefs::kLanguageRemapSearchKeyTo, 236 input_method::kSearchKey, 237 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 238 registry->RegisterIntegerPref( 239 prefs::kLanguageRemapControlKeyTo, 240 input_method::kControlKey, 241 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 242 registry->RegisterIntegerPref( 243 prefs::kLanguageRemapAltKeyTo, 244 input_method::kAltKey, 245 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 246 // We don't sync the CapsLock remapping pref, since the UI hides this pref 247 // on certain devices, so syncing a non-default value to a device that 248 // doesn't allow changing the pref would be odd. http://crbug.com/167237 249 registry->RegisterIntegerPref( 250 prefs::kLanguageRemapCapsLockKeyTo, 251 input_method::kCapsLockKey, 252 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 253 registry->RegisterIntegerPref( 254 prefs::kLanguageRemapDiamondKeyTo, 255 input_method::kControlKey, 256 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); 257 // The following pref isn't synced since the user may desire a different value 258 // depending on whether an external keyboard is attached to a particular 259 // device. 260 registry->RegisterBooleanPref( 261 prefs::kLanguageSendFunctionKeys, 262 false, 263 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 264 registry->RegisterBooleanPref( 265 prefs::kLanguageXkbAutoRepeatEnabled, 266 true, 267 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 268 registry->RegisterIntegerPref( 269 prefs::kLanguageXkbAutoRepeatDelay, 270 language_prefs::kXkbAutoRepeatDelayInMs, 271 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 272 registry->RegisterIntegerPref( 273 prefs::kLanguageXkbAutoRepeatInterval, 274 language_prefs::kXkbAutoRepeatIntervalInMs, 275 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 276 277 // Mobile plan notifications default to on. 278 registry->RegisterBooleanPref( 279 prefs::kShowPlanNotifications, 280 true, 281 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 282 283 // 3G first-time usage promo will be shown at least once. 284 registry->RegisterBooleanPref( 285 prefs::kShow3gPromoNotification, 286 true, 287 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 288 289 // Initially all existing users would see "What's new" for current version 290 // after update. 291 registry->RegisterStringPref(prefs::kChromeOSReleaseNotesVersion, 292 "0.0.0.0", 293 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 294 295 registry->RegisterBooleanPref( 296 prefs::kExternalStorageDisabled, 297 false, 298 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 299 300 registry->RegisterStringPref( 301 prefs::kTermsOfServiceURL, 302 "", 303 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 304 305 registry->RegisterBooleanPref( 306 prefs::kTouchHudProjectionEnabled, 307 false, 308 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 309 310 registry->RegisterBooleanPref( 311 prefs::kTouchVirtualKeyboardEnabled, 312 false, 313 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 314 } 315 316 void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) { 317 prefs_ = prefs; 318 319 BooleanPrefMember::NamedChangeCallback callback = 320 base::Bind(&Preferences::OnPreferenceChanged, base::Unretained(this)); 321 322 performance_tracing_enabled_.Init(prefs::kPerformanceTracingEnabled, 323 prefs, callback); 324 tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, prefs, callback); 325 tap_dragging_enabled_.Init(prefs::kTapDraggingEnabled, prefs, callback); 326 three_finger_click_enabled_.Init(prefs::kEnableTouchpadThreeFingerClick, 327 prefs, callback); 328 natural_scroll_.Init(prefs::kNaturalScroll, prefs, callback); 329 mouse_sensitivity_.Init(prefs::kMouseSensitivity, prefs, callback); 330 touchpad_sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, callback); 331 primary_mouse_button_right_.Init(prefs::kPrimaryMouseButtonRight, 332 prefs, callback); 333 download_default_directory_.Init(prefs::kDownloadDefaultDirectory, 334 prefs, callback); 335 touch_hud_projection_enabled_.Init(prefs::kTouchHudProjectionEnabled, 336 prefs, callback); 337 preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, callback); 338 enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes, 339 prefs, callback); 340 current_input_method_.Init(prefs::kLanguageCurrentInputMethod, 341 prefs, callback); 342 previous_input_method_.Init(prefs::kLanguagePreviousInputMethod, 343 prefs, callback); 344 345 xkb_auto_repeat_enabled_.Init( 346 prefs::kLanguageXkbAutoRepeatEnabled, prefs, callback); 347 xkb_auto_repeat_delay_pref_.Init( 348 prefs::kLanguageXkbAutoRepeatDelay, prefs, callback); 349 xkb_auto_repeat_interval_pref_.Init( 350 prefs::kLanguageXkbAutoRepeatInterval, prefs, callback); 351 } 352 353 void Preferences::Init(Profile* profile, const user_manager::User* user) { 354 DCHECK(profile); 355 DCHECK(user); 356 PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile); 357 user_ = user; 358 user_is_primary_ = 359 user_manager::UserManager::Get()->GetPrimaryUser() == user_; 360 InitUserPrefs(prefs); 361 362 user_manager::UserManager::Get()->AddSessionStateObserver(this); 363 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(); 369 DCHECK(session_manager); 370 ime_state_ = session_manager->GetDefaultIMEState(profile); 371 input_method_manager_->SetState(ime_state_); 372 373 // Initialize preferences to currently saved state. 374 ApplyPreferences(REASON_INITIALIZATION, ""); 375 376 // 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 378 // UserSessionManager::InitProfilePreferences(). 379 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) 380 session_manager->SetFirstLoginPrefs(profile, std::string(), std::string()); 381 } 382 383 void Preferences::InitUserPrefsForTesting( 384 PrefServiceSyncable* prefs, 385 const user_manager::User* user, 386 scoped_refptr<input_method::InputMethodManager::State> ime_state) { 387 user_ = user; 388 ime_state_ = ime_state; 389 390 if (ime_state.get()) 391 input_method_manager_->SetState(ime_state); 392 393 InitUserPrefs(prefs); 394 } 395 396 void Preferences::SetInputMethodListForTesting() { 397 SetInputMethodList(); 398 } 399 400 void Preferences::OnPreferenceChanged(const std::string& pref_name) { 401 ApplyPreferences(REASON_PREF_CHANGED, pref_name); 402 } 403 404 void Preferences::ApplyPreferences(ApplyReason reason, 405 const std::string& pref_name) { 406 DCHECK(reason != REASON_PREF_CHANGED || !pref_name.empty()); 407 const bool user_is_owner = 408 user_manager::UserManager::Get()->GetOwnerEmail() == user_->email(); 409 const bool user_is_active = user_->is_active(); 410 411 system::TouchpadSettings touchpad_settings; 412 system::MouseSettings mouse_settings; 413 414 if (user_is_primary_ && (reason == REASON_INITIALIZATION || 415 pref_name == prefs::kPerformanceTracingEnabled)) { 416 const bool enabled = performance_tracing_enabled_.GetValue(); 417 if (enabled) 418 tracing_manager_ = TracingManager::Create(); 419 else 420 tracing_manager_.reset(); 421 } 422 if (reason != REASON_PREF_CHANGED || pref_name == prefs::kTapToClickEnabled) { 423 const bool enabled = tap_to_click_enabled_.GetValue(); 424 if (user_is_active) 425 touchpad_settings.SetTapToClick(enabled); 426 if (reason == REASON_PREF_CHANGED) 427 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Changed", enabled); 428 else if (reason == REASON_INITIALIZATION) 429 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Started", enabled); 430 431 // Save owner preference in local state to use on login screen. 432 if (user_is_owner) { 433 PrefService* prefs = g_browser_process->local_state(); 434 if (prefs->GetBoolean(prefs::kOwnerTapToClickEnabled) != enabled) 435 prefs->SetBoolean(prefs::kOwnerTapToClickEnabled, enabled); 436 } 437 } 438 if (reason != REASON_PREF_CHANGED || 439 pref_name == prefs::kTapDraggingEnabled) { 440 const bool enabled = tap_dragging_enabled_.GetValue(); 441 if (user_is_active) 442 touchpad_settings.SetTapDragging(enabled); 443 if (reason == REASON_PREF_CHANGED) 444 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Changed", enabled); 445 else if (reason == REASON_INITIALIZATION) 446 UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Started", enabled); 447 } 448 if (reason != REASON_PREF_CHANGED || 449 pref_name == prefs::kEnableTouchpadThreeFingerClick) { 450 const bool enabled = three_finger_click_enabled_.GetValue(); 451 if (user_is_active) 452 touchpad_settings.SetThreeFingerClick(enabled); 453 if (reason == REASON_PREF_CHANGED) 454 UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Changed", enabled); 455 else if (reason == REASON_INITIALIZATION) 456 UMA_HISTOGRAM_BOOLEAN("Touchpad.ThreeFingerClick.Started", enabled); 457 } 458 if (reason != REASON_PREF_CHANGED || pref_name == prefs::kNaturalScroll) { 459 // Force natural scroll default if we've sync'd and if the cmd line arg is 460 // set. 461 ForceNaturalScrollDefault(); 462 463 const bool enabled = natural_scroll_.GetValue(); 464 DVLOG(1) << "Natural scroll set to " << enabled; 465 if (user_is_active) 466 touchpad_settings.SetNaturalScroll(enabled); 467 if (reason == REASON_PREF_CHANGED) 468 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Changed", enabled); 469 else if (reason == REASON_INITIALIZATION) 470 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Started", enabled); 471 } 472 if (reason != REASON_PREF_CHANGED || pref_name == prefs::kMouseSensitivity) { 473 const int sensitivity = mouse_sensitivity_.GetValue(); 474 if (user_is_active) 475 mouse_settings.SetSensitivity(sensitivity); 476 if (reason == REASON_PREF_CHANGED) { 477 UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Changed", 478 sensitivity, 479 system::kMaxPointerSensitivity + 1); 480 } else if (reason == REASON_INITIALIZATION) { 481 UMA_HISTOGRAM_ENUMERATION("Mouse.PointerSensitivity.Started", 482 sensitivity, 483 system::kMaxPointerSensitivity + 1); 484 } 485 } 486 if (reason != REASON_PREF_CHANGED || 487 pref_name == prefs::kTouchpadSensitivity) { 488 const int sensitivity = touchpad_sensitivity_.GetValue(); 489 if (user_is_active) 490 touchpad_settings.SetSensitivity(sensitivity); 491 if (reason == REASON_PREF_CHANGED) { 492 UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Changed", 493 sensitivity, 494 system::kMaxPointerSensitivity + 1); 495 } else if (reason == REASON_INITIALIZATION) { 496 UMA_HISTOGRAM_ENUMERATION("Touchpad.PointerSensitivity.Started", 497 sensitivity, 498 system::kMaxPointerSensitivity + 1); 499 } 500 } 501 if (reason != REASON_PREF_CHANGED || 502 pref_name == prefs::kPrimaryMouseButtonRight) { 503 const bool right = primary_mouse_button_right_.GetValue(); 504 if (user_is_active) 505 mouse_settings.SetPrimaryButtonRight(right); 506 if (reason == REASON_PREF_CHANGED) 507 UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Changed", right); 508 else if (reason == REASON_INITIALIZATION) 509 UMA_HISTOGRAM_BOOLEAN("Mouse.PrimaryButtonRight.Started", right); 510 // Save owner preference in local state to use on login screen. 511 if (user_is_owner) { 512 PrefService* prefs = g_browser_process->local_state(); 513 if (prefs->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight) != right) 514 prefs->SetBoolean(prefs::kOwnerPrimaryMouseButtonRight, right); 515 } 516 } 517 if (reason != REASON_PREF_CHANGED || 518 pref_name == prefs::kDownloadDefaultDirectory) { 519 const bool default_download_to_drive = drive::util::IsUnderDriveMountPoint( 520 download_default_directory_.GetValue()); 521 if (reason == REASON_PREF_CHANGED) 522 UMA_HISTOGRAM_BOOLEAN( 523 "FileBrowser.DownloadDestination.IsGoogleDrive.Changed", 524 default_download_to_drive); 525 else if (reason == REASON_INITIALIZATION) 526 UMA_HISTOGRAM_BOOLEAN( 527 "FileBrowser.DownloadDestination.IsGoogleDrive.Started", 528 default_download_to_drive); 529 } 530 if (reason != REASON_PREF_CHANGED || 531 pref_name == prefs::kTouchHudProjectionEnabled) { 532 #if !defined(USE_ATHENA) 533 if (user_is_active) { 534 const bool enabled = touch_hud_projection_enabled_.GetValue(); 535 ash::Shell::GetInstance()->SetTouchHudProjectionEnabled(enabled); 536 } 537 #endif 538 } 539 540 if (reason != REASON_PREF_CHANGED || 541 pref_name == prefs::kLanguageXkbAutoRepeatEnabled) { 542 if (user_is_active) { 543 const bool enabled = xkb_auto_repeat_enabled_.GetValue(); 544 input_method::InputMethodManager::Get() 545 ->GetImeKeyboard() 546 ->SetAutoRepeatEnabled(enabled); 547 } 548 } 549 if (reason != REASON_PREF_CHANGED || 550 pref_name == prefs::kLanguageXkbAutoRepeatDelay || 551 pref_name == prefs::kLanguageXkbAutoRepeatInterval) { 552 if (user_is_active) 553 UpdateAutoRepeatRate(); 554 } 555 556 if (reason == REASON_INITIALIZATION) 557 SetInputMethodList(); 558 559 if (pref_name == prefs::kLanguagePreloadEngines && 560 reason == REASON_PREF_CHANGED) { 561 SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, 562 language_prefs::kPreloadEnginesConfigName, 563 preload_engines_.GetValue()); 564 } 565 566 if ((reason == REASON_INITIALIZATION) || 567 (pref_name == prefs::kLanguageEnabledExtensionImes && 568 reason == REASON_PREF_CHANGED)) { 569 std::string value(enabled_extension_imes_.GetValue()); 570 571 std::vector<std::string> split_values; 572 if (!value.empty()) 573 base::SplitString(value, ',', &split_values); 574 575 ime_state_->SetEnabledExtensionImes(&split_values); 576 } 577 578 if (user_is_active) { 579 system::InputDeviceSettings::Get()->UpdateTouchpadSettings( 580 touchpad_settings); 581 system::InputDeviceSettings::Get()->UpdateMouseSettings(mouse_settings); 582 } 583 } 584 585 void Preferences::OnIsSyncingChanged() { 586 DVLOG(1) << "OnIsSyncingChanged"; 587 ForceNaturalScrollDefault(); 588 } 589 590 void Preferences::ForceNaturalScrollDefault() { 591 DVLOG(1) << "ForceNaturalScrollDefault"; 592 if (CommandLine::ForCurrentProcess()->HasSwitch( 593 switches::kNaturalScrollDefault) && 594 prefs_->IsSyncing() && 595 !prefs_->GetUserPrefValue(prefs::kNaturalScroll)) { 596 DVLOG(1) << "Natural scroll forced to true"; 597 natural_scroll_.SetValue(true); 598 UMA_HISTOGRAM_BOOLEAN("Touchpad.NaturalScroll.Forced", true); 599 } 600 } 601 602 void Preferences::SetLanguageConfigStringListAsCSV(const char* section, 603 const char* name, 604 const std::string& value) { 605 VLOG(1) << "Setting " << name << " to '" << value << "'"; 606 607 std::vector<std::string> split_values; 608 if (!value.empty()) 609 base::SplitString(value, ',', &split_values); 610 611 // Transfers the xkb id to extension-xkb id. 612 if (input_method_manager_->MigrateInputMethods(&split_values)) 613 preload_engines_.SetValue(JoinString(split_values, ',')); 614 615 if (section == std::string(language_prefs::kGeneralSectionName) && 616 name == std::string(language_prefs::kPreloadEnginesConfigName)) { 617 ime_state_->ReplaceEnabledInputMethods(split_values); 618 return; 619 } 620 } 621 622 void Preferences::SetInputMethodList() { 623 // When |preload_engines_| are set, InputMethodManager::ChangeInputMethod() 624 // might be called to change the current input method to the first one in the 625 // |preload_engines_| list. This also updates previous/current input method 626 // prefs. That's why GetValue() calls are placed before the 627 // SetLanguageConfigStringListAsCSV() call below. 628 const std::string previous_input_method_id = 629 previous_input_method_.GetValue(); 630 const std::string current_input_method_id = current_input_method_.GetValue(); 631 SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName, 632 language_prefs::kPreloadEnginesConfigName, 633 preload_engines_.GetValue()); 634 635 // ChangeInputMethod() has to be called AFTER the value of |preload_engines_| 636 // is sent to the InputMethodManager. Otherwise, the ChangeInputMethod request 637 // might be ignored as an invalid input method ID. The ChangeInputMethod() 638 // calls are also necessary to restore the previous/current input method prefs 639 // which could have been modified by the SetLanguageConfigStringListAsCSV call 640 // above to the original state. 641 if (!previous_input_method_id.empty()) 642 ime_state_->ChangeInputMethod(previous_input_method_id, 643 false /* show_message */); 644 if (!current_input_method_id.empty()) 645 ime_state_->ChangeInputMethod(current_input_method_id, 646 false /* show_message */); 647 } 648 649 void Preferences::UpdateAutoRepeatRate() { 650 input_method::AutoRepeatRate rate; 651 rate.initial_delay_in_ms = xkb_auto_repeat_delay_pref_.GetValue(); 652 rate.repeat_interval_in_ms = xkb_auto_repeat_interval_pref_.GetValue(); 653 DCHECK(rate.initial_delay_in_ms > 0); 654 DCHECK(rate.repeat_interval_in_ms > 0); 655 input_method::InputMethodManager::Get() 656 ->GetImeKeyboard() 657 ->SetAutoRepeatRate(rate); 658 } 659 660 void Preferences::OnTouchHudProjectionToggled(bool enabled) { 661 if (touch_hud_projection_enabled_.GetValue() == enabled) 662 return; 663 if (!user_->is_active()) 664 return; 665 touch_hud_projection_enabled_.SetValue(enabled); 666 } 667 668 void Preferences::ActiveUserChanged(const user_manager::User* active_user) { 669 if (active_user != user_) 670 return; 671 ApplyPreferences(REASON_ACTIVE_USER_CHANGED, ""); 672 } 673 674 } // namespace chromeos 675