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