1// Copyright 2014 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 "components/signin/core/browser/account_service_flag_fetcher.h"
6
7#include "base/strings/string_split.h"
8#include "components/signin/core/browser/profile_oauth2_token_service.h"
9#include "google_apis/gaia/gaia_constants.h"
10
11AccountServiceFlagFetcher::AccountServiceFlagFetcher(
12    const std::string& account_id,
13    ProfileOAuth2TokenService* token_service,
14    net::URLRequestContextGetter* request_context,
15    const ResultCallback& callback)
16    : OAuth2TokenService::Consumer("account_service_flag_fetcher"),
17      account_id_(account_id),
18      token_service_(token_service),
19      gaia_auth_fetcher_(this, GaiaConstants::kChromeSource, request_context),
20      callback_(callback) {
21  Start();
22}
23
24AccountServiceFlagFetcher::~AccountServiceFlagFetcher() {
25  // Ensures PO2TS observation is cleared when AccountServiceFlagFetcher is
26  // destructed before refresh token is available.
27  token_service_->RemoveObserver(this);
28
29  gaia_auth_fetcher_.CancelRequest();
30}
31
32void AccountServiceFlagFetcher::Start() {
33  if (token_service_->RefreshTokenIsAvailable(account_id_)) {
34    StartFetchingOAuth2AccessToken();
35  } else {
36    // Wait until we get a refresh token.
37    token_service_->AddObserver(this);
38  }
39}
40
41void AccountServiceFlagFetcher::OnRefreshTokenAvailable(
42    const std::string& account_id) {
43  // Wait until we get a refresh token for the requested account.
44  if (account_id != account_id_)
45    return;
46
47  token_service_->RemoveObserver(this);
48
49  StartFetchingOAuth2AccessToken();
50}
51
52void AccountServiceFlagFetcher::OnRefreshTokensLoaded() {
53  token_service_->RemoveObserver(this);
54
55  // The PO2TS has loaded all tokens, but we didn't get one for the account we
56  // want. We probably won't get one any time soon, so report an error.
57  DLOG(WARNING) << "AccountServiceFlagFetcher::OnRefreshTokensLoaded: "
58                << "Did not get a refresh token for account " << account_id_;
59  callback_.Run(TOKEN_ERROR, std::vector<std::string>());
60}
61
62void AccountServiceFlagFetcher::StartFetchingOAuth2AccessToken() {
63  OAuth2TokenService::ScopeSet scopes;
64  scopes.insert(GaiaConstants::kOAuth1LoginScope);
65  oauth2_access_token_request_ = token_service_->StartRequest(
66      account_id_, scopes, this);
67}
68
69void AccountServiceFlagFetcher::OnGetTokenSuccess(
70    const OAuth2TokenService::Request* request,
71    const std::string& access_token,
72    const base::Time& expiration_time) {
73  DCHECK_EQ(oauth2_access_token_request_.get(), request);
74  oauth2_access_token_request_.reset();
75
76  gaia_auth_fetcher_.StartOAuthLogin(access_token, GaiaConstants::kGaiaService);
77}
78
79void AccountServiceFlagFetcher::OnGetTokenFailure(
80    const OAuth2TokenService::Request* request,
81    const GoogleServiceAuthError& error) {
82  DCHECK_EQ(oauth2_access_token_request_.get(), request);
83  oauth2_access_token_request_.reset();
84
85  DLOG(WARNING) << "AccountServiceFlagFetcher::OnGetTokenFailure: "
86                << error.ToString();
87  callback_.Run(TOKEN_ERROR, std::vector<std::string>());
88}
89
90void AccountServiceFlagFetcher::OnClientLoginSuccess(
91    const ClientLoginResult& result) {
92  gaia_auth_fetcher_.StartGetUserInfo(result.lsid);
93}
94
95void AccountServiceFlagFetcher::OnClientLoginFailure(
96    const GoogleServiceAuthError& error) {
97  DLOG(WARNING) << "AccountServiceFlagFetcher::OnClientLoginFailure: "
98                << error.ToString();
99  callback_.Run(SERVICE_ERROR, std::vector<std::string>());
100}
101
102void AccountServiceFlagFetcher::OnGetUserInfoSuccess(const UserInfoMap& data) {
103  ResultCode result = SERVICE_ERROR;
104  std::vector<std::string> services;
105  UserInfoMap::const_iterator services_iter = data.find("allServices");
106  if (services_iter != data.end()) {
107    result = SUCCESS;
108    base::SplitString(services_iter->second, ',', &services);
109  } else {
110    DLOG(WARNING) << "AccountServiceFlagFetcher::OnGetUserInfoSuccess: "
111                  << "GetUserInfo response didn't include allServices field.";
112  }
113  callback_.Run(result, services);
114}
115
116void AccountServiceFlagFetcher::OnGetUserInfoFailure(
117    const GoogleServiceAuthError& error) {
118  DLOG(WARNING) << "AccountServiceFlagFetcher::OnGetUserInfoFailure: "
119                << error.ToString();
120  callback_.Run(SERVICE_ERROR, std::vector<std::string>());
121}
122