Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / screens / user_selection_screen.cc
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 "base/location.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/values.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/browser_process_platform_part.h"
13 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
14 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
15 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
16 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
17 #include "chrome/browser/signin/screenlock_bridge.h"
18 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
19 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
20 #include "components/user_manager/user_manager.h"
21 #include "components/user_manager/user_type.h"
22 #include "ui/wm/core/user_activity_detector.h"
23
24 namespace chromeos {
25
26 namespace {
27
28 // User dictionary keys.
29 const char kKeyUsername[] = "username";
30 const char kKeyDisplayName[] = "displayName";
31 const char kKeyEmailAddress[] = "emailAddress";
32 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
33 const char kKeyPublicAccount[] = "publicAccount";
34 const char kKeySupervisedUser[] = "supervisedUser";
35 const char kKeySignedIn[] = "signedIn";
36 const char kKeyCanRemove[] = "canRemove";
37 const char kKeyIsOwner[] = "isOwner";
38 const char kKeyInitialAuthType[] = "initialAuthType";
39 const char kKeyMultiProfilesAllowed[] = "isMultiProfilesAllowed";
40 const char kKeyMultiProfilesPolicy[] = "multiProfilesPolicy";
41 const char kKeyInitialLocales[] = "initialLocales";
42 const char kKeyInitialLocale[] = "initialLocale";
43 const char kKeyInitialMultipleRecommendedLocales[] =
44     "initialMultipleRecommendedLocales";
45 const char kKeyInitialKeyboardLayout[] = "initialKeyboardLayout";
46
47 // Max number of users to show.
48 // Please keep synced with one in signin_userlist_unittest.cc.
49 const size_t kMaxUsers = 18;
50
51 const int kPasswordClearTimeoutSec = 60;
52
53 void AddPublicSessionDetailsToUserDictionaryEntry(
54     base::DictionaryValue* user_dict,
55     const std::vector<std::string>* public_session_recommended_locales) {
56   policy::BrowserPolicyConnectorChromeOS* policy_connector =
57       g_browser_process->platform_part()->browser_policy_connector_chromeos();
58
59   if (policy_connector->IsEnterpriseManaged()) {
60     user_dict->SetString(kKeyEnterpriseDomain,
61                          policy_connector->GetEnterpriseDomain());
62   }
63
64   std::vector<std::string> kEmptyRecommendedLocales;
65   const std::vector<std::string>& recommended_locales =
66       public_session_recommended_locales ?
67           *public_session_recommended_locales : kEmptyRecommendedLocales;
68
69   // Construct the list of available locales. This list consists of the
70   // recommended locales, followed by all others.
71   scoped_ptr<base::ListValue> available_locales =
72       GetUILanguageList(&recommended_locales, std::string());
73
74   // Select the the first recommended locale that is actually available or the
75   // current UI locale if none of them are available.
76   const std::string selected_locale = FindMostRelevantLocale(
77       recommended_locales,
78       *available_locales.get(),
79       g_browser_process->GetApplicationLocale());
80
81   // Set |kKeyInitialLocales| to the list of available locales.
82   user_dict->Set(kKeyInitialLocales, available_locales.release());
83
84   // Set |kKeyInitialLocale| to the initially selected locale.
85   user_dict->SetString(kKeyInitialLocale, selected_locale);
86
87   // Set |kKeyInitialMultipleRecommendedLocales| to indicate whether the list
88   // of recommended locales contains at least two entries. This is used to
89   // decide whether the public session pod expands to its basic form (for zero
90   // or one recommended locales) or the advanced form (two or more recommended
91   // locales).
92   user_dict->SetBoolean(kKeyInitialMultipleRecommendedLocales,
93                         recommended_locales.size() >= 2);
94
95   // Set |kKeyInitialKeyboardLayout| to the current keyboard layout. This
96   // value will be used temporarily only because the UI immediately requests a
97   // list of keyboard layouts suitable for the currently selected locale.
98   user_dict->Set(kKeyInitialKeyboardLayout,
99                  GetCurrentKeyboardLayout().release());
100 }
101
102 }  // namespace
103
104 UserSelectionScreen::UserSelectionScreen() : handler_(NULL) {
105 }
106
107 UserSelectionScreen::~UserSelectionScreen() {
108   wm::UserActivityDetector* activity_detector = wm::UserActivityDetector::Get();
109   if (activity_detector->HasObserver(this))
110     activity_detector->RemoveObserver(this);
111 }
112
113 // static
114 void UserSelectionScreen::FillUserDictionary(
115     user_manager::User* user,
116     bool is_owner,
117     bool is_signin_to_add,
118     ScreenlockBridge::LockHandler::AuthType auth_type,
119     const std::vector<std::string>* public_session_recommended_locales,
120     base::DictionaryValue* user_dict) {
121   const std::string& user_id = user->email();
122   const bool is_public_session =
123       user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
124   const bool is_supervised_user =
125       user->GetType() == user_manager::USER_TYPE_SUPERVISED;
126
127   user_dict->SetString(kKeyUsername, user_id);
128   user_dict->SetString(kKeyEmailAddress, user->display_email());
129   user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
130   user_dict->SetBoolean(kKeyPublicAccount, is_public_session);
131   user_dict->SetBoolean(kKeySupervisedUser, is_supervised_user);
132   user_dict->SetInteger(kKeyInitialAuthType, auth_type);
133   user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
134   user_dict->SetBoolean(kKeyIsOwner, is_owner);
135
136   // Fill in multi-profiles related fields.
137   if (is_signin_to_add) {
138     MultiProfileUserController* multi_profile_user_controller =
139         ChromeUserManager::Get()->GetMultiProfileUserController();
140     MultiProfileUserController::UserAllowedInSessionReason isUserAllowedReason;
141     bool isUserAllowed = multi_profile_user_controller->IsUserAllowedInSession(
142         user_id, &isUserAllowedReason);
143     user_dict->SetBoolean(kKeyMultiProfilesAllowed, isUserAllowed);
144
145     std::string behavior;
146     switch (isUserAllowedReason) {
147       case MultiProfileUserController::NOT_ALLOWED_OWNER_AS_SECONDARY:
148         behavior = MultiProfileUserController::kBehaviorOwnerPrimaryOnly;
149         break;
150       default:
151         behavior = multi_profile_user_controller->GetCachedValue(user_id);
152     }
153     user_dict->SetString(kKeyMultiProfilesPolicy, behavior);
154   } else {
155     user_dict->SetBoolean(kKeyMultiProfilesAllowed, true);
156   }
157
158   if (is_public_session) {
159     AddPublicSessionDetailsToUserDictionaryEntry(
160         user_dict,
161         public_session_recommended_locales);
162   }
163 }
164
165 // static
166 bool UserSelectionScreen::ShouldForceOnlineSignIn(
167     const user_manager::User* user) {
168   // Public sessions are always allowed to log in offline.
169   // Supervised user are allowed to log in offline if their OAuth token status
170   // is unknown or valid.
171   // For all other users, force online sign in if:
172   // * The flag to force online sign-in is set for the user.
173   // * The user's OAuth token is invalid.
174   // * The user's OAuth token status is unknown (except supervised users,
175   //   see above).
176   if (user->is_logged_in())
177     return false;
178
179   const user_manager::User::OAuthTokenStatus token_status =
180       user->oauth_token_status();
181   const bool is_supervised_user =
182       user->GetType() == user_manager::USER_TYPE_SUPERVISED;
183   const bool is_public_session =
184       user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
185
186   if (is_supervised_user &&
187       token_status == user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN) {
188     return false;
189   }
190
191   if (is_public_session)
192     return false;
193
194   return user->force_online_signin() ||
195          (token_status == user_manager::User::OAUTH2_TOKEN_STATUS_INVALID) ||
196          (token_status == user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN);
197 }
198
199 void UserSelectionScreen::SetHandler(LoginDisplayWebUIHandler* handler) {
200   handler_ = handler;
201 }
202
203 void UserSelectionScreen::Init(const user_manager::UserList& users,
204                                bool show_guest) {
205   users_ = users;
206   show_guest_ = show_guest;
207
208   wm::UserActivityDetector* activity_detector = wm::UserActivityDetector::Get();
209   if (!activity_detector->HasObserver(this))
210     activity_detector->AddObserver(this);
211 }
212
213 void UserSelectionScreen::OnBeforeUserRemoved(const std::string& username) {
214   for (user_manager::UserList::iterator it = users_.begin(); it != users_.end();
215        ++it) {
216     if ((*it)->email() == username) {
217       users_.erase(it);
218       break;
219     }
220   }
221 }
222
223 void UserSelectionScreen::OnUserRemoved(const std::string& username) {
224   if (!handler_)
225     return;
226
227   handler_->OnUserRemoved(username);
228 }
229
230 void UserSelectionScreen::OnUserImageChanged(const user_manager::User& user) {
231   if (!handler_)
232     return;
233   handler_->OnUserImageChanged(user);
234   // TODO(antrim) : updateUserImage(user.email())
235 }
236
237 const user_manager::UserList& UserSelectionScreen::GetUsers() const {
238   return users_;
239 }
240
241 void UserSelectionScreen::OnPasswordClearTimerExpired() {
242   if (handler_)
243     handler_->ClearUserPodPassword();
244 }
245
246 void UserSelectionScreen::OnUserActivity(const ui::Event* event) {
247   if (!password_clear_timer_.IsRunning()) {
248     password_clear_timer_.Start(
249         FROM_HERE,
250         base::TimeDelta::FromSeconds(kPasswordClearTimeoutSec),
251         this,
252         &UserSelectionScreen::OnPasswordClearTimerExpired);
253   }
254   password_clear_timer_.Reset();
255 }
256
257 // static
258 const user_manager::UserList UserSelectionScreen::PrepareUserListForSending(
259     const user_manager::UserList& users,
260     std::string owner,
261     bool is_signin_to_add) {
262   user_manager::UserList users_to_send;
263   bool has_owner = owner.size() > 0;
264   size_t max_non_owner_users = has_owner ? kMaxUsers - 1 : kMaxUsers;
265   size_t non_owner_count = 0;
266
267   for (user_manager::UserList::const_iterator it = users.begin();
268        it != users.end();
269        ++it) {
270     const std::string& user_id = (*it)->email();
271     bool is_owner = (user_id == owner);
272     bool is_public_account =
273         ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT);
274
275     if ((is_public_account && !is_signin_to_add) || is_owner ||
276         (!is_public_account && non_owner_count < max_non_owner_users)) {
277
278       if (!is_owner)
279         ++non_owner_count;
280       if (is_owner && users_to_send.size() > kMaxUsers) {
281         // Owner is always in the list.
282         users_to_send.insert(users_to_send.begin() + (kMaxUsers - 1), *it);
283         while (users_to_send.size() > kMaxUsers)
284           users_to_send.erase(users_to_send.begin() + kMaxUsers);
285       } else if (users_to_send.size() < kMaxUsers) {
286         users_to_send.push_back(*it);
287       }
288     }
289   }
290   return users_to_send;
291 }
292
293 void UserSelectionScreen::SendUserList() {
294   base::ListValue users_list;
295   const user_manager::UserList& users = GetUsers();
296
297   // TODO(nkostylev): Move to a separate method in UserManager.
298   // http://crbug.com/230852
299   bool single_user = users.size() == 1;
300   bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
301                           user_manager::UserManager::Get()->IsUserLoggedIn();
302   std::string owner;
303   chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
304
305   policy::BrowserPolicyConnectorChromeOS* connector =
306       g_browser_process->platform_part()->browser_policy_connector_chromeos();
307   bool is_enterprise_managed = connector->IsEnterpriseManaged();
308
309   const user_manager::UserList users_to_send =
310       PrepareUserListForSending(users, owner, is_signin_to_add);
311
312   user_auth_type_map_.clear();
313
314   const std::vector<std::string> kEmptyRecommendedLocales;
315   for (user_manager::UserList::const_iterator it = users_to_send.begin();
316        it != users_to_send.end();
317        ++it) {
318     const std::string& user_id = (*it)->email();
319     bool is_owner = (user_id == owner);
320     const bool is_public_account =
321         ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT);
322     const ScreenlockBridge::LockHandler::AuthType initial_auth_type =
323         is_public_account
324             ? ScreenlockBridge::LockHandler::EXPAND_THEN_USER_CLICK
325             : (ShouldForceOnlineSignIn(*it)
326                    ? ScreenlockBridge::LockHandler::ONLINE_SIGN_IN
327                    : ScreenlockBridge::LockHandler::OFFLINE_PASSWORD);
328     user_auth_type_map_[user_id] = initial_auth_type;
329
330     base::DictionaryValue* user_dict = new base::DictionaryValue();
331     const std::vector<std::string>* public_session_recommended_locales =
332         public_session_recommended_locales_.find(user_id) ==
333             public_session_recommended_locales_.end() ?
334                 &kEmptyRecommendedLocales :
335                 &public_session_recommended_locales_[user_id];
336     FillUserDictionary(*it,
337                        is_owner,
338                        is_signin_to_add,
339                        initial_auth_type,
340                        public_session_recommended_locales,
341                        user_dict);
342     bool signed_in = (*it)->is_logged_in();
343     // Single user check here is necessary because owner info might not be
344     // available when running into login screen on first boot.
345     // See http://crosbug.com/12723
346     bool can_remove_user =
347         ((!single_user || is_enterprise_managed) && !user_id.empty() &&
348          !is_owner && !is_public_account && !signed_in && !is_signin_to_add);
349     user_dict->SetBoolean(kKeyCanRemove, can_remove_user);
350     users_list.Append(user_dict);
351   }
352
353   handler_->LoadUsers(users_list, show_guest_);
354 }
355
356 void UserSelectionScreen::HandleGetUsers() {
357   SendUserList();
358 }
359
360 void UserSelectionScreen::SetAuthType(
361     const std::string& username,
362     ScreenlockBridge::LockHandler::AuthType auth_type) {
363   DCHECK(GetAuthType(username) !=
364              ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD ||
365          auth_type == ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD);
366   user_auth_type_map_[username] = auth_type;
367 }
368
369 ScreenlockBridge::LockHandler::AuthType UserSelectionScreen::GetAuthType(
370     const std::string& username) const {
371   if (user_auth_type_map_.find(username) == user_auth_type_map_.end())
372     return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
373   return user_auth_type_map_.find(username)->second;
374 }
375
376 }  // namespace chromeos