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