blob: b3e3c13d140fe55aa96ef472164456f58defc2ec [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/signin/signin_account_id_helper.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_oauth_client.h"
// TODO(guohui): this class should be moved to a more generic place for reuse.
class SigninAccountIdHelper::AccountIdFetcher
: public OAuth2TokenService::Consumer,
public gaia::GaiaOAuthClient::Delegate {
public:
AccountIdFetcher(Profile* profile,
SigninAccountIdHelper* signin_account_id_helper);
virtual ~AccountIdFetcher();
// OAuth2TokenService::Consumer implementation.
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) OVERRIDE;
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
// gaia::GaiaOAuthClient::Delegate implementation.
virtual void OnGetUserIdResponse(const std::string& gaia_id) OVERRIDE;
virtual void OnOAuthError() OVERRIDE;
virtual void OnNetworkError(int response_code) OVERRIDE;
private:
void Start();
Profile* profile_;
SigninAccountIdHelper* signin_account_id_helper_;
scoped_ptr<OAuth2TokenService::Request> login_token_request_;
scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
DISALLOW_COPY_AND_ASSIGN(AccountIdFetcher);
};
SigninAccountIdHelper::AccountIdFetcher::AccountIdFetcher(
Profile* profile,
SigninAccountIdHelper* signin_account_id_helper)
: profile_(profile),
signin_account_id_helper_(signin_account_id_helper) {
Start();
}
SigninAccountIdHelper::AccountIdFetcher::~AccountIdFetcher() {}
void SigninAccountIdHelper::AccountIdFetcher::Start() {
ProfileOAuth2TokenService* service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
login_token_request_ = service->StartRequest(
service->GetPrimaryAccountId(), OAuth2TokenService::ScopeSet(), this);
}
void SigninAccountIdHelper::AccountIdFetcher::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
DCHECK_EQ(request, login_token_request_.get());
gaia_oauth_client_.reset(
new gaia::GaiaOAuthClient(profile_->GetRequestContext()));
const int kMaxGetUserIdRetries = 3;
gaia_oauth_client_->GetUserId(access_token, kMaxGetUserIdRetries, this);
}
void SigninAccountIdHelper::AccountIdFetcher::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
VLOG(1) << "OnGetTokenFailure: " << error.error_message();
DCHECK_EQ(request, login_token_request_.get());
signin_account_id_helper_->OnPrimaryAccountIdFetched("");
}
void SigninAccountIdHelper::AccountIdFetcher::OnGetUserIdResponse(
const std::string& account_id) {
signin_account_id_helper_->OnPrimaryAccountIdFetched(account_id);
}
void SigninAccountIdHelper::AccountIdFetcher::OnOAuthError() {
VLOG(1) << "OnOAuthError";
}
void SigninAccountIdHelper::AccountIdFetcher::OnNetworkError(
int response_code) {
VLOG(1) << "OnNetworkError " << response_code;
}
SigninAccountIdHelper::SigninAccountIdHelper(Profile* profile)
: profile_(profile) {
registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
content::Source<Profile>(profile_));
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
std::string primary_email = token_service->GetPrimaryAccountId();
if (!primary_email.empty() &&
token_service->RefreshTokenIsAvailable(primary_email) &&
!disable_for_test_) {
id_fetcher_.reset(new AccountIdFetcher(profile_, this));
}
token_service->AddObserver(this);
}
SigninAccountIdHelper::~SigninAccountIdHelper() {
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
RemoveObserver(this);
}
void SigninAccountIdHelper::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == chrome::NOTIFICATION_GOOGLE_SIGNED_OUT)
profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
}
void SigninAccountIdHelper::OnRefreshTokenAvailable(const std::string& email) {
ProfileOAuth2TokenService* service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
if (email == service->GetPrimaryAccountId()) {
std::string current_account_id =
profile_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId);
if (current_account_id.empty() && !disable_for_test_) {
id_fetcher_.reset(new AccountIdFetcher(profile_, this));
}
}
}
void SigninAccountIdHelper::OnPrimaryAccountIdFetched(
const std::string& account_id) {
if (!account_id.empty()) {
profile_->GetPrefs()->SetString(
prefs::kGoogleServicesUserAccountId, account_id);
}
}
// static
bool SigninAccountIdHelper::disable_for_test_ = false;
// static
void SigninAccountIdHelper::SetDisableForTest(bool disable_for_test) {
disable_for_test_ = disable_for_test;
}