OLD | NEW |
| (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/browser/autofill/wallet/wallet_client.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/json/json_reader.h" | |
9 #include "base/json/json_writer.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/string_util.h" | |
13 #include "chrome/browser/autofill/wallet/cart.h" | |
14 #include "chrome/browser/autofill/wallet/instrument.h" | |
15 #include "chrome/browser/autofill/wallet/wallet_address.h" | |
16 #include "chrome/browser/autofill/wallet/wallet_client_observer.h" | |
17 #include "chrome/browser/autofill/wallet/wallet_items.h" | |
18 #include "chrome/browser/autofill/wallet/wallet_service_url.h" | |
19 #include "crypto/random.h" | |
20 #include "google_apis/google_api_keys.h" | |
21 #include "googleurl/src/gurl.h" | |
22 #include "net/http/http_status_code.h" | |
23 #include "net/url_request/url_fetcher.h" | |
24 #include "net/url_request/url_request_context_getter.h" | |
25 | |
26 namespace autofill { | |
27 namespace wallet { | |
28 | |
29 namespace { | |
30 | |
31 const char kJsonMimeType[] = "application/json"; | |
32 const size_t kOneTimePadLength = 6; | |
33 | |
34 std::string AutocheckoutStatusToString(AutocheckoutStatus status) { | |
35 switch (status) { | |
36 case MISSING_FIELDMAPPING: | |
37 return "MISSING_FIELDMAPPING"; | |
38 case MISSING_ADVANCE: | |
39 return "MISSING_ADVANCE"; | |
40 case CANNOT_PROCEED: | |
41 return "CANNOT_PROCEED"; | |
42 case SUCCESS: | |
43 // SUCCESS cannot be sent to the server as it will result in a failure. | |
44 NOTREACHED(); | |
45 return "ERROR"; | |
46 } | |
47 NOTREACHED(); | |
48 return "NOT_POSSIBLE"; | |
49 } | |
50 | |
51 std::string DialogTypeToFeatureString(autofill::DialogType dialog_type) { | |
52 switch (dialog_type) { | |
53 case DIALOG_TYPE_REQUEST_AUTOCOMPLETE: | |
54 return "REQUEST_AUTOCOMPLETE"; | |
55 case DIALOG_TYPE_AUTOCHECKOUT: | |
56 return "AUTOCHECKOUT"; | |
57 } | |
58 NOTREACHED(); | |
59 return "NOT_POSSIBLE"; | |
60 } | |
61 | |
62 // Gets and parses required actions from a SaveToWallet response. Returns | |
63 // false if any unknown required actions are seen and true otherwise. | |
64 void GetRequiredActionsForSaveToWallet( | |
65 const base::DictionaryValue& dict, | |
66 std::vector<RequiredAction>* required_actions) { | |
67 const ListValue* required_action_list; | |
68 if (!dict.GetList("required_action", &required_action_list)) | |
69 return; | |
70 | |
71 for (size_t i = 0; i < required_action_list->GetSize(); ++i) { | |
72 std::string action_string; | |
73 if (required_action_list->GetString(i, &action_string)) { | |
74 RequiredAction action = ParseRequiredActionFromString(action_string); | |
75 if (!ActionAppliesToSaveToWallet(action)) { | |
76 DLOG(ERROR) << "Response from Google wallet with bad required action:" | |
77 " \"" << action_string << "\""; | |
78 required_actions->clear(); | |
79 return; | |
80 } | |
81 required_actions->push_back(action); | |
82 } | |
83 } | |
84 } | |
85 | |
86 // Keys for JSON communication with the Online Wallet server. | |
87 const char kAcceptedLegalDocumentKey[] = "accepted_legal_document"; | |
88 const char kApiKeyKey[] = "api_key"; | |
89 const char kAuthResultKey[] = "auth_result"; | |
90 const char kCartKey[] = "cart"; | |
91 const char kEncryptedOtpKey[] = "encrypted_otp"; | |
92 const char kFeatureKey[] = "feature"; | |
93 const char kGoogleTransactionIdKey[] = "google_transaction_id"; | |
94 const char kInstrumentIdKey[] = "instrument_id"; | |
95 const char kInstrumentKey[] = "instrument"; | |
96 const char kInstrumentEscrowHandleKey[] = "instrument_escrow_handle"; | |
97 const char kInstrumentPhoneNumberKey[] = "instrument_phone_number"; | |
98 const char kMerchantDomainKey[] = "merchant_domain"; | |
99 const char kReasonKey[] = "reason"; | |
100 const char kRiskParamsKey[] = "risk_params"; | |
101 const char kSelectedAddressIdKey[] = "selected_address_id"; | |
102 const char kSelectedInstrumentIdKey[] = "selected_instrument_id"; | |
103 const char kSessionMaterialKey[] = "session_material"; | |
104 const char kShippingAddressIdKey[] = "shipping_address_id"; | |
105 const char kShippingAddressKey[] = "shipping_address"; | |
106 const char kSuccessKey[] = "success"; | |
107 const char kUpgradedBillingAddressKey[] = "upgraded_billing_address"; | |
108 const char kUpgradedInstrumentIdKey[] = "upgraded_instrument_id"; | |
109 | |
110 } // namespace | |
111 | |
112 | |
113 WalletClient::WalletClient(net::URLRequestContextGetter* context_getter, | |
114 WalletClientObserver* observer) | |
115 : context_getter_(context_getter), | |
116 observer_(observer), | |
117 request_type_(NO_PENDING_REQUEST), | |
118 one_time_pad_(kOneTimePadLength), | |
119 ALLOW_THIS_IN_INITIALIZER_LIST( | |
120 encryption_escrow_client_(context_getter, this)) { | |
121 DCHECK(context_getter_); | |
122 DCHECK(observer_); | |
123 } | |
124 | |
125 WalletClient::~WalletClient() {} | |
126 | |
127 void WalletClient::AcceptLegalDocuments( | |
128 const std::vector<std::string>& document_ids, | |
129 const std::string& google_transaction_id, | |
130 const GURL& source_url) { | |
131 if (HasRequestInProgress()) { | |
132 pending_requests_.push(base::Bind(&WalletClient::AcceptLegalDocuments, | |
133 base::Unretained(this), | |
134 document_ids, | |
135 google_transaction_id, | |
136 source_url)); | |
137 return; | |
138 } | |
139 | |
140 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
141 request_type_ = ACCEPT_LEGAL_DOCUMENTS; | |
142 | |
143 base::DictionaryValue request_dict; | |
144 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
145 request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id); | |
146 request_dict.SetString(kMerchantDomainKey, | |
147 source_url.GetWithEmptyPath().spec()); | |
148 ListValue* docs_list = new ListValue(); | |
149 for (std::vector<std::string>::const_iterator it = document_ids.begin(); | |
150 it != document_ids.end(); | |
151 ++it) { | |
152 docs_list->AppendString(*it); | |
153 } | |
154 request_dict.Set(kAcceptedLegalDocumentKey, docs_list); | |
155 | |
156 std::string post_body; | |
157 base::JSONWriter::Write(&request_dict, &post_body); | |
158 | |
159 MakeWalletRequest(GetAcceptLegalDocumentsUrl(), post_body); | |
160 } | |
161 | |
162 void WalletClient::AuthenticateInstrument( | |
163 const std::string& instrument_id, | |
164 const std::string& card_verification_number, | |
165 const std::string& obfuscated_gaia_id) { | |
166 if (HasRequestInProgress()) { | |
167 pending_requests_.push(base::Bind(&WalletClient::AuthenticateInstrument, | |
168 base::Unretained(this), | |
169 instrument_id, | |
170 card_verification_number, | |
171 obfuscated_gaia_id)); | |
172 return; | |
173 } | |
174 | |
175 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
176 DCHECK(pending_request_body_.empty()); | |
177 request_type_ = AUTHENTICATE_INSTRUMENT; | |
178 | |
179 pending_request_body_.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
180 pending_request_body_.SetString(kRiskParamsKey, GetRiskParams()); | |
181 pending_request_body_.SetString(kInstrumentIdKey, instrument_id); | |
182 | |
183 encryption_escrow_client_.EscrowCardVerificationNumber( | |
184 card_verification_number, obfuscated_gaia_id); | |
185 } | |
186 | |
187 void WalletClient::GetFullWallet(const std::string& instrument_id, | |
188 const std::string& address_id, | |
189 const GURL& source_url, | |
190 const Cart& cart, | |
191 const std::string& google_transaction_id, | |
192 autofill::DialogType dialog_type) { | |
193 if (HasRequestInProgress()) { | |
194 pending_requests_.push(base::Bind(&WalletClient::GetFullWallet, | |
195 base::Unretained(this), | |
196 instrument_id, | |
197 address_id, | |
198 source_url, | |
199 cart, | |
200 google_transaction_id, | |
201 dialog_type)); | |
202 return; | |
203 } | |
204 | |
205 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
206 DCHECK(pending_request_body_.empty()); | |
207 request_type_ = GET_FULL_WALLET; | |
208 | |
209 pending_request_body_.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
210 pending_request_body_.SetString(kRiskParamsKey, GetRiskParams()); | |
211 pending_request_body_.SetString(kSelectedInstrumentIdKey, instrument_id); | |
212 pending_request_body_.SetString(kSelectedAddressIdKey, address_id); | |
213 pending_request_body_.SetString(kMerchantDomainKey, | |
214 source_url.GetWithEmptyPath().spec()); | |
215 pending_request_body_.SetString(kGoogleTransactionIdKey, | |
216 google_transaction_id); | |
217 pending_request_body_.Set(kCartKey, cart.ToDictionary().release()); | |
218 pending_request_body_.SetString(kFeatureKey, | |
219 DialogTypeToFeatureString(dialog_type)); | |
220 | |
221 crypto::RandBytes(&(one_time_pad_[0]), one_time_pad_.size()); | |
222 encryption_escrow_client_.EncryptOneTimePad(one_time_pad_); | |
223 } | |
224 | |
225 void WalletClient::GetWalletItems(const GURL& source_url) { | |
226 if (HasRequestInProgress()) { | |
227 pending_requests_.push(base::Bind(&WalletClient::GetWalletItems, | |
228 base::Unretained(this), | |
229 source_url)); | |
230 return; | |
231 } | |
232 | |
233 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
234 request_type_ = GET_WALLET_ITEMS; | |
235 | |
236 base::DictionaryValue request_dict; | |
237 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
238 request_dict.SetString(kRiskParamsKey, GetRiskParams()); | |
239 request_dict.SetString(kMerchantDomainKey, | |
240 source_url.GetWithEmptyPath().spec()); | |
241 | |
242 std::string post_body; | |
243 base::JSONWriter::Write(&request_dict, &post_body); | |
244 | |
245 MakeWalletRequest(GetGetWalletItemsUrl(), post_body); | |
246 } | |
247 | |
248 void WalletClient::SaveAddress(const Address& shipping_address, | |
249 const GURL& source_url) { | |
250 if (HasRequestInProgress()) { | |
251 pending_requests_.push(base::Bind(&WalletClient::SaveAddress, | |
252 base::Unretained(this), | |
253 shipping_address, | |
254 source_url)); | |
255 return; | |
256 } | |
257 | |
258 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
259 request_type_ = SAVE_ADDRESS; | |
260 | |
261 base::DictionaryValue request_dict; | |
262 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
263 request_dict.SetString(kRiskParamsKey, GetRiskParams()); | |
264 request_dict.SetString(kMerchantDomainKey, | |
265 source_url.GetWithEmptyPath().spec()); | |
266 | |
267 request_dict.Set(kShippingAddressKey, | |
268 shipping_address.ToDictionaryWithID().release()); | |
269 | |
270 std::string post_body; | |
271 base::JSONWriter::Write(&request_dict, &post_body); | |
272 | |
273 MakeWalletRequest(GetSaveToWalletUrl(), post_body); | |
274 } | |
275 | |
276 void WalletClient::SaveInstrument( | |
277 const Instrument& instrument, | |
278 const std::string& obfuscated_gaia_id, | |
279 const GURL& source_url) { | |
280 if (HasRequestInProgress()) { | |
281 pending_requests_.push(base::Bind(&WalletClient::SaveInstrument, | |
282 base::Unretained(this), | |
283 instrument, | |
284 obfuscated_gaia_id, | |
285 source_url)); | |
286 return; | |
287 } | |
288 | |
289 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
290 DCHECK(pending_request_body_.empty()); | |
291 request_type_ = SAVE_INSTRUMENT; | |
292 | |
293 pending_request_body_.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
294 pending_request_body_.SetString(kRiskParamsKey, GetRiskParams()); | |
295 pending_request_body_.SetString(kMerchantDomainKey, | |
296 source_url.GetWithEmptyPath().spec()); | |
297 | |
298 pending_request_body_.Set(kInstrumentKey, | |
299 instrument.ToDictionary().release()); | |
300 pending_request_body_.SetString(kInstrumentPhoneNumberKey, | |
301 instrument.address().phone_number()); | |
302 | |
303 encryption_escrow_client_.EscrowInstrumentInformation(instrument, | |
304 obfuscated_gaia_id); | |
305 } | |
306 | |
307 void WalletClient::SaveInstrumentAndAddress( | |
308 const Instrument& instrument, | |
309 const Address& address, | |
310 const std::string& obfuscated_gaia_id, | |
311 const GURL& source_url) { | |
312 if (HasRequestInProgress()) { | |
313 pending_requests_.push(base::Bind(&WalletClient::SaveInstrumentAndAddress, | |
314 base::Unretained(this), | |
315 instrument, | |
316 address, | |
317 obfuscated_gaia_id, | |
318 source_url)); | |
319 return; | |
320 } | |
321 | |
322 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
323 DCHECK(pending_request_body_.empty()); | |
324 request_type_ = SAVE_INSTRUMENT_AND_ADDRESS; | |
325 | |
326 pending_request_body_.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
327 pending_request_body_.SetString(kRiskParamsKey, GetRiskParams()); | |
328 pending_request_body_.SetString(kMerchantDomainKey, | |
329 source_url.GetWithEmptyPath().spec()); | |
330 | |
331 pending_request_body_.Set(kInstrumentKey, | |
332 instrument.ToDictionary().release()); | |
333 pending_request_body_.SetString(kInstrumentPhoneNumberKey, | |
334 instrument.address().phone_number()); | |
335 | |
336 pending_request_body_.Set(kShippingAddressKey, | |
337 address.ToDictionaryWithID().release()); | |
338 | |
339 encryption_escrow_client_.EscrowInstrumentInformation(instrument, | |
340 obfuscated_gaia_id); | |
341 } | |
342 | |
343 void WalletClient::SendAutocheckoutStatus( | |
344 AutocheckoutStatus status, | |
345 const GURL& source_url, | |
346 const std::string& google_transaction_id) { | |
347 if (HasRequestInProgress()) { | |
348 pending_requests_.push(base::Bind(&WalletClient::SendAutocheckoutStatus, | |
349 base::Unretained(this), | |
350 status, | |
351 source_url, | |
352 google_transaction_id)); | |
353 return; | |
354 } | |
355 | |
356 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
357 request_type_ = SEND_STATUS; | |
358 | |
359 base::DictionaryValue request_dict; | |
360 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
361 bool success = status == SUCCESS; | |
362 request_dict.SetBoolean(kSuccessKey, success); | |
363 request_dict.SetString(kMerchantDomainKey, | |
364 source_url.GetWithEmptyPath().spec()); | |
365 if (!success) | |
366 request_dict.SetString(kReasonKey, AutocheckoutStatusToString(status)); | |
367 request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id); | |
368 | |
369 std::string post_body; | |
370 base::JSONWriter::Write(&request_dict, &post_body); | |
371 | |
372 MakeWalletRequest(GetSendStatusUrl(), post_body); | |
373 } | |
374 | |
375 void WalletClient::UpdateInstrument( | |
376 const std::string& instrument_id, | |
377 const Address& billing_address, | |
378 const GURL& source_url) { | |
379 if (HasRequestInProgress()) { | |
380 pending_requests_.push(base::Bind(&WalletClient::UpdateInstrument, | |
381 base::Unretained(this), | |
382 instrument_id, | |
383 billing_address, | |
384 source_url)); | |
385 return; | |
386 } | |
387 | |
388 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); | |
389 request_type_ = UPDATE_INSTRUMENT; | |
390 | |
391 base::DictionaryValue request_dict; | |
392 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); | |
393 request_dict.SetString(kRiskParamsKey, GetRiskParams()); | |
394 request_dict.SetString(kMerchantDomainKey, | |
395 source_url.GetWithEmptyPath().spec()); | |
396 | |
397 request_dict.SetString(kUpgradedInstrumentIdKey, instrument_id); | |
398 request_dict.SetString(kInstrumentPhoneNumberKey, | |
399 billing_address.phone_number()); | |
400 request_dict.Set(kUpgradedBillingAddressKey, | |
401 billing_address.ToDictionaryWithoutID().release()); | |
402 | |
403 std::string post_body; | |
404 base::JSONWriter::Write(&request_dict, &post_body); | |
405 | |
406 MakeWalletRequest(GetSaveToWalletUrl(), post_body); | |
407 } | |
408 | |
409 bool WalletClient::HasRequestInProgress() const { | |
410 return request_.get() != NULL; | |
411 } | |
412 | |
413 void WalletClient::CancelPendingRequests() { | |
414 while (!pending_requests_.empty()) { | |
415 pending_requests_.pop(); | |
416 } | |
417 } | |
418 | |
419 void WalletClient::MakeWalletRequest(const GURL& url, | |
420 const std::string& post_body) { | |
421 DCHECK(!HasRequestInProgress()); | |
422 | |
423 request_.reset(net::URLFetcher::Create( | |
424 0, url, net::URLFetcher::POST, this)); | |
425 request_->SetRequestContext(context_getter_); | |
426 DVLOG(1) << "url=" << url << ", post_body=" << post_body; | |
427 request_->SetUploadData(kJsonMimeType, post_body); | |
428 request_->Start(); | |
429 } | |
430 | |
431 // TODO(ahutter): Add manual retry logic if it's necessary. | |
432 void WalletClient::OnURLFetchComplete( | |
433 const net::URLFetcher* source) { | |
434 DCHECK_EQ(source, request_.get()); | |
435 DVLOG(1) << "Got response from " << source->GetOriginalURL(); | |
436 | |
437 std::string data; | |
438 source->GetResponseAsString(&data); | |
439 DVLOG(1) << "Response body: " << data; | |
440 | |
441 scoped_ptr<base::DictionaryValue> response_dict; | |
442 | |
443 int response_code = source->GetResponseCode(); | |
444 switch (response_code) { | |
445 // HTTP_BAD_REQUEST means the arguments are invalid. No point retrying. | |
446 case net::HTTP_BAD_REQUEST: { | |
447 request_type_ = NO_PENDING_REQUEST; | |
448 observer_->OnWalletError(); | |
449 return; | |
450 } | |
451 // HTTP_OK holds a valid response and HTTP_INTERNAL_SERVER_ERROR holds an | |
452 // error code and message for the user. | |
453 case net::HTTP_OK: | |
454 case net::HTTP_INTERNAL_SERVER_ERROR: { | |
455 scoped_ptr<Value> message_value(base::JSONReader::Read(data)); | |
456 if (message_value.get() && | |
457 message_value->IsType(Value::TYPE_DICTIONARY)) { | |
458 response_dict.reset( | |
459 static_cast<base::DictionaryValue*>(message_value.release())); | |
460 } | |
461 if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) { | |
462 request_type_ = NO_PENDING_REQUEST; | |
463 // TODO(ahutter): Do something with the response. See | |
464 // http://crbug.com/164410. | |
465 observer_->OnWalletError(); | |
466 return; | |
467 } | |
468 break; | |
469 } | |
470 // Anything else is an error. | |
471 default: { | |
472 request_type_ = NO_PENDING_REQUEST; | |
473 observer_->OnNetworkError(response_code); | |
474 return; | |
475 } | |
476 } | |
477 | |
478 RequestType type = request_type_; | |
479 request_type_ = NO_PENDING_REQUEST; | |
480 | |
481 if (!(type == ACCEPT_LEGAL_DOCUMENTS || type == SEND_STATUS) && | |
482 !response_dict) { | |
483 HandleMalformedResponse(); | |
484 return; | |
485 } | |
486 | |
487 switch (type) { | |
488 case ACCEPT_LEGAL_DOCUMENTS: | |
489 observer_->OnDidAcceptLegalDocuments(); | |
490 break; | |
491 | |
492 case AUTHENTICATE_INSTRUMENT: { | |
493 std::string auth_result; | |
494 if (response_dict->GetString(kAuthResultKey, &auth_result)) { | |
495 std::string trimmed; | |
496 TrimWhitespaceASCII(auth_result, | |
497 TRIM_ALL, | |
498 &trimmed); | |
499 observer_->OnDidAuthenticateInstrument( | |
500 LowerCaseEqualsASCII(trimmed, "success")); | |
501 } else { | |
502 HandleMalformedResponse(); | |
503 } | |
504 break; | |
505 } | |
506 | |
507 case SEND_STATUS: | |
508 observer_->OnDidSendAutocheckoutStatus(); | |
509 break; | |
510 | |
511 case GET_FULL_WALLET: { | |
512 scoped_ptr<FullWallet> full_wallet( | |
513 FullWallet::CreateFullWallet(*response_dict)); | |
514 if (full_wallet) { | |
515 full_wallet->set_one_time_pad(one_time_pad_); | |
516 observer_->OnDidGetFullWallet(full_wallet.Pass()); | |
517 } else { | |
518 HandleMalformedResponse(); | |
519 } | |
520 break; | |
521 } | |
522 | |
523 case GET_WALLET_ITEMS: { | |
524 scoped_ptr<WalletItems> wallet_items( | |
525 WalletItems::CreateWalletItems(*response_dict)); | |
526 if (wallet_items) | |
527 observer_->OnDidGetWalletItems(wallet_items.Pass()); | |
528 else | |
529 HandleMalformedResponse(); | |
530 break; | |
531 } | |
532 | |
533 case SAVE_ADDRESS: { | |
534 std::string shipping_address_id; | |
535 std::vector<RequiredAction> required_actions; | |
536 GetRequiredActionsForSaveToWallet(*response_dict, &required_actions); | |
537 if (response_dict->GetString(kShippingAddressIdKey, | |
538 &shipping_address_id) || | |
539 !required_actions.empty()) { | |
540 observer_->OnDidSaveAddress(shipping_address_id, required_actions); | |
541 } else { | |
542 HandleMalformedResponse(); | |
543 } | |
544 break; | |
545 } | |
546 | |
547 case SAVE_INSTRUMENT: { | |
548 std::string instrument_id; | |
549 std::vector<RequiredAction> required_actions; | |
550 GetRequiredActionsForSaveToWallet(*response_dict, &required_actions); | |
551 if (response_dict->GetString(kInstrumentIdKey, &instrument_id) || | |
552 !required_actions.empty()) { | |
553 observer_->OnDidSaveInstrument(instrument_id, required_actions); | |
554 } else { | |
555 HandleMalformedResponse(); | |
556 } | |
557 break; | |
558 } | |
559 | |
560 case SAVE_INSTRUMENT_AND_ADDRESS: { | |
561 std::string instrument_id; | |
562 response_dict->GetString(kInstrumentIdKey, &instrument_id); | |
563 std::string shipping_address_id; | |
564 response_dict->GetString(kShippingAddressIdKey, | |
565 &shipping_address_id); | |
566 std::vector<RequiredAction> required_actions; | |
567 GetRequiredActionsForSaveToWallet(*response_dict, &required_actions); | |
568 if ((!instrument_id.empty() && !shipping_address_id.empty()) || | |
569 !required_actions.empty()) { | |
570 observer_->OnDidSaveInstrumentAndAddress(instrument_id, | |
571 shipping_address_id, | |
572 required_actions); | |
573 } else { | |
574 HandleMalformedResponse(); | |
575 } | |
576 break; | |
577 } | |
578 | |
579 case UPDATE_INSTRUMENT: { | |
580 std::string instrument_id; | |
581 std::vector<RequiredAction> required_actions; | |
582 GetRequiredActionsForSaveToWallet(*response_dict, &required_actions); | |
583 if (response_dict->GetString(kInstrumentIdKey, &instrument_id) || | |
584 !required_actions.empty()) { | |
585 observer_->OnDidUpdateInstrument(instrument_id, required_actions); | |
586 } else { | |
587 HandleMalformedResponse(); | |
588 } | |
589 break; | |
590 } | |
591 | |
592 case NO_PENDING_REQUEST: | |
593 NOTREACHED(); | |
594 } | |
595 | |
596 request_.reset(); | |
597 StartNextPendingRequest(); | |
598 } | |
599 | |
600 void WalletClient::StartNextPendingRequest() { | |
601 if (pending_requests_.empty()) | |
602 return; | |
603 | |
604 base::Closure next_request = pending_requests_.front(); | |
605 pending_requests_.pop(); | |
606 next_request.Run(); | |
607 } | |
608 | |
609 void WalletClient::HandleMalformedResponse() { | |
610 // Called to inform exponential backoff logic of the error. | |
611 request_->ReceivedContentWasMalformed(); | |
612 observer_->OnMalformedResponse(); | |
613 } | |
614 | |
615 void WalletClient::OnDidEncryptOneTimePad( | |
616 const std::string& encrypted_one_time_pad, | |
617 const std::string& session_material) { | |
618 DCHECK_EQ(GET_FULL_WALLET, request_type_); | |
619 pending_request_body_.SetString(kEncryptedOtpKey, encrypted_one_time_pad); | |
620 pending_request_body_.SetString(kSessionMaterialKey, session_material); | |
621 | |
622 std::string post_body; | |
623 base::JSONWriter::Write(&pending_request_body_, &post_body); | |
624 pending_request_body_.Clear(); | |
625 | |
626 MakeWalletRequest(GetGetFullWalletUrl(), post_body); | |
627 } | |
628 | |
629 void WalletClient::OnDidEscrowInstrumentInformation( | |
630 const std::string& escrow_handle) { | |
631 DCHECK(request_type_ == SAVE_INSTRUMENT || | |
632 request_type_ == SAVE_INSTRUMENT_AND_ADDRESS); | |
633 | |
634 pending_request_body_.SetString(kInstrumentEscrowHandleKey, escrow_handle); | |
635 | |
636 std::string post_body; | |
637 base::JSONWriter::Write(&pending_request_body_, &post_body); | |
638 pending_request_body_.Clear(); | |
639 | |
640 MakeWalletRequest(GetSaveToWalletUrl(), post_body); | |
641 } | |
642 | |
643 void WalletClient::OnDidEscrowCardVerificationNumber( | |
644 const std::string& escrow_handle) { | |
645 DCHECK_EQ(AUTHENTICATE_INSTRUMENT, request_type_); | |
646 pending_request_body_.SetString(kInstrumentEscrowHandleKey, escrow_handle); | |
647 | |
648 std::string post_body; | |
649 base::JSONWriter::Write(&pending_request_body_, &post_body); | |
650 pending_request_body_.Clear(); | |
651 | |
652 MakeWalletRequest(GetAuthenticateInstrumentUrl(), post_body); | |
653 } | |
654 | |
655 void WalletClient::OnNetworkError(int response_code) { | |
656 observer_->OnNetworkError(response_code); | |
657 } | |
658 | |
659 void WalletClient::OnMalformedResponse() { | |
660 observer_->OnMalformedResponse(); | |
661 } | |
662 | |
663 } // namespace wallet | |
664 } // namespace autofill | |
OLD | NEW |