Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(542)

Side by Side Diff: chrome/common/net/gaia/oauth2_access_token_fetcher.cc

Issue 10928017: Moving google_apis and GaiaClient to src/google_apis. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge to head Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/common/net/gaia/oauth2_access_token_fetcher.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/json/json_reader.h"
12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
14 #include "base/time.h"
15 #include "base/values.h"
16 #include "chrome/common/net/gaia/gaia_urls.h"
17 #include "chrome/common/net/gaia/google_service_auth_error.h"
18 #include "net/base/escape.h"
19 #include "net/base/load_flags.h"
20 #include "net/http/http_status_code.h"
21 #include "net/url_request/url_fetcher.h"
22 #include "net/url_request/url_request_context_getter.h"
23 #include "net/url_request/url_request_status.h"
24
25 using net::ResponseCookies;
26 using net::URLFetcher;
27 using net::URLFetcherDelegate;
28 using net::URLRequestContextGetter;
29 using net::URLRequestStatus;
30
31 namespace {
32 static const char kGetAccessTokenBodyFormat[] =
33 "client_id=%s&"
34 "client_secret=%s&"
35 "grant_type=refresh_token&"
36 "refresh_token=%s";
37
38 static const char kGetAccessTokenBodyWithScopeFormat[] =
39 "client_id=%s&"
40 "client_secret=%s&"
41 "grant_type=refresh_token&"
42 "refresh_token=%s&"
43 "scope=%s";
44
45 static const char kAccessTokenKey[] = "access_token";
46 static const char kExpiresInKey[] = "expires_in";
47
48 static GoogleServiceAuthError CreateAuthError(URLRequestStatus status) {
49 CHECK(!status.is_success());
50 if (status.status() == URLRequestStatus::CANCELED) {
51 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
52 } else {
53 DLOG(WARNING) << "Could not reach Google Accounts servers: errno "
54 << status.error();
55 return GoogleServiceAuthError::FromConnectionError(status.error());
56 }
57 }
58
59 static URLFetcher* CreateFetcher(URLRequestContextGetter* getter,
60 const GURL& url,
61 const std::string& body,
62 URLFetcherDelegate* delegate) {
63 bool empty_body = body.empty();
64 URLFetcher* result = net::URLFetcher::Create(
65 0, url,
66 empty_body ? URLFetcher::GET : URLFetcher::POST,
67 delegate);
68
69 result->SetRequestContext(getter);
70 result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
71 net::LOAD_DO_NOT_SAVE_COOKIES);
72
73 if (!empty_body)
74 result->SetUploadData("application/x-www-form-urlencoded", body);
75
76 return result;
77 }
78 } // namespace
79
80 OAuth2AccessTokenFetcher::OAuth2AccessTokenFetcher(
81 OAuth2AccessTokenConsumer* consumer,
82 URLRequestContextGetter* getter)
83 : consumer_(consumer),
84 getter_(getter),
85 state_(INITIAL) { }
86
87 OAuth2AccessTokenFetcher::~OAuth2AccessTokenFetcher() { }
88
89 void OAuth2AccessTokenFetcher::CancelRequest() {
90 fetcher_.reset();
91 }
92
93 void OAuth2AccessTokenFetcher::Start(const std::string& client_id,
94 const std::string& client_secret,
95 const std::string& refresh_token,
96 const std::vector<std::string>& scopes) {
97 client_id_ = client_id;
98 client_secret_ = client_secret;
99 refresh_token_ = refresh_token;
100 scopes_ = scopes;
101 StartGetAccessToken();
102 }
103
104 void OAuth2AccessTokenFetcher::StartGetAccessToken() {
105 CHECK_EQ(INITIAL, state_);
106 state_ = GET_ACCESS_TOKEN_STARTED;
107 fetcher_.reset(CreateFetcher(
108 getter_,
109 MakeGetAccessTokenUrl(),
110 MakeGetAccessTokenBody(
111 client_id_, client_secret_, refresh_token_, scopes_),
112 this));
113 fetcher_->Start(); // OnURLFetchComplete will be called.
114 }
115
116 void OAuth2AccessTokenFetcher::EndGetAccessToken(
117 const net::URLFetcher* source) {
118 CHECK_EQ(GET_ACCESS_TOKEN_STARTED, state_);
119 state_ = GET_ACCESS_TOKEN_DONE;
120
121 URLRequestStatus status = source->GetStatus();
122 if (!status.is_success()) {
123 OnGetTokenFailure(CreateAuthError(status));
124 return;
125 }
126
127 if (source->GetResponseCode() != net::HTTP_OK) {
128 OnGetTokenFailure(GoogleServiceAuthError(
129 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
130 return;
131 }
132
133 // The request was successfully fetched and it returned OK.
134 // Parse out the access token and the expiration time.
135 std::string access_token;
136 int expires_in;
137 if (!ParseGetAccessTokenResponse(source, &access_token, &expires_in)) {
138 DLOG(WARNING) << "Response doesn't match expected format";
139 OnGetTokenFailure(
140 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
141 return;
142 }
143 // The token will expire in |expires_in| seconds. Take a 10% error margin to
144 // prevent reusing a token too close to its expiration date.
145 OnGetTokenSuccess(
146 access_token,
147 base::Time::Now() + base::TimeDelta::FromSeconds(9 * expires_in / 10));
148 }
149
150 void OAuth2AccessTokenFetcher::OnGetTokenSuccess(
151 const std::string& access_token,
152 const base::Time& expiration_time) {
153 consumer_->OnGetTokenSuccess(access_token, expiration_time);
154 }
155
156 void OAuth2AccessTokenFetcher::OnGetTokenFailure(
157 const GoogleServiceAuthError& error) {
158 state_ = ERROR_STATE;
159 consumer_->OnGetTokenFailure(error);
160 }
161
162 void OAuth2AccessTokenFetcher::OnURLFetchComplete(
163 const net::URLFetcher* source) {
164 CHECK(source);
165 CHECK(state_ == GET_ACCESS_TOKEN_STARTED);
166 EndGetAccessToken(source);
167 }
168
169 // static
170 GURL OAuth2AccessTokenFetcher::MakeGetAccessTokenUrl() {
171 return GURL(GaiaUrls::GetInstance()->oauth2_token_url());
172 }
173
174 // static
175 std::string OAuth2AccessTokenFetcher::MakeGetAccessTokenBody(
176 const std::string& client_id,
177 const std::string& client_secret,
178 const std::string& refresh_token,
179 const std::vector<std::string>& scopes) {
180 std::string enc_client_id = net::EscapeUrlEncodedData(client_id, true);
181 std::string enc_client_secret =
182 net::EscapeUrlEncodedData(client_secret, true);
183 std::string enc_refresh_token =
184 net::EscapeUrlEncodedData(refresh_token, true);
185 if (scopes.empty()) {
186 return StringPrintf(
187 kGetAccessTokenBodyFormat,
188 enc_client_id.c_str(),
189 enc_client_secret.c_str(),
190 enc_refresh_token.c_str());
191 } else {
192 std::string scopes_string = JoinString(scopes, ' ');
193 return StringPrintf(
194 kGetAccessTokenBodyWithScopeFormat,
195 enc_client_id.c_str(),
196 enc_client_secret.c_str(),
197 enc_refresh_token.c_str(),
198 net::EscapeUrlEncodedData(scopes_string, true).c_str());
199 }
200 }
201
202 // static
203 bool OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse(
204 const net::URLFetcher* source,
205 std::string* access_token,
206 int* expires_in) {
207 CHECK(source);
208 CHECK(access_token);
209 std::string data;
210 source->GetResponseAsString(&data);
211 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
212 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY)
213 return false;
214
215 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
216 return dict->GetString(kAccessTokenKey, access_token) &&
217 dict->GetInteger(kExpiresInKey, expires_in);
218 }
OLDNEW
« no previous file with comments | « chrome/common/net/gaia/oauth2_access_token_fetcher.h ('k') | chrome/common/net/gaia/oauth2_access_token_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698