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