Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
blobb009483bd207f98e3906a13e9da8b9e68bcc9531
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
7 #include "base/bind.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/profiler/scoped_tracker.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/value_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
18 #include "chrome/browser/profiles/profile_info_cache.h"
19 #include "chrome/browser/profiles/profile_info_cache_observer.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/profiles/profile_metrics.h"
22 #include "chrome/browser/profiles/profile_window.h"
23 #include "chrome/browser/profiles/profiles_state.h"
24 #include "chrome/browser/signin/local_auth.h"
25 #include "chrome/browser/signin/proximity_auth_facade.h"
26 #include "chrome/browser/ui/app_list/app_list_service.h"
27 #include "chrome/browser/ui/browser_commands.h"
28 #include "chrome/browser/ui/browser_dialogs.h"
29 #include "chrome/browser/ui/browser_finder.h"
30 #include "chrome/browser/ui/browser_list.h"
31 #include "chrome/browser/ui/browser_list_observer.h"
32 #include "chrome/browser/ui/chrome_pages.h"
33 #include "chrome/browser/ui/singleton_tabs.h"
34 #include "chrome/browser/ui/user_manager.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h"
37 #include "chrome/grit/chromium_strings.h"
38 #include "chrome/grit/generated_resources.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/web_contents.h"
41 #include "content/public/browser/web_ui.h"
42 #include "google_apis/gaia/gaia_auth_fetcher.h"
43 #include "google_apis/gaia/gaia_constants.h"
44 #include "third_party/skia/include/core/SkBitmap.h"
45 #include "ui/base/l10n/l10n_util.h"
46 #include "ui/base/resource/resource_bundle.h"
47 #include "ui/base/webui/web_ui_util.h"
48 #include "ui/gfx/image/image.h"
49 #include "ui/gfx/image/image_skia.h"
50 #include "ui/gfx/image/image_util.h"
52 #if defined(USE_ASH)
53 #include "ash/shell.h"
54 #endif
56 namespace {
57 // User dictionary keys.
58 const char kKeyUsername[] = "username";
59 const char kKeyDisplayName[]= "displayName";
60 const char kKeyEmailAddress[] = "emailAddress";
61 const char kKeyProfilePath[] = "profilePath";
62 const char kKeyPublicAccount[] = "publicAccount";
63 const char kKeyLegacySupervisedUser[] = "legacySupervisedUser";
64 const char kKeyChildUser[] = "childUser";
65 const char kKeyCanRemove[] = "canRemove";
66 const char kKeyIsOwner[] = "isOwner";
67 const char kKeyIsDesktop[] = "isDesktopUser";
68 const char kKeyAvatarUrl[] = "userImage";
69 const char kKeyNeedsSignin[] = "needsSignin";
71 // JS API callback names.
72 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
73 const char kJsApiUserManagerAddUser[] = "addUser";
74 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
75 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
76 const char kJsApiUserManagerLaunchUser[] = "launchUser";
77 const char kJsApiUserManagerRemoveUser[] = "removeUser";
78 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
79 const char kJsApiUserManagerLogRemoveUserWarningShown[] =
80 "logRemoveUserWarningShown";
82 const size_t kAvatarIconSize = 180;
84 void HandleAndDoNothing(const base::ListValue* args) {
87 // This callback is run if the only profile has been deleted, and a new
88 // profile has been created to replace it.
89 void OpenNewWindowForProfile(
90 chrome::HostDesktopType desktop_type,
91 Profile* profile,
92 Profile::CreateStatus status) {
93 if (status != Profile::CREATE_STATUS_INITIALIZED)
94 return;
95 profiles::FindOrCreateNewWindowForProfile(
96 profile,
97 chrome::startup::IS_PROCESS_STARTUP,
98 chrome::startup::IS_FIRST_RUN,
99 desktop_type,
100 false);
103 std::string GetAvatarImageAtIndex(
104 size_t index, ProfileInfoCache* info_cache) {
105 bool is_gaia_picture =
106 info_cache->IsUsingGAIAPictureOfProfileAtIndex(index) &&
107 info_cache->GetGAIAPictureOfProfileAtIndex(index);
109 // If the avatar is too small (i.e. the old-style low resolution avatar),
110 // it will be pixelated when displayed in the User Manager, so we should
111 // return the placeholder avatar instead.
112 gfx::Image avatar_image = info_cache->GetAvatarIconOfProfileAtIndex(index);
113 if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
114 avatar_image.Height() <= profiles::kAvatarIconHeight ) {
115 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
116 profiles::GetPlaceholderAvatarIconResourceID());
118 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
119 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
120 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
123 size_t GetIndexOfProfileWithEmail(const ProfileInfoCache& info_cache,
124 const std::string& email) {
125 const base::string16& profile_email = base::UTF8ToUTF16(email);
126 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
127 if (info_cache.GetUserNameOfProfileAtIndex(i) == profile_email)
128 return i;
130 return std::string::npos;
133 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
134 const std::string& email) {
135 const ProfileInfoCache& info_cache =
136 g_browser_process->profile_manager()->GetProfileInfoCache();
137 const size_t profile_index = GetIndexOfProfileWithEmail(info_cache, email);
138 Profile* profile = g_browser_process->profile_manager()
139 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index));
140 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
141 profile);
144 bool IsGuestModeEnabled() {
145 PrefService* service = g_browser_process->local_state();
146 DCHECK(service);
147 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
150 bool IsAddPersonEnabled() {
151 PrefService* service = g_browser_process->local_state();
152 DCHECK(service);
153 return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
156 // Executes the action specified by the URL's Hash parameter, if any. Deletes
157 // itself after the action would be performed.
158 class UrlHashHelper : public chrome::BrowserListObserver {
159 public:
160 UrlHashHelper(Browser* browser, const std::string& hash);
161 ~UrlHashHelper() override;
163 void ExecuteUrlHash();
165 // chrome::BrowserListObserver overrides:
166 void OnBrowserRemoved(Browser* browser) override;
168 private:
169 Browser* browser_;
170 Profile* profile_;
171 chrome::HostDesktopType desktop_type_;
172 std::string hash_;
174 DISALLOW_COPY_AND_ASSIGN(UrlHashHelper);
177 UrlHashHelper::UrlHashHelper(Browser* browser, const std::string& hash)
178 : browser_(browser),
179 profile_(browser->profile()),
180 desktop_type_(browser->host_desktop_type()),
181 hash_(hash) {
182 BrowserList::AddObserver(this);
185 UrlHashHelper::~UrlHashHelper() {
186 BrowserList::RemoveObserver(this);
189 void UrlHashHelper::OnBrowserRemoved(Browser* browser) {
190 if (browser == browser_)
191 browser_ = nullptr;
194 void UrlHashHelper::ExecuteUrlHash() {
195 if (hash_ == profiles::kUserManagerSelectProfileAppLauncher) {
196 AppListService* app_list_service = AppListService::Get(desktop_type_);
197 app_list_service->ShowForProfile(profile_);
198 return;
201 Browser* target_browser = browser_;
202 if (!target_browser) {
203 target_browser = chrome::FindLastActiveWithProfile(profile_, desktop_type_);
204 if (!target_browser)
205 return;
208 if (hash_ == profiles::kUserManagerSelectProfileTaskManager)
209 chrome::OpenTaskManager(target_browser);
210 else if (hash_ == profiles::kUserManagerSelectProfileAboutChrome)
211 chrome::ShowAboutChrome(target_browser);
212 else if (hash_ == profiles::kUserManagerSelectProfileChromeSettings)
213 chrome::ShowSettings(target_browser);
214 else if (hash_ == profiles::kUserManagerSelectProfileChromeMemory)
215 chrome::ShowMemory(target_browser);
218 void HandleLogRemoveUserWarningShown(const base::ListValue* args) {
219 ProfileMetrics::LogProfileDeleteUser(
220 ProfileMetrics::DELETE_PROFILE_USER_MANAGER_SHOW_WARNING);
223 } // namespace
225 // ProfileUpdateObserver ------------------------------------------------------
227 class UserManagerScreenHandler::ProfileUpdateObserver
228 : public ProfileInfoCacheObserver {
229 public:
230 ProfileUpdateObserver(
231 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
232 : profile_manager_(profile_manager),
233 user_manager_handler_(handler) {
234 DCHECK(profile_manager_);
235 DCHECK(user_manager_handler_);
236 profile_manager_->GetProfileInfoCache().AddObserver(this);
239 ~ProfileUpdateObserver() override {
240 DCHECK(profile_manager_);
241 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
244 private:
245 // ProfileInfoCacheObserver implementation:
246 // If any change has been made to a profile, propagate it to all the
247 // visible user manager screens.
248 void OnProfileAdded(const base::FilePath& profile_path) override {
249 user_manager_handler_->SendUserList();
252 void OnProfileWasRemoved(const base::FilePath& profile_path,
253 const base::string16& profile_name) override {
254 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
255 // UserManager is able to find pod belonging to removed user.
256 user_manager_handler_->SendUserList();
259 void OnProfileNameChanged(const base::FilePath& profile_path,
260 const base::string16& old_profile_name) override {
261 user_manager_handler_->SendUserList();
264 void OnProfileAvatarChanged(const base::FilePath& profile_path) override {
265 user_manager_handler_->SendUserList();
268 void OnProfileHighResAvatarLoaded(
269 const base::FilePath& profile_path) override {
270 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/461175
271 // is fixed.
272 tracked_objects::ScopedTracker tracking_profile(
273 FROM_HERE_WITH_EXPLICIT_FUNCTION(
274 "461175 UserManagerScreenHandler::OnProfileHighResAvatarLoaded"));
275 user_manager_handler_->SendUserList();
278 void OnProfileSigninRequiredChanged(
279 const base::FilePath& profile_path) override {
280 user_manager_handler_->SendUserList();
283 ProfileManager* profile_manager_;
285 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
287 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
290 // UserManagerScreenHandler ---------------------------------------------------
292 UserManagerScreenHandler::UserManagerScreenHandler()
293 : desktop_type_(chrome::GetActiveDesktop()),
294 weak_ptr_factory_(this) {
295 profileInfoCacheObserver_.reset(
296 new UserManagerScreenHandler::ProfileUpdateObserver(
297 g_browser_process->profile_manager(), this));
300 UserManagerScreenHandler::~UserManagerScreenHandler() {
301 GetScreenlockBridgeInstance()->SetLockHandler(NULL);
304 void UserManagerScreenHandler::ShowBannerMessage(
305 const base::string16& message) {
306 web_ui()->CallJavascriptFunction(
307 "login.AccountPickerScreen.showBannerMessage",
308 base::StringValue(message));
311 void UserManagerScreenHandler::ShowUserPodCustomIcon(
312 const std::string& user_email,
313 const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions&
314 icon_options) {
315 scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
316 if (!icon || icon->empty())
317 return;
318 web_ui()->CallJavascriptFunction(
319 "login.AccountPickerScreen.showUserPodCustomIcon",
320 base::StringValue(user_email),
321 *icon);
324 void UserManagerScreenHandler::HideUserPodCustomIcon(
325 const std::string& user_email) {
326 web_ui()->CallJavascriptFunction(
327 "login.AccountPickerScreen.hideUserPodCustomIcon",
328 base::StringValue(user_email));
331 void UserManagerScreenHandler::EnableInput() {
332 // Nothing here because UI is not disabled when starting to authenticate.
335 void UserManagerScreenHandler::SetAuthType(
336 const std::string& user_email,
337 proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type,
338 const base::string16& auth_value) {
339 if (GetAuthType(user_email) ==
340 proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
341 return;
343 user_auth_type_map_[user_email] = auth_type;
344 web_ui()->CallJavascriptFunction(
345 "login.AccountPickerScreen.setAuthType",
346 base::StringValue(user_email),
347 base::FundamentalValue(auth_type),
348 base::StringValue(auth_value));
351 proximity_auth::ScreenlockBridge::LockHandler::AuthType
352 UserManagerScreenHandler::GetAuthType(const std::string& user_email) const {
353 UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email);
354 if (it == user_auth_type_map_.end())
355 return proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
356 return it->second;
359 proximity_auth::ScreenlockBridge::LockHandler::ScreenType
360 UserManagerScreenHandler::GetScreenType() const {
361 return proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN;
364 void UserManagerScreenHandler::Unlock(const std::string& user_email) {
365 const ProfileInfoCache& info_cache =
366 g_browser_process->profile_manager()->GetProfileInfoCache();
367 const size_t profile_index =
368 GetIndexOfProfileWithEmail(info_cache, user_email);
369 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles());
371 authenticating_profile_index_ = profile_index;
372 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
375 void UserManagerScreenHandler::AttemptEasySignin(
376 const std::string& user_email,
377 const std::string& secret,
378 const std::string& key_label) {
379 NOTREACHED();
382 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
383 // If the URL has a hash parameter, store it for later.
384 args->GetString(0, &url_hash_);
386 SendUserList();
387 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
388 base::FundamentalValue(IsGuestModeEnabled()),
389 base::FundamentalValue(IsAddPersonEnabled()));
390 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
391 web_ui()->GetWebContents()->GetNativeView());
393 GetScreenlockBridgeInstance()->SetLockHandler(this);
396 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
397 if (!IsAddPersonEnabled()) {
398 // The 'Add User' UI should not be showing.
399 NOTREACHED();
400 return;
402 profiles::CreateAndSwitchToNewProfile(
403 desktop_type_,
404 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
405 weak_ptr_factory_.GetWeakPtr()),
406 ProfileMetrics::ADD_NEW_USER_MANAGER);
409 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
410 const base::ListValue* args) {
411 const base::Value* profile_path_value;
412 if (!args->Get(0, &profile_path_value))
413 return;
415 base::FilePath profile_path;
416 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
417 return;
419 base::string16 email_address;
420 if (!args->GetString(1, &email_address))
421 return;
423 std::string password;
424 if (!args->GetString(2, &password))
425 return;
427 const ProfileInfoCache& info_cache =
428 g_browser_process->profile_manager()->GetProfileInfoCache();
429 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
431 if (profile_index == std::string::npos) {
432 NOTREACHED();
433 return;
436 authenticating_profile_index_ = profile_index;
437 if (!LocalAuth::ValidateLocalAuthCredentials(profile_index, password)) {
438 // Make a second attempt via an on-line authentication call. This handles
439 // profiles that are missing sign-in credentials and also cases where the
440 // password has been changed externally.
441 client_login_.reset(new GaiaAuthFetcher(
442 this,
443 GaiaConstants::kChromeSource,
444 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
446 client_login_->StartClientLogin(
447 base::UTF16ToUTF8(email_address),
448 password,
449 GaiaConstants::kSyncService,
450 std::string(),
451 std::string(),
452 GaiaAuthFetcher::HostedAccountsAllowed);
453 password_attempt_ = password;
454 return;
457 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
460 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
461 DCHECK(args);
462 const base::Value* profile_path_value;
463 if (!args->Get(0, &profile_path_value)) {
464 NOTREACHED();
465 return;
468 base::FilePath profile_path;
469 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) {
470 NOTREACHED();
471 return;
474 if (!profiles::IsMultipleProfilesEnabled()) {
475 NOTREACHED();
476 return;
479 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
480 profile_path,
481 base::Bind(&OpenNewWindowForProfile, desktop_type_));
482 ProfileMetrics::LogProfileDeleteUser(
483 ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
486 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
487 if (IsGuestModeEnabled()) {
488 profiles::SwitchToGuestProfile(
489 desktop_type_,
490 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
491 weak_ptr_factory_.GetWeakPtr()));
492 } else {
493 // The UI should have prevented the user from allowing the selection of
494 // guest mode.
495 NOTREACHED();
499 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
500 const base::Value* profile_path_value = NULL;
501 if (!args->Get(0, &profile_path_value))
502 return;
504 base::FilePath profile_path;
505 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
506 return;
508 const ProfileInfoCache& info_cache =
509 g_browser_process->profile_manager()->GetProfileInfoCache();
510 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
512 if (profile_index == std::string::npos) {
513 NOTREACHED();
514 return;
517 // It's possible that a user breaks into the user-manager page using the
518 // JavaScript Inspector and causes a "locked" profile to call this
519 // unauthenticated version of "launch" instead of the proper one. Thus,
520 // we have to validate in (secure) C++ code that it really is a profile
521 // not needing authentication. If it is, just ignore the "launch" request.
522 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
523 return;
524 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
526 profiles::SwitchToProfile(
527 profile_path,
528 desktop_type_,
529 false, /* reuse any existing windows */
530 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
531 weak_ptr_factory_.GetWeakPtr()),
532 ProfileMetrics::SWITCH_PROFILE_MANAGER);
535 void UserManagerScreenHandler::HandleAttemptUnlock(
536 const base::ListValue* args) {
537 std::string email;
538 CHECK(args->GetString(0, &email));
539 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
542 void UserManagerScreenHandler::HandleHardlockUserPod(
543 const base::ListValue* args) {
544 std::string email;
545 CHECK(args->GetString(0, &email));
546 SetAuthType(
547 email,
548 proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
549 base::string16());
550 HideUserPodCustomIcon(email);
553 void UserManagerScreenHandler::OnClientLoginSuccess(
554 const ClientLoginResult& result) {
555 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
556 password_attempt_);
557 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
560 void UserManagerScreenHandler::OnClientLoginFailure(
561 const GoogleServiceAuthError& error) {
562 const GoogleServiceAuthError::State state = error.state();
563 // Some "error" results mean the password was correct but some other action
564 // should be taken. For our purposes, we only care that the password was
565 // correct so count those as a success.
566 bool success = (state == GoogleServiceAuthError::NONE ||
567 state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
568 state == GoogleServiceAuthError::TWO_FACTOR ||
569 state == GoogleServiceAuthError::ACCOUNT_DELETED ||
570 state == GoogleServiceAuthError::ACCOUNT_DISABLED ||
571 state == GoogleServiceAuthError::WEB_LOGIN_REQUIRED);
573 // If the password was correct, the user must have changed it since the
574 // profile was locked. Save the password to streamline future unlocks.
575 if (success) {
576 DCHECK(!password_attempt_.empty());
577 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
578 password_attempt_);
581 bool offline = error.IsTransientError();
582 ProfileMetrics::ProfileAuth failure_metric =
583 offline ? ProfileMetrics::AUTH_FAILED_OFFLINE :
584 ProfileMetrics::AUTH_FAILED;
585 ReportAuthenticationResult(
586 success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric);
589 void UserManagerScreenHandler::RegisterMessages() {
590 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
591 base::Bind(&UserManagerScreenHandler::HandleInitialize,
592 base::Unretained(this)));
593 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
594 base::Bind(&UserManagerScreenHandler::HandleAddUser,
595 base::Unretained(this)));
596 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
597 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
598 base::Unretained(this)));
599 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
600 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
601 base::Unretained(this)));
602 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
603 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
604 base::Unretained(this)));
605 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
606 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
607 base::Unretained(this)));
608 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
609 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
610 base::Unretained(this)));
611 web_ui()->RegisterMessageCallback(kJsApiUserManagerLogRemoveUserWarningShown,
612 base::Bind(&HandleLogRemoveUserWarningShown));
614 const content::WebUI::MessageCallback& kDoNothingCallback =
615 base::Bind(&HandleAndDoNothing);
617 // Unused callbacks from screen_account_picker.js
618 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
619 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
620 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
621 web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback);
622 // Unused callbacks from display_manager.js
623 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
624 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
625 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
626 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
627 // Unused callbacks from user_pod_row.js
628 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
631 void UserManagerScreenHandler::GetLocalizedValues(
632 base::DictionaryValue* localized_strings) {
633 // For Control Bar.
634 localized_strings->SetString("signedIn",
635 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
636 localized_strings->SetString("signinButton",
637 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
638 localized_strings->SetString("addUser",
639 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
640 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
641 localized_strings->SetString("browseAsGuest",
642 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
643 localized_strings->SetString("signOutUser",
644 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
645 localized_strings->SetString("addSupervisedUser",
646 l10n_util::GetStringUTF16(IDS_CREATE_SUPERVISED_USER_MENU_LABEL));
648 // For AccountPickerScreen.
649 localized_strings->SetString("screenType", "login-add-user");
650 localized_strings->SetString("highlightStrength", "normal");
651 localized_strings->SetString("title",
652 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
653 localized_strings->SetString("passwordHint",
654 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
655 localized_strings->SetString("signingIn",
656 l10n_util::GetStringUTF16(IDS_LOGIN_POD_SIGNING_IN));
657 localized_strings->SetString("podMenuButtonAccessibleName",
658 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
659 localized_strings->SetString("podMenuRemoveItemAccessibleName",
660 l10n_util::GetStringUTF16(
661 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
662 localized_strings->SetString("removeUser",
663 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
664 localized_strings->SetString("passwordFieldAccessibleName",
665 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
666 localized_strings->SetString("bootIntoWallpaper", "off");
668 // For AccountPickerScreen, the remove user warning overlay.
669 localized_strings->SetString("removeUserWarningButtonTitle",
670 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
671 localized_strings->SetString("removeUserWarningText",
672 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
673 localized_strings->SetString("removeLegacySupervisedUserWarningText",
674 l10n_util::GetStringFUTF16(
675 IDS_LOGIN_POD_LEGACY_SUPERVISED_USER_REMOVE_WARNING,
676 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)));
678 // Strings needed for the User Manager tutorial slides.
679 localized_strings->SetString("tutorialNext",
680 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT));
681 localized_strings->SetString("tutorialDone",
682 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE));
683 localized_strings->SetString("slideWelcomeTitle",
684 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE));
685 localized_strings->SetString("slideWelcomeText",
686 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT));
687 localized_strings->SetString("slideYourChromeTitle",
688 l10n_util::GetStringUTF16(
689 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE));
690 localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
691 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT));
692 localized_strings->SetString("slideGuestsTitle",
693 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE));
694 localized_strings->SetString("slideGuestsText",
695 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT));
696 localized_strings->SetString("slideFriendsTitle",
697 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE));
698 localized_strings->SetString("slideFriendsText",
699 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT));
700 localized_strings->SetString("slideCompleteTitle",
701 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE));
702 localized_strings->SetString("slideCompleteText",
703 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT));
704 localized_strings->SetString("slideCompleteUserNotFound",
705 l10n_util::GetStringUTF16(
706 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND));
707 localized_strings->SetString("slideCompleteAddUser",
708 l10n_util::GetStringUTF16(
709 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER));
711 // Strings needed for the user_pod_template public account div, but not ever
712 // actually displayed for desktop users.
713 localized_strings->SetString("publicAccountReminder", base::string16());
714 localized_strings->SetString("publicSessionLanguageAndInput",
715 base::string16());
716 localized_strings->SetString("publicAccountEnter", base::string16());
717 localized_strings->SetString("publicAccountEnterAccessibleName",
718 base::string16());
719 localized_strings->SetString("publicSessionSelectLanguage", base::string16());
720 localized_strings->SetString("publicSessionSelectKeyboard", base::string16());
721 localized_strings->SetString("signinBannerText", base::string16());
722 localized_strings->SetString("launchAppButton", base::string16());
723 localized_strings->SetString("multiProfilesRestrictedPolicyTitle",
724 base::string16());
725 localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
726 base::string16());
727 localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
728 base::string16());
729 localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
730 base::string16());
733 void UserManagerScreenHandler::SendUserList() {
734 base::ListValue users_list;
735 ProfileInfoCache* info_cache =
736 &g_browser_process->profile_manager()->GetProfileInfoCache();
737 user_auth_type_map_.clear();
739 // Profile deletion is not allowed in Metro mode.
740 bool can_remove = true;
741 #if defined(USE_ASH)
742 can_remove = !ash::Shell::HasInstance();
743 #endif
745 for (size_t i = 0; i < info_cache->GetNumberOfProfiles(); ++i) {
746 base::DictionaryValue* profile_value = new base::DictionaryValue();
747 base::FilePath profile_path = info_cache->GetPathOfProfileAtIndex(i);
749 profile_value->SetString(
750 kKeyUsername, info_cache->GetUserNameOfProfileAtIndex(i));
751 profile_value->SetString(
752 kKeyEmailAddress, info_cache->GetUserNameOfProfileAtIndex(i));
753 profile_value->SetString(
754 kKeyDisplayName,
755 profiles::GetAvatarNameForProfile(profile_path));
756 profile_value->Set(
757 kKeyProfilePath, base::CreateFilePathValue(profile_path));
758 profile_value->SetBoolean(kKeyPublicAccount, false);
759 profile_value->SetBoolean(kKeyLegacySupervisedUser,
760 info_cache->ProfileIsLegacySupervisedAtIndex(i));
761 profile_value->SetBoolean(
762 kKeyChildUser, info_cache->ProfileIsChildAtIndex(i));
763 profile_value->SetBoolean(
764 kKeyNeedsSignin, info_cache->ProfileIsSigninRequiredAtIndex(i));
765 profile_value->SetBoolean(kKeyIsOwner, false);
766 profile_value->SetBoolean(kKeyCanRemove, can_remove);
767 profile_value->SetBoolean(kKeyIsDesktop, true);
768 profile_value->SetString(
769 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
771 users_list.Append(profile_value);
774 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
775 users_list, base::FundamentalValue(IsGuestModeEnabled()));
777 // This is the latest C++ code we have in the flow to show the UserManager.
778 // This may be invoked more than once per UserManager lifetime; the
779 // UserManager will ensure all relevant logging only happens once.
780 UserManager::OnUserManagerShown();
783 void UserManagerScreenHandler::ReportAuthenticationResult(
784 bool success,
785 ProfileMetrics::ProfileAuth auth) {
786 ProfileMetrics::LogProfileAuthResult(auth);
787 password_attempt_.clear();
789 if (success) {
790 const ProfileInfoCache& info_cache =
791 g_browser_process->profile_manager()->GetProfileInfoCache();
792 base::FilePath path = info_cache.GetPathOfProfileAtIndex(
793 authenticating_profile_index_);
794 profiles::SwitchToProfile(
795 path,
796 desktop_type_,
797 true,
798 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
799 weak_ptr_factory_.GetWeakPtr()),
800 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
801 } else {
802 web_ui()->CallJavascriptFunction(
803 "cr.ui.Oobe.showSignInError",
804 base::FundamentalValue(0),
805 base::StringValue(l10n_util::GetStringUTF8(
806 auth == ProfileMetrics::AUTH_FAILED_OFFLINE ?
807 IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE :
808 IDS_LOGIN_ERROR_AUTHENTICATING)),
809 base::StringValue(""),
810 base::FundamentalValue(0));
814 void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) {
815 DCHECK(browser);
816 DCHECK(browser->window());
818 // Unlock the profile after browser opens so startup can read the lock bit.
819 // Any necessary authentication must have been successful to reach this point.
820 if (!browser->profile()->IsGuestSession()) {
821 ProfileInfoCache& info_cache =
822 g_browser_process->profile_manager()->GetProfileInfoCache();
823 size_t index = info_cache.GetIndexOfProfileWithPath(
824 browser->profile()->GetPath());
825 info_cache.SetProfileSigninRequiredAtIndex(index, false);
828 if (!url_hash_.empty()) {
829 base::MessageLoop::current()->PostTask(
830 FROM_HERE,
831 base::Bind(&UrlHashHelper::ExecuteUrlHash,
832 base::Owned(new UrlHashHelper(browser, url_hash_))));
835 // This call is last as it deletes this object.
836 UserManager::Hide();
839 void UserManagerScreenHandler::Observe(
840 int type,
841 const content::NotificationSource& source,
842 const content::NotificationDetails& details) {
843 switch (type) {
844 case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
845 // Only respond to one Browser Window Ready event.
846 registrar_.Remove(this,
847 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
848 content::NotificationService::AllSources());
849 OnBrowserWindowReady(content::Source<Browser>(source).ptr());
850 break;
851 default:
852 NOTREACHED();
856 // This callback is run after switching to a new profile has finished. This
857 // means either a new browser has been created (but not the window), or an
858 // existing one has been found. The HideUserManager task needs to be posted
859 // since closing the User Manager before the window is created can flakily
860 // cause Chrome to close.
861 void UserManagerScreenHandler::OnSwitchToProfileComplete(
862 Profile* profile, Profile::CreateStatus profile_create_status) {
863 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
864 if (browser && browser->window()) {
865 OnBrowserWindowReady(browser);
866 } else {
867 registrar_.Add(this,
868 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
869 content::NotificationService::AllSources());