diff options
author | mlerman <mlerman@chromium.org> | 2014-12-07 09:34:49 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-07 17:35:20 +0000 |
commit | 86ffbbf837c62778b9695f944471d055e8405716 (patch) | |
tree | ebb6ea00ef309a3fbacb61b4823eb7cf5e0622ce | |
parent | 78222454fd92c13c99ff03ae6a1255e14a2e7577 (diff) | |
download | chromium_src-86ffbbf837c62778b9695f944471d055e8405716.zip chromium_src-86ffbbf837c62778b9695f944471d055e8405716.tar.gz chromium_src-86ffbbf837c62778b9695f944471d055e8405716.tar.bz2 |
The Account Tracker now collects Hosted Domain information. The Signin
Manager observes the Account Tracker, so that a new PostSignedIn method
is called only after both OnSignedIn is done and the
AccountTrackerService has called ClientInfo. This is used to save a
hash of the user's password only when Profile Lock is available.
The next CL will clean up the GAIAInfoUpdateService, ProfileDownloader and profile_window so that the hosted_domain is only acquired through the AccountTracker.
(TBR of pavely@ and bartfab@ since their files only involve specifying fake signin factories for unit tests)
BUG=432286
TBR=pavely@chromium.org, bartfab@chromium.org
Review URL: https://codereview.chromium.org/753243003
Cr-Commit-Position: refs/heads/master@{#307188}
23 files changed, 361 insertions, 101 deletions
diff --git a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc b/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc index 3cb9046..2552b14 100644 --- a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc +++ b/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc @@ -3,9 +3,13 @@ // found in the LICENSE file. #include "base/run_loop.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_account_tracker_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/test_signin_client_builder.h" #include "chrome/test/base/testing_profile.h" #include "components/gcm_driver/fake_gcm_driver.h" #include "components/gcm_driver/gcm_driver.h" @@ -54,6 +58,10 @@ class GCMInvalidationBridgeTest : public ::testing::Test { TestingProfile::Builder builder; builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), &BuildAutoIssuingFakeProfileOAuth2TokenService); + builder.AddTestingFactory(AccountTrackerServiceFactory::GetInstance(), + FakeAccountTrackerService::Build); + builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(), + signin::BuildTestSigninClient); profile_ = builder.Build(); FakeProfileOAuth2TokenService* token_service = diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc index c5e7f2ba..9bd3908 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc @@ -14,11 +14,15 @@ #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_account_tracker_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/fake_signin_manager.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/test_signin_client_builder.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_pref_service_syncable.h" #include "chrome/test/base/testing_profile.h" @@ -177,6 +181,10 @@ class UserPolicySigninServiceTest : public testing::Test { SigninManagerFake::Build); builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), BuildFakeProfileOAuth2TokenService); + builder.AddTestingFactory(AccountTrackerServiceFactory::GetInstance(), + FakeAccountTrackerService::Build); + builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(), + signin::BuildTestSigninClient); profile_ = builder.Build().Pass(); url_factory_.set_remove_fetcher_on_delete(true); diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc index 96310bd..1b4c131 100644 --- a/chrome/browser/profiles/profile_window.cc +++ b/chrome/browser/profiles/profile_window.cc @@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/account_reconcilor_factory.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -27,6 +28,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "components/signin/core/browser/account_reconcilor.h" +#include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/common/profile_management_switches.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/user_metrics.h" @@ -364,8 +366,22 @@ bool IsLockAvailable(Profile* profile) { if (!switches::IsNewProfileManagement()) return false; - const std::string& hosted_domain = profile->GetPrefs()-> + if (profile->IsGuestSession()) + return false; + + const ProfileInfoCache& cache = + g_browser_process->profile_manager()->GetProfileInfoCache(); + std::string hosted_domain = profile->GetPrefs()-> GetString(prefs::kGoogleServicesHostedDomain); + // TODO(mlerman): After one release remove any hosted_domain reference to the + // pref, since all users will have this in the AccountTrackerService. + if (hosted_domain.empty()) { + AccountTrackerService* account_tracker = + AccountTrackerServiceFactory::GetForProfile(profile); + int profile_index = cache.GetIndexOfProfileWithPath(profile->GetPath()); + hosted_domain = account_tracker->FindAccountInfoByEmail(base::UTF16ToUTF8( + cache.GetUserNameOfProfileAtIndex(profile_index))).hosted_domain; + } // TODO(mlerman): Prohibit only users who authenticate using SAML. Until then, // prohibited users who use hosted domains (aside from google.com). if (hosted_domain != Profile::kNoHostedDomainFound && @@ -373,8 +389,6 @@ bool IsLockAvailable(Profile* profile) { return false; } - const ProfileInfoCache& cache = - g_browser_process->profile_manager()->GetProfileInfoCache(); for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) { if (cache.ProfileIsSupervisedAtIndex(i)) return true; diff --git a/chrome/browser/services/gcm/fake_signin_manager.cc b/chrome/browser/services/gcm/fake_signin_manager.cc index 049b415..28ea3fd 100644 --- a/chrome/browser/services/gcm/fake_signin_manager.cc +++ b/chrome/browser/services/gcm/fake_signin_manager.cc @@ -7,6 +7,7 @@ #include "base/observer_list.h" #include "base/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/common/signin_pref_names.h" @@ -25,7 +26,8 @@ FakeSigninManager::FakeSigninManager(Profile* profile) #else : SigninManager( ChromeSigninClientFactory::GetInstance()->GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + AccountTrackerServiceFactory::GetForProfile(profile)), #endif profile_(profile) { Initialize(NULL); @@ -36,7 +38,7 @@ FakeSigninManager::~FakeSigninManager() { void FakeSigninManager::SignIn(const std::string& username) { SetAuthenticatedUsername(username); - FOR_EACH_OBSERVER(Observer, + FOR_EACH_OBSERVER(SigninManagerBase::Observer, observer_list_, GoogleSigninSucceeded(username, username, std::string())); } @@ -47,7 +49,7 @@ void FakeSigninManager::SignOut( const std::string username = GetAuthenticatedUsername(); ClearAuthenticatedUsername(); profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername); - FOR_EACH_OBSERVER(Observer, + FOR_EACH_OBSERVER(SigninManagerBase::Observer, observer_list_, GoogleSignedOut(account_id, username)); } diff --git a/chrome/browser/signin/account_tracker_service_factory.cc b/chrome/browser/signin/account_tracker_service_factory.cc index 1869834..60ddfff 100644 --- a/chrome/browser/signin/account_tracker_service_factory.cc +++ b/chrome/browser/signin/account_tracker_service_factory.cc @@ -6,6 +6,7 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -17,6 +18,7 @@ AccountTrackerServiceFactory::AccountTrackerServiceFactory() : BrowserContextKeyedServiceFactory( "AccountTrackerServiceFactory", BrowserContextDependencyManager::GetInstance()) { + DependsOn(ChromeSigninClientFactory::GetInstance()); DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); } @@ -52,7 +54,6 @@ KeyedService* AccountTrackerServiceFactory::BuildServiceInstanceFor( AccountTrackerService* service = new AccountTrackerService(); service->Initialize( ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - profile->GetPrefs(), - profile->GetRequestContext()); + ChromeSigninClientFactory::GetForProfile(profile)); return service; } diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 077f601..412f3ed 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc @@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_metrics.h" +#include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/signin/local_auth.h" #include "chrome/browser/signin/signin_cookie_changed_subscription.h" #include "chrome/browser/webdata/web_data_service_factory.h" @@ -209,15 +210,9 @@ ChromeSigninClient::AddCookieChangedCallback( return subscription.Pass(); } -void ChromeSigninClient::GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) { -#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) - // Don't store password hash except for users of new profile management. - if (switches::IsNewProfileManagement() && !password.empty()) - chrome::SetLocalAuthCredentials(profile_, password); -#endif - +void ChromeSigninClient::OnSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) { ProfileManager* profile_manager = g_browser_process->profile_manager(); ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); size_t index = cache.GetIndexOfProfileWithPath(profile_->GetPath()); @@ -226,3 +221,13 @@ void ChromeSigninClient::GoogleSigninSucceeded(const std::string& account_id, ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager); } } + +void ChromeSigninClient::PostSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) { +#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) + // Don't store password hash except when lock is available for the user. + if (!password.empty() && profiles::IsLockAvailable(profile_)) + chrome::SetLocalAuthCredentials(profile_, password); +#endif +} diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h index 81b4abf..3a21c0b 100644 --- a/chrome/browser/signin/chrome_signin_client.h +++ b/chrome/browser/signin/chrome_signin_client.h @@ -58,9 +58,12 @@ class ChromeSigninClient : public SigninClient, const GURL& url, const std::string& name, const net::CookieStore::CookieChangedCallback& callback) override; - void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) override; + void OnSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) override; + void PostSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) override; private: Profile* profile_; diff --git a/chrome/browser/signin/fake_account_tracker_service.cc b/chrome/browser/signin/fake_account_tracker_service.cc index 0b80661..b6ec07b 100644 --- a/chrome/browser/signin/fake_account_tracker_service.cc +++ b/chrome/browser/signin/fake_account_tracker_service.cc @@ -4,7 +4,9 @@ #include "chrome/browser/signin/fake_account_tracker_service.h" +#include "base/values.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" @@ -15,8 +17,7 @@ KeyedService* FakeAccountTrackerService::Build( FakeAccountTrackerService* service = new FakeAccountTrackerService(); service->Initialize( ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - profile->GetPrefs(), - profile->GetRequestContext()); + ChromeSigninClientFactory::GetForProfile(profile)); return service; } @@ -28,3 +29,15 @@ void FakeAccountTrackerService::StartFetchingUserInfo( const std::string& account_id) { // In tests, don't do actual network fetch. } + +void FakeAccountTrackerService::FakeUserInfoFetchSuccess( + const std::string& account_id, + const std::string& email, + const std::string& gaia, + const std::string& hosted_domain) { + base::DictionaryValue user_info; + user_info.SetString("id", gaia); + user_info.SetString("email", email); + user_info.SetString("hd", hosted_domain); + SetAccountStateFromUserInfo(account_id, &user_info); +} diff --git a/chrome/browser/signin/fake_account_tracker_service.h b/chrome/browser/signin/fake_account_tracker_service.h index b25a850..fe0b11a 100644 --- a/chrome/browser/signin/fake_account_tracker_service.h +++ b/chrome/browser/signin/fake_account_tracker_service.h @@ -20,6 +20,11 @@ class FakeAccountTrackerService : public AccountTrackerService { public: static KeyedService* Build(content::BrowserContext* context); + void FakeUserInfoFetchSuccess(const std::string& account_id, + const std::string& email, + const std::string& gaia, + const std::string& hosted_domain); + private: FakeAccountTrackerService(); ~FakeAccountTrackerService() override; diff --git a/chrome/browser/signin/fake_signin_manager.cc b/chrome/browser/signin/fake_signin_manager.cc index 43de553..5704738 100644 --- a/chrome/browser/signin/fake_signin_manager.cc +++ b/chrome/browser/signin/fake_signin_manager.cc @@ -7,6 +7,7 @@ #include "base/callback_helpers.h" #include "base/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" @@ -40,7 +41,8 @@ KeyedService* FakeSigninManagerBase::Build(content::BrowserContext* context) { FakeSigninManager::FakeSigninManager(Profile* profile) : SigninManager( ChromeSigninClientFactory::GetInstance()->GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)) {} + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + AccountTrackerServiceFactory::GetForProfile(profile)) {} FakeSigninManager::~FakeSigninManager() { } @@ -60,7 +62,7 @@ void FakeSigninManager::StartSignInWithRefreshToken( void FakeSigninManager::CompletePendingSignin() { SetAuthenticatedUsername(GetUsernameForAuthInProgress()); set_auth_in_progress(std::string()); - FOR_EACH_OBSERVER(Observer, + FOR_EACH_OBSERVER(SigninManagerBase::Observer, observer_list_, GoogleSigninSucceeded(authenticated_username_, authenticated_username_, @@ -75,7 +77,9 @@ void FakeSigninManager::SignIn(const std::string& username, } void FakeSigninManager::FailSignin(const GoogleServiceAuthError& error) { - FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSigninFailed(error)); + FOR_EACH_OBSERVER(SigninManagerBase::Observer, + observer_list_, + GoogleSigninFailed(error)); } void FakeSigninManager::SignOut( diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc index 499fbc4..0774902 100644 --- a/chrome/browser/signin/signin_manager_factory.cc +++ b/chrome/browser/signin/signin_manager_factory.cc @@ -131,7 +131,9 @@ KeyedService* SigninManagerFactory::BuildServiceInstanceFor( service = new SigninManagerBase(client); #else service = new SigninManager( - client, ProfileOAuth2TokenServiceFactory::GetForProfile(profile)); + client, + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + AccountTrackerServiceFactory::GetForProfile(profile)); #endif service->Initialize(g_browser_process->local_state()); FOR_EACH_OBSERVER(Observer, observer_list_, SigninManagerCreated(service)); diff --git a/chrome/browser/signin/signin_manager_unittest.cc b/chrome/browser/signin/signin_manager_unittest.cc index f1bee6f..500c1d6 100644 --- a/chrome/browser/signin/signin_manager_unittest.cc +++ b/chrome/browser/signin/signin_manager_unittest.cc @@ -16,7 +16,9 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/prefs/browser_prefs.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_account_tracker_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" @@ -49,7 +51,8 @@ KeyedService* SigninManagerBuild(content::BrowserContext* context) { Profile* profile = static_cast<Profile*>(context); service = new SigninManager( ChromeSigninClientFactory::GetInstance()->GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)); + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + AccountTrackerServiceFactory::GetForProfile(profile)); service->Initialize(NULL); return service; } @@ -106,11 +109,11 @@ class SigninManagerTest : public testing::Test { signin::BuildTestSigninClient); builder.AddTestingFactory(SigninManagerFactory::GetInstance(), SigninManagerBuild); + builder.AddTestingFactory(AccountTrackerServiceFactory::GetInstance(), + FakeAccountTrackerService::Build); profile_ = builder.Build(); - static_cast<TestSigninClient*>( - ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()))-> - SetURLRequestContext(profile_->GetRequestContext()); + signin_client()->SetURLRequestContext(profile_->GetRequestContext()); } void TearDown() override { @@ -134,6 +137,11 @@ class SigninManagerTest : public testing::Test { TestingProfile* profile() { return profile_.get(); } + TestSigninClient* signin_client() { + return static_cast<TestSigninClient*>( + ChromeSigninClientFactory::GetInstance()->GetForProfile(profile())); + } + // Sets up the signin manager as a service if other code will try to get it as // a PKS. void SetUpSigninManagerAsService() { @@ -149,7 +157,8 @@ class SigninManagerTest : public testing::Test { DCHECK(!manager_); naked_manager_.reset(new SigninManager( ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile()))); + ProfileOAuth2TokenServiceFactory::GetForProfile(profile()), + AccountTrackerServiceFactory::GetForProfile(profile()))); manager_ = naked_manager_.get(); manager_->AddObserver(&test_observer_); @@ -232,6 +241,41 @@ TEST_F(SigninManagerTest, SignInWithRefreshTokenCallbackComplete) { EXPECT_EQ(oauth_tokens_fetched_[0], "rt1"); } +TEST_F(SigninManagerTest, SignInWithRefreshTokenCallsPostSignout) { + SetUpSigninManagerAsService(); + EXPECT_FALSE(manager_->IsAuthenticated()); + + std::string gaia_id = "12345"; + std::string email = "user@google.com"; + + FakeAccountTrackerService* account_tracker_service = + static_cast<FakeAccountTrackerService*>( + AccountTrackerServiceFactory::GetForProfile(profile())); + account_tracker_service->SeedAccountInfo(gaia_id, email); + std::string account_id = account_tracker_service->PickAccountIdForAccount( + gaia_id, email); + + ASSERT_TRUE(signin_client()->get_signed_in_password().empty()); + + manager_->StartSignInWithRefreshToken( + "rt1", + email, + "password", + SigninManager::OAuthTokenFetchedCallback()); + + // PostSignedIn is not called until the AccountTrackerService returns. + ASSERT_EQ("", signin_client()->get_signed_in_password()); + + account_tracker_service->FakeUserInfoFetchSuccess( + account_id, email, gaia_id, "google.com"); + + // AccountTracker and SigninManager are both done and PostSignedIn was called. + ASSERT_EQ("password", signin_client()->get_signed_in_password()); + + ExpectSignInWithRefreshTokenSuccess(); + +} + TEST_F(SigninManagerTest, SignOut) { SetUpSigninManagerAsService(); manager_->StartSignInWithRefreshToken( diff --git a/chrome/browser/sync/profile_sync_auth_provider_unittest.cc b/chrome/browser/sync/profile_sync_auth_provider_unittest.cc index c216090e..595756c 100644 --- a/chrome/browser/sync/profile_sync_auth_provider_unittest.cc +++ b/chrome/browser/sync/profile_sync_auth_provider_unittest.cc @@ -3,9 +3,13 @@ // found in the LICENSE file. #include "base/run_loop.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_account_tracker_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/test_signin_client_builder.h" #include "chrome/browser/sync/profile_sync_auth_provider.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" @@ -26,6 +30,10 @@ class ProfileSyncAuthProviderTest : public ::testing::Test { TestingProfile::Builder builder; builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), &BuildAutoIssuingFakeProfileOAuth2TokenService); + builder.AddTestingFactory(AccountTrackerServiceFactory::GetInstance(), + FakeAccountTrackerService::Build); + builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(), + signin::BuildTestSigninClient); profile_ = builder.Build(); diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc index 6c45aa9..ab7b8f1 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc @@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/signin/about_signin_internals_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" @@ -135,7 +136,9 @@ void InlineSigninHelper::OnClientOAuthSuccess(const ClientOAuthResult& result) { SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername(); if (gaia::AreEmailsSame(email_, primary_email) && source == signin::SOURCE_REAUTH && - switches::IsNewProfileManagement() && !password_.empty()) { + switches::IsNewProfileManagement() && + !password_.empty() && + profiles::IsLockAvailable(profile_)) { chrome::SetLocalAuthCredentials(profile_, password_); } diff --git a/components/signin/core/browser/account_tracker_service.cc b/components/signin/core/browser/account_tracker_service.cc index 5d09b40..ecbeb29 100644 --- a/components/signin/core/browser/account_tracker_service.cc +++ b/components/signin/core/browser/account_tracker_service.cc @@ -6,16 +6,15 @@ #include "base/debug/trace_event.h" #include "base/logging.h" -#include "base/prefs/pref_service.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/profiler/scoped_tracker.h" #include "base/strings/utf_string_conversions.h" +#include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/common/signin_pref_names.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_oauth_client.h" -#include "google_apis/gaia/oauth2_token_service.h" #include "net/url_request/url_request_context_getter.h" namespace { @@ -23,9 +22,13 @@ namespace { const char kAccountKeyPath[] = "account_id"; const char kAccountEmailPath[] = "email"; const char kAccountGaiaPath[] = "gaia"; +const char kAccountHostedDomainPath[] = "hd"; } +// This must be a string which can never be a valid domain. +const char AccountTrackerService::kNoHostedDomainFound[] = "NO_HOSTED_DOMAIN"; + class AccountInfoFetcher : public OAuth2TokenService::Consumer, public gaia::GaiaOAuthClient::Delegate { public: @@ -146,12 +149,20 @@ void AccountInfoFetcher::OnNetworkError(int response_code) { service_->OnUserInfoFetchFailure(this); } +AccountTrackerService::AccountInfo::AccountInfo() {} +AccountTrackerService::AccountInfo::~AccountInfo() {} + +bool AccountTrackerService::AccountInfo::IsValid() { + return account_id.empty() || email.empty() || gaia.empty() || + hosted_domain.empty(); +} + const char AccountTrackerService::kAccountInfoPref[] = "account_info"; AccountTrackerService::AccountTrackerService() : token_service_(NULL), - pref_service_(NULL), + signin_client_(NULL), shutdown_called_(false) { } @@ -161,15 +172,13 @@ AccountTrackerService::~AccountTrackerService() { void AccountTrackerService::Initialize( OAuth2TokenService* token_service, - PrefService* pref_service, - net::URLRequestContextGetter* request_context_getter) { + SigninClient* signin_client) { DCHECK(token_service); DCHECK(!token_service_); - DCHECK(pref_service); - DCHECK(!pref_service_); + DCHECK(signin_client); + DCHECK(!signin_client_); token_service_ = token_service; - pref_service_ = pref_service; - request_context_getter_ = request_context_getter; + signin_client_ = signin_client; token_service_->AddObserver(this); LoadFromPrefs(); LoadFromTokenService(); @@ -247,7 +256,7 @@ AccountTrackerService::FindAccountInfoByEmail( AccountTrackerService::AccountIdMigrationState AccountTrackerService::GetMigrationState() { - return GetMigrationState(pref_service_); + return GetMigrationState(signin_client_->GetPrefs()); } // static @@ -273,7 +282,7 @@ void AccountTrackerService::OnRefreshTokenAvailable( StartTrackingAccount(account_id); AccountState& state = accounts_[account_id]; - if (state.info.gaia.empty()) + if (state.info.IsValid()) StartFetchingUserInfo(account_id); } @@ -294,6 +303,12 @@ void AccountTrackerService::NotifyAccountUpdated(const AccountState& state) { Observer, observer_list_, OnAccountUpdated(state.info)); } +void AccountTrackerService::NotifyAccountUpdateFailed( + const std::string& account_id) { + FOR_EACH_OBSERVER( + Observer, observer_list_, OnAccountUpdateFailed(account_id)); +} + void AccountTrackerService::NotifyAccountRemoved(const AccountState& state) { DCHECK(!state.info.gaia.empty()); FOR_EACH_OBSERVER( @@ -340,18 +355,16 @@ void AccountTrackerService::StartFetchingUserInfo( DVLOG(1) << "StartFetching " << account_id; AccountInfoFetcher* fetcher = new AccountInfoFetcher(token_service_, - request_context_getter_.get(), + signin_client_->GetURLRequestContext(), this, account_id); user_info_requests_[account_id] = fetcher; fetcher->Start(); } -void AccountTrackerService::OnUserInfoFetchSuccess( - AccountInfoFetcher* fetcher, +void AccountTrackerService::SetAccountStateFromUserInfo( + const std::string& account_id, const base::DictionaryValue* user_info) { - const std::string& account_id = fetcher->account_id(); - DCHECK(ContainsKey(accounts_, account_id)); AccountState& state = accounts_[account_id]; std::string gaia_id; @@ -361,15 +374,32 @@ void AccountTrackerService::OnUserInfoFetchSuccess( state.info.gaia = gaia_id; state.info.email = email; + std::string hosted_domain; + if (user_info->GetString("hd", &hosted_domain) && !hosted_domain.empty()) { + state.info.hosted_domain = hosted_domain; + } else { + state.info.hosted_domain = kNoHostedDomainFound; + } + NotifyAccountUpdated(state); SaveToPrefs(state); } +} + +void AccountTrackerService::OnUserInfoFetchSuccess( + AccountInfoFetcher* fetcher, + const base::DictionaryValue* user_info) { + const std::string& account_id = fetcher->account_id(); + DCHECK(ContainsKey(accounts_, account_id)); + + SetAccountStateFromUserInfo(account_id, user_info); DeleteFetcher(fetcher); } void AccountTrackerService::OnUserInfoFetchFailure( AccountInfoFetcher* fetcher) { LOG(WARNING) << "Failed to get UserInfo for " << fetcher->account_id(); + NotifyAccountUpdateFailed(fetcher->account_id()); DeleteFetcher(fetcher); // TODO(rogerta): figure out when to retry. } @@ -384,7 +414,8 @@ void AccountTrackerService::DeleteFetcher(AccountInfoFetcher* fetcher) { } void AccountTrackerService::LoadFromPrefs() { - const base::ListValue* list = pref_service_->GetList(kAccountInfoPref); + const base::ListValue* list = + signin_client_->GetPrefs()->GetList(kAccountInfoPref); for (size_t i = 0; i < list->GetSize(); ++i) { const base::DictionaryValue* dict; if (list->GetDictionary(i, &dict)) { @@ -398,8 +429,9 @@ void AccountTrackerService::LoadFromPrefs() { state.info.gaia = base::UTF16ToUTF8(value); if (dict->GetString(kAccountEmailPath, &value)) state.info.email = base::UTF16ToUTF8(value); - - if (!state.info.gaia.empty()) + if (dict->GetString(kAccountHostedDomainPath, &value)) + state.info.hosted_domain = base::UTF16ToUTF8(value); + if (!state.info.IsValid()) NotifyAccountUpdated(state); } } @@ -407,12 +439,12 @@ void AccountTrackerService::LoadFromPrefs() { } void AccountTrackerService::SaveToPrefs(const AccountState& state) { - if (!pref_service_) + if (!signin_client_->GetPrefs()) return; base::DictionaryValue* dict = NULL; base::string16 account_id_16 = base::UTF8ToUTF16(state.info.account_id); - ListPrefUpdate update(pref_service_, kAccountInfoPref); + ListPrefUpdate update(signin_client_->GetPrefs(), kAccountInfoPref); for(size_t i = 0; i < update->GetSize(); ++i, dict = NULL) { if (update->GetDictionary(i, &dict)) { base::string16 value; @@ -429,14 +461,15 @@ void AccountTrackerService::SaveToPrefs(const AccountState& state) { dict->SetString(kAccountEmailPath, state.info.email); dict->SetString(kAccountGaiaPath, state.info.gaia); + dict->SetString(kAccountHostedDomainPath, state.info.hosted_domain); } void AccountTrackerService::RemoveFromPrefs(const AccountState& state) { - if (!pref_service_) + if (!signin_client_->GetPrefs()) return; base::string16 account_id_16 = base::UTF8ToUTF16(state.info.account_id); - ListPrefUpdate update(pref_service_, kAccountInfoPref); + ListPrefUpdate update(signin_client_->GetPrefs(), kAccountInfoPref); for(size_t i = 0; i < update->GetSize(); ++i) { base::DictionaryValue* dict = NULL; if (update->GetDictionary(i, &dict)) { @@ -460,7 +493,7 @@ void AccountTrackerService::LoadFromTokenService() { std::string AccountTrackerService::PickAccountIdForAccount( const std::string& gaia, const std::string& email) { - return PickAccountIdForAccount(pref_service_, gaia, email); + return PickAccountIdForAccount(signin_client_->GetPrefs(), gaia, email); } // static diff --git a/components/signin/core/browser/account_tracker_service.h b/components/signin/core/browser/account_tracker_service.h index c65ed01..f1790ad 100644 --- a/components/signin/core/browser/account_tracker_service.h +++ b/components/signin/core/browser/account_tracker_service.h @@ -16,6 +16,7 @@ class AccountInfoFetcher; class OAuth2TokenService; class PrefService; +class SigninClient; namespace base { class DictionaryValue; @@ -30,13 +31,24 @@ class AccountTrackerService : public KeyedService, // tracked by this service. static const char kAccountInfoPref[]; + // TODO(mlerman): Remove all references to Profile::kNoHostedDomainFound in + // favour of this. + // Value representing no hosted domain in the kProfileHostedDomain preference. + static const char kNoHostedDomainFound[]; + // Information about a specific account. struct AccountInfo { + AccountInfo(); + ~AccountInfo(); + std::string account_id; // The account ID used by OAuth2TokenService. std::string gaia; std::string email; + std::string hosted_domain; // TODO(rogerta): eventually this structure will include other information // about the account, like full name, profile picture URL, etc. + + bool IsValid(); }; // Clients of AccountTrackerService can implement this interface and register @@ -44,8 +56,9 @@ class AccountTrackerService : public KeyedService, class Observer { public: virtual ~Observer() {} - virtual void OnAccountUpdated(const AccountInfo& info) = 0; - virtual void OnAccountRemoved(const AccountInfo& info) = 0; + virtual void OnAccountUpdated(const AccountInfo& info) {} + virtual void OnAccountUpdateFailed(const std::string& account_id) {} + virtual void OnAccountRemoved(const AccountInfo& info) {} }; // Possible values for the kAccountIdMigrationState preference. @@ -64,9 +77,11 @@ class AccountTrackerService : public KeyedService, void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); + // Take a SigninClient rather than a PrefService and a URLRequestContextGetter + // since RequestContext cannot be created at startup. + // (see http://crbug.com/171406) void Initialize(OAuth2TokenService* token_service, - PrefService* pref_service, - net::URLRequestContextGetter* request_context_getter); + SigninClient* signin_client); // Returns the list of known accounts and for which gaia IDs // have been fetched. @@ -94,6 +109,11 @@ class AccountTrackerService : public KeyedService, AccountIdMigrationState GetMigrationState(); static AccountIdMigrationState GetMigrationState(PrefService* pref_service); + protected: + // Available to be called in tests. + void SetAccountStateFromUserInfo(const std::string& account_id, + const base::DictionaryValue* user_info); + private: friend class AccountInfoFetcher; @@ -111,6 +131,7 @@ class AccountTrackerService : public KeyedService, }; void NotifyAccountUpdated(const AccountState& state); + void NotifyAccountUpdateFailed(const std::string& account_id); void NotifyAccountRemoved(const AccountState& state); void StartTrackingAccount(const std::string& account_id); @@ -128,8 +149,7 @@ class AccountTrackerService : public KeyedService, void LoadFromTokenService(); OAuth2TokenService* token_service_; // Not owned. - PrefService* pref_service_; // Not owned. - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + SigninClient* signin_client_; // Not owned. std::map<std::string, AccountInfoFetcher*> user_info_requests_; std::map<std::string, AccountState> accounts_; ObserverList<Observer> observer_list_; diff --git a/components/signin/core/browser/account_tracker_service_unittest.cc b/components/signin/core/browser/account_tracker_service_unittest.cc index 356f06f..c990b1a 100644 --- a/components/signin/core/browser/account_tracker_service_unittest.cc +++ b/components/signin/core/browser/account_tracker_service_unittest.cc @@ -10,6 +10,7 @@ #include "base/prefs/testing_pref_service.h" #include "base/strings/stringprintf.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/test_signin_client.h" #include "components/signin/core/common/signin_pref_names.h" #include "google_apis/gaia/fake_oauth2_token_service.h" #include "google_apis/gaia/gaia_oauth_client.h" @@ -202,12 +203,14 @@ class AccountTrackerServiceTest : public testing::Test { pref_service_.registry()->RegisterIntegerPref( prefs::kAccountIdMigrationState, AccountTrackerService::MIGRATION_NOT_STARTED); + signin_client_.reset(new TestSigninClient(&pref_service_)); + signin_client_.get()->SetURLRequestContext( + new net::TestURLRequestContextGetter( + message_loop_.message_loop_proxy())); account_tracker_.reset(new AccountTrackerService()); account_tracker_->Initialize(fake_oauth2_token_service_.get(), - &pref_service_, - new net::TestURLRequestContextGetter( - message_loop_.message_loop_proxy())); + signin_client_.get()); account_tracker_->AddObserver(&observer_); } @@ -231,9 +234,10 @@ class AccountTrackerServiceTest : public testing::Test { } std::string GenerateValidTokenInfoResponse(const std::string& account_id) { - return base::StringPrintf("{\"id\": \"%s\", \"email\": \"%s\"}", - AccountIdToGaiaId(account_id).c_str(), - AccountIdToEmail(account_id).c_str()); + return base::StringPrintf( + "{\"id\": \"%s\", \"email\": \"%s\", \"hd\": \"\"}", + AccountIdToGaiaId(account_id).c_str(), + AccountIdToEmail(account_id).c_str()); } void ReturnOAuthUrlFetchSuccess(const std::string& account_id); @@ -246,6 +250,7 @@ class AccountTrackerServiceTest : public testing::Test { return fake_oauth2_token_service_.get(); } TestingPrefServiceSimple* pref_service() { return &pref_service_; } + SigninClient* signin_client() { return signin_client_.get(); } private: void ReturnOAuthUrlFetchResults(int fetcher_id, @@ -258,6 +263,7 @@ class AccountTrackerServiceTest : public testing::Test { TestingPrefServiceSimple pref_service_; scoped_ptr<AccountTrackerService> account_tracker_; AccountTrackerObserver observer_; + scoped_ptr<TestSigninClient> signin_client_; }; void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults( @@ -326,15 +332,23 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfoFailed) { ASSERT_TRUE(observer()->CheckEvents()); } +TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) { + SimulateTokenAvailable("alpha"); + ReturnOAuthUrlFetchSuccess("alpha"); + ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched()); + ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha"))); + + SimulateTokenAvailable("alpha"); + ASSERT_TRUE(account_tracker()->IsAllUserInfoFetched()); + ASSERT_TRUE(observer()->CheckEvents()); +} + TEST_F(AccountTrackerServiceTest, TokenAlreadyExists) { SimulateTokenAvailable("alpha"); AccountTrackerService tracker; AccountTrackerObserver observer; tracker.AddObserver(&observer); - tracker.Initialize(token_service(), - pref_service(), - new net::TestURLRequestContextGetter( - message_loop()->message_loop_proxy())); + tracker.Initialize(token_service(), signin_client()); ASSERT_FALSE(tracker.IsAllUserInfoFetched()); ASSERT_TRUE(observer.CheckEvents()); tracker.RemoveObserver(&observer); @@ -377,12 +391,18 @@ TEST_F(AccountTrackerServiceTest, GetAccounts) { EXPECT_EQ("alpha", infos[0].account_id); EXPECT_EQ(AccountIdToGaiaId("alpha"), infos[0].gaia); EXPECT_EQ(AccountIdToEmail("alpha"), infos[0].email); + EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound, + infos[0].hosted_domain); EXPECT_EQ("beta", infos[1].account_id); EXPECT_EQ(AccountIdToGaiaId("beta"), infos[1].gaia); EXPECT_EQ(AccountIdToEmail("beta"), infos[1].email); + EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound, + infos[1].hosted_domain); EXPECT_EQ("gamma", infos[2].account_id); EXPECT_EQ(AccountIdToGaiaId("gamma"), infos[2].gaia); EXPECT_EQ(AccountIdToEmail("gamma"), infos[2].email); + EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound, + infos[2].hosted_domain); } TEST_F(AccountTrackerServiceTest, GetAccountInfo_Empty) { @@ -408,6 +428,7 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_UserInfo) { ASSERT_EQ("alpha", info.account_id); ASSERT_EQ(AccountIdToGaiaId("alpha"), info.gaia); ASSERT_EQ(AccountIdToEmail("alpha"), info.email); + ASSERT_EQ(AccountTrackerService::kNoHostedDomainFound, info.hosted_domain); } TEST_F(AccountTrackerServiceTest, FindAccountInfoByGaiaId) { @@ -453,10 +474,7 @@ TEST_F(AccountTrackerServiceTest, Persistence) { // to be saved to persistence. { AccountTrackerService tracker; - tracker.Initialize(token_service(), - pref_service(), - new net::TestURLRequestContextGetter( - message_loop()->message_loop_proxy())); + tracker.Initialize(token_service(), signin_client()); SimulateTokenAvailable("alpha"); ReturnOAuthUrlFetchSuccess("alpha"); SimulateTokenAvailable("beta"); @@ -469,10 +487,7 @@ TEST_F(AccountTrackerServiceTest, Persistence) { { AccountTrackerService tracker; tracker.AddObserver(observer()); - tracker.Initialize(token_service(), - pref_service(), - new net::TestURLRequestContextGetter( - message_loop()->message_loop_proxy())); + tracker.Initialize(token_service(), signin_client()); ASSERT_TRUE(observer()->CheckEvents(TrackingEvent(UPDATED, "alpha"), TrackingEvent(UPDATED, "beta"))); @@ -495,10 +510,7 @@ TEST_F(AccountTrackerServiceTest, Persistence) { // persistence. { AccountTrackerService tracker; - tracker.Initialize(token_service(), - pref_service(), - new net::TestURLRequestContextGetter( - message_loop()->message_loop_proxy())); + tracker.Initialize(token_service(), signin_client()); std::vector<AccountTrackerService::AccountInfo> infos = tracker.GetAccounts(); diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h index 282b31c..c8f8a4d 100644 --- a/components/signin/core/browser/signin_client.h +++ b/components/signin/core/browser/signin_client.h @@ -80,10 +80,15 @@ class SigninClient : public KeyedService { const std::string& name, const net::CookieStore::CookieChangedCallback& callback) = 0; - // Called when Google signin has succeeded. - virtual void GoogleSigninSucceeded(const std::string& account_id, - const std::string& username, - const std::string& password) {} + // Called after Google signin has succeeded. + virtual void OnSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) {} + + // Called after Google signin has succeeded and GetUserInfo has returned. + virtual void PostSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) {} virtual void SetSigninProcess(int host_id) = 0; virtual void ClearSigninProcess() = 0; diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index 8376f2e..5fe774d 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc @@ -60,12 +60,14 @@ bool SigninManager::IsWebBasedSigninFlowURL(const GURL& url) { } SigninManager::SigninManager(SigninClient* client, - ProfileOAuth2TokenService* token_service) + ProfileOAuth2TokenService* token_service, + AccountTrackerService* account_tracker_service) : SigninManagerBase(client), prohibit_signout_(false), type_(SIGNIN_TYPE_NONE), client_(client), token_service_(token_service), + account_tracker_service_(account_tracker_service), weak_pointer_factory_(this) {} void SigninManager::AddMergeSessionObserver( @@ -122,6 +124,8 @@ bool SigninManager::PrepareForSignin(SigninType type, type_ = type; possibly_invalid_username_.assign(username); password_.assign(password); + signin_manager_signed_in_ = false; + user_info_fetched_by_account_tracker_ = false; NotifyDiagnosticsObservers(SIGNIN_TYPE, SigninTypeToString(type)); return true; } @@ -170,7 +174,9 @@ void SigninManager::ClearTransientSigninData() { void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) { ClearTransientSigninData(); - FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSigninFailed(error)); + FOR_EACH_OBSERVER(SigninManagerBase::Observer, + observer_list_, + GoogleSigninFailed(error)); } void SigninManager::SignOut( @@ -229,7 +235,7 @@ void SigninManager::SignOut( << "IsSigninAllowed: " << IsSigninAllowed(); token_service_->RevokeAllCredentials(); - FOR_EACH_OBSERVER(Observer, + FOR_EACH_OBSERVER(SigninManagerBase::Observer, observer_list_, GoogleSignedOut(account_id, username)); } @@ -261,9 +267,12 @@ void SigninManager::Initialize(PrefService* local_state) { InitTokenService(); account_id_helper_.reset( new SigninAccountIdHelper(client_, token_service_, this)); + + account_tracker_service_->AddObserver(this); } void SigninManager::Shutdown() { + account_tracker_service_->RemoveObserver(this); if (merge_session_helper_) merge_session_helper_->CancelAll(); @@ -374,23 +383,46 @@ void SigninManager::OnSignedIn(const std::string& username) { base::Time::Now().ToInternalValue()); SetAuthenticatedUsername(username); possibly_invalid_username_.clear(); + signin_manager_signed_in_ = true; FOR_EACH_OBSERVER( - Observer, + SigninManagerBase::Observer, observer_list_, GoogleSigninSucceeded(GetAuthenticatedAccountId(), GetAuthenticatedUsername(), password_)); - client_->GoogleSigninSucceeded(GetAuthenticatedAccountId(), - GetAuthenticatedUsername(), - password_); + client_->OnSignedIn(GetAuthenticatedAccountId(), + GetAuthenticatedUsername(), + password_); signin_metrics::LogSigninProfile(client_->IsFirstRun(), client_->GetInstallDate()); - password_.clear(); // Don't need it anymore. DisableOneClickSignIn(client_->GetPrefs()); // Don't ever offer again. + + PostSignedIn(); +} + +void SigninManager::PostSignedIn() { + if (!signin_manager_signed_in_ || !user_info_fetched_by_account_tracker_) + return; + + client_->PostSignedIn(GetAuthenticatedAccountId(), + GetAuthenticatedUsername(), + password_); + password_.clear(); +} + +void SigninManager::OnAccountUpdated( + const AccountTrackerService::AccountInfo& info) { + user_info_fetched_by_account_tracker_ = true; + PostSignedIn(); +} + +void SigninManager::OnAccountUpdateFailed(const std::string& account_id) { + user_info_fetched_by_account_tracker_ = true; + PostSignedIn(); } void SigninManager::ProhibitSignout(bool prohibit_signout) { diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/signin_manager.h index 57f3813..04b645a 100644 --- a/components/signin/core/browser/signin_manager.h +++ b/components/signin/core/browser/signin_manager.h @@ -32,6 +32,7 @@ #include "base/prefs/pref_change_registrar.h" #include "base/prefs/pref_member.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/signin_internals_util.h" #include "components/signin/core/browser/signin_manager_base.h" #include "components/signin/core/browser/signin_metrics.h" @@ -44,7 +45,8 @@ class ProfileOAuth2TokenService; class SigninAccountIdHelper; class SigninClient; -class SigninManager : public SigninManagerBase { +class SigninManager : public SigninManagerBase, + public AccountTrackerService::Observer { public: // The callback invoked once the OAuth token has been fetched during signin, // but before the profile transitions to the "signed-in" state. This allows @@ -63,7 +65,9 @@ class SigninManager : public SigninManagerBase { // OneClickSigninHelper. static const char kChromeSigninEffectiveSite[]; - SigninManager(SigninClient* client, ProfileOAuth2TokenService* token_service); + SigninManager(SigninClient* client, + ProfileOAuth2TokenService* token_service, + AccountTrackerService* account_tracker_service); ~SigninManager() override; // Returns true if the username is allowed based on the policy string. @@ -162,6 +166,15 @@ class SigninManager : public SigninManagerBase { // a sign-in success notification. void OnSignedIn(const std::string& username); + // Waits for the AccountTrackerService, then sends GoogleSigninSucceeded to + // the client and clears the local password. + void PostSignedIn(); + + // AccountTrackerService::Observer implementation. + void OnAccountUpdated(const AccountTrackerService::AccountInfo& info) + override; + void OnAccountUpdateFailed(const std::string& account_id) override; + // Called when a new request to re-authenticate a user is in progress. // Will clear in memory data but leaves the db as such so when the browser // restarts we can use the old token(which might throw a password error). @@ -199,6 +212,10 @@ class SigninManager : public SigninManagerBase { // outlive this object. ProfileOAuth2TokenService* token_service_; + // The AccountTrackerService instance associated with this object. Must + // outlive this object. + AccountTrackerService* account_tracker_service_; + // Helper object to listen for changes to signin preferences stored in non- // profile-specific local prefs (like kGoogleServicesUsernamePattern). PrefChangeRegistrar local_state_pref_registrar_; @@ -211,6 +228,12 @@ class SigninManager : public SigninManagerBase { base::WeakPtrFactory<SigninManager> weak_pointer_factory_; + // Two gate conditions for when PostSignedIn should be called. Verify + // that the SigninManager has reached OnSignedIn() and the AccountTracker + // has completed calling GetUserInfo. + bool signin_manager_signed_in_; + bool user_info_fetched_by_account_tracker_; + DISALLOW_COPY_AND_ASSIGN(SigninManager); }; diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc index 68b32df..6c16931 100644 --- a/components/signin/core/browser/test_signin_client.cc +++ b/components/signin/core/browser/test_signin_client.cc @@ -45,7 +45,12 @@ std::string TestSigninClient::GetSigninScopedDeviceId() { return std::string(); } -void TestSigninClient::OnSignedOut() { +void TestSigninClient::OnSignedOut() {} + +void TestSigninClient::PostSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) { + signed_in_password_ = password; } net::URLRequestContextGetter* TestSigninClient::GetURLRequestContext() { diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h index a359804..8f52f20 100644 --- a/components/signin/core/browser/test_signin_client.h +++ b/components/signin/core/browser/test_signin_client.h @@ -47,6 +47,13 @@ class TestSigninClient : public SigninClient { // Does nothing. void OnSignedOut() override; + // Trace that this was called. + void PostSignedIn(const std::string& account_id, + const std::string& username, + const std::string& password) override; + + std::string get_signed_in_password() { return signed_in_password_; } + // Returns the empty string. std::string GetProductVersion() override; @@ -94,6 +101,9 @@ class TestSigninClient : public SigninClient { int signin_host_id_; PrefService* pref_service_; + // Pointer to be filled by PostSignedIn. + std::string signed_in_password_; + #if defined(OS_IOS) scoped_ptr<ios::FakeProfileOAuth2TokenServiceIOSProvider> iosProvider_; #endif diff --git a/components/signin/core/common/signin_pref_names.cc b/components/signin/core/common/signin_pref_names.cc index 3348d27..5d2ea19 100644 --- a/components/signin/core/common/signin_pref_names.cc +++ b/components/signin/core/common/signin_pref_names.cc @@ -14,8 +14,8 @@ const char kAccountIdMigrationState[] = "account_id_migration_state"; // Boolean identifying whether reverse auto-login is enabled. const char kAutologinEnabled[] = "autologin.enabled"; -// The profile's hosted domain; empty if unset; Profile::kNoHostedDomainFound -// if there is none. +// The profile's hosted domain; empty if unset; +// AccountTrackerService::kNoHostedDomainFound if there is none. const char kGoogleServicesHostedDomain[] = "google.services.hosted_domain"; // String the identifies the last user that logged into sync and other |