Home | History | Annotate | Download | only in input_method
      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/input_method/input_method_persistence.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/prefs/scoped_user_pref_update.h"
     10 #include "base/sys_info.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     13 #include "chrome/browser/chromeos/language_preferences.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/profiles/profile_manager.h"
     16 #include "chrome/common/pref_names.h"
     17 
     18 namespace chromeos {
     19 namespace input_method {
     20 namespace {
     21 
     22 void PersistSystemInputMethod(const std::string& input_method) {
     23   if (!g_browser_process || !g_browser_process->local_state())
     24     return;
     25 
     26   g_browser_process->local_state()->SetString(
     27         language_prefs::kPreferredKeyboardLayout, input_method);
     28 }
     29 
     30 static void SetUserLRUInputMethodPreference(const std::string& username,
     31                                             const std::string& input_method,
     32                                             PrefService* local_state) {
     33   if (!username.empty() && !local_state->ReadOnly()) {
     34     bool update_succeed = false;
     35     {
     36       // Updater may have side-effects, therefore we do not replace
     37       // entry while updater exists.
     38       DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
     39       base::DictionaryValue* const users_lru_input_methods = updater.Get();
     40       if (users_lru_input_methods) {
     41         users_lru_input_methods->SetStringWithoutPathExpansion(username,
     42                                                                input_method);
     43         update_succeed = true;
     44       }
     45     }
     46     if (!update_succeed) {
     47       // Somehow key kUsersLRUInputMethod has value of invalid type.
     48       // Replace and retry.
     49       local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue());
     50 
     51       DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
     52       base::DictionaryValue* const users_lru_input_methods = updater.Get();
     53       if (users_lru_input_methods) {
     54         users_lru_input_methods->SetStringWithoutPathExpansion(username,
     55                                                                input_method);
     56         update_succeed = true;
     57       }
     58     }
     59     if (!update_succeed) {
     60       DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '"
     61                << prefs::kUsersLRUInputMethod << "' for '" << username << "'";
     62     }
     63   }
     64 }
     65 
     66 // Update user LRU keyboard layout for login screen
     67 static void SetUserLRUInputMethod(
     68     const std::string& input_method,
     69     const chromeos::input_method::InputMethodManager* const manager,
     70     Profile* profile) {
     71   // Skip if it's not a keyboard layout. Drop input methods including
     72   // extension ones.
     73   if (!manager->IsLoginKeyboard(input_method))
     74     return;
     75 
     76   if (profile == NULL)
     77     return;
     78 
     79   PrefService* const local_state = g_browser_process->local_state();
     80 
     81   SetUserLRUInputMethodPreference(
     82       profile->GetProfileName(), input_method, local_state);
     83 }
     84 
     85 void PersistUserInputMethod(const std::string& input_method,
     86                             InputMethodManager* const manager) {
     87   PrefService* user_prefs = NULL;
     88   // Persist the method on a per user basis. Note that the keyboard settings are
     89   // stored per user desktop and a visiting window will use the same input
     90   // method as the desktop it is on (and not of the owner of the window).
     91   Profile* profile = ProfileManager::GetActiveUserProfile();
     92   if (profile)
     93     user_prefs = profile->GetPrefs();
     94   if (!user_prefs)
     95     return;
     96   SetUserLRUInputMethod(input_method, manager, profile);
     97 
     98   const std::string current_input_method_on_pref =
     99       user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
    100   if (current_input_method_on_pref == input_method)
    101     return;
    102 
    103   user_prefs->SetString(prefs::kLanguagePreviousInputMethod,
    104                         current_input_method_on_pref);
    105   user_prefs->SetString(prefs::kLanguageCurrentInputMethod,
    106                         input_method);
    107 }
    108 
    109 }  // namespace
    110 
    111 InputMethodPersistence::InputMethodPersistence(
    112     InputMethodManager* input_method_manager)
    113     : input_method_manager_(input_method_manager),
    114       ui_session_(InputMethodManager::STATE_LOGIN_SCREEN) {
    115   input_method_manager_->AddObserver(this);
    116 }
    117 
    118 InputMethodPersistence::~InputMethodPersistence() {
    119   input_method_manager_->RemoveObserver(this);
    120 }
    121 
    122 void InputMethodPersistence::InputMethodChanged(
    123     InputMethodManager* manager, bool show_message) {
    124   DCHECK_EQ(input_method_manager_, manager);
    125   const std::string current_input_method =
    126       manager->GetActiveIMEState()->GetCurrentInputMethod().id();
    127   // Save the new input method id depending on the current browser state.
    128   switch (ui_session_) {
    129     case InputMethodManager::STATE_LOGIN_SCREEN:
    130       if (!manager->IsLoginKeyboard(current_input_method)) {
    131         DVLOG(1) << "Only keyboard layouts are supported: "
    132                  << current_input_method;
    133         return;
    134       }
    135       PersistSystemInputMethod(current_input_method);
    136       return;
    137     case InputMethodManager::STATE_BROWSER_SCREEN:
    138       PersistUserInputMethod(current_input_method, manager);
    139       return;
    140     case InputMethodManager::STATE_LOCK_SCREEN:
    141       // We use a special set of input methods on the screen. Do not update.
    142       return;
    143     case InputMethodManager::STATE_TERMINATING:
    144       return;
    145   }
    146   NOTREACHED();
    147 }
    148 
    149 void InputMethodPersistence::OnSessionStateChange(
    150     InputMethodManager::UISessionState new_ui_session) {
    151   ui_session_ = new_ui_session;
    152 }
    153 
    154 void SetUserLRUInputMethodPreferenceForTesting(const std::string& username,
    155                                                const std::string& input_method,
    156                                                PrefService* const local_state) {
    157   SetUserLRUInputMethodPreference(username, input_method, local_state);
    158 }
    159 
    160 }  // namespace input_method
    161 }  // namespace chromeos
    162