• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AccountIdFetcher(Profile * profile,SigninAccountIdHelper * signin_account_id_helper)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 
~AccountIdFetcher()57 SigninAccountIdHelper::AccountIdFetcher::~AccountIdFetcher() {}
58 
Start()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 
OnGetTokenSuccess(const OAuth2TokenService::Request * request,const std::string & access_token,const base::Time & expiration_time)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 
OnGetTokenFailure(const OAuth2TokenService::Request * request,const GoogleServiceAuthError & error)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 
OnGetUserIdResponse(const std::string & account_id)89 void SigninAccountIdHelper::AccountIdFetcher::OnGetUserIdResponse(
90     const std::string& account_id) {
91   signin_account_id_helper_->OnPrimaryAccountIdFetched(account_id);
92 }
93 
OnOAuthError()94 void SigninAccountIdHelper::AccountIdFetcher::OnOAuthError() {
95   VLOG(1) << "OnOAuthError";
96 }
97 
OnNetworkError(int response_code)98 void SigninAccountIdHelper::AccountIdFetcher::OnNetworkError(
99     int response_code) {
100   VLOG(1) << "OnNetworkError " << response_code;
101 }
102 
SigninAccountIdHelper(Profile * profile)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 
~SigninAccountIdHelper()119 SigninAccountIdHelper::~SigninAccountIdHelper() {
120   ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
121       RemoveObserver(this);
122 }
123 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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 
OnRefreshTokenAvailable(const std::string & email)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 
OnPrimaryAccountIdFetched(const std::string & account_id)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
SetDisableForTest(bool disable_for_test)156 void SigninAccountIdHelper::SetDisableForTest(bool disable_for_test) {
157   disable_for_test_ = disable_for_test;
158 }
159 
160