user_selection_screen.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright 2014 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/login/screens/user_selection_screen.h"
6
7#include "ash/shell.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/login/ui/login_display_host_impl.h"
12#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
13#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
14#include "chrome/browser/signin/screenlock_bridge.h"
15#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
16#include "chrome/common/pref_names.h"
17#include "ui/wm/core/user_activity_detector.h"
18
19namespace chromeos {
20
21namespace {
22
23// User dictionary keys.
24const char kKeyUsername[] = "username";
25const char kKeyDisplayName[] = "displayName";
26const char kKeyEmailAddress[] = "emailAddress";
27const char kKeyEnterpriseDomain[] = "enterpriseDomain";
28const char kKeyPublicAccount[] = "publicAccount";
29const char kKeyLocallyManagedUser[] = "locallyManagedUser";
30const char kKeySignedIn[] = "signedIn";
31const char kKeyCanRemove[] = "canRemove";
32const char kKeyIsOwner[] = "isOwner";
33const char kKeyInitialAuthType[] = "initialAuthType";
34const char kKeyMultiProfilesAllowed[] = "isMultiProfilesAllowed";
35const char kKeyMultiProfilesPolicy[] = "multiProfilesPolicy";
36
37// Max number of users to show.
38const size_t kMaxUsers = 18;
39
40const int kPasswordClearTimeoutSec = 60;
41
42}  // namespace
43
44UserSelectionScreen::UserSelectionScreen() : handler_(NULL) {
45}
46
47UserSelectionScreen::~UserSelectionScreen() {
48  wm::UserActivityDetector* activity_detector =
49      ash::Shell::GetInstance()->user_activity_detector();
50  if (activity_detector->HasObserver(this))
51    activity_detector->RemoveObserver(this);
52}
53
54// static
55void UserSelectionScreen::FillUserDictionary(
56    User* user,
57    bool is_owner,
58    bool is_signin_to_add,
59    ScreenlockBridge::LockHandler::AuthType auth_type,
60    base::DictionaryValue* user_dict) {
61  const std::string& user_id = user->email();
62  const bool is_public_account =
63      user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
64  const bool is_locally_managed_user =
65      user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
66
67  user_dict->SetString(kKeyUsername, user_id);
68  user_dict->SetString(kKeyEmailAddress, user->display_email());
69  user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
70  user_dict->SetBoolean(kKeyPublicAccount, is_public_account);
71  user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user);
72  user_dict->SetInteger(kKeyInitialAuthType, auth_type);
73  user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
74  user_dict->SetBoolean(kKeyIsOwner, is_owner);
75
76  // Fill in multi-profiles related fields.
77  if (is_signin_to_add) {
78    MultiProfileUserController* multi_profile_user_controller =
79        UserManager::Get()->GetMultiProfileUserController();
80    std::string behavior =
81        multi_profile_user_controller->GetCachedValue(user_id);
82    user_dict->SetBoolean(kKeyMultiProfilesAllowed,
83                          multi_profile_user_controller->IsUserAllowedInSession(
84                              user_id) == MultiProfileUserController::ALLOWED);
85    user_dict->SetString(kKeyMultiProfilesPolicy, behavior);
86  } else {
87    user_dict->SetBoolean(kKeyMultiProfilesAllowed, true);
88  }
89
90  if (is_public_account) {
91    policy::BrowserPolicyConnectorChromeOS* policy_connector =
92        g_browser_process->platform_part()->browser_policy_connector_chromeos();
93
94    if (policy_connector->IsEnterpriseManaged()) {
95      user_dict->SetString(kKeyEnterpriseDomain,
96                           policy_connector->GetEnterpriseDomain());
97    }
98  }
99}
100
101// static
102bool UserSelectionScreen::ShouldForceOnlineSignIn(const User* user) {
103  // Public sessions are always allowed to log in offline.
104  // Supervised user are allowed to log in offline if their OAuth token status
105  // is unknown or valid.
106  // For all other users, force online sign in if:
107  // * The flag to force online sign-in is set for the user.
108  // * The user's OAuth token is invalid.
109  // * The user's OAuth token status is unknown (except supervised users,
110  //   see above).
111  if (user->is_logged_in())
112    return false;
113
114  const User::OAuthTokenStatus token_status = user->oauth_token_status();
115  const bool is_locally_managed_user =
116      user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
117  const bool is_public_session =
118      user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
119
120  if (is_locally_managed_user &&
121      token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN) {
122    return false;
123  }
124
125  if (is_public_session)
126    return false;
127
128  return user->force_online_signin() ||
129         (token_status == User::OAUTH2_TOKEN_STATUS_INVALID) ||
130         (token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN);
131}
132
133void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) {
134  handler_ = handler;
135}
136
137void UserSelectionScreen::Init(const UserList& users, bool show_guest) {
138  users_ = users;
139  show_guest_ = show_guest;
140
141  wm::UserActivityDetector* activity_detector =
142      ash::Shell::GetInstance()->user_activity_detector();
143  if (!activity_detector->HasObserver(this))
144    activity_detector->AddObserver(this);
145}
146
147void UserSelectionScreen::OnBeforeUserRemoved(const std::string& username) {
148  for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) {
149    if ((*it)->email() == username) {
150      users_.erase(it);
151      break;
152    }
153  }
154}
155
156void UserSelectionScreen::OnUserRemoved(const std::string& username) {
157  if (!handler_)
158    return;
159
160  handler_->OnUserRemoved(username);
161}
162
163void UserSelectionScreen::OnUserImageChanged(const User& user) {
164  if (!handler_)
165    return;
166  handler_->OnUserImageChanged(user);
167  // TODO(antrim) : updateUserImage(user.email())
168}
169
170const UserList& UserSelectionScreen::GetUsers() const {
171  return users_;
172}
173
174void UserSelectionScreen::OnPasswordClearTimerExpired() {
175  if (handler_)
176    handler_->ClearUserPodPassword();
177}
178
179void UserSelectionScreen::OnUserActivity(const ui::Event* event) {
180  if (!password_clear_timer_.IsRunning()) {
181    password_clear_timer_.Start(
182        FROM_HERE,
183        base::TimeDelta::FromSeconds(kPasswordClearTimeoutSec),
184        this,
185        &UserSelectionScreen::OnPasswordClearTimerExpired);
186  }
187  password_clear_timer_.Reset();
188}
189
190void UserSelectionScreen::SendUserList(bool animated) {
191  base::ListValue users_list;
192  const UserList& users = GetUsers();
193
194  // TODO(nkostylev): Move to a separate method in UserManager.
195  // http://crbug.com/230852
196  bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
197                          UserManager::Get()->IsUserLoggedIn();
198
199  user_auth_type_map_.clear();
200
201  bool single_user = users.size() == 1;
202  std::string owner;
203  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
204  bool has_owner = owner.size() > 0;
205  size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers;
206  size_t non_owner_count = 0;
207
208  policy::BrowserPolicyConnectorChromeOS* connector =
209      g_browser_process->platform_part()->browser_policy_connector_chromeos();
210
211  bool is_enterprise_managed = connector->IsEnterpriseManaged();
212
213  for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
214    const std::string& user_id = (*it)->email();
215    bool is_owner = (user_id == owner);
216    bool is_public_account =
217        ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
218
219    if ((is_public_account && !is_signin_to_add) || is_owner ||
220        (!is_public_account && non_owner_count < max_non_owner_users)) {
221      ScreenlockBridge::LockHandler::AuthType initial_auth_type =
222          ShouldForceOnlineSignIn(*it)
223              ? ScreenlockBridge::LockHandler::ONLINE_SIGN_IN
224              : ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
225      user_auth_type_map_[user_id] = initial_auth_type;
226
227      base::DictionaryValue* user_dict = new base::DictionaryValue();
228      FillUserDictionary(
229          *it, is_owner, is_signin_to_add, initial_auth_type, user_dict);
230      bool signed_in = (*it)->is_logged_in();
231      // Single user check here is necessary because owner info might not be
232      // available when running into login screen on first boot.
233      // See http://crosbug.com/12723
234      bool can_remove_user =
235          ((!single_user || is_enterprise_managed) && !user_id.empty() &&
236           !is_owner && !is_public_account && !signed_in && !is_signin_to_add);
237      user_dict->SetBoolean(kKeyCanRemove, can_remove_user);
238
239      if (!is_owner)
240        ++non_owner_count;
241      if (is_owner && users_list.GetSize() > kMaxUsers) {
242        // Owner is always in the list.
243        users_list.Insert(kMaxUsers - 1, user_dict);
244        while (users_list.GetSize() > kMaxUsers)
245          users_list.Remove(kMaxUsers, NULL);
246      } else if (users_list.GetSize() < kMaxUsers) {
247        users_list.Append(user_dict);
248      }
249    }
250  }
251
252  handler_->LoadUsers(users_list, animated, show_guest_);
253}
254
255void UserSelectionScreen::HandleGetUsers() {
256  SendUserList(false);
257}
258
259void UserSelectionScreen::SetAuthType(
260    const std::string& username,
261    ScreenlockBridge::LockHandler::AuthType auth_type) {
262  user_auth_type_map_[username] = auth_type;
263}
264
265ScreenlockBridge::LockHandler::AuthType UserSelectionScreen::GetAuthType(
266    const std::string& username) const {
267  if (user_auth_type_map_.find(username) == user_auth_type_map_.end())
268    return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
269  return user_auth_type_map_.find(username)->second;
270}
271
272}  // namespace chromeos
273