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/chrome_notification_types.h"
14 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
17 #include "chrome/browser/profiles/profile_info_cache.h"
18 #include "chrome/browser/profiles/profile_info_cache_observer.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/profiles/profile_metrics.h"
21 #include "chrome/browser/profiles/profile_window.h"
22 #include "chrome/browser/profiles/profiles_state.h"
23 #include "chrome/browser/signin/local_auth.h"
24 #include "chrome/browser/ui/browser_dialogs.h"
25 #include "chrome/browser/ui/browser_finder.h"
26 #include "chrome/browser/ui/browser_list.h"
27 #include "chrome/browser/ui/chrome_pages.h"
28 #include "chrome/browser/ui/singleton_tabs.h"
29 #include "chrome/browser/ui/user_manager.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/grit/chromium_strings.h"
33 #include "chrome/grit/generated_resources.h"
34 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/browser/web_ui.h"
37 #include "google_apis/gaia/gaia_auth_fetcher.h"
38 #include "google_apis/gaia/gaia_constants.h"
39 #include "third_party/skia/include/core/SkBitmap.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/resource/resource_bundle.h"
42 #include "ui/base/webui/web_ui_util.h"
43 #include "ui/gfx/image/image.h"
44 #include "ui/gfx/image/image_skia.h"
45 #include "ui/gfx/image/image_util.h"
48 // User dictionary keys.
49 const char kKeyUsername[] = "username";
50 const char kKeyDisplayName[]= "displayName";
51 const char kKeyEmailAddress[] = "emailAddress";
52 const char kKeyProfilePath[] = "profilePath";
53 const char kKeyPublicAccount[] = "publicAccount";
54 const char kKeySupervisedUser[] = "supervisedUser";
55 const char kKeySignedIn[] = "signedIn";
56 const char kKeyCanRemove[] = "canRemove";
57 const char kKeyIsOwner[] = "isOwner";
58 const char kKeyIsDesktop[] = "isDesktopUser";
59 const char kKeyAvatarUrl[] = "userImage";
60 const char kKeyNeedsSignin[] = "needsSignin";
62 // JS API callback names.
63 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
64 const char kJsApiUserManagerAddUser[] = "addUser";
65 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
66 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
67 const char kJsApiUserManagerLaunchUser[] = "launchUser";
68 const char kJsApiUserManagerRemoveUser[] = "removeUser";
69 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
71 const size_t kAvatarIconSize = 180;
73 void HandleAndDoNothing(const base::ListValue* args) {
76 // This callback is run if the only profile has been deleted, and a new
77 // profile has been created to replace it.
78 void OpenNewWindowForProfile(
79 chrome::HostDesktopType desktop_type,
81 Profile::CreateStatus status) {
82 if (status != Profile::CREATE_STATUS_INITIALIZED)
84 profiles::FindOrCreateNewWindowForProfile(
86 chrome::startup::IS_PROCESS_STARTUP,
87 chrome::startup::IS_FIRST_RUN,
92 std::string GetAvatarImageAtIndex(
93 size_t index, const ProfileInfoCache& info_cache) {
94 bool is_gaia_picture =
95 info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
96 info_cache.GetGAIAPictureOfProfileAtIndex(index);
98 // If the avatar is too small (i.e. the old-style low resolution avatar),
99 // it will be pixelated when displayed in the User Manager, so we should
100 // return the placeholder avatar instead.
101 gfx::Image avatar_image = info_cache.GetAvatarIconOfProfileAtIndex(index);
102 if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
103 avatar_image.Height() <= profiles::kAvatarIconHeight ) {
104 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
105 profiles::GetPlaceholderAvatarIconResourceID());
107 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
108 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
109 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
112 size_t GetIndexOfProfileWithEmailAndName(const ProfileInfoCache& info_cache,
113 const base::string16& email,
114 const base::string16& name) {
115 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
116 if (info_cache.GetUserNameOfProfileAtIndex(i) == email &&
118 profiles::GetAvatarNameForProfile(
119 info_cache.GetPathOfProfileAtIndex(i)) == name)) {
123 return std::string::npos;
126 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
127 const std::string& email) {
128 ProfileInfoCache& info_cache =
129 g_browser_process->profile_manager()->GetProfileInfoCache();
130 const size_t profile_index = GetIndexOfProfileWithEmailAndName(
131 info_cache, base::UTF8ToUTF16(email), base::string16());
132 Profile* profile = g_browser_process->profile_manager()
133 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index));
134 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
138 bool IsGuestModeEnabled() {
139 PrefService* service = g_browser_process->local_state();
141 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
144 bool IsAddPersonEnabled() {
145 PrefService* service = g_browser_process->local_state();
147 return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
152 // ProfileUpdateObserver ------------------------------------------------------
154 class UserManagerScreenHandler::ProfileUpdateObserver
155 : public ProfileInfoCacheObserver {
157 ProfileUpdateObserver(
158 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
159 : profile_manager_(profile_manager),
160 user_manager_handler_(handler) {
161 DCHECK(profile_manager_);
162 DCHECK(user_manager_handler_);
163 profile_manager_->GetProfileInfoCache().AddObserver(this);
166 virtual ~ProfileUpdateObserver() {
167 DCHECK(profile_manager_);
168 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
172 // ProfileInfoCacheObserver implementation:
173 // If any change has been made to a profile, propagate it to all the
174 // visible user manager screens.
175 virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
176 user_manager_handler_->SendUserList();
179 virtual void OnProfileWasRemoved(
180 const base::FilePath& profile_path,
181 const base::string16& profile_name) OVERRIDE {
182 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
183 // UserManager is able to find pod belonging to removed user.
184 user_manager_handler_->SendUserList();
187 virtual void OnProfileNameChanged(
188 const base::FilePath& profile_path,
189 const base::string16& old_profile_name) OVERRIDE {
190 user_manager_handler_->SendUserList();
193 virtual void OnProfileAvatarChanged(
194 const base::FilePath& profile_path) OVERRIDE {
195 user_manager_handler_->SendUserList();
198 virtual void OnProfileSigninRequiredChanged(
199 const base::FilePath& profile_path) OVERRIDE {
200 user_manager_handler_->SendUserList();
203 ProfileManager* profile_manager_;
205 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
207 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
210 // UserManagerScreenHandler ---------------------------------------------------
212 UserManagerScreenHandler::UserManagerScreenHandler()
213 : desktop_type_(chrome::GetActiveDesktop()),
214 weak_ptr_factory_(this) {
215 profileInfoCacheObserver_.reset(
216 new UserManagerScreenHandler::ProfileUpdateObserver(
217 g_browser_process->profile_manager(), this));
220 UserManagerScreenHandler::~UserManagerScreenHandler() {
221 ScreenlockBridge::Get()->SetLockHandler(NULL);
224 void UserManagerScreenHandler::ShowBannerMessage(
225 const base::string16& message) {
226 web_ui()->CallJavascriptFunction(
227 "login.AccountPickerScreen.showBannerMessage",
228 base::StringValue(message));
231 void UserManagerScreenHandler::ShowUserPodCustomIcon(
232 const std::string& user_email,
233 const ScreenlockBridge::UserPodCustomIconOptions& icon_options) {
234 scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
235 if (!icon || icon->empty())
237 web_ui()->CallJavascriptFunction(
238 "login.AccountPickerScreen.showUserPodCustomIcon",
239 base::StringValue(user_email),
243 void UserManagerScreenHandler::HideUserPodCustomIcon(
244 const std::string& user_email) {
245 web_ui()->CallJavascriptFunction(
246 "login.AccountPickerScreen.hideUserPodCustomIcon",
247 base::StringValue(user_email));
250 void UserManagerScreenHandler::EnableInput() {
251 // Nothing here because UI is not disabled when starting to authenticate.
254 void UserManagerScreenHandler::SetAuthType(
255 const std::string& user_email,
256 ScreenlockBridge::LockHandler::AuthType auth_type,
257 const base::string16& auth_value) {
258 if (GetAuthType(user_email) ==
259 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
262 user_auth_type_map_[user_email] = auth_type;
263 web_ui()->CallJavascriptFunction(
264 "login.AccountPickerScreen.setAuthType",
265 base::StringValue(user_email),
266 base::FundamentalValue(auth_type),
267 base::StringValue(auth_value));
270 ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType(
271 const std::string& user_email) const {
272 UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email);
273 if (it == user_auth_type_map_.end())
274 return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
278 void UserManagerScreenHandler::Unlock(const std::string& user_email) {
279 ProfileInfoCache& info_cache =
280 g_browser_process->profile_manager()->GetProfileInfoCache();
281 const size_t profile_index = GetIndexOfProfileWithEmailAndName(
282 info_cache, base::UTF8ToUTF16(user_email), base::string16());
283 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles());
285 authenticating_profile_index_ = profile_index;
286 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
289 void UserManagerScreenHandler::AttemptEasySignin(
290 const std::string& user_email,
291 const std::string& secret,
292 const std::string& key_label) {
296 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
297 // If the URL has a hash parameter, store it for later.
298 args->GetString(0, &url_hash_);
301 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
302 base::FundamentalValue(IsGuestModeEnabled()),
303 base::FundamentalValue(IsAddPersonEnabled()));
304 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
305 web_ui()->GetWebContents()->GetNativeView());
307 ScreenlockBridge::Get()->SetLockHandler(this);
310 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
311 if (!IsAddPersonEnabled()) {
312 // The 'Add User' UI should not be showing.
316 profiles::CreateAndSwitchToNewProfile(
318 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
319 weak_ptr_factory_.GetWeakPtr()),
320 ProfileMetrics::ADD_NEW_USER_MANAGER);
323 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
324 const base::ListValue* args) {
325 base::string16 email_address;
326 if (!args->GetString(0, &email_address))
329 base::string16 display_name;
330 if (!args->GetString(1, &display_name))
333 std::string password;
334 if (!args->GetString(2, &password))
337 ProfileInfoCache& info_cache =
338 g_browser_process->profile_manager()->GetProfileInfoCache();
339 size_t profile_index = GetIndexOfProfileWithEmailAndName(
340 info_cache, email_address, display_name);
341 if (profile_index >= info_cache.GetNumberOfProfiles()) {
346 authenticating_profile_index_ = profile_index;
347 if (!chrome::ValidateLocalAuthCredentials(profile_index, password)) {
348 // Make a second attempt via an on-line authentication call. This handles
349 // profiles that are missing sign-in credentials and also cases where the
350 // password has been changed externally.
351 client_login_.reset(new GaiaAuthFetcher(
353 GaiaConstants::kChromeSource,
354 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
355 std::string email_string;
356 args->GetString(0, &email_string);
357 client_login_->StartClientLogin(
360 GaiaConstants::kSyncService,
363 GaiaAuthFetcher::HostedAccountsAllowed);
364 password_attempt_ = password;
368 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
371 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
373 const base::Value* profile_path_value;
374 if (!args->Get(0, &profile_path_value))
377 base::FilePath profile_path;
378 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
381 // This handler could have been called for a supervised user, for example
382 // because the user fiddled with the web inspector. Silently return in this
384 if (Profile::FromWebUI(web_ui())->IsSupervised())
387 if (!profiles::IsMultipleProfilesEnabled())
390 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
392 base::Bind(&OpenNewWindowForProfile, desktop_type_));
393 ProfileMetrics::LogProfileDeleteUser(
394 ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
397 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
398 if (IsGuestModeEnabled()) {
399 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST);
400 profiles::SwitchToGuestProfile(
402 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
403 weak_ptr_factory_.GetWeakPtr()));
405 // The UI should have prevented the user from allowing the selection of
411 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
412 base::string16 email_address;
413 base::string16 display_name;
415 if (!args->GetString(0, &email_address) ||
416 !args->GetString(1, &display_name)) {
421 ProfileInfoCache& info_cache =
422 g_browser_process->profile_manager()->GetProfileInfoCache();
423 size_t profile_index = GetIndexOfProfileWithEmailAndName(
424 info_cache, email_address, display_name);
426 if (profile_index >= info_cache.GetNumberOfProfiles()) {
431 // It's possible that a user breaks into the user-manager page using the
432 // JavaScript Inspector and causes a "locked" profile to call this
433 // unauthenticated version of "launch" instead of the proper one. Thus,
434 // we have to validate in (secure) C++ code that it really is a profile
435 // not needing authentication. If it is, just ignore the "launch" request.
436 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
438 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
440 base::FilePath path = info_cache.GetPathOfProfileAtIndex(profile_index);
441 profiles::SwitchToProfile(
444 false, /* reuse any existing windows */
445 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
446 weak_ptr_factory_.GetWeakPtr()),
447 ProfileMetrics::SWITCH_PROFILE_MANAGER);
450 void UserManagerScreenHandler::HandleAttemptUnlock(
451 const base::ListValue* args) {
453 CHECK(args->GetString(0, &email));
454 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
457 void UserManagerScreenHandler::HandleHardlockUserPod(
458 const base::ListValue* args) {
460 CHECK(args->GetString(0, &email));
462 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
464 HideUserPodCustomIcon(email);
467 void UserManagerScreenHandler::OnClientLoginSuccess(
468 const ClientLoginResult& result) {
469 chrome::SetLocalAuthCredentials(authenticating_profile_index_,
471 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
474 void UserManagerScreenHandler::OnClientLoginFailure(
475 const GoogleServiceAuthError& error) {
476 const GoogleServiceAuthError::State state = error.state();
477 // Some "error" results mean the password was correct but some other action
478 // should be taken. For our purposes, we only care that the password was
479 // correct so count those as a success.
480 bool success = (state == GoogleServiceAuthError::NONE ||
481 state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
482 state == GoogleServiceAuthError::TWO_FACTOR ||
483 state == GoogleServiceAuthError::ACCOUNT_DELETED ||
484 state == GoogleServiceAuthError::ACCOUNT_DISABLED);
485 bool offline = (state == GoogleServiceAuthError::CONNECTION_FAILED ||
486 state == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
487 state == GoogleServiceAuthError::REQUEST_CANCELED);
488 ProfileMetrics::ProfileAuth failure_metric =
489 offline ? ProfileMetrics::AUTH_FAILED_OFFLINE :
490 ProfileMetrics::AUTH_FAILED;
491 ReportAuthenticationResult(
492 success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric);
495 void UserManagerScreenHandler::RegisterMessages() {
496 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
497 base::Bind(&UserManagerScreenHandler::HandleInitialize,
498 base::Unretained(this)));
499 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
500 base::Bind(&UserManagerScreenHandler::HandleAddUser,
501 base::Unretained(this)));
502 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
503 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
504 base::Unretained(this)));
505 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
506 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
507 base::Unretained(this)));
508 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
509 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
510 base::Unretained(this)));
511 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
512 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
513 base::Unretained(this)));
514 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
515 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
516 base::Unretained(this)));
518 const content::WebUI::MessageCallback& kDoNothingCallback =
519 base::Bind(&HandleAndDoNothing);
521 // Unused callbacks from screen_account_picker.js
522 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
523 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
524 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
525 web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback);
526 // Unused callbacks from display_manager.js
527 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
528 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
529 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
530 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
531 // Unused callbacks from user_pod_row.js
532 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
535 void UserManagerScreenHandler::GetLocalizedValues(
536 base::DictionaryValue* localized_strings) {
538 localized_strings->SetString("signedIn",
539 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
540 localized_strings->SetString("signinButton",
541 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
542 localized_strings->SetString("addUser",
543 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
544 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
545 localized_strings->SetString("browseAsGuest",
546 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
547 localized_strings->SetString("signOutUser",
548 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
550 // For AccountPickerScreen.
551 localized_strings->SetString("screenType", "login-add-user");
552 localized_strings->SetString("highlightStrength", "normal");
553 localized_strings->SetString("title",
554 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
555 localized_strings->SetString("passwordHint",
556 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
557 localized_strings->SetString("podMenuButtonAccessibleName",
558 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
559 localized_strings->SetString("podMenuRemoveItemAccessibleName",
560 l10n_util::GetStringUTF16(
561 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
562 localized_strings->SetString("removeUser",
563 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
564 localized_strings->SetString("passwordFieldAccessibleName",
565 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
566 localized_strings->SetString("bootIntoWallpaper", "off");
568 // For AccountPickerScreen, the remove user warning overlay.
569 localized_strings->SetString("removeUserWarningButtonTitle",
570 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
571 localized_strings->SetString("removeUserWarningText",
572 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
573 localized_strings->SetString("removeSupervisedUserWarningText",
574 l10n_util::GetStringFUTF16(
575 IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING,
576 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)));
578 // Strings needed for the User Manager tutorial slides.
579 localized_strings->SetString("tutorialNext",
580 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT));
581 localized_strings->SetString("tutorialDone",
582 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE));
583 localized_strings->SetString("slideWelcomeTitle",
584 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE));
585 localized_strings->SetString("slideWelcomeText",
586 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT));
587 localized_strings->SetString("slideYourChromeTitle",
588 l10n_util::GetStringUTF16(
589 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE));
590 localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
591 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT));
592 localized_strings->SetString("slideGuestsTitle",
593 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE));
594 localized_strings->SetString("slideGuestsText",
595 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT));
596 localized_strings->SetString("slideFriendsTitle",
597 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE));
598 localized_strings->SetString("slideFriendsText",
599 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT));
600 localized_strings->SetString("slideCompleteTitle",
601 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE));
602 localized_strings->SetString("slideCompleteText",
603 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT));
604 localized_strings->SetString("slideCompleteUserNotFound",
605 l10n_util::GetStringUTF16(
606 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND));
607 localized_strings->SetString("slideCompleteAddUser",
608 l10n_util::GetStringUTF16(
609 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER));
611 // Strings needed for the user_pod_template public account div, but not ever
612 // actually displayed for desktop users.
613 localized_strings->SetString("publicAccountReminder", base::string16());
614 localized_strings->SetString("publicSessionLanguageAndInput",
616 localized_strings->SetString("publicAccountEnter", base::string16());
617 localized_strings->SetString("publicAccountEnterAccessibleName",
619 localized_strings->SetString("publicSessionSelectLanguage", base::string16());
620 localized_strings->SetString("publicSessionSelectKeyboard", base::string16());
621 localized_strings->SetString("signinBannerText", base::string16());
622 localized_strings->SetString("launchAppButton", base::string16());
623 localized_strings->SetString("multiProfilesRestrictedPolicyTitle",
625 localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
627 localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
629 localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
633 void UserManagerScreenHandler::SendUserList() {
634 base::ListValue users_list;
635 base::FilePath active_profile_path =
636 web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
637 const ProfileInfoCache& info_cache =
638 g_browser_process->profile_manager()->GetProfileInfoCache();
640 user_auth_type_map_.clear();
642 // If the active user is a supervised user, then they may not perform
643 // certain actions (i.e. delete another user).
644 bool active_user_is_supervised = Profile::FromWebUI(web_ui())->IsSupervised();
645 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
646 base::DictionaryValue* profile_value = new base::DictionaryValue();
648 base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
649 bool is_active_user = (profile_path == active_profile_path);
651 profile_value->SetString(
652 kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i));
653 profile_value->SetString(
654 kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i));
655 // The profiles displayed in the User Manager are never guest profiles.
656 profile_value->SetString(
658 profiles::GetAvatarNameForProfile(profile_path));
659 profile_value->SetString(kKeyProfilePath, profile_path.MaybeAsASCII());
660 profile_value->SetBoolean(kKeyPublicAccount, false);
661 profile_value->SetBoolean(
662 kKeySupervisedUser, info_cache.ProfileIsSupervisedAtIndex(i));
663 profile_value->SetBoolean(kKeySignedIn, is_active_user);
664 profile_value->SetBoolean(
665 kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i));
666 profile_value->SetBoolean(kKeyIsOwner, false);
667 profile_value->SetBoolean(kKeyCanRemove, !active_user_is_supervised);
668 profile_value->SetBoolean(kKeyIsDesktop, true);
669 profile_value->SetString(
670 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
672 // The row of user pods should display the active user first.
674 users_list.Insert(0, profile_value);
676 users_list.Append(profile_value);
679 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
680 users_list, base::FundamentalValue(IsGuestModeEnabled()));
683 void UserManagerScreenHandler::ReportAuthenticationResult(
685 ProfileMetrics::ProfileAuth auth) {
686 ProfileMetrics::LogProfileAuthResult(auth);
687 password_attempt_.clear();
690 ProfileInfoCache& info_cache =
691 g_browser_process->profile_manager()->GetProfileInfoCache();
692 info_cache.SetProfileSigninRequiredAtIndex(
693 authenticating_profile_index_, false);
694 base::FilePath path = info_cache.GetPathOfProfileAtIndex(
695 authenticating_profile_index_);
696 profiles::SwitchToProfile(
700 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
701 weak_ptr_factory_.GetWeakPtr()),
702 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
704 web_ui()->CallJavascriptFunction(
705 "cr.ui.Oobe.showSignInError",
706 base::FundamentalValue(0),
707 base::StringValue(l10n_util::GetStringUTF8(
708 auth == ProfileMetrics::AUTH_FAILED_OFFLINE ?
709 IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE :
710 IDS_LOGIN_ERROR_AUTHENTICATING)),
711 base::StringValue(""),
712 base::FundamentalValue(0));
716 void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) {
718 DCHECK(browser->window());
719 if (url_hash_ == profiles::kUserManagerSelectProfileTaskManager) {
720 base::MessageLoop::current()->PostTask(
721 FROM_HERE, base::Bind(&chrome::ShowTaskManager, browser));
722 } else if (url_hash_ == profiles::kUserManagerSelectProfileAboutChrome) {
723 base::MessageLoop::current()->PostTask(
724 FROM_HERE, base::Bind(&chrome::ShowAboutChrome, browser));
727 // This call is last as it deletes this object.
731 void UserManagerScreenHandler::Observe(
733 const content::NotificationSource& source,
734 const content::NotificationDetails& details) {
736 case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
737 // Only respond to one Browser Window Ready event.
738 registrar_.Remove(this,
739 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
740 content::NotificationService::AllSources());
741 OnBrowserWindowReady(content::Source<Browser>(source).ptr());
748 // This callback is run after switching to a new profile has finished. This
749 // means either a new browser has been created (but not the window), or an
750 // existing one has been found. The HideUserManager task needs to be posted
751 // since closing the User Manager before the window is created can flakily
752 // cause Chrome to close.
753 void UserManagerScreenHandler::OnSwitchToProfileComplete(
754 Profile* profile, Profile::CreateStatus profile_create_status) {
755 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
756 if (browser && browser->window()) {
757 OnBrowserWindowReady(browser);
760 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
761 content::NotificationService::AllSources());