1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
6 #define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
12 #include "base/basictypes.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/threading/non_thread_safe.h"
18 #include "base/time/time.h"
19 #include "base/timer/timer.h"
20 #include "google_apis/gaia/google_service_auth_error.h"
21 #include "google_apis/gaia/oauth2_access_token_consumer.h"
22 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
25 class URLRequestContextGetter;
28 class GoogleServiceAuthError;
30 // Abstract base class for a service that fetches and caches OAuth2 access
31 // tokens. Concrete subclasses should implement GetRefreshToken to return
32 // the appropriate refresh token. Derived services might maintain refresh tokens
33 // for multiple accounts.
35 // All calls are expected from the UI thread.
37 // To use this service, call StartRequest() with a given set of scopes and a
38 // consumer of the request results. The consumer is required to outlive the
39 // request. The request can be deleted. The consumer may be called back
40 // asynchronously with the fetch results.
42 // - If the consumer is not called back before the request is deleted, it will
43 // never be called back.
44 // Note in this case, the actual network requests are not canceled and the
45 // cache will be populated with the fetched results; it is just the consumer
46 // callback that is aborted.
48 // - Otherwise the consumer will be called back with the request and the fetch
51 // The caller of StartRequest() owns the returned request and is responsible to
52 // delete the request even once the callback has been invoked.
53 class OAuth2TokenService : public base::NonThreadSafe {
55 // Class representing a request that fetches an OAuth2 access token.
63 // Class representing the consumer of a Request passed to |StartRequest|,
64 // which will be called back when the request completes.
69 // |request| is a Request that is started by this consumer and has
71 virtual void OnGetTokenSuccess(const Request* request,
72 const std::string& access_token,
73 const base::Time& expiration_time) = 0;
74 virtual void OnGetTokenFailure(const Request* request,
75 const GoogleServiceAuthError& error) = 0;
78 // Classes that want to listen for token availability should implement this
79 // interface and register with the AddObserver() call.
82 // Called whenever a new login-scoped refresh token is available for
83 // account |account_id|. Once available, access tokens can be retrieved for
84 // this account. This is called during initial startup for each token
86 virtual void OnRefreshTokenAvailable(const std::string& account_id) {}
87 // Called whenever the login-scoped refresh token becomes unavailable for
88 // account |account_id|.
89 virtual void OnRefreshTokenRevoked(const std::string& account_id) {}
90 // Called after all refresh tokens are loaded during OAuth2TokenService
92 virtual void OnRefreshTokensLoaded() {}
94 virtual ~Observer() {}
97 // A set of scopes in OAuth2 authentication.
98 typedef std::set<std::string> ScopeSet;
100 OAuth2TokenService();
101 virtual ~OAuth2TokenService();
103 // Add or remove observers of this token service.
104 void AddObserver(Observer* observer);
105 void RemoveObserver(Observer* observer);
107 // Checks in the cache for a valid access token for a specified |account_id|
108 // and |scopes|, and if not found starts a request for an OAuth2 access token
109 // using the OAuth2 refresh token maintained by this instance for that
110 // |account_id|. The caller owns the returned Request.
111 // |scopes| is the set of scopes to get an access token for, |consumer| is
112 // the object that will be called back with results if the returned request
114 scoped_ptr<Request> StartRequest(const std::string& account_id,
115 const ScopeSet& scopes,
118 // This method does the same as |StartRequest| except it uses |client_id| and
119 // |client_secret| to identify OAuth client app instead of using
120 // Chrome's default values.
121 scoped_ptr<Request> StartRequestForClient(
122 const std::string& account_id,
123 const std::string& client_id,
124 const std::string& client_secret,
125 const ScopeSet& scopes,
128 // This method does the same as |StartRequest| except it uses the request
129 // context given by |getter| instead of using the one returned by
130 // |GetRequestContext| implemented by derived classes.
131 scoped_ptr<Request> StartRequestWithContext(
132 const std::string& account_id,
133 net::URLRequestContextGetter* getter,
134 const ScopeSet& scopes,
137 // Lists account IDs of all accounts with a refresh token maintained by this
139 virtual std::vector<std::string> GetAccounts();
141 // Returns true if a refresh token exists for |account_id|. If false, calls to
142 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
143 virtual bool RefreshTokenIsAvailable(const std::string& account_id);
145 // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
146 // invalid. This should be done if the token was received from this class,
147 // but was not accepted by the server (e.g., the server returned
148 // 401 Unauthorized). The token will be removed from the cache for the given
150 void InvalidateToken(const std::string& account_id,
151 const ScopeSet& scopes,
152 const std::string& access_token);
154 // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client
155 // app that issued the request instead of Chrome's default values.
156 void InvalidateTokenForClient(const std::string& account_id,
157 const std::string& client_id,
158 const ScopeSet& scopes,
159 const std::string& access_token);
162 // Return the current number of entries in the cache.
163 int cache_size_for_testing() const;
164 void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
165 // Returns the current number of pending fetchers matching given params.
166 size_t GetNumPendingRequestsForTesting(
167 const std::string& client_id,
168 const std::string& account_id,
169 const ScopeSet& scopes) const;
172 // Implements a cancelable |OAuth2TokenService::Request|, which should be
173 // operated on the UI thread.
174 // TODO(davidroche): move this out of header file.
175 class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
176 public base::NonThreadSafe,
179 // |consumer| is required to outlive this.
180 explicit RequestImpl(Consumer* consumer);
181 virtual ~RequestImpl();
183 // Informs |consumer_| that this request is completed.
184 void InformConsumer(const GoogleServiceAuthError& error,
185 const std::string& access_token,
186 const base::Time& expiration_date);
189 // |consumer_| to call back when this request completes.
190 Consumer* const consumer_;
193 // Subclasses should return the maintained refresh token for |account_id|.
194 // If no token is available, return an empty string.
195 virtual std::string GetRefreshToken(const std::string& account_id) = 0;
197 // Subclasses can override if they want to report errors to the user.
198 virtual void UpdateAuthError(
199 const std::string& account_id,
200 const GoogleServiceAuthError& error);
202 // Add a new entry to the cache.
203 // Subclasses can override if there are implementation-specific reasons
204 // that an access token should ever not be cached.
205 virtual void RegisterCacheEntry(const std::string& client_id,
206 const std::string& account_id,
207 const ScopeSet& scopes,
208 const std::string& access_token,
209 const base::Time& expiration_date);
211 // Clears the internal token cache.
214 // Clears all of the tokens belonging to |account_id| from the internal token
215 // cache. It does not matter what other parameters, like |client_id| were
216 // used to request the tokens.
217 void ClearCacheForAccount(const std::string& account_id);
219 // Cancels all requests that are currently in progress.
220 void CancelAllRequests();
222 // Cancels all requests related to a given |account_id|.
223 void CancelRequestsForAccount(const std::string& account_id);
225 // Called by subclasses to notify observers.
226 virtual void FireRefreshTokenAvailable(const std::string& account_id);
227 virtual void FireRefreshTokenRevoked(const std::string& account_id);
228 virtual void FireRefreshTokensLoaded();
230 // Creates a request implementation. Can be overriden by derived classes to
231 // provide additional control of token consumption. |consumer| will outlive
232 // the created request.
233 virtual scoped_ptr<RequestImpl> CreateRequest(Consumer* consumer);
235 // Fetches an OAuth token for the specified client/scopes. Virtual so it can
236 // be overridden for tests and for platform-specific behavior on Android.
237 virtual void FetchOAuth2Token(RequestImpl* request,
238 const std::string& account_id,
239 net::URLRequestContextGetter* getter,
240 const std::string& client_id,
241 const std::string& client_secret,
242 const ScopeSet& scopes);
244 // Invalidates the |access_token| issued for |account_id|, |client_id| and
245 // |scopes|. Virtual so it can be overriden for tests and for platform-
247 virtual void InvalidateOAuth2Token(const std::string& account_id,
248 const std::string& client_id,
249 const ScopeSet& scopes,
250 const std::string& access_token);
254 friend class Fetcher;
256 // The parameters used to fetch an OAuth2 access token.
257 struct RequestParameters {
258 RequestParameters(const std::string& client_id,
259 const std::string& account_id,
260 const ScopeSet& scopes);
261 ~RequestParameters();
262 bool operator<(const RequestParameters& params) const;
265 std::string client_id;
266 // Account id for which the request is made.
267 std::string account_id;
268 // URL scopes for the requested access token.
272 typedef std::map<RequestParameters, Fetcher*> PendingFetcherMap;
274 // Derived classes must provide a request context used for fetching access
275 // tokens with the |StartRequest| method.
276 virtual net::URLRequestContextGetter* GetRequestContext() = 0;
278 // Struct that contains the information of an OAuth2 access token.
280 std::string access_token;
281 base::Time expiration_date;
284 // This method does the same as |StartRequestWithContext| except it
285 // uses |client_id| and |client_secret| to identify OAuth
286 // client app instead of using Chrome's default values.
287 scoped_ptr<Request> StartRequestForClientWithContext(
288 const std::string& account_id,
289 net::URLRequestContextGetter* getter,
290 const std::string& client_id,
291 const std::string& client_secret,
292 const ScopeSet& scopes,
295 // Returns true if GetCacheEntry would return a valid cache entry for the
297 bool HasCacheEntry(const RequestParameters& client_scopes);
299 // Posts a task to fire the Consumer callback with the cached token. Must
300 // Must only be called if HasCacheEntry() returns true.
301 void StartCacheLookupRequest(RequestImpl* request,
302 const RequestParameters& client_scopes,
305 // Returns a currently valid OAuth2 access token for the given set of scopes,
306 // or NULL if none have been cached. Note the user of this method should
307 // ensure no entry with the same |client_scopes| is added before the usage of
308 // the returned entry is done.
309 const CacheEntry* GetCacheEntry(const RequestParameters& client_scopes);
311 // Removes an access token for the given set of scopes from the cache.
312 // Returns true if the entry was removed, otherwise false.
313 bool RemoveCacheEntry(const RequestParameters& client_scopes,
314 const std::string& token_to_remove);
316 // Called when |fetcher| finishes fetching.
317 void OnFetchComplete(Fetcher* fetcher);
319 // Called when a number of fetchers need to be canceled.
320 void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel);
322 // The cache of currently valid tokens.
323 typedef std::map<RequestParameters, CacheEntry> TokenCache;
324 TokenCache token_cache_;
326 // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
327 // token using these parameters.
328 PendingFetcherMap pending_fetchers_;
330 // List of observers to notify when token availability changes.
331 // Makes sure list is empty on destruction.
332 ObserverList<Observer, true> observer_list_;
334 // Maximum number of retries in fetching an OAuth2 access token.
335 static int max_fetch_retry_num_;
337 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest);
338 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest,
339 SameScopesRequestedForDifferentClients);
341 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
344 #endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_