| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/login/screens/user_selection_screen.h" |
| |
| #include "ash/shell.h" |
| #include "base/logging.h" |
| #include "base/prefs/pref_service.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" |
| #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" |
| #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| #include "chrome/browser/signin/screenlock_bridge.h" |
| #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/user_manager/user_type.h" |
| #include "ui/wm/core/user_activity_detector.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| // User dictionary keys. |
| const char kKeyUsername[] = "username"; |
| const char kKeyDisplayName[] = "displayName"; |
| const char kKeyEmailAddress[] = "emailAddress"; |
| const char kKeyEnterpriseDomain[] = "enterpriseDomain"; |
| const char kKeyPublicAccount[] = "publicAccount"; |
| const char kKeyLocallyManagedUser[] = "locallyManagedUser"; |
| const char kKeySignedIn[] = "signedIn"; |
| const char kKeyCanRemove[] = "canRemove"; |
| const char kKeyIsOwner[] = "isOwner"; |
| const char kKeyInitialAuthType[] = "initialAuthType"; |
| const char kKeyMultiProfilesAllowed[] = "isMultiProfilesAllowed"; |
| const char kKeyMultiProfilesPolicy[] = "multiProfilesPolicy"; |
| |
| // Max number of users to show. |
| // Please keep synced with one in signin_userlist_unittest.cc. |
| const size_t kMaxUsers = 18; |
| |
| const int kPasswordClearTimeoutSec = 60; |
| |
| } // namespace |
| |
| UserSelectionScreen::UserSelectionScreen() : handler_(NULL) { |
| } |
| |
| UserSelectionScreen::~UserSelectionScreen() { |
| wm::UserActivityDetector* activity_detector = |
| ash::Shell::GetInstance()->user_activity_detector(); |
| if (activity_detector->HasObserver(this)) |
| activity_detector->RemoveObserver(this); |
| } |
| |
| // static |
| void UserSelectionScreen::FillUserDictionary( |
| User* user, |
| bool is_owner, |
| bool is_signin_to_add, |
| ScreenlockBridge::LockHandler::AuthType auth_type, |
| base::DictionaryValue* user_dict) { |
| const std::string& user_id = user->email(); |
| const bool is_public_account = |
| user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT; |
| const bool is_locally_managed_user = |
| user->GetType() == user_manager::USER_TYPE_LOCALLY_MANAGED; |
| |
| user_dict->SetString(kKeyUsername, user_id); |
| user_dict->SetString(kKeyEmailAddress, user->display_email()); |
| user_dict->SetString(kKeyDisplayName, user->GetDisplayName()); |
| user_dict->SetBoolean(kKeyPublicAccount, is_public_account); |
| user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user); |
| user_dict->SetInteger(kKeyInitialAuthType, auth_type); |
| user_dict->SetBoolean(kKeySignedIn, user->is_logged_in()); |
| user_dict->SetBoolean(kKeyIsOwner, is_owner); |
| |
| // Fill in multi-profiles related fields. |
| if (is_signin_to_add) { |
| MultiProfileUserController* multi_profile_user_controller = |
| UserManager::Get()->GetMultiProfileUserController(); |
| std::string behavior = |
| multi_profile_user_controller->GetCachedValue(user_id); |
| user_dict->SetBoolean(kKeyMultiProfilesAllowed, |
| multi_profile_user_controller->IsUserAllowedInSession( |
| user_id) == MultiProfileUserController::ALLOWED); |
| user_dict->SetString(kKeyMultiProfilesPolicy, behavior); |
| } else { |
| user_dict->SetBoolean(kKeyMultiProfilesAllowed, true); |
| } |
| |
| if (is_public_account) { |
| policy::BrowserPolicyConnectorChromeOS* policy_connector = |
| g_browser_process->platform_part()->browser_policy_connector_chromeos(); |
| |
| if (policy_connector->IsEnterpriseManaged()) { |
| user_dict->SetString(kKeyEnterpriseDomain, |
| policy_connector->GetEnterpriseDomain()); |
| } |
| } |
| } |
| |
| // static |
| bool UserSelectionScreen::ShouldForceOnlineSignIn(const User* user) { |
| // Public sessions are always allowed to log in offline. |
| // Supervised user are allowed to log in offline if their OAuth token status |
| // is unknown or valid. |
| // For all other users, force online sign in if: |
| // * The flag to force online sign-in is set for the user. |
| // * The user's OAuth token is invalid. |
| // * The user's OAuth token status is unknown (except supervised users, |
| // see above). |
| if (user->is_logged_in()) |
| return false; |
| |
| const User::OAuthTokenStatus token_status = user->oauth_token_status(); |
| const bool is_locally_managed_user = |
| user->GetType() == user_manager::USER_TYPE_LOCALLY_MANAGED; |
| const bool is_public_session = |
| user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT; |
| |
| if (is_locally_managed_user && |
| token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN) { |
| return false; |
| } |
| |
| if (is_public_session) |
| return false; |
| |
| return user->force_online_signin() || |
| (token_status == User::OAUTH2_TOKEN_STATUS_INVALID) || |
| (token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN); |
| } |
| |
| void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) { |
| handler_ = handler; |
| } |
| |
| void UserSelectionScreen::Init(const UserList& users, bool show_guest) { |
| users_ = users; |
| show_guest_ = show_guest; |
| |
| wm::UserActivityDetector* activity_detector = |
| ash::Shell::GetInstance()->user_activity_detector(); |
| if (!activity_detector->HasObserver(this)) |
| activity_detector->AddObserver(this); |
| } |
| |
| void UserSelectionScreen::OnBeforeUserRemoved(const std::string& username) { |
| for (UserList::iterator it = users_.begin(); it != users_.end(); ++it) { |
| if ((*it)->email() == username) { |
| users_.erase(it); |
| break; |
| } |
| } |
| } |
| |
| void UserSelectionScreen::OnUserRemoved(const std::string& username) { |
| if (!handler_) |
| return; |
| |
| handler_->OnUserRemoved(username); |
| } |
| |
| void UserSelectionScreen::OnUserImageChanged(const User& user) { |
| if (!handler_) |
| return; |
| handler_->OnUserImageChanged(user); |
| // TODO(antrim) : updateUserImage(user.email()) |
| } |
| |
| const UserList& UserSelectionScreen::GetUsers() const { |
| return users_; |
| } |
| |
| void UserSelectionScreen::OnPasswordClearTimerExpired() { |
| if (handler_) |
| handler_->ClearUserPodPassword(); |
| } |
| |
| void UserSelectionScreen::OnUserActivity(const ui::Event* event) { |
| if (!password_clear_timer_.IsRunning()) { |
| password_clear_timer_.Start( |
| FROM_HERE, |
| base::TimeDelta::FromSeconds(kPasswordClearTimeoutSec), |
| this, |
| &UserSelectionScreen::OnPasswordClearTimerExpired); |
| } |
| password_clear_timer_.Reset(); |
| } |
| |
| // static |
| const UserList UserSelectionScreen::PrepareUserListForSending( |
| const UserList& users, |
| std::string owner, |
| bool is_signin_to_add) { |
| |
| UserList users_to_send; |
| bool has_owner = owner.size() > 0; |
| size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers; |
| size_t non_owner_count = 0; |
| |
| for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { |
| const std::string& user_id = (*it)->email(); |
| bool is_owner = (user_id == owner); |
| bool is_public_account = |
| ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT); |
| |
| if ((is_public_account && !is_signin_to_add) || is_owner || |
| (!is_public_account && non_owner_count < max_non_owner_users)) { |
| |
| if (!is_owner) |
| ++non_owner_count; |
| if (is_owner && users_to_send.size() > kMaxUsers) { |
| // Owner is always in the list. |
| users_to_send.insert(users_to_send.begin() + (kMaxUsers - 1), *it); |
| while (users_to_send.size() > kMaxUsers) |
| users_to_send.erase(users_to_send.begin() + kMaxUsers); |
| } else if (users_to_send.size() < kMaxUsers) { |
| users_to_send.push_back(*it); |
| } |
| } |
| } |
| return users_to_send; |
| } |
| |
| void UserSelectionScreen::SendUserList() { |
| base::ListValue users_list; |
| const UserList& users = GetUsers(); |
| |
| // TODO(nkostylev): Move to a separate method in UserManager. |
| // http://crbug.com/230852 |
| bool single_user = users.size() == 1; |
| bool is_signin_to_add = LoginDisplayHostImpl::default_host() && |
| UserManager::Get()->IsUserLoggedIn(); |
| std::string owner; |
| chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner); |
| |
| policy::BrowserPolicyConnectorChromeOS* connector = |
| g_browser_process->platform_part()->browser_policy_connector_chromeos(); |
| bool is_enterprise_managed = connector->IsEnterpriseManaged(); |
| |
| const UserList users_to_send = PrepareUserListForSending(users, |
| owner, |
| is_signin_to_add); |
| |
| user_auth_type_map_.clear(); |
| |
| for (UserList::const_iterator it = users_to_send.begin(); |
| it != users_to_send.end(); |
| ++it) { |
| const std::string& user_id = (*it)->email(); |
| bool is_owner = (user_id == owner); |
| const bool is_public_account = |
| ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT); |
| const ScreenlockBridge::LockHandler::AuthType initial_auth_type = |
| is_public_account |
| ? ScreenlockBridge::LockHandler::EXPAND_THEN_USER_CLICK |
| : (ShouldForceOnlineSignIn(*it) |
| ? ScreenlockBridge::LockHandler::ONLINE_SIGN_IN |
| : ScreenlockBridge::LockHandler::OFFLINE_PASSWORD); |
| user_auth_type_map_[user_id] = initial_auth_type; |
| |
| base::DictionaryValue* user_dict = new base::DictionaryValue(); |
| FillUserDictionary( |
| *it, is_owner, is_signin_to_add, initial_auth_type, user_dict); |
| bool signed_in = (*it)->is_logged_in(); |
| // Single user check here is necessary because owner info might not be |
| // available when running into login screen on first boot. |
| // See http://crosbug.com/12723 |
| bool can_remove_user = |
| ((!single_user || is_enterprise_managed) && !user_id.empty() && |
| !is_owner && !is_public_account && !signed_in && !is_signin_to_add); |
| user_dict->SetBoolean(kKeyCanRemove, can_remove_user); |
| users_list.Append(user_dict); |
| } |
| |
| handler_->LoadUsers(users_list, show_guest_); |
| } |
| |
| void UserSelectionScreen::HandleGetUsers() { |
| SendUserList(); |
| } |
| |
| void UserSelectionScreen::SetAuthType( |
| const std::string& username, |
| ScreenlockBridge::LockHandler::AuthType auth_type) { |
| user_auth_type_map_[username] = auth_type; |
| } |
| |
| ScreenlockBridge::LockHandler::AuthType UserSelectionScreen::GetAuthType( |
| const std::string& username) const { |
| if (user_auth_type_map_.find(username) == user_auth_type_map_.end()) |
| return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; |
| return user_auth_type_map_.find(username)->second; |
| } |
| |
| } // namespace chromeos |