preferences.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
1// Copyright (c) 2011 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 "base/i18n/time_formatting.h"
8#include "base/metrics/histogram.h"
9#include "base/string_split.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/chromeos/cros/cros_library.h"
13#include "chrome/browser/chromeos/cros/input_method_library.h"
14#include "chrome/browser/chromeos/cros/power_library.h"
15#include "chrome/browser/chromeos/cros/touchpad_library.h"
16#include "chrome/browser/chromeos/input_method/input_method_util.h"
17#include "chrome/browser/chromeos/input_method/xkeyboard.h"
18#include "chrome/browser/chromeos/login/login_utils.h"
19#include "chrome/browser/prefs/pref_member.h"
20#include "chrome/browser/prefs/pref_service.h"
21#include "chrome/common/pref_names.h"
22#include "content/common/notification_details.h"
23#include "content/common/notification_source.h"
24#include "content/common/notification_type.h"
25#include "unicode/timezone.h"
26
27namespace chromeos {
28
29static const char kFallbackInputMethodLocale[] = "en-US";
30
31Preferences::Preferences() {}
32
33Preferences::~Preferences() {}
34
35// static
36void Preferences::RegisterUserPrefs(PrefService* prefs) {
37  prefs->RegisterBooleanPref(prefs::kTapToClickEnabled, false);
38  prefs->RegisterBooleanPref(prefs::kLabsMediaplayerEnabled, false);
39  prefs->RegisterBooleanPref(prefs::kLabsAdvancedFilesystemEnabled, false);
40  // Check if the accessibility pref is already registered, which can happen
41  // in WizardController::RegisterPrefs. We still want to try to register
42  // the pref here in case of Chrome/Linux with ChromeOS=1.
43  if (prefs->FindPreference(prefs::kAccessibilityEnabled) == NULL) {
44    prefs->RegisterBooleanPref(prefs::kAccessibilityEnabled, false);
45  }
46  prefs->RegisterIntegerPref(prefs::kTouchpadSensitivity, 3);
47  // Set the default based on the hour clock type of the current locale.
48  prefs->RegisterBooleanPref(prefs::kUse24HourClock,
49                             base::GetHourClockType() == base::k24HourClock);
50  prefs->RegisterStringPref(prefs::kLanguageCurrentInputMethod, "");
51  prefs->RegisterStringPref(prefs::kLanguagePreviousInputMethod, "");
52  prefs->RegisterStringPref(prefs::kLanguageHotkeyNextEngineInMenu,
53                            language_prefs::kHotkeyNextEngineInMenu);
54  prefs->RegisterStringPref(prefs::kLanguageHotkeyPreviousEngine,
55                            language_prefs::kHotkeyPreviousEngine);
56  prefs->RegisterStringPref(prefs::kLanguagePreferredLanguages,
57                            kFallbackInputMethodLocale);
58  prefs->RegisterStringPref(
59      prefs::kLanguagePreloadEngines,
60      input_method::GetHardwareInputMethodId());
61  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
62    prefs->RegisterBooleanPref(
63        language_prefs::kChewingBooleanPrefs[i].pref_name,
64        language_prefs::kChewingBooleanPrefs[i].default_pref_value);
65  }
66  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
67    prefs->RegisterStringPref(
68        language_prefs::kChewingMultipleChoicePrefs[i].pref_name,
69        language_prefs::kChewingMultipleChoicePrefs[i].default_pref_value);
70  }
71  prefs->RegisterIntegerPref(
72      language_prefs::kChewingHsuSelKeyType.pref_name,
73      language_prefs::kChewingHsuSelKeyType.default_pref_value);
74
75  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
76    prefs->RegisterIntegerPref(
77        language_prefs::kChewingIntegerPrefs[i].pref_name,
78        language_prefs::kChewingIntegerPrefs[i].default_pref_value);
79  }
80  prefs->RegisterStringPref(
81      prefs::kLanguageHangulKeyboard,
82      language_prefs::kHangulKeyboardNameIDPairs[0].keyboard_id);
83  prefs->RegisterStringPref(prefs::kLanguageHangulHanjaKeys,
84                            language_prefs::kHangulHanjaKeys);
85  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
86    prefs->RegisterBooleanPref(
87        language_prefs::kPinyinBooleanPrefs[i].pref_name,
88        language_prefs::kPinyinBooleanPrefs[i].default_pref_value);
89  }
90  for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
91    prefs->RegisterIntegerPref(
92        language_prefs::kPinyinIntegerPrefs[i].pref_name,
93        language_prefs::kPinyinIntegerPrefs[i].default_pref_value);
94  }
95  prefs->RegisterIntegerPref(
96      language_prefs::kPinyinDoublePinyinSchema.pref_name,
97      language_prefs::kPinyinDoublePinyinSchema.default_pref_value);
98
99  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
100    prefs->RegisterBooleanPref(
101        language_prefs::kMozcBooleanPrefs[i].pref_name,
102        language_prefs::kMozcBooleanPrefs[i].default_pref_value);
103  }
104  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
105    prefs->RegisterStringPref(
106        language_prefs::kMozcMultipleChoicePrefs[i].pref_name,
107        language_prefs::kMozcMultipleChoicePrefs[i].default_pref_value);
108  }
109  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
110    prefs->RegisterIntegerPref(
111        language_prefs::kMozcIntegerPrefs[i].pref_name,
112        language_prefs::kMozcIntegerPrefs[i].default_pref_value);
113  }
114  prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapSearchKeyTo,
115                             input_method::kSearchKey);
116  prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapControlKeyTo,
117                             input_method::kLeftControlKey);
118  prefs->RegisterIntegerPref(prefs::kLanguageXkbRemapAltKeyTo,
119                             input_method::kLeftAltKey);
120  prefs->RegisterBooleanPref(prefs::kLanguageXkbAutoRepeatEnabled, true);
121  prefs->RegisterIntegerPref(prefs::kLanguageXkbAutoRepeatDelay,
122                             language_prefs::kXkbAutoRepeatDelayInMs);
123  prefs->RegisterIntegerPref(prefs::kLanguageXkbAutoRepeatInterval,
124                             language_prefs::kXkbAutoRepeatIntervalInMs);
125
126  // Screen lock default to off.
127  prefs->RegisterBooleanPref(prefs::kEnableScreenLock, false);
128
129  // Mobile plan notifications default to on.
130  prefs->RegisterBooleanPref(prefs::kShowPlanNotifications, true);
131
132  // 3G first-time usage promo will be shown at least once.
133  prefs->RegisterBooleanPref(prefs::kShow3gPromoNotification, true);
134
135  // Carrier deal notification shown count defaults to 0.
136  prefs->RegisterIntegerPref(prefs::kCarrierDealPromoShown, 0);
137
138  // The map of timestamps of the last used file browser handlers.
139  prefs->RegisterDictionaryPref(prefs::kLastUsedFileBrowserHandlers);
140}
141
142void Preferences::Init(PrefService* prefs) {
143  tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, prefs, this);
144  accessibility_enabled_.Init(prefs::kAccessibilityEnabled, prefs, this);
145  sensitivity_.Init(prefs::kTouchpadSensitivity, prefs, this);
146  use_24hour_clock_.Init(prefs::kUse24HourClock, prefs, this);
147  language_hotkey_next_engine_in_menu_.Init(
148      prefs::kLanguageHotkeyNextEngineInMenu, prefs, this);
149  language_hotkey_previous_engine_.Init(
150      prefs::kLanguageHotkeyPreviousEngine, prefs, this);
151  language_preferred_languages_.Init(prefs::kLanguagePreferredLanguages,
152                                     prefs, this);
153  language_preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, this);
154  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
155    language_chewing_boolean_prefs_[i].Init(
156        language_prefs::kChewingBooleanPrefs[i].pref_name, prefs, this);
157  }
158  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
159    language_chewing_multiple_choice_prefs_[i].Init(
160        language_prefs::kChewingMultipleChoicePrefs[i].pref_name, prefs, this);
161  }
162  language_chewing_hsu_sel_key_type_.Init(
163      language_prefs::kChewingHsuSelKeyType.pref_name, prefs, this);
164  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
165    language_chewing_integer_prefs_[i].Init(
166        language_prefs::kChewingIntegerPrefs[i].pref_name, prefs, this);
167  }
168  language_hangul_keyboard_.Init(prefs::kLanguageHangulKeyboard, prefs, this);
169  language_hangul_hanja_keys_.Init(
170      prefs::kLanguageHangulHanjaKeys, prefs, this);
171  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
172    language_pinyin_boolean_prefs_[i].Init(
173        language_prefs::kPinyinBooleanPrefs[i].pref_name, prefs, this);
174  }
175  for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
176    language_pinyin_int_prefs_[i].Init(
177        language_prefs::kPinyinIntegerPrefs[i].pref_name, prefs, this);
178  }
179  language_pinyin_double_pinyin_schema_.Init(
180      language_prefs::kPinyinDoublePinyinSchema.pref_name, prefs, this);
181  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
182    language_mozc_boolean_prefs_[i].Init(
183        language_prefs::kMozcBooleanPrefs[i].pref_name, prefs, this);
184  }
185  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
186    language_mozc_multiple_choice_prefs_[i].Init(
187        language_prefs::kMozcMultipleChoicePrefs[i].pref_name, prefs, this);
188  }
189  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
190    language_mozc_integer_prefs_[i].Init(
191        language_prefs::kMozcIntegerPrefs[i].pref_name, prefs, this);
192  }
193  language_xkb_remap_search_key_to_.Init(
194      prefs::kLanguageXkbRemapSearchKeyTo, prefs, this);
195  language_xkb_remap_control_key_to_.Init(
196      prefs::kLanguageXkbRemapControlKeyTo, prefs, this);
197  language_xkb_remap_alt_key_to_.Init(
198      prefs::kLanguageXkbRemapAltKeyTo, prefs, this);
199  language_xkb_auto_repeat_enabled_.Init(
200      prefs::kLanguageXkbAutoRepeatEnabled, prefs, this);
201  language_xkb_auto_repeat_delay_pref_.Init(
202      prefs::kLanguageXkbAutoRepeatDelay, prefs, this);
203  language_xkb_auto_repeat_interval_pref_.Init(
204      prefs::kLanguageXkbAutoRepeatInterval, prefs, this);
205
206  enable_screen_lock_.Init(prefs::kEnableScreenLock, prefs, this);
207
208  // Initialize preferences to currently saved state.
209  NotifyPrefChanged(NULL);
210
211  // If a guest is logged in, initialize the prefs as if this is the first
212  // login.
213  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) {
214    LoginUtils::Get()->SetFirstLoginPrefs(prefs);
215  }
216}
217
218void Preferences::Observe(NotificationType type,
219                          const NotificationSource& source,
220                          const NotificationDetails& details) {
221  if (type == NotificationType::PREF_CHANGED)
222    NotifyPrefChanged(Details<std::string>(details).ptr());
223}
224
225void Preferences::NotifyPrefChanged(const std::string* pref_name) {
226  if (!pref_name || *pref_name == prefs::kTapToClickEnabled) {
227    bool enabled = tap_to_click_enabled_.GetValue();
228    CrosLibrary::Get()->GetTouchpadLibrary()->SetTapToClick(enabled);
229    if (pref_name)
230      UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Changed", enabled);
231    else
232      UMA_HISTOGRAM_BOOLEAN("Touchpad.TapToClick.Started", enabled);
233  }
234  if (!pref_name || *pref_name == prefs::kTouchpadSensitivity) {
235    int sensitivity = sensitivity_.GetValue();
236    CrosLibrary::Get()->GetTouchpadLibrary()->SetSensitivity(sensitivity);
237    if (pref_name) {
238      UMA_HISTOGRAM_CUSTOM_COUNTS(
239          "Touchpad.Sensitivity.Changed", sensitivity, 1, 5, 5);
240    } else {
241      UMA_HISTOGRAM_CUSTOM_COUNTS(
242          "Touchpad.Sensitivity.Started", sensitivity, 1, 5, 5);
243    }
244  }
245
246  // We don't handle prefs::kLanguageCurrentInputMethod and PreviousInputMethod
247  // here.
248
249  if (!pref_name || *pref_name == prefs::kLanguageHotkeyNextEngineInMenu) {
250    SetLanguageConfigStringListAsCSV(
251        language_prefs::kHotKeySectionName,
252        language_prefs::kNextEngineInMenuConfigName,
253        language_hotkey_next_engine_in_menu_.GetValue());
254  }
255  if (!pref_name || *pref_name == prefs::kLanguageHotkeyPreviousEngine) {
256    SetLanguageConfigStringListAsCSV(
257        language_prefs::kHotKeySectionName,
258        language_prefs::kPreviousEngineConfigName,
259        language_hotkey_previous_engine_.GetValue());
260  }
261  if (!pref_name || *pref_name == prefs::kLanguagePreferredLanguages) {
262    // Unlike kLanguagePreloadEngines and some other input method
263    // preferencs, we don't need to send this to ibus-daemon.
264  }
265
266  // Here, we set up the the modifier key mapping. This has to be done
267  // before changing the current keyboard layout, so that the modifier key
268  // preference is properly preserved. For this reason, we should do this
269  // before setting preload engines, that could change the current
270  // keyboard layout as needed.
271  if (!pref_name || (*pref_name == prefs::kLanguageXkbRemapSearchKeyTo ||
272                     *pref_name == prefs::kLanguageXkbRemapControlKeyTo ||
273                     *pref_name == prefs::kLanguageXkbRemapAltKeyTo)) {
274    UpdateModifierKeyMapping();
275  }
276  if (!pref_name || *pref_name == prefs::kLanguageXkbAutoRepeatEnabled) {
277    const bool enabled = language_xkb_auto_repeat_enabled_.GetValue();
278    input_method::SetAutoRepeatEnabled(enabled);
279  }
280  if (!pref_name || ((*pref_name == prefs::kLanguageXkbAutoRepeatDelay) ||
281                     (*pref_name == prefs::kLanguageXkbAutoRepeatInterval))) {
282    UpdateAutoRepeatRate();
283  }
284
285  if (!pref_name || *pref_name == prefs::kLanguagePreloadEngines) {
286    SetLanguageConfigStringListAsCSV(language_prefs::kGeneralSectionName,
287                                     language_prefs::kPreloadEnginesConfigName,
288                                     language_preload_engines_.GetValue());
289  }
290  for (size_t i = 0; i < language_prefs::kNumChewingBooleanPrefs; ++i) {
291    if (!pref_name ||
292        *pref_name == language_prefs::kChewingBooleanPrefs[i].pref_name) {
293      SetLanguageConfigBoolean(
294          language_prefs::kChewingSectionName,
295          language_prefs::kChewingBooleanPrefs[i].ibus_config_name,
296          language_chewing_boolean_prefs_[i].GetValue());
297    }
298  }
299  for (size_t i = 0; i < language_prefs::kNumChewingMultipleChoicePrefs; ++i) {
300    if (!pref_name ||
301        *pref_name ==
302        language_prefs::kChewingMultipleChoicePrefs[i].pref_name) {
303      SetLanguageConfigString(
304          language_prefs::kChewingSectionName,
305          language_prefs::kChewingMultipleChoicePrefs[i].ibus_config_name,
306          language_chewing_multiple_choice_prefs_[i].GetValue());
307    }
308  }
309  if (!pref_name ||
310      *pref_name == language_prefs::kChewingHsuSelKeyType.pref_name) {
311    SetLanguageConfigInteger(
312        language_prefs::kChewingSectionName,
313        language_prefs::kChewingHsuSelKeyType.ibus_config_name,
314        language_chewing_hsu_sel_key_type_.GetValue());
315  }
316  for (size_t i = 0; i < language_prefs::kNumChewingIntegerPrefs; ++i) {
317    if (!pref_name ||
318        *pref_name == language_prefs::kChewingIntegerPrefs[i].pref_name) {
319      SetLanguageConfigInteger(
320          language_prefs::kChewingSectionName,
321          language_prefs::kChewingIntegerPrefs[i].ibus_config_name,
322          language_chewing_integer_prefs_[i].GetValue());
323    }
324  }
325  if (!pref_name ||
326      *pref_name == prefs::kLanguageHangulKeyboard) {
327    SetLanguageConfigString(language_prefs::kHangulSectionName,
328                            language_prefs::kHangulKeyboardConfigName,
329                            language_hangul_keyboard_.GetValue());
330  }
331  if (!pref_name || *pref_name == prefs::kLanguageHangulHanjaKeys) {
332    SetLanguageConfigString(language_prefs::kHangulSectionName,
333                            language_prefs::kHangulHanjaKeysConfigName,
334                            language_hangul_hanja_keys_.GetValue());
335  }
336  for (size_t i = 0; i < language_prefs::kNumPinyinBooleanPrefs; ++i) {
337    if (!pref_name ||
338        *pref_name == language_prefs::kPinyinBooleanPrefs[i].pref_name) {
339      SetLanguageConfigBoolean(
340          language_prefs::kPinyinSectionName,
341          language_prefs::kPinyinBooleanPrefs[i].ibus_config_name,
342          language_pinyin_boolean_prefs_[i].GetValue());
343    }
344  }
345  for (size_t i = 0; i < language_prefs::kNumPinyinIntegerPrefs; ++i) {
346    if (!pref_name ||
347        *pref_name == language_prefs::kPinyinIntegerPrefs[i].pref_name) {
348      SetLanguageConfigInteger(
349          language_prefs::kPinyinSectionName,
350          language_prefs::kPinyinIntegerPrefs[i].ibus_config_name,
351          language_pinyin_int_prefs_[i].GetValue());
352    }
353  }
354  if (!pref_name ||
355      *pref_name == language_prefs::kPinyinDoublePinyinSchema.pref_name) {
356    SetLanguageConfigInteger(
357        language_prefs::kPinyinSectionName,
358        language_prefs::kPinyinDoublePinyinSchema.ibus_config_name,
359        language_pinyin_double_pinyin_schema_.GetValue());
360  }
361  for (size_t i = 0; i < language_prefs::kNumMozcBooleanPrefs; ++i) {
362    if (!pref_name ||
363        *pref_name == language_prefs::kMozcBooleanPrefs[i].pref_name) {
364      SetLanguageConfigBoolean(
365          language_prefs::kMozcSectionName,
366          language_prefs::kMozcBooleanPrefs[i].ibus_config_name,
367          language_mozc_boolean_prefs_[i].GetValue());
368    }
369  }
370  for (size_t i = 0; i < language_prefs::kNumMozcMultipleChoicePrefs; ++i) {
371    if (!pref_name ||
372        *pref_name == language_prefs::kMozcMultipleChoicePrefs[i].pref_name) {
373      SetLanguageConfigString(
374          language_prefs::kMozcSectionName,
375          language_prefs::kMozcMultipleChoicePrefs[i].ibus_config_name,
376          language_mozc_multiple_choice_prefs_[i].GetValue());
377    }
378  }
379  for (size_t i = 0; i < language_prefs::kNumMozcIntegerPrefs; ++i) {
380    if (!pref_name ||
381        *pref_name == language_prefs::kMozcIntegerPrefs[i].pref_name) {
382      SetLanguageConfigInteger(
383          language_prefs::kMozcSectionName,
384          language_prefs::kMozcIntegerPrefs[i].ibus_config_name,
385          language_mozc_integer_prefs_[i].GetValue());
386    }
387  }
388
389  // Init or update power manager config.
390  if (!pref_name || *pref_name == prefs::kEnableScreenLock) {
391    CrosLibrary::Get()->GetPowerLibrary()->EnableScreenLock(
392        enable_screen_lock_.GetValue());
393  }
394}
395
396void Preferences::SetLanguageConfigBoolean(const char* section,
397                                           const char* name,
398                                           bool value) {
399  ImeConfigValue config;
400  config.type = ImeConfigValue::kValueTypeBool;
401  config.bool_value = value;
402  CrosLibrary::Get()->GetInputMethodLibrary()->
403      SetImeConfig(section, name, config);
404}
405
406void Preferences::SetLanguageConfigInteger(const char* section,
407                                           const char* name,
408                                           int value) {
409  ImeConfigValue config;
410  config.type = ImeConfigValue::kValueTypeInt;
411  config.int_value = value;
412  CrosLibrary::Get()->GetInputMethodLibrary()->
413      SetImeConfig(section, name, config);
414}
415
416void Preferences::SetLanguageConfigString(const char* section,
417                                          const char* name,
418                                          const std::string& value) {
419  ImeConfigValue config;
420  config.type = ImeConfigValue::kValueTypeString;
421  config.string_value = value;
422  CrosLibrary::Get()->GetInputMethodLibrary()->
423      SetImeConfig(section, name, config);
424}
425
426void Preferences::SetLanguageConfigStringList(
427    const char* section,
428    const char* name,
429    const std::vector<std::string>& values) {
430  ImeConfigValue config;
431  config.type = ImeConfigValue::kValueTypeStringList;
432  for (size_t i = 0; i < values.size(); ++i)
433    config.string_list_value.push_back(values[i]);
434
435  CrosLibrary::Get()->GetInputMethodLibrary()->
436      SetImeConfig(section, name, config);
437}
438
439void Preferences::SetLanguageConfigStringListAsCSV(const char* section,
440                                                   const char* name,
441                                                   const std::string& value) {
442  VLOG(1) << "Setting " << name << " to '" << value << "'";
443
444  std::vector<std::string> split_values;
445  if (!value.empty())
446    base::SplitString(value, ',', &split_values);
447
448  // We should call the cros API even when |value| is empty, to disable default
449  // config.
450  SetLanguageConfigStringList(section, name, split_values);
451}
452
453void Preferences::UpdateModifierKeyMapping() {
454  const int search_remap = language_xkb_remap_search_key_to_.GetValue();
455  const int control_remap = language_xkb_remap_control_key_to_.GetValue();
456  const int alt_remap = language_xkb_remap_alt_key_to_.GetValue();
457  if ((search_remap < input_method::kNumModifierKeys) && (search_remap >= 0) &&
458      (control_remap < input_method::kNumModifierKeys) &&
459      (control_remap >= 0) &&
460      (alt_remap < input_method::kNumModifierKeys) && (alt_remap >= 0)) {
461    input_method::ModifierMap modifier_map;
462    modifier_map.push_back(
463        input_method::ModifierKeyPair(
464            input_method::kSearchKey,
465            input_method::ModifierKey(search_remap)));
466    modifier_map.push_back(
467        input_method::ModifierKeyPair(
468            input_method::kLeftControlKey,
469            input_method::ModifierKey(control_remap)));
470    modifier_map.push_back(
471        input_method::ModifierKeyPair(
472            input_method::kLeftAltKey,
473            input_method::ModifierKey(alt_remap)));
474    input_method::RemapModifierKeys(modifier_map);
475  } else {
476    LOG(ERROR) << "Failed to remap modifier keys. Unexpected value(s): "
477               << search_remap << ", " << control_remap << ", " << alt_remap;
478  }
479}
480
481void Preferences::UpdateAutoRepeatRate() {
482  input_method::AutoRepeatRate rate;
483  rate.initial_delay_in_ms = language_xkb_auto_repeat_delay_pref_.GetValue();
484  rate.repeat_interval_in_ms =
485      language_xkb_auto_repeat_interval_pref_.GetValue();
486  DCHECK(rate.initial_delay_in_ms > 0);
487  DCHECK(rate.repeat_interval_in_ms > 0);
488  input_method::SetAutoRepeatRate(rate);
489}
490
491}  // namespace chromeos
492