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_API_CALL_FLOW_H_ 6 #define GOOGLE_APIS_GAIA_OAUTH2_API_CALL_FLOW_H_ 7 8 #include <string> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "google_apis/gaia/oauth2_access_token_consumer.h" 13 #include "google_apis/gaia/oauth2_access_token_fetcher.h" 14 #include "net/url_request/url_fetcher_delegate.h" 15 #include "url/gurl.h" 16 17 class GoogleServiceAuthError; 18 class OAuth2MintTokenFlowTest; 19 20 namespace net { 21 class URLFetcher; 22 class URLRequestContextGetter; 23 } 24 25 // Base class for all classes that implement a flow to call OAuth2 26 // enabled APIs. 27 // 28 // Given a refresh token, an access token, and a list of scopes an OAuth2 29 // enabled API is called in the following way: 30 // 1. Try the given access token to call the API. 31 // 2. If that does not work, use the refresh token and scopes to generate 32 // a new access token. 33 // 3. Try the new access token to call the API. 34 // 35 // This class abstracts the basic steps and exposes template methods 36 // for sub-classes to implement for API specific details. 37 class OAuth2ApiCallFlow 38 : public net::URLFetcherDelegate, 39 public OAuth2AccessTokenConsumer { 40 public: 41 // Creates an instance that works with the given data. 42 // Note that |access_token| can be empty. In that case, the flow will skip 43 // the first step (of trying an existing access token). 44 OAuth2ApiCallFlow( 45 net::URLRequestContextGetter* context, 46 const std::string& refresh_token, 47 const std::string& access_token, 48 const std::vector<std::string>& scopes); 49 50 virtual ~OAuth2ApiCallFlow(); 51 52 // Start the flow. 53 virtual void Start(); 54 55 // OAuth2AccessTokenFetcher implementation. 56 virtual void OnGetTokenSuccess(const std::string& access_token, 57 const base::Time& expiration_time) OVERRIDE; 58 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; 59 60 // net::URLFetcherDelegate implementation. 61 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 62 63 protected: 64 // Template methods for sub-classes. 65 66 // Methods to help create HTTP request. 67 virtual GURL CreateApiCallUrl() = 0; 68 virtual std::string CreateApiCallBody() = 0; 69 70 // Sub-classes can expose an appropriate observer interface by implementing 71 // these template methods. 72 // Called when the API call finished successfully. 73 virtual void ProcessApiCallSuccess(const net::URLFetcher* source) = 0; 74 // Called when the API call failed. 75 virtual void ProcessApiCallFailure(const net::URLFetcher* source) = 0; 76 // Called when a new access token is generated. 77 virtual void ProcessNewAccessToken(const std::string& access_token) = 0; 78 virtual void ProcessMintAccessTokenFailure( 79 const GoogleServiceAuthError& error) = 0; 80 81 private: 82 enum State { 83 INITIAL, 84 API_CALL_STARTED, 85 API_CALL_DONE, 86 MINT_ACCESS_TOKEN_STARTED, 87 MINT_ACCESS_TOKEN_DONE, 88 ERROR_STATE 89 }; 90 91 friend class OAuth2ApiCallFlowTest; 92 FRIEND_TEST_ALL_PREFIXES(OAuth2ApiCallFlowTest, CreateURLFetcher); 93 94 // Helper to create an instance of access token fetcher. 95 // Caller owns the returned instance. 96 // Note that this is virtual since it is mocked during unit testing. 97 virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(); 98 99 // Creates an instance of URLFetcher that does not send or save cookies. 100 // Template method CreateApiCallUrl is used to get the URL. 101 // Template method CreateApiCallBody is used to get the body. 102 // The URLFether's method will be GET if body is empty, POST otherwise. 103 // Caller owns the returned instance. 104 // Note that this is virtual since it is mocked during unit testing. 105 virtual net::URLFetcher* CreateURLFetcher(); 106 107 // Helper methods to implement the state machine for the flow. 108 void BeginApiCall(); 109 void EndApiCall(const net::URLFetcher* source); 110 void BeginMintAccessToken(); 111 void EndMintAccessToken(const GoogleServiceAuthError* error); 112 113 net::URLRequestContextGetter* context_; 114 std::string refresh_token_; 115 std::string access_token_; 116 std::vector<std::string> scopes_; 117 118 State state_; 119 // Whether we have already tried minting an access token once. 120 bool tried_mint_access_token_; 121 122 scoped_ptr<net::URLFetcher> url_fetcher_; 123 scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_; 124 125 DISALLOW_COPY_AND_ASSIGN(OAuth2ApiCallFlow); 126 }; 127 128 #endif // GOOGLE_APIS_GAIA_OAUTH2_API_CALL_FLOW_H_ 129