1 // Copyright 2013 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 "components/autofill/content/browser/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/message_loop/message_loop.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "components/autofill/content/browser/wallet/form_field_error.h" 18 #include "components/autofill/content/browser/wallet/instrument.h" 19 #include "components/autofill/content/browser/wallet/wallet_address.h" 20 #include "components/autofill/content/browser/wallet/wallet_client_delegate.h" 21 #include "components/autofill/content/browser/wallet/wallet_items.h" 22 #include "components/autofill/content/browser/wallet/wallet_service_url.h" 23 #include "components/autofill/core/browser/autofill_metrics.h" 24 #include "crypto/random.h" 25 #include "google_apis/google_api_keys.h" 26 #include "net/base/escape.h" 27 #include "net/http/http_status_code.h" 28 #include "net/url_request/url_fetcher.h" 29 #include "net/url_request/url_request_context_getter.h" 30 31 // TODO(ahutter): Change all VLOGs to DVLOGs after dogfood. 32 namespace autofill { 33 namespace wallet { 34 35 namespace { 36 37 const char kFormEncodedMimeType[] = "application/x-www-form-urlencoded"; 38 const char kJsonMimeType[] = "application/json"; 39 const char kEscrowNewInstrumentFormat[] = 40 "request_content_type=application/json&request=%s&cvn=%s&card_number=%s"; 41 const char kEscrowCardVerificationNumberFormat[] = 42 "request_content_type=application/json&request=%s&cvn=%s"; 43 const char kGetFullWalletRequestFormat[] = 44 "request_content_type=application/json&request=%s&otp=%s:%s"; 45 const size_t kOneTimePadLength = 6; 46 47 // The maximum number of bits in the one time pad that the server is willing to 48 // accept. 49 const size_t kMaxBits = 56; 50 51 // The minimum number of bits in the one time pad that the server is willing to 52 // accept. 53 const size_t kMinBits = 40; 54 55 std::string AutocheckoutStatusToString(AutocheckoutStatus status) { 56 switch (status) { 57 case MISSING_FIELDMAPPING: 58 return "MISSING_FIELDMAPPING"; 59 case MISSING_ADVANCE: 60 return "MISSING_ADVANCE"; 61 case MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING: 62 return "MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING"; 63 case MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING: 64 return "MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING"; 65 case CANNOT_PROCEED: 66 return "CANNOT_PROCEED"; 67 case SUCCESS: 68 // SUCCESS cannot be sent to the server as it will result in a failure. 69 NOTREACHED(); 70 return "ERROR"; 71 case AUTOCHECKOUT_STATUS_NUM_STATUS: 72 NOTREACHED(); 73 } 74 NOTREACHED(); 75 return "NOT_POSSIBLE"; 76 } 77 78 std::string DialogTypeToFeatureString(autofill::DialogType dialog_type) { 79 switch (dialog_type) { 80 case DIALOG_TYPE_REQUEST_AUTOCOMPLETE: 81 return "REQUEST_AUTOCOMPLETE"; 82 case DIALOG_TYPE_AUTOCHECKOUT: 83 return "AUTOCHECKOUT"; 84 } 85 NOTREACHED(); 86 return "NOT_POSSIBLE"; 87 } 88 89 std::string RiskCapabilityToString( 90 WalletClient::RiskCapability risk_capability) { 91 switch (risk_capability) { 92 case WalletClient::RELOGIN: 93 return "RELOGIN"; 94 case WalletClient::VERIFY_CVC: 95 return "VERIFY_CVC"; 96 } 97 NOTREACHED(); 98 return "NOT_POSSIBLE"; 99 } 100 101 WalletClient::ErrorType StringToErrorType(const std::string& error_type) { 102 std::string trimmed; 103 TrimWhitespaceASCII(error_type, 104 TRIM_ALL, 105 &trimmed); 106 if (LowerCaseEqualsASCII(trimmed, "buyer_account_error")) 107 return WalletClient::BUYER_ACCOUNT_ERROR; 108 if (LowerCaseEqualsASCII(trimmed, "unsupported_merchant")) 109 return WalletClient::UNSUPPORTED_MERCHANT; 110 if (LowerCaseEqualsASCII(trimmed, "internal_error")) 111 return WalletClient::INTERNAL_ERROR; 112 if (LowerCaseEqualsASCII(trimmed, "invalid_params")) 113 return WalletClient::INVALID_PARAMS; 114 if (LowerCaseEqualsASCII(trimmed, "service_unavailable")) 115 return WalletClient::SERVICE_UNAVAILABLE; 116 if (LowerCaseEqualsASCII(trimmed, "unsupported_api_version")) 117 return WalletClient::UNSUPPORTED_API_VERSION; 118 119 return WalletClient::UNKNOWN_ERROR; 120 } 121 122 // Get the more specific WalletClient::ErrorType when the error is 123 // |BUYER_ACCOUNT_ERROR|. 124 WalletClient::ErrorType BuyerErrorStringToErrorType( 125 const std::string& buyer_error_type) { 126 std::string trimmed; 127 TrimWhitespaceASCII(buyer_error_type, 128 TRIM_ALL, 129 &trimmed); 130 if (LowerCaseEqualsASCII(trimmed, "bla_country_not_supported")) 131 return WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED; 132 if (LowerCaseEqualsASCII(trimmed, "buyer_kyc_error")) 133 return WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS; 134 135 return WalletClient::BUYER_ACCOUNT_ERROR; 136 } 137 138 // Gets and parses required actions from a SaveToWallet response. Returns 139 // false if any unknown required actions are seen and true otherwise. 140 void GetRequiredActionsForSaveToWallet( 141 const base::DictionaryValue& dict, 142 std::vector<RequiredAction>* required_actions) { 143 const base::ListValue* required_action_list; 144 if (!dict.GetList("required_action", &required_action_list)) 145 return; 146 147 for (size_t i = 0; i < required_action_list->GetSize(); ++i) { 148 std::string action_string; 149 if (required_action_list->GetString(i, &action_string)) { 150 RequiredAction action = ParseRequiredActionFromString(action_string); 151 if (!ActionAppliesToSaveToWallet(action)) { 152 DLOG(ERROR) << "Response from Google wallet with bad required action:" 153 " \"" << action_string << "\""; 154 required_actions->clear(); 155 return; 156 } 157 required_actions->push_back(action); 158 } 159 } 160 } 161 162 void GetFormFieldErrors(const base::DictionaryValue& dict, 163 std::vector<FormFieldError>* form_errors) { 164 DCHECK(form_errors->empty()); 165 const base::ListValue* form_errors_list; 166 if (!dict.GetList("form_field_error", &form_errors_list)) 167 return; 168 169 for (size_t i = 0; i < form_errors_list->GetSize(); ++i) { 170 const base::DictionaryValue* dictionary; 171 if (form_errors_list->GetDictionary(i, &dictionary)) 172 form_errors->push_back(FormFieldError::CreateFormFieldError(*dictionary)); 173 } 174 } 175 176 // Converts the |error_type| to the corresponding value from the stable UMA 177 // metric enumeration. 178 AutofillMetrics::WalletErrorMetric ErrorTypeToUmaMetric( 179 WalletClient::ErrorType error_type) { 180 switch (error_type) { 181 case WalletClient::BAD_REQUEST: 182 return AutofillMetrics::WALLET_BAD_REQUEST; 183 case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED: 184 return AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED; 185 case WalletClient::BUYER_ACCOUNT_ERROR: 186 return AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR; 187 case WalletClient::INTERNAL_ERROR: 188 return AutofillMetrics::WALLET_INTERNAL_ERROR; 189 case WalletClient::INVALID_PARAMS: 190 return AutofillMetrics::WALLET_INVALID_PARAMS; 191 case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS: 192 return AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS; 193 case WalletClient::SERVICE_UNAVAILABLE: 194 return AutofillMetrics::WALLET_SERVICE_UNAVAILABLE; 195 case WalletClient::UNSUPPORTED_API_VERSION: 196 return AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION; 197 case WalletClient::UNSUPPORTED_MERCHANT: 198 return AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT; 199 case WalletClient::MALFORMED_RESPONSE: 200 return AutofillMetrics::WALLET_MALFORMED_RESPONSE; 201 case WalletClient::NETWORK_ERROR: 202 return AutofillMetrics::WALLET_NETWORK_ERROR; 203 case WalletClient::UNKNOWN_ERROR: 204 return AutofillMetrics::WALLET_UNKNOWN_ERROR; 205 } 206 207 NOTREACHED(); 208 return AutofillMetrics::WALLET_UNKNOWN_ERROR; 209 } 210 211 // Converts the |required_action| to the corresponding value from the stable UMA 212 // metric enumeration. 213 AutofillMetrics::WalletRequiredActionMetric RequiredActionToUmaMetric( 214 RequiredAction required_action) { 215 switch (required_action) { 216 case UNKNOWN_TYPE: 217 return AutofillMetrics::UNKNOWN_REQUIRED_ACTION; 218 case CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS: 219 return AutofillMetrics::CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS; 220 case SETUP_WALLET: 221 return AutofillMetrics::SETUP_WALLET; 222 case ACCEPT_TOS: 223 return AutofillMetrics::ACCEPT_TOS; 224 case GAIA_AUTH: 225 return AutofillMetrics::GAIA_AUTH; 226 case UPDATE_EXPIRATION_DATE: 227 return AutofillMetrics::UPDATE_EXPIRATION_DATE; 228 case UPGRADE_MIN_ADDRESS: 229 return AutofillMetrics::UPGRADE_MIN_ADDRESS; 230 case INVALID_FORM_FIELD: 231 return AutofillMetrics::INVALID_FORM_FIELD; 232 case VERIFY_CVV: 233 return AutofillMetrics::VERIFY_CVV; 234 case PASSIVE_GAIA_AUTH: 235 return AutofillMetrics::PASSIVE_GAIA_AUTH; 236 case REQUIRE_PHONE_NUMBER: 237 return AutofillMetrics::REQUIRE_PHONE_NUMBER; 238 } 239 240 NOTREACHED(); 241 return AutofillMetrics::UNKNOWN_REQUIRED_ACTION; 242 } 243 244 // Keys for JSON communication with the Online Wallet server. 245 const char kAcceptedLegalDocumentKey[] = "accepted_legal_document"; 246 const char kApiKeyKey[] = "api_key"; 247 const char kAuthResultKey[] = "auth_result"; 248 const char kBuyerErrorTypeKey[] = "wallet_error.buyer_error_type"; 249 const char kEncryptedOtpKey[] = "encrypted_otp"; 250 const char kErrorTypeKey[] = "wallet_error.error_type"; 251 const char kFeatureKey[] = "feature"; 252 const char kGoogleTransactionIdKey[] = "google_transaction_id"; 253 const char kInstrumentIdKey[] = "instrument_id"; 254 const char kInstrumentKey[] = "instrument"; 255 const char kInstrumentEscrowHandleKey[] = "instrument_escrow_handle"; 256 const char kInstrumentExpMonthKey[] = "instrument.credit_card.exp_month"; 257 const char kInstrumentExpYearKey[] = "instrument.credit_card.exp_year"; 258 const char kInstrumentType[] = "instrument.type"; 259 const char kInstrumentPhoneNumberKey[] = "instrument_phone_number"; 260 const char kMerchantDomainKey[] = "merchant_domain"; 261 const char kPhoneNumberRequired[] = "phone_number_required"; 262 const char kReasonKey[] = "reason"; 263 const char kRiskCapabilitiesKey[] = "supported_risk_challenge"; 264 const char kRiskParamsKey[] = "risk_params"; 265 const char kSelectedAddressIdKey[] = "selected_address_id"; 266 const char kSelectedInstrumentIdKey[] = "selected_instrument_id"; 267 const char kSessionMaterialKey[] = "session_material"; 268 const char kShippingAddressIdKey[] = "shipping_address_id"; 269 const char kShippingAddressKey[] = "shipping_address"; 270 const char kShippingAddressRequired[] = "shipping_address_required"; 271 const char kAutocheckoutStepsKey[] = "steps"; 272 const char kSuccessKey[] = "success"; 273 const char kUpgradedBillingAddressKey[] = "upgraded_billing_address"; 274 const char kUpgradedInstrumentIdKey[] = "upgraded_instrument_id"; 275 const char kUseMinimalAddresses[] = "use_minimal_addresses"; 276 277 } // namespace 278 279 WalletClient::FullWalletRequest::FullWalletRequest( 280 const std::string& instrument_id, 281 const std::string& address_id, 282 const GURL& source_url, 283 const std::string& google_transaction_id, 284 const std::vector<RiskCapability> risk_capabilities) 285 : instrument_id(instrument_id), 286 address_id(address_id), 287 source_url(source_url), 288 google_transaction_id(google_transaction_id), 289 risk_capabilities(risk_capabilities) {} 290 291 WalletClient::FullWalletRequest::~FullWalletRequest() {} 292 293 WalletClient::WalletClient(net::URLRequestContextGetter* context_getter, 294 WalletClientDelegate* delegate) 295 : context_getter_(context_getter), 296 delegate_(delegate), 297 request_type_(NO_PENDING_REQUEST), 298 one_time_pad_(kOneTimePadLength), 299 weak_ptr_factory_(this) { 300 DCHECK(context_getter_.get()); 301 DCHECK(delegate_); 302 } 303 304 WalletClient::~WalletClient() {} 305 306 void WalletClient::AcceptLegalDocuments( 307 const std::vector<WalletItems::LegalDocument*>& documents, 308 const std::string& google_transaction_id, 309 const GURL& source_url) { 310 if (documents.empty()) 311 return; 312 313 std::vector<std::string> document_ids; 314 for (size_t i = 0; i < documents.size(); ++i) { 315 document_ids.push_back(documents[i]->id()); 316 } 317 DoAcceptLegalDocuments(document_ids, google_transaction_id, source_url); 318 } 319 320 void WalletClient::AuthenticateInstrument( 321 const std::string& instrument_id, 322 const std::string& card_verification_number) { 323 if (HasRequestInProgress()) { 324 pending_requests_.push(base::Bind(&WalletClient::AuthenticateInstrument, 325 base::Unretained(this), 326 instrument_id, 327 card_verification_number)); 328 return; 329 } 330 331 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 332 request_type_ = AUTHENTICATE_INSTRUMENT; 333 334 base::DictionaryValue request_dict; 335 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 336 request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData()); 337 request_dict.SetString(kInstrumentIdKey, instrument_id); 338 339 std::string json_payload; 340 base::JSONWriter::Write(&request_dict, &json_payload); 341 342 std::string escaped_card_verification_number = net::EscapeUrlEncodedData( 343 card_verification_number, true); 344 345 std::string post_body = base::StringPrintf( 346 kEscrowCardVerificationNumberFormat, 347 net::EscapeUrlEncodedData(json_payload, true).c_str(), 348 escaped_card_verification_number.c_str()); 349 350 MakeWalletRequest(GetAuthenticateInstrumentUrl(), 351 post_body, 352 kFormEncodedMimeType); 353 } 354 355 void WalletClient::GetFullWallet(const FullWalletRequest& full_wallet_request) { 356 if (HasRequestInProgress()) { 357 pending_requests_.push(base::Bind(&WalletClient::GetFullWallet, 358 base::Unretained(this), 359 full_wallet_request)); 360 return; 361 } 362 363 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 364 request_type_ = GET_FULL_WALLET; 365 366 base::DictionaryValue request_dict; 367 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 368 request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData()); 369 request_dict.SetBoolean(kUseMinimalAddresses, false); 370 request_dict.SetBoolean(kPhoneNumberRequired, true); 371 372 request_dict.SetString(kSelectedInstrumentIdKey, 373 full_wallet_request.instrument_id); 374 request_dict.SetString(kSelectedAddressIdKey, full_wallet_request.address_id); 375 request_dict.SetString( 376 kMerchantDomainKey, 377 full_wallet_request.source_url.GetWithEmptyPath().spec()); 378 request_dict.SetString(kGoogleTransactionIdKey, 379 full_wallet_request.google_transaction_id); 380 request_dict.SetString(kFeatureKey, 381 DialogTypeToFeatureString(delegate_->GetDialogType())); 382 383 scoped_ptr<base::ListValue> risk_capabilities_list(new base::ListValue()); 384 for (std::vector<RiskCapability>::const_iterator it = 385 full_wallet_request.risk_capabilities.begin(); 386 it != full_wallet_request.risk_capabilities.end(); 387 ++it) { 388 risk_capabilities_list->AppendString(RiskCapabilityToString(*it)); 389 } 390 request_dict.Set(kRiskCapabilitiesKey, risk_capabilities_list.release()); 391 392 std::string json_payload; 393 base::JSONWriter::Write(&request_dict, &json_payload); 394 395 crypto::RandBytes(&(one_time_pad_[0]), one_time_pad_.size()); 396 397 size_t num_bits = one_time_pad_.size() * 8; 398 DCHECK_LE(num_bits, kMaxBits); 399 DCHECK_GE(num_bits, kMinBits); 400 401 std::string post_body = base::StringPrintf( 402 kGetFullWalletRequestFormat, 403 net::EscapeUrlEncodedData(json_payload, true).c_str(), 404 base::HexEncode(&num_bits, 1).c_str(), 405 base::HexEncode(&(one_time_pad_[0]), one_time_pad_.size()).c_str()); 406 407 MakeWalletRequest(GetGetFullWalletUrl(), post_body, kFormEncodedMimeType); 408 } 409 410 void WalletClient::SaveToWallet(scoped_ptr<Instrument> instrument, 411 scoped_ptr<Address> address, 412 const GURL& source_url) { 413 DCHECK(instrument || address); 414 if (HasRequestInProgress()) { 415 pending_requests_.push(base::Bind(&WalletClient::SaveToWallet, 416 base::Unretained(this), 417 base::Passed(&instrument), 418 base::Passed(&address), 419 source_url)); 420 return; 421 } 422 423 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 424 request_type_ = SAVE_TO_WALLET; 425 426 base::DictionaryValue request_dict; 427 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 428 request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData()); 429 request_dict.SetString(kMerchantDomainKey, 430 source_url.GetWithEmptyPath().spec()); 431 request_dict.SetBoolean(kUseMinimalAddresses, false); 432 request_dict.SetBoolean(kPhoneNumberRequired, true); 433 434 std::string primary_account_number; 435 std::string card_verification_number; 436 if (instrument) { 437 primary_account_number = net::EscapeUrlEncodedData( 438 UTF16ToUTF8(instrument->primary_account_number()), true); 439 card_verification_number = net::EscapeUrlEncodedData( 440 UTF16ToUTF8(instrument->card_verification_number()), true); 441 442 if (instrument->object_id().empty()) { 443 request_dict.Set(kInstrumentKey, instrument->ToDictionary().release()); 444 request_dict.SetString(kInstrumentPhoneNumberKey, 445 instrument->address()->phone_number()); 446 } else { 447 DCHECK(instrument->address() || 448 (instrument->expiration_month() > 0 && 449 instrument->expiration_year() > 0)); 450 451 request_dict.SetString(kUpgradedInstrumentIdKey, 452 instrument->object_id()); 453 454 if (instrument->address()) { 455 request_dict.SetString(kInstrumentPhoneNumberKey, 456 instrument->address()->phone_number()); 457 request_dict.Set( 458 kUpgradedBillingAddressKey, 459 instrument->address()->ToDictionaryWithoutID().release()); 460 } 461 462 if (instrument->expiration_month() > 0 && 463 instrument->expiration_year() > 0) { 464 DCHECK(!instrument->card_verification_number().empty()); 465 request_dict.SetInteger(kInstrumentExpMonthKey, 466 instrument->expiration_month()); 467 request_dict.SetInteger(kInstrumentExpYearKey, 468 instrument->expiration_year()); 469 } 470 471 if (request_dict.HasKey(kInstrumentKey)) 472 request_dict.SetString(kInstrumentType, "CREDIT_CARD"); 473 } 474 } 475 if (address) { 476 request_dict.Set(kShippingAddressKey, 477 address->ToDictionaryWithID().release()); 478 } 479 480 std::string json_payload; 481 base::JSONWriter::Write(&request_dict, &json_payload); 482 483 if (!card_verification_number.empty()) { 484 std::string post_body; 485 if (!primary_account_number.empty()) { 486 post_body = base::StringPrintf( 487 kEscrowNewInstrumentFormat, 488 net::EscapeUrlEncodedData(json_payload, true).c_str(), 489 card_verification_number.c_str(), 490 primary_account_number.c_str()); 491 } else { 492 post_body = base::StringPrintf( 493 kEscrowCardVerificationNumberFormat, 494 net::EscapeUrlEncodedData(json_payload, true).c_str(), 495 card_verification_number.c_str()); 496 } 497 MakeWalletRequest(GetSaveToWalletUrl(), post_body, kFormEncodedMimeType); 498 } else { 499 MakeWalletRequest(GetSaveToWalletNoEscrowUrl(), 500 json_payload, 501 kJsonMimeType); 502 } 503 } 504 505 void WalletClient::GetWalletItems(const GURL& source_url) { 506 if (HasRequestInProgress()) { 507 pending_requests_.push(base::Bind(&WalletClient::GetWalletItems, 508 base::Unretained(this), 509 source_url)); 510 return; 511 } 512 513 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 514 request_type_ = GET_WALLET_ITEMS; 515 516 base::DictionaryValue request_dict; 517 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 518 request_dict.SetString(kMerchantDomainKey, 519 source_url.GetWithEmptyPath().spec()); 520 request_dict.SetBoolean(kShippingAddressRequired, 521 delegate_->IsShippingAddressRequired()); 522 request_dict.SetBoolean(kUseMinimalAddresses, false); 523 request_dict.SetBoolean(kPhoneNumberRequired, true); 524 525 std::string post_body; 526 base::JSONWriter::Write(&request_dict, &post_body); 527 528 MakeWalletRequest(GetGetWalletItemsUrl(), post_body, kJsonMimeType); 529 } 530 531 void WalletClient::SendAutocheckoutStatus( 532 AutocheckoutStatus status, 533 const GURL& source_url, 534 const std::vector<AutocheckoutStatistic>& latency_statistics, 535 const std::string& google_transaction_id) { 536 DVLOG(1) << "Sending Autocheckout Status: " << status 537 << " for: " << source_url; 538 if (HasRequestInProgress()) { 539 pending_requests_.push(base::Bind(&WalletClient::SendAutocheckoutStatus, 540 base::Unretained(this), 541 status, 542 source_url, 543 latency_statistics, 544 google_transaction_id)); 545 return; 546 } 547 548 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 549 request_type_ = SEND_STATUS; 550 551 base::DictionaryValue request_dict; 552 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 553 bool success = status == SUCCESS; 554 request_dict.SetBoolean(kSuccessKey, success); 555 request_dict.SetString(kMerchantDomainKey, 556 source_url.GetWithEmptyPath().spec()); 557 if (!success) 558 request_dict.SetString(kReasonKey, AutocheckoutStatusToString(status)); 559 if (!latency_statistics.empty()) { 560 scoped_ptr<base::ListValue> latency_statistics_json( 561 new base::ListValue()); 562 for (size_t i = 0; i < latency_statistics.size(); ++i) { 563 latency_statistics_json->Append( 564 latency_statistics[i].ToDictionary().release()); 565 } 566 request_dict.Set(kAutocheckoutStepsKey, 567 latency_statistics_json.release()); 568 } 569 request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id); 570 571 std::string post_body; 572 base::JSONWriter::Write(&request_dict, &post_body); 573 574 MakeWalletRequest(GetSendStatusUrl(), post_body, kJsonMimeType); 575 } 576 577 bool WalletClient::HasRequestInProgress() const { 578 return request_; 579 } 580 581 void WalletClient::CancelRequests() { 582 request_.reset(); 583 request_type_ = NO_PENDING_REQUEST; 584 while (!pending_requests_.empty()) { 585 pending_requests_.pop(); 586 } 587 } 588 589 void WalletClient::DoAcceptLegalDocuments( 590 const std::vector<std::string>& document_ids, 591 const std::string& google_transaction_id, 592 const GURL& source_url) { 593 if (HasRequestInProgress()) { 594 pending_requests_.push(base::Bind(&WalletClient::DoAcceptLegalDocuments, 595 base::Unretained(this), 596 document_ids, 597 google_transaction_id, 598 source_url)); 599 return; 600 } 601 602 DCHECK_EQ(NO_PENDING_REQUEST, request_type_); 603 request_type_ = ACCEPT_LEGAL_DOCUMENTS; 604 605 base::DictionaryValue request_dict; 606 request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey()); 607 request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id); 608 request_dict.SetString(kMerchantDomainKey, 609 source_url.GetWithEmptyPath().spec()); 610 scoped_ptr<base::ListValue> docs_list(new base::ListValue()); 611 for (std::vector<std::string>::const_iterator it = document_ids.begin(); 612 it != document_ids.end(); ++it) { 613 if (!it->empty()) 614 docs_list->AppendString(*it); 615 } 616 request_dict.Set(kAcceptedLegalDocumentKey, docs_list.release()); 617 618 std::string post_body; 619 base::JSONWriter::Write(&request_dict, &post_body); 620 621 MakeWalletRequest(GetAcceptLegalDocumentsUrl(), post_body, kJsonMimeType); 622 } 623 624 void WalletClient::MakeWalletRequest(const GURL& url, 625 const std::string& post_body, 626 const std::string& mime_type) { 627 DCHECK(!HasRequestInProgress()); 628 629 request_.reset(net::URLFetcher::Create( 630 0, url, net::URLFetcher::POST, this)); 631 request_->SetRequestContext(context_getter_.get()); 632 VLOG(1) << "Making request to " << url << " with post_body=" << post_body; 633 request_->SetUploadData(mime_type, post_body); 634 request_->AddExtraRequestHeader("Authorization: GoogleLogin auth=" + 635 delegate_->GetWalletCookieValue()); 636 DVLOG(1) << "Setting authorization header value to " 637 << delegate_->GetWalletCookieValue(); 638 request_started_timestamp_ = base::Time::Now(); 639 request_->Start(); 640 641 delegate_->GetMetricLogger().LogWalletErrorMetric( 642 delegate_->GetDialogType(), 643 AutofillMetrics::WALLET_ERROR_BASELINE_ISSUED_REQUEST); 644 delegate_->GetMetricLogger().LogWalletRequiredActionMetric( 645 delegate_->GetDialogType(), 646 AutofillMetrics::WALLET_REQUIRED_ACTION_BASELINE_ISSUED_REQUEST); 647 } 648 649 // TODO(ahutter): Add manual retry logic if it's necessary. 650 void WalletClient::OnURLFetchComplete( 651 const net::URLFetcher* source) { 652 delegate_->GetMetricLogger().LogWalletApiCallDuration( 653 RequestTypeToUmaMetric(request_type_), 654 base::Time::Now() - request_started_timestamp_); 655 656 DCHECK_EQ(source, request_.get()); 657 VLOG(1) << "Got response from " << source->GetOriginalURL(); 658 659 // |request_|, which is aliased to |source|, might continue to be used in this 660 // |method, but should be freed once control leaves the method. 661 scoped_ptr<net::URLFetcher> scoped_request(request_.Pass()); 662 663 // Prepare to start the next pending request. This is queued up as an 664 // asynchronous message because |this| WalletClient instance can be destroyed 665 // before the end of the method in response to the current incoming request. 666 base::MessageLoop::current()->PostTask( 667 FROM_HERE, 668 base::Bind(&WalletClient::StartNextPendingRequest, 669 weak_ptr_factory_.GetWeakPtr()));; 670 671 std::string data; 672 source->GetResponseAsString(&data); 673 VLOG(1) << "Response body: " << data; 674 675 scoped_ptr<base::DictionaryValue> response_dict; 676 677 int response_code = source->GetResponseCode(); 678 switch (response_code) { 679 // HTTP_BAD_REQUEST means the arguments are invalid. No point retrying. 680 case net::HTTP_BAD_REQUEST: { 681 request_type_ = NO_PENDING_REQUEST; 682 HandleWalletError(BAD_REQUEST); 683 return; 684 } 685 // HTTP_OK holds a valid response and HTTP_INTERNAL_SERVER_ERROR holds an 686 // error code and message for the user. 687 case net::HTTP_OK: 688 case net::HTTP_INTERNAL_SERVER_ERROR: { 689 scoped_ptr<Value> message_value(base::JSONReader::Read(data)); 690 if (message_value.get() && 691 message_value->IsType(Value::TYPE_DICTIONARY)) { 692 response_dict.reset( 693 static_cast<base::DictionaryValue*>(message_value.release())); 694 } 695 if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) { 696 request_type_ = NO_PENDING_REQUEST; 697 698 std::string error_type_string; 699 if (!response_dict->GetString(kErrorTypeKey, &error_type_string)) { 700 HandleWalletError(UNKNOWN_ERROR); 701 return; 702 } 703 WalletClient::ErrorType error_type = 704 StringToErrorType(error_type_string); 705 if (error_type == BUYER_ACCOUNT_ERROR) { 706 // If the error_type is |BUYER_ACCOUNT_ERROR|, then buyer_error_type 707 // field contains more specific information about the error. 708 std::string buyer_error_type_string; 709 if (response_dict->GetString(kBuyerErrorTypeKey, 710 &buyer_error_type_string)) { 711 error_type = BuyerErrorStringToErrorType(buyer_error_type_string); 712 } 713 } 714 715 HandleWalletError(error_type); 716 return; 717 } 718 break; 719 } 720 721 // Anything else is an error. 722 default: 723 request_type_ = NO_PENDING_REQUEST; 724 HandleWalletError(NETWORK_ERROR); 725 return; 726 } 727 728 RequestType type = request_type_; 729 request_type_ = NO_PENDING_REQUEST; 730 731 if (!(type == ACCEPT_LEGAL_DOCUMENTS || type == SEND_STATUS) && 732 !response_dict) { 733 HandleMalformedResponse(scoped_request.get()); 734 return; 735 } 736 737 switch (type) { 738 case ACCEPT_LEGAL_DOCUMENTS: 739 delegate_->OnDidAcceptLegalDocuments(); 740 break; 741 742 case AUTHENTICATE_INSTRUMENT: { 743 std::string auth_result; 744 if (response_dict->GetString(kAuthResultKey, &auth_result)) { 745 std::string trimmed; 746 TrimWhitespaceASCII(auth_result, 747 TRIM_ALL, 748 &trimmed); 749 delegate_->OnDidAuthenticateInstrument( 750 LowerCaseEqualsASCII(trimmed, "success")); 751 } else { 752 HandleMalformedResponse(scoped_request.get()); 753 } 754 break; 755 } 756 757 case SEND_STATUS: 758 break; 759 760 case GET_FULL_WALLET: { 761 scoped_ptr<FullWallet> full_wallet( 762 FullWallet::CreateFullWallet(*response_dict)); 763 if (full_wallet) { 764 full_wallet->set_one_time_pad(one_time_pad_); 765 LogRequiredActions(full_wallet->required_actions()); 766 delegate_->OnDidGetFullWallet(full_wallet.Pass()); 767 } else { 768 HandleMalformedResponse(scoped_request.get()); 769 } 770 break; 771 } 772 773 case GET_WALLET_ITEMS: { 774 scoped_ptr<WalletItems> wallet_items( 775 WalletItems::CreateWalletItems(*response_dict)); 776 if (wallet_items) { 777 LogRequiredActions(wallet_items->required_actions()); 778 delegate_->OnDidGetWalletItems(wallet_items.Pass()); 779 } else { 780 HandleMalformedResponse(scoped_request.get()); 781 } 782 break; 783 } 784 785 case SAVE_TO_WALLET: { 786 std::string instrument_id; 787 response_dict->GetString(kInstrumentIdKey, &instrument_id); 788 std::string shipping_address_id; 789 response_dict->GetString(kShippingAddressIdKey, 790 &shipping_address_id); 791 std::vector<RequiredAction> required_actions; 792 GetRequiredActionsForSaveToWallet(*response_dict, &required_actions); 793 std::vector<FormFieldError> form_errors; 794 GetFormFieldErrors(*response_dict, &form_errors); 795 if (instrument_id.empty() && shipping_address_id.empty() && 796 required_actions.empty()) { 797 HandleMalformedResponse(scoped_request.get()); 798 } else { 799 LogRequiredActions(required_actions); 800 delegate_->OnDidSaveToWallet(instrument_id, 801 shipping_address_id, 802 required_actions, 803 form_errors); 804 } 805 break; 806 } 807 808 case NO_PENDING_REQUEST: 809 NOTREACHED(); 810 } 811 } 812 813 void WalletClient::StartNextPendingRequest() { 814 if (pending_requests_.empty()) 815 return; 816 817 base::Closure next_request = pending_requests_.front(); 818 pending_requests_.pop(); 819 next_request.Run(); 820 } 821 822 void WalletClient::HandleMalformedResponse(net::URLFetcher* request) { 823 // Called to inform exponential backoff logic of the error. 824 request->ReceivedContentWasMalformed(); 825 HandleWalletError(MALFORMED_RESPONSE); 826 } 827 828 void WalletClient::HandleWalletError(WalletClient::ErrorType error_type) { 829 std::string error_message; 830 switch (error_type) { 831 case WalletClient::BAD_REQUEST: 832 error_message = "WALLET_BAD_REQUEST"; 833 break; 834 case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED: 835 error_message = "WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED"; 836 break; 837 case WalletClient::BUYER_ACCOUNT_ERROR: 838 error_message = "WALLET_BUYER_ACCOUNT_ERROR"; 839 break; 840 case WalletClient::INTERNAL_ERROR: 841 error_message = "WALLET_INTERNAL_ERROR"; 842 break; 843 case WalletClient::INVALID_PARAMS: 844 error_message = "WALLET_INVALID_PARAMS"; 845 break; 846 case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS: 847 error_message = "WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS"; 848 break; 849 case WalletClient::SERVICE_UNAVAILABLE: 850 error_message = "WALLET_SERVICE_UNAVAILABLE"; 851 break; 852 case WalletClient::UNSUPPORTED_API_VERSION: 853 error_message = "WALLET_UNSUPPORTED_API_VERSION"; 854 break; 855 case WalletClient::UNSUPPORTED_MERCHANT: 856 error_message = "WALLET_UNSUPPORTED_MERCHANT"; 857 break; 858 case WalletClient::MALFORMED_RESPONSE: 859 error_message = "WALLET_MALFORMED_RESPONSE"; 860 break; 861 case WalletClient::NETWORK_ERROR: 862 error_message = "WALLET_NETWORK_ERROR"; 863 break; 864 case WalletClient::UNKNOWN_ERROR: 865 error_message = "WALLET_UNKNOWN_ERROR"; 866 break; 867 } 868 869 VLOG(1) << "Wallet encountered a " << error_message; 870 871 delegate_->OnWalletError(error_type); 872 delegate_->GetMetricLogger().LogWalletErrorMetric( 873 delegate_->GetDialogType(), ErrorTypeToUmaMetric(error_type)); 874 } 875 876 // Logs an UMA metric for each of the |required_actions|. 877 void WalletClient::LogRequiredActions( 878 const std::vector<RequiredAction>& required_actions) const { 879 for (size_t i = 0; i < required_actions.size(); ++i) { 880 delegate_->GetMetricLogger().LogWalletRequiredActionMetric( 881 delegate_->GetDialogType(), 882 RequiredActionToUmaMetric(required_actions[i])); 883 } 884 } 885 886 AutofillMetrics::WalletApiCallMetric WalletClient::RequestTypeToUmaMetric( 887 RequestType request_type) const { 888 switch (request_type) { 889 case ACCEPT_LEGAL_DOCUMENTS: 890 return AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS; 891 case AUTHENTICATE_INSTRUMENT: 892 return AutofillMetrics::AUTHENTICATE_INSTRUMENT; 893 case GET_FULL_WALLET: 894 return AutofillMetrics::GET_FULL_WALLET; 895 case GET_WALLET_ITEMS: 896 return AutofillMetrics::GET_WALLET_ITEMS; 897 case SAVE_TO_WALLET: 898 return AutofillMetrics::SAVE_TO_WALLET; 899 case SEND_STATUS: 900 return AutofillMetrics::SEND_STATUS; 901 case NO_PENDING_REQUEST: 902 NOTREACHED(); 903 return AutofillMetrics::UNKNOWN_API_CALL; 904 } 905 906 NOTREACHED(); 907 return AutofillMetrics::UNKNOWN_API_CALL; 908 } 909 910 } // namespace wallet 911 } // namespace autofill 912