Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
bloba955bb4df3fd475eeea3d1a3e87935f8ef42504b
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/location.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/profiler/scoped_tracker.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/value_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
21 #include "chrome/browser/profiles/profile_info_cache.h"
22 #include "chrome/browser/profiles/profile_info_cache_observer.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/browser/profiles/profile_metrics.h"
25 #include "chrome/browser/profiles/profile_window.h"
26 #include "chrome/browser/profiles/profiles_state.h"
27 #include "chrome/browser/signin/local_auth.h"
28 #include "chrome/browser/ui/app_list/app_list_service.h"
29 #include "chrome/browser/ui/browser_commands.h"
30 #include "chrome/browser/ui/browser_dialogs.h"
31 #include "chrome/browser/ui/browser_finder.h"
32 #include "chrome/browser/ui/browser_list.h"
33 #include "chrome/browser/ui/browser_list_observer.h"
34 #include "chrome/browser/ui/chrome_pages.h"
35 #include "chrome/browser/ui/singleton_tabs.h"
36 #include "chrome/browser/ui/user_manager.h"
37 #include "chrome/common/pref_names.h"
38 #include "chrome/common/url_constants.h"
39 #include "chrome/grit/chromium_strings.h"
40 #include "chrome/grit/generated_resources.h"
41 #include "components/proximity_auth/screenlock_bridge.h"
42 #include "content/public/browser/notification_service.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/browser/web_ui.h"
45 #include "google_apis/gaia/gaia_auth_fetcher.h"
46 #include "google_apis/gaia/gaia_constants.h"
47 #include "third_party/skia/include/core/SkBitmap.h"
48 #include "ui/base/l10n/l10n_util.h"
49 #include "ui/base/resource/resource_bundle.h"
50 #include "ui/base/webui/web_ui_util.h"
51 #include "ui/gfx/image/image.h"
52 #include "ui/gfx/image/image_skia.h"
53 #include "ui/gfx/image/image_util.h"
55 #if defined(USE_ASH)
56 #include "ash/shell.h"
57 #endif
59 namespace {
60 // User dictionary keys.
61 const char kKeyUsername[] = "username";
62 const char kKeyDisplayName[]= "displayName";
63 const char kKeyEmailAddress[] = "emailAddress";
64 const char kKeyProfilePath[] = "profilePath";
65 const char kKeyPublicAccount[] = "publicAccount";
66 const char kKeyLegacySupervisedUser[] = "legacySupervisedUser";
67 const char kKeyChildUser[] = "childUser";
68 const char kKeyCanRemove[] = "canRemove";
69 const char kKeyIsOwner[] = "isOwner";
70 const char kKeyIsDesktop[] = "isDesktopUser";
71 const char kKeyAvatarUrl[] = "userImage";
72 const char kKeyNeedsSignin[] = "needsSignin";
73 const char kKeyHasLocalCreds[] = "hasLocalCreds";
75 // JS API callback names.
76 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
77 const char kJsApiUserManagerAddUser[] = "addUser";
78 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser";
79 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
80 const char kJsApiUserManagerLaunchUser[] = "launchUser";
81 const char kJsApiUserManagerRemoveUser[] = "removeUser";
82 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock";
83 const char kJsApiUserManagerLogRemoveUserWarningShown[] =
84 "logRemoveUserWarningShown";
86 const size_t kAvatarIconSize = 180;
87 const int kMaxOAuthRetries = 3;
89 void HandleAndDoNothing(const base::ListValue* args) {
92 // This callback is run if the only profile has been deleted, and a new
93 // profile has been created to replace it.
94 void OpenNewWindowForProfile(
95 chrome::HostDesktopType desktop_type,
96 Profile* profile,
97 Profile::CreateStatus status) {
98 if (status != Profile::CREATE_STATUS_INITIALIZED)
99 return;
100 profiles::FindOrCreateNewWindowForProfile(
101 profile,
102 chrome::startup::IS_PROCESS_STARTUP,
103 chrome::startup::IS_FIRST_RUN,
104 desktop_type,
105 false);
108 std::string GetAvatarImageAtIndex(
109 size_t index, ProfileInfoCache* info_cache) {
110 bool is_gaia_picture =
111 info_cache->IsUsingGAIAPictureOfProfileAtIndex(index) &&
112 info_cache->GetGAIAPictureOfProfileAtIndex(index);
114 // If the avatar is too small (i.e. the old-style low resolution avatar),
115 // it will be pixelated when displayed in the User Manager, so we should
116 // return the placeholder avatar instead.
117 gfx::Image avatar_image = info_cache->GetAvatarIconOfProfileAtIndex(index);
118 if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
119 avatar_image.Height() <= profiles::kAvatarIconHeight ) {
120 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
121 profiles::GetPlaceholderAvatarIconResourceID());
123 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
124 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
125 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
128 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
129 const std::string& email) {
130 base::FilePath path =
131 profiles::GetPathOfProfileWithEmail(g_browser_process->profile_manager(),
132 email);
133 Profile* profile = g_browser_process->profile_manager()
134 ->GetProfileByPath(path);
135 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
136 profile);
139 bool IsGuestModeEnabled() {
140 PrefService* service = g_browser_process->local_state();
141 DCHECK(service);
142 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
145 bool IsAddPersonEnabled() {
146 PrefService* service = g_browser_process->local_state();
147 DCHECK(service);
148 return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
151 // Executes the action specified by the URL's Hash parameter, if any. Deletes
152 // itself after the action would be performed.
153 class UrlHashHelper : public chrome::BrowserListObserver {
154 public:
155 UrlHashHelper(Browser* browser, const std::string& hash);
156 ~UrlHashHelper() override;
158 void ExecuteUrlHash();
160 // chrome::BrowserListObserver overrides:
161 void OnBrowserRemoved(Browser* browser) override;
163 private:
164 Browser* browser_;
165 Profile* profile_;
166 chrome::HostDesktopType desktop_type_;
167 std::string hash_;
169 DISALLOW_COPY_AND_ASSIGN(UrlHashHelper);
172 UrlHashHelper::UrlHashHelper(Browser* browser, const std::string& hash)
173 : browser_(browser),
174 profile_(browser->profile()),
175 desktop_type_(browser->host_desktop_type()),
176 hash_(hash) {
177 BrowserList::AddObserver(this);
180 UrlHashHelper::~UrlHashHelper() {
181 BrowserList::RemoveObserver(this);
184 void UrlHashHelper::OnBrowserRemoved(Browser* browser) {
185 if (browser == browser_)
186 browser_ = nullptr;
189 void UrlHashHelper::ExecuteUrlHash() {
190 if (hash_ == profiles::kUserManagerSelectProfileAppLauncher) {
191 AppListService* app_list_service = AppListService::Get(desktop_type_);
192 app_list_service->ShowForProfile(profile_);
193 return;
196 Browser* target_browser = browser_;
197 if (!target_browser) {
198 target_browser = chrome::FindLastActiveWithProfile(profile_, desktop_type_);
199 if (!target_browser)
200 return;
203 if (hash_ == profiles::kUserManagerSelectProfileTaskManager)
204 chrome::OpenTaskManager(target_browser);
205 else if (hash_ == profiles::kUserManagerSelectProfileAboutChrome)
206 chrome::ShowAboutChrome(target_browser);
207 else if (hash_ == profiles::kUserManagerSelectProfileChromeSettings)
208 chrome::ShowSettings(target_browser);
209 else if (hash_ == profiles::kUserManagerSelectProfileChromeMemory)
210 chrome::ShowMemory(target_browser);
213 void HandleLogRemoveUserWarningShown(const base::ListValue* args) {
214 ProfileMetrics::LogProfileDeleteUser(
215 ProfileMetrics::DELETE_PROFILE_USER_MANAGER_SHOW_WARNING);
218 } // namespace
220 // ProfileUpdateObserver ------------------------------------------------------
222 class UserManagerScreenHandler::ProfileUpdateObserver
223 : public ProfileInfoCacheObserver {
224 public:
225 ProfileUpdateObserver(
226 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
227 : profile_manager_(profile_manager),
228 user_manager_handler_(handler) {
229 DCHECK(profile_manager_);
230 DCHECK(user_manager_handler_);
231 profile_manager_->GetProfileInfoCache().AddObserver(this);
234 ~ProfileUpdateObserver() override {
235 DCHECK(profile_manager_);
236 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
239 private:
240 // ProfileInfoCacheObserver implementation:
241 // If any change has been made to a profile, propagate it to all the
242 // visible user manager screens.
243 void OnProfileAdded(const base::FilePath& profile_path) override {
244 user_manager_handler_->SendUserList();
247 void OnProfileWasRemoved(const base::FilePath& profile_path,
248 const base::string16& profile_name) override {
249 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when
250 // UserManager is able to find pod belonging to removed user.
251 user_manager_handler_->SendUserList();
254 void OnProfileNameChanged(const base::FilePath& profile_path,
255 const base::string16& old_profile_name) override {
256 user_manager_handler_->SendUserList();
259 void OnProfileAvatarChanged(const base::FilePath& profile_path) override {
260 user_manager_handler_->SendUserList();
263 void OnProfileHighResAvatarLoaded(
264 const base::FilePath& profile_path) override {
265 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/461175
266 // is fixed.
267 tracked_objects::ScopedTracker tracking_profile(
268 FROM_HERE_WITH_EXPLICIT_FUNCTION(
269 "461175 UserManagerScreenHandler::OnProfileHighResAvatarLoaded"));
270 user_manager_handler_->SendUserList();
273 void OnProfileSigninRequiredChanged(
274 const base::FilePath& profile_path) override {
275 user_manager_handler_->SendUserList();
278 void OnProfileIsOmittedChanged(
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 proximity_auth::ScreenlockBridge::Get()->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 base::FilePath path =
366 profiles::GetPathOfProfileWithEmail(g_browser_process->profile_manager(),
367 user_email);
368 if (!path.empty()) {
369 authenticating_profile_path_ = path;
370 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
374 void UserManagerScreenHandler::AttemptEasySignin(
375 const std::string& user_email,
376 const std::string& secret,
377 const std::string& key_label) {
378 NOTREACHED();
381 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
382 // If the URL has a hash parameter, store it for later.
383 args->GetString(0, &url_hash_);
385 SendUserList();
386 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen",
387 base::FundamentalValue(IsGuestModeEnabled()),
388 base::FundamentalValue(IsAddPersonEnabled()));
389 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
390 web_ui()->GetWebContents()->GetNativeView());
392 proximity_auth::ScreenlockBridge::Get()->SetLockHandler(this);
395 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
396 if (!IsAddPersonEnabled()) {
397 // The 'Add User' UI should not be showing.
398 NOTREACHED();
399 return;
401 profiles::CreateAndSwitchToNewProfile(
402 desktop_type_,
403 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
404 weak_ptr_factory_.GetWeakPtr()),
405 ProfileMetrics::ADD_NEW_USER_MANAGER);
408 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
409 const base::ListValue* args) {
410 const base::Value* profile_path_value;
411 if (!args->Get(0, &profile_path_value))
412 return;
414 base::FilePath profile_path;
415 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
416 return;
418 ProfileInfoCache& info_cache =
419 g_browser_process->profile_manager()->GetProfileInfoCache();
421 ProfileAttributesEntry* entry;
422 if (!info_cache.GetProfileAttributesWithPath(profile_path, &entry))
423 return;
425 base::string16 email_address;
426 if (!args->GetString(1, &email_address))
427 return;
429 std::string password;
430 if (!args->GetString(2, &password))
431 return;
433 authenticating_profile_path_ = profile_path;
434 email_address_ = base::UTF16ToUTF8(email_address);
436 // Only try to validate locally or check the password change detection
437 // if we actually have a local credential saved.
438 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
439 const bool has_local_credential =
440 !info_cache.GetLocalAuthCredentialsOfProfileAtIndex(profile_index)
441 .empty();
442 if (has_local_credential) {
443 if (LocalAuth::ValidateLocalAuthCredentials(profile_index, password)) {
444 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
445 return;
448 // This could be a mis-typed password or typing a new password while we
449 // still have a hash of the old one. The new way of checking a password
450 // change makes use of a token so we do that... if it's available.
451 if (!oauth_client_) {
452 oauth_client_.reset(new gaia::GaiaOAuthClient(
453 web_ui()->GetWebContents()->GetBrowserContext()
454 ->GetRequestContext()));
457 const std::string token = entry->GetPasswordChangeDetectionToken();
458 if (!token.empty()) {
459 oauth_client_->GetTokenHandleInfo(token, kMaxOAuthRetries, this);
460 return;
464 // In order to support the upgrade case where we have a local hash but no
465 // password token, the user perform a full online reauth.
466 UserManager::ShowReauthDialog(web_ui()->GetWebContents()->GetBrowserContext(),
467 email_address_);
470 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
471 DCHECK(args);
472 const base::Value* profile_path_value;
473 if (!args->Get(0, &profile_path_value)) {
474 NOTREACHED();
475 return;
478 base::FilePath profile_path;
479 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) {
480 NOTREACHED();
481 return;
484 if (!profiles::IsMultipleProfilesEnabled()) {
485 NOTREACHED();
486 return;
489 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
490 profile_path,
491 base::Bind(&OpenNewWindowForProfile, desktop_type_));
492 ProfileMetrics::LogProfileDeleteUser(
493 ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
496 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
497 if (IsGuestModeEnabled()) {
498 profiles::SwitchToGuestProfile(
499 desktop_type_,
500 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
501 weak_ptr_factory_.GetWeakPtr()));
502 } else {
503 // The UI should have prevented the user from allowing the selection of
504 // guest mode.
505 NOTREACHED();
509 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
510 const base::Value* profile_path_value = NULL;
511 if (!args->Get(0, &profile_path_value))
512 return;
514 base::FilePath profile_path;
515 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
516 return;
518 const ProfileInfoCache& info_cache =
519 g_browser_process->profile_manager()->GetProfileInfoCache();
520 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
522 if (profile_index == std::string::npos) {
523 NOTREACHED();
524 return;
527 // It's possible that a user breaks into the user-manager page using the
528 // JavaScript Inspector and causes a "locked" profile to call this
529 // unauthenticated version of "launch" instead of the proper one. Thus,
530 // we have to validate in (secure) C++ code that it really is a profile
531 // not needing authentication. If it is, just ignore the "launch" request.
532 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index))
533 return;
534 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
536 profiles::SwitchToProfile(
537 profile_path,
538 desktop_type_,
539 false, /* reuse any existing windows */
540 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
541 weak_ptr_factory_.GetWeakPtr()),
542 ProfileMetrics::SWITCH_PROFILE_MANAGER);
545 void UserManagerScreenHandler::HandleAttemptUnlock(
546 const base::ListValue* args) {
547 std::string email;
548 CHECK(args->GetString(0, &email));
549 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), "");
552 void UserManagerScreenHandler::HandleHardlockUserPod(
553 const base::ListValue* args) {
554 std::string email;
555 CHECK(args->GetString(0, &email));
556 SetAuthType(
557 email,
558 proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD,
559 base::string16());
560 HideUserPodCustomIcon(email);
563 void UserManagerScreenHandler::OnGetTokenInfoResponse(
564 scoped_ptr<base::DictionaryValue> token_info) {
565 // Password is unchanged so user just mistyped it. Ask again.
566 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED);
569 void UserManagerScreenHandler::OnOAuthError() {
570 // Password has changed. Go through online signin flow.
571 DCHECK(!email_address_.empty());
572 oauth_client_.reset();
573 UserManager::ShowReauthDialog(web_ui()->GetWebContents()->GetBrowserContext(),
574 email_address_);
577 void UserManagerScreenHandler::OnNetworkError(int response_code) {
578 // Inconclusive but can't do real signin without being online anyway.
579 oauth_client_.reset();
580 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED_OFFLINE);
583 void UserManagerScreenHandler::RegisterMessages() {
584 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
585 base::Bind(&UserManagerScreenHandler::HandleInitialize,
586 base::Unretained(this)));
587 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
588 base::Bind(&UserManagerScreenHandler::HandleAddUser,
589 base::Unretained(this)));
590 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
591 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
592 base::Unretained(this)));
593 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
594 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
595 base::Unretained(this)));
596 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
597 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
598 base::Unretained(this)));
599 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
600 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
601 base::Unretained(this)));
602 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock,
603 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock,
604 base::Unretained(this)));
605 web_ui()->RegisterMessageCallback(kJsApiUserManagerLogRemoveUserWarningShown,
606 base::Bind(&HandleLogRemoveUserWarningShown));
608 const content::WebUI::MessageCallback& kDoNothingCallback =
609 base::Bind(&HandleAndDoNothing);
611 // Unused callbacks from screen_account_picker.js
612 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
613 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
614 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
615 web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback);
616 // Unused callbacks from display_manager.js
617 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
618 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
619 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
620 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
621 // Unused callbacks from user_pod_row.js
622 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
625 void UserManagerScreenHandler::GetLocalizedValues(
626 base::DictionaryValue* localized_strings) {
627 // For Control Bar.
628 localized_strings->SetString("signedIn",
629 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
630 localized_strings->SetString("addUser",
631 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
632 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
633 localized_strings->SetString("browseAsGuest",
634 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
635 localized_strings->SetString("signOutUser",
636 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
637 localized_strings->SetString("addSupervisedUser",
638 l10n_util::GetStringUTF16(IDS_CREATE_LEGACY_SUPERVISED_USER_MENU_LABEL));
640 // For AccountPickerScreen.
641 localized_strings->SetString("screenType", "login-add-user");
642 localized_strings->SetString("highlightStrength", "normal");
643 localized_strings->SetString("title",
644 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
645 localized_strings->SetString("passwordHint",
646 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
647 localized_strings->SetString("signingIn",
648 l10n_util::GetStringUTF16(IDS_LOGIN_POD_SIGNING_IN));
649 localized_strings->SetString("podMenuButtonAccessibleName",
650 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
651 localized_strings->SetString("podMenuRemoveItemAccessibleName",
652 l10n_util::GetStringUTF16(
653 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
654 localized_strings->SetString("removeUser",
655 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
656 localized_strings->SetString("passwordFieldAccessibleName",
657 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
658 localized_strings->SetString("bootIntoWallpaper", "off");
660 // For AccountPickerScreen, the remove user warning overlay.
661 localized_strings->SetString("removeUserWarningButtonTitle",
662 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
663 localized_strings->SetString("removeUserWarningText",
664 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING));
665 localized_strings->SetString("removeLegacySupervisedUserWarningText",
666 l10n_util::GetStringFUTF16(
667 IDS_LOGIN_POD_LEGACY_SUPERVISED_USER_REMOVE_WARNING,
668 base::UTF8ToUTF16(
669 chrome::kLegacySupervisedUserManagementDisplayURL)));
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 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 // Don't show profiles still in the middle of being set up as new legacy
740 // supervised users.
741 if (info_cache->IsOmittedProfileAtIndex(i))
742 continue;
744 base::DictionaryValue* profile_value = new base::DictionaryValue();
745 base::FilePath profile_path = info_cache->GetPathOfProfileAtIndex(i);
747 profile_value->SetString(
748 kKeyUsername, info_cache->GetUserNameOfProfileAtIndex(i));
749 profile_value->SetString(
750 kKeyEmailAddress, info_cache->GetUserNameOfProfileAtIndex(i));
751 profile_value->SetString(
752 kKeyDisplayName,
753 profiles::GetAvatarNameForProfile(profile_path));
754 profile_value->Set(
755 kKeyProfilePath, base::CreateFilePathValue(profile_path));
756 profile_value->SetBoolean(kKeyPublicAccount, false);
757 profile_value->SetBoolean(kKeyLegacySupervisedUser,
758 info_cache->ProfileIsLegacySupervisedAtIndex(i));
759 profile_value->SetBoolean(
760 kKeyChildUser, info_cache->ProfileIsChildAtIndex(i));
761 profile_value->SetBoolean(
762 kKeyNeedsSignin, info_cache->ProfileIsSigninRequiredAtIndex(i));
763 profile_value->SetBoolean(
764 kKeyHasLocalCreds,
765 !info_cache->GetLocalAuthCredentialsOfProfileAtIndex(i).empty());
766 profile_value->SetBoolean(kKeyIsOwner, false);
767 profile_value->SetBoolean(kKeyCanRemove, can_remove);
768 profile_value->SetBoolean(kKeyIsDesktop, true);
769 profile_value->SetString(
770 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
772 users_list.Append(profile_value);
775 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
776 users_list, base::FundamentalValue(IsGuestModeEnabled()));
778 // This is the latest C++ code we have in the flow to show the UserManager.
779 // This may be invoked more than once per UserManager lifetime; the
780 // UserManager will ensure all relevant logging only happens once.
781 UserManager::OnUserManagerShown();
784 void UserManagerScreenHandler::ReportAuthenticationResult(
785 bool success,
786 ProfileMetrics::ProfileAuth auth) {
787 ProfileMetrics::LogProfileAuthResult(auth);
788 email_address_.clear();
790 if (success) {
791 profiles::SwitchToProfile(
792 authenticating_profile_path_,
793 desktop_type_,
794 true,
795 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
796 weak_ptr_factory_.GetWeakPtr()),
797 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
798 } else {
799 web_ui()->CallJavascriptFunction(
800 "cr.ui.Oobe.showSignInError",
801 base::FundamentalValue(0),
802 base::StringValue(l10n_util::GetStringUTF8(
803 auth == ProfileMetrics::AUTH_FAILED_OFFLINE ?
804 IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE :
805 IDS_LOGIN_ERROR_AUTHENTICATING)),
806 base::StringValue(""),
807 base::FundamentalValue(0));
811 void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) {
812 DCHECK(browser);
813 DCHECK(browser->window());
815 // Unlock the profile after browser opens so startup can read the lock bit.
816 // Any necessary authentication must have been successful to reach this point.
817 if (!browser->profile()->IsGuestSession()) {
818 ProfileInfoCache& info_cache =
819 g_browser_process->profile_manager()->GetProfileInfoCache();
820 size_t index = info_cache.GetIndexOfProfileWithPath(
821 browser->profile()->GetPath());
822 info_cache.SetProfileSigninRequiredAtIndex(index, false);
825 if (!url_hash_.empty()) {
826 base::ThreadTaskRunnerHandle::Get()->PostTask(
827 FROM_HERE,
828 base::Bind(&UrlHashHelper::ExecuteUrlHash,
829 base::Owned(new UrlHashHelper(browser, url_hash_))));
832 // This call is last as it deletes this object.
833 UserManager::Hide();
836 void UserManagerScreenHandler::Observe(
837 int type,
838 const content::NotificationSource& source,
839 const content::NotificationDetails& details) {
840 switch (type) {
841 case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
842 // Only respond to one Browser Window Ready event.
843 registrar_.Remove(this,
844 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
845 content::NotificationService::AllSources());
846 OnBrowserWindowReady(content::Source<Browser>(source).ptr());
847 break;
848 default:
849 NOTREACHED();
853 // This callback is run after switching to a new profile has finished. This
854 // means either a new browser has been created (but not the window), or an
855 // existing one has been found. The HideUserManager task needs to be posted
856 // since closing the User Manager before the window is created can flakily
857 // cause Chrome to close.
858 void UserManagerScreenHandler::OnSwitchToProfileComplete(
859 Profile* profile, Profile::CreateStatus profile_create_status) {
860 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
861 if (browser && browser->window()) {
862 OnBrowserWindowReady(browser);
863 } else {
864 registrar_.Add(this,
865 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
866 content::NotificationService::AllSources());