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 "net/url_request/url_fetcher_delegate.h" 15 #include "url/gurl.h" 16 17 class OAuth2AccessTokenFetcherTest; 18 19 namespace base { 20 class Time; 21 } 22 23 namespace net { 24 class URLFetcher; 25 class URLRequestContextGetter; 26 class 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. 47 class 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 94 static bool ParseGetAccessTokenSuccessResponse( 95 const net::URLFetcher* source, 96 std::string* access_token, 97 int* expires_in); 98 99 static bool ParseGetAccessTokenFailureResponse( 100 const net::URLFetcher* source, 101 std::string* error); 102 103 // State that is set during construction. 104 OAuth2AccessTokenConsumer* const consumer_; 105 net::URLRequestContextGetter* const getter_; 106 State state_; 107 108 // While a fetch is in progress. 109 scoped_ptr<net::URLFetcher> fetcher_; 110 std::string client_id_; 111 std::string client_secret_; 112 std::string refresh_token_; 113 std::vector<std::string> scopes_; 114 115 friend class OAuth2AccessTokenFetcherTest; 116 FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest, 117 ParseGetAccessTokenResponse); 118 FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest, 119 MakeGetAccessTokenBody); 120 121 DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcher); 122 }; 123 124 #endif // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_ 125