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