Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: chrome/browser/ui/webui/signin/user_manager_screen_handler.cc

Issue 1220843003: Perform online reauth when password is changed for a locked profile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h" 5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "base/profiler/scoped_tracker.h" 10 #include "base/profiler/scoped_tracker.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 if (avatar_image.Width() <= profiles::kAvatarIconWidth || 117 if (avatar_image.Width() <= profiles::kAvatarIconWidth ||
118 avatar_image.Height() <= profiles::kAvatarIconHeight ) { 118 avatar_image.Height() <= profiles::kAvatarIconHeight ) {
119 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 119 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
120 profiles::GetPlaceholderAvatarIconResourceID()); 120 profiles::GetPlaceholderAvatarIconResourceID());
121 } 121 }
122 gfx::Image resized_image = profiles::GetSizedAvatarIcon( 122 gfx::Image resized_image = profiles::GetSizedAvatarIcon(
123 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize); 123 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
124 return webui::GetBitmapDataUrl(resized_image.AsBitmap()); 124 return webui::GetBitmapDataUrl(resized_image.AsBitmap());
125 } 125 }
126 126
127 size_t GetIndexOfProfileWithEmail(const ProfileInfoCache& info_cache,
128 const std::string& email) {
129 const base::string16& profile_email = base::UTF8ToUTF16(email);
130 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
131 if (info_cache.GetUserNameOfProfileAtIndex(i) == profile_email)
132 return i;
133 }
134 return std::string::npos;
135 }
136
137 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter( 127 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter(
138 const std::string& email) { 128 const std::string& email) {
139 const ProfileInfoCache& info_cache = 129 base::FilePath path =
140 g_browser_process->profile_manager()->GetProfileInfoCache(); 130 profiles::GetPathOfProfileWithEmail(g_browser_process->profile_manager(),
141 const size_t profile_index = GetIndexOfProfileWithEmail(info_cache, email); 131 email);
142 Profile* profile = g_browser_process->profile_manager() 132 Profile* profile = g_browser_process->profile_manager()
143 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index)); 133 ->GetProfileByPath(path);
144 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get( 134 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
145 profile); 135 profile);
146 } 136 }
147 137
148 bool IsGuestModeEnabled() { 138 bool IsGuestModeEnabled() {
149 PrefService* service = g_browser_process->local_state(); 139 PrefService* service = g_browser_process->local_state();
150 DCHECK(service); 140 DCHECK(service);
151 return service->GetBoolean(prefs::kBrowserGuestModeEnabled); 141 return service->GetBoolean(prefs::kBrowserGuestModeEnabled);
152 } 142 }
153 143
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 return proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; 349 return proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD;
360 return it->second; 350 return it->second;
361 } 351 }
362 352
363 proximity_auth::ScreenlockBridge::LockHandler::ScreenType 353 proximity_auth::ScreenlockBridge::LockHandler::ScreenType
364 UserManagerScreenHandler::GetScreenType() const { 354 UserManagerScreenHandler::GetScreenType() const {
365 return proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN; 355 return proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN;
366 } 356 }
367 357
368 void UserManagerScreenHandler::Unlock(const std::string& user_email) { 358 void UserManagerScreenHandler::Unlock(const std::string& user_email) {
369 const ProfileInfoCache& info_cache = 359 base::FilePath path =
370 g_browser_process->profile_manager()->GetProfileInfoCache(); 360 profiles::GetPathOfProfileWithEmail(g_browser_process->profile_manager(),
371 const size_t profile_index = 361 user_email);
372 GetIndexOfProfileWithEmail(info_cache, user_email); 362 if (!path.empty()) {
373 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles()); 363 authenticating_profile_path_ = path;
374 364 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
375 authenticating_profile_index_ = profile_index; 365 }
376 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
377 } 366 }
378 367
379 void UserManagerScreenHandler::AttemptEasySignin( 368 void UserManagerScreenHandler::AttemptEasySignin(
380 const std::string& user_email, 369 const std::string& user_email,
381 const std::string& secret, 370 const std::string& secret,
382 const std::string& key_label) { 371 const std::string& key_label) {
383 NOTREACHED(); 372 NOTREACHED();
384 } 373 }
385 374
386 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) { 375 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
(...skipping 26 matching lines...) Expand all
413 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( 402 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser(
414 const base::ListValue* args) { 403 const base::ListValue* args) {
415 const base::Value* profile_path_value; 404 const base::Value* profile_path_value;
416 if (!args->Get(0, &profile_path_value)) 405 if (!args->Get(0, &profile_path_value))
417 return; 406 return;
418 407
419 base::FilePath profile_path; 408 base::FilePath profile_path;
420 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) 409 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
421 return; 410 return;
422 411
412 ProfileInfoCache& info_cache =
413 g_browser_process->profile_manager()->GetProfileInfoCache();
Alexei Svitkine (slow) 2015/07/24 16:36:42 Nit: Make this a pointer via &g_browser_process->p
Roger Tawa OOO till Jul 10th 2015/07/24 17:01:29 I think I'll keep it as is. All the code in chrom
414
415 ProfileAttributesEntry* entry;
416 if (!info_cache.GetProfileAttributesWithPath(profile_path, &entry))
417 return;
418
423 base::string16 email_address; 419 base::string16 email_address;
424 if (!args->GetString(1, &email_address)) 420 if (!args->GetString(1, &email_address))
425 return; 421 return;
426 422
427 std::string password; 423 std::string password;
428 if (!args->GetString(2, &password)) 424 if (!args->GetString(2, &password))
429 return; 425 return;
430 426
431 const ProfileInfoCache& info_cache = 427 authenticating_profile_path_ = profile_path;
432 g_browser_process->profile_manager()->GetProfileInfoCache(); 428
433 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path); 429 size_t profile_index = info_cache.GetIndexOfProfileWithPath(profile_path);
434
435 if (profile_index == std::string::npos) {
436 NOTREACHED();
437 return;
438 }
439
440 authenticating_profile_index_ = profile_index;
441 if (LocalAuth::ValidateLocalAuthCredentials(profile_index, password)) { 430 if (LocalAuth::ValidateLocalAuthCredentials(profile_index, password)) {
442 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL); 431 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL);
443 return; 432 return;
444 } 433 }
445 434
446 email_address_ = email_address; 435 email_address_ = email_address;
447 password_attempt_ = password; 436 password_attempt_ = password;
448 437
449 // This could be a mis-typed password or typing a new password while we 438 // This could be a mis-typed password or typing a new password while we
450 // still have a hash of the old one. The new way of checking a password 439 // still have a hash of the old one. The new way of checking a password
451 // change makes use of a token so we do that... if it's available. 440 // change makes use of a token so we do that... if it's available.
452 if (!oauth_client_) { 441 if (!oauth_client_) {
453 oauth_client_.reset(new gaia::GaiaOAuthClient( 442 oauth_client_.reset(new gaia::GaiaOAuthClient(
454 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext())); 443 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
455 } 444 }
456 std::string token = info_cache.GetPasswordChangeDetectionTokenAtIndex( 445
457 profile_index); 446 std::string token = entry->GetPasswordChangeDetectionToken();
458 if (!token.empty()) { 447 if (!token.empty()) {
459 oauth_client_->GetTokenHandleInfo(token, kMaxOAuthRetries, this); 448 oauth_client_->GetTokenHandleInfo(token, kMaxOAuthRetries, this);
460 return; 449 return;
461 } 450 }
462 451
463 // In order to support the upgrade case where we have a local hash but no 452 // In order to support the upgrade case where we have a local hash but no
464 // password token, we fall back on (deprecated) ClientLogin. This will 453 // password token, the user perform a full online reauth.
465 // have to be removed in future versions as the service gets turned down 454 UserManager::ShowReauthDialog(web_ui()->GetWebContents()->GetBrowserContext(),
466 // but by then we'll have seamlessly updated the majority of users. 455 base::UTF16ToUTF8(email_address_));
Alexei Svitkine (slow) 2015/07/24 16:36:42 What's the reason for doing the conversion at the
Roger Tawa OOO till Jul 10th 2015/07/24 17:01:29 Everyone email is just an std::string (except when
Alexei Svitkine (slow) 2015/07/24 17:09:08 Woot, that's even better. :)
467 client_login_.reset(new GaiaAuthFetcher(
468 this,
469 GaiaConstants::kChromeSource,
470 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
471
472 client_login_->StartClientLogin(
473 base::UTF16ToUTF8(email_address),
474 password,
475 GaiaConstants::kSyncService,
476 std::string(),
477 std::string(),
478 GaiaAuthFetcher::HostedAccountsAllowed);
479 } 456 }
480 457
481 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) { 458 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
482 DCHECK(args); 459 DCHECK(args);
483 const base::Value* profile_path_value; 460 const base::Value* profile_path_value;
484 if (!args->Get(0, &profile_path_value)) { 461 if (!args->Get(0, &profile_path_value)) {
485 NOTREACHED(); 462 NOTREACHED();
486 return; 463 return;
487 } 464 }
488 465
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 } 549 }
573 550
574 void UserManagerScreenHandler::OnGetTokenInfoResponse( 551 void UserManagerScreenHandler::OnGetTokenInfoResponse(
575 scoped_ptr<base::DictionaryValue> token_info) { 552 scoped_ptr<base::DictionaryValue> token_info) {
576 // Password is unchanged so user just mistyped it. Ask again. 553 // Password is unchanged so user just mistyped it. Ask again.
577 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED); 554 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED);
578 } 555 }
579 556
580 void UserManagerScreenHandler::OnOAuthError() { 557 void UserManagerScreenHandler::OnOAuthError() {
581 // Password has changed. Go through online signin flow. 558 // Password has changed. Go through online signin flow.
582 // ... if we had it. Until then, use deprecated ClientLogin to validate
583 // the password. This will have to be changed soon. (TODO: bcwhite)
584 oauth_client_.reset();
585 client_login_.reset(new GaiaAuthFetcher(
586 this,
587 GaiaConstants::kChromeSource,
588 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext()));
589
590 DCHECK(!email_address_.empty()); 559 DCHECK(!email_address_.empty());
591 DCHECK(!password_attempt_.empty()); 560 oauth_client_.reset();
592 client_login_->StartClientLogin( 561 UserManager::ShowReauthDialog(web_ui()->GetWebContents()->GetBrowserContext(),
593 base::UTF16ToUTF8(email_address_), 562 base::UTF16ToUTF8(email_address_));
594 password_attempt_,
595 GaiaConstants::kSyncService,
596 std::string(),
597 std::string(),
598 GaiaAuthFetcher::HostedAccountsAllowed);
599 } 563 }
600 564
601 void UserManagerScreenHandler::OnNetworkError(int response_code) { 565 void UserManagerScreenHandler::OnNetworkError(int response_code) {
602 // Inconclusive but can't do real signin without being online anyway. 566 // Inconclusive but can't do real signin without being online anyway.
603 oauth_client_.reset(); 567 oauth_client_.reset();
604 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED_OFFLINE); 568 ReportAuthenticationResult(false, ProfileMetrics::AUTH_FAILED_OFFLINE);
605 } 569 }
606 570
607 void UserManagerScreenHandler::OnClientLoginSuccess(
608 const ClientLoginResult& result) {
609 oauth_client_.reset();
610 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
611 password_attempt_);
612 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE);
613 }
614
615 void UserManagerScreenHandler::OnClientLoginFailure(
616 const GoogleServiceAuthError& error) {
617 const GoogleServiceAuthError::State state = error.state();
618 // Some "error" results mean the password was correct but some other action
619 // should be taken. For our purposes, we only care that the password was
620 // correct so count those as a success.
621 bool success = (state == GoogleServiceAuthError::NONE ||
622 state == GoogleServiceAuthError::CAPTCHA_REQUIRED ||
623 state == GoogleServiceAuthError::TWO_FACTOR ||
624 state == GoogleServiceAuthError::ACCOUNT_DELETED ||
625 state == GoogleServiceAuthError::ACCOUNT_DISABLED ||
626 state == GoogleServiceAuthError::WEB_LOGIN_REQUIRED);
627
628 // If the password was correct, the user must have changed it since the
629 // profile was locked. Save the password to streamline future unlocks.
630 if (success) {
631 DCHECK(!password_attempt_.empty());
632 LocalAuth::SetLocalAuthCredentials(authenticating_profile_index_,
633 password_attempt_);
634 }
635
636 bool offline = error.IsTransientError();
637 ProfileMetrics::ProfileAuth failure_metric =
638 offline ? ProfileMetrics::AUTH_FAILED_OFFLINE :
639 ProfileMetrics::AUTH_FAILED;
640 ReportAuthenticationResult(
641 success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric);
642 }
643
644 void UserManagerScreenHandler::RegisterMessages() { 571 void UserManagerScreenHandler::RegisterMessages() {
645 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize, 572 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
646 base::Bind(&UserManagerScreenHandler::HandleInitialize, 573 base::Bind(&UserManagerScreenHandler::HandleInitialize,
647 base::Unretained(this))); 574 base::Unretained(this)));
648 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser, 575 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
649 base::Bind(&UserManagerScreenHandler::HandleAddUser, 576 base::Bind(&UserManagerScreenHandler::HandleAddUser,
650 base::Unretained(this))); 577 base::Unretained(this)));
651 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser, 578 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
652 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser, 579 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
653 base::Unretained(this))); 580 base::Unretained(this)));
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 } 761 }
835 762
836 void UserManagerScreenHandler::ReportAuthenticationResult( 763 void UserManagerScreenHandler::ReportAuthenticationResult(
837 bool success, 764 bool success,
838 ProfileMetrics::ProfileAuth auth) { 765 ProfileMetrics::ProfileAuth auth) {
839 ProfileMetrics::LogProfileAuthResult(auth); 766 ProfileMetrics::LogProfileAuthResult(auth);
840 email_address_.clear(); 767 email_address_.clear();
841 password_attempt_.clear(); 768 password_attempt_.clear();
842 769
843 if (success) { 770 if (success) {
844 const ProfileInfoCache& info_cache =
845 g_browser_process->profile_manager()->GetProfileInfoCache();
846 base::FilePath path = info_cache.GetPathOfProfileAtIndex(
847 authenticating_profile_index_);
848 profiles::SwitchToProfile( 771 profiles::SwitchToProfile(
849 path, 772 authenticating_profile_path_,
850 desktop_type_, 773 desktop_type_,
851 true, 774 true,
852 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, 775 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
853 weak_ptr_factory_.GetWeakPtr()), 776 weak_ptr_factory_.GetWeakPtr()),
854 ProfileMetrics::SWITCH_PROFILE_UNLOCK); 777 ProfileMetrics::SWITCH_PROFILE_UNLOCK);
855 } else { 778 } else {
856 web_ui()->CallJavascriptFunction( 779 web_ui()->CallJavascriptFunction(
857 "cr.ui.Oobe.showSignInError", 780 "cr.ui.Oobe.showSignInError",
858 base::FundamentalValue(0), 781 base::FundamentalValue(0),
859 base::StringValue(l10n_util::GetStringUTF8( 782 base::StringValue(l10n_util::GetStringUTF8(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 Profile* profile, Profile::CreateStatus profile_create_status) { 839 Profile* profile, Profile::CreateStatus profile_create_status) {
917 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_); 840 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_);
918 if (browser && browser->window()) { 841 if (browser && browser->window()) {
919 OnBrowserWindowReady(browser); 842 OnBrowserWindowReady(browser);
920 } else { 843 } else {
921 registrar_.Add(this, 844 registrar_.Add(this,
922 chrome::NOTIFICATION_BROWSER_WINDOW_READY, 845 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
923 content::NotificationService::AllSources()); 846 content::NotificationService::AllSources());
924 } 847 }
925 } 848 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698