Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
blob95a25f43df7fda70d51d3df71f220022a9f22f96
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/ui/app_list/app_list_service.h"
26 #include "chrome/browser/ui/browser_commands.h"
27 #include "chrome/browser/ui/browser_dialogs.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/browser_list_observer.h"
31 #include "chrome/browser/ui/chrome_pages.h"
32 #include "chrome/browser/ui/singleton_tabs.h"
33 #include "chrome/browser/ui/user_manager.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "chrome/grit/chromium_strings.h"
37 #include "chrome/grit/generated_resources.h"
38 #include "content/public/browser/notification_service.h"
39 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/web_ui.h"
41 #include "google_apis/gaia/gaia_auth_fetcher.h"
42 #include "google_apis/gaia/gaia_constants.h"
43 #include "third_party/skia/include/core/SkBitmap.h"
44 #include "ui/base/l10n/l10n_util.h"
45 #include "ui/base/resource/resource_bundle.h"
46 #include "ui/base/webui/web_ui_util.h"
47 #include "ui/gfx/image/image.h"
48 #include "ui/gfx/image/image_skia.h"
49 #include "ui/gfx/image/image_util.h"
51 #if defined(USE_ASH)
52 #include "ash/shell.h"
53 #endif
55 namespace {
56 // User dictionary keys.
57 const char kKeyUsername[] = "username";
58 const char kKeyDisplayName[]= "displayName";
59 const char kKeyEmailAddress[] = "emailAddress";
60 const char kKeyProfilePath[] = "profilePath";
61 const char kKeyPublicAccount[] = "publicAccount";
62 const char kKeyLegacySupervisedUser[] = "legacySupervisedUser";
63 const char kKeyChildUser[] = "childUser";
64 const char kKeyCanRemove[] = "canRemove";
65 const char kKeyIsOwner[] = "isOwner";
66 const char kKeyIsDesktop[] = "isDesktopUser";
67 const char kKeyAvatarUrl[] = "userImage";
68 const char kKeyNeedsSignin[] = "needsSignin";
70 // JS API callback names.
71 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
72 const char kJsApiUserManagerAddUser[] = "addUser";
73 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
74 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
75 const char kJsApiUserManagerLaunchUser[] = "launchUser";
76 const char kJsApiUserManagerRemoveUser[] = "removeUser";
77 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
78 const char kJsApiUserManagerLogRemoveUserWarningShown[] =
79 "logRemoveUserWarningShown";
81 const size_t kAvatarIconSize = 180;
83 void HandleAndDoNothing(const base::ListValue* args) {
86 // This callback is run if the only profile has been deleted, and a new
87 // profile has been created to replace it.
88 void OpenNewWindowForProfile(
89 chrome::HostDesktopType desktop_type,
90 Profile* profile,
91 Profile::CreateStatus status) {
92 if (status != Profile::CREATE_STATUS_INITIALIZED)
93 return;
94 profiles::FindOrCreateNewWindowForProfile(
95 profile,
96 chrome::startup::IS_PROCESS_STARTUP,
97 chrome::startup::IS_FIRST_RUN,
98 desktop_type,
99 false);
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);
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());
117 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
118 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
119 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
122 size_t GetIndexOfProfileWithEmail(const ProfileInfoCache& info_cache,
123 const std::string& email) {
124 const base::string16& profile_email = base::UTF8ToUTF16(email);
125 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
126 if (info_cache.GetUserNameOfProfileAtIndex(i) == profile_email)
127 return i;
129 return std::string::npos;
132 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
133 const std::string& email) {
134 const ProfileInfoCache& info_cache =
135 g_browser_process->profile_manager()->GetProfileInfoCache();
136 const size_t profile_index = GetIndexOfProfileWithEmail(info_cache, email);
137 Profile* profile = g_browser_process->profile_manager()
138 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index));
139 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
140 profile);
143 bool IsGuestModeEnabled() {
144 PrefService* service = g_browser_process->local_state();
145 DCHECK(service);
146 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
149 bool IsAddPersonEnabled() {
150 PrefService* service = g_browser_process->local_state();
151 DCHECK(service);
152 return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
155 // Executes the action specified by the URL's Hash parameter, if any. Deletes
156 // itself after the action would be performed.
157 class UrlHashHelper : public chrome::BrowserListObserver {
158 public:
159 UrlHashHelper(Browser* browser, const std::string& hash);
160 ~UrlHashHelper() override;
162 void ExecuteUrlHash();
164 // chrome::BrowserListObserver overrides:
165 void OnBrowserRemoved(Browser* browser) override;
167 private:
168 Browser* browser_;
169 Profile* profile_;
170 chrome::HostDesktopType desktop_type_;
171 std::string hash_;
173 DISALLOW_COPY_AND_ASSIGN(UrlHashHelper);
176 UrlHashHelper::UrlHashHelper(Browser* browser, const std::string& hash)
177 : browser_(browser),
178 profile_(browser->profile()),
179 desktop_type_(browser->host_desktop_type()),
180 hash_(hash) {
181 BrowserList::AddObserver(this);
184 UrlHashHelper::~UrlHashHelper() {
185 BrowserList::RemoveObserver(this);
188 void UrlHashHelper::OnBrowserRemoved(Browser* browser) {
189 if (browser == browser_)
190 browser_ = nullptr;
193 void UrlHashHelper::ExecuteUrlHash() {
194 if (hash_ == profiles::kUserManagerSelectProfileAppLauncher) {
195 AppListService* app_list_service = AppListService::Get(desktop_type_);
196 app_list_service->ShowForProfile(profile_);
197 return;
200 Browser* target_browser = browser_;
201 if (!target_browser) {
202 target_browser = chrome::FindLastActiveWithProfile(profile_, desktop_type_);
203 if (!target_browser)
204 return;
207 if (hash_ == profiles::kUserManagerSelectProfileTaskManager)
208 chrome::OpenTaskManager(target_browser);
209 else if (hash_ == profiles::kUserManagerSelectProfileAboutChrome)
210 chrome::ShowAboutChrome(target_browser);
211 else if (hash_ == profiles::kUserManagerSelectProfileChromeSettings)
212 chrome::ShowSettings(target_browser);
213 else if (hash_ == profiles::kUserManagerSelectProfileChromeMemory)
214 chrome::ShowMemory(target_browser);
217 void HandleLogRemoveUserWarningShown(const base::ListValue* args) {
218 ProfileMetrics::LogProfileDeleteUser(
219 ProfileMetrics::DELETE_PROFILE_USER_MANAGER_SHOW_WARNING);
222 } // namespace
224 // ProfileUpdateObserver ------------------------------------------------------
226 class UserManagerScreenHandler::ProfileUpdateObserver
227 : public ProfileInfoCacheObserver {
228 public:
229 ProfileUpdateObserver(
230 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
231 : profile_manager_(profile_manager),
232 user_manager_handler_(handler) {
233 DCHECK(profile_manager_);
234 DCHECK(user_manager_handler_);
235 profile_manager_->GetProfileInfoCache().AddObserver(this);
238 ~ProfileUpdateObserver() override {
239 DCHECK(profile_manager_);
240 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
243 private:
244 // ProfileInfoCacheObserver implementation:
245 // If any change has been made to a profile, propagate it to all the
246 // visible user manager screens.
247 void OnProfileAdded(const base::FilePath& profile_path) override {
248 user_manager_handler_->SendUserList();
251 void OnProfileWasRemoved(const base::FilePath& profile_path,
252 const base::string16& profile_name) override {
253 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
254 // UserManager is able to find pod belonging to removed user.
255 user_manager_handler_->SendUserList();
258 void OnProfileNameChanged(const base::FilePath& profile_path,
259 const base::string16& old_profile_name) override {
260 user_manager_handler_->SendUserList();
263 void OnProfileAvatarChanged(const base::FilePath& profile_path) override {
264 user_manager_handler_->SendUserList();
267 void OnProfileHighResAvatarLoaded(
268 const base::FilePath& profile_path) override {
269 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/461175
270 // is fixed.
271 tracked_objects::ScopedTracker tracking_profile(
272 FROM_HERE_WITH_EXPLICIT_FUNCTION(
273 "461175 UserManagerScreenHandler::OnProfileHighResAvatarLoaded"));
274 user_manager_handler_->SendUserList();
277 void OnProfileSigninRequiredChanged(
278 const base::FilePath& profile_path) override {
279 user_manager_handler_->SendUserList();
282 ProfileManager* profile_manager_;
284 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
286 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
289 // UserManagerScreenHandler ---------------------------------------------------
291 UserManagerScreenHandler::UserManagerScreenHandler()
292 : desktop_type_(chrome::GetActiveDesktop()),
293 weak_ptr_factory_(this) {
294 profileInfoCacheObserver_.reset(
295 new UserManagerScreenHandler::ProfileUpdateObserver(
296 g_browser_process->profile_manager(), this));
299 UserManagerScreenHandler::~UserManagerScreenHandler() {
300 ScreenlockBridge::Get()->SetLockHandler(NULL);
303 void UserManagerScreenHandler::ShowBannerMessage(
304 const base::string16& message) {
305 web_ui()->CallJavascriptFunction(
306 "login.AccountPickerScreen.showBannerMessage",
307 base::StringValue(message));
310 void UserManagerScreenHandler::ShowUserPodCustomIcon(
311 const std::string& user_email,
312 const ScreenlockBridge::UserPodCustomIconOptions& icon_options) {
313 scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue();
314 if (!icon || icon->empty())
315 return;
316 web_ui()->CallJavascriptFunction(
317 "login.AccountPickerScreen.showUserPodCustomIcon",
318 base::StringValue(user_email),
319 *icon);
322 void UserManagerScreenHandler::HideUserPodCustomIcon(
323 const std::string& user_email) {
324 web_ui()->CallJavascriptFunction(
325 "login.AccountPickerScreen.hideUserPodCustomIcon",
326 base::StringValue(user_email));
329 void UserManagerScreenHandler::EnableInput() {
330 // Nothing here because UI is not disabled when starting to authenticate.
333 void UserManagerScreenHandler::SetAuthType(
334 const std::string& user_email,
335 ScreenlockBridge::LockHandler::AuthType auth_type,
336 const base::string16& auth_value) {
337 if (GetAuthType(user_email) ==
338 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD)
339 return;
341 user_auth_type_map_[user_email] = auth_type;
342 web_ui()->CallJavascriptFunction(
343 "login.AccountPickerScreen.setAuthType",
344 base::StringValue(user_email),
345 base::FundamentalValue(auth_type),
346 base::StringValue(auth_value));
349 ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType(
350 const std::string& user_email) const {
351 UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email);
352 if (it == user_auth_type_map_.end())
353 return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
354 return it->second;
357 ScreenlockBridge::LockHandler::ScreenType
358 UserManagerScreenHandler::GetScreenType() const {
359 return ScreenlockBridge::LockHandler::LOCK_SCREEN;
362 void UserManagerScreenHandler::Unlock(const std::string& user_email) {
363 const ProfileInfoCache& info_cache =
364 g_browser_process->profile_manager()->GetProfileInfoCache();
365 const size_t profile_index =
366 GetIndexOfProfileWithEmail(info_cache, user_email);
367 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles());
369 authenticating_profile_index_ = profile_index;
370 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
373 void UserManagerScreenHandler::AttemptEasySignin(
374 const std::string& user_email,
375 const std::string& secret,
376 const std::string& key_label) {
377 NOTREACHED();
380 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
381 // If the URL has a hash parameter, store it for later.
382 args->GetString(0, &url_hash_);
384 SendUserList();
385 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
386 base::FundamentalValue(IsGuestModeEnabled()),
387 base::FundamentalValue(IsAddPersonEnabled()));
388 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
389 web_ui()->GetWebContents()->GetNativeView());
391 ScreenlockBridge::Get()->SetLockHandler(this);
394 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
395 if (!IsAddPersonEnabled()) {
396 // The 'Add User' UI should not be showing.
397 NOTREACHED();
398 return;
400 profiles::CreateAndSwitchToNewProfile(
401 desktop_type_,
402 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
403 weak_ptr_factory_.GetWeakPtr()),
404 ProfileMetrics::ADD_NEW_USER_MANAGER);
407 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
408 const base::ListValue* args) {
409 const base::Value* profile_path_value;
410 if (!args->Get(0, &profile_path_value))
411 return;
413 base::FilePath profile_path;
414 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
415 return;
417 base::string16 email_address;
418 if (!args->GetString(1, &email_address))
419 return;
421 std::string password;
422 if (!args->GetString(2, &password))
423 return;
425 const ProfileInfoCache& info_cache =
426 g_browser_process->profile_manager()->GetProfileInfoCache();
427 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
429 if (profile_index == std::string::npos) {
430 NOTREACHED();
431 return;
434 authenticating_profile_index_ = profile_index;
435 if (!LocalAuth::ValidateLocalAuthCredentials(profile_index, password)) {
436 // Make a second attempt via an on-line authentication call. This handles
437 // profiles that are missing sign-in credentials and also cases where the
438 // password has been changed externally.
439 client_login_.reset(new GaiaAuthFetcher(
440 this,
441 GaiaConstants::kChromeSource,
442 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
444 client_login_->StartClientLogin(
445 base::UTF16ToUTF8(email_address),
446 password,
447 GaiaConstants::kSyncService,
448 std::string(),
449 std::string(),
450 GaiaAuthFetcher::HostedAccountsAllowed);
451 password_attempt_ = password;
452 return;
455 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
458 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
459 DCHECK(args);
460 const base::Value* profile_path_value;
461 if (!args->Get(0, &profile_path_value))
462 return;
464 base::FilePath profile_path;
465 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
466 return;
468 if (!profiles::IsMultipleProfilesEnabled())
469 return;
471 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
472 profile_path,
473 base::Bind(&OpenNewWindowForProfile, desktop_type_));
474 ProfileMetrics::LogProfileDeleteUser(
475 ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
478 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
479 if (IsGuestModeEnabled()) {
480 profiles::SwitchToGuestProfile(
481 desktop_type_,
482 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
483 weak_ptr_factory_.GetWeakPtr()));
484 } else {
485 // The UI should have prevented the user from allowing the selection of
486 // guest mode.
487 NOTREACHED();
491 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
492 const base::Value* profile_path_value = NULL;
493 if (!args->Get(0, &profile_path_value))
494 return;
496 base::FilePath profile_path;
497 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
498 return;
500 const ProfileInfoCache& info_cache =
501 g_browser_process->profile_manager()->GetProfileInfoCache();
502 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
504 if (profile_index == std::string::npos) {
505 NOTREACHED();
506 return;
509 // It's possible that a user breaks into the user-manager page using the
510 // JavaScript Inspector and causes a "locked" profile to call this
511 // unauthenticated version of "launch" instead of the proper one. Thus,
512 // we have to validate in (secure) C++ code that it really is a profile
513 // not needing authentication. If it is, just ignore the "launch" request.
514 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
515 return;
516 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
518 profiles::SwitchToProfile(
519 profile_path,
520 desktop_type_,
521 false, /* reuse any existing windows */
522 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
523 weak_ptr_factory_.GetWeakPtr()),
524 ProfileMetrics::SWITCH_PROFILE_MANAGER);
527 void UserManagerScreenHandler::HandleAttemptUnlock(
528 const base::ListValue* args) {
529 std::string email;
530 CHECK(args->GetString(0, &email));
531 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
534 void UserManagerScreenHandler::HandleHardlockUserPod(
535 const base::ListValue* args) {
536 std::string email;
537 CHECK(args->GetString(0, &email));
538 SetAuthType(email,
539 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
540 base::string16());
541 HideUserPodCustomIcon(email);
544 void UserManagerScreenHandler::OnClientLoginSuccess(
545 const ClientLoginResult& result) {
546 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
547 password_attempt_);
548 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
551 void UserManagerScreenHandler::OnClientLoginFailure(
552 const GoogleServiceAuthError& error) {
553 const GoogleServiceAuthError::State state = error.state();
554 // Some "error" results mean the password was correct but some other action
555 // should be taken. For our purposes, we only care that the password was
556 // correct so count those as a success.
557 bool success = (state == GoogleServiceAuthError::NONE ||
558 state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
559 state == GoogleServiceAuthError::TWO_FACTOR ||
560 state == GoogleServiceAuthError::ACCOUNT_DELETED ||
561 state == GoogleServiceAuthError::ACCOUNT_DISABLED ||
562 state == GoogleServiceAuthError::WEB_LOGIN_REQUIRED);
564 // If the password was correct, the user must have changed it since the
565 // profile was locked. Save the password to streamline future unlocks.
566 if (success) {
567 DCHECK(!password_attempt_.empty());
568 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
569 password_attempt_);
572 bool offline = (state == GoogleServiceAuthError::CONNECTION_FAILED ||
573 state == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
574 state == GoogleServiceAuthError::REQUEST_CANCELED);
575 ProfileMetrics::ProfileAuth failure_metric =
576 offline ? ProfileMetrics::AUTH_FAILED_OFFLINE :
577 ProfileMetrics::AUTH_FAILED;
578 ReportAuthenticationResult(
579 success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric);
582 void UserManagerScreenHandler::RegisterMessages() {
583 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
584 base::Bind(&UserManagerScreenHandler::HandleInitialize,
585 base::Unretained(this)));
586 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
587 base::Bind(&UserManagerScreenHandler::HandleAddUser,
588 base::Unretained(this)));
589 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
590 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
591 base::Unretained(this)));
592 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
593 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
594 base::Unretained(this)));
595 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
596 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
597 base::Unretained(this)));
598 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
599 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
600 base::Unretained(this)));
601 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
602 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
603 base::Unretained(this)));
604 web_ui()->RegisterMessageCallback(kJsApiUserManagerLogRemoveUserWarningShown,
605 base::Bind(&HandleLogRemoveUserWarningShown));
607 const content::WebUI::MessageCallback& kDoNothingCallback =
608 base::Bind(&HandleAndDoNothing);
610 // Unused callbacks from screen_account_picker.js
611 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
612 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
613 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
614 web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback);
615 // Unused callbacks from display_manager.js
616 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
617 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
618 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
619 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
620 // Unused callbacks from user_pod_row.js
621 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
624 void UserManagerScreenHandler::GetLocalizedValues(
625 base::DictionaryValue* localized_strings) {
626 // For Control Bar.
627 localized_strings->SetString("signedIn",
628 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
629 localized_strings->SetString("signinButton",
630 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
631 localized_strings->SetString("addUser",
632 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
633 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
634 localized_strings->SetString("browseAsGuest",
635 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
636 localized_strings->SetString("signOutUser",
637 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
638 localized_strings->SetString("addSupervisedUser",
639 l10n_util::GetStringUTF16(IDS_CREATE_SUPERVISED_USER_MENU_LABEL));
641 // For AccountPickerScreen.
642 localized_strings->SetString("screenType", "login-add-user");
643 localized_strings->SetString("highlightStrength", "normal");
644 localized_strings->SetString("title",
645 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
646 localized_strings->SetString("passwordHint",
647 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
648 localized_strings->SetString("signingIn",
649 l10n_util::GetStringUTF16(IDS_LOGIN_POD_SIGNING_IN));
650 localized_strings->SetString("podMenuButtonAccessibleName",
651 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
652 localized_strings->SetString("podMenuRemoveItemAccessibleName",
653 l10n_util::GetStringUTF16(
654 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
655 localized_strings->SetString("removeUser",
656 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
657 localized_strings->SetString("passwordFieldAccessibleName",
658 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
659 localized_strings->SetString("bootIntoWallpaper", "off");
661 // For AccountPickerScreen, the remove user warning overlay.
662 localized_strings->SetString("removeUserWarningButtonTitle",
663 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
664 localized_strings->SetString("removeUserWarningText",
665 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
666 localized_strings->SetString("removeLegacySupervisedUserWarningText",
667 l10n_util::GetStringFUTF16(
668 IDS_LOGIN_POD_LEGACY_SUPERVISED_USER_REMOVE_WARNING,
669 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL)));
671 // Strings needed for the User Manager tutorial slides.
672 localized_strings->SetString("tutorialNext",
673 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT));
674 localized_strings->SetString("tutorialDone",
675 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE));
676 localized_strings->SetString("slideWelcomeTitle",
677 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE));
678 localized_strings->SetString("slideWelcomeText",
679 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT));
680 localized_strings->SetString("slideYourChromeTitle",
681 l10n_util::GetStringUTF16(
682 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE));
683 localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16(
684 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT));
685 localized_strings->SetString("slideGuestsTitle",
686 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE));
687 localized_strings->SetString("slideGuestsText",
688 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT));
689 localized_strings->SetString("slideFriendsTitle",
690 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE));
691 localized_strings->SetString("slideFriendsText",
692 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT));
693 localized_strings->SetString("slideCompleteTitle",
694 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE));
695 localized_strings->SetString("slideCompleteText",
696 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT));
697 localized_strings->SetString("slideCompleteUserNotFound",
698 l10n_util::GetStringUTF16(
699 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND));
700 localized_strings->SetString("slideCompleteAddUser",
701 l10n_util::GetStringUTF16(
702 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER));
704 // Strings needed for the user_pod_template public account div, but not ever
705 // actually displayed for desktop users.
706 localized_strings->SetString("publicAccountReminder", base::string16());
707 localized_strings->SetString("publicSessionLanguageAndInput",
708 base::string16());
709 localized_strings->SetString("publicAccountEnter", base::string16());
710 localized_strings->SetString("publicAccountEnterAccessibleName",
711 base::string16());
712 localized_strings->SetString("publicSessionSelectLanguage", base::string16());
713 localized_strings->SetString("publicSessionSelectKeyboard", base::string16());
714 localized_strings->SetString("signinBannerText", base::string16());
715 localized_strings->SetString("launchAppButton", base::string16());
716 localized_strings->SetString("multiProfilesRestrictedPolicyTitle",
717 base::string16());
718 localized_strings->SetString("multiProfilesNotAllowedPolicyMsg",
719 base::string16());
720 localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg",
721 base::string16());
722 localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg",
723 base::string16());
726 void UserManagerScreenHandler::SendUserList() {
727 base::ListValue users_list;
728 const ProfileInfoCache& info_cache =
729 g_browser_process->profile_manager()->GetProfileInfoCache();
730 user_auth_type_map_.clear();
732 // Profile deletion is not allowed in Metro mode.
733 bool can_remove = true;
734 #if defined(USE_ASH)
735 can_remove = !ash::Shell::HasInstance();
736 #endif
738 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
739 base::DictionaryValue* profile_value = new base::DictionaryValue();
740 base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
742 profile_value->SetString(
743 kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i));
744 profile_value->SetString(
745 kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i));
746 profile_value->SetString(
747 kKeyDisplayName,
748 profiles::GetAvatarNameForProfile(profile_path));
749 profile_value->Set(
750 kKeyProfilePath, base::CreateFilePathValue(profile_path));
751 profile_value->SetBoolean(kKeyPublicAccount, false);
752 profile_value->SetBoolean(kKeyLegacySupervisedUser,
753 info_cache.ProfileIsLegacySupervisedAtIndex(i));
754 profile_value->SetBoolean(
755 kKeyChildUser, info_cache.ProfileIsChildAtIndex(i));
756 profile_value->SetBoolean(
757 kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i));
758 profile_value->SetBoolean(kKeyIsOwner, false);
759 profile_value->SetBoolean(kKeyCanRemove, can_remove);
760 profile_value->SetBoolean(kKeyIsDesktop, true);
761 profile_value->SetString(
762 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
764 users_list.Append(profile_value);
767 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
768 users_list, base::FundamentalValue(IsGuestModeEnabled()));
770 // This is the latest C++ code we have in the flow to show the UserManager.
771 // This may be invoked more than once per UserManager lifetime; the
772 // UserManager will ensure all relevant logging only happens once.
773 UserManager::OnUserManagerShown();
776 void UserManagerScreenHandler::ReportAuthenticationResult(
777 bool success,
778 ProfileMetrics::ProfileAuth auth) {
779 ProfileMetrics::LogProfileAuthResult(auth);
780 password_attempt_.clear();
782 if (success) {
783 const ProfileInfoCache& info_cache =
784 g_browser_process->profile_manager()->GetProfileInfoCache();
785 base::FilePath path = info_cache.GetPathOfProfileAtIndex(
786 authenticating_profile_index_);
787 profiles::SwitchToProfile(
788 path,
789 desktop_type_,
790 true,
791 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
792 weak_ptr_factory_.GetWeakPtr()),
793 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
794 } else {
795 web_ui()->CallJavascriptFunction(
796 "cr.ui.Oobe.showSignInError",
797 base::FundamentalValue(0),
798 base::StringValue(l10n_util::GetStringUTF8(
799 auth == ProfileMetrics::AUTH_FAILED_OFFLINE ?
800 IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE :
801 IDS_LOGIN_ERROR_AUTHENTICATING)),
802 base::StringValue(""),
803 base::FundamentalValue(0));
807 void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) {
808 DCHECK(browser);
809 DCHECK(browser->window());
811 // Unlock the profile after browser opens so startup can read the lock bit.
812 // Any necessary authentication must have been successful to reach this point.
813 if (!browser->profile()->IsGuestSession()) {
814 ProfileInfoCache& info_cache =
815 g_browser_process->profile_manager()->GetProfileInfoCache();
816 size_t index = info_cache.GetIndexOfProfileWithPath(
817 browser->profile()->GetPath());
818 info_cache.SetProfileSigninRequiredAtIndex(index, false);
821 if (!url_hash_.empty()) {
822 base::MessageLoop::current()->PostTask(
823 FROM_HERE,
824 base::Bind(&UrlHashHelper::ExecuteUrlHash,
825 base::Owned(new UrlHashHelper(browser, url_hash_))));
828 // This call is last as it deletes this object.
829 UserManager::Hide();
832 void UserManagerScreenHandler::Observe(
833 int type,
834 const content::NotificationSource& source,
835 const content::NotificationDetails& details) {
836 switch (type) {
837 case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
838 // Only respond to one Browser Window Ready event.
839 registrar_.Remove(this,
840 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
841 content::NotificationService::AllSources());
842 OnBrowserWindowReady(content::Source<Browser>(source).ptr());
843 break;
844 default:
845 NOTREACHED();
849 // This callback is run after switching to a new profile has finished. This
850 // means either a new browser has been created (but not the window), or an
851 // existing one has been found. The HideUserManager task needs to be posted
852 // since closing the User Manager before the window is created can flakily
853 // cause Chrome to close.
854 void UserManagerScreenHandler::OnSwitchToProfileComplete(
855 Profile* profile, Profile::CreateStatus profile_create_status) {
856 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
857 if (browser && browser->window()) {
858 OnBrowserWindowReady(browser);
859 } else {
860 registrar_.Add(this,
861 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
862 content::NotificationService::AllSources());