oauth2_access_token_fetcher.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 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 GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
6#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/gtest_prod_util.h"
12#include "base/memory/scoped_ptr.h"
13#include "google_apis/gaia/oauth2_access_token_consumer.h"
14#include "googleurl/src/gurl.h"
15#include "net/url_request/url_fetcher_delegate.h"
16
17class OAuth2AccessTokenFetcherTest;
18
19namespace base {
20class Time;
21}
22
23namespace net {
24class URLFetcher;
25class URLRequestContextGetter;
26class URLRequestStatus;
27}
28
29// Abstracts the details to get OAuth2 access token token from
30// OAuth2 refresh token.
31// See "Using the Refresh Token" section in:
32// http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
33//
34// This class should be used on a single thread, but it can be whichever thread
35// that you like.
36// Also, do not reuse the same instance. Once Start() is called, the instance
37// should not be reused.
38//
39// Usage:
40// * Create an instance with a consumer.
41// * Call Start()
42// * The consumer passed in the constructor will be called on the same
43//   thread Start was called with the results.
44//
45// This class can handle one request at a time. To parallelize requests,
46// create multiple instances.
47class OAuth2AccessTokenFetcher : public net::URLFetcherDelegate {
48 public:
49  OAuth2AccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
50                           net::URLRequestContextGetter* getter);
51  virtual ~OAuth2AccessTokenFetcher();
52
53  // Starts the flow with the given parameters.
54  // |scopes| can be empty. If it is empty then the access token will have the
55  // same scope as the refresh token. If not empty, then access token will have
56  // the scopes specified. In this case, the access token will successfully be
57  // generated only if refresh token has login scope of a list of scopes that is
58  // a super-set of the specified scopes.
59  virtual void Start(const std::string& client_id,
60                     const std::string& client_secret,
61                     const std::string& refresh_token,
62                     const std::vector<std::string>& scopes);
63
64  void CancelRequest();
65
66  // Implementation of net::URLFetcherDelegate
67  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
68
69 private:
70  enum State {
71    INITIAL,
72    GET_ACCESS_TOKEN_STARTED,
73    GET_ACCESS_TOKEN_DONE,
74    ERROR_STATE,
75  };
76
77  // Helper methods for the flow.
78  void StartGetAccessToken();
79  void EndGetAccessToken(const net::URLFetcher* source);
80
81  // Helper mehtods for reporting back results.
82  void OnGetTokenSuccess(const std::string& access_token,
83                         const base::Time& expiration_time);
84  void OnGetTokenFailure(const GoogleServiceAuthError& error);
85
86  // Other helpers.
87  static GURL MakeGetAccessTokenUrl();
88  static std::string MakeGetAccessTokenBody(
89      const std::string& client_id,
90      const std::string& client_secret,
91      const std::string& refresh_token,
92      const std::vector<std::string>& scopes);
93  static bool ParseGetAccessTokenResponse(const net::URLFetcher* source,
94                                          std::string* access_token,
95                                          int* expires_in);
96
97  // State that is set during construction.
98  OAuth2AccessTokenConsumer* const consumer_;
99  net::URLRequestContextGetter* const getter_;
100  State state_;
101
102  // While a fetch is in progress.
103  scoped_ptr<net::URLFetcher> fetcher_;
104  std::string client_id_;
105  std::string client_secret_;
106  std::string refresh_token_;
107  std::vector<std::string> scopes_;
108
109  friend class OAuth2AccessTokenFetcherTest;
110  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest,
111                           ParseGetAccessTokenResponse);
112  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest,
113                           MakeGetAccessTokenBody);
114
115  DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcher);
116};
117
118#endif  // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
119