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