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