OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
battre
2017/04/07 08:42:27
Same here. I think that we want unittests, not int
Ramin Halavati
2017/04/07 11:33:32
Ditto.
| |
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 "components/autofill/core/browser/payments/payments_client.h" | |
6 | |
7 #include <memory> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/command_line.h" | |
12 #include "base/json/json_reader.h" | |
13 #include "base/json/json_writer.h" | |
14 #include "base/memory/ptr_util.h" | |
15 #include "base/strings/string_number_conversions.h" | |
16 #include "base/strings/string_util.h" | |
17 #include "base/strings/stringprintf.h" | |
18 #include "base/strings/utf_string_conversions.h" | |
19 #include "base/values.h" | |
20 #include "build/build_config.h" | |
21 #include "components/autofill/core/browser/autofill_data_model.h" | |
22 #include "components/autofill/core/browser/autofill_type.h" | |
23 #include "components/autofill/core/browser/credit_card.h" | |
24 #include "components/autofill/core/browser/payments/payments_request.h" | |
25 #include "components/autofill/core/browser/payments/payments_service_url.h" | |
26 #include "components/data_use_measurement/core/data_use_user_data.h" | |
27 #include "google_apis/gaia/identity_provider.h" | |
28 #include "net/base/escape.h" | |
29 #include "net/base/load_flags.h" | |
30 #include "net/http/http_status_code.h" | |
31 #include "net/traffic_annotation/network_traffic_annotation.h" | |
32 #include "net/url_request/url_fetcher.h" | |
33 #include "net/url_request/url_request_context_getter.h" | |
34 | |
35 namespace autofill { | |
36 namespace payments { | |
37 | |
38 namespace { | |
39 | |
40 const char kUnmaskCardRequestPath[] = | |
41 "payments/apis-secure/creditcardservice/getrealpan?s7e_suffix=chromewallet"; | |
42 const char kUnmaskCardRequestFormat[] = | |
43 "requestContentType=application/json; charset=utf-8&request=%s" | |
44 "&s7e_13_cvc=%s"; | |
45 | |
46 const char kGetUploadDetailsRequestPath[] = | |
47 "payments/apis/chromepaymentsservice/getdetailsforsavecard"; | |
48 | |
49 const char kUploadCardRequestPath[] = | |
50 "payments/apis-secure/chromepaymentsservice/savecard" | |
51 "?s7e_suffix=chromewallet"; | |
52 const char kUploadCardRequestFormat[] = | |
53 "requestContentType=application/json; charset=utf-8&request=%s" | |
54 "&s7e_1_pan=%s&s7e_13_cvc=%s"; | |
55 | |
56 const char kTokenServiceConsumerId[] = "wallet_client"; | |
57 const char kPaymentsOAuth2Scope[] = | |
58 "https://www.googleapis.com/auth/wallet.chrome"; | |
59 | |
60 GURL GetRequestUrl(const std::string& path) { | |
61 if (base::CommandLine::ForCurrentProcess()->HasSwitch("sync-url")) { | |
62 if (IsPaymentsProductionEnabled()) { | |
63 LOG(ERROR) << "You are using production Payments but you specified a " | |
64 "--sync-url. You likely want to disable the sync sandbox " | |
65 "or switch to sandbox Payments. Both are controlled in " | |
66 "about:flags."; | |
67 } | |
68 } else if (!IsPaymentsProductionEnabled()) { | |
69 LOG(ERROR) << "You are using sandbox Payments but you didn't specify a " | |
70 "--sync-url. You likely want to enable the sync sandbox " | |
71 "or switch to production Payments. Both are controlled in " | |
72 "about:flags."; | |
73 } | |
74 | |
75 return GetBaseSecureUrl().Resolve(path); | |
76 } | |
77 | |
78 std::unique_ptr<base::DictionaryValue> BuildRiskDictionary( | |
79 const std::string& encoded_risk_data) { | |
80 std::unique_ptr<base::DictionaryValue> risk_data(new base::DictionaryValue()); | |
81 #if defined(OS_IOS) | |
82 // Browser fingerprinting is not available on iOS. Instead, we generate | |
83 // RiskAdvisoryData. | |
84 risk_data->SetString("message_type", "RISK_ADVISORY_DATA"); | |
85 risk_data->SetString("encoding_type", "BASE_64_URL"); | |
86 #else | |
87 risk_data->SetString("message_type", "BROWSER_NATIVE_FINGERPRINTING"); | |
88 risk_data->SetString("encoding_type", "BASE_64"); | |
89 #endif | |
90 | |
91 risk_data->SetString("value", encoded_risk_data); | |
92 | |
93 return risk_data; | |
94 } | |
95 | |
96 void SetStringIfNotEmpty(const AutofillDataModel& profile, | |
97 const ServerFieldType& type, | |
98 const std::string& app_locale, | |
99 const std::string& path, | |
100 base::DictionaryValue* dictionary) { | |
101 const base::string16 value = profile.GetInfo(AutofillType(type), app_locale); | |
102 if (!value.empty()) | |
103 dictionary->SetString(path, value); | |
104 } | |
105 | |
106 void AppendStringIfNotEmpty(const AutofillProfile& profile, | |
107 const ServerFieldType& type, | |
108 const std::string& app_locale, | |
109 base::ListValue* list) { | |
110 const base::string16 value = profile.GetInfo(AutofillType(type), app_locale); | |
111 if (!value.empty()) | |
112 list->AppendString(value); | |
113 } | |
114 | |
115 // Returns a dictionary with the structure expected by Payments RPCs, containing | |
116 // each of the fields in |profile|, formatted according to |app_locale|. If | |
117 // |include_non_location_data| is false, the name and phone number in |profile| | |
118 // are not included. | |
119 std::unique_ptr<base::DictionaryValue> BuildAddressDictionary( | |
120 const AutofillProfile& profile, | |
121 const std::string& app_locale, | |
122 bool include_non_location_data) { | |
123 std::unique_ptr<base::DictionaryValue> postal_address( | |
124 new base::DictionaryValue()); | |
125 | |
126 if (include_non_location_data) { | |
127 SetStringIfNotEmpty(profile, NAME_FULL, app_locale, | |
128 PaymentsClient::kRecipientName, postal_address.get()); | |
129 } | |
130 | |
131 std::unique_ptr<base::ListValue> address_lines(new base::ListValue()); | |
132 AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE1, app_locale, | |
133 address_lines.get()); | |
134 AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE2, app_locale, | |
135 address_lines.get()); | |
136 AppendStringIfNotEmpty(profile, ADDRESS_HOME_LINE3, app_locale, | |
137 address_lines.get()); | |
138 if (!address_lines->empty()) | |
139 postal_address->Set("address_line", std::move(address_lines)); | |
140 | |
141 SetStringIfNotEmpty(profile, ADDRESS_HOME_CITY, app_locale, "locality_name", | |
142 postal_address.get()); | |
143 SetStringIfNotEmpty(profile, ADDRESS_HOME_STATE, app_locale, | |
144 "administrative_area_name", postal_address.get()); | |
145 SetStringIfNotEmpty(profile, ADDRESS_HOME_ZIP, app_locale, | |
146 "postal_code_number", postal_address.get()); | |
147 | |
148 // Use GetRawInfo to get a country code instead of the country name: | |
149 const base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); | |
150 if (!country_code.empty()) | |
151 postal_address->SetString("country_name_code", country_code); | |
152 | |
153 std::unique_ptr<base::DictionaryValue> address(new base::DictionaryValue()); | |
154 address->Set("postal_address", std::move(postal_address)); | |
155 | |
156 if (include_non_location_data) { | |
157 SetStringIfNotEmpty(profile, PHONE_HOME_WHOLE_NUMBER, app_locale, | |
158 PaymentsClient::kPhoneNumber, address.get()); | |
159 } | |
160 | |
161 return address; | |
162 } | |
163 | |
164 class UnmaskCardRequest : public PaymentsRequest { | |
165 public: | |
166 UnmaskCardRequest(const PaymentsClient::UnmaskRequestDetails& request_details) | |
167 : request_details_(request_details) { | |
168 DCHECK( | |
169 CreditCard::MASKED_SERVER_CARD == request_details.card.record_type() || | |
170 CreditCard::FULL_SERVER_CARD == request_details.card.record_type()); | |
171 } | |
172 ~UnmaskCardRequest() override {} | |
173 | |
174 std::string GetRequestUrlPath() override { return kUnmaskCardRequestPath; } | |
175 | |
176 std::string GetRequestContentType() override { | |
177 return "application/x-www-form-urlencoded"; | |
178 } | |
179 | |
180 std::string GetRequestContent() override { | |
181 base::DictionaryValue request_dict; | |
182 request_dict.SetString("encrypted_cvc", "__param:s7e_13_cvc"); | |
183 request_dict.SetString("credit_card_id", request_details_.card.server_id()); | |
184 request_dict.Set("risk_data_encoded", | |
185 BuildRiskDictionary(request_details_.risk_data)); | |
186 request_dict.Set("context", base::MakeUnique<base::DictionaryValue>()); | |
187 | |
188 int value = 0; | |
189 if (base::StringToInt(request_details_.user_response.exp_month, &value)) | |
190 request_dict.SetInteger("expiration_month", value); | |
191 if (base::StringToInt(request_details_.user_response.exp_year, &value)) | |
192 request_dict.SetInteger("expiration_year", value); | |
193 | |
194 std::string json_request; | |
195 base::JSONWriter::Write(request_dict, &json_request); | |
196 std::string request_content = base::StringPrintf( | |
197 kUnmaskCardRequestFormat, | |
198 net::EscapeUrlEncodedData(json_request, true).c_str(), | |
199 net::EscapeUrlEncodedData( | |
200 base::UTF16ToASCII(request_details_.user_response.cvc), true) | |
201 .c_str()); | |
202 VLOG(3) << "getrealpan request body: " << request_content; | |
203 return request_content; | |
204 } | |
205 | |
206 void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override { | |
207 response->GetString("pan", &real_pan_); | |
208 } | |
209 | |
210 bool IsResponseComplete() override { return !real_pan_.empty(); } | |
211 | |
212 void RespondToDelegate(PaymentsClientDelegate* delegate, | |
213 AutofillClient::PaymentsRpcResult result) override { | |
214 delegate->OnDidGetRealPan(result, real_pan_); | |
215 } | |
216 | |
217 private: | |
218 PaymentsClient::UnmaskRequestDetails request_details_; | |
219 std::string real_pan_; | |
220 }; | |
221 | |
222 class GetUploadDetailsRequest : public PaymentsRequest { | |
223 public: | |
224 GetUploadDetailsRequest(const std::vector<AutofillProfile>& addresses, | |
225 const std::string& app_locale) | |
226 : addresses_(addresses), app_locale_(app_locale) {} | |
227 ~GetUploadDetailsRequest() override {} | |
228 | |
229 std::string GetRequestUrlPath() override { | |
230 return kGetUploadDetailsRequestPath; | |
231 } | |
232 | |
233 std::string GetRequestContentType() override { return "application/json"; } | |
234 | |
235 std::string GetRequestContent() override { | |
236 base::DictionaryValue request_dict; | |
237 std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue()); | |
238 context->SetString("language_code", app_locale_); | |
239 request_dict.Set("context", std::move(context)); | |
240 | |
241 std::unique_ptr<base::ListValue> addresses(new base::ListValue()); | |
242 for (const AutofillProfile& profile : addresses_) { | |
243 // These addresses are used by Payments to (1) accurately determine the | |
244 // user's country in order to show the correct legal documents and (2) to | |
245 // verify that the addresses are valid for their purposes so that we don't | |
246 // offer save in a case where it would definitely fail (e.g. P.O. boxes). | |
247 // The final parameter directs BuildAddressDictionary to omit names and | |
248 // phone numbers, which aren't useful for these purposes. | |
249 addresses->Append(BuildAddressDictionary(profile, app_locale_, false)); | |
250 } | |
251 request_dict.Set("address", std::move(addresses)); | |
252 | |
253 std::string request_content; | |
254 base::JSONWriter::Write(request_dict, &request_content); | |
255 VLOG(3) << "getdetailsforsavecard request body: " << request_content; | |
256 return request_content; | |
257 } | |
258 | |
259 void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override { | |
260 response->GetString("context_token", &context_token_); | |
261 base::DictionaryValue* unowned_legal_message; | |
262 if (response->GetDictionary("legal_message", &unowned_legal_message)) | |
263 legal_message_ = unowned_legal_message->CreateDeepCopy(); | |
264 } | |
265 | |
266 bool IsResponseComplete() override { | |
267 return !context_token_.empty() && legal_message_; | |
268 } | |
269 | |
270 void RespondToDelegate(PaymentsClientDelegate* delegate, | |
271 AutofillClient::PaymentsRpcResult result) override { | |
272 delegate->OnDidGetUploadDetails(result, context_token_, | |
273 std::move(legal_message_)); | |
274 } | |
275 | |
276 private: | |
277 std::vector<AutofillProfile> addresses_; | |
278 std::string app_locale_; | |
279 base::string16 context_token_; | |
280 std::unique_ptr<base::DictionaryValue> legal_message_; | |
281 }; | |
282 | |
283 class UploadCardRequest : public PaymentsRequest { | |
284 public: | |
285 UploadCardRequest(const PaymentsClient::UploadRequestDetails& request_details) | |
286 : request_details_(request_details) {} | |
287 ~UploadCardRequest() override {} | |
288 | |
289 std::string GetRequestUrlPath() override { return kUploadCardRequestPath; } | |
290 | |
291 std::string GetRequestContentType() override { | |
292 return "application/x-www-form-urlencoded"; | |
293 } | |
294 | |
295 std::string GetRequestContent() override { | |
296 base::DictionaryValue request_dict; | |
297 request_dict.SetString("encrypted_pan", "__param:s7e_1_pan"); | |
298 request_dict.SetString("encrypted_cvc", "__param:s7e_13_cvc"); | |
299 request_dict.Set("risk_data_encoded", | |
300 BuildRiskDictionary(request_details_.risk_data)); | |
301 | |
302 const std::string& app_locale = request_details_.app_locale; | |
303 std::unique_ptr<base::DictionaryValue> context(new base::DictionaryValue()); | |
304 context->SetString("language_code", app_locale); | |
305 request_dict.Set("context", std::move(context)); | |
306 | |
307 SetStringIfNotEmpty(request_details_.card, CREDIT_CARD_NAME_FULL, | |
308 app_locale, "cardholder_name", &request_dict); | |
309 | |
310 std::unique_ptr<base::ListValue> addresses(new base::ListValue()); | |
311 for (const AutofillProfile& profile : request_details_.profiles) { | |
312 addresses->Append(BuildAddressDictionary(profile, app_locale, true)); | |
313 } | |
314 request_dict.Set("address", std::move(addresses)); | |
315 | |
316 request_dict.SetString("context_token", request_details_.context_token); | |
317 | |
318 int value = 0; | |
319 const base::string16 exp_month = request_details_.card.GetInfo( | |
320 AutofillType(CREDIT_CARD_EXP_MONTH), app_locale); | |
321 const base::string16 exp_year = request_details_.card.GetInfo( | |
322 AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), app_locale); | |
323 if (base::StringToInt(exp_month, &value)) | |
324 request_dict.SetInteger("expiration_month", value); | |
325 if (base::StringToInt(exp_year, &value)) | |
326 request_dict.SetInteger("expiration_year", value); | |
327 | |
328 const base::string16 pan = request_details_.card.GetInfo( | |
329 AutofillType(CREDIT_CARD_NUMBER), app_locale); | |
330 std::string json_request; | |
331 base::JSONWriter::Write(request_dict, &json_request); | |
332 std::string request_content = base::StringPrintf( | |
333 kUploadCardRequestFormat, | |
334 net::EscapeUrlEncodedData(json_request, true).c_str(), | |
335 net::EscapeUrlEncodedData(base::UTF16ToASCII(pan), true).c_str(), | |
336 net::EscapeUrlEncodedData(base::UTF16ToASCII(request_details_.cvc), | |
337 true) | |
338 .c_str()); | |
339 VLOG(3) << "savecard request body: " << request_content; | |
340 return request_content; | |
341 } | |
342 | |
343 void ParseResponse(std::unique_ptr<base::DictionaryValue> response) override { | |
344 } | |
345 | |
346 bool IsResponseComplete() override { return true; } | |
347 | |
348 void RespondToDelegate(PaymentsClientDelegate* delegate, | |
349 AutofillClient::PaymentsRpcResult result) override { | |
350 delegate->OnDidUploadCard(result); | |
351 } | |
352 | |
353 private: | |
354 PaymentsClient::UploadRequestDetails request_details_; | |
355 }; | |
356 | |
357 } // namespace | |
358 | |
359 const char PaymentsClient::kRecipientName[] = "recipient_name"; | |
360 const char PaymentsClient::kPhoneNumber[] = "phone_number"; | |
361 | |
362 PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails() {} | |
363 PaymentsClient::UnmaskRequestDetails::~UnmaskRequestDetails() {} | |
364 | |
365 PaymentsClient::UploadRequestDetails::UploadRequestDetails() {} | |
366 PaymentsClient::UploadRequestDetails::UploadRequestDetails( | |
367 const UploadRequestDetails& other) = default; | |
368 PaymentsClient::UploadRequestDetails::~UploadRequestDetails() {} | |
369 | |
370 PaymentsClient::PaymentsClient(net::URLRequestContextGetter* context_getter, | |
371 PaymentsClientDelegate* delegate) | |
372 : OAuth2TokenService::Consumer(kTokenServiceConsumerId), | |
373 context_getter_(context_getter), | |
374 delegate_(delegate), | |
375 has_retried_authorization_(false), | |
376 weak_ptr_factory_(this) { | |
377 DCHECK(delegate); | |
378 } | |
379 | |
380 PaymentsClient::~PaymentsClient() {} | |
381 | |
382 void PaymentsClient::Prepare() { | |
383 if (access_token_.empty()) | |
384 StartTokenFetch(false); | |
385 } | |
386 | |
387 void PaymentsClient::UnmaskCard( | |
388 const PaymentsClient::UnmaskRequestDetails& request_details) { | |
389 IssueRequest(base::MakeUnique<UnmaskCardRequest>(request_details), true); | |
390 } | |
391 | |
392 void PaymentsClient::GetUploadDetails( | |
393 const std::vector<AutofillProfile>& addresses, | |
394 const std::string& app_locale) { | |
395 IssueRequest(base::MakeUnique<GetUploadDetailsRequest>(addresses, app_locale), | |
396 false); | |
397 } | |
398 | |
399 void PaymentsClient::UploadCard( | |
400 const PaymentsClient::UploadRequestDetails& request_details) { | |
401 IssueRequest(base::MakeUnique<UploadCardRequest>(request_details), true); | |
402 } | |
403 | |
404 void PaymentsClient::IssueRequest(std::unique_ptr<PaymentsRequest> request, | |
405 bool authenticate) { | |
406 request_ = std::move(request); | |
407 has_retried_authorization_ = false; | |
408 InitializeUrlFetcher(); | |
409 | |
410 if (!authenticate) | |
411 url_fetcher_->Start(); | |
412 else if (access_token_.empty()) | |
413 StartTokenFetch(false); | |
414 else | |
415 SetOAuth2TokenAndStartRequest(); | |
416 } | |
417 | |
418 void PaymentsClient::InitializeUrlFetcher() { | |
419 net::NetworkTrafficAnnotationTag traffic_annotation = | |
420 net::DefineNetworkTrafficAnnotation("payments_sync_cards", R"( | |
421 semantics { | |
422 sender: "Payments" | |
423 description: | |
424 "This service communicates with Google Payments servers to upload " | |
425 "(save) or receive the user's credit card info." | |
426 trigger: | |
427 "Requests are triggered by a user action, such as selecting a " | |
428 "masked server card from Chromium's credit card autofill dropdown, " | |
429 "submitting a form which has credit card information, or accepting " | |
430 "the prompt to save a credit card to Payments servers." | |
431 data: | |
432 "In case of save, a protocol buffer containing relevant address " | |
433 "and credit card information which should be saved in Google " | |
434 "Payments servers, along with user credentials. In case of load, a " | |
435 "protocol buffer containing the id of the credit card to unmask, " | |
436 "an encrypted cvc value, an optional updated card expiration date, " | |
437 "and user credentials." | |
438 destination: GOOGLE_OWNED_SERVICE | |
439 } | |
440 policy { | |
441 cookies_allowed: false | |
442 setting: | |
443 "Users can enable or disable this feature in Chromium settings by " | |
444 "toggling 'Credit cards and addresses using Google Payments', " | |
445 "under 'Advanced sync settings...'. This feature is enabled by " | |
446 "default." | |
447 chrome_policy { | |
448 AutoFillEnabled { | |
449 policy_options {mode: MANDATORY} | |
450 AutoFillEnabled: false | |
451 } | |
452 } | |
453 })"); | |
454 url_fetcher_ = | |
455 net::URLFetcher::Create(0, GetRequestUrl(request_->GetRequestUrlPath()), | |
456 net::URLFetcher::POST, this, traffic_annotation); | |
457 | |
458 data_use_measurement::DataUseUserData::AttachToFetcher( | |
459 url_fetcher_.get(), data_use_measurement::DataUseUserData::AUTOFILL); | |
460 url_fetcher_->SetRequestContext(context_getter_.get()); | |
461 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | |
462 net::LOAD_DO_NOT_SEND_COOKIES | | |
463 net::LOAD_DISABLE_CACHE); | |
464 | |
465 url_fetcher_->SetUploadData(request_->GetRequestContentType(), | |
466 request_->GetRequestContent()); | |
467 } | |
468 | |
469 void PaymentsClient::CancelRequest() { | |
470 request_.reset(); | |
471 url_fetcher_.reset(); | |
472 access_token_request_.reset(); | |
473 access_token_.clear(); | |
474 has_retried_authorization_ = false; | |
475 } | |
476 | |
477 void PaymentsClient::OnURLFetchComplete(const net::URLFetcher* source) { | |
478 DCHECK_EQ(source, url_fetcher_.get()); | |
479 | |
480 // |url_fetcher_|, which is aliased to |source|, might continue to be used in | |
481 // this method, but should be freed once control leaves the method. | |
482 std::unique_ptr<net::URLFetcher> scoped_url_fetcher(std::move(url_fetcher_)); | |
483 std::unique_ptr<base::DictionaryValue> response_dict; | |
484 int response_code = source->GetResponseCode(); | |
485 std::string data; | |
486 source->GetResponseAsString(&data); | |
487 VLOG(2) << "Got data: " << data; | |
488 | |
489 AutofillClient::PaymentsRpcResult result = AutofillClient::SUCCESS; | |
490 | |
491 switch (response_code) { | |
492 // Valid response. | |
493 case net::HTTP_OK: { | |
494 std::string error_code; | |
495 std::unique_ptr<base::Value> message_value = base::JSONReader::Read(data); | |
496 if (message_value.get() && | |
497 message_value->IsType(base::Value::Type::DICTIONARY)) { | |
498 response_dict.reset( | |
499 static_cast<base::DictionaryValue*>(message_value.release())); | |
500 response_dict->GetString("error.code", &error_code); | |
501 request_->ParseResponse(std::move(response_dict)); | |
502 } | |
503 | |
504 if (base::LowerCaseEqualsASCII(error_code, "internal")) | |
505 result = AutofillClient::TRY_AGAIN_FAILURE; | |
506 else if (!error_code.empty() || !request_->IsResponseComplete()) | |
507 result = AutofillClient::PERMANENT_FAILURE; | |
508 | |
509 break; | |
510 } | |
511 | |
512 case net::HTTP_UNAUTHORIZED: { | |
513 if (has_retried_authorization_) { | |
514 result = AutofillClient::PERMANENT_FAILURE; | |
515 break; | |
516 } | |
517 has_retried_authorization_ = true; | |
518 | |
519 InitializeUrlFetcher(); | |
520 StartTokenFetch(true); | |
521 return; | |
522 } | |
523 | |
524 // TODO(estade): is this actually how network connectivity issues are | |
525 // reported? | |
526 case net::HTTP_REQUEST_TIMEOUT: { | |
527 result = AutofillClient::NETWORK_ERROR; | |
528 break; | |
529 } | |
530 | |
531 // Handle anything else as a generic (permanent) failure. | |
532 default: { | |
533 result = AutofillClient::PERMANENT_FAILURE; | |
534 break; | |
535 } | |
536 } | |
537 | |
538 if (result != AutofillClient::SUCCESS) { | |
539 VLOG(1) << "Payments returned error: " << response_code | |
540 << " with data: " << data; | |
541 } | |
542 | |
543 request_->RespondToDelegate(delegate_, result); | |
544 } | |
545 | |
546 void PaymentsClient::OnGetTokenSuccess( | |
547 const OAuth2TokenService::Request* request, | |
548 const std::string& access_token, | |
549 const base::Time& expiration_time) { | |
550 DCHECK_EQ(request, access_token_request_.get()); | |
551 access_token_ = access_token; | |
552 if (url_fetcher_) | |
553 SetOAuth2TokenAndStartRequest(); | |
554 | |
555 access_token_request_.reset(); | |
556 } | |
557 | |
558 void PaymentsClient::OnGetTokenFailure( | |
559 const OAuth2TokenService::Request* request, | |
560 const GoogleServiceAuthError& error) { | |
561 DCHECK_EQ(request, access_token_request_.get()); | |
562 VLOG(1) << "Unhandled OAuth2 error: " << error.ToString(); | |
563 if (url_fetcher_) { | |
564 url_fetcher_.reset(); | |
565 request_->RespondToDelegate(delegate_, AutofillClient::PERMANENT_FAILURE); | |
566 } | |
567 access_token_request_.reset(); | |
568 } | |
569 | |
570 void PaymentsClient::StartTokenFetch(bool invalidate_old) { | |
571 // We're still waiting for the last request to come back. | |
572 if (!invalidate_old && access_token_request_) | |
573 return; | |
574 | |
575 OAuth2TokenService::ScopeSet payments_scopes; | |
576 payments_scopes.insert(kPaymentsOAuth2Scope); | |
577 IdentityProvider* identity = delegate_->GetIdentityProvider(); | |
578 if (invalidate_old) { | |
579 DCHECK(!access_token_.empty()); | |
580 identity->GetTokenService()->InvalidateAccessToken( | |
581 identity->GetActiveAccountId(), payments_scopes, access_token_); | |
582 } | |
583 access_token_.clear(); | |
584 access_token_request_ = identity->GetTokenService()->StartRequest( | |
585 identity->GetActiveAccountId(), payments_scopes, this); | |
586 } | |
587 | |
588 void PaymentsClient::SetOAuth2TokenAndStartRequest() { | |
589 url_fetcher_->AddExtraRequestHeader(net::HttpRequestHeaders::kAuthorization + | |
590 std::string(": Bearer ") + access_token_); | |
591 | |
592 url_fetcher_->Start(); | |
593 } | |
594 | |
595 } // namespace payments | |
596 } // namespace autofill | |
OLD | NEW |