- add sources.
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / oauth2_token_service.h
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.
4
5 #ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
6 #define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11
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"
23
24 namespace net {
25 class URLRequestContextGetter;
26 }
27
28 class 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. Derived services might maintain refresh tokens
33 // for multiple accounts.
34 //
35 // All calls are expected from the UI thread.
36 //
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.
41 //
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.
47 //
48 // - Otherwise the consumer will be called back with the request and the fetch
49 //   results.
50 //
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   // Class representing a request that fetches an OAuth2 access token.
56   class Request {
57    public:
58     virtual ~Request();
59    protected:
60     Request();
61   };
62
63   // Class representing the consumer of a Request passed to |StartRequest|,
64   // which will be called back when the request completes.
65   class Consumer {
66    public:
67     Consumer();
68     virtual ~Consumer();
69     // |request| is a Request that is started by this consumer and has
70     // completed.
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;
76   };
77
78   // Classes that want to listen for token availability should implement this
79   // interface and register with the AddObserver() call.
80   class Observer {
81    public:
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
85     // loaded.
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
91     // startup.
92     virtual void OnRefreshTokensLoaded() {}
93    protected:
94     virtual ~Observer() {}
95   };
96
97   // A set of scopes in OAuth2 authentication.
98   typedef std::set<std::string> ScopeSet;
99
100   OAuth2TokenService();
101   virtual ~OAuth2TokenService();
102
103   // Add or remove observers of this token service.
104   void AddObserver(Observer* observer);
105   void RemoveObserver(Observer* observer);
106
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
113   // is not deleted.
114   scoped_ptr<Request> StartRequest(const std::string& account_id,
115                                    const ScopeSet& scopes,
116                                    Consumer* consumer);
117
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,
126       Consumer* consumer);
127
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,
135       Consumer* consumer);
136
137   // Lists account IDs of all accounts with a refresh token maintained by this
138   // instance.
139   virtual std::vector<std::string> GetAccounts();
140
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);
144
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
149   // scopes.
150   void InvalidateToken(const std::string& account_id,
151                        const ScopeSet& scopes,
152                        const std::string& access_token);
153
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);
160
161
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;
170
171  protected:
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,
177                       public Request {
178    public:
179     // |consumer| is required to outlive this.
180     explicit RequestImpl(Consumer* consumer);
181     virtual ~RequestImpl();
182
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);
187
188    private:
189     // |consumer_| to call back when this request completes.
190     Consumer* const consumer_;
191   };
192
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;
196
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);
201
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);
210
211   // Clears the internal token cache.
212   void ClearCache();
213
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);
218
219   // Cancels all requests that are currently in progress.
220   void CancelAllRequests();
221
222   // Cancels all requests related to a given |account_id|.
223   void CancelRequestsForAccount(const std::string& account_id);
224
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();
229
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);
234
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);
243
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-
246   // specifc behavior.
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);
251
252  private:
253   class Fetcher;
254   friend class Fetcher;
255
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;
263
264     // OAuth2 client id.
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.
269     ScopeSet scopes;
270   };
271
272   typedef std::map<RequestParameters, Fetcher*> PendingFetcherMap;
273
274   // Derived classes must provide a request context used for fetching access
275   // tokens with the |StartRequest| method.
276   virtual net::URLRequestContextGetter* GetRequestContext() = 0;
277
278   // Struct that contains the information of an OAuth2 access token.
279   struct CacheEntry {
280     std::string access_token;
281     base::Time expiration_date;
282   };
283
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,
293       Consumer* consumer);
294
295   // Returns true if GetCacheEntry would return a valid cache entry for the
296   // given scopes.
297   bool HasCacheEntry(const RequestParameters& client_scopes);
298
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,
303                                Consumer* consumer);
304
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);
310
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);
315
316   // Called when |fetcher| finishes fetching.
317   void OnFetchComplete(Fetcher* fetcher);
318
319   // Called when a number of fetchers need to be canceled.
320   void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel);
321
322   // The cache of currently valid tokens.
323   typedef std::map<RequestParameters, CacheEntry> TokenCache;
324   TokenCache token_cache_;
325
326   // A map from fetch parameters to a fetcher that is fetching an OAuth2 access
327   // token using these parameters.
328   PendingFetcherMap pending_fetchers_;
329
330   // List of observers to notify when token availability changes.
331   // Makes sure list is empty on destruction.
332   ObserverList<Observer, true> observer_list_;
333
334   // Maximum number of retries in fetching an OAuth2 access token.
335   static int max_fetch_retry_num_;
336
337   FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest);
338   FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest,
339                            SameScopesRequestedForDifferentClients);
340
341   DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
342 };
343
344 #endif  // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_