1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_account_id_helper.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/prefs/pref_service.h"
8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h"
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/signin_client.h"
10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/common/signin_pref_names.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(guohui): this class should be moved to a more generic place for reuse.
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SigninAccountIdHelper::GaiaIdFetcher
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : public OAuth2TokenService::Consumer,
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      public gaia::GaiaOAuthClient::Delegate {
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  GaiaIdFetcher(SigninClient* client,
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                ProfileOAuth2TokenService* token_service,
20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                SigninManagerBase* signin_manager,
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                SigninAccountIdHelper* signin_account_id_helper);
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~GaiaIdFetcher();
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // OAuth2TokenService::Consumer implementation.
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 const std::string& access_token,
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 const base::Time& expiration_time) OVERRIDE;
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 const GoogleServiceAuthError& error) OVERRIDE;
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // gaia::GaiaOAuthClient::Delegate implementation.
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnGetUserIdResponse(const std::string& gaia_id) OVERRIDE;
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnOAuthError() OVERRIDE;
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnNetworkError(int response_code) OVERRIDE;
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Start();
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SigninClient* client_;
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ProfileOAuth2TokenService* token_service_;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SigninManagerBase* signin_manager_;
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SigninAccountIdHelper* signin_account_id_helper_;
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<OAuth2TokenService::Request> login_token_request_;
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GaiaIdFetcher);
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SigninAccountIdHelper::GaiaIdFetcher::GaiaIdFetcher(
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SigninClient* client,
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ProfileOAuth2TokenService* token_service,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SigninManagerBase* signin_manager,
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SigninAccountIdHelper* signin_account_id_helper)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : OAuth2TokenService::Consumer("gaia_id_fetcher"),
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      client_(client),
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      token_service_(token_service),
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      signin_manager_(signin_manager),
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      signin_account_id_helper_(signin_account_id_helper) {
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Start();
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SigninAccountIdHelper::GaiaIdFetcher::~GaiaIdFetcher() {}
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::GaiaIdFetcher::Start() {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OAuth2TokenService::ScopeSet scopes;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scopes.insert("https://www.googleapis.com/auth/userinfo.profile");
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  login_token_request_ = token_service_->StartRequest(
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      signin_manager_->GetAuthenticatedAccountId(), scopes, this);
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::GaiaIdFetcher::OnGetTokenSuccess(
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const OAuth2TokenService::Request* request,
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& access_token,
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::Time& expiration_time) {
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_EQ(request, login_token_request_.get());
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gaia_oauth_client_.reset(
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new gaia::GaiaOAuthClient(client_->GetURLRequestContext()));
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const int kMaxGetUserIdRetries = 3;
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gaia_oauth_client_->GetUserId(access_token, kMaxGetUserIdRetries, this);
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::GaiaIdFetcher::OnGetTokenFailure(
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const OAuth2TokenService::Request* request,
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GoogleServiceAuthError& error) {
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "OnGetTokenFailure: " << error.error_message();
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_EQ(request, login_token_request_.get());
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  signin_account_id_helper_->OnPrimaryAccountIdFetched("");
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::GaiaIdFetcher::OnGetUserIdResponse(
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& gaia_id) {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  signin_account_id_helper_->OnPrimaryAccountIdFetched(gaia_id);
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::GaiaIdFetcher::OnOAuthError() {
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "OnOAuthError";
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid SigninAccountIdHelper::GaiaIdFetcher::OnNetworkError(int response_code) {
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "OnNetworkError " << response_code;
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
106effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSigninAccountIdHelper::SigninAccountIdHelper(
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SigninClient* client,
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ProfileOAuth2TokenService* token_service,
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    SigninManagerBase* signin_manager)
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : client_(client),
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      token_service_(token_service),
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      signin_manager_(signin_manager) {
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(client_);
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(token_service_);
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(signin_manager_);
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  signin_manager_->AddObserver(this);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string primary_email = signin_manager_->GetAuthenticatedAccountId();
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!primary_email.empty() &&
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      token_service_->RefreshTokenIsAvailable(primary_email) &&
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !disable_for_test_) {
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    id_fetcher_.reset(
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        new GaiaIdFetcher(client_, token_service_, signin_manager_, this));
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  token_service_->AddObserver(this);
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)SigninAccountIdHelper::~SigninAccountIdHelper() {
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  signin_manager_->RemoveObserver(this);
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  token_service_->RemoveObserver(this);
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SigninAccountIdHelper::GoogleSignedOut(const std::string& account_id,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            const std::string& username) {
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::OnRefreshTokenAvailable(
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& account_id) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (account_id == signin_manager_->GetAuthenticatedAccountId()) {
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string current_gaia_id =
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        client_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (current_gaia_id.empty() && !disable_for_test_) {
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      id_fetcher_.reset(
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          new GaiaIdFetcher(client_, token_service_, signin_manager_, this));
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SigninAccountIdHelper::OnPrimaryAccountIdFetched(
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& gaia_id) {
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!gaia_id.empty()) {
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    client_->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                   gaia_id);
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SigninAccountIdHelper::disable_for_test_ = false;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SigninAccountIdHelper::SetDisableForTest(bool disable_for_test) {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disable_for_test_ = disable_for_test;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
164