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. 4 5 #include "chrome/browser/signin/signin_account_id_helper.h" 6 7 #include "base/prefs/pref_service.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/signin/profile_oauth2_token_service.h" 11 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 12 #include "chrome/common/pref_names.h" 13 #include "content/public/browser/notification_service.h" 14 #include "google_apis/gaia/gaia_oauth_client.h" 15 16 // TODO(guohui): this class should be moved to a more generic place for reuse. 17 class SigninAccountIdHelper::AccountIdFetcher 18 : public OAuth2TokenService::Consumer, 19 public gaia::GaiaOAuthClient::Delegate { 20 public: 21 AccountIdFetcher(Profile* profile, 22 SigninAccountIdHelper* signin_account_id_helper); 23 virtual ~AccountIdFetcher(); 24 25 // OAuth2TokenService::Consumer implementation. 26 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 27 const std::string& access_token, 28 const base::Time& expiration_time) OVERRIDE; 29 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 30 const GoogleServiceAuthError& error) OVERRIDE; 31 32 // gaia::GaiaOAuthClient::Delegate implementation. 33 virtual void OnGetUserIdResponse(const std::string& gaia_id) OVERRIDE; 34 virtual void OnOAuthError() OVERRIDE; 35 virtual void OnNetworkError(int response_code) OVERRIDE; 36 37 private: 38 void Start(); 39 40 Profile* profile_; 41 SigninAccountIdHelper* signin_account_id_helper_; 42 43 scoped_ptr<OAuth2TokenService::Request> login_token_request_; 44 scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; 45 46 DISALLOW_COPY_AND_ASSIGN(AccountIdFetcher); 47 }; 48 49 SigninAccountIdHelper::AccountIdFetcher::AccountIdFetcher( 50 Profile* profile, 51 SigninAccountIdHelper* signin_account_id_helper) 52 : profile_(profile), 53 signin_account_id_helper_(signin_account_id_helper) { 54 Start(); 55 } 56 57 SigninAccountIdHelper::AccountIdFetcher::~AccountIdFetcher() {} 58 59 void SigninAccountIdHelper::AccountIdFetcher::Start() { 60 ProfileOAuth2TokenService* service = 61 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 62 OAuth2TokenService::ScopeSet scopes; 63 scopes.insert("https://www.googleapis.com/auth/userinfo.profile"); 64 login_token_request_ = service->StartRequest( 65 service->GetPrimaryAccountId(), scopes, this); 66 } 67 68 void SigninAccountIdHelper::AccountIdFetcher::OnGetTokenSuccess( 69 const OAuth2TokenService::Request* request, 70 const std::string& access_token, 71 const base::Time& expiration_time) { 72 DCHECK_EQ(request, login_token_request_.get()); 73 74 gaia_oauth_client_.reset( 75 new gaia::GaiaOAuthClient(profile_->GetRequestContext())); 76 77 const int kMaxGetUserIdRetries = 3; 78 gaia_oauth_client_->GetUserId(access_token, kMaxGetUserIdRetries, this); 79 } 80 81 void SigninAccountIdHelper::AccountIdFetcher::OnGetTokenFailure( 82 const OAuth2TokenService::Request* request, 83 const GoogleServiceAuthError& error) { 84 VLOG(1) << "OnGetTokenFailure: " << error.error_message(); 85 DCHECK_EQ(request, login_token_request_.get()); 86 signin_account_id_helper_->OnPrimaryAccountIdFetched(""); 87 } 88 89 void SigninAccountIdHelper::AccountIdFetcher::OnGetUserIdResponse( 90 const std::string& account_id) { 91 signin_account_id_helper_->OnPrimaryAccountIdFetched(account_id); 92 } 93 94 void SigninAccountIdHelper::AccountIdFetcher::OnOAuthError() { 95 VLOG(1) << "OnOAuthError"; 96 } 97 98 void SigninAccountIdHelper::AccountIdFetcher::OnNetworkError( 99 int response_code) { 100 VLOG(1) << "OnNetworkError " << response_code; 101 } 102 103 SigninAccountIdHelper::SigninAccountIdHelper(Profile* profile) 104 : profile_(profile) { 105 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 106 content::Source<Profile>(profile_)); 107 108 ProfileOAuth2TokenService* token_service = 109 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 110 std::string primary_email = token_service->GetPrimaryAccountId(); 111 if (!primary_email.empty() && 112 token_service->RefreshTokenIsAvailable(primary_email) && 113 !disable_for_test_) { 114 id_fetcher_.reset(new AccountIdFetcher(profile_, this)); 115 } 116 token_service->AddObserver(this); 117 } 118 119 SigninAccountIdHelper::~SigninAccountIdHelper() { 120 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)-> 121 RemoveObserver(this); 122 } 123 124 void SigninAccountIdHelper::Observe( 125 int type, 126 const content::NotificationSource& source, 127 const content::NotificationDetails& details) { 128 if (type == chrome::NOTIFICATION_GOOGLE_SIGNED_OUT) 129 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId); 130 } 131 132 void SigninAccountIdHelper::OnRefreshTokenAvailable(const std::string& email) { 133 ProfileOAuth2TokenService* service = 134 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 135 if (email == service->GetPrimaryAccountId()) { 136 std::string current_account_id = 137 profile_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId); 138 if (current_account_id.empty() && !disable_for_test_) { 139 id_fetcher_.reset(new AccountIdFetcher(profile_, this)); 140 } 141 } 142 } 143 144 void SigninAccountIdHelper::OnPrimaryAccountIdFetched( 145 const std::string& account_id) { 146 if (!account_id.empty()) { 147 profile_->GetPrefs()->SetString( 148 prefs::kGoogleServicesUserAccountId, account_id); 149 } 150 } 151 152 // static 153 bool SigninAccountIdHelper::disable_for_test_ = false; 154 155 // static 156 void SigninAccountIdHelper::SetDisableForTest(bool disable_for_test) { 157 disable_for_test_ = disable_for_test; 158 } 159 160