c8104f767934026b1f38cad2b6f9dca25e9876b5
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
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.
4
5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
6
7 #include "base/bind.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"
43
44 namespace {
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";
58
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";
67
68 const size_t kAvatarIconSize = 180;
69
70 void HandleAndDoNothing(const base::ListValue* args) {
71 }
72
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,
77     Profile* profile,
78     Profile::CreateStatus status) {
79   if (status != Profile::CREATE_STATUS_INITIALIZED)
80     return;
81   profiles::FindOrCreateNewWindowForProfile(
82     profile,
83     chrome::startup::IS_PROCESS_STARTUP,
84     chrome::startup::IS_FIRST_RUN,
85     desktop_type,
86     false);
87 }
88
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(
97         FROM_HERE,
98         base::Bind(&chrome::HideUserManager));
99 }
100
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);
106
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());
115   }
116   gfx::Image resized_image = profiles::GetSizedAvatarIcon(
117       avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
118   return webui::GetBitmapDataUrl(resized_image.AsBitmap());
119 }
120
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 &&
126         (name.empty() ||
127          profiles::GetAvatarNameForProfile(
128              info_cache.GetPathOfProfileAtIndex(i)) == name)) {
129       return i;
130     }
131   }
132   return std::string::npos;
133 }
134
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(
144       profile);
145 }
146
147 bool IsGuestModeEnabled() {
148   PrefService* service = g_browser_process->local_state();
149   DCHECK(service);
150   return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
151 }
152
153 }  // namespace
154
155 // ProfileUpdateObserver ------------------------------------------------------
156
157 class UserManagerScreenHandler::ProfileUpdateObserver
158     : public ProfileInfoCacheObserver {
159  public:
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);
167   }
168
169   virtual ~ProfileUpdateObserver() {
170     DCHECK(profile_manager_);
171     profile_manager_->GetProfileInfoCache().RemoveObserver(this);
172   }
173
174  private:
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();
180   }
181
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();
188   }
189
190   virtual void OnProfileNameChanged(
191       const base::FilePath& profile_path,
192       const base::string16& old_profile_name) OVERRIDE {
193     user_manager_handler_->SendUserList();
194   }
195
196   virtual void OnProfileAvatarChanged(
197       const base::FilePath& profile_path) OVERRIDE {
198     user_manager_handler_->SendUserList();
199   }
200
201   virtual void OnProfileSigninRequiredChanged(
202       const base::FilePath& profile_path) OVERRIDE {
203     user_manager_handler_->SendUserList();
204   }
205
206   ProfileManager* profile_manager_;
207
208   UserManagerScreenHandler* user_manager_handler_;  // Weak; owns us.
209
210   DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
211 };
212
213 // UserManagerScreenHandler ---------------------------------------------------
214
215 UserManagerScreenHandler::UserManagerScreenHandler()
216     : desktop_type_(chrome::GetActiveDesktop()) {
217   profileInfoCacheObserver_.reset(
218       new UserManagerScreenHandler::ProfileUpdateObserver(
219           g_browser_process->profile_manager(), this));
220 }
221
222 UserManagerScreenHandler::~UserManagerScreenHandler() {
223   ScreenlockBridge::Get()->SetLockHandler(NULL);
224 }
225
226 void UserManagerScreenHandler::ShowBannerMessage(
227     const base::string16& message) {
228   web_ui()->CallJavascriptFunction(
229       "login.AccountPickerScreen.showBannerMessage",
230       base::StringValue(message));
231 }
232
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())
238     return;
239   web_ui()->CallJavascriptFunction(
240       "login.AccountPickerScreen.showUserPodCustomIcon",
241       base::StringValue(user_email),
242       *icon);
243 }
244
245 void UserManagerScreenHandler::HideUserPodCustomIcon(
246     const std::string& user_email) {
247   web_ui()->CallJavascriptFunction(
248       "login.AccountPickerScreen.hideUserPodCustomIcon",
249       base::StringValue(user_email));
250 }
251
252 void UserManagerScreenHandler::EnableInput() {
253   // Nothing here because UI is not disabled when starting to authenticate.
254 }
255
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));
266 }
267
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;
273   return it->second;
274 }
275
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());
282
283   authenticating_profile_index_ = profile_index;
284   ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
285 }
286
287 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
288   SendUserList();
289   web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
290       base::FundamentalValue(IsGuestModeEnabled()));
291   desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
292       web_ui()->GetWebContents()->GetNativeView());
293
294   ScreenlockBridge::Get()->SetLockHandler(this);
295 }
296
297 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
298   profiles::CreateAndSwitchToNewProfile(desktop_type_,
299                                         base::Bind(&OnSwitchToProfileComplete),
300                                         ProfileMetrics::ADD_NEW_USER_MANAGER);
301 }
302
303 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
304     const base::ListValue* args) {
305   base::string16 email_address;
306   if (!args->GetString(0, &email_address))
307     return;
308
309   base::string16 display_name;
310   if (!args->GetString(1, &display_name))
311     return;
312
313   std::string password;
314   if (!args->GetString(2, &password))
315     return;
316
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()) {
322     NOTREACHED();
323     return;
324   }
325
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(
332         this,
333         GaiaConstants::kChromeSource,
334         web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
335     std::string email_string;
336     args->GetString(0, &email_string);
337     client_login_->StartClientLogin(
338         email_string,
339         password,
340         GaiaConstants::kSyncService,
341         std::string(),
342         std::string(),
343         GaiaAuthFetcher::HostedAccountsAllowed);
344     password_attempt_ = password;
345     return;
346   }
347
348   ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
349 }
350
351 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
352   DCHECK(args);
353   const base::Value* profile_path_value;
354   if (!args->Get(0, &profile_path_value))
355     return;
356
357   base::FilePath profile_path;
358   if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
359     return;
360
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
363   // case.
364   if (Profile::FromWebUI(web_ui())->IsSupervised())
365     return;
366
367   if (!profiles::IsMultipleProfilesEnabled())
368     return;
369
370   g_browser_process->profile_manager()->ScheduleProfileForDeletion(
371       profile_path,
372       base::Bind(&OpenNewWindowForProfile, desktop_type_));
373   ProfileMetrics::LogProfileDeleteUser(
374       ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
375 }
376
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);
382   } else {
383     // The UI should have prevented the user from allowing the selection of
384     // guest mode.
385     NOTREACHED();
386   }
387 }
388
389 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
390   base::string16 email_address;
391   base::string16 display_name;
392
393   if (!args->GetString(0, &email_address) ||
394       !args->GetString(1, &display_name)) {
395     NOTREACHED();
396     return;
397   }
398
399   ProfileInfoCache& info_cache =
400       g_browser_process->profile_manager()->GetProfileInfoCache();
401   size_t profile_index = GetIndexOfProfileWithEmailAndName(
402       info_cache, email_address, display_name);
403
404   if (profile_index >= info_cache.GetNumberOfProfiles()) {
405     NOTREACHED();
406     return;
407   }
408
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))
415     return;
416   ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
417
418   base::FilePath path = info_cache.GetPathOfProfileAtIndex(profile_index);
419   profiles::SwitchToProfile(path,
420                             desktop_type_,
421                             false,  /* reuse any existing windows */
422                             base::Bind(&OnSwitchToProfileComplete),
423                             ProfileMetrics::SWITCH_PROFILE_MANAGER);
424 }
425
426 void UserManagerScreenHandler::HandleAttemptUnlock(
427     const base::ListValue* args) {
428   std::string email;
429   CHECK(args->GetString(0, &email));
430   GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
431 }
432
433 void UserManagerScreenHandler::OnClientLoginSuccess(
434     const ClientLoginResult& result) {
435   chrome::SetLocalAuthCredentials(authenticating_profile_index_,
436                                   password_attempt_);
437   ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
438 }
439
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);
454 }
455
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)));
478
479   const content::WebUI::MessageCallback& kDoNothingCallback =
480       base::Bind(&HandleAndDoNothing);
481
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);
493 }
494
495 void UserManagerScreenHandler::GetLocalizedValues(
496     base::DictionaryValue* localized_strings) {
497   // For Control Bar.
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));
509
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");
527
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)));
537
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));
570
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",
575                                base::string16());
576   localized_strings->SetString("publicAccountEnter", base::string16());
577   localized_strings->SetString("publicAccountEnterAccessibleName",
578                                base::string16());
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",
584                                base::string16());
585   localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
586                                 base::string16());
587   localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
588                                 base::string16());
589   localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
590                                 base::string16());
591 }
592
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();
599
600   user_auth_type_map_.clear();
601
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();
607
608     base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
609     bool is_active_user = (profile_path == active_profile_path);
610
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(
617         kKeyDisplayName,
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));
631
632     // The row of user pods should display the active user first.
633     if (is_active_user)
634       users_list.Insert(0, profile_value);
635     else
636       users_list.Append(profile_value);
637   }
638
639   web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
640       users_list, base::FundamentalValue(IsGuestModeEnabled()));
641 }
642
643 void UserManagerScreenHandler::ReportAuthenticationResult(
644     bool success,
645     ProfileMetrics::ProfileAuth auth) {
646   ProfileMetrics::LogProfileAuthResult(auth);
647   password_attempt_.clear();
648
649   if (success) {
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);
659   } else {
660     web_ui()->CallJavascriptFunction(
661         "cr.ui.Oobe.showSignInError",
662         base::FundamentalValue(0),
663         base::StringValue(
664             l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_AUTHENTICATING)),
665         base::StringValue(""),
666         base::FundamentalValue(0));
667   }
668 }