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