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