12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_persistence.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/language_preferences.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace input_method { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PersistSystemInputMethod(const std::string& input_method) { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!g_browser_process || !g_browser_process->local_state()) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_browser_process->local_state()->SetString( 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) language_prefs::kPreferredKeyboardLayout, input_method); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic void SetUserLRUInputMethodPreference(const std::string& username, 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& input_method, 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PrefService* local_state) { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!username.empty() && !local_state->ReadOnly()) { 34a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch bool update_succeed = false; 35a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch { 36a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Updater may have side-effects, therefore we do not replace 37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // entry while updater exists. 38a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod); 39a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch base::DictionaryValue* const users_lru_input_methods = updater.Get(); 40a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (users_lru_input_methods) { 41a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch users_lru_input_methods->SetStringWithoutPathExpansion(username, 42a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch input_method); 43a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch update_succeed = true; 44a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 45a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 46a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (!update_succeed) { 47a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Somehow key kUsersLRUInputMethod has value of invalid type. 48a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch // Replace and retry. 49a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue()); 50a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 51a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod); 52a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch base::DictionaryValue* const users_lru_input_methods = updater.Get(); 53a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (users_lru_input_methods) { 54a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch users_lru_input_methods->SetStringWithoutPathExpansion(username, 55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch input_method); 56a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch update_succeed = true; 57a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 58a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 59a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (!update_succeed) { 60a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '" 61a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch << prefs::kUsersLRUInputMethod << "' for '" << username << "'"; 62a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 63a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 64a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 65a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Update user LRU keyboard layout for login screen 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic void SetUserLRUInputMethod( 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& input_method, 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const chromeos::input_method::InputMethodManager* const manager, 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Profile* profile) { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Skip if it's not a keyboard layout. Drop input methods including 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // extension ones. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!manager->IsLoginKeyboard(input_method)) 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (profile == NULL) 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PrefService* const local_state = g_browser_process->local_state(); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetUserLRUInputMethodPreference( 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile->GetProfileName(), input_method, local_state); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 85a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid PersistUserInputMethod(const std::string& input_method, 86a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch InputMethodManager* const manager) { 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrefService* user_prefs = NULL; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Persist the method on a per user basis. Note that the keyboard settings are 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // stored per user desktop and a visiting window will use the same input 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // method as the desktop it is on (and not of the owner of the window). 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = ProfileManager::GetActiveUserProfile(); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (profile) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_prefs = profile->GetPrefs(); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!user_prefs) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetUserLRUInputMethod(input_method, manager, profile); 97a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string current_input_method_on_pref = 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_prefs->GetString(prefs::kLanguageCurrentInputMethod); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_input_method_on_pref == input_method) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_prefs->SetString(prefs::kLanguagePreviousInputMethod, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_input_method_on_pref); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_prefs->SetString(prefs::kLanguageCurrentInputMethod, 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_method); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InputMethodPersistence::InputMethodPersistence( 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InputMethodManager* input_method_manager) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : input_method_manager_(input_method_manager), 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ui_session_(InputMethodManager::STATE_LOGIN_SCREEN) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_method_manager_->AddObserver(this); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InputMethodPersistence::~InputMethodPersistence() { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_method_manager_->RemoveObserver(this); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InputMethodPersistence::InputMethodChanged( 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InputMethodManager* manager, bool show_message) { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(input_method_manager_, manager); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string current_input_method = 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) manager->GetActiveIMEState()->GetCurrentInputMethod().id(); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Save the new input method id depending on the current browser state. 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) switch (ui_session_) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case InputMethodManager::STATE_LOGIN_SCREEN: 130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!manager->IsLoginKeyboard(current_input_method)) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Only keyboard layouts are supported: " 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_input_method; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PersistSystemInputMethod(current_input_method); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case InputMethodManager::STATE_BROWSER_SCREEN: 138a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch PersistUserInputMethod(current_input_method, manager); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case InputMethodManager::STATE_LOCK_SCREEN: 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We use a special set of input methods on the screen. Do not update. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case InputMethodManager::STATE_TERMINATING: 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InputMethodPersistence::OnSessionStateChange( 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) InputMethodManager::UISessionState new_ui_session) { 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ui_session_ = new_ui_session; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SetUserLRUInputMethodPreferenceForTesting(const std::string& username, 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& input_method, 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PrefService* const local_state) { 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetUserLRUInputMethodPreference(username, input_method, local_state); 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace input_method 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chromeos 162