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/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/value_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
16 #include "chrome/browser/profiles/profile_info_cache.h"
17 #include "chrome/browser/profiles/profile_info_cache_observer.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/profiles/profile_metrics.h"
20 #include "chrome/browser/profiles/profile_window.h"
21 #include "chrome/browser/profiles/profiles_state.h"
22 #include "chrome/browser/signin/local_auth.h"
23 #include "chrome/browser/ui/browser_dialogs.h"
24 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/browser/ui/singleton_tabs.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/url_constants.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_ui.h"
30 #include "google_apis/gaia/gaia_auth_fetcher.h"
31 #include "google_apis/gaia/gaia_constants.h"
32 #include "grit/browser_resources.h"
33 #include "grit/chromium_strings.h"
34 #include "grit/generated_resources.h"
35 #include "grit/theme_resources.h"
36 #include "third_party/skia/include/core/SkBitmap.h"
37 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/base/resource/resource_bundle.h"
39 #include "ui/base/webui/web_ui_util.h"
40 #include "ui/gfx/image/image.h"
41 #include "ui/gfx/image/image_skia.h"
42 #include "ui/gfx/image/image_util.h"
45 // User dictionary keys.
46 const char kKeyUsername[] = "username";
47 const char kKeyDisplayName[]= "displayName";
48 const char kKeyEmailAddress[] = "emailAddress";
49 const char kKeyProfilePath[] = "profilePath";
50 const char kKeyPublicAccount[] = "publicAccount";
51 const char kKeySupervisedUser[] = "supervisedUser";
52 const char kKeySignedIn[] = "signedIn";
53 const char kKeyCanRemove[] = "canRemove";
54 const char kKeyIsOwner[] = "isOwner";
55 const char kKeyIsDesktop[] = "isDesktopUser";
56 const char kKeyAvatarUrl[] = "userImage";
57 const char kKeyNeedsSignin[] = "needsSignin";
59 // JS API callback names.
60 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
61 const char kJsApiUserManagerAddUser[] = "addUser";
62 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
63 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
64 const char kJsApiUserManagerLaunchUser[] = "launchUser";
65 const char kJsApiUserManagerRemoveUser[] = "removeUser";
66 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
68 const size_t kAvatarIconSize = 180;
70 void HandleAndDoNothing(const base::ListValue* args) {
73 // This callback is run if the only profile has been deleted, and a new
74 // profile has been created to replace it.
75 void OpenNewWindowForProfile(
76 chrome::HostDesktopType desktop_type,
78 Profile::CreateStatus status) {
79 if (status != Profile::CREATE_STATUS_INITIALIZED)
81 profiles::FindOrCreateNewWindowForProfile(
83 chrome::startup::IS_PROCESS_STARTUP,
84 chrome::startup::IS_FIRST_RUN,
89 // This callback is run after switching to a new profile has finished. This
90 // means either a new browser window has been opened, or an existing one
91 // has been found, which means we can safely close the User Manager without
92 // accidentally terminating the browser process. The task needs to be posted,
93 // as HideUserManager will end up destroying its WebContents, which will
94 // destruct the UserManagerScreenHandler as well.
95 void OnSwitchToProfileComplete() {
96 base::MessageLoop::current()->PostTask(
98 base::Bind(&chrome::HideUserManager));
101 std::string GetAvatarImageAtIndex(
102 size_t index, const ProfileInfoCache& info_cache) {
103 bool is_gaia_picture =
104 info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
105 info_cache.GetGAIAPictureOfProfileAtIndex(index);
107 // If the avatar is too small (i.e. the old-style low resolution avatar),
108 // it will be pixelated when displayed in the User Manager, so we should
109 // return the placeholder avatar instead.
110 gfx::Image avatar_image = info_cache.GetAvatarIconOfProfileAtIndex(index);
111 if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
112 avatar_image.Height() <= profiles::kAvatarIconHeight ) {
113 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
114 profiles::GetPlaceholderAvatarIconResourceID());
116 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
117 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
118 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
121 size_t GetIndexOfProfileWithEmailAndName(const ProfileInfoCache& info_cache,
122 const base::string16& email,
123 const base::string16& name) {
124 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
125 if (info_cache.GetUserNameOfProfileAtIndex(i) == email &&
127 profiles::GetAvatarNameForProfile(
128 info_cache.GetPathOfProfileAtIndex(i)) == name)) {
132 return std::string::npos;
135 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
136 const std::string& email) {
137 ProfileInfoCache& info_cache =
138 g_browser_process->profile_manager()->GetProfileInfoCache();
139 const size_t profile_index = GetIndexOfProfileWithEmailAndName(
140 info_cache, base::UTF8ToUTF16(email), base::string16());
141 Profile* profile = g_browser_process->profile_manager()
142 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index));
143 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
147 bool IsGuestModeEnabled() {
148 PrefService* service = g_browser_process->local_state();
150 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
155 // ProfileUpdateObserver ------------------------------------------------------
157 class UserManagerScreenHandler::ProfileUpdateObserver
158 : public ProfileInfoCacheObserver {
160 ProfileUpdateObserver(
161 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
162 : profile_manager_(profile_manager),
163 user_manager_handler_(handler) {
164 DCHECK(profile_manager_);
165 DCHECK(user_manager_handler_);
166 profile_manager_->GetProfileInfoCache().AddObserver(this);
169 virtual ~ProfileUpdateObserver() {
170 DCHECK(profile_manager_);
171 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
175 // ProfileInfoCacheObserver implementation:
176 // If any change has been made to a profile, propagate it to all the
177 // visible user manager screens.
178 virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
179 user_manager_handler_->SendUserList();
182 virtual void OnProfileWasRemoved(
183 const base::FilePath& profile_path,
184 const base::string16& profile_name) OVERRIDE {
185 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
186 // UserManager is able to find pod belonging to removed user.
187 user_manager_handler_->SendUserList();
190 virtual void OnProfileNameChanged(
191 const base::FilePath& profile_path,
192 const base::string16& old_profile_name) OVERRIDE {
193 user_manager_handler_->SendUserList();
196 virtual void OnProfileAvatarChanged(
197 const base::FilePath& profile_path) OVERRIDE {
198 user_manager_handler_->SendUserList();
201 virtual void OnProfileSigninRequiredChanged(
202 const base::FilePath& profile_path) OVERRIDE {
203 user_manager_handler_->SendUserList();
206 ProfileManager* profile_manager_;
208 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
210 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
213 // UserManagerScreenHandler ---------------------------------------------------
215 UserManagerScreenHandler::UserManagerScreenHandler()
216 : desktop_type_(chrome::GetActiveDesktop()) {
217 profileInfoCacheObserver_.reset(
218 new UserManagerScreenHandler::ProfileUpdateObserver(
219 g_browser_process->profile_manager(), this));
222 UserManagerScreenHandler::~UserManagerScreenHandler() {
223 ScreenlockBridge::Get()->SetLockHandler(NULL);
226 void UserManagerScreenHandler::ShowBannerMessage(
227 const base::string16& message) {
228 web_ui()->CallJavascriptFunction(
229 "login.AccountPickerScreen.showBannerMessage",
230 base::StringValue(message));
233 void UserManagerScreenHandler::ShowUserPodCustomIcon(
234 const std::string& user_email,
235 const ScreenlockBridge::UserPodCustomIconOptions& icon_options) {
236 scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
237 if (!icon || icon->empty())
239 web_ui()->CallJavascriptFunction(
240 "login.AccountPickerScreen.showUserPodCustomIcon",
241 base::StringValue(user_email),
245 void UserManagerScreenHandler::HideUserPodCustomIcon(
246 const std::string& user_email) {
247 web_ui()->CallJavascriptFunction(
248 "login.AccountPickerScreen.hideUserPodCustomIcon",
249 base::StringValue(user_email));
252 void UserManagerScreenHandler::EnableInput() {
253 // Nothing here because UI is not disabled when starting to authenticate.
256 void UserManagerScreenHandler::SetAuthType(
257 const std::string& user_email,
258 ScreenlockBridge::LockHandler::AuthType auth_type,
259 const base::string16& auth_value) {
260 user_auth_type_map_[user_email] = auth_type;
261 web_ui()->CallJavascriptFunction(
262 "login.AccountPickerScreen.setAuthType",
263 base::StringValue(user_email),
264 base::FundamentalValue(auth_type),
265 base::StringValue(auth_value));
268 ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType(
269 const std::string& user_email) const {
270 UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email);
271 if (it == user_auth_type_map_.end())
272 return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
276 void UserManagerScreenHandler::Unlock(const std::string& user_email) {
277 ProfileInfoCache& info_cache =
278 g_browser_process->profile_manager()->GetProfileInfoCache();
279 const size_t profile_index = GetIndexOfProfileWithEmailAndName(
280 info_cache, base::UTF8ToUTF16(user_email), base::string16());
281 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles());
283 authenticating_profile_index_ = profile_index;
284 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
287 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
289 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
290 base::FundamentalValue(IsGuestModeEnabled()));
291 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
292 web_ui()->GetWebContents()->GetNativeView());
294 ScreenlockBridge::Get()->SetLockHandler(this);
297 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
298 profiles::CreateAndSwitchToNewProfile(desktop_type_,
299 base::Bind(&OnSwitchToProfileComplete),
300 ProfileMetrics::ADD_NEW_USER_MANAGER);
303 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
304 const base::ListValue* args) {
305 base::string16 email_address;
306 if (!args->GetString(0, &email_address))
309 base::string16 display_name;
310 if (!args->GetString(1, &display_name))
313 std::string password;
314 if (!args->GetString(2, &password))
317 ProfileInfoCache& info_cache =
318 g_browser_process->profile_manager()->GetProfileInfoCache();
319 size_t profile_index = GetIndexOfProfileWithEmailAndName(
320 info_cache, email_address, display_name);
321 if (profile_index >= info_cache.GetNumberOfProfiles()) {
326 authenticating_profile_index_ = profile_index;
327 if (!chrome::ValidateLocalAuthCredentials(profile_index, password)) {
328 // Make a second attempt via an on-line authentication call. This handles
329 // profiles that are missing sign-in credentials and also cases where the
330 // password has been changed externally.
331 client_login_.reset(new GaiaAuthFetcher(
333 GaiaConstants::kChromeSource,
334 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
335 std::string email_string;
336 args->GetString(0, &email_string);
337 client_login_->StartClientLogin(
340 GaiaConstants::kSyncService,
343 GaiaAuthFetcher::HostedAccountsAllowed);
344 password_attempt_ = password;
348 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
351 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
353 const base::Value* profile_path_value;
354 if (!args->Get(0, &profile_path_value))
357 base::FilePath profile_path;
358 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
361 // This handler could have been called for a supervised user, for example
362 // because the user fiddled with the web inspector. Silently return in this
364 if (Profile::FromWebUI(web_ui())->IsSupervised())
367 if (!profiles::IsMultipleProfilesEnabled())
370 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
372 base::Bind(&OpenNewWindowForProfile, desktop_type_));
373 ProfileMetrics::LogProfileDeleteUser(
374 ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
377 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
378 if (IsGuestModeEnabled()) {
379 profiles::SwitchToGuestProfile(desktop_type_,
380 base::Bind(&OnSwitchToProfileComplete));
381 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST);
383 // The UI should have prevented the user from allowing the selection of
389 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
390 base::string16 email_address;
391 base::string16 display_name;
393 if (!args->GetString(0, &email_address) ||
394 !args->GetString(1, &display_name)) {
399 ProfileInfoCache& info_cache =
400 g_browser_process->profile_manager()->GetProfileInfoCache();
401 size_t profile_index = GetIndexOfProfileWithEmailAndName(
402 info_cache, email_address, display_name);
404 if (profile_index >= info_cache.GetNumberOfProfiles()) {
409 // It's possible that a user breaks into the user-manager page using the
410 // JavaScript Inspector and causes a "locked" profile to call this
411 // unauthenticated version of "launch" instead of the proper one. Thus,
412 // we have to validate in (secure) C++ code that it really is a profile
413 // not needing authentication. If it is, just ignore the "launch" request.
414 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
416 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
418 base::FilePath path = info_cache.GetPathOfProfileAtIndex(profile_index);
419 profiles::SwitchToProfile(path,
421 false, /* reuse any existing windows */
422 base::Bind(&OnSwitchToProfileComplete),
423 ProfileMetrics::SWITCH_PROFILE_MANAGER);
426 void UserManagerScreenHandler::HandleAttemptUnlock(
427 const base::ListValue* args) {
429 CHECK(args->GetString(0, &email));
430 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
433 void UserManagerScreenHandler::OnClientLoginSuccess(
434 const ClientLoginResult& result) {
435 chrome::SetLocalAuthCredentials(authenticating_profile_index_,
437 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
440 void UserManagerScreenHandler::OnClientLoginFailure(
441 const GoogleServiceAuthError& error) {
442 const GoogleServiceAuthError::State state = error.state();
443 // Some "error" results mean the password was correct but some other action
444 // should be taken. For our purposes, we only care that the password was
445 // correct so count those as a success.
446 bool success = (state == GoogleServiceAuthError::NONE ||
447 state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
448 state == GoogleServiceAuthError::TWO_FACTOR ||
449 state == GoogleServiceAuthError::ACCOUNT_DELETED ||
450 state == GoogleServiceAuthError::ACCOUNT_DISABLED);
451 ReportAuthenticationResult(success,
452 success ? ProfileMetrics::AUTH_ONLINE
453 : ProfileMetrics::AUTH_FAILED);
456 void UserManagerScreenHandler::RegisterMessages() {
457 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
458 base::Bind(&UserManagerScreenHandler::HandleInitialize,
459 base::Unretained(this)));
460 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
461 base::Bind(&UserManagerScreenHandler::HandleAddUser,
462 base::Unretained(this)));
463 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
464 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
465 base::Unretained(this)));
466 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
467 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
468 base::Unretained(this)));
469 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
470 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
471 base::Unretained(this)));
472 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
473 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
474 base::Unretained(this)));
475 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
476 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
477 base::Unretained(this)));
479 const content::WebUI::MessageCallback& kDoNothingCallback =
480 base::Bind(&HandleAndDoNothing);
482 // Unused callbacks from screen_account_picker.js
483 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
484 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
485 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
486 // Unused callbacks from display_manager.js
487 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
488 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
489 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
490 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
491 // Unused callbacks from user_pod_row.js
492 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
495 void UserManagerScreenHandler::GetLocalizedValues(
496 base::DictionaryValue* localized_strings) {
498 localized_strings->SetString("signedIn",
499 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
500 localized_strings->SetString("signinButton",
501 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
502 localized_strings->SetString("addUser",
503 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
504 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
505 localized_strings->SetString("browseAsGuest",
506 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
507 localized_strings->SetString("signOutUser",
508 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
510 // For AccountPickerScreen.
511 localized_strings->SetString("screenType", "login-add-user");
512 localized_strings->SetString("highlightStrength", "normal");
513 localized_strings->SetString("title",
514 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
515 localized_strings->SetString("passwordHint",
516 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
517 localized_strings->SetString("podMenuButtonAccessibleName",
518 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
519 localized_strings->SetString("podMenuRemoveItemAccessibleName",
520 l10n_util::GetStringUTF16(
521 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
522 localized_strings->SetString("removeUser",
523 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
524 localized_strings->SetString("passwordFieldAccessibleName",
525 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
526 localized_strings->SetString("bootIntoWallpaper", "off");
528 // For AccountPickerScreen, the remove user warning overlay.
529 localized_strings->SetString("removeUserWarningButtonTitle",
530 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
531 localized_strings->SetString("removeUserWarningText",
532 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
533 localized_strings->SetString("removeSupervisedUserWarningText",
534 l10n_util::GetStringFUTF16(
535 IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING,
536 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)));
538 // Strings needed for the User Manager tutorial slides.
539 localized_strings->SetString("tutorialNext",
540 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT));
541 localized_strings->SetString("tutorialDone",
542 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE));
543 localized_strings->SetString("slideWelcomeTitle",
544 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE));
545 localized_strings->SetString("slideWelcomeText",
546 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT));
547 localized_strings->SetString("slideYourChromeTitle",
548 l10n_util::GetStringUTF16(
549 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE));
550 localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
551 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT));
552 localized_strings->SetString("slideGuestsTitle",
553 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE));
554 localized_strings->SetString("slideGuestsText",
555 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT));
556 localized_strings->SetString("slideFriendsTitle",
557 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE));
558 localized_strings->SetString("slideFriendsText",
559 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT));
560 localized_strings->SetString("slideCompleteTitle",
561 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE));
562 localized_strings->SetString("slideCompleteText",
563 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT));
564 localized_strings->SetString("slideCompleteUserNotFound",
565 l10n_util::GetStringUTF16(
566 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND));
567 localized_strings->SetString("slideCompleteAddUser",
568 l10n_util::GetStringUTF16(
569 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER));
571 // Strings needed for the user_pod_template public account div, but not ever
572 // actually displayed for desktop users.
573 localized_strings->SetString("publicAccountReminder", base::string16());
574 localized_strings->SetString("publicSessionLanguageAndInput",
576 localized_strings->SetString("publicAccountEnter", base::string16());
577 localized_strings->SetString("publicAccountEnterAccessibleName",
579 localized_strings->SetString("publicSessionSelectLanguage", base::string16());
580 localized_strings->SetString("publicSessionSelectKeyboard", base::string16());
581 localized_strings->SetString("signinBannerText", base::string16());
582 localized_strings->SetString("launchAppButton", base::string16());
583 localized_strings->SetString("multiProfilesRestrictedPolicyTitle",
585 localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
587 localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
589 localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
593 void UserManagerScreenHandler::SendUserList() {
594 base::ListValue users_list;
595 base::FilePath active_profile_path =
596 web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
597 const ProfileInfoCache& info_cache =
598 g_browser_process->profile_manager()->GetProfileInfoCache();
600 user_auth_type_map_.clear();
602 // If the active user is a supervised user, then they may not perform
603 // certain actions (i.e. delete another user).
604 bool active_user_is_supervised = Profile::FromWebUI(web_ui())->IsSupervised();
605 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
606 base::DictionaryValue* profile_value = new base::DictionaryValue();
608 base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
609 bool is_active_user = (profile_path == active_profile_path);
611 profile_value->SetString(
612 kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i));
613 profile_value->SetString(
614 kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i));
615 // The profiles displayed in the User Manager are never guest profiles.
616 profile_value->SetString(
618 profiles::GetAvatarNameForProfile(profile_path));
619 profile_value->SetString(kKeyProfilePath, profile_path.MaybeAsASCII());
620 profile_value->SetBoolean(kKeyPublicAccount, false);
621 profile_value->SetBoolean(
622 kKeySupervisedUser, info_cache.ProfileIsSupervisedAtIndex(i));
623 profile_value->SetBoolean(kKeySignedIn, is_active_user);
624 profile_value->SetBoolean(
625 kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i));
626 profile_value->SetBoolean(kKeyIsOwner, false);
627 profile_value->SetBoolean(kKeyCanRemove, !active_user_is_supervised);
628 profile_value->SetBoolean(kKeyIsDesktop, true);
629 profile_value->SetString(
630 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
632 // The row of user pods should display the active user first.
634 users_list.Insert(0, profile_value);
636 users_list.Append(profile_value);
639 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
640 users_list, base::FundamentalValue(IsGuestModeEnabled()));
643 void UserManagerScreenHandler::ReportAuthenticationResult(
645 ProfileMetrics::ProfileAuth auth) {
646 ProfileMetrics::LogProfileAuthResult(auth);
647 password_attempt_.clear();
650 ProfileInfoCache& info_cache =
651 g_browser_process->profile_manager()->GetProfileInfoCache();
652 info_cache.SetProfileSigninRequiredAtIndex(
653 authenticating_profile_index_, false);
654 base::FilePath path = info_cache.GetPathOfProfileAtIndex(
655 authenticating_profile_index_);
656 profiles::SwitchToProfile(path, desktop_type_, true,
657 base::Bind(&OnSwitchToProfileComplete),
658 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
660 web_ui()->CallJavascriptFunction(
661 "cr.ui.Oobe.showSignInError",
662 base::FundamentalValue(0),
664 l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_AUTHENTICATING)),
665 base::StringValue(""),
666 base::FundamentalValue(0));