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/fake_profile_oauth2_token_service.h"
6
7#include "base/message_loop/message_loop.h"
8#include "components/signin/core/browser/signin_account_id_helper.h"
9
10FakeProfileOAuth2TokenService::PendingRequest::PendingRequest() {
11}
12
13FakeProfileOAuth2TokenService::PendingRequest::~PendingRequest() {
14}
15
16FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService()
17    : auto_post_fetch_response_on_message_loop_(false),
18      weak_ptr_factory_(this) {
19  SigninAccountIdHelper::SetDisableForTest(true);
20}
21
22FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {
23  SigninAccountIdHelper::SetDisableForTest(false);
24}
25
26bool FakeProfileOAuth2TokenService::RefreshTokenIsAvailable(
27    const std::string& account_id) const {
28  return !GetRefreshToken(account_id).empty();
29}
30
31void FakeProfileOAuth2TokenService::LoadCredentials(
32    const std::string& primary_account_id) {
33  // Empty implementation as FakeProfileOAuth2TokenService does not have any
34  // credentials to load.
35}
36
37std::vector<std::string> FakeProfileOAuth2TokenService::GetAccounts() {
38  std::vector<std::string> account_ids;
39  for (std::map<std::string, std::string>::const_iterator iter =
40           refresh_tokens_.begin(); iter != refresh_tokens_.end(); ++iter) {
41    account_ids.push_back(iter->first);
42  }
43  return account_ids;
44}
45
46void FakeProfileOAuth2TokenService::UpdateCredentials(
47    const std::string& account_id,
48    const std::string& refresh_token) {
49  IssueRefreshTokenForUser(account_id, refresh_token);
50}
51
52void FakeProfileOAuth2TokenService::IssueRefreshToken(
53    const std::string& token) {
54  IssueRefreshTokenForUser("account_id", token);
55}
56
57void FakeProfileOAuth2TokenService::IssueRefreshTokenForUser(
58    const std::string& account_id,
59    const std::string& token) {
60  ScopedBacthChange batch(this);
61  if (token.empty()) {
62    refresh_tokens_.erase(account_id);
63    FireRefreshTokenRevoked(account_id);
64  } else {
65    refresh_tokens_[account_id] = token;
66    FireRefreshTokenAvailable(account_id);
67    // TODO(atwilson): Maybe we should also call FireRefreshTokensLoaded() here?
68  }
69}
70
71void FakeProfileOAuth2TokenService::IssueAllRefreshTokensLoaded() {
72  FireRefreshTokensLoaded();
73}
74
75void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
76    const std::string& account_id,
77    const std::string& access_token,
78    const base::Time& expiration) {
79  CompleteRequests(account_id,
80                   true,
81                   ScopeSet(),
82                   GoogleServiceAuthError::AuthErrorNone(),
83                   access_token,
84                   expiration);
85}
86
87void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequestsForAccount(
88    const std::string& account_id,
89    const GoogleServiceAuthError& error) {
90  CompleteRequests(account_id,
91                   true,
92                   ScopeSet(),
93                   error,
94                   std::string(),
95                   base::Time());
96}
97
98void FakeProfileOAuth2TokenService::IssueTokenForScope(
99    const ScopeSet& scope,
100    const std::string& access_token,
101    const base::Time& expiration) {
102  CompleteRequests("",
103                   false,
104                   scope,
105                   GoogleServiceAuthError::AuthErrorNone(),
106                   access_token,
107                   expiration);
108}
109
110void FakeProfileOAuth2TokenService::IssueErrorForScope(
111    const ScopeSet& scope,
112    const GoogleServiceAuthError& error) {
113  CompleteRequests("", false, scope, error, std::string(), base::Time());
114}
115
116void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequests(
117    const GoogleServiceAuthError& error) {
118  CompleteRequests("", true, ScopeSet(), error, std::string(), base::Time());
119}
120
121void FakeProfileOAuth2TokenService::IssueTokenForAllPendingRequests(
122    const std::string& access_token,
123    const base::Time& expiration) {
124  CompleteRequests("",
125                   true,
126                   ScopeSet(),
127                   GoogleServiceAuthError::AuthErrorNone(),
128                   access_token,
129                   expiration);
130}
131
132void FakeProfileOAuth2TokenService::CompleteRequests(
133    const std::string& account_id,
134    bool all_scopes,
135    const ScopeSet& scope,
136    const GoogleServiceAuthError& error,
137    const std::string& access_token,
138    const base::Time& expiration) {
139  std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests =
140      GetPendingRequests();
141
142  // Walk the requests and notify the callbacks.
143  for (std::vector<PendingRequest>::iterator it = pending_requests_.begin();
144       it != pending_requests_.end(); ++it) {
145    if (!it->request)
146      continue;
147
148    bool scope_matches = all_scopes || it->scopes == scope;
149    bool account_matches = account_id.empty() || account_id == it->account_id;
150    if (account_matches && scope_matches)
151      it->request->InformConsumer(error, access_token, expiration);
152  }
153}
154
155std::string FakeProfileOAuth2TokenService::GetRefreshToken(
156    const std::string& account_id) const {
157  std::map<std::string, std::string>::const_iterator it =
158      refresh_tokens_.find(account_id);
159  if (it != refresh_tokens_.end())
160    return it->second;
161  return std::string();
162}
163
164net::URLRequestContextGetter*
165FakeProfileOAuth2TokenService::GetRequestContext() {
166  return NULL;
167}
168
169std::vector<FakeProfileOAuth2TokenService::PendingRequest>
170FakeProfileOAuth2TokenService::GetPendingRequests() {
171  std::vector<PendingRequest> valid_requests;
172  for (std::vector<PendingRequest>::iterator it = pending_requests_.begin();
173       it != pending_requests_.end(); ++it) {
174    if (it->request)
175      valid_requests.push_back(*it);
176  }
177  return valid_requests;
178}
179
180void FakeProfileOAuth2TokenService::FetchOAuth2Token(
181    RequestImpl* request,
182    const std::string& account_id,
183    net::URLRequestContextGetter* getter,
184    const std::string& client_id,
185    const std::string& client_secret,
186    const ScopeSet& scopes) {
187  PendingRequest pending_request;
188  pending_request.account_id = account_id;
189  pending_request.client_id = client_id;
190  pending_request.client_secret = client_secret;
191  pending_request.scopes = scopes;
192  pending_request.request = request->AsWeakPtr();
193  pending_requests_.push_back(pending_request);
194
195  if (auto_post_fetch_response_on_message_loop_) {
196    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
197        &FakeProfileOAuth2TokenService::IssueAllTokensForAccount,
198        weak_ptr_factory_.GetWeakPtr(),
199        account_id,
200        "access_token",
201        base::Time::Max()));
202  }
203}
204
205OAuth2AccessTokenFetcher*
206FakeProfileOAuth2TokenService::CreateAccessTokenFetcher(
207    const std::string& account_id,
208    net::URLRequestContextGetter* getter,
209    OAuth2AccessTokenConsumer* consumer) {
210  NOTREACHED();
211  return NULL;
212}
213
214void FakeProfileOAuth2TokenService::InvalidateOAuth2Token(
215    const std::string& account_id,
216    const std::string& client_id,
217    const ScopeSet& scopes,
218    const std::string& access_token) {
219  // Do nothing, as we don't have a cache from which to remove the token.
220}
221