OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/net/gaia/oauth2_access_token_fetcher.h" | 5 #include "chrome/common/net/gaia/oauth2_access_token_fetcher.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
| 9 #include <vector> |
9 | 10 |
10 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 12 #include "base/string_util.h" |
11 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
12 #include "base/values.h" | 14 #include "base/values.h" |
13 #include "chrome/common/net/gaia/gaia_urls.h" | 15 #include "chrome/common/net/gaia/gaia_urls.h" |
14 #include "chrome/common/net/gaia/google_service_auth_error.h" | 16 #include "chrome/common/net/gaia/google_service_auth_error.h" |
15 #include "chrome/common/net/http_return.h" | 17 #include "chrome/common/net/http_return.h" |
16 #include "net/base/escape.h" | 18 #include "net/base/escape.h" |
17 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
18 #include "net/url_request/url_request_context_getter.h" | 20 #include "net/url_request/url_request_context_getter.h" |
19 #include "net/url_request/url_request_status.h" | 21 #include "net/url_request/url_request_status.h" |
20 | 22 |
21 using content::URLFetcher; | 23 using content::URLFetcher; |
22 using content::URLFetcherDelegate; | 24 using content::URLFetcherDelegate; |
23 using net::ResponseCookies; | 25 using net::ResponseCookies; |
24 using net::URLRequestContextGetter; | 26 using net::URLRequestContextGetter; |
25 using net::URLRequestStatus; | 27 using net::URLRequestStatus; |
26 | 28 |
27 namespace { | 29 namespace { |
28 static const char kGetAccessTokenBodyFormat[] = | 30 static const char kGetAccessTokenBodyFormat[] = |
29 "client_id=%s&" | 31 "client_id=%s&" |
30 "client_secret=%s" | 32 "client_secret=%s&" |
31 "grant_type=refresh_token&" | 33 "grant_type=refresh_token&" |
32 "refresh_token=%s"; | 34 "refresh_token=%s"; |
33 | 35 |
| 36 static const char kGetAccessTokenBodyWithScopeFormat[] = |
| 37 "client_id=%s&" |
| 38 "client_secret=%s&" |
| 39 "grant_type=refresh_token&" |
| 40 "refresh_token=%s&" |
| 41 "scope=%s"; |
| 42 |
34 static const char kAccessTokenKey[] = "access_token"; | 43 static const char kAccessTokenKey[] = "access_token"; |
35 | 44 |
36 static bool GetStringFromDictionary(const DictionaryValue* dict, | 45 static bool GetStringFromDictionary(const DictionaryValue* dict, |
37 const std::string& key, | 46 const std::string& key, |
38 std::string* value) { | 47 std::string* value) { |
39 Value* json_value; | 48 Value* json_value; |
40 if (!dict->Get(key, &json_value)) | 49 if (!dict->Get(key, &json_value)) |
41 return false; | 50 return false; |
42 if (json_value->GetType() != base::Value::TYPE_STRING) | 51 if (json_value->GetType() != base::Value::TYPE_STRING) |
43 return false; | 52 return false; |
(...skipping 30 matching lines...) Expand all Loading... |
74 | 83 |
75 if (!empty_body) | 84 if (!empty_body) |
76 result->SetUploadData("application/x-www-form-urlencoded", body); | 85 result->SetUploadData("application/x-www-form-urlencoded", body); |
77 | 86 |
78 return result; | 87 return result; |
79 } | 88 } |
80 } // namespace | 89 } // namespace |
81 | 90 |
82 OAuth2AccessTokenFetcher::OAuth2AccessTokenFetcher( | 91 OAuth2AccessTokenFetcher::OAuth2AccessTokenFetcher( |
83 OAuth2AccessTokenConsumer* consumer, | 92 OAuth2AccessTokenConsumer* consumer, |
84 URLRequestContextGetter* getter, | 93 URLRequestContextGetter* getter) |
85 const std::string& source) | |
86 : consumer_(consumer), | 94 : consumer_(consumer), |
87 getter_(getter), | 95 getter_(getter), |
88 source_(source), | |
89 state_(INITIAL) { } | 96 state_(INITIAL) { } |
90 | 97 |
91 OAuth2AccessTokenFetcher::~OAuth2AccessTokenFetcher() { } | 98 OAuth2AccessTokenFetcher::~OAuth2AccessTokenFetcher() { } |
92 | 99 |
93 void OAuth2AccessTokenFetcher::CancelRequest() { | 100 void OAuth2AccessTokenFetcher::CancelRequest() { |
94 fetcher_.reset(); | 101 fetcher_.reset(); |
95 } | 102 } |
96 | 103 |
97 void OAuth2AccessTokenFetcher::Start(const std::string& client_id, | 104 void OAuth2AccessTokenFetcher::Start(const std::string& client_id, |
98 const std::string& client_secret, | 105 const std::string& client_secret, |
99 const std::string& refresh_token) { | 106 const std::string& refresh_token, |
| 107 const std::vector<std::string>& scopes) { |
100 client_id_ = client_id; | 108 client_id_ = client_id; |
101 client_secret_ = client_secret; | 109 client_secret_ = client_secret; |
102 refresh_token_ = refresh_token; | 110 refresh_token_ = refresh_token; |
| 111 scopes_ = scopes; |
103 StartGetAccessToken(); | 112 StartGetAccessToken(); |
104 } | 113 } |
105 | 114 |
106 void OAuth2AccessTokenFetcher::StartGetAccessToken() { | 115 void OAuth2AccessTokenFetcher::StartGetAccessToken() { |
107 CHECK_EQ(INITIAL, state_); | 116 CHECK_EQ(INITIAL, state_); |
108 state_ = GET_ACCESS_TOKEN_STARTED; | 117 state_ = GET_ACCESS_TOKEN_STARTED; |
109 fetcher_.reset(CreateFetcher( | 118 fetcher_.reset(CreateFetcher( |
110 getter_, | 119 getter_, |
111 MakeGetAccessTokenUrl(), | 120 MakeGetAccessTokenUrl(), |
112 MakeGetAccessTokenBody(client_id_, client_secret_, refresh_token_), | 121 MakeGetAccessTokenBody( |
| 122 client_id_, client_secret_, refresh_token_, scopes_), |
113 this)); | 123 this)); |
114 fetcher_->Start(); // OnURLFetchComplete will be called. | 124 fetcher_->Start(); // OnURLFetchComplete will be called. |
115 } | 125 } |
116 | 126 |
117 void OAuth2AccessTokenFetcher::EndGetAccessToken(const URLFetcher* source) { | 127 void OAuth2AccessTokenFetcher::EndGetAccessToken(const URLFetcher* source) { |
118 CHECK_EQ(GET_ACCESS_TOKEN_STARTED, state_); | 128 CHECK_EQ(GET_ACCESS_TOKEN_STARTED, state_); |
119 state_ = GET_ACCESS_TOKEN_DONE; | 129 state_ = GET_ACCESS_TOKEN_DONE; |
120 | 130 |
121 URLRequestStatus status = source->GetStatus(); | 131 URLRequestStatus status = source->GetStatus(); |
122 if (!status.is_success()) { | 132 if (!status.is_success()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 165 |
156 // static | 166 // static |
157 GURL OAuth2AccessTokenFetcher::MakeGetAccessTokenUrl() { | 167 GURL OAuth2AccessTokenFetcher::MakeGetAccessTokenUrl() { |
158 return GURL(GaiaUrls::GetInstance()->oauth2_token_url()); | 168 return GURL(GaiaUrls::GetInstance()->oauth2_token_url()); |
159 } | 169 } |
160 | 170 |
161 // static | 171 // static |
162 std::string OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( | 172 std::string OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( |
163 const std::string& client_id, | 173 const std::string& client_id, |
164 const std::string& client_secret, | 174 const std::string& client_secret, |
165 const std::string& refresh_token) { | 175 const std::string& refresh_token, |
166 return StringPrintf( | 176 const std::vector<std::string>& scopes) { |
167 kGetAccessTokenBodyFormat, | 177 std::string enc_client_id = net::EscapeUrlEncodedData(client_id, true); |
168 net::EscapeUrlEncodedData(client_id, true).c_str(), | 178 std::string enc_client_secret = |
169 net::EscapeUrlEncodedData(client_secret, true).c_str(), | 179 net::EscapeUrlEncodedData(client_secret, true); |
170 net::EscapeUrlEncodedData(refresh_token, true).c_str()); | 180 std::string enc_refresh_token = |
| 181 net::EscapeUrlEncodedData(refresh_token, true); |
| 182 if (scopes.empty()) { |
| 183 return StringPrintf( |
| 184 kGetAccessTokenBodyFormat, |
| 185 enc_client_id.c_str(), |
| 186 enc_client_secret.c_str(), |
| 187 enc_refresh_token.c_str()); |
| 188 } else { |
| 189 std::string scopes_string = JoinString(scopes, ','); |
| 190 return StringPrintf( |
| 191 kGetAccessTokenBodyWithScopeFormat, |
| 192 enc_client_id.c_str(), |
| 193 enc_client_secret.c_str(), |
| 194 enc_refresh_token.c_str(), |
| 195 net::EscapeUrlEncodedData(scopes_string, true).c_str()); |
| 196 } |
171 } | 197 } |
172 | 198 |
173 // static | 199 // static |
174 bool OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( | 200 bool OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( |
175 const URLFetcher* source, | 201 const URLFetcher* source, |
176 std::string* access_token) { | 202 std::string* access_token) { |
177 CHECK(source); | 203 CHECK(source); |
178 CHECK(access_token); | 204 CHECK(access_token); |
179 std::string data; | 205 std::string data; |
180 source->GetResponseAsString(&data); | 206 source->GetResponseAsString(&data); |
181 base::JSONReader reader; | 207 base::JSONReader reader; |
182 scoped_ptr<base::Value> value(reader.Read(data, false)); | 208 scoped_ptr<base::Value> value(reader.Read(data, false)); |
183 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY) | 209 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY) |
184 return false; | 210 return false; |
185 | 211 |
186 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); | 212 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); |
187 return GetStringFromDictionary(dict, kAccessTokenKey, access_token); | 213 return GetStringFromDictionary(dict, kAccessTokenKey, access_token); |
188 } | 214 } |
OLD | NEW |