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