Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
index d969164..7512ce8 100644 (file)
@@ -5,35 +5,45 @@
 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
 
 #include "base/bind.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_info_cache_observer.h"
-#include "chrome/browser/profiles/profile_info_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_metrics.h"
 #include "chrome/browser/profiles/profile_window.h"
 #include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/signin/local_auth.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/singleton_tabs.h"
+#include "chrome/browser/ui/user_manager.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
 #include "content/public/browser/web_ui.h"
-#include "grit/browser_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_constants.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_util.h"
 
-#if defined(ENABLE_MANAGED_USERS)
-#include "chrome/browser/managed_mode/managed_user_service.h"
-#endif
-
 namespace {
 // User dictionary keys.
 const char kKeyUsername[] = "username";
@@ -41,7 +51,7 @@ const char kKeyDisplayName[]= "displayName";
 const char kKeyEmailAddress[] = "emailAddress";
 const char kKeyProfilePath[] = "profilePath";
 const char kKeyPublicAccount[] = "publicAccount";
-const char kKeyLocallyManagedUser[] = "locallyManagedUser";
+const char kKeySupervisedUser[] = "supervisedUser";
 const char kKeySignedIn[] = "signedIn";
 const char kKeyCanRemove[] = "canRemove";
 const char kKeyIsOwner[] = "isOwner";
@@ -52,9 +62,11 @@ const char kKeyNeedsSignin[] = "needsSignin";
 // JS API callback names.
 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
 const char kJsApiUserManagerAddUser[] = "addUser";
+const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
 const char kJsApiUserManagerLaunchUser[] = "launchUser";
 const char kJsApiUserManagerRemoveUser[] = "removeUser";
+const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
 
 const size_t kAvatarIconSize = 180;
 
@@ -83,13 +95,59 @@ std::string GetAvatarImageAtIndex(
       info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
       info_cache.GetGAIAPictureOfProfileAtIndex(index);
 
-  gfx::Image icon = profiles::GetSizedAvatarIconWithBorder(
-      info_cache.GetAvatarIconOfProfileAtIndex(index),
-      is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
-  return webui::GetBitmapDataUrl(icon.AsBitmap());
+  // If the avatar is too small (i.e. the old-style low resolution avatar),
+  // it will be pixelated when displayed in the User Manager, so we should
+  // return the placeholder avatar instead.
+  gfx::Image avatar_image = info_cache.GetAvatarIconOfProfileAtIndex(index);
+  if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
+      avatar_image.Height() <= profiles::kAvatarIconHeight ) {
+    avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+        profiles::GetPlaceholderAvatarIconResourceID());
+  }
+  gfx::Image resized_image = profiles::GetSizedAvatarIcon(
+      avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
+  return webui::GetBitmapDataUrl(resized_image.AsBitmap());
 }
 
-} // namespace
+size_t GetIndexOfProfileWithEmailAndName(const ProfileInfoCache& info_cache,
+                                         const base::string16& email,
+                                         const base::string16& name) {
+  for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
+    if (info_cache.GetUserNameOfProfileAtIndex(i) == email &&
+        (name.empty() ||
+         profiles::GetAvatarNameForProfile(
+             info_cache.GetPathOfProfileAtIndex(i)) == name)) {
+      return i;
+    }
+  }
+  return std::string::npos;
+}
+
+extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
+    const std::string& email) {
+  ProfileInfoCache& info_cache =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  const size_t profile_index = GetIndexOfProfileWithEmailAndName(
+      info_cache, base::UTF8ToUTF16(email), base::string16());
+  Profile* profile = g_browser_process->profile_manager()
+      ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index));
+  return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
+      profile);
+}
+
+bool IsGuestModeEnabled() {
+  PrefService* service = g_browser_process->local_state();
+  DCHECK(service);
+  return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
+}
+
+bool IsAddPersonEnabled() {
+  PrefService* service = g_browser_process->local_state();
+  DCHECK(service);
+  return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
+}
+
+}  // namespace
 
 // ProfileUpdateObserver ------------------------------------------------------
 
@@ -118,23 +176,26 @@ class UserManagerScreenHandler::ProfileUpdateObserver
     user_manager_handler_->SendUserList();
   }
 
-  virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
-                                   const string16& profile_name) OVERRIDE {
+  virtual void OnProfileWasRemoved(
+      const base::FilePath& profile_path,
+      const base::string16& profile_name) OVERRIDE {
+    // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
+    // UserManager is able to find pod belonging to removed user.
     user_manager_handler_->SendUserList();
   }
 
-  virtual void OnProfileWillBeRemoved(
-      const base::FilePath& profile_path) OVERRIDE {
-    // No-op. When the profile is actually removed, OnProfileWasRemoved
-    // will be called.
+  virtual void OnProfileNameChanged(
+      const base::FilePath& profile_path,
+      const base::string16& old_profile_name) OVERRIDE {
+    user_manager_handler_->SendUserList();
   }
 
-  virtual void OnProfileNameChanged(const base::FilePath& profile_path,
-                                    const string16& old_profile_name) OVERRIDE {
+  virtual void OnProfileAvatarChanged(
+      const base::FilePath& profile_path) OVERRIDE {
     user_manager_handler_->SendUserList();
   }
 
-  virtual void OnProfileAvatarChanged(
+  virtual void OnProfileSigninRequiredChanged(
       const base::FilePath& profile_path) OVERRIDE {
     user_manager_handler_->SendUserList();
   }
@@ -149,30 +210,167 @@ class UserManagerScreenHandler::ProfileUpdateObserver
 // UserManagerScreenHandler ---------------------------------------------------
 
 UserManagerScreenHandler::UserManagerScreenHandler()
-    : desktop_type_(chrome::GetActiveDesktop()) {
+    : desktop_type_(chrome::GetActiveDesktop()),
+      weak_ptr_factory_(this) {
   profileInfoCacheObserver_.reset(
       new UserManagerScreenHandler::ProfileUpdateObserver(
           g_browser_process->profile_manager(), this));
 }
 
 UserManagerScreenHandler::~UserManagerScreenHandler() {
+  ScreenlockBridge::Get()->SetLockHandler(NULL);
+}
+
+void UserManagerScreenHandler::ShowBannerMessage(
+    const base::string16& message) {
+  web_ui()->CallJavascriptFunction(
+      "login.AccountPickerScreen.showBannerMessage",
+      base::StringValue(message));
+}
+
+void UserManagerScreenHandler::ShowUserPodCustomIcon(
+    const std::string& user_email,
+    const ScreenlockBridge::UserPodCustomIconOptions& icon_options) {
+  scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
+  if (!icon || icon->empty())
+    return;
+  web_ui()->CallJavascriptFunction(
+      "login.AccountPickerScreen.showUserPodCustomIcon",
+      base::StringValue(user_email),
+      *icon);
+}
+
+void UserManagerScreenHandler::HideUserPodCustomIcon(
+    const std::string& user_email) {
+  web_ui()->CallJavascriptFunction(
+      "login.AccountPickerScreen.hideUserPodCustomIcon",
+      base::StringValue(user_email));
+}
+
+void UserManagerScreenHandler::EnableInput() {
+  // Nothing here because UI is not disabled when starting to authenticate.
+}
+
+void UserManagerScreenHandler::SetAuthType(
+    const std::string& user_email,
+    ScreenlockBridge::LockHandler::AuthType auth_type,
+    const base::string16& auth_value) {
+  if (GetAuthType(user_email) ==
+          ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
+    return;
+
+  user_auth_type_map_[user_email] = auth_type;
+  web_ui()->CallJavascriptFunction(
+      "login.AccountPickerScreen.setAuthType",
+      base::StringValue(user_email),
+      base::FundamentalValue(auth_type),
+      base::StringValue(auth_value));
+}
+
+ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType(
+      const std::string& user_email) const {
+  UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email);
+  if (it == user_auth_type_map_.end())
+    return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
+  return it->second;
+}
+
+void UserManagerScreenHandler::Unlock(const std::string& user_email) {
+  ProfileInfoCache& info_cache =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  const size_t profile_index = GetIndexOfProfileWithEmailAndName(
+      info_cache, base::UTF8ToUTF16(user_email), base::string16());
+  DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles());
+
+  authenticating_profile_index_ = profile_index;
+  ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
+}
+
+void UserManagerScreenHandler::AttemptEasySignin(
+    const std::string& user_email,
+    const std::string& secret,
+    const std::string& key_label) {
+  NOTREACHED();
 }
 
 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
+  // If the URL has a hash parameter, store it for later.
+  args->GetString(0, &url_hash_);
+
   SendUserList();
-  web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
+  web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
+      base::FundamentalValue(IsGuestModeEnabled()),
+      base::FundamentalValue(IsAddPersonEnabled()));
   desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
-      web_ui()->GetWebContents()->GetView()->GetNativeView());
+      web_ui()->GetWebContents()->GetNativeView());
+
+  ScreenlockBridge::Get()->SetLockHandler(this);
 }
 
 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
-  profiles::CreateAndSwitchToNewProfile(desktop_type_,
-                                        base::Bind(&chrome::HideUserManager));
+  if (!IsAddPersonEnabled()) {
+    // The 'Add User' UI should not be showing.
+    NOTREACHED();
+    return;
+  }
+  profiles::CreateAndSwitchToNewProfile(
+      desktop_type_,
+      base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
+                 weak_ptr_factory_.GetWeakPtr()),
+      ProfileMetrics::ADD_NEW_USER_MANAGER);
+}
+
+void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
+    const base::ListValue* args) {
+  base::string16 email_address;
+  if (!args->GetString(0, &email_address))
+    return;
+
+  base::string16 display_name;
+  if (!args->GetString(1, &display_name))
+    return;
+
+  std::string password;
+  if (!args->GetString(2, &password))
+    return;
+
+  ProfileInfoCache& info_cache =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  size_t profile_index = GetIndexOfProfileWithEmailAndName(
+      info_cache, email_address, display_name);
+  if (profile_index >= info_cache.GetNumberOfProfiles()) {
+    NOTREACHED();
+    return;
+  }
+
+  authenticating_profile_index_ = profile_index;
+  if (!chrome::ValidateLocalAuthCredentials(profile_index, password)) {
+    // Make a second attempt via an on-line authentication call.  This handles
+    // profiles that are missing sign-in credentials and also cases where the
+    // password has been changed externally.
+    client_login_.reset(new GaiaAuthFetcher(
+        this,
+        GaiaConstants::kChromeSource,
+        web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
+    std::string email_string;
+    args->GetString(0, &email_string);
+    client_login_->StartClientLogin(
+        email_string,
+        password,
+        GaiaConstants::kSyncService,
+        std::string(),
+        std::string(),
+        GaiaAuthFetcher::HostedAccountsAllowed);
+    password_attempt_ = password;
+    return;
+  }
+
+  ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
 }
 
 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
   DCHECK(args);
-  const Value* profile_path_value;
+  const base::Value* profile_path_value;
   if (!args->Get(0, &profile_path_value))
     return;
 
@@ -180,9 +378,10 @@ void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
   if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
     return;
 
-  // This handler could have been called in managed mode, for example because
-  // the user fiddled with the web inspector. Silently return in this case.
-  if (Profile::FromWebUI(web_ui())->IsManaged())
+  // This handler could have been called for a supervised user, for example
+  // because the user fiddled with the web inspector. Silently return in this
+  // case.
+  if (Profile::FromWebUI(web_ui())->IsSupervised())
     return;
 
   if (!profiles::IsMultipleProfilesEnabled())
@@ -191,35 +390,106 @@ void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
   g_browser_process->profile_manager()->ScheduleProfileForDeletion(
       profile_path,
       base::Bind(&OpenNewWindowForProfile, desktop_type_));
+  ProfileMetrics::LogProfileDeleteUser(
+      ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
 }
 
 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
-  profiles::SwitchToGuestProfile(desktop_type_,
-                                 base::Bind(&chrome::HideUserManager));
+  if (IsGuestModeEnabled()) {
+    ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST);
+    profiles::SwitchToGuestProfile(
+        desktop_type_,
+        base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
+                   weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    // The UI should have prevented the user from allowing the selection of
+    // guest mode.
+    NOTREACHED();
+  }
 }
 
 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
-  string16 emailAddress;
-  string16 displayName;
+  base::string16 email_address;
+  base::string16 display_name;
 
-  if (!args->GetString(0, &emailAddress) ||
-      !args->GetString(1, &displayName)) {
+  if (!args->GetString(0, &email_address) ||
+      !args->GetString(1, &display_name)) {
     NOTREACHED();
     return;
   }
 
   ProfileInfoCache& info_cache =
       g_browser_process->profile_manager()->GetProfileInfoCache();
+  size_t profile_index = GetIndexOfProfileWithEmailAndName(
+      info_cache, email_address, display_name);
 
-  for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
-    if (info_cache.GetUserNameOfProfileAtIndex(i) == emailAddress &&
-        info_cache.GetNameOfProfileAtIndex(i) == displayName) {
-      base::FilePath path = info_cache.GetPathOfProfileAtIndex(i);
-      profiles::SwitchToProfile(path, chrome::GetActiveDesktop(), true,
-                                base::Bind(&chrome::HideUserManager));
-      break;
-    }
+  if (profile_index >= info_cache.GetNumberOfProfiles()) {
+    NOTREACHED();
+    return;
   }
+
+  // It's possible that a user breaks into the user-manager page using the
+  // JavaScript Inspector and causes a "locked" profile to call this
+  // unauthenticated version of "launch" instead of the proper one.  Thus,
+  // we have to validate in (secure) C++ code that it really is a profile
+  // not needing authentication.  If it is, just ignore the "launch" request.
+  if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
+    return;
+  ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
+
+  base::FilePath path = info_cache.GetPathOfProfileAtIndex(profile_index);
+  profiles::SwitchToProfile(
+      path,
+      desktop_type_,
+      false,  /* reuse any existing windows */
+      base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
+                 weak_ptr_factory_.GetWeakPtr()),
+      ProfileMetrics::SWITCH_PROFILE_MANAGER);
+}
+
+void UserManagerScreenHandler::HandleAttemptUnlock(
+    const base::ListValue* args) {
+  std::string email;
+  CHECK(args->GetString(0, &email));
+  GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
+}
+
+void UserManagerScreenHandler::HandleHardlockUserPod(
+    const base::ListValue* args) {
+  std::string email;
+  CHECK(args->GetString(0, &email));
+  SetAuthType(email,
+              ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
+              base::string16());
+  HideUserPodCustomIcon(email);
+}
+
+void UserManagerScreenHandler::OnClientLoginSuccess(
+    const ClientLoginResult& result) {
+  chrome::SetLocalAuthCredentials(authenticating_profile_index_,
+                                  password_attempt_);
+  ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
+}
+
+void UserManagerScreenHandler::OnClientLoginFailure(
+    const GoogleServiceAuthError& error) {
+  const GoogleServiceAuthError::State state = error.state();
+  // Some "error" results mean the password was correct but some other action
+  // should be taken.  For our purposes, we only care that the password was
+  // correct so count those as a success.
+  bool success = (state == GoogleServiceAuthError::NONE ||
+                  state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
+                  state == GoogleServiceAuthError::TWO_FACTOR ||
+                  state == GoogleServiceAuthError::ACCOUNT_DELETED ||
+                  state == GoogleServiceAuthError::ACCOUNT_DISABLED);
+  bool offline = (state == GoogleServiceAuthError::CONNECTION_FAILED ||
+                  state == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
+                  state == GoogleServiceAuthError::REQUEST_CANCELED);
+  ProfileMetrics::ProfileAuth failure_metric =
+      offline ? ProfileMetrics::AUTH_FAILED_OFFLINE :
+                ProfileMetrics::AUTH_FAILED;
+  ReportAuthenticationResult(
+      success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric);
 }
 
 void UserManagerScreenHandler::RegisterMessages() {
@@ -229,6 +499,9 @@ void UserManagerScreenHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
       base::Bind(&UserManagerScreenHandler::HandleAddUser,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
+      base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
+                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
       base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
                  base::Unretained(this)));
@@ -238,6 +511,9 @@ void UserManagerScreenHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
       base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
+      base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
+                 base::Unretained(this)));
 
   const content::WebUI::MessageCallback& kDoNothingCallback =
       base::Bind(&HandleAndDoNothing);
@@ -246,6 +522,7 @@ void UserManagerScreenHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
   web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
   web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
+  web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback);
   // Unused callbacks from display_manager.js
   web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
   web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
@@ -274,7 +551,7 @@ void UserManagerScreenHandler::GetLocalizedValues(
   localized_strings->SetString("screenType", "login-add-user");
   localized_strings->SetString("highlightStrength", "normal");
   localized_strings->SetString("title",
-      l10n_util::GetStringUTF16(IDS_USER_MANAGER_SCREEN_TITLE));
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
   localized_strings->SetString("passwordHint",
       l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
   localized_strings->SetString("podMenuButtonAccessibleName",
@@ -292,29 +569,81 @@ void UserManagerScreenHandler::GetLocalizedValues(
   localized_strings->SetString("removeUserWarningButtonTitle",
       l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
   localized_strings->SetString("removeUserWarningText",
+      l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
+  localized_strings->SetString("removeSupervisedUserWarningText",
+      l10n_util::GetStringFUTF16(
+          IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING,
+          base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)));
+
+  // Strings needed for the User Manager tutorial slides.
+  localized_strings->SetString("tutorialNext",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT));
+  localized_strings->SetString("tutorialDone",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE));
+  localized_strings->SetString("slideWelcomeTitle",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE));
+  localized_strings->SetString("slideWelcomeText",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT));
+  localized_strings->SetString("slideYourChromeTitle",
       l10n_util::GetStringUTF16(
-           IDS_LOGIN_POD_USER_REMOVE_WARNING));
+          IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE));
+  localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
+      IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT));
+  localized_strings->SetString("slideGuestsTitle",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE));
+  localized_strings->SetString("slideGuestsText",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT));
+  localized_strings->SetString("slideFriendsTitle",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE));
+  localized_strings->SetString("slideFriendsText",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT));
+  localized_strings->SetString("slideCompleteTitle",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE));
+  localized_strings->SetString("slideCompleteText",
+      l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT));
+  localized_strings->SetString("slideCompleteUserNotFound",
+      l10n_util::GetStringUTF16(
+          IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND));
+  localized_strings->SetString("slideCompleteAddUser",
+      l10n_util::GetStringUTF16(
+          IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER));
 
   // Strings needed for the user_pod_template public account div, but not ever
   // actually displayed for desktop users.
-  localized_strings->SetString("publicAccountReminder", string16());
-  localized_strings->SetString("publicAccountEnter", string16());
-  localized_strings->SetString("publicAccountEnterAccessibleName", string16());
-  localized_strings->SetString("multiple-signin-banner-text", string16());
- }
+  localized_strings->SetString("publicAccountReminder", base::string16());
+  localized_strings->SetString("publicSessionLanguageAndInput",
+                               base::string16());
+  localized_strings->SetString("publicAccountEnter", base::string16());
+  localized_strings->SetString("publicAccountEnterAccessibleName",
+                               base::string16());
+  localized_strings->SetString("publicSessionSelectLanguage", base::string16());
+  localized_strings->SetString("publicSessionSelectKeyboard", base::string16());
+  localized_strings->SetString("signinBannerText", base::string16());
+  localized_strings->SetString("launchAppButton", base::string16());
+  localized_strings->SetString("multiProfilesRestrictedPolicyTitle",
+                               base::string16());
+  localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
+                                base::string16());
+  localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
+                                base::string16());
+  localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
+                                base::string16());
+}
 
 void UserManagerScreenHandler::SendUserList() {
-  ListValue users_list;
+  base::ListValue users_list;
   base::FilePath active_profile_path =
       web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
   const ProfileInfoCache& info_cache =
       g_browser_process->profile_manager()->GetProfileInfoCache();
 
-  // If the active user is a managed user, then they may not perform
+  user_auth_type_map_.clear();
+
+  // If the active user is a supervised user, then they may not perform
   // certain actions (i.e. delete another user).
-  bool active_user_is_managed = Profile::FromWebUI(web_ui())->IsManaged();
+  bool active_user_is_supervised = Profile::FromWebUI(web_ui())->IsSupervised();
   for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
-    DictionaryValue* profile_value = new DictionaryValue();
+    base::DictionaryValue* profile_value = new base::DictionaryValue();
 
     base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
     bool is_active_user = (profile_path == active_profile_path);
@@ -323,16 +652,19 @@ void UserManagerScreenHandler::SendUserList() {
         kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i));
     profile_value->SetString(
         kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i));
+    // The profiles displayed in the User Manager are never guest profiles.
     profile_value->SetString(
-        kKeyDisplayName, info_cache.GetNameOfProfileAtIndex(i));
+        kKeyDisplayName,
+        profiles::GetAvatarNameForProfile(profile_path));
     profile_value->SetString(kKeyProfilePath, profile_path.MaybeAsASCII());
     profile_value->SetBoolean(kKeyPublicAccount, false);
-    profile_value->SetBoolean(kKeyLocallyManagedUser, false);
+    profile_value->SetBoolean(
+        kKeySupervisedUser, info_cache.ProfileIsSupervisedAtIndex(i));
     profile_value->SetBoolean(kKeySignedIn, is_active_user);
     profile_value->SetBoolean(
         kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i));
     profile_value->SetBoolean(kKeyIsOwner, false);
-    profile_value->SetBoolean(kKeyCanRemove, !active_user_is_managed);
+    profile_value->SetBoolean(kKeyCanRemove, !active_user_is_supervised);
     profile_value->SetBoolean(kKeyIsDesktop, true);
     profile_value->SetString(
         kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
@@ -345,5 +677,87 @@ void UserManagerScreenHandler::SendUserList() {
   }
 
   web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
-    users_list, base::FundamentalValue(false), base::FundamentalValue(true));
+      users_list, base::FundamentalValue(IsGuestModeEnabled()));
+}
+
+void UserManagerScreenHandler::ReportAuthenticationResult(
+    bool success,
+    ProfileMetrics::ProfileAuth auth) {
+  ProfileMetrics::LogProfileAuthResult(auth);
+  password_attempt_.clear();
+
+  if (success) {
+    ProfileInfoCache& info_cache =
+        g_browser_process->profile_manager()->GetProfileInfoCache();
+    info_cache.SetProfileSigninRequiredAtIndex(
+        authenticating_profile_index_, false);
+    base::FilePath path = info_cache.GetPathOfProfileAtIndex(
+        authenticating_profile_index_);
+    profiles::SwitchToProfile(
+        path,
+        desktop_type_,
+        true,
+        base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
+                   weak_ptr_factory_.GetWeakPtr()),
+        ProfileMetrics::SWITCH_PROFILE_UNLOCK);
+  } else {
+    web_ui()->CallJavascriptFunction(
+        "cr.ui.Oobe.showSignInError",
+        base::FundamentalValue(0),
+        base::StringValue(l10n_util::GetStringUTF8(
+            auth == ProfileMetrics::AUTH_FAILED_OFFLINE ?
+                IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE :
+                IDS_LOGIN_ERROR_AUTHENTICATING)),
+        base::StringValue(""),
+        base::FundamentalValue(0));
+  }
+}
+
+void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) {
+  DCHECK(browser);
+  DCHECK(browser->window());
+  if (url_hash_ == profiles::kUserManagerSelectProfileTaskManager) {
+     base::MessageLoop::current()->PostTask(
+         FROM_HERE, base::Bind(&chrome::ShowTaskManager, browser));
+  } else if (url_hash_ == profiles::kUserManagerSelectProfileAboutChrome) {
+     base::MessageLoop::current()->PostTask(
+         FROM_HERE, base::Bind(&chrome::ShowAboutChrome, browser));
+  }
+
+  // This call is last as it deletes this object.
+  UserManager::Hide();
+}
+
+void UserManagerScreenHandler::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  switch (type) {
+    case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
+      // Only respond to one Browser Window Ready event.
+      registrar_.Remove(this,
+                        chrome::NOTIFICATION_BROWSER_WINDOW_READY,
+                        content::NotificationService::AllSources());
+      OnBrowserWindowReady(content::Source<Browser>(source).ptr());
+    break;
+    default:
+      NOTREACHED();
+  }
+}
+
+// This callback is run after switching to a new profile has finished. This
+// means either a new browser has been created (but not the window), or an
+// existing one has been found. The HideUserManager task needs to be posted
+// since closing the User Manager before the window is created can flakily
+// cause Chrome to close.
+void UserManagerScreenHandler::OnSwitchToProfileComplete(
+    Profile* profile, Profile::CreateStatus profile_create_status) {
+  Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
+  if (browser && browser->window()) {
+    OnBrowserWindowReady(browser);
+  } else {
+    registrar_.Add(this,
+                   chrome::NOTIFICATION_BROWSER_WINDOW_READY,
+                   content::NotificationService::AllSources());
+  }
 }