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
;
29 class OAuth2AccessTokenFetcher
;
31 // Abstract base class for a service that fetches and caches OAuth2 access
32 // tokens. Concrete subclasses should implement GetRefreshToken to return
33 // the appropriate refresh token. Derived services might maintain refresh tokens
34 // for multiple accounts.
36 // All calls are expected from the UI thread.
38 // To use this service, call StartRequest() with a given set of scopes and a
39 // consumer of the request results. The consumer is required to outlive the
40 // request. The request can be deleted. The consumer may be called back
41 // asynchronously with the fetch results.
43 // - If the consumer is not called back before the request is deleted, it will
44 // never be called back.
45 // Note in this case, the actual network requests are not canceled and the
46 // cache will be populated with the fetched results; it is just the consumer
47 // callback that is aborted.
49 // - Otherwise the consumer will be called back with the request and the fetch
52 // The caller of StartRequest() owns the returned request and is responsible to
53 // delete the request even once the callback has been invoked.
54 class OAuth2TokenService
: public base::NonThreadSafe
{
56 // A set of scopes in OAuth2 authentication.
57 typedef std::set
<std::string
> ScopeSet
;
59 // Class representing a request that fetches an OAuth2 access token.
63 virtual std::string
GetAccountId() const = 0;
68 // Class representing the consumer of a Request passed to |StartRequest|,
69 // which will be called back when the request completes.
72 Consumer(const std::string
& id
);
75 std::string
id() const { return id_
; }
77 // |request| is a Request that is started by this consumer and has
79 virtual void OnGetTokenSuccess(const Request
* request
,
80 const std::string
& access_token
,
81 const base::Time
& expiration_time
) = 0;
82 virtual void OnGetTokenFailure(const Request
* request
,
83 const GoogleServiceAuthError
& error
) = 0;
88 // Classes that want to listen for refresh token availability should
89 // implement this interface and register with the AddObserver() call.
92 // Called whenever a new login-scoped refresh token is available for
93 // account |account_id|. Once available, access tokens can be retrieved for
94 // this account. This is called during initial startup for each token
96 virtual void OnRefreshTokenAvailable(const std::string
& account_id
) {}
97 // Called whenever the login-scoped refresh token becomes unavailable for
98 // account |account_id|.
99 virtual void OnRefreshTokenRevoked(const std::string
& account_id
) {}
100 // Called after all refresh tokens are loaded during OAuth2TokenService
102 virtual void OnRefreshTokensLoaded() {}
103 // Sent before starting a batch of refresh token changes.
104 virtual void OnStartBatchChanges() {}
105 // Sent after a batch of refresh token changes is done.
106 virtual void OnEndBatchChanges() {}
109 virtual ~Observer() {}
112 // Classes that want to monitor status of access token and access token
113 // request should implement this interface and register with the
114 // AddDiagnosticsObserver() call.
115 class DiagnosticsObserver
{
117 // Called when receiving request for access token.
118 virtual void OnAccessTokenRequested(const std::string
& account_id
,
119 const std::string
& consumer_id
,
120 const ScopeSet
& scopes
) = 0;
121 // Called when access token fetching finished successfully or
122 // unsuccessfully. |expiration_time| are only valid with
123 // successful completion.
124 virtual void OnFetchAccessTokenComplete(const std::string
& account_id
,
125 const std::string
& consumer_id
,
126 const ScopeSet
& scopes
,
127 GoogleServiceAuthError error
,
128 base::Time expiration_time
) = 0;
129 virtual void OnTokenRemoved(const std::string
& account_id
,
130 const ScopeSet
& scopes
) = 0;
133 OAuth2TokenService();
134 virtual ~OAuth2TokenService();
136 // Add or remove observers of this token service.
137 void AddObserver(Observer
* observer
);
138 void RemoveObserver(Observer
* observer
);
140 // Add or remove observers of this token service.
141 void AddDiagnosticsObserver(DiagnosticsObserver
* observer
);
142 void RemoveDiagnosticsObserver(DiagnosticsObserver
* observer
);
144 // Checks in the cache for a valid access token for a specified |account_id|
145 // and |scopes|, and if not found starts a request for an OAuth2 access token
146 // using the OAuth2 refresh token maintained by this instance for that
147 // |account_id|. The caller owns the returned Request.
148 // |scopes| is the set of scopes to get an access token for, |consumer| is
149 // the object that will be called back with results if the returned request
151 scoped_ptr
<Request
> StartRequest(const std::string
& account_id
,
152 const ScopeSet
& scopes
,
155 // This method does the same as |StartRequest| except it uses |client_id| and
156 // |client_secret| to identify OAuth client app instead of using
157 // Chrome's default values.
158 scoped_ptr
<Request
> StartRequestForClient(
159 const std::string
& account_id
,
160 const std::string
& client_id
,
161 const std::string
& client_secret
,
162 const ScopeSet
& scopes
,
165 // This method does the same as |StartRequest| except it uses the request
166 // context given by |getter| instead of using the one returned by
167 // |GetRequestContext| implemented by derived classes.
168 scoped_ptr
<Request
> StartRequestWithContext(
169 const std::string
& account_id
,
170 net::URLRequestContextGetter
* getter
,
171 const ScopeSet
& scopes
,
174 // Lists account IDs of all accounts with a refresh token maintained by this
176 virtual std::vector
<std::string
> GetAccounts();
178 // Returns true if a refresh token exists for |account_id|. If false, calls to
179 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
180 virtual bool RefreshTokenIsAvailable(const std::string
& account_id
) const = 0;
182 // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
183 // invalid. This should be done if the token was received from this class,
184 // but was not accepted by the server (e.g., the server returned
185 // 401 Unauthorized). The token will be removed from the cache for the given
187 void InvalidateToken(const std::string
& account_id
,
188 const ScopeSet
& scopes
,
189 const std::string
& access_token
);
191 // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client
192 // app that issued the request instead of Chrome's default values.
193 void InvalidateTokenForClient(const std::string
& account_id
,
194 const std::string
& client_id
,
195 const ScopeSet
& scopes
,
196 const std::string
& access_token
);
199 // Return the current number of entries in the cache.
200 int cache_size_for_testing() const;
201 void set_max_authorization_token_fetch_retries_for_testing(int max_retries
);
202 // Returns the current number of pending fetchers matching given params.
203 size_t GetNumPendingRequestsForTesting(
204 const std::string
& client_id
,
205 const std::string
& account_id
,
206 const ScopeSet
& scopes
) const;
209 // Implements a cancelable |OAuth2TokenService::Request|, which should be
210 // operated on the UI thread.
211 // TODO(davidroche): move this out of header file.
212 class RequestImpl
: public base::SupportsWeakPtr
<RequestImpl
>,
213 public base::NonThreadSafe
,
216 // |consumer| is required to outlive this.
217 explicit RequestImpl(const std::string
& account_id
, Consumer
* consumer
);
218 virtual ~RequestImpl();
220 // Overridden from Request:
221 virtual std::string
GetAccountId() const OVERRIDE
;
223 std::string
GetConsumerId() const;
225 // Informs |consumer_| that this request is completed.
226 void InformConsumer(const GoogleServiceAuthError
& error
,
227 const std::string
& access_token
,
228 const base::Time
& expiration_date
);
231 // |consumer_| to call back when this request completes.
232 const std::string account_id_
;
233 Consumer
* const consumer_
;
236 // Helper class to scope batch changes.
237 class ScopedBacthChange
{
239 ScopedBacthChange(OAuth2TokenService
* token_service
);
240 ~ScopedBacthChange();
242 OAuth2TokenService
* token_service_
; // Weak.
243 DISALLOW_COPY_AND_ASSIGN(ScopedBacthChange
);
246 // Subclasses can override if they want to report errors to the user.
247 virtual void UpdateAuthError(
248 const std::string
& account_id
,
249 const GoogleServiceAuthError
& error
);
251 // Add a new entry to the cache.
252 // Subclasses can override if there are implementation-specific reasons
253 // that an access token should ever not be cached.
254 virtual void RegisterCacheEntry(const std::string
& client_id
,
255 const std::string
& account_id
,
256 const ScopeSet
& scopes
,
257 const std::string
& access_token
,
258 const base::Time
& expiration_date
);
260 // Clears the internal token cache.
263 // Clears all of the tokens belonging to |account_id| from the internal token
264 // cache. It does not matter what other parameters, like |client_id| were
265 // used to request the tokens.
266 void ClearCacheForAccount(const std::string
& account_id
);
268 // Cancels all requests that are currently in progress.
269 void CancelAllRequests();
271 // Cancels all requests related to a given |account_id|.
272 void CancelRequestsForAccount(const std::string
& account_id
);
274 // Called by subclasses to notify observers.
275 virtual void FireRefreshTokenAvailable(const std::string
& account_id
);
276 virtual void FireRefreshTokenRevoked(const std::string
& account_id
);
277 virtual void FireRefreshTokensLoaded();
279 virtual void StartBatchChanges();
280 virtual void EndBatchChanges();
282 // Fetches an OAuth token for the specified client/scopes. Virtual so it can
283 // be overridden for tests and for platform-specific behavior on Android.
284 virtual void FetchOAuth2Token(RequestImpl
* request
,
285 const std::string
& account_id
,
286 net::URLRequestContextGetter
* getter
,
287 const std::string
& client_id
,
288 const std::string
& client_secret
,
289 const ScopeSet
& scopes
);
291 // Creates an access token fetcher for the given account id.
293 // Subclasses should override to create an access token fetcher for the given
294 // |account_id|. This method is only called if subclasses use the default
295 // implementation of |FetchOAuth2Token|.
296 virtual OAuth2AccessTokenFetcher
* CreateAccessTokenFetcher(
297 const std::string
& account_id
,
298 net::URLRequestContextGetter
* getter
,
299 OAuth2AccessTokenConsumer
* consumer
) = 0;
301 // Invalidates the |access_token| issued for |account_id|, |client_id| and
302 // |scopes|. Virtual so it can be overriden for tests and for platform-
304 virtual void InvalidateOAuth2Token(const std::string
& account_id
,
305 const std::string
& client_id
,
306 const ScopeSet
& scopes
,
307 const std::string
& access_token
);
311 friend class Fetcher
;
313 // The parameters used to fetch an OAuth2 access token.
314 struct RequestParameters
{
315 RequestParameters(const std::string
& client_id
,
316 const std::string
& account_id
,
317 const ScopeSet
& scopes
);
318 ~RequestParameters();
319 bool operator<(const RequestParameters
& params
) const;
322 std::string client_id
;
323 // Account id for which the request is made.
324 std::string account_id
;
325 // URL scopes for the requested access token.
329 typedef std::map
<RequestParameters
, Fetcher
*> PendingFetcherMap
;
331 // Derived classes must provide a request context used for fetching access
332 // tokens with the |StartRequest| method.
333 virtual net::URLRequestContextGetter
* GetRequestContext() = 0;
335 // Struct that contains the information of an OAuth2 access token.
337 std::string access_token
;
338 base::Time expiration_date
;
341 // This method does the same as |StartRequestWithContext| except it
342 // uses |client_id| and |client_secret| to identify OAuth
343 // client app instead of using Chrome's default values.
344 scoped_ptr
<Request
> StartRequestForClientWithContext(
345 const std::string
& account_id
,
346 net::URLRequestContextGetter
* getter
,
347 const std::string
& client_id
,
348 const std::string
& client_secret
,
349 const ScopeSet
& scopes
,
352 // Returns true if GetCacheEntry would return a valid cache entry for the
354 bool HasCacheEntry(const RequestParameters
& client_scopes
);
356 // Posts a task to fire the Consumer callback with the cached token. Must
357 // Must only be called if HasCacheEntry() returns true.
358 void StartCacheLookupRequest(RequestImpl
* request
,
359 const RequestParameters
& client_scopes
,
362 // Returns a currently valid OAuth2 access token for the given set of scopes,
363 // or NULL if none have been cached. Note the user of this method should
364 // ensure no entry with the same |client_scopes| is added before the usage of
365 // the returned entry is done.
366 const CacheEntry
* GetCacheEntry(const RequestParameters
& client_scopes
);
368 // Removes an access token for the given set of scopes from the cache.
369 // Returns true if the entry was removed, otherwise false.
370 bool RemoveCacheEntry(const RequestParameters
& client_scopes
,
371 const std::string
& token_to_remove
);
373 // Called when |fetcher| finishes fetching.
374 void OnFetchComplete(Fetcher
* fetcher
);
376 // Called when a number of fetchers need to be canceled.
377 void CancelFetchers(std::vector
<Fetcher
*> fetchers_to_cancel
);
379 // The cache of currently valid tokens.
380 typedef std::map
<RequestParameters
, CacheEntry
> TokenCache
;
381 TokenCache token_cache_
;
383 // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
384 // token using these parameters.
385 PendingFetcherMap pending_fetchers_
;
387 // List of observers to notify when refresh token availability changes.
388 // Makes sure list is empty on destruction.
389 ObserverList
<Observer
, true> observer_list_
;
391 // List of observers to notify when access token status changes.
392 ObserverList
<DiagnosticsObserver
, true> diagnostics_observer_list_
;
394 // The depth of batch changes.
395 int batch_change_depth_
;
397 // Maximum number of retries in fetching an OAuth2 access token.
398 static int max_fetch_retry_num_
;
400 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest
, RequestParametersOrderTest
);
401 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest
,
402 SameScopesRequestedForDifferentClients
);
404 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService
);
407 #endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_