oauth2_token_service.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/rand_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint OAuth2TokenService::max_fetch_retry_num_ = 5;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)OAuth2TokenService::RequestParameters::RequestParameters(
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_id,
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const ScopeSet& scopes)
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : client_id(client_id),
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id(account_id),
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      scopes(scopes) {
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)OAuth2TokenService::RequestParameters::~RequestParameters() {
3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool OAuth2TokenService::RequestParameters::operator<(
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const RequestParameters& p) const {
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (client_id < p.client_id)
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  else if (p.client_id < client_id)
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (account_id < p.account_id)
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else if (p.account_id < account_id)
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return scopes < p.scopes;
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::RequestImpl::RequestImpl(
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& account_id,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OAuth2TokenService::Consumer* consumer)
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : account_id_(account_id),
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      consumer_(consumer) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::RequestImpl::~RequestImpl() {
57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string OAuth2TokenService::RequestImpl::GetAccountId() const {
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return account_id_;
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string OAuth2TokenService::RequestImpl::GetConsumerId() const {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return consumer_->id();
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::RequestImpl::InformConsumer(
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GoogleServiceAuthError& error,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& access_token,
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& expiration_date) {
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error.state() == GoogleServiceAuthError::NONE)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    consumer_->OnGetTokenSuccess(this, access_token, expiration_date);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    consumer_->OnGetTokenFailure(this, error);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Class that fetches an OAuth2 access token for a given set of scopes and
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// OAuth2 refresh token.
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Class that fetches OAuth2 access tokens for given scopes and refresh token.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// It aims to meet OAuth2TokenService's requirements on token fetching. Retry
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// mechanism is used to handle failures.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To use this class, call CreateAndStart() to create and start a Fetcher.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The Fetcher will call back the service by calling
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// not destructed before it completes fetching; if the Fetcher is destructed
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// before it completes fetching, the service will never be called back. The
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Fetcher destructs itself after calling back the service when finishes
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// fetching.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Requests that are waiting for the fetching results of this Fetcher can be
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// added to the Fetcher by calling
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// completes fetching.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The waiting requests are taken as weak pointers and they can be deleted.
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The waiting requests will be called back with fetching results if they are
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// not deleted
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - when the Fetcher completes fetching, if the Fetcher is not destructed
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   before it completes fetching, or
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - when the Fetcher is destructed if the Fetcher is destructed before it
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//   completes fetching (in this case, the waiting requests will be called
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//   back with error).
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates a Fetcher and starts fetching an OAuth2 access token for
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |refresh_token| and |scopes| in the request context obtained by |getter|.
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The given |oauth2_token_service| will be informed when fetching is done.
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 const std::string& account_id,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 net::URLRequestContextGetter* getter,
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                 const std::string& client_id,
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                 const std::string& client_secret,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& refresh_token,
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                 const ScopeSet& scopes,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 base::WeakPtr<RequestImpl> waiting_request);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~Fetcher();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add a request that is waiting for the result of this Fetcher.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns count of waiting requests.
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t GetWaitingRequestCount() const;
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::vector<base::WeakPtr<RequestImpl> >& waiting_requests() const {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return waiting_requests_;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void Cancel();
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const ScopeSet& GetScopeSet() const;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& GetRefreshToken() const;
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const std::string& GetClientId() const;
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const std::string& GetAccountId() const;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The error result from this fetcher.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GoogleServiceAuthError& error() const { return error_; }
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   // OAuth2AccessTokenConsumer
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGetTokenSuccess(const std::string& access_token,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::Time& expiration_date) OVERRIDE;
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnGetTokenFailure(
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const GoogleServiceAuthError& error) OVERRIDE;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Fetcher(OAuth2TokenService* oauth2_token_service,
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          const std::string& account_id,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          net::URLRequestContextGetter* getter,
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          const std::string& client_id,
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          const std::string& client_secret,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const std::string& refresh_token,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const OAuth2TokenService::ScopeSet& scopes,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::WeakPtr<RequestImpl> waiting_request);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Start();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InformWaitingRequests();
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void InformWaitingRequestsAndDelete();
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static bool ShouldRetry(const GoogleServiceAuthError& error);
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 ComputeExponentialBackOffMilliseconds(int retry_num);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |oauth2_token_service_| remains valid for the life of this Fetcher, since
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // (whichever comes first).
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OAuth2TokenService* const oauth2_token_service_;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> getter_;
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const std::string account_id_;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string refresh_token_;
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const ScopeSet scopes_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int retry_number_;
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::OneShotTimer<Fetcher> retry_timer_;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<OAuth2AccessTokenFetcher> fetcher_;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Variables that store fetch results.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // destruction.
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GoogleServiceAuthError error_;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string access_token_;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time expiration_date_;
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // OAuth2 client id and secret.
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string client_id_;
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string client_secret_;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Fetcher);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart(
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OAuth2TokenService* oauth2_token_service,
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::URLRequestContextGetter* getter,
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_id,
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_secret,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& refresh_token,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<RequestImpl> waiting_request) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OAuth2TokenService::Fetcher* fetcher = new Fetcher(
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      oauth2_token_service,
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id,
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      getter,
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_id,
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_secret,
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      refresh_token,
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      scopes,
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      waiting_request);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fetcher->Start();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fetcher;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Fetcher::Fetcher(
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OAuth2TokenService* oauth2_token_service,
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::URLRequestContextGetter* getter,
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_id,
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_secret,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& refresh_token,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<RequestImpl> waiting_request)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : oauth2_token_service_(oauth2_token_service),
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      getter_(getter),
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id_(account_id),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      refresh_token_(refresh_token),
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scopes_(scopes),
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      retry_number_(0),
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_id_(client_id),
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_secret_(client_secret) {
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(oauth2_token_service_);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(getter_.get());
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(refresh_token_.length());
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  waiting_requests_.push_back(waiting_request);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Fetcher::~Fetcher() {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Inform the waiting requests if it has not done so.
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (waiting_requests_.size())
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InformWaitingRequests();
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::Fetcher::Start() {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get()));
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fetcher_->Start(client_id_,
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  client_secret_,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  refresh_token_,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  std::vector<std::string>(scopes_.begin(), scopes_.end()));
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  retry_timer_.Stop();
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& access_token,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& expiration_date) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fetcher_.reset();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fetch completes.
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = GoogleServiceAuthError::AuthErrorNone();
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  access_token_ = access_token;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expiration_date_ = expiration_date;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Subclasses may override this method to skip caching in some cases, but
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we still inform all waiting Consumers of a successful token fetch below.
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This is intentional -- some consumers may need the token for cleanup
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // tasks. https://chromiumcodereview.appspot.com/11312124/
27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  oauth2_token_service_->RegisterCacheEntry(client_id_,
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            account_id_,
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            scopes_,
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            access_token_,
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            expiration_date_);
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  InformWaitingRequestsAndDelete();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::Fetcher::OnGetTokenFailure(
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GoogleServiceAuthError& error) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fetcher_.reset();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::TimeDelta backoff = base::TimeDelta::FromMilliseconds(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ComputeExponentialBackOffMilliseconds(retry_number_));
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++retry_number_;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    retry_timer_.Stop();
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    retry_timer_.Start(FROM_HERE,
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       backoff,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       this,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       &OAuth2TokenService::Fetcher::Start);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_ = error;
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  InformWaitingRequestsAndDelete();
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Returns an exponential backoff in milliseconds including randomness less than
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 1000 ms when retrying fetching an OAuth2 access token.
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int retry_num) {
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(retry_num < max_fetch_retry_num_);
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int64 exponential_backoff_in_seconds = 1 << retry_num;
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Returns a backoff with randomness < 1000ms
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool OAuth2TokenService::Fetcher::ShouldRetry(
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GoogleServiceAuthError& error) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GoogleServiceAuthError::State error_state = error.state();
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::Fetcher::InformWaitingRequests() {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      waiting_requests_.begin();
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; iter != waiting_requests_.end(); ++iter) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<RequestImpl> waiting_request = *iter;
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (waiting_request.get())
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      waiting_request->InformConsumer(error_, access_token_, expiration_date_);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  waiting_requests_.clear();
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Deregisters itself from the service to prevent more waiting requests to
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // be added when it calls back the waiting requests.
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  oauth2_token_service_->OnFetchComplete(this);
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  InformWaitingRequests();
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::Fetcher::AddWaitingRequest(
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  waiting_requests_.push_back(waiting_request);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return waiting_requests_.size();
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OAuth2TokenService::Fetcher::Cancel() {
347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fetcher_.reset();
348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  retry_timer_.Stop();
349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  InformWaitingRequestsAndDelete();
351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return scopes_;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& OAuth2TokenService::Fetcher::GetRefreshToken() const {
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return refresh_token_;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return client_id_;
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return account_id_;
36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Request::Request() {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Request::~Request() {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)OAuth2TokenService::Consumer::Consumer(const std::string& id)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : id_(id) {}
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::Consumer::~Consumer() {
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochOAuth2TokenService::OAuth2TokenService() {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2TokenService::~OAuth2TokenService() {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Release all the pending fetchers.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_fetchers_.begin(), pending_fetchers_.end());
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenService::AddObserver(Observer* observer) {
3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  observer_list_.AddObserver(observer);
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenService::RemoveObserver(Observer* observer) {
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  observer_list_.RemoveObserver(observer);
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  diagnostics_observer_list_.AddObserver(observer);
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OAuth2TokenService::RemoveDiagnosticsObserver(
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DiagnosticsObserver* observer) {
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  diagnostics_observer_list_.RemoveObserver(observer);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool OAuth2TokenService::RefreshTokenIsAvailable(
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id) {
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(CalledOnValidThread());
41168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return !GetRefreshToken(account_id).empty();
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<std::string> OAuth2TokenService::GetAccounts() {
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return std::vector<std::string>();
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OAuth2TokenService::Consumer* consumer) {
422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return StartRequestForClientWithContext(
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id,
424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GetRequestContext(),
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      scopes,
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      consumer);
429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<OAuth2TokenService::Request>
432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)OAuth2TokenService::StartRequestForClient(
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_id,
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_secret,
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    OAuth2TokenService::Consumer* consumer) {
438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return StartRequestForClientWithContext(
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id,
440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GetRequestContext(),
441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      client_id,
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      client_secret,
443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      scopes,
444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      consumer);
44558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}
44658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
44758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochscoped_ptr<OAuth2TokenService::Request>
44858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben MurdochOAuth2TokenService::StartRequestWithContext(
44968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
45058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    net::URLRequestContextGetter* getter,
45158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    const ScopeSet& scopes,
45258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    Consumer* consumer) {
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return StartRequestForClientWithContext(
45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      account_id,
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      getter,
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      scopes,
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      consumer);
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<OAuth2TokenService::Request>
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)OAuth2TokenService::StartRequestForClientWithContext(
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    net::URLRequestContextGetter* getter,
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_id,
467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& client_secret,
468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const ScopeSet& scopes,
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Consumer* consumer) {
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<RequestImpl> request = CreateRequest(account_id, consumer);
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnAccessTokenRequested(account_id,
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           consumer->id(),
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           scopes));
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
47868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!RefreshTokenIsAvailable(account_id)) {
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      OnFetchAccessTokenComplete(
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          account_id, consumer->id(), scopes, error,
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          base::Time()));
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &RequestImpl::InformConsumer,
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request->AsWeakPtr(),
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        error,
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string(),
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Time()));
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return request.PassAs<Request>();
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RequestParameters request_parameters(client_id,
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       account_id,
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       scopes);
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (HasCacheEntry(request_parameters)) {
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    StartCacheLookupRequest(request.get(), request_parameters, consumer);
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    FetchOAuth2Token(request.get(),
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     account_id,
5033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     getter,
5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     client_id,
5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     client_secret,
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     scopes);
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return request.PassAs<Request>();
5093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)scoped_ptr<OAuth2TokenService::RequestImpl> OAuth2TokenService::CreateRequest(
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& account_id,
51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Consumer* consumer) {
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return scoped_ptr<RequestImpl>(new RequestImpl(account_id, consumer));
51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                          const std::string& account_id,
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                          net::URLRequestContextGetter* getter,
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                          const std::string& client_id,
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                          const std::string& client_secret,
5223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                          const ScopeSet& scopes) {
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string refresh_token = GetRefreshToken(account_id);
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If there is already a pending fetcher for |scopes| and |account_id|,
526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // simply register this |request| for those results rather than starting
527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // a new fetcher.
52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RequestParameters request_parameters = RequestParameters(client_id,
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                           account_id,
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                           scopes);
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RequestParameters, Fetcher*>::iterator iter =
53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pending_fetchers_.find(request_parameters);
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != pending_fetchers_.end()) {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iter->second->AddWaitingRequest(request->AsWeakPtr());
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
53868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pending_fetchers_[request_parameters] =
539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Fetcher::CreateAndStart(this,
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              account_id,
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              getter,
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              client_id,
543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              client_secret,
544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              refresh_token,
545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              scopes,
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              request->AsWeakPtr());
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void OAuth2TokenService::StartCacheLookupRequest(
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    RequestImpl* request,
55168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const OAuth2TokenService::RequestParameters& request_parameters,
5523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    OAuth2TokenService::Consumer* consumer) {
55368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CHECK(HasCacheEntry(request_parameters));
55468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    OnFetchAccessTokenComplete(
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        request_parameters.account_id,
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        consumer->id(),
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        request_parameters.scopes,
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        GoogleServiceAuthError::AuthErrorNone(),
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        cache_entry->expiration_date));
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &RequestImpl::InformConsumer,
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      request->AsWeakPtr(),
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GoogleServiceAuthError(GoogleServiceAuthError::NONE),
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cache_entry->access_token,
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cache_entry->expiration_date));
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
57068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::InvalidateToken(const std::string& account_id,
57168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                         const ScopeSet& scopes,
57268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                         const std::string& access_token) {
57368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InvalidateOAuth2Token(account_id,
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
57568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        scopes,
57668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        access_token);
57768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
57868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::InvalidateTokenForClient(
58068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
58168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& client_id,
58268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ScopeSet& scopes,
58368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& access_token) {
58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  InvalidateOAuth2Token(account_id, client_id, scopes, access_token);
58568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
58768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::InvalidateOAuth2Token(
58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& client_id,
59068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ScopeSet& scopes,
59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& access_token) {
592424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RemoveCacheEntry(
59468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RequestParameters(client_id,
59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        account_id,
59668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        scopes),
59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      access_token);
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
601424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update the auth error state so auth errors are appropriately communicated
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to the user.
60568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UpdateAuthError(fetcher->GetAccountId(), fetcher->error());
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // token and scope set. This is guaranteed as follows; here a Fetcher is said
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be uncompleted if it has not finished calling back
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OAuth2TokenService::OnFetchComplete().
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (1) All the live Fetchers are created by this service.
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     This is because (1) all the live Fetchers are created by a live
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     service, as all the fetchers created by a service are destructed in the
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //     service's dtor.
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (2) All the uncompleted Fetchers created by this service are recorded in
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |pending_fetchers_|.
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     This is because (1) all the created Fetchers are added to
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |pending_fetchers_| (in method StartRequest()) and (2) method
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     OnFetchComplete() is the only place where a Fetcher is erased from
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |pending_fetchers_|. Note no Fetcher is erased in method
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     StartRequest().
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     refresh token and ScopeSet. This is guaranteed by Fetcher creation in
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //     method StartRequest().
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When this method is called, |fetcher| is alive and uncompleted.
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // By (1), |fetcher| is created by this service.
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  RequestParameters request_param(fetcher->GetClientId(),
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  fetcher->GetAccountId(),
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  fetcher->GetScopeSet());
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const OAuth2TokenService::CacheEntry* entry = GetCacheEntry(request_param);
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::vector<base::WeakPtr<RequestImpl> >& requests =
6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      fetcher->waiting_requests();
6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < requests.size(); ++i) {
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const RequestImpl* req = requests[i].get();
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (req) {
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        OnFetchAccessTokenComplete(
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            req->GetAccountId(), req->GetConsumerId(),
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            fetcher->GetScopeSet(), fetcher->error(),
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            entry ? entry->expiration_date : base::Time()));
6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RequestParameters, Fetcher*>::iterator iter =
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_fetchers_.find(request_param);
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(iter != pending_fetchers_.end());
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(fetcher, iter->second);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_fetchers_.erase(iter);
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OAuth2TokenService::HasCacheEntry(
65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const RequestParameters& request_parameters) {
66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return cache_entry && cache_entry->access_token.length();
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const RequestParameters& request_parameters) {
666424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (token_iterator == token_cache_.end())
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (token_iterator->second.expiration_date <= base::Time::Now()) {
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    token_cache_.erase(token_iterator);
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &token_iterator->second;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool OAuth2TokenService::RemoveCacheEntry(
67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const RequestParameters& request_parameters,
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& token_to_remove) {
680424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
68168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (token_iterator != token_cache_.end() &&
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_iterator->second.access_token == token_to_remove) {
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      OnTokenRemoved(request_parameters.account_id,
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     request_parameters.scopes));
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    token_cache_.erase(token_iterator);
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2TokenService::RegisterCacheEntry(
69458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_id,
69568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OAuth2TokenService::ScopeSet& scopes,
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& access_token,
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& expiration_date) {
699424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CacheEntry& token = token_cache_[RequestParameters(client_id,
70268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                     account_id,
70368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                     scopes)];
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  token.access_token = access_token;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  token.expiration_date = expiration_date;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::UpdateAuthError(
70968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
71068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const GoogleServiceAuthError& error) {
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Default implementation does nothing.
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void OAuth2TokenService::ClearCache() {
715424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (TokenCache::iterator iter = token_cache_.begin();
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != token_cache_.end(); ++iter) {
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      OnTokenRemoved(iter->first.account_id,
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     iter->first.scopes));
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_cache_.clear();
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) {
72768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(CalledOnValidThread());
72868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (TokenCache::iterator iter = token_cache_.begin();
72968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       iter != token_cache_.end();
73068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       /* iter incremented in body */) {
73168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (iter->first.account_id == account_id) {
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        OnTokenRemoved(account_id, iter->first.scopes));
73468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      token_cache_.erase(iter++);
73568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
73668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++iter;
73768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
73868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
73968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
74068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
741a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OAuth2TokenService::CancelAllRequests() {
742a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Fetcher*> fetchers_to_cancel;
74368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<RequestParameters, Fetcher*>::iterator iter =
744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           pending_fetchers_.begin();
745a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       iter != pending_fetchers_.end();
746a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       ++iter) {
747a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    fetchers_to_cancel.push_back(iter->second);
748a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
749a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  CancelFetchers(fetchers_to_cancel);
750a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
751a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
75268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void OAuth2TokenService::CancelRequestsForAccount(
75368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id) {
754a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Fetcher*> fetchers_to_cancel;
75568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<RequestParameters, Fetcher*>::iterator iter =
756a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           pending_fetchers_.begin();
757a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       iter != pending_fetchers_.end();
758a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       ++iter) {
75968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (iter->first.account_id == account_id)
760a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      fetchers_to_cancel.push_back(iter->second);
761a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
762a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  CancelFetchers(fetchers_to_cancel);
763a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
764a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
765a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void OAuth2TokenService::CancelFetchers(
766a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::vector<Fetcher*> fetchers_to_cancel) {
767a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter =
768a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           fetchers_to_cancel.begin();
769a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       iter != fetchers_to_cancel.end();
770a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       ++iter) {
771a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    (*iter)->Cancel();
772a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
773a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
774a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenService::FireRefreshTokenAvailable(
7767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& account_id) {
7777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observer_list_,
7787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    OnRefreshTokenAvailable(account_id));
7797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenService::FireRefreshTokenRevoked(
7823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const std::string& account_id) {
7837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observer_list_,
7843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    OnRefreshTokenRevoked(account_id));
7857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenService::FireRefreshTokensLoaded() {
7887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
7897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
7907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int OAuth2TokenService::cache_size_for_testing() const {
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return token_cache_.size();
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int max_retries) {
797424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(CalledOnValidThread());
798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  max_fetch_retry_num_ = max_retries;
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
80058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
80158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
80258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& client_id,
80368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
80458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const ScopeSet& scopes) const {
80558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  PendingFetcherMap::const_iterator iter = pending_fetchers_.find(
80668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      OAuth2TokenService::RequestParameters(
80758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          client_id,
80868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          account_id,
80958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          scopes));
81058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return iter == pending_fetchers_.end() ?
81158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             0 : iter->second->GetWaitingRequestCount();
81258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
813