Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(308)

Side by Side Diff: chrome/browser/signin/oauth2_token_service.h

Issue 22581003: Handling of multiple concurrent requests from different clients in OAuth2TokenService (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 5 #ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_
6 #define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 6 #define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_
7 7
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/gtest_prod_util.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h" 16 #include "base/memory/weak_ptr.h"
16 #include "base/observer_list.h" 17 #include "base/observer_list.h"
17 #include "base/time/time.h" 18 #include "base/time/time.h"
19 #include "base/timer/timer.h"
18 #include "google_apis/gaia/google_service_auth_error.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"
19 23
20 namespace base { 24 namespace base {
21 class Time; 25 class Time;
22 } 26 }
23 27
24 namespace net { 28 namespace net {
25 class URLRequestContextGetter; 29 class URLRequestContextGetter;
26 } 30 }
27 31
28 class GoogleServiceAuthError; 32 class GoogleServiceAuthError;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // a request for an OAuth2 access token using the OAuth2 refresh token 116 // a request for an OAuth2 access token using the OAuth2 refresh token
113 // maintained by this instance. The caller owns the returned Request. 117 // maintained by this instance. The caller owns the returned Request.
114 // |scopes| is the set of scopes to get an access token for, |consumer| is 118 // |scopes| is the set of scopes to get an access token for, |consumer| is
115 // the object that will be called back with results if the returned request 119 // the object that will be called back with results if the returned request
116 // is not deleted. 120 // is not deleted.
117 virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes, 121 virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes,
118 Consumer* consumer); 122 Consumer* consumer);
119 123
120 // This method does the same as |StartRequest| except it uses |client_id| and 124 // This method does the same as |StartRequest| except it uses |client_id| and
121 // |client_secret| to identify OAuth client app instead of using 125 // |client_secret| to identify OAuth client app instead of using
122 // Chrome's default values. 126 // Chrome's default values. |request_origin| is used to differentiate where
127 // request originates from. It's expected to be empty for requests from
128 // the internal chrome services while we will use webapp id for their
Andrew T Wilson (Slow) 2013/08/19 14:04:19 So, one thing this CL (and the associated bug) is
129 // requests.
123 virtual scoped_ptr<Request> StartRequestForClient( 130 virtual scoped_ptr<Request> StartRequestForClient(
131 const std::string& request_origin,
124 const std::string& client_id, 132 const std::string& client_id,
125 const std::string& client_secret, 133 const std::string& client_secret,
126 const ScopeSet& scopes, 134 const ScopeSet& scopes,
127 Consumer* consumer); 135 Consumer* consumer);
128 136
129 // This method does the same as |StartRequest| except it uses the request 137 // This method does the same as |StartRequest| except it uses the request
130 // context given by |getter| instead of using the one returned by 138 // context given by |getter| instead of using the one returned by
131 // |GetRequestContext| implemented by derived classes. 139 // |GetRequestContext| implemented by derived classes.
132 virtual scoped_ptr<Request> StartRequestWithContext( 140 virtual scoped_ptr<Request> StartRequestWithContext(
133 net::URLRequestContextGetter* getter, 141 net::URLRequestContextGetter* getter,
134 const ScopeSet& scopes, 142 const ScopeSet& scopes,
135 Consumer* consumer); 143 Consumer* consumer);
136 144
137 // Returns true if a refresh token exists. If false, calls to 145 // Returns true if a refresh token exists. If false, calls to
138 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback. 146 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
139 virtual bool RefreshTokenIsAvailable(); 147 virtual bool RefreshTokenIsAvailable();
140 148
141 // Mark an OAuth2 access token as invalid. This should be done if the token 149 // Mark an OAuth2 access token as invalid. This should be done if the token
142 // was received from this class, but was not accepted by the server (e.g., 150 // was received from this class, but was not accepted by the server (e.g.,
143 // the server returned 401 Unauthorized). The token will be removed from the 151 // the server returned 401 Unauthorized). The token will be removed from the
144 // cache for the given scopes. 152 // cache for the given scopes.
145 virtual void InvalidateToken(const ScopeSet& scopes, 153 virtual void InvalidateToken(const ScopeSet& scopes,
146 const std::string& invalid_token); 154 const std::string& invalid_token);
147 155
148 // Return the current number of entries in the cache. 156 // Return the current number of entries in the cache.
149 int cache_size_for_testing() const; 157 int cache_size_for_testing() const;
150 void set_max_authorization_token_fetch_retries_for_testing(int max_retries); 158 void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
151 159
152 protected: 160 protected:
161 struct ClientScopeSet {
162 ClientScopeSet(const std::string& request_origin,
163 const std::string& client_id,
164 const ScopeSet& scopes);
165 bool operator<(const ClientScopeSet& set) const;
166
167 std::string request_origin;
168 std::string client_id;
169 ScopeSet scopes;
170 };
171
153 // Implements a cancelable |OAuth2TokenService::Request|, which should be 172 // Implements a cancelable |OAuth2TokenService::Request|, which should be
154 // operated on the UI thread. 173 // operated on the UI thread.
155 // TODO(davidroche): move this out of header file. 174 // TODO(davidroche): move this out of header file.
156 class RequestImpl : public base::SupportsWeakPtr<RequestImpl>, 175 class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
157 public Request { 176 public Request {
158 public: 177 public:
159 // |consumer| is required to outlive this. 178 // |consumer| is required to outlive this.
160 explicit RequestImpl(Consumer* consumer); 179 explicit RequestImpl(Consumer* consumer);
161 virtual ~RequestImpl(); 180 virtual ~RequestImpl();
162 181
(...skipping 10 matching lines...) Expand all
173 // Subclasses should return the refresh token maintained. 192 // Subclasses should return the refresh token maintained.
174 // If no token is available, return an empty string. 193 // If no token is available, return an empty string.
175 virtual std::string GetRefreshToken() = 0; 194 virtual std::string GetRefreshToken() = 0;
176 195
177 // Subclasses can override if they want to report errors to the user. 196 // Subclasses can override if they want to report errors to the user.
178 virtual void UpdateAuthError(const GoogleServiceAuthError& error); 197 virtual void UpdateAuthError(const GoogleServiceAuthError& error);
179 198
180 // Add a new entry to the cache. 199 // Add a new entry to the cache.
181 // Subclasses can override if there are implementation-specific reasons 200 // Subclasses can override if there are implementation-specific reasons
182 // that an access token should ever not be cached. 201 // that an access token should ever not be cached.
183 virtual void RegisterCacheEntry(const std::string& refresh_token, 202 virtual void RegisterCacheEntry(const std::string& request_origin,
203 const std::string& client_id,
204 const std::string& refresh_token,
184 const ScopeSet& scopes, 205 const ScopeSet& scopes,
185 const std::string& access_token, 206 const std::string& access_token,
186 const base::Time& expiration_date); 207 const base::Time& expiration_date);
187 208
188 // Returns true if GetCacheEntry would return a valid cache entry for the 209 // Returns true if GetCacheEntry would return a valid cache entry for the
189 // given scopes. 210 // given scopes.
190 bool HasCacheEntry(const ScopeSet& scopes); 211 bool HasCacheEntry(const ClientScopeSet& client_scopes);
191 212
192 // Posts a task to fire the Consumer callback with the cached token. Must 213 // Posts a task to fire the Consumer callback with the cached token. Must
193 // Must only be called if HasCacheEntry() returns true. 214 // Must only be called if HasCacheEntry() returns true.
194 scoped_ptr<Request> StartCacheLookupRequest(const ScopeSet& scopes, 215 scoped_ptr<Request> StartCacheLookupRequest(
195 Consumer* consumer); 216 const ClientScopeSet& client_scopes,
217 Consumer* consumer);
196 218
197 // Clears the internal token cache. 219 // Clears the internal token cache.
198 void ClearCache(); 220 void ClearCache();
199 221
200 // Cancels all requests that are currently in progress. 222 // Cancels all requests that are currently in progress.
201 void CancelAllRequests(); 223 void CancelAllRequests();
202 224
203 // Cancels all requests related to a given refresh token. 225 // Cancels all requests related to a given refresh token.
204 void CancelRequestsForToken(const std::string& refresh_token); 226 void CancelRequestsForToken(const std::string& refresh_token);
205 227
206 // Called by subclasses to notify observers. 228 // Called by subclasses to notify observers.
207 void FireRefreshTokenAvailable(const std::string& account_id); 229 void FireRefreshTokenAvailable(const std::string& account_id);
208 void FireRefreshTokenRevoked(const std::string& account_id, 230 void FireRefreshTokenRevoked(const std::string& account_id,
209 const GoogleServiceAuthError& error); 231 const GoogleServiceAuthError& error);
210 void FireRefreshTokensLoaded(); 232 void FireRefreshTokensLoaded();
211 void FireRefreshTokensCleared(); 233 void FireRefreshTokensCleared();
212 234
213 private: 235 private:
236 // Class that fetches an OAuth2 access token for a given set of scopes and
Andrew T Wilson (Slow) 2013/08/19 14:04:19 I don't really like the fact that we're exposing t
237 // OAuth2 refresh token.
238
239 // Class that fetches OAuth2 access tokens for given scopes and refresh token.
240 //
241 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry
242 // mechanism is used to handle failures.
243 //
244 // To use this class, call CreateAndStart() to create and start a Fetcher.
245 //
246 // The Fetcher will call back the service by calling
247 // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is
248 // not destructed before it completes fetching; if the Fetcher is destructed
249 // before it completes fetching, the service will never be called back. The
250 // Fetcher destructs itself after calling back the service when finishes
251 // fetching.
252 //
253 // Requests that are waiting for the fetching results of this Fetcher can be
254 // added to the Fetcher by calling
255 // OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher
256 // completes fetching.
257 //
258 // The waiting requests are taken as weak pointers and they can be deleted.
259 // The waiting requests will be called back with fetching results if they are
260 // not deleted
261 // - when the Fetcher completes fetching, if the Fetcher is not destructed
262 // before it completes fetching, or
263 // - when the Fetcher is destructed if the Fetcher is destructed before it
264 // completes fetching (in this case, the waiting requests will be called
265 // back with error).
266 class Fetcher : public OAuth2AccessTokenConsumer {
267 public:
268 // Creates a Fetcher and starts fetching an OAuth2 access token for
269 // |refresh_token| and |scopes| in the request context obtained by |getter|.
270 // The given |oauth2_token_service| will be informed when fetching is done.
271 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
272 net::URLRequestContextGetter* getter,
273 const std::string& request_origin,
274 const std::string& client_id,
275 const std::string& client_secret,
276 const std::string& refresh_token,
277 const ScopeSet& scopes,
278 base::WeakPtr<RequestImpl> waiting_request);
279 virtual ~Fetcher();
280
281 // Add a request that is waiting for the result of this Fetcher.
282 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
283
284 // Returns count of waiting requests.
285 size_t GetWaitingRequestCount() const;
286
287 void Cancel();
288
289 const ScopeSet& GetScopeSet() const;
290 const std::string& GetRefreshToken() const;
291 const std::string& GetClientId() const;
292 const std::string& GetRequestOrigin() const;
293
294 // The error result from this fetcher.
295 const GoogleServiceAuthError& error() const { return error_; }
296
297 protected:
298 // OAuth2AccessTokenConsumer
299 virtual void OnGetTokenSuccess(const std::string& access_token,
300 const base::Time& expiration_date) OVERRIDE;
301 virtual void OnGetTokenFailure(
302 const GoogleServiceAuthError& error) OVERRIDE;
303
304 private:
305 Fetcher(OAuth2TokenService* oauth2_token_service,
306 net::URLRequestContextGetter* getter,
307 const std::string& request_origin,
308 const std::string& client_id,
309 const std::string& client_secret,
310 const std::string& refresh_token,
311 const OAuth2TokenService::ScopeSet& scopes,
312 base::WeakPtr<RequestImpl> waiting_request);
313 void Start();
314 void InformWaitingRequests();
315 void InformWaitingRequestsAndDelete();
316 static bool ShouldRetry(const GoogleServiceAuthError& error);
317 int64 ComputeExponentialBackOffMilliseconds(int retry_num);
318
319 // |oauth2_token_service_| remains valid for the life of this Fetcher, since
320 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
321 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
322 // (whichever comes first).
323 OAuth2TokenService* const oauth2_token_service_;
324 scoped_refptr<net::URLRequestContextGetter> getter_;
325 const std::string refresh_token_;
326 const ScopeSet scopes_;
327 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
328
329 int retry_number_;
330 base::OneShotTimer<Fetcher> retry_timer_;
331 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_;
332
333 // Variables that store fetch results.
334 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
335 // destruction.
336 GoogleServiceAuthError error_;
337 std::string access_token_;
338 base::Time expiration_date_;
339
340 // Token fetch request origin identifier.
341 std::string request_origin_;
342
343 // OAuth2 client id and secret.
344 std::string client_id_;
345 std::string client_secret_;
346
347 DISALLOW_COPY_AND_ASSIGN(Fetcher);
348 };
349
350 friend class Fetcher;
351
352 // The parameters used to fetch an OAuth2 access token.
353 struct FetchParameters {
354 FetchParameters(const std::string& request_origin,
355 const std::string& client_id,
356 const std::string& refresh_token,
357 const ScopeSet& scopes);
358 bool operator<(const FetchParameters& params) const;
359
360 // Request origin identifier. It's empty for internal chrome services
361 // requests but the requests originating from webapps should be identified
362 // by their originating extension_id.
363 std::string request_origin;
364 // OAuth2 client id.
365 std::string client_id;
366 // Refresh token used for minting access tokens within this request.
367 std::string refresh_token;
368 // URL scopes for the requested access token.
369 ScopeSet scopes;
370 };
371
372 typedef std::map<FetchParameters, Fetcher*> PendingFetcherMap;
373
374 const PendingFetcherMap& GetPendingFetchersForTesting() const {
375 return pending_fetchers_;
376 }
377
214 // Derived classes must provide a request context used for fetching access 378 // Derived classes must provide a request context used for fetching access
215 // tokens with the |StartRequest| method. 379 // tokens with the |StartRequest| method.
216 virtual net::URLRequestContextGetter* GetRequestContext() = 0; 380 virtual net::URLRequestContextGetter* GetRequestContext() = 0;
217 381
218 // Class that fetches an OAuth2 access token for a given set of scopes and
219 // OAuth2 refresh token.
220 class Fetcher;
221 friend class Fetcher;
222
223 // Struct that contains the information of an OAuth2 access token. 382 // Struct that contains the information of an OAuth2 access token.
224 struct CacheEntry { 383 struct CacheEntry {
225 std::string access_token; 384 std::string access_token;
226 base::Time expiration_date; 385 base::Time expiration_date;
227 }; 386 };
228 387
229 // This method does the same as |StartRequestWithContext| except it 388 // This method does the same as |StartRequestWithContext| except it
230 // uses |client_id| and |client_secret| to identify OAuth 389 // uses |client_id| and |client_secret| to identify OAuth
231 // client app instead of using Chrome's default values. 390 // client app instead of using Chrome's default values.
232 scoped_ptr<Request> StartRequestForClientWithContext( 391 scoped_ptr<Request> StartRequestForClientWithContext(
233 net::URLRequestContextGetter* getter, 392 net::URLRequestContextGetter* getter,
393 const std::string& request_origin,
234 const std::string& client_id, 394 const std::string& client_id,
235 const std::string& client_secret, 395 const std::string& client_secret,
236 const ScopeSet& scopes, 396 const ScopeSet& scopes,
237 Consumer* consumer); 397 Consumer* consumer);
238 398
239 // Returns a currently valid OAuth2 access token for the given set of scopes, 399 // Returns a currently valid OAuth2 access token for the given set of scopes,
240 // or NULL if none have been cached. Note the user of this method should 400 // or NULL if none have been cached. Note the user of this method should
241 // ensure no entry with the same |scopes| is added before the usage of the 401 // ensure no entry with the same |client_scopes| is added before the usage of
242 // returned entry is done. 402 // the returned entry is done.
243 const CacheEntry* GetCacheEntry(const ScopeSet& scopes); 403 const CacheEntry* GetCacheEntry(const ClientScopeSet& client_scopes);
244 404
245 405
246 // Removes an access token for the given set of scopes from the cache. 406 // Removes an access token for the given set of scopes from the cache.
247 // Returns true if the entry was removed, otherwise false. 407 // Returns true if the entry was removed, otherwise false.
248 bool RemoveCacheEntry(const OAuth2TokenService::ScopeSet& scopes, 408 bool RemoveCacheEntry(const ClientScopeSet& client_scopes,
249 const std::string& token_to_remove); 409 const std::string& token_to_remove);
250 410
251 411
252 // Called when |fetcher| finishes fetching. 412 // Called when |fetcher| finishes fetching.
253 void OnFetchComplete(Fetcher* fetcher); 413 void OnFetchComplete(Fetcher* fetcher);
254 414
255 // Called when a number of fetchers need to be canceled. 415 // Called when a number of fetchers need to be canceled.
256 void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel); 416 void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel);
257 417
258 // The cache of currently valid tokens. 418 // The cache of currently valid tokens.
259 typedef std::map<ScopeSet, CacheEntry> TokenCache; 419 typedef std::map<ClientScopeSet, CacheEntry> TokenCache;
260 TokenCache token_cache_; 420 TokenCache token_cache_;
261 421
262 // The parameters (refresh token and scope set) used to fetch an OAuth2 access
263 // token.
264 typedef std::pair<std::string, ScopeSet> FetchParameters;
265 // A map from fetch parameters to a fetcher that is fetching an OAuth2 access 422 // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
266 // token using these parameters. 423 // token using these parameters.
267 std::map<FetchParameters, Fetcher*> pending_fetchers_; 424 PendingFetcherMap pending_fetchers_;
268 425
269 // List of observers to notify when token availiability changes. 426 // List of observers to notify when token availiability changes.
270 // Makes sure list is empty on destruction. 427 // Makes sure list is empty on destruction.
271 ObserverList<Observer, true> observer_list_; 428 ObserverList<Observer, true> observer_list_;
272 429
273 // Maximum number of retries in fetching an OAuth2 access token. 430 // Maximum number of retries in fetching an OAuth2 access token.
274 static int max_fetch_retry_num_; 431 static int max_fetch_retry_num_;
275 432
433 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, ClientScopeSetOrderTest);
434 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, FetchParametersOrderTest);
435 FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest,
436 SameScopesRequestedForDifferentClients);
437
276 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService); 438 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
277 }; 439 };
278 440
279 #endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 441 #endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698