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