1// Copyright (c) 2013 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/ui/ash/session_state_delegate_chromeos.h" 6 7#include "ash/multi_profile_uma.h" 8#include "ash/session/session_state_observer.h" 9#include "ash/system/chromeos/multi_user/user_switch_util.h" 10#include "base/bind.h" 11#include "base/callback.h" 12#include "base/command_line.h" 13#include "base/logging.h" 14#include "base/prefs/pref_service.h" 15#include "chrome/browser/chromeos/login/lock/screen_locker.h" 16#include "chrome/browser/chromeos/login/ui/user_adding_screen.h" 17#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" 18#include "chrome/browser/chromeos/profiles/profile_helper.h" 19#include "chrome/browser/profiles/profile.h" 20#include "chrome/browser/profiles/profile_manager.h" 21#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 22#include "chrome/common/pref_names.h" 23#include "chromeos/chromeos_switches.h" 24#include "chromeos/dbus/dbus_thread_manager.h" 25#include "chromeos/dbus/session_manager_client.h" 26#include "chromeos/login/login_state.h" 27#include "components/user_manager/user.h" 28#include "components/user_manager/user_manager.h" 29#include "google_apis/gaia/gaia_auth_util.h" 30 31SessionStateDelegateChromeos::SessionStateDelegateChromeos() 32 : session_state_(SESSION_STATE_LOGIN_PRIMARY) { 33 user_manager::UserManager::Get()->AddSessionStateObserver(this); 34 chromeos::UserAddingScreen::Get()->AddObserver(this); 35 36 // LoginState is not initialized in unit_tests. 37 if (chromeos::LoginState::IsInitialized()) { 38 chromeos::LoginState::Get()->AddObserver(this); 39 SetSessionState(chromeos::LoginState::Get()->IsUserLoggedIn() ? 40 SESSION_STATE_ACTIVE : SESSION_STATE_LOGIN_PRIMARY, true); 41 } 42} 43 44SessionStateDelegateChromeos::~SessionStateDelegateChromeos() { 45 user_manager::UserManager::Get()->RemoveSessionStateObserver(this); 46 chromeos::UserAddingScreen::Get()->RemoveObserver(this); 47 48 // LoginState is not initialized in unit_tests. 49 if (chromeos::LoginState::IsInitialized()) 50 chromeos::LoginState::Get()->RemoveObserver(this); 51} 52 53content::BrowserContext* SessionStateDelegateChromeos::GetBrowserContextByIndex( 54 ash::MultiProfileIndex index) { 55 DCHECK_LT(index, NumberOfLoggedInUsers()); 56 user_manager::User* user = 57 user_manager::UserManager::Get()->GetLRULoggedInUsers()[index]; 58 CHECK(user); 59 return chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); 60} 61 62content::BrowserContext* 63SessionStateDelegateChromeos::GetBrowserContextForWindow( 64 aura::Window* window) { 65 const std::string& user_id = 66 chrome::MultiUserWindowManager::GetInstance()->GetWindowOwner(window); 67 const user_manager::User* user = 68 user_manager::UserManager::Get()->FindUser(user_id); 69 DCHECK(user); 70 return chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); 71} 72 73int SessionStateDelegateChromeos::GetMaximumNumberOfLoggedInUsers() const { 74 // We limit list of logged in users to 10 due to memory constraints. 75 // Note that 10 seems excessive, but we want to test how many users are 76 // actually added to a session. 77 // TODO(nkostylev): Adjust this limitation based on device capabilites. 78 // http://crbug.com/230865 79 return 10; 80} 81 82int SessionStateDelegateChromeos::NumberOfLoggedInUsers() const { 83 return user_manager::UserManager::Get()->GetLoggedInUsers().size(); 84} 85 86bool SessionStateDelegateChromeos::CanAddUserToMultiProfile( 87 AddUserError* error) const { 88 if (user_manager::UserManager::Get() 89 ->GetUsersAdmittedForMultiProfile() 90 .size() == 0) { 91 if (error) 92 *error = ADD_USER_ERROR_OUT_OF_USERS; 93 return false; 94 } 95 return SessionStateDelegate::CanAddUserToMultiProfile(error); 96} 97 98bool SessionStateDelegateChromeos::IsActiveUserSessionStarted() const { 99 return user_manager::UserManager::Get()->IsSessionStarted(); 100} 101 102bool SessionStateDelegateChromeos::CanLockScreen() const { 103 const user_manager::UserList unlock_users = 104 user_manager::UserManager::Get()->GetUnlockUsers(); 105 return !unlock_users.empty(); 106} 107 108bool SessionStateDelegateChromeos::IsScreenLocked() const { 109 return chromeos::ScreenLocker::default_screen_locker() && 110 chromeos::ScreenLocker::default_screen_locker()->locked(); 111} 112 113bool SessionStateDelegateChromeos::ShouldLockScreenBeforeSuspending() const { 114 const user_manager::UserList logged_in_users = 115 user_manager::UserManager::Get()->GetLoggedInUsers(); 116 for (user_manager::UserList::const_iterator it = logged_in_users.begin(); 117 it != logged_in_users.end(); 118 ++it) { 119 user_manager::User* user = (*it); 120 Profile* profile = 121 chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); 122 if (profile->GetPrefs()->GetBoolean(prefs::kEnableAutoScreenLock)) 123 return true; 124 } 125 return false; 126} 127 128void SessionStateDelegateChromeos::LockScreen() { 129 if (!CanLockScreen()) 130 return; 131 132 VLOG(1) << "Requesting screen lock from SessionStateDelegate"; 133 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()-> 134 RequestLockScreen(); 135} 136 137void SessionStateDelegateChromeos::UnlockScreen() { 138 // This is used only for testing thus far. 139 NOTIMPLEMENTED(); 140} 141 142bool SessionStateDelegateChromeos::IsUserSessionBlocked() const { 143 bool has_login_manager = CommandLine::ForCurrentProcess()->HasSwitch( 144 chromeos::switches::kLoginManager); 145 return (has_login_manager && !IsActiveUserSessionStarted()) || 146 IsScreenLocked() || 147 chromeos::UserAddingScreen::Get()->IsRunning(); 148} 149 150ash::SessionStateDelegate::SessionState 151SessionStateDelegateChromeos::GetSessionState() const { 152 return session_state_; 153} 154 155const user_manager::UserInfo* SessionStateDelegateChromeos::GetUserInfo( 156 ash::MultiProfileIndex index) const { 157 DCHECK_LT(index, NumberOfLoggedInUsers()); 158 return user_manager::UserManager::Get()->GetLRULoggedInUsers()[index]; 159} 160 161const user_manager::UserInfo* SessionStateDelegateChromeos::GetUserInfo( 162 content::BrowserContext* context) const { 163 DCHECK(context); 164 return chromeos::ProfileHelper::Get()->GetUserByProfile( 165 Profile::FromBrowserContext(context)); 166} 167 168bool SessionStateDelegateChromeos::ShouldShowAvatar( 169 aura::Window* window) const { 170 return chrome::MultiUserWindowManager::GetInstance()-> 171 ShouldShowAvatar(window); 172} 173 174void SessionStateDelegateChromeos::SwitchActiveUser( 175 const std::string& user_id) { 176 // Disallow switching to an already active user since that might crash. 177 // Also check that we got a user id and not an email address. 178 DCHECK_EQ(user_id, 179 gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_id))); 180 if (user_id == user_manager::UserManager::Get()->GetActiveUser()->email()) 181 return; 182 TryToSwitchUser(user_id); 183} 184 185void SessionStateDelegateChromeos::CycleActiveUser(CycleUser cycle_user) { 186 // Make sure there is a user to switch to. 187 if (NumberOfLoggedInUsers() <= 1) 188 return; 189 190 const user_manager::UserList& logged_in_users = 191 user_manager::UserManager::Get()->GetLoggedInUsers(); 192 193 std::string user_id = 194 user_manager::UserManager::Get()->GetActiveUser()->email(); 195 196 // Get an iterator positioned at the active user. 197 user_manager::UserList::const_iterator it; 198 for (it = logged_in_users.begin(); 199 it != logged_in_users.end(); ++it) { 200 if ((*it)->email() == user_id) 201 break; 202 } 203 204 // Active user not found. 205 if (it == logged_in_users.end()) 206 return; 207 208 // Get the user's email to select, wrapping to the start/end of the list if 209 // necessary. 210 switch (cycle_user) { 211 case CYCLE_TO_NEXT_USER: 212 if (++it == logged_in_users.end()) 213 user_id = (*logged_in_users.begin())->email(); 214 else 215 user_id = (*it)->email(); 216 break; 217 case CYCLE_TO_PREVIOUS_USER: 218 if (it == logged_in_users.begin()) 219 it = logged_in_users.end(); 220 user_id = (*(--it))->email(); 221 break; 222 } 223 224 // Switch using the transformed |user_id|. 225 TryToSwitchUser(user_id); 226} 227 228bool SessionStateDelegateChromeos::IsMultiProfileAllowedByPrimaryUserPolicy() 229 const { 230 return chromeos::MultiProfileUserController::GetPrimaryUserPolicy() == 231 chromeos::MultiProfileUserController::ALLOWED; 232} 233 234void SessionStateDelegateChromeos::AddSessionStateObserver( 235 ash::SessionStateObserver* observer) { 236 session_state_observer_list_.AddObserver(observer); 237} 238 239void SessionStateDelegateChromeos::RemoveSessionStateObserver( 240 ash::SessionStateObserver* observer) { 241 session_state_observer_list_.RemoveObserver(observer); 242} 243 244void SessionStateDelegateChromeos::LoggedInStateChanged() { 245 SetSessionState(chromeos::LoginState::Get()->IsUserLoggedIn() ? 246 SESSION_STATE_ACTIVE : SESSION_STATE_LOGIN_PRIMARY, false); 247} 248 249void SessionStateDelegateChromeos::ActiveUserChanged( 250 const user_manager::User* active_user) { 251 FOR_EACH_OBSERVER(ash::SessionStateObserver, 252 session_state_observer_list_, 253 ActiveUserChanged(active_user->email())); 254} 255 256void SessionStateDelegateChromeos::UserAddedToSession( 257 const user_manager::User* added_user) { 258 FOR_EACH_OBSERVER(ash::SessionStateObserver, 259 session_state_observer_list_, 260 UserAddedToSession(added_user->email())); 261} 262 263void SessionStateDelegateChromeos::OnUserAddingStarted() { 264 SetSessionState(SESSION_STATE_LOGIN_SECONDARY, false); 265} 266 267void SessionStateDelegateChromeos::OnUserAddingFinished() { 268 SetSessionState(SESSION_STATE_ACTIVE, false); 269} 270 271void SessionStateDelegateChromeos::SetSessionState(SessionState new_state, 272 bool force) { 273 if (session_state_ == new_state && !force) 274 return; 275 276 session_state_ = new_state; 277 NotifySessionStateChanged(); 278} 279 280void SessionStateDelegateChromeos::NotifySessionStateChanged() { 281 FOR_EACH_OBSERVER(ash::SessionStateObserver, 282 session_state_observer_list_, 283 SessionStateChanged(session_state_)); 284} 285 286void DoSwitchUser(const std::string& user_id) { 287 user_manager::UserManager::Get()->SwitchActiveUser(user_id); 288} 289 290void SessionStateDelegateChromeos::TryToSwitchUser( 291 const std::string& user_id) { 292 ash::TrySwitchingActiveUser(base::Bind(&DoSwitchUser, user_id)); 293} 294