Home | History | Annotate | Download | only in ash
      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