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

Side by Side Diff: chrome/common/net/gaia/oauth2_mint_token_flow.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_mint_token_flow.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/json/json_reader.h"
14 #include "base/message_loop.h"
15 #include "base/string_util.h"
16 #include "base/stringprintf.h"
17 #include "base/utf_string_conversions.h"
18 #include "base/values.h"
19 #include "chrome/common/net/gaia/gaia_urls.h"
20 #include "chrome/common/net/gaia/google_service_auth_error.h"
21 #include "net/base/escape.h"
22 #include "net/url_request/url_fetcher.h"
23 #include "net/url_request/url_request_context_getter.h"
24 #include "net/url_request/url_request_status.h"
25
26 using net::URLFetcher;
27 using net::URLRequestContextGetter;
28 using net::URLRequestStatus;
29
30 namespace {
31
32 static const char kForceValueFalse[] = "false";
33 static const char kForceValueTrue[] = "true";
34 static const char kResponseTypeValueNone[] = "none";
35 static const char kResponseTypeValueToken[] = "token";
36
37 static const char kOAuth2IssueTokenBodyFormat[] =
38 "force=%s"
39 "&response_type=%s"
40 "&scope=%s"
41 "&client_id=%s"
42 "&origin=%s";
43 static const char kIssueAdviceKey[] = "issueAdvice";
44 static const char kIssueAdviceValueAuto[] = "auto";
45 static const char kIssueAdviceValueConsent[] = "consent";
46 static const char kAccessTokenKey[] = "token";
47 static const char kConsentKey[] = "consent";
48 static const char kScopesKey[] = "scopes";
49 static const char kDescriptionKey[] = "description";
50 static const char kDetailKey[] = "detail";
51 static const char kDetailSeparators[] = "\n";
52
53 static GoogleServiceAuthError CreateAuthError(URLRequestStatus status) {
54 if (status.status() == URLRequestStatus::CANCELED) {
55 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
56 } else {
57 // TODO(munjal): Improve error handling. Currently we return connection
58 // error for even application level errors. We need to either expand the
59 // GoogleServiceAuthError enum or create a new one to report better
60 // errors.
61 DLOG(WARNING) << "Server returned error: errno " << status.error();
62 return GoogleServiceAuthError::FromConnectionError(status.error());
63 }
64 }
65
66 } // namespace
67
68 IssueAdviceInfoEntry::IssueAdviceInfoEntry() {}
69 IssueAdviceInfoEntry::~IssueAdviceInfoEntry() {}
70
71 bool IssueAdviceInfoEntry::operator ==(const IssueAdviceInfoEntry& rhs) const {
72 return description == rhs.description && details == rhs.details;
73 }
74
75 OAuth2MintTokenFlow::Parameters::Parameters() : mode(MODE_ISSUE_ADVICE) {}
76
77 OAuth2MintTokenFlow::Parameters::Parameters(
78 const std::string& rt,
79 const std::string& eid,
80 const std::string& cid,
81 const std::vector<std::string>& scopes_arg,
82 Mode mode_arg)
83 : login_refresh_token(rt),
84 extension_id(eid),
85 client_id(cid),
86 scopes(scopes_arg),
87 mode(mode_arg) {
88 }
89
90 OAuth2MintTokenFlow::Parameters::~Parameters() {}
91
92 OAuth2MintTokenFlow::OAuth2MintTokenFlow(
93 URLRequestContextGetter* context,
94 Delegate* delegate,
95 const Parameters& parameters)
96 : OAuth2ApiCallFlow(
97 context, parameters.login_refresh_token,
98 "", std::vector<std::string>()),
99 context_(context),
100 delegate_(delegate),
101 parameters_(parameters),
102 delete_when_done_(false),
103 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
104 }
105
106 OAuth2MintTokenFlow::~OAuth2MintTokenFlow() { }
107
108 void OAuth2MintTokenFlow::FireAndForget() {
109 delete_when_done_ = true;
110 Start();
111 }
112
113 void OAuth2MintTokenFlow::ReportSuccess(const std::string& access_token) {
114 scoped_ptr<OAuth2MintTokenFlow> will_delete(delete_when_done_ ? this : NULL);
115
116 if (delegate_)
117 delegate_->OnMintTokenSuccess(access_token);
118
119 // |this| may already be deleted.
120 }
121
122 void OAuth2MintTokenFlow::ReportIssueAdviceSuccess(
123 const IssueAdviceInfo& issue_advice) {
124 scoped_ptr<OAuth2MintTokenFlow> will_delete(delete_when_done_ ? this : NULL);
125
126 if (delegate_)
127 delegate_->OnIssueAdviceSuccess(issue_advice);
128
129 // |this| may already be deleted.
130 }
131
132 void OAuth2MintTokenFlow::ReportFailure(
133 const GoogleServiceAuthError& error) {
134 scoped_ptr<OAuth2MintTokenFlow> will_delete(delete_when_done_ ? this : NULL);
135
136 if (delegate_)
137 delegate_->OnMintTokenFailure(error);
138
139 // |this| may already be deleted.
140 }
141
142 GURL OAuth2MintTokenFlow::CreateApiCallUrl() {
143 return GURL(GaiaUrls::GetInstance()->oauth2_issue_token_url());
144 }
145
146 std::string OAuth2MintTokenFlow::CreateApiCallBody() {
147 const char* force_value =
148 (parameters_.mode == MODE_MINT_TOKEN_FORCE ||
149 parameters_.mode == MODE_RECORD_GRANT)
150 ? kForceValueTrue : kForceValueFalse;
151 const char* response_type_value =
152 (parameters_.mode == MODE_MINT_TOKEN_NO_FORCE ||
153 parameters_.mode == MODE_MINT_TOKEN_FORCE)
154 ? kResponseTypeValueToken : kResponseTypeValueNone;
155 return StringPrintf(
156 kOAuth2IssueTokenBodyFormat,
157 net::EscapeUrlEncodedData(force_value, true).c_str(),
158 net::EscapeUrlEncodedData(response_type_value, true).c_str(),
159 net::EscapeUrlEncodedData(
160 JoinString(parameters_.scopes, ' '), true).c_str(),
161 net::EscapeUrlEncodedData(parameters_.client_id, true).c_str(),
162 net::EscapeUrlEncodedData(parameters_.extension_id, true).c_str());
163 }
164
165 void OAuth2MintTokenFlow::ProcessApiCallSuccess(
166 const net::URLFetcher* source) {
167 // TODO(munjal): Change error code paths in this method to report an
168 // internal error.
169 std::string response_body;
170 source->GetResponseAsString(&response_body);
171 scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
172 DictionaryValue* dict = NULL;
173 if (!value.get() || !value->GetAsDictionary(&dict)) {
174 ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
175 return;
176 }
177
178 std::string issue_advice;
179 if (!dict->GetString(kIssueAdviceKey, &issue_advice)) {
180 ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
181 return;
182 }
183 if (issue_advice == kIssueAdviceValueConsent) {
184 IssueAdviceInfo issue_advice;
185 if (ParseIssueAdviceResponse(dict, &issue_advice))
186 ReportIssueAdviceSuccess(issue_advice);
187 else
188 ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
189 } else {
190 std::string access_token;
191 if (ParseMintTokenResponse(dict, &access_token))
192 ReportSuccess(access_token);
193 else
194 ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
195 }
196
197 // |this| may be deleted!
198 }
199
200 void OAuth2MintTokenFlow::ProcessApiCallFailure(
201 const net::URLFetcher* source) {
202 ReportFailure(CreateAuthError(source->GetStatus()));
203 }
204 void OAuth2MintTokenFlow::ProcessNewAccessToken(
205 const std::string& access_token) {
206 // We don't currently store new access tokens. We generate one every time.
207 // So we have nothing to do here.
208 return;
209 }
210 void OAuth2MintTokenFlow::ProcessMintAccessTokenFailure(
211 const GoogleServiceAuthError& error) {
212 ReportFailure(error);
213 }
214
215 // static
216 bool OAuth2MintTokenFlow::ParseMintTokenResponse(
217 const base::DictionaryValue* dict, std::string* access_token) {
218 CHECK(dict);
219 CHECK(access_token);
220 return dict->GetString(kAccessTokenKey, access_token);
221 }
222
223 // static
224 bool OAuth2MintTokenFlow::ParseIssueAdviceResponse(
225 const base::DictionaryValue* dict, IssueAdviceInfo* issue_advice) {
226 CHECK(dict);
227 CHECK(issue_advice);
228
229 const base::DictionaryValue* consent_dict = NULL;
230 if (!dict->GetDictionary(kConsentKey, &consent_dict))
231 return false;
232
233 const base::ListValue* scopes_list = NULL;
234 if (!consent_dict->GetList(kScopesKey, &scopes_list))
235 return false;
236
237 bool success = true;
238 for (size_t index = 0; index < scopes_list->GetSize(); ++index) {
239 const base::DictionaryValue* scopes_entry = NULL;
240 IssueAdviceInfoEntry entry;
241 string16 detail;
242 if (!scopes_list->GetDictionary(index, &scopes_entry) ||
243 !scopes_entry->GetString(kDescriptionKey, &entry.description) ||
244 !scopes_entry->GetString(kDetailKey, &detail)) {
245 success = false;
246 break;
247 }
248
249 TrimWhitespace(entry.description, TRIM_ALL, &entry.description);
250 static const string16 detail_separators = ASCIIToUTF16(kDetailSeparators);
251 Tokenize(detail, detail_separators, &entry.details);
252 for (size_t i = 0; i < entry.details.size(); i++)
253 TrimWhitespace(entry.details[i], TRIM_ALL, &entry.details[i]);
254 issue_advice->push_back(entry);
255 }
256
257 if (!success)
258 issue_advice->clear();
259
260 return success;
261 }
OLDNEW
« no previous file with comments | « chrome/common/net/gaia/oauth2_mint_token_flow.h ('k') | chrome/common/net/gaia/oauth2_mint_token_flow_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698