Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / google_apis / gaia / oauth2_token_service.h
blob2306c1031024716f71ca562be70174e57c944fdc
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_
8 #include <map>
9 #include <set>
10 #include <string>
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 "google_apis/gaia/google_service_auth_error.h"
20 #include "google_apis/gaia/oauth2_access_token_consumer.h"
21 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
23 namespace net {
24 class URLRequestContextGetter;
27 class GoogleServiceAuthError;
28 class OAuth2AccessTokenFetcher;
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
49 // results.
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 {
54 public:
55 // A set of scopes in OAuth2 authentication.
56 typedef std::set<std::string> ScopeSet;
58 // Class representing a request that fetches an OAuth2 access token.
59 class Request {
60 public:
61 virtual ~Request();
62 virtual std::string GetAccountId() const = 0;
63 protected:
64 Request();
67 // Class representing the consumer of a Request passed to |StartRequest|,
68 // which will be called back when the request completes.
69 class Consumer {
70 public:
71 explicit Consumer(const std::string& id);
72 virtual ~Consumer();
74 std::string id() const { return id_; }
76 // |request| is a Request that is started by this consumer and has
77 // completed.
78 virtual void OnGetTokenSuccess(const Request* request,
79 const std::string& access_token,
80 const base::Time& expiration_time) = 0;
81 virtual void OnGetTokenFailure(const Request* request,
82 const GoogleServiceAuthError& error) = 0;
83 private:
84 std::string id_;
87 // Classes that want to listen for refresh token availability should
88 // implement this interface and register with the AddObserver() call.
89 class Observer {
90 public:
91 // Called whenever a new login-scoped refresh token is available for
92 // account |account_id|. Once available, access tokens can be retrieved for
93 // this account. This is called during initial startup for each token
94 // loaded.
95 virtual void OnRefreshTokenAvailable(const std::string& account_id) {}
96 // Called whenever the login-scoped refresh token becomes unavailable for
97 // account |account_id|.
98 virtual void OnRefreshTokenRevoked(const std::string& account_id) {}
99 // Called after all refresh tokens are loaded during OAuth2TokenService
100 // startup.
101 virtual void OnRefreshTokensLoaded() {}
102 // Sent before starting a batch of refresh token changes.
103 virtual void OnStartBatchChanges() {}
104 // Sent after a batch of refresh token changes is done.
105 virtual void OnEndBatchChanges() {}
107 protected:
108 virtual ~Observer() {}
111 // Classes that want to monitor status of access token and access token
112 // request should implement this interface and register with the
113 // AddDiagnosticsObserver() call.
114 class DiagnosticsObserver {
115 public:
116 // Called when receiving request for access token.
117 virtual void OnAccessTokenRequested(const std::string& account_id,
118 const std::string& consumer_id,
119 const ScopeSet& scopes) = 0;
120 // Called when access token fetching finished successfully or
121 // unsuccessfully. |expiration_time| are only valid with
122 // successful completion.
123 virtual void OnFetchAccessTokenComplete(const std::string& account_id,
124 const std::string& consumer_id,
125 const ScopeSet& scopes,
126 GoogleServiceAuthError error,
127 base::Time expiration_time) = 0;
128 virtual void OnTokenRemoved(const std::string& account_id,
129 const ScopeSet& scopes) = 0;
132 OAuth2TokenService();
133 virtual ~OAuth2TokenService();
135 // Add or remove observers of this token service.
136 void AddObserver(Observer* observer);
137 void RemoveObserver(Observer* observer);
139 // Add or remove observers of this token service.
140 void AddDiagnosticsObserver(DiagnosticsObserver* observer);
141 void RemoveDiagnosticsObserver(DiagnosticsObserver* observer);
143 // Checks in the cache for a valid access token for a specified |account_id|
144 // and |scopes|, and if not found starts a request for an OAuth2 access token
145 // using the OAuth2 refresh token maintained by this instance for that
146 // |account_id|. The caller owns the returned Request.
147 // |scopes| is the set of scopes to get an access token for, |consumer| is
148 // the object that will be called back with results if the returned request
149 // is not deleted. Virtual for mocking.
150 virtual scoped_ptr<Request> StartRequest(const std::string& account_id,
151 const ScopeSet& scopes,
152 Consumer* consumer);
154 // This method does the same as |StartRequest| except it uses |client_id| and
155 // |client_secret| to identify OAuth client app instead of using
156 // Chrome's default values.
157 scoped_ptr<Request> StartRequestForClient(
158 const std::string& account_id,
159 const std::string& client_id,
160 const std::string& client_secret,
161 const ScopeSet& scopes,
162 Consumer* consumer);
164 // This method does the same as |StartRequest| except it uses the request
165 // context given by |getter| instead of using the one returned by
166 // |GetRequestContext| implemented by derived classes.
167 scoped_ptr<Request> StartRequestWithContext(
168 const std::string& account_id,
169 net::URLRequestContextGetter* getter,
170 const ScopeSet& scopes,
171 Consumer* consumer);
173 // Lists account IDs of all accounts with a refresh token maintained by this
174 // instance.
175 virtual std::vector<std::string> GetAccounts();
177 // Returns true if a refresh token exists for |account_id|. If false, calls to
178 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
179 virtual bool RefreshTokenIsAvailable(const std::string& account_id) const = 0;
181 // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
182 // invalid. This should be done if the token was received from this class,
183 // but was not accepted by the server (e.g., the server returned
184 // 401 Unauthorized). The token will be removed from the cache for the given
185 // scopes.
186 void InvalidateToken(const std::string& account_id,
187 const ScopeSet& scopes,
188 const std::string& access_token);
190 // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client
191 // app that issued the request instead of Chrome's default values.
192 void InvalidateTokenForClient(const std::string& account_id,
193 const std::string& client_id,
194 const ScopeSet& scopes,
195 const std::string& access_token);
198 // Return the current number of entries in the cache.
199 int cache_size_for_testing() const;
200 void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
201 // Returns the current number of pending fetchers matching given params.
202 size_t GetNumPendingRequestsForTesting(
203 const std::string& client_id,
204 const std::string& account_id,
205 const ScopeSet& scopes) const;
207 protected:
208 // Implements a cancelable |OAuth2TokenService::Request|, which should be
209 // operated on the UI thread.
210 // TODO(davidroche): move this out of header file.
211 class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
212 public base::NonThreadSafe,
213 public Request {
214 public:
215 // |consumer| is required to outlive this.
216 RequestImpl(const std::string& account_id, Consumer* consumer);
217 ~RequestImpl() override;
219 // Overridden from Request:
220 std::string GetAccountId() const override;
222 std::string GetConsumerId() const;
224 // Informs |consumer_| that this request is completed.
225 void InformConsumer(const GoogleServiceAuthError& error,
226 const std::string& access_token,
227 const base::Time& expiration_date);
229 private:
230 // |consumer_| to call back when this request completes.
231 const std::string account_id_;
232 Consumer* const consumer_;
235 // Helper class to scope batch changes.
236 class ScopedBatchChange {
237 public:
238 explicit ScopedBatchChange(OAuth2TokenService* token_service);
239 ~ScopedBatchChange();
240 private:
241 OAuth2TokenService* token_service_; // Weak.
242 DISALLOW_COPY_AND_ASSIGN(ScopedBatchChange);
245 // Subclasses can override if they want to report errors to the user.
246 virtual void UpdateAuthError(
247 const std::string& account_id,
248 const GoogleServiceAuthError& error);
250 // Add a new entry to the cache.
251 // Subclasses can override if there are implementation-specific reasons
252 // that an access token should ever not be cached.
253 virtual void RegisterCacheEntry(const std::string& client_id,
254 const std::string& account_id,
255 const ScopeSet& scopes,
256 const std::string& access_token,
257 const base::Time& expiration_date);
259 // Clears the internal token cache.
260 void ClearCache();
262 // Clears all of the tokens belonging to |account_id| from the internal token
263 // cache. It does not matter what other parameters, like |client_id| were
264 // used to request the tokens.
265 void ClearCacheForAccount(const std::string& account_id);
267 // Cancels all requests that are currently in progress.
268 void CancelAllRequests();
270 // Cancels all requests related to a given |account_id|.
271 void CancelRequestsForAccount(const std::string& account_id);
273 // Called by subclasses to notify observers.
274 virtual void FireRefreshTokenAvailable(const std::string& account_id);
275 virtual void FireRefreshTokenRevoked(const std::string& account_id);
276 virtual void FireRefreshTokensLoaded();
278 virtual void StartBatchChanges();
279 virtual void EndBatchChanges();
281 // Fetches an OAuth token for the specified client/scopes. Virtual so it can
282 // be overridden for tests and for platform-specific behavior on Android.
283 virtual void FetchOAuth2Token(RequestImpl* request,
284 const std::string& account_id,
285 net::URLRequestContextGetter* getter,
286 const std::string& client_id,
287 const std::string& client_secret,
288 const ScopeSet& scopes);
290 // Creates an access token fetcher for the given account id.
292 // Subclasses should override to create an access token fetcher for the given
293 // |account_id|. This method is only called if subclasses use the default
294 // implementation of |FetchOAuth2Token|.
295 virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
296 const std::string& account_id,
297 net::URLRequestContextGetter* getter,
298 OAuth2AccessTokenConsumer* consumer) = 0;
300 // Invalidates the |access_token| issued for |account_id|, |client_id| and
301 // |scopes|. Virtual so it can be overriden for tests and for platform-
302 // specifc behavior.
303 virtual void InvalidateOAuth2Token(const std::string& account_id,
304 const std::string& client_id,
305 const ScopeSet& scopes,
306 const std::string& access_token);
308 private:
309 class Fetcher;
310 friend class Fetcher;
312 // The parameters used to fetch an OAuth2 access token.
313 struct RequestParameters {
314 RequestParameters(const std::string& client_id,
315 const std::string& account_id,
316 const ScopeSet& scopes);
317 ~RequestParameters();
318 bool operator<(const RequestParameters& params) const;
320 // OAuth2 client id.
321 std::string client_id;
322 // Account id for which the request is made.
323 std::string account_id;
324 // URL scopes for the requested access token.
325 ScopeSet scopes;
328 typedef std::map<RequestParameters, Fetcher*> PendingFetcherMap;
330 // Derived classes must provide a request context used for fetching access
331 // tokens with the |StartRequest| method.
332 virtual net::URLRequestContextGetter* GetRequestContext() = 0;
334 // Struct that contains the information of an OAuth2 access token.
335 struct CacheEntry {
336 std::string access_token;
337 base::Time expiration_date;
340 // This method does the same as |StartRequestWithContext| except it
341 // uses |client_id| and |client_secret| to identify OAuth
342 // client app instead of using Chrome's default values.
343 scoped_ptr<Request> StartRequestForClientWithContext(
344 const std::string& account_id,
345 net::URLRequestContextGetter* getter,
346 const std::string& client_id,
347 const std::string& client_secret,
348 const ScopeSet& scopes,
349 Consumer* consumer);
351 // Returns true if GetCacheEntry would return a valid cache entry for the
352 // given scopes.
353 bool HasCacheEntry(const RequestParameters& client_scopes);
355 // Posts a task to fire the Consumer callback with the cached token. Must
356 // Must only be called if HasCacheEntry() returns true.
357 void StartCacheLookupRequest(RequestImpl* request,
358 const RequestParameters& client_scopes,
359 Consumer* consumer);
361 // Returns a currently valid OAuth2 access token for the given set of scopes,
362 // or NULL if none have been cached. Note the user of this method should
363 // ensure no entry with the same |client_scopes| is added before the usage of
364 // the returned entry is done.
365 const CacheEntry* GetCacheEntry(const RequestParameters& client_scopes);
367 // Removes an access token for the given set of scopes from the cache.
368 // Returns true if the entry was removed, otherwise false.
369 bool RemoveCacheEntry(const RequestParameters& client_scopes,
370 const std::string& token_to_remove);
372 // Called when |fetcher| finishes fetching.
373 void OnFetchComplete(Fetcher* fetcher);
375 // Called when a number of fetchers need to be canceled.
376 void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel);
378 // The cache of currently valid tokens.
379 typedef std::map<RequestParameters, CacheEntry> TokenCache;
380 TokenCache token_cache_;
382 // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
383 // token using these parameters.
384 PendingFetcherMap pending_fetchers_;
386 // List of observers to notify when refresh token availability changes.
387 // Makes sure list is empty on destruction.
388 ObserverList<Observer, true> observer_list_;
390 // List of observers to notify when access token status changes.
391 ObserverList<DiagnosticsObserver, true> diagnostics_observer_list_;
393 // The depth of batch changes.
394 int batch_change_depth_;
396 // Maximum number of retries in fetching an OAuth2 access token.
397 static int max_fetch_retry_num_;
399 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest);
400 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest,
401 SameScopesRequestedForDifferentClients);
403 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
406 #endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_