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)#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/gtest_prod_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/observer_list.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/timer/timer.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "google_apis/gaia/google_service_auth_error.h"
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_consumer.h"
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_fetcher.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class URLRequestContextGetter;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GoogleServiceAuthError;
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OAuth2AccessTokenFetcher;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Abstract base class for a service that fetches and caches OAuth2 access
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// tokens. Concrete subclasses should implement GetRefreshToken to return
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// the appropriate refresh token. Derived services might maintain refresh tokens
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// for multiple accounts.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// All calls are expected from the UI thread.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To use this service, call StartRequest() with a given set of scopes and a
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// consumer of the request results. The consumer is required to outlive the
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request. The request can be deleted. The consumer may be called back
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// asynchronously with the fetch results.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - If the consumer is not called back before the request is deleted, it will
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   never be called back.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   Note in this case, the actual network requests are not canceled and the
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   cache will be populated with the fetched results; it is just the consumer
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   callback that is aborted.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - Otherwise the consumer will be called back with the request and the fetch
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   results.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The caller of StartRequest() owns the returned request and is responsible to
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// delete the request even once the callback has been invoked.
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class OAuth2TokenService : public base::NonThreadSafe {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // A set of scopes in OAuth2 authentication.
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  typedef std::set<std::string> ScopeSet;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Class representing a request that fetches an OAuth2 access token.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class Request {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~Request();
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    virtual std::string GetAccountId() const = 0;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   protected:
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Request();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Class representing the consumer of a Request passed to |StartRequest|,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // which will be called back when the request completes.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class Consumer {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Consumer(const std::string& id);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~Consumer();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string id() const { return id_; }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |request| is a Request that is started by this consumer and has
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // completed.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnGetTokenSuccess(const Request* request,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& access_token,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const base::Time& expiration_time) = 0;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnGetTokenFailure(const Request* request,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const GoogleServiceAuthError& error) = 0;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   private:
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string id_;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Classes that want to listen for refresh token availability should
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implement this interface and register with the AddObserver() call.
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  class Observer {
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   public:
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Called whenever a new login-scoped refresh token is available for
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // account |account_id|. Once available, access tokens can be retrieved for
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // this account.  This is called during initial startup for each token
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // loaded.
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual void OnRefreshTokenAvailable(const std::string& account_id) {}
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Called whenever the login-scoped refresh token becomes unavailable for
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // account |account_id|.
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    virtual void OnRefreshTokenRevoked(const std::string& account_id) {}
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Called after all refresh tokens are loaded during OAuth2TokenService
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // startup.
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual void OnRefreshTokensLoaded() {}
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Sent before starting a batch of refresh token changes.
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    virtual void OnStartBatchChanges() {}
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Sent after a batch of refresh token changes is done.
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    virtual void OnEndBatchChanges() {}
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   protected:
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual ~Observer() {}
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  };
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Classes that want to monitor status of access token and access token
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // request should implement this interface and register with the
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // AddDiagnosticsObserver() call.
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class DiagnosticsObserver {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Called when receiving request for access token.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void OnAccessTokenRequested(const std::string& account_id,
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const std::string& consumer_id,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const ScopeSet& scopes) = 0;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Called when access token fetching finished successfully or
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // unsuccessfully. |expiration_time| are only valid with
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // successful completion.
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void OnFetchAccessTokenComplete(const std::string& account_id,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            const std::string& consumer_id,
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            const ScopeSet& scopes,
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            GoogleServiceAuthError error,
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            base::Time expiration_time) = 0;
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void OnTokenRemoved(const std::string& account_id,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const ScopeSet& scopes) = 0;
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  OAuth2TokenService();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~OAuth2TokenService();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Add or remove observers of this token service.
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void AddObserver(Observer* observer);
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void RemoveObserver(Observer* observer);
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add or remove observers of this token service.
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddDiagnosticsObserver(DiagnosticsObserver* observer);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RemoveDiagnosticsObserver(DiagnosticsObserver* observer);
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Checks in the cache for a valid access token for a specified |account_id|
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // and |scopes|, and if not found starts a request for an OAuth2 access token
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // using the OAuth2 refresh token maintained by this instance for that
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |account_id|. The caller owns the returned Request.
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |scopes| is the set of scopes to get an access token for, |consumer| is
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the object that will be called back with results if the returned request
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // is not deleted.
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<Request> StartRequest(const std::string& account_id,
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                   const ScopeSet& scopes,
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                   Consumer* consumer);
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // This method does the same as |StartRequest| except it uses |client_id| and
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // |client_secret| to identify OAuth client app instead of using
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Chrome's default values.
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<Request> StartRequestForClient(
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const std::string& account_id,
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const std::string& client_id,
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const std::string& client_secret,
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const ScopeSet& scopes,
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Consumer* consumer);
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // This method does the same as |StartRequest| except it uses the request
16658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // context given by |getter| instead of using the one returned by
16758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // |GetRequestContext| implemented by derived classes.
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<Request> StartRequestWithContext(
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const std::string& account_id,
17058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      net::URLRequestContextGetter* getter,
17158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      const ScopeSet& scopes,
17258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      Consumer* consumer);
17358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Lists account IDs of all accounts with a refresh token maintained by this
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // instance.
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual std::vector<std::string> GetAccounts();
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns true if a refresh token exists for |account_id|. If false, calls to
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool RefreshTokenIsAvailable(const std::string& account_id) const = 0;
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // invalid. This should be done if the token was received from this class,
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // but was not accepted by the server (e.g., the server returned
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // 401 Unauthorized). The token will be removed from the cache for the given
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // scopes.
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void InvalidateToken(const std::string& account_id,
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       const ScopeSet& scopes,
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                       const std::string& access_token);
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // app that issued the request instead of Chrome's default values.
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void InvalidateTokenForClient(const std::string& account_id,
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                const std::string& client_id,
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                const ScopeSet& scopes,
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                const std::string& access_token);
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Return the current number of entries in the cache.
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int cache_size_for_testing() const;
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns the current number of pending fetchers matching given params.
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t GetNumPendingRequestsForTesting(
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const std::string& client_id,
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const std::string& account_id,
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const ScopeSet& scopes) const;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Implements a cancelable |OAuth2TokenService::Request|, which should be
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // operated on the UI thread.
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(davidroche): move this out of header file.
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                      public base::NonThreadSafe,
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      public Request {
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch   public:
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // |consumer| is required to outlive this.
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    explicit RequestImpl(const std::string& account_id, Consumer* consumer);
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    virtual ~RequestImpl();
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Overridden from Request:
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    virtual std::string GetAccountId() const OVERRIDE;
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string GetConsumerId() const;
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Informs |consumer_| that this request is completed.
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    void InformConsumer(const GoogleServiceAuthError& error,
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        const std::string& access_token,
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        const base::Time& expiration_date);
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch   private:
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // |consumer_| to call back when this request completes.
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string account_id_;
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Consumer* const consumer_;
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Helper class to scope batch changes.
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  class ScopedBacthChange {
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   public:
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ScopedBacthChange(OAuth2TokenService* token_service);
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ~ScopedBacthChange();
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   private:
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    OAuth2TokenService* token_service_;  // Weak.
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DISALLOW_COPY_AND_ASSIGN(ScopedBacthChange);
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Subclasses can override if they want to report errors to the user.
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void UpdateAuthError(
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const std::string& account_id,
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const GoogleServiceAuthError& error);
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add a new entry to the cache.
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Subclasses can override if there are implementation-specific reasons
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // that an access token should ever not be cached.
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void RegisterCacheEntry(const std::string& client_id,
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                  const std::string& account_id,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const ScopeSet& scopes,
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const std::string& access_token,
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const base::Time& expiration_date);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Clears the internal token cache.
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ClearCache();
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Clears all of the tokens belonging to |account_id| from the internal token
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // cache. It does not matter what other parameters, like |client_id| were
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // used to request the tokens.
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void ClearCacheForAccount(const std::string& account_id);
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Cancels all requests that are currently in progress.
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void CancelAllRequests();
270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Cancels all requests related to a given |account_id|.
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void CancelRequestsForAccount(const std::string& account_id);
273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Called by subclasses to notify observers.
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void FireRefreshTokenAvailable(const std::string& account_id);
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void FireRefreshTokenRevoked(const std::string& account_id);
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void FireRefreshTokensLoaded();
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void StartBatchChanges();
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void EndBatchChanges();
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Fetches an OAuth token for the specified client/scopes. Virtual so it can
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // be overridden for tests and for platform-specific behavior on Android.
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual void FetchOAuth2Token(RequestImpl* request,
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                const std::string& account_id,
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                net::URLRequestContextGetter* getter,
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                const std::string& client_id,
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                const std::string& client_secret,
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                const ScopeSet& scopes);
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Creates an access token fetcher for the given account id.
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Subclasses should override to create an access token fetcher for the given
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |account_id|. This method is only called if subclasses use the default
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // implementation of |FetchOAuth2Token|.
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& account_id,
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::URLRequestContextGetter* getter,
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OAuth2AccessTokenConsumer* consumer) = 0;
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Invalidates the |access_token| issued for |account_id|, |client_id| and
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |scopes|. Virtual so it can be overriden for tests and for platform-
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // specifc behavior.
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void InvalidateOAuth2Token(const std::string& account_id,
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     const std::string& client_id,
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     const ScopeSet& scopes,
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     const std::string& access_token);
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class Fetcher;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class Fetcher;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The parameters used to fetch an OAuth2 access token.
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  struct RequestParameters {
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RequestParameters(const std::string& client_id,
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                      const std::string& account_id,
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                      const ScopeSet& scopes);
31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ~RequestParameters();
31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool operator<(const RequestParameters& params) const;
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // OAuth2 client id.
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string client_id;
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Account id for which the request is made.
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    std::string account_id;
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // URL scopes for the requested access token.
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ScopeSet scopes;
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  };
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  typedef std::map<RequestParameters, Fetcher*> PendingFetcherMap;
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Derived classes must provide a request context used for fetching access
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // tokens with the |StartRequest| method.
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual net::URLRequestContextGetter* GetRequestContext() = 0;
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Struct that contains the information of an OAuth2 access token.
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct CacheEntry {
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string access_token;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time expiration_date;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // This method does the same as |StartRequestWithContext| except it
342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // uses |client_id| and |client_secret| to identify OAuth
343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // client app instead of using Chrome's default values.
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<Request> StartRequestForClientWithContext(
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const std::string& account_id,
346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      net::URLRequestContextGetter* getter,
347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const std::string& client_id,
348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const std::string& client_secret,
349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const ScopeSet& scopes,
350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Consumer* consumer);
351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns true if GetCacheEntry would return a valid cache entry for the
35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // given scopes.
35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool HasCacheEntry(const RequestParameters& client_scopes);
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Posts a task to fire the Consumer callback with the cached token.  Must
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Must only be called if HasCacheEntry() returns true.
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void StartCacheLookupRequest(RequestImpl* request,
35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                               const RequestParameters& client_scopes,
36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                               Consumer* consumer);
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns a currently valid OAuth2 access token for the given set of scopes,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // or NULL if none have been cached. Note the user of this method should
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // ensure no entry with the same |client_scopes| is added before the usage of
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the returned entry is done.
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const CacheEntry* GetCacheEntry(const RequestParameters& client_scopes);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Removes an access token for the given set of scopes from the cache.
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns true if the entry was removed, otherwise false.
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool RemoveCacheEntry(const RequestParameters& client_scopes,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        const std::string& token_to_remove);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called when |fetcher| finishes fetching.
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnFetchComplete(Fetcher* fetcher);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Called when a number of fetchers need to be canceled.
377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel);
378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The cache of currently valid tokens.
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  typedef std::map<RequestParameters, CacheEntry> TokenCache;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TokenCache token_cache_;
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // token using these parameters.
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  PendingFetcherMap pending_fetchers_;
3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // List of observers to notify when refresh token availability changes.
3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Makes sure list is empty on destruction.
3897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ObserverList<Observer, true> observer_list_;
3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // List of observers to notify when access token status changes.
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ObserverList<DiagnosticsObserver, true> diagnostics_observer_list_;
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The depth of batch changes.
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int batch_change_depth_;
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Maximum number of retries in fetching an OAuth2 access token.
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static int max_fetch_retry_num_;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest);
40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest,
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           SameScopesRequestedForDifferentClients);
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif  // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
408