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