Home | History | Annotate | Download | only in signin
      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