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 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 6#define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 7 8#include <map> 9#include <set> 10#include <string> 11 12#include "base/basictypes.h" 13#include "base/memory/ref_counted.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/memory/weak_ptr.h" 16#include "base/observer_list.h" 17#include "base/time/time.h" 18#include "google_apis/gaia/google_service_auth_error.h" 19 20namespace base { 21class Time; 22} 23 24namespace net { 25class URLRequestContextGetter; 26} 27 28class GoogleServiceAuthError; 29 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. 33// 34// All calls are expected from the UI thread. 35// 36// To use this service, call StartRequest() with a given set of scopes and a 37// consumer of the request results. The consumer is required to outlive the 38// request. The request can be deleted. The consumer may be called back 39// asynchronously with the fetch results. 40// 41// - If the consumer is not called back before the request is deleted, it will 42// never be called back. 43// Note in this case, the actual network requests are not canceled and the 44// cache will be populated with the fetched results; it is just the consumer 45// callback that is aborted. 46// 47// - Otherwise the consumer will be called back with the request and the fetch 48// results. 49// 50// The caller of StartRequest() owns the returned request and is responsible to 51// delete the request even once the callback has been invoked. 52class OAuth2TokenService { 53 public: 54 // Class representing a request that fetches an OAuth2 access token. 55 class Request { 56 public: 57 virtual ~Request(); 58 protected: 59 Request(); 60 }; 61 62 // Class representing the consumer of a Request passed to |StartRequest|, 63 // which will be called back when the request completes. 64 class Consumer { 65 public: 66 Consumer(); 67 virtual ~Consumer(); 68 // |request| is a Request that is started by this consumer and has 69 // completed. 70 virtual void OnGetTokenSuccess(const Request* request, 71 const std::string& access_token, 72 const base::Time& expiration_time) = 0; 73 virtual void OnGetTokenFailure(const Request* request, 74 const GoogleServiceAuthError& error) = 0; 75 }; 76 77 // Classes that want to listen for token availability should implement this 78 // interface and register with the AddObserver() call. 79 // TODO(rogerta): may get rid of |error| argument for OnRefreshTokenRevoked() 80 // once we stop supporting ClientLogin. Need to evaluate if its still useful. 81 class Observer { 82 public: 83 // Called whenever a new login-scoped refresh token is available for 84 // account |account_id|. Once available, access tokens can be retrieved for 85 // this account. This is called during initial startup for each token 86 // loaded. 87 virtual void OnRefreshTokenAvailable(const std::string& account_id) {} 88 // Called whenever the login-scoped refresh token becomes unavailable for 89 // account |account_id|. 90 virtual void OnRefreshTokenRevoked(const std::string& account_id, 91 const GoogleServiceAuthError& error) {} 92 // Called after all refresh tokens are loaded during OAuth2TokenService 93 // startup. 94 virtual void OnRefreshTokensLoaded() {} 95 // Called after all refresh tokens are removed from OAuth2TokenService. 96 virtual void OnRefreshTokensCleared() {} 97 protected: 98 virtual ~Observer() {} 99 }; 100 101 // A set of scopes in OAuth2 authentication. 102 typedef std::set<std::string> ScopeSet; 103 104 OAuth2TokenService(); 105 virtual ~OAuth2TokenService(); 106 107 // Add or remove observers of this token service. 108 void AddObserver(Observer* observer); 109 void RemoveObserver(Observer* observer); 110 111 // Checks in the cache for a valid access token, and if not found starts 112 // a request for an OAuth2 access token using the OAuth2 refresh token 113 // 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 115 // the object that will be called back with results if the returned request 116 // is not deleted. 117 virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes, 118 Consumer* consumer); 119 120 // This method does the same as |StartRequest| except it uses |client_id| and 121 // |client_secret| to identify OAuth client app instead of using 122 // Chrome's default values. 123 virtual scoped_ptr<Request> StartRequestForClient( 124 const std::string& client_id, 125 const std::string& client_secret, 126 const ScopeSet& scopes, 127 Consumer* consumer); 128 129 // This method does the same as |StartRequest| except it uses the request 130 // context given by |getter| instead of using the one returned by 131 // |GetRequestContext| implemented by derived classes. 132 virtual scoped_ptr<Request> StartRequestWithContext( 133 net::URLRequestContextGetter* getter, 134 const ScopeSet& scopes, 135 Consumer* consumer); 136 137 // Returns true if a refresh token exists. If false, calls to 138 // |StartRequest| will result in a Consumer::OnGetTokenFailure callback. 139 virtual bool RefreshTokenIsAvailable(); 140 141 // 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., 143 // the server returned 401 Unauthorized). The token will be removed from the 144 // cache for the given scopes. 145 virtual void InvalidateToken(const ScopeSet& scopes, 146 const std::string& invalid_token); 147 148 // Return the current number of entries in the cache. 149 int cache_size_for_testing() const; 150 void set_max_authorization_token_fetch_retries_for_testing(int max_retries); 151 152 protected: 153 // Implements a cancelable |OAuth2TokenService::Request|, which should be 154 // operated on the UI thread. 155 // TODO(davidroche): move this out of header file. 156 class RequestImpl : public base::SupportsWeakPtr<RequestImpl>, 157 public Request { 158 public: 159 // |consumer| is required to outlive this. 160 explicit RequestImpl(Consumer* consumer); 161 virtual ~RequestImpl(); 162 163 // Informs |consumer_| that this request is completed. 164 void InformConsumer(const GoogleServiceAuthError& error, 165 const std::string& access_token, 166 const base::Time& expiration_date); 167 168 private: 169 // |consumer_| to call back when this request completes. 170 Consumer* const consumer_; 171 }; 172 173 // Subclasses should return the refresh token maintained. 174 // If no token is available, return an empty string. 175 virtual std::string GetRefreshToken() = 0; 176 177 // Subclasses can override if they want to report errors to the user. 178 virtual void UpdateAuthError(const GoogleServiceAuthError& error); 179 180 // Add a new entry to the cache. 181 // Subclasses can override if there are implementation-specific reasons 182 // that an access token should ever not be cached. 183 virtual void RegisterCacheEntry(const std::string& refresh_token, 184 const ScopeSet& scopes, 185 const std::string& access_token, 186 const base::Time& expiration_date); 187 188 // Returns true if GetCacheEntry would return a valid cache entry for the 189 // given scopes. 190 bool HasCacheEntry(const ScopeSet& scopes); 191 192 // Posts a task to fire the Consumer callback with the cached token. Must 193 // Must only be called if HasCacheEntry() returns true. 194 scoped_ptr<Request> StartCacheLookupRequest(const ScopeSet& scopes, 195 Consumer* consumer); 196 197 // Clears the internal token cache. 198 void ClearCache(); 199 200 // Cancels all requests that are currently in progress. 201 void CancelAllRequests(); 202 203 // Cancels all requests related to a given refresh token. 204 void CancelRequestsForToken(const std::string& refresh_token); 205 206 // Called by subclasses to notify observers. 207 void FireRefreshTokenAvailable(const std::string& account_id); 208 void FireRefreshTokenRevoked(const std::string& account_id, 209 const GoogleServiceAuthError& error); 210 void FireRefreshTokensLoaded(); 211 void FireRefreshTokensCleared(); 212 213 private: 214 // Derived classes must provide a request context used for fetching access 215 // tokens with the |StartRequest| method. 216 virtual net::URLRequestContextGetter* GetRequestContext() = 0; 217 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. 224 struct CacheEntry { 225 std::string access_token; 226 base::Time expiration_date; 227 }; 228 229 // This method does the same as |StartRequestWithContext| except it 230 // uses |client_id| and |client_secret| to identify OAuth 231 // client app instead of using Chrome's default values. 232 scoped_ptr<Request> StartRequestForClientWithContext( 233 net::URLRequestContextGetter* getter, 234 const std::string& client_id, 235 const std::string& client_secret, 236 const ScopeSet& scopes, 237 Consumer* consumer); 238 239 // 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 241 // ensure no entry with the same |scopes| is added before the usage of the 242 // returned entry is done. 243 const CacheEntry* GetCacheEntry(const ScopeSet& scopes); 244 245 246 // Removes an access token for the given set of scopes from the cache. 247 // Returns true if the entry was removed, otherwise false. 248 bool RemoveCacheEntry(const OAuth2TokenService::ScopeSet& scopes, 249 const std::string& token_to_remove); 250 251 252 // Called when |fetcher| finishes fetching. 253 void OnFetchComplete(Fetcher* fetcher); 254 255 // Called when a number of fetchers need to be canceled. 256 void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel); 257 258 // The cache of currently valid tokens. 259 typedef std::map<ScopeSet, CacheEntry> TokenCache; 260 TokenCache token_cache_; 261 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 266 // token using these parameters. 267 std::map<FetchParameters, Fetcher*> pending_fetchers_; 268 269 // List of observers to notify when token availiability changes. 270 // Makes sure list is empty on destruction. 271 ObserverList<Observer, true> observer_list_; 272 273 // Maximum number of retries in fetching an OAuth2 access token. 274 static int max_fetch_retry_num_; 275 276 DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService); 277}; 278 279#endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_H_ 280