// 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/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 AutocheckoutStatusToString(AutocheckoutStatus status) {
  switch (status) {
    case MISSING_FIELDMAPPING:
      return "MISSING_FIELDMAPPING";
    case MISSING_ADVANCE:
      return "MISSING_ADVANCE";
    case MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING:
      return "MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING";
    case MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING:
      return "MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING";
    case CANNOT_PROCEED:
      return "CANNOT_PROCEED";
    case SUCCESS:
      // SUCCESS cannot be sent to the server as it will result in a failure.
      NOTREACHED();
      return "ERROR";
    case AUTOCHECKOUT_STATUS_NUM_STATUS:
      NOTREACHED();
  }
  NOTREACHED();
  return "NOT_POSSIBLE";
}

std::string DialogTypeToFeatureString(autofill::DialogType dialog_type) {
  switch (dialog_type) {
    case DIALOG_TYPE_REQUEST_AUTOCOMPLETE:
      return "REQUEST_AUTOCOMPLETE";
    case DIALOG_TYPE_AUTOCHECKOUT:
      return "AUTOCHECKOUT";
  }
  NOTREACHED();
  return "NOT_POSSIBLE";
}

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, "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;
}

// 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_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::SERVICE_UNAVAILABLE:
      return AutofillMetrics::WALLET_SERVICE_UNAVAILABLE;
    case WalletClient::UNSUPPORTED_API_VERSION:
      return AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION;
    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 kEncryptedOtpKey[] = "encrypted_otp";
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 kInstrumentEscrowHandleKey[] = "instrument_escrow_handle";
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 kReasonKey[] = "reason";
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 kSessionMaterialKey[] = "session_material";
const char kShippingAddressIdKey[] = "shipping_address_id";
const char kShippingAddressKey[] = "shipping_address";
const char kAutocheckoutStepsKey[] = "steps";
const char kSuccessKey[] = "success";
const char kUpgradedBillingAddressKey[] = "upgraded_billing_address";
const char kUpgradedInstrumentIdKey[] = "upgraded_instrument_id";

}  // namespace

WalletClient::FullWalletRequest::FullWalletRequest(
    const std::string& instrument_id,
    const std::string& address_id,
    const GURL& source_url,
    const std::string& google_transaction_id,
    const std::vector<RiskCapability> risk_capabilities)
    : instrument_id(instrument_id),
      address_id(address_id),
      source_url(source_url),
      google_transaction_id(google_transaction_id),
      risk_capabilities(risk_capabilities) {}

WalletClient::FullWalletRequest::~FullWalletRequest() {}

WalletClient::WalletClient(net::URLRequestContextGetter* context_getter,
                           WalletClientDelegate* delegate)
    : context_getter_(context_getter),
      delegate_(delegate),
      request_type_(NO_PENDING_REQUEST),
      one_time_pad_(kOneTimePadLength) {
  DCHECK(context_getter_.get());
  DCHECK(delegate_);
}

WalletClient::~WalletClient() {}

void WalletClient::AcceptLegalDocuments(
    const std::vector<WalletItems::LegalDocument*>& documents,
    const std::string& google_transaction_id,
    const GURL& source_url) {
  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, source_url);
}

void WalletClient::AuthenticateInstrument(
    const std::string& instrument_id,
    const std::string& card_verification_number) {
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::AuthenticateInstrument,
                                      base::Unretained(this),
                                      instrument_id,
                                      card_verification_number));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = AUTHENTICATE_INSTRUMENT;

  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(),
                    post_body,
                    kFormEncodedMimeType);
}

void WalletClient::GetFullWallet(const FullWalletRequest& full_wallet_request) {
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::GetFullWallet,
                                      base::Unretained(this),
                                      full_wallet_request));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = GET_FULL_WALLET;

  base::DictionaryValue request_dict;
  request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
  request_dict.SetString(kRiskParamsKey, delegate_->GetRiskData());
  request_dict.SetString(kSelectedInstrumentIdKey,
                         full_wallet_request.instrument_id);
  request_dict.SetString(kSelectedAddressIdKey, full_wallet_request.address_id);
  request_dict.SetString(
      kMerchantDomainKey,
      full_wallet_request.source_url.GetWithEmptyPath().spec());
  request_dict.SetString(kGoogleTransactionIdKey,
                         full_wallet_request.google_transaction_id);
  request_dict.SetString(kFeatureKey,
                         DialogTypeToFeatureString(delegate_->GetDialogType()));

  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(), post_body, kFormEncodedMimeType);
}

void WalletClient::SaveToWallet(scoped_ptr<Instrument> instrument,
                                scoped_ptr<Address> address,
                                const GURL& source_url) {
  DCHECK(instrument || address);
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::SaveToWallet,
                                      base::Unretained(this),
                                      base::Passed(&instrument),
                                      base::Passed(&address),
                                      source_url));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = SAVE_TO_WALLET;

  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());

  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 (instrument->object_id().empty()) {
      request_dict.Set(kInstrumentKey, instrument->ToDictionary().release());
      request_dict.SetString(kInstrumentPhoneNumberKey,
                             instrument->address()->phone_number());
    } else {
      DCHECK(instrument->address() ||
             (instrument->expiration_month() > 0 &&
              instrument->expiration_year() > 0));

      request_dict.SetString(kUpgradedInstrumentIdKey,
                             instrument->object_id());

      if (instrument->address()) {
        request_dict.SetString(kInstrumentPhoneNumberKey,
                               instrument->address()->phone_number());
        request_dict.Set(
            kUpgradedBillingAddressKey,
            instrument->address()->ToDictionaryWithoutID().release());
      }

      if (instrument->expiration_month() > 0 &&
          instrument->expiration_year() > 0) {
        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) {
    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(), post_body, kFormEncodedMimeType);
  } else {
    MakeWalletRequest(GetSaveToWalletNoEscrowUrl(),
                      json_payload,
                      kJsonMimeType);
  }
}

void WalletClient::GetWalletItems(const GURL& source_url) {
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::GetWalletItems,
                                      base::Unretained(this),
                                      source_url));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = GET_WALLET_ITEMS;

  base::DictionaryValue request_dict;
  request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
  request_dict.SetString(kMerchantDomainKey,
                         source_url.GetWithEmptyPath().spec());

  std::string post_body;
  base::JSONWriter::Write(&request_dict, &post_body);

  MakeWalletRequest(GetGetWalletItemsUrl(), post_body, kJsonMimeType);
}

void WalletClient::SendAutocheckoutStatus(
    AutocheckoutStatus status,
    const GURL& source_url,
    const std::vector<AutocheckoutStatistic>& latency_statistics,
    const std::string& google_transaction_id) {
  DVLOG(1) << "Sending Autocheckout Status: " << status
           << " for: " << source_url;
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::SendAutocheckoutStatus,
                                      base::Unretained(this),
                                      status,
                                      source_url,
                                      latency_statistics,
                                      google_transaction_id));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = SEND_STATUS;

  base::DictionaryValue request_dict;
  request_dict.SetString(kApiKeyKey, google_apis::GetAPIKey());
  bool success = status == SUCCESS;
  request_dict.SetBoolean(kSuccessKey, success);
  request_dict.SetString(kMerchantDomainKey,
                         source_url.GetWithEmptyPath().spec());
  if (!success)
    request_dict.SetString(kReasonKey, AutocheckoutStatusToString(status));
  if (!latency_statistics.empty()) {
    scoped_ptr<base::ListValue> latency_statistics_json(
        new base::ListValue());
    for (size_t i = 0; i < latency_statistics.size(); ++i) {
      latency_statistics_json->Append(
          latency_statistics[i].ToDictionary().release());
    }
    request_dict.Set(kAutocheckoutStepsKey,
                     latency_statistics_json.release());
  }
  request_dict.SetString(kGoogleTransactionIdKey, google_transaction_id);

  std::string post_body;
  base::JSONWriter::Write(&request_dict, &post_body);

  MakeWalletRequest(GetSendStatusUrl(), post_body, kJsonMimeType);
}

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::DoAcceptLegalDocuments(
    const std::vector<std::string>& document_ids,
    const std::string& google_transaction_id,
    const GURL& source_url) {
  if (HasRequestInProgress()) {
    pending_requests_.push(base::Bind(&WalletClient::DoAcceptLegalDocuments,
                                      base::Unretained(this),
                                      document_ids,
                                      google_transaction_id,
                                      source_url));
    return;
  }

  DCHECK_EQ(NO_PENDING_REQUEST, request_type_);
  request_type_ = ACCEPT_LEGAL_DOCUMENTS;

  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(), post_body, kJsonMimeType);
}

void WalletClient::MakeWalletRequest(const GURL& url,
                                     const std::string& post_body,
                                     const std::string& mime_type) {
  DCHECK(!HasRequestInProgress());

  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(
      delegate_->GetDialogType(),
      AutofillMetrics::WALLET_ERROR_BASELINE_ISSUED_REQUEST);
  delegate_->GetMetricLogger().LogWalletRequiredActionMetric(
      delegate_->GetDialogType(),
      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());

  std::string data;
  source->GetResponseAsString(&data);
  VLOG(1) << "Response body: " << data;

  scoped_ptr<base::DictionaryValue> response_dict;

  int response_code = source->GetResponseCode();
  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;
        if (!response_dict->GetString(kErrorTypeKey, &error_type)) {
          HandleWalletError(UNKNOWN_ERROR);
          return;
        }

        HandleWalletError(StringToErrorType(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 || type == SEND_STATUS) &&
      !response_dict) {
    HandleMalformedResponse(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(scoped_request.get());
      }
      break;
    }

    case SEND_STATUS:
      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(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(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(scoped_request.get());
      } else {
        LogRequiredActions(required_actions);
        delegate_->OnDidSaveToWallet(instrument_id,
                                     shipping_address_id,
                                     required_actions,
                                     form_errors);
      }
      break;
    }

    case NO_PENDING_REQUEST:
      NOTREACHED();
  }

  StartNextPendingRequest();
}

void WalletClient::StartNextPendingRequest() {
  if (pending_requests_.empty())
    return;

  base::Closure next_request = pending_requests_.front();
  pending_requests_.pop();
  next_request.Run();
}

void WalletClient::HandleMalformedResponse(net::URLFetcher* request) {
  // Called to inform exponential backoff logic of the error.
  request->ReceivedContentWasMalformed();
  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_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::SERVICE_UNAVAILABLE:
      error_message = "WALLET_SERVICE_UNAVAILABLE";
      break;
    case WalletClient::UNSUPPORTED_API_VERSION:
      error_message = "WALLET_UNSUPPORTED_API_VERSION";
      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(
      delegate_->GetDialogType(), 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(
        delegate_->GetDialogType(),
        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 SEND_STATUS:
      return AutofillMetrics::SEND_STATUS;
    case NO_PENDING_REQUEST:
      NOTREACHED();
      return AutofillMetrics::UNKNOWN_API_CALL;
  }

  NOTREACHED();
  return AutofillMetrics::UNKNOWN_API_CALL;
}

}  // namespace wallet
}  // namespace autofill
