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