summaryrefslogtreecommitdiffstats
path: root/chromium/components/autofill/content/browser/wallet/wallet_client.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/autofill/content/browser/wallet/wallet_client.cc')
-rw-r--r--chromium/components/autofill/content/browser/wallet/wallet_client.cc815
1 files changed, 0 insertions, 815 deletions
diff --git a/chromium/components/autofill/content/browser/wallet/wallet_client.cc b/chromium/components/autofill/content/browser/wallet/wallet_client.cc
deleted file mode 100644
index b0e4588728d..00000000000
--- a/chromium/components/autofill/content/browser/wallet/wallet_client.cc
+++ /dev/null
@@ -1,815 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/content/browser/wallet/wallet_client.h"
-
-#include "base/bind.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/content/browser/wallet/form_field_error.h"
-#include "components/autofill/content/browser/wallet/instrument.h"
-#include "components/autofill/content/browser/wallet/wallet_address.h"
-#include "components/autofill/content/browser/wallet/wallet_client_delegate.h"
-#include "components/autofill/content/browser/wallet/wallet_items.h"
-#include "components/autofill/content/browser/wallet/wallet_service_url.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
-#include "crypto/random.h"
-#include "google_apis/google_api_keys.h"
-#include "net/base/escape.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
-
-// TODO(ahutter): Change all VLOGs to DVLOGs after dogfood.
-namespace autofill {
-namespace wallet {
-
-namespace {
-
-const char kFormEncodedMimeType[] = "application/x-www-form-urlencoded";
-const char kJsonMimeType[] = "application/json";
-const char kEscrowNewInstrumentFormat[] =
- "request_content_type=application/json&request=%s&cvn=%s&card_number=%s";
-const char kEscrowCardVerificationNumberFormat[] =
- "request_content_type=application/json&request=%s&cvn=%s";
-const char kGetFullWalletRequestFormat[] =
- "request_content_type=application/json&request=%s&otp=%s:%s";
-const size_t kOneTimePadLength = 6;
-
-// The maximum number of bits in the one time pad that the server is willing to
-// accept.
-const size_t kMaxBits = 56;
-
-// The minimum number of bits in the one time pad that the server is willing to
-// accept.
-const size_t kMinBits = 40;
-
-std::string RiskCapabilityToString(
- WalletClient::RiskCapability risk_capability) {
- switch (risk_capability) {
- case WalletClient::RELOGIN:
- return "RELOGIN";
- case WalletClient::VERIFY_CVC:
- return "VERIFY_CVC";
- }
- NOTREACHED();
- return "NOT_POSSIBLE";
-}
-
-WalletClient::ErrorType StringToErrorType(const std::string& error_type) {
- std::string trimmed;
- TrimWhitespaceASCII(error_type,
- TRIM_ALL,
- &trimmed);
- if (LowerCaseEqualsASCII(trimmed, "buyer_account_error"))
- return WalletClient::BUYER_ACCOUNT_ERROR;
- if (LowerCaseEqualsASCII(trimmed, "unsupported_merchant"))
- return WalletClient::UNSUPPORTED_MERCHANT;
- if (LowerCaseEqualsASCII(trimmed, "internal_error"))
- return WalletClient::INTERNAL_ERROR;
- if (LowerCaseEqualsASCII(trimmed, "invalid_params"))
- return WalletClient::INVALID_PARAMS;
- if (LowerCaseEqualsASCII(trimmed, "service_unavailable"))
- return WalletClient::SERVICE_UNAVAILABLE;
- if (LowerCaseEqualsASCII(trimmed, "unsupported_api_version"))
- return WalletClient::UNSUPPORTED_API_VERSION;
-
- return WalletClient::UNKNOWN_ERROR;
-}
-
-// Get the more specific WalletClient::ErrorType when the error is
-// |BUYER_ACCOUNT_ERROR|.
-WalletClient::ErrorType BuyerErrorStringToErrorType(
- const std::string& message_type_for_buyer) {
- std::string trimmed;
- TrimWhitespaceASCII(message_type_for_buyer,
- TRIM_ALL,
- &trimmed);
- if (LowerCaseEqualsASCII(trimmed, "bla_country_not_supported"))
- return WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
- if (LowerCaseEqualsASCII(trimmed, "buyer_kyc_error"))
- return WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
-
- return WalletClient::BUYER_ACCOUNT_ERROR;
-}
-
-// Gets and parses required actions from a SaveToWallet response. Returns
-// false if any unknown required actions are seen and true otherwise.
-void GetRequiredActionsForSaveToWallet(
- const base::DictionaryValue& dict,
- std::vector<RequiredAction>* required_actions) {
- const base::ListValue* required_action_list;
- if (!dict.GetList("required_action", &required_action_list))
- return;
-
- for (size_t i = 0; i < required_action_list->GetSize(); ++i) {
- std::string action_string;
- if (required_action_list->GetString(i, &action_string)) {
- RequiredAction action = ParseRequiredActionFromString(action_string);
- if (!ActionAppliesToSaveToWallet(action)) {
- DLOG(ERROR) << "Response from Google wallet with bad required action:"
- " \"" << action_string << "\"";
- required_actions->clear();
- return;
- }
- required_actions->push_back(action);
- }
- }
-}
-
-void GetFormFieldErrors(const base::DictionaryValue& dict,
- std::vector<FormFieldError>* form_errors) {
- DCHECK(form_errors->empty());
- const base::ListValue* form_errors_list;
- if (!dict.GetList("form_field_error", &form_errors_list))
- return;
-
- for (size_t i = 0; i < form_errors_list->GetSize(); ++i) {
- const base::DictionaryValue* dictionary;
- if (form_errors_list->GetDictionary(i, &dictionary))
- form_errors->push_back(FormFieldError::CreateFormFieldError(*dictionary));
- }
-}
-
-// Converts the |error_type| to the corresponding value from the stable UMA
-// metric enumeration.
-AutofillMetrics::WalletErrorMetric ErrorTypeToUmaMetric(
- WalletClient::ErrorType error_type) {
- switch (error_type) {
- case WalletClient::BAD_REQUEST:
- return AutofillMetrics::WALLET_BAD_REQUEST;
- case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
- return AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
- case WalletClient::BUYER_ACCOUNT_ERROR:
- return AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR;
- case WalletClient::INTERNAL_ERROR:
- return AutofillMetrics::WALLET_INTERNAL_ERROR;
- case WalletClient::INVALID_PARAMS:
- return AutofillMetrics::WALLET_INVALID_PARAMS;
- case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
- return AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
- case WalletClient::SERVICE_UNAVAILABLE:
- return AutofillMetrics::WALLET_SERVICE_UNAVAILABLE;
- case WalletClient::UNSUPPORTED_API_VERSION:
- return AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION;
- case WalletClient::UNSUPPORTED_MERCHANT:
- return AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT;
- case WalletClient::MALFORMED_RESPONSE:
- return AutofillMetrics::WALLET_MALFORMED_RESPONSE;
- case WalletClient::NETWORK_ERROR:
- return AutofillMetrics::WALLET_NETWORK_ERROR;
- case WalletClient::UNKNOWN_ERROR:
- return AutofillMetrics::WALLET_UNKNOWN_ERROR;
- }
-
- NOTREACHED();
- return AutofillMetrics::WALLET_UNKNOWN_ERROR;
-}
-
-// Converts the |required_action| to the corresponding value from the stable UMA
-// metric enumeration.
-AutofillMetrics::WalletRequiredActionMetric RequiredActionToUmaMetric(
- RequiredAction required_action) {
- switch (required_action) {
- case UNKNOWN_TYPE:
- return AutofillMetrics::UNKNOWN_REQUIRED_ACTION;
- case CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS:
- return AutofillMetrics::CHOOSE_ANOTHER_INSTRUMENT_OR_ADDRESS;
- case SETUP_WALLET:
- return AutofillMetrics::SETUP_WALLET;
- case ACCEPT_TOS:
- return AutofillMetrics::ACCEPT_TOS;
- case GAIA_AUTH:
- return AutofillMetrics::GAIA_AUTH;
- case UPDATE_EXPIRATION_DATE:
- return AutofillMetrics::UPDATE_EXPIRATION_DATE;
- case UPGRADE_MIN_ADDRESS:
- return AutofillMetrics::UPGRADE_MIN_ADDRESS;
- case INVALID_FORM_FIELD:
- return AutofillMetrics::INVALID_FORM_FIELD;
- case VERIFY_CVV:
- return AutofillMetrics::VERIFY_CVV;
- case PASSIVE_GAIA_AUTH:
- return AutofillMetrics::PASSIVE_GAIA_AUTH;
- case REQUIRE_PHONE_NUMBER:
- return AutofillMetrics::REQUIRE_PHONE_NUMBER;
- }
-
- NOTREACHED();
- return AutofillMetrics::UNKNOWN_REQUIRED_ACTION;
-}
-
-// Keys for JSON communication with the Online Wallet server.
-const char kAcceptedLegalDocumentKey[] = "accepted_legal_document";
-const char kApiKeyKey[] = "api_key";
-const char kAuthResultKey[] = "auth_result";
-const char kErrorTypeKey[] = "wallet_error.error_type";
-const char kFeatureKey[] = "feature";
-const char kGoogleTransactionIdKey[] = "google_transaction_id";
-const char kInstrumentIdKey[] = "instrument_id";
-const char kInstrumentKey[] = "instrument";
-const char kInstrumentExpMonthKey[] = "instrument.credit_card.exp_month";
-const char kInstrumentExpYearKey[] = "instrument.credit_card.exp_year";
-const char kInstrumentType[] = "instrument.type";
-const char kInstrumentPhoneNumberKey[] = "instrument_phone_number";
-const char kMerchantDomainKey[] = "merchant_domain";
-const char kMessageTypeForBuyerKey[] = "wallet_error.message_type_for_buyer";
-const char kNewWalletUser[] = "new_wallet_user";
-const char kPhoneNumberRequired[] = "phone_number_required";
-const char kRiskCapabilitiesKey[] = "supported_risk_challenge";
-const char kRiskParamsKey[] = "risk_params";
-const char kSelectedAddressIdKey[] = "selected_address_id";
-const char kSelectedInstrumentIdKey[] = "selected_instrument_id";
-const char kShippingAddressIdKey[] = "shipping_address_id";
-const char kShippingAddressKey[] = "shipping_address";
-const char kShippingAddressRequired[] = "shipping_address_required";
-const char kUpgradedBillingAddressKey[] = "upgraded_billing_address";
-const char kUpgradedInstrumentIdKey[] = "upgraded_instrument_id";
-const char kUseMinimalAddresses[] = "use_minimal_addresses";
-
-} // namespace
-
-WalletClient::FullWalletRequest::FullWalletRequest(
- const std::string& instrument_id,
- const std::string& address_id,
- const std::string& google_transaction_id,
- const std::vector<RiskCapability> risk_capabilities,
- bool new_wallet_user)
- : instrument_id(instrument_id),
- address_id(address_id),
- google_transaction_id(google_transaction_id),
- risk_capabilities(risk_capabilities),
- new_wallet_user(new_wallet_user) {}
-
-WalletClient::FullWalletRequest::~FullWalletRequest() {}
-
-WalletClient::WalletClient(net::URLRequestContextGetter* context_getter,
- WalletClientDelegate* delegate,
- const GURL& source_url)
- : context_getter_(context_getter),
- delegate_(delegate),
- user_index_(0U),
- source_url_(source_url),
- request_type_(NO_PENDING_REQUEST),
- one_time_pad_(kOneTimePadLength),
- weak_ptr_factory_(this) {
- DCHECK(context_getter_.get());
- DCHECK(delegate_);
-}
-
-WalletClient::~WalletClient() {}
-
-void WalletClient::AcceptLegalDocuments(
- const std::vector<WalletItems::LegalDocument*>& documents,
- const std::string& google_transaction_id) {
- if (documents.empty())
- return;
-
- std::vector<std::string> document_ids;
- for (size_t i = 0; i < documents.size(); ++i) {
- document_ids.push_back(documents[i]->id());
- }
- DoAcceptLegalDocuments(document_ids, google_transaction_id);
-}
-
-void WalletClient::AuthenticateInstrument(
- const std::string& instrument_id,
- const std::string& card_verification_number) {
- base::DictionaryValue request_dict;
- request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
- request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData());
- request_dict.SetString(kInstrumentIdKey, instrument_id);
-
- std::string json_payload;
- base::JSONWriter::Write(&request_dict, &json_payload);
-
- std::string escaped_card_verification_number = net::EscapeUrlEncodedData(
- card_verification_number, true);
-
- std::string post_body = base::StringPrintf(
- kEscrowCardVerificationNumberFormat,
- net::EscapeUrlEncodedData(json_payload, true).c_str(),
- escaped_card_verification_number.c_str());
-
- MakeWalletRequest(GetAuthenticateInstrumentUrl(user_index_),
- post_body,
- kFormEncodedMimeType,
- AUTHENTICATE_INSTRUMENT);
-}
-
-void WalletClient::GetFullWallet(const FullWalletRequest& full_wallet_request) {
- base::DictionaryValue request_dict;
- request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
- request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData());
- request_dict.SetBoolean(kUseMinimalAddresses, false);
- request_dict.SetBoolean(kPhoneNumberRequired, true);
- request_dict.SetBoolean(kNewWalletUser, full_wallet_request.new_wallet_user);
-
- request_dict.SetString(kSelectedInstrumentIdKey,
- full_wallet_request.instrument_id);
- request_dict.SetString(kSelectedAddressIdKey, full_wallet_request.address_id);
- request_dict.SetString(
- kMerchantDomainKey,
- source_url_.GetWithEmptyPath().spec());
- request_dict.SetString(kGoogleTransactionIdKey,
- full_wallet_request.google_transaction_id);
- request_dict.SetString(kFeatureKey, "REQUEST_AUTOCOMPLETE");
-
- scoped_ptr<base::ListValue> risk_capabilities_list(new base::ListValue());
- for (std::vector<RiskCapability>::const_iterator it =
- full_wallet_request.risk_capabilities.begin();
- it != full_wallet_request.risk_capabilities.end();
- ++it) {
- risk_capabilities_list->AppendString(RiskCapabilityToString(*it));
- }
- request_dict.Set(kRiskCapabilitiesKey, risk_capabilities_list.release());
-
- std::string json_payload;
- base::JSONWriter::Write(&request_dict, &json_payload);
-
- crypto::RandBytes(&(one_time_pad_[0]), one_time_pad_.size());
-
- size_t num_bits = one_time_pad_.size() * 8;
- DCHECK_LE(num_bits, kMaxBits);
- DCHECK_GE(num_bits, kMinBits);
-
- std::string post_body = base::StringPrintf(
- kGetFullWalletRequestFormat,
- net::EscapeUrlEncodedData(json_payload, true).c_str(),
- base::HexEncode(&num_bits, 1).c_str(),
- base::HexEncode(&(one_time_pad_[0]), one_time_pad_.size()).c_str());
-
- MakeWalletRequest(GetGetFullWalletUrl(user_index_),
- post_body,
- kFormEncodedMimeType,
- GET_FULL_WALLET);
-}
-
-void WalletClient::SaveToWallet(
- scoped_ptr<Instrument> instrument,
- scoped_ptr<Address> address,
- const WalletItems::MaskedInstrument* reference_instrument,
- const Address* reference_address) {
- DCHECK(instrument || address);
-
- base::DictionaryValue request_dict;
- request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
- request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData());
- request_dict.SetString(kMerchantDomainKey,
- source_url_.GetWithEmptyPath().spec());
- request_dict.SetBoolean(kUseMinimalAddresses, false);
- request_dict.SetBoolean(kPhoneNumberRequired, true);
-
- std::string primary_account_number;
- std::string card_verification_number;
- if (instrument) {
- primary_account_number = net::EscapeUrlEncodedData(
- UTF16ToUTF8(instrument->primary_account_number()), true);
- card_verification_number = net::EscapeUrlEncodedData(
- UTF16ToUTF8(instrument->card_verification_number()), true);
-
- if (!reference_instrument) {
- request_dict.Set(kInstrumentKey, instrument->ToDictionary().release());
- request_dict.SetString(kInstrumentPhoneNumberKey,
- instrument->address()->phone_number());
- } else {
- DCHECK(!reference_instrument->object_id().empty());
-
- int new_month = instrument->expiration_month();
- int new_year = instrument->expiration_year();
- bool expiration_date_changed =
- new_month != reference_instrument->expiration_month() ||
- new_year != reference_instrument->expiration_year();
-
- DCHECK(instrument->address() || expiration_date_changed);
-
- request_dict.SetString(kUpgradedInstrumentIdKey,
- reference_instrument->object_id());
-
- if (instrument->address()) {
- request_dict.SetString(kInstrumentPhoneNumberKey,
- instrument->address()->phone_number());
- request_dict.Set(
- kUpgradedBillingAddressKey,
- instrument->address()->ToDictionaryWithoutID().release());
- }
-
- if (expiration_date_changed) {
- // Updating expiration date requires a CVC.
- DCHECK(!instrument->card_verification_number().empty());
- request_dict.SetInteger(kInstrumentExpMonthKey,
- instrument->expiration_month());
- request_dict.SetInteger(kInstrumentExpYearKey,
- instrument->expiration_year());
- }
-
- if (request_dict.HasKey(kInstrumentKey))
- request_dict.SetString(kInstrumentType, "CREDIT_CARD");
- }
- }
- if (address) {
- if (reference_address) {
- address->set_object_id(reference_address->object_id());
- DCHECK(!address->object_id().empty());
- }
- request_dict.Set(kShippingAddressKey,
- address->ToDictionaryWithID().release());
- }
-
- std::string json_payload;
- base::JSONWriter::Write(&request_dict, &json_payload);
-
- if (!card_verification_number.empty()) {
- std::string post_body;
- if (!primary_account_number.empty()) {
- post_body = base::StringPrintf(
- kEscrowNewInstrumentFormat,
- net::EscapeUrlEncodedData(json_payload, true).c_str(),
- card_verification_number.c_str(),
- primary_account_number.c_str());
- } else {
- post_body = base::StringPrintf(
- kEscrowCardVerificationNumberFormat,
- net::EscapeUrlEncodedData(json_payload, true).c_str(),
- card_verification_number.c_str());
- }
- MakeWalletRequest(GetSaveToWalletUrl(user_index_),
- post_body,
- kFormEncodedMimeType,
- SAVE_TO_WALLET);
- } else {
- MakeWalletRequest(GetSaveToWalletNoEscrowUrl(user_index_),
- json_payload,
- kJsonMimeType,
- SAVE_TO_WALLET);
- }
-}
-
-void WalletClient::GetWalletItems() {
- base::DictionaryValue request_dict;
- request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
- request_dict.SetString(kMerchantDomainKey,
- source_url_.GetWithEmptyPath().spec());
- request_dict.SetBoolean(kShippingAddressRequired,
- delegate_->IsShippingAddressRequired());
- request_dict.SetBoolean(kUseMinimalAddresses, false);
- request_dict.SetBoolean(kPhoneNumberRequired, true);
-
- std::string post_body;
- base::JSONWriter::Write(&request_dict, &post_body);
-
- MakeWalletRequest(GetGetWalletItemsUrl(user_index_),
- post_body,
- kJsonMimeType,
- GET_WALLET_ITEMS);
-}
-
-bool WalletClient::HasRequestInProgress() const {
- return request_;
-}
-
-void WalletClient::CancelRequests() {
- request_.reset();
- request_type_ = NO_PENDING_REQUEST;
- while (!pending_requests_.empty()) {
- pending_requests_.pop();
- }
-}
-
-void WalletClient::SetUserIndex(size_t user_index) {
- CancelRequests();
- user_index_ = user_index;
-}
-
-void WalletClient::DoAcceptLegalDocuments(
- const std::vector<std::string>& document_ids,
- const std::string& google_transaction_id) {
- base::DictionaryValue request_dict;
- request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
- request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id);
- request_dict.SetString(kMerchantDomainKey,
- source_url_.GetWithEmptyPath().spec());
- scoped_ptr<base::ListValue> docs_list(new base::ListValue());
- for (std::vector<std::string>::const_iterator it = document_ids.begin();
- it != document_ids.end(); ++it) {
- if (!it->empty())
- docs_list->AppendString(*it);
- }
- request_dict.Set(kAcceptedLegalDocumentKey, docs_list.release());
-
- std::string post_body;
- base::JSONWriter::Write(&request_dict, &post_body);
-
- MakeWalletRequest(GetAcceptLegalDocumentsUrl(user_index_),
- post_body,
- kJsonMimeType,
- ACCEPT_LEGAL_DOCUMENTS);
-}
-
-void WalletClient::MakeWalletRequest(const GURL& url,
- const std::string& post_body,
- const std::string& mime_type,
- RequestType request_type) {
- if (HasRequestInProgress()) {
- pending_requests_.push(base::Bind(&WalletClient::MakeWalletRequest,
- base::Unretained(this),
- url,
- post_body,
- mime_type,
- request_type));
- return;
- }
-
- DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
- request_type_ = request_type;
-
- request_.reset(net::URLFetcher::Create(
- 0, url, net::URLFetcher::POST, this));
- request_->SetRequestContext(context_getter_.get());
- VLOG(1) << "Making request to " << url << " with post_body=" << post_body;
- request_->SetUploadData(mime_type, post_body);
- request_->AddExtraRequestHeader("Authorization: GoogleLogin auth=" +
- delegate_->GetWalletCookieValue());
- DVLOG(1) << "Setting authorization header value to "
- << delegate_->GetWalletCookieValue();
- request_started_timestamp_ = base::Time::Now();
- request_->Start();
-
- delegate_->GetMetricLogger().LogWalletErrorMetric(
- AutofillMetrics::WALLET_ERROR_BASELINE_ISSUED_REQUEST);
- delegate_->GetMetricLogger().LogWalletRequiredActionMetric(
- AutofillMetrics::WALLET_REQUIRED_ACTION_BASELINE_ISSUED_REQUEST);
-}
-
-// TODO(ahutter): Add manual retry logic if it's necessary.
-void WalletClient::OnURLFetchComplete(
- const net::URLFetcher* source) {
- delegate_->GetMetricLogger().LogWalletApiCallDuration(
- RequestTypeToUmaMetric(request_type_),
- base::Time::Now() - request_started_timestamp_);
-
- DCHECK_EQ(source, request_.get());
- VLOG(1) << "Got response from " << source->GetOriginalURL();
-
- // |request_|, which is aliased to |source|, might continue to be used in this
- // |method, but should be freed once control leaves the method.
- scoped_ptr<net::URLFetcher> scoped_request(request_.Pass());
-
- // Prepare to start the next pending request. This is queued up as an
- // asynchronous message because |this| WalletClient instance can be destroyed
- // before the end of the method in response to the current incoming request.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&WalletClient::StartNextPendingRequest,
- weak_ptr_factory_.GetWeakPtr()));;
-
- std::string data;
- source->GetResponseAsString(&data);
- VLOG(1) << "Response body: " << data;
-
- scoped_ptr<base::DictionaryValue> response_dict;
-
- int response_code = source->GetResponseCode();
- delegate_->GetMetricLogger().LogWalletResponseCode(response_code);
-
- switch (response_code) {
- // HTTP_BAD_REQUEST means the arguments are invalid. No point retrying.
- case net::HTTP_BAD_REQUEST: {
- request_type_ = NO_PENDING_REQUEST;
- HandleWalletError(BAD_REQUEST);
- return;
- }
- // HTTP_OK holds a valid response and HTTP_INTERNAL_SERVER_ERROR holds an
- // error code and message for the user.
- case net::HTTP_OK:
- case net::HTTP_INTERNAL_SERVER_ERROR: {
- scoped_ptr<Value> message_value(base::JSONReader::Read(data));
- if (message_value.get() &&
- message_value->IsType(Value::TYPE_DICTIONARY)) {
- response_dict.reset(
- static_cast<base::DictionaryValue*>(message_value.release()));
- }
- if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) {
- request_type_ = NO_PENDING_REQUEST;
-
- std::string error_type_string;
- if (!response_dict->GetString(kErrorTypeKey, &error_type_string)) {
- HandleWalletError(UNKNOWN_ERROR);
- return;
- }
- WalletClient::ErrorType error_type =
- StringToErrorType(error_type_string);
- if (error_type == BUYER_ACCOUNT_ERROR) {
- // If the error_type is |BUYER_ACCOUNT_ERROR|, then
- // message_type_for_buyer field contains more specific information
- // about the error.
- std::string message_type_for_buyer_string;
- if (response_dict->GetString(kMessageTypeForBuyerKey,
- &message_type_for_buyer_string)) {
- error_type = BuyerErrorStringToErrorType(
- message_type_for_buyer_string);
- }
- }
-
- HandleWalletError(error_type);
- return;
- }
- break;
- }
-
- // Anything else is an error.
- default:
- request_type_ = NO_PENDING_REQUEST;
- HandleWalletError(NETWORK_ERROR);
- return;
- }
-
- RequestType type = request_type_;
- request_type_ = NO_PENDING_REQUEST;
-
- if (type != ACCEPT_LEGAL_DOCUMENTS && !response_dict) {
- HandleMalformedResponse(type, scoped_request.get());
- return;
- }
-
- switch (type) {
- case ACCEPT_LEGAL_DOCUMENTS:
- delegate_->OnDidAcceptLegalDocuments();
- break;
-
- case AUTHENTICATE_INSTRUMENT: {
- std::string auth_result;
- if (response_dict->GetString(kAuthResultKey, &auth_result)) {
- std::string trimmed;
- TrimWhitespaceASCII(auth_result,
- TRIM_ALL,
- &trimmed);
- delegate_->OnDidAuthenticateInstrument(
- LowerCaseEqualsASCII(trimmed, "success"));
- } else {
- HandleMalformedResponse(type, scoped_request.get());
- }
- break;
- }
-
- case GET_FULL_WALLET: {
- scoped_ptr<FullWallet> full_wallet(
- FullWallet::CreateFullWallet(*response_dict));
- if (full_wallet) {
- full_wallet->set_one_time_pad(one_time_pad_);
- LogRequiredActions(full_wallet->required_actions());
- delegate_->OnDidGetFullWallet(full_wallet.Pass());
- } else {
- HandleMalformedResponse(type, scoped_request.get());
- }
- break;
- }
-
- case GET_WALLET_ITEMS: {
- scoped_ptr<WalletItems> wallet_items(
- WalletItems::CreateWalletItems(*response_dict));
- if (wallet_items) {
- LogRequiredActions(wallet_items->required_actions());
- delegate_->OnDidGetWalletItems(wallet_items.Pass());
- } else {
- HandleMalformedResponse(type, scoped_request.get());
- }
- break;
- }
-
- case SAVE_TO_WALLET: {
- std::string instrument_id;
- response_dict->GetString(kInstrumentIdKey, &instrument_id);
- std::string shipping_address_id;
- response_dict->GetString(kShippingAddressIdKey,
- &shipping_address_id);
- std::vector<RequiredAction> required_actions;
- GetRequiredActionsForSaveToWallet(*response_dict, &required_actions);
- std::vector<FormFieldError> form_errors;
- GetFormFieldErrors(*response_dict, &form_errors);
- if (instrument_id.empty() && shipping_address_id.empty() &&
- required_actions.empty()) {
- HandleMalformedResponse(type, scoped_request.get());
- } else {
- LogRequiredActions(required_actions);
- delegate_->OnDidSaveToWallet(instrument_id,
- shipping_address_id,
- required_actions,
- form_errors);
- }
- break;
- }
-
- case NO_PENDING_REQUEST:
- NOTREACHED();
- }
-}
-
-void WalletClient::StartNextPendingRequest() {
- if (pending_requests_.empty())
- return;
-
- base::Closure next_request = pending_requests_.front();
- pending_requests_.pop();
- next_request.Run();
-}
-
-void WalletClient::HandleMalformedResponse(RequestType request_type,
- net::URLFetcher* request) {
- // Called to inform exponential backoff logic of the error.
- request->ReceivedContentWasMalformed();
- // Record failed API call in metrics.
- delegate_->GetMetricLogger().LogWalletMalformedResponseMetric(
- RequestTypeToUmaMetric(request_type));
- HandleWalletError(MALFORMED_RESPONSE);
-}
-
-void WalletClient::HandleWalletError(WalletClient::ErrorType error_type) {
- std::string error_message;
- switch (error_type) {
- case WalletClient::BAD_REQUEST:
- error_message = "WALLET_BAD_REQUEST";
- break;
- case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
- error_message = "WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED";
- break;
- case WalletClient::BUYER_ACCOUNT_ERROR:
- error_message = "WALLET_BUYER_ACCOUNT_ERROR";
- break;
- case WalletClient::INTERNAL_ERROR:
- error_message = "WALLET_INTERNAL_ERROR";
- break;
- case WalletClient::INVALID_PARAMS:
- error_message = "WALLET_INVALID_PARAMS";
- break;
- case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
- error_message = "WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS";
- break;
- case WalletClient::SERVICE_UNAVAILABLE:
- error_message = "WALLET_SERVICE_UNAVAILABLE";
- break;
- case WalletClient::UNSUPPORTED_API_VERSION:
- error_message = "WALLET_UNSUPPORTED_API_VERSION";
- break;
- case WalletClient::UNSUPPORTED_MERCHANT:
- error_message = "WALLET_UNSUPPORTED_MERCHANT";
- break;
- case WalletClient::MALFORMED_RESPONSE:
- error_message = "WALLET_MALFORMED_RESPONSE";
- break;
- case WalletClient::NETWORK_ERROR:
- error_message = "WALLET_NETWORK_ERROR";
- break;
- case WalletClient::UNKNOWN_ERROR:
- error_message = "WALLET_UNKNOWN_ERROR";
- break;
- }
-
- VLOG(1) << "Wallet encountered a " << error_message;
-
- delegate_->OnWalletError(error_type);
- delegate_->GetMetricLogger().LogWalletErrorMetric(
- ErrorTypeToUmaMetric(error_type));
-}
-
-// Logs an UMA metric for each of the |required_actions|.
-void WalletClient::LogRequiredActions(
- const std::vector<RequiredAction>& required_actions) const {
- for (size_t i = 0; i < required_actions.size(); ++i) {
- delegate_->GetMetricLogger().LogWalletRequiredActionMetric(
- RequiredActionToUmaMetric(required_actions[i]));
- }
-}
-
-AutofillMetrics::WalletApiCallMetric WalletClient::RequestTypeToUmaMetric(
- RequestType request_type) const {
- switch (request_type) {
- case ACCEPT_LEGAL_DOCUMENTS:
- return AutofillMetrics::ACCEPT_LEGAL_DOCUMENTS;
- case AUTHENTICATE_INSTRUMENT:
- return AutofillMetrics::AUTHENTICATE_INSTRUMENT;
- case GET_FULL_WALLET:
- return AutofillMetrics::GET_FULL_WALLET;
- case GET_WALLET_ITEMS:
- return AutofillMetrics::GET_WALLET_ITEMS;
- case SAVE_TO_WALLET:
- return AutofillMetrics::SAVE_TO_WALLET;
- case NO_PENDING_REQUEST:
- NOTREACHED();
- return AutofillMetrics::UNKNOWN_API_CALL;
- }
-
- NOTREACHED();
- return AutofillMetrics::UNKNOWN_API_CALL;
-}
-
-} // namespace wallet
-} // namespace autofill