1 // Copyright 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.
5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
8 #include "base/value_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
13 #include "chrome/browser/profiles/profile_info_cache.h"
14 #include "chrome/browser/profiles/profile_info_cache_observer.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/profiles/profile_window.h"
17 #include "chrome/browser/profiles/profiles_state.h"
18 #include "chrome/browser/signin/local_auth.h"
19 #include "chrome/browser/ui/browser_dialogs.h"
20 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/singleton_tabs.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_ui.h"
24 #include "google_apis/gaia/gaia_auth_fetcher.h"
25 #include "google_apis/gaia/gaia_constants.h"
26 #include "grit/browser_resources.h"
27 #include "grit/chromium_strings.h"
28 #include "grit/generated_resources.h"
29 #include "grit/theme_resources.h"
30 #include "third_party/skia/include/core/SkBitmap.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
33 #include "ui/base/webui/web_ui_util.h"
34 #include "ui/gfx/image/image_util.h"
36 #if defined(ENABLE_MANAGED_USERS)
37 #include "chrome/browser/managed_mode/managed_user_service.h"
41 // User dictionary keys.
42 const char kKeyUsername
[] = "username";
43 const char kKeyDisplayName
[]= "displayName";
44 const char kKeyEmailAddress
[] = "emailAddress";
45 const char kKeyProfilePath
[] = "profilePath";
46 const char kKeyPublicAccount
[] = "publicAccount";
47 const char kKeyLocallyManagedUser
[] = "locallyManagedUser";
48 const char kKeySignedIn
[] = "signedIn";
49 const char kKeyCanRemove
[] = "canRemove";
50 const char kKeyIsOwner
[] = "isOwner";
51 const char kKeyIsDesktop
[] = "isDesktopUser";
52 const char kKeyAvatarUrl
[] = "userImage";
53 const char kKeyNeedsSignin
[] = "needsSignin";
55 // JS API callback names.
56 const char kJsApiUserManagerInitialize
[] = "userManagerInitialize";
57 const char kJsApiUserManagerAddUser
[] = "addUser";
58 const char kJsApiUserManagerAuthLaunchUser
[] = "authenticatedLaunchUser";
59 const char kJsApiUserManagerLaunchGuest
[] = "launchGuest";
60 const char kJsApiUserManagerLaunchUser
[] = "launchUser";
61 const char kJsApiUserManagerRemoveUser
[] = "removeUser";
63 const size_t kAvatarIconSize
= 180;
65 void HandleAndDoNothing(const base::ListValue
* args
) {
68 // This callback is run if the only profile has been deleted, and a new
69 // profile has been created to replace it.
70 void OpenNewWindowForProfile(
71 chrome::HostDesktopType desktop_type
,
73 Profile::CreateStatus status
) {
74 if (status
!= Profile::CREATE_STATUS_INITIALIZED
)
76 profiles::FindOrCreateNewWindowForProfile(
78 chrome::startup::IS_PROCESS_STARTUP
,
79 chrome::startup::IS_FIRST_RUN
,
84 // This callback is run after switching to a new profile has finished. This
85 // means either a new browser window has been opened, or an existing one
86 // has been found, which means we can safely close the User Manager without
87 // accidentally terminating the browser process. The task needs to be posted,
88 // as HideUserManager will end up destroying its WebContents, which will
89 // destruct the UserManagerScreenHandler as well.
90 void OnSwitchToProfileComplete() {
91 base::MessageLoop::current()->PostTask(
93 base::Bind(&chrome::HideUserManager
));
96 std::string
GetAvatarImageAtIndex(
97 size_t index
, const ProfileInfoCache
& info_cache
) {
98 bool is_gaia_picture
=
99 info_cache
.IsUsingGAIAPictureOfProfileAtIndex(index
) &&
100 info_cache
.GetGAIAPictureOfProfileAtIndex(index
);
102 // If the avatar is too small (i.e. the old-style low resolution avatar),
103 // it will be pixelated when displayed in the User Manager, so we should
104 // return the placeholder avatar instead.
105 gfx::Image avatar_image
= info_cache
.GetAvatarIconOfProfileAtIndex(index
);
106 if (avatar_image
.Width() <= profiles::kAvatarIconWidth
||
107 avatar_image
.Height() <= profiles::kAvatarIconHeight
) {
108 avatar_image
= ui::ResourceBundle::GetSharedInstance().GetImageNamed(
109 profiles::GetPlaceholderAvatarIconResourceID());
111 gfx::Image resized_image
= profiles::GetSizedAvatarIcon(
112 avatar_image
, is_gaia_picture
, kAvatarIconSize
, kAvatarIconSize
);
113 return webui::GetBitmapDataUrl(resized_image
.AsBitmap());
116 size_t GetIndexOfProfileWithEmailAndName(const ProfileInfoCache
& info_cache
,
117 const base::string16
& email
,
118 const base::string16
& name
) {
119 for (size_t i
= 0; i
< info_cache
.GetNumberOfProfiles(); ++i
) {
120 if (info_cache
.GetUserNameOfProfileAtIndex(i
) == email
&&
121 info_cache
.GetNameOfProfileAtIndex(i
) == name
) {
125 return std::string::npos
;
130 // ProfileUpdateObserver ------------------------------------------------------
132 class UserManagerScreenHandler::ProfileUpdateObserver
133 : public ProfileInfoCacheObserver
{
135 ProfileUpdateObserver(
136 ProfileManager
* profile_manager
, UserManagerScreenHandler
* handler
)
137 : profile_manager_(profile_manager
),
138 user_manager_handler_(handler
) {
139 DCHECK(profile_manager_
);
140 DCHECK(user_manager_handler_
);
141 profile_manager_
->GetProfileInfoCache().AddObserver(this);
144 virtual ~ProfileUpdateObserver() {
145 DCHECK(profile_manager_
);
146 profile_manager_
->GetProfileInfoCache().RemoveObserver(this);
150 // ProfileInfoCacheObserver implementation:
151 // If any change has been made to a profile, propagate it to all the
152 // visible user manager screens.
153 virtual void OnProfileAdded(const base::FilePath
& profile_path
) OVERRIDE
{
154 user_manager_handler_
->SendUserList();
157 virtual void OnProfileWasRemoved(
158 const base::FilePath
& profile_path
,
159 const base::string16
& profile_name
) OVERRIDE
{
160 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
161 // UserManager is able to find pod belonging to removed user.
162 user_manager_handler_
->SendUserList();
165 virtual void OnProfileNameChanged(
166 const base::FilePath
& profile_path
,
167 const base::string16
& old_profile_name
) OVERRIDE
{
168 user_manager_handler_
->SendUserList();
171 virtual void OnProfileAvatarChanged(
172 const base::FilePath
& profile_path
) OVERRIDE
{
173 user_manager_handler_
->SendUserList();
176 virtual void OnProfileSigninRequiredChanged(
177 const base::FilePath
& profile_path
) OVERRIDE
{
178 user_manager_handler_
->SendUserList();
181 ProfileManager
* profile_manager_
;
183 UserManagerScreenHandler
* user_manager_handler_
; // Weak; owns us.
185 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver
);
188 // UserManagerScreenHandler ---------------------------------------------------
190 UserManagerScreenHandler::UserManagerScreenHandler()
191 : desktop_type_(chrome::GetActiveDesktop()) {
192 profileInfoCacheObserver_
.reset(
193 new UserManagerScreenHandler::ProfileUpdateObserver(
194 g_browser_process
->profile_manager(), this));
197 UserManagerScreenHandler::~UserManagerScreenHandler() {
200 void UserManagerScreenHandler::HandleInitialize(const base::ListValue
* args
) {
202 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
203 desktop_type_
= chrome::GetHostDesktopTypeForNativeView(
204 web_ui()->GetWebContents()->GetNativeView());
207 void UserManagerScreenHandler::HandleAddUser(const base::ListValue
* args
) {
208 profiles::CreateAndSwitchToNewProfile(desktop_type_
,
209 base::Bind(&OnSwitchToProfileComplete
),
210 ProfileMetrics::ADD_NEW_USER_MANAGER
);
213 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
214 const base::ListValue
* args
) {
215 base::string16 email_address
;
216 if (!args
->GetString(0, &email_address
))
219 base::string16 display_name
;
220 if (!args
->GetString(1, &display_name
))
223 std::string password
;
224 if (!args
->GetString(2, &password
))
227 ProfileInfoCache
& info_cache
=
228 g_browser_process
->profile_manager()->GetProfileInfoCache();
229 size_t profile_index
= GetIndexOfProfileWithEmailAndName(
230 info_cache
, email_address
, display_name
);
231 if (profile_index
>= info_cache
.GetNumberOfProfiles()) {
236 authenticating_profile_index_
= profile_index
;
237 if (!chrome::ValidateLocalAuthCredentials(profile_index
, password
)) {
238 // Make a second attempt via an on-line authentication call. This handles
239 // profiles that are missing sign-in credentials and also cases where the
240 // password has been changed externally.
241 client_login_
.reset(new GaiaAuthFetcher(
243 GaiaConstants::kChromeSource
,
244 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
245 std::string email_string
;
246 args
->GetString(0, &email_string
);
247 client_login_
->StartClientLogin(
250 GaiaConstants::kSyncService
,
253 GaiaAuthFetcher::HostedAccountsAllowed
);
254 password_attempt_
= password
;
258 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL
);
261 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue
* args
) {
263 const base::Value
* profile_path_value
;
264 if (!args
->Get(0, &profile_path_value
))
267 base::FilePath profile_path
;
268 if (!base::GetValueAsFilePath(*profile_path_value
, &profile_path
))
271 // This handler could have been called in managed mode, for example because
272 // the user fiddled with the web inspector. Silently return in this case.
273 if (Profile::FromWebUI(web_ui())->IsManaged())
276 if (!profiles::IsMultipleProfilesEnabled())
279 g_browser_process
->profile_manager()->ScheduleProfileForDeletion(
281 base::Bind(&OpenNewWindowForProfile
, desktop_type_
));
282 ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED
);
285 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue
* args
) {
286 profiles::SwitchToGuestProfile(desktop_type_
,
287 base::Bind(&OnSwitchToProfileComplete
));
288 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST
);
291 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue
* args
) {
292 base::string16 email_address
;
293 base::string16 display_name
;
295 if (!args
->GetString(0, &email_address
) ||
296 !args
->GetString(1, &display_name
)) {
301 ProfileInfoCache
& info_cache
=
302 g_browser_process
->profile_manager()->GetProfileInfoCache();
303 size_t profile_index
= GetIndexOfProfileWithEmailAndName(
304 info_cache
, email_address
, display_name
);
306 if (profile_index
>= info_cache
.GetNumberOfProfiles()) {
311 // It's possible that a user breaks into the user-manager page using the
312 // JavaScript Inspector and causes a "locked" profile to call this
313 // unauthenticated version of "launch" instead of the proper one. Thus,
314 // we have to validate in (secure) C++ code that it really is a profile
315 // not needing authentication. If it is, just ignore the "launch" request.
316 if (info_cache
.ProfileIsSigninRequiredAtIndex(profile_index
))
318 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY
);
320 base::FilePath path
= info_cache
.GetPathOfProfileAtIndex(profile_index
);
321 profiles::SwitchToProfile(path
,
323 false, /* reuse any existing windows */
324 base::Bind(&OnSwitchToProfileComplete
),
325 ProfileMetrics::SWITCH_PROFILE_MANAGER
);
328 void UserManagerScreenHandler::OnClientLoginSuccess(
329 const ClientLoginResult
& result
) {
330 chrome::SetLocalAuthCredentials(authenticating_profile_index_
,
332 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE
);
335 void UserManagerScreenHandler::OnClientLoginFailure(
336 const GoogleServiceAuthError
& error
) {
337 const GoogleServiceAuthError::State state
= error
.state();
338 // Some "error" results mean the password was correct but some other action
339 // should be taken. For our purposes, we only care that the password was
340 // correct so count those as a success.
341 bool success
= (state
== GoogleServiceAuthError::NONE
||
342 state
== GoogleServiceAuthError::CAPTCHA_REQUIRED
||
343 state
== GoogleServiceAuthError::TWO_FACTOR
||
344 state
== GoogleServiceAuthError::ACCOUNT_DELETED
||
345 state
== GoogleServiceAuthError::ACCOUNT_DISABLED
);
346 ReportAuthenticationResult(success
,
347 success
? ProfileMetrics::AUTH_ONLINE
348 : ProfileMetrics::AUTH_FAILED
);
351 void UserManagerScreenHandler::RegisterMessages() {
352 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize
,
353 base::Bind(&UserManagerScreenHandler::HandleInitialize
,
354 base::Unretained(this)));
355 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser
,
356 base::Bind(&UserManagerScreenHandler::HandleAddUser
,
357 base::Unretained(this)));
358 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser
,
359 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser
,
360 base::Unretained(this)));
361 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest
,
362 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest
,
363 base::Unretained(this)));
364 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser
,
365 base::Bind(&UserManagerScreenHandler::HandleLaunchUser
,
366 base::Unretained(this)));
367 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser
,
368 base::Bind(&UserManagerScreenHandler::HandleRemoveUser
,
369 base::Unretained(this)));
371 const content::WebUI::MessageCallback
& kDoNothingCallback
=
372 base::Bind(&HandleAndDoNothing
);
374 // Unused callbacks from screen_account_picker.js
375 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback
);
376 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback
);
377 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback
);
378 // Unused callbacks from display_manager.js
379 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback
);
380 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback
);
381 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback
);
382 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback
);
383 // Unused callbacks from user_pod_row.js
384 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback
);
387 void UserManagerScreenHandler::GetLocalizedValues(
388 base::DictionaryValue
* localized_strings
) {
390 localized_strings
->SetString("signedIn",
391 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER
));
392 localized_strings
->SetString("signinButton",
393 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON
));
394 localized_strings
->SetString("addUser",
395 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON
));
396 localized_strings
->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL
));
397 localized_strings
->SetString("browseAsGuest",
398 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON
));
399 localized_strings
->SetString("signOutUser",
400 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT
));
402 // For AccountPickerScreen.
403 localized_strings
->SetString("screenType", "login-add-user");
404 localized_strings
->SetString("highlightStrength", "normal");
405 localized_strings
->SetString("title",
406 l10n_util::GetStringUTF16(IDS_USER_MANAGER_SCREEN_TITLE
));
407 localized_strings
->SetString("passwordHint",
408 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT
));
409 localized_strings
->SetString("podMenuButtonAccessibleName",
410 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME
));
411 localized_strings
->SetString("podMenuRemoveItemAccessibleName",
412 l10n_util::GetStringUTF16(
413 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME
));
414 localized_strings
->SetString("removeUser",
415 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON
));
416 localized_strings
->SetString("passwordFieldAccessibleName",
417 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME
));
418 localized_strings
->SetString("bootIntoWallpaper", "off");
420 // For AccountPickerScreen, the remove user warning overlay.
421 localized_strings
->SetString("removeUserWarningButtonTitle",
422 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON
));
423 localized_strings
->SetString("removeUserWarningText",
424 l10n_util::GetStringUTF16(
425 IDS_LOGIN_POD_USER_REMOVE_WARNING
));
427 // Strings needed for the User Manager tutorial slides.
428 localized_strings
->SetString("tutorialStart",
429 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_START
));
430 localized_strings
->SetString("tutorialSkip",
431 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SKIP
));
432 localized_strings
->SetString("tutorialNext",
433 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT
));
434 localized_strings
->SetString("tutorialDone",
435 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE
));
436 localized_strings
->SetString("slideWelcomeTitle",
437 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE
));
438 localized_strings
->SetString("slideWelcomeText",
439 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT
));
440 localized_strings
->SetString("slideYourChromeTitle",
441 l10n_util::GetStringUTF16(
442 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE
));
443 localized_strings
->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
444 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT
));
445 localized_strings
->SetString("slideGuestsTitle",
446 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE
));
447 localized_strings
->SetString("slideGuestsText",
448 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT
));
449 localized_strings
->SetString("slideFriendsTitle",
450 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE
));
451 localized_strings
->SetString("slideFriendsText",
452 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT
));
453 localized_strings
->SetString("slideCompleteTitle",
454 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE
));
455 localized_strings
->SetString("slideCompleteText",
456 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT
));
457 localized_strings
->SetString("slideCompleteUserNotFound",
458 l10n_util::GetStringUTF16(
459 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND
));
460 localized_strings
->SetString("slideCompleteAddUser",
461 l10n_util::GetStringUTF16(
462 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER
));
464 // Strings needed for the user_pod_template public account div, but not ever
465 // actually displayed for desktop users.
466 localized_strings
->SetString("publicAccountReminder", base::string16());
467 localized_strings
->SetString("publicAccountEnter", base::string16());
468 localized_strings
->SetString("publicAccountEnterAccessibleName",
470 localized_strings
->SetString("multiple-signin-banner-text",
472 localized_strings
->SetString("signinBannerText", base::string16());
473 localized_strings
->SetString("launchAppButton", base::string16());
474 localized_strings
->SetString("multiProfilesRestrictedPolicyTitle",
476 localized_strings
->SetString("multiProfilesNotAllowedPolicyMsg",
478 localized_strings
->SetString("multiProfilesPrimaryOnlyPolicyMsg",
482 void UserManagerScreenHandler::SendUserList() {
483 base::ListValue users_list
;
484 base::FilePath active_profile_path
=
485 web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
486 const ProfileInfoCache
& info_cache
=
487 g_browser_process
->profile_manager()->GetProfileInfoCache();
489 // If the active user is a managed user, then they may not perform
490 // certain actions (i.e. delete another user).
491 bool active_user_is_managed
= Profile::FromWebUI(web_ui())->IsManaged();
492 for (size_t i
= 0; i
< info_cache
.GetNumberOfProfiles(); ++i
) {
493 base::DictionaryValue
* profile_value
= new base::DictionaryValue();
495 base::FilePath profile_path
= info_cache
.GetPathOfProfileAtIndex(i
);
496 bool is_active_user
= (profile_path
== active_profile_path
);
498 profile_value
->SetString(
499 kKeyUsername
, info_cache
.GetUserNameOfProfileAtIndex(i
));
500 profile_value
->SetString(
501 kKeyEmailAddress
, info_cache
.GetUserNameOfProfileAtIndex(i
));
502 profile_value
->SetString(
503 kKeyDisplayName
, info_cache
.GetNameOfProfileAtIndex(i
));
504 profile_value
->SetString(kKeyProfilePath
, profile_path
.MaybeAsASCII());
505 profile_value
->SetBoolean(kKeyPublicAccount
, false);
506 profile_value
->SetBoolean(kKeyLocallyManagedUser
, false);
507 profile_value
->SetBoolean(kKeySignedIn
, is_active_user
);
508 profile_value
->SetBoolean(
509 kKeyNeedsSignin
, info_cache
.ProfileIsSigninRequiredAtIndex(i
));
510 profile_value
->SetBoolean(kKeyIsOwner
, false);
511 profile_value
->SetBoolean(kKeyCanRemove
, !active_user_is_managed
);
512 profile_value
->SetBoolean(kKeyIsDesktop
, true);
513 profile_value
->SetString(
514 kKeyAvatarUrl
, GetAvatarImageAtIndex(i
, info_cache
));
516 // The row of user pods should display the active user first.
518 users_list
.Insert(0, profile_value
);
520 users_list
.Append(profile_value
);
523 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
524 users_list
, base::FundamentalValue(false), base::FundamentalValue(true));
527 void UserManagerScreenHandler::ReportAuthenticationResult(
529 ProfileMetrics::ProfileAuth auth
) {
530 ProfileMetrics::LogProfileAuthResult(auth
);
531 password_attempt_
.clear();
534 ProfileInfoCache
& info_cache
=
535 g_browser_process
->profile_manager()->GetProfileInfoCache();
536 info_cache
.SetProfileSigninRequiredAtIndex(
537 authenticating_profile_index_
, false);
538 base::FilePath path
= info_cache
.GetPathOfProfileAtIndex(
539 authenticating_profile_index_
);
540 profiles::SwitchToProfile(path
, desktop_type_
, true,
541 base::Bind(&OnSwitchToProfileComplete
),
542 ProfileMetrics::SWITCH_PROFILE_UNLOCK
);
544 web_ui()->CallJavascriptFunction(
545 "cr.ui.Oobe.showSignInError",
546 base::FundamentalValue(0),
548 l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_AUTHENTICATING
)),
549 base::StringValue(""),
550 base::FundamentalValue(0));