Home | History | Annotate | Download | only in wallet
      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