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