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