Chromium Code Reviews| Index: ios/chrome/browser/ui/payments/payment_request_manager.mm |
| diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm |
| index 79398b3ea49472c772110a1314562b2a0cb93075..770f0f8441173c522ee8e30ec71519a6ebb3f3c0 100644 |
| --- a/ios/chrome/browser/ui/payments/payment_request_manager.mm |
| +++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm |
| @@ -13,15 +13,19 @@ |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #import "base/values.h" |
| +#include "components/autofill/core/browser/autofill_country.h" |
| #include "components/autofill/core/browser/autofill_data_util.h" |
| #include "components/autofill/core/browser/autofill_manager.h" |
| #include "components/autofill/core/browser/credit_card.h" |
| #include "components/autofill/core/browser/personal_data_manager.h" |
| #include "components/autofill/ios/browser/autofill_driver_ios.h" |
| +#include "components/payments/core/address_normalization_manager.h" |
| +#include "components/payments/core/address_normalizer_impl.h" |
| #include "components/payments/core/payment_address.h" |
| #include "components/payments/core/payment_request_data_util.h" |
| #include "ios/chrome/browser/application_context.h" |
| #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" |
| +#include "ios/chrome/browser/autofill/validation_rules_storage_factory.h" |
| #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| #include "ios/chrome/browser/payments/payment_request.h" |
| #include "ios/chrome/browser/procedural_block_types.h" |
| @@ -41,6 +45,8 @@ |
| #include "ios/web/public/web_state/url_verification_constants.h" |
| #include "ios/web/public/web_state/web_state.h" |
| #import "ios/web/public/web_state/web_state_observer_bridge.h" |
| +#include "third_party/libaddressinput/chromium/chrome_metadata_source.h" |
| +#include "third_party/libaddressinput/chromium/chrome_storage_impl.h" |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| @@ -61,6 +67,12 @@ const NSTimeInterval kTimeoutInterval = 60.0; |
| NSString* kAbortMessage = @"The payment request was aborted."; |
| NSString* kCancelMessage = @"The payment request was canceled."; |
| +struct FullCard { |
| + autofill::CreditCard creditCard; |
| + base::string16 verificationCode; |
| + autofill::AutofillProfile billingAddress; |
| +}; |
| + |
| } // namespace |
| @interface PaymentRequestManager ()<CRWWebStateObserver, |
| @@ -104,6 +116,14 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| // Timer used to cancel the Payment Request flow and close the UI if the |
| // page does not settle the pending update promise in a timely fashion. |
| NSTimer* _updateEventTimeoutTimer; |
| + |
| + // AddressNormalizationManager used to normalize the various addresses (e.g. |
| + // shipping, contact, billing). |
| + std::unique_ptr<payments::AddressNormalizationManager> |
| + _addressNormalizationManager; |
| + |
| + // Storage for the full card. |
| + FullCard _fullCard; |
| } |
| // Object that manages JavaScript injection into the web view. |
| @@ -135,7 +155,7 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| // Called by |_updateEventTimeoutTimer|, displays an error message. Upon |
| // dismissal of the error message, cancels the Payment Request as if it was |
| -// performend by the user. |
| +// performed by the user. |
| - (BOOL)displayErrorThenCancelRequest; |
| // Called by |_paymentResponseTimeoutTimer|, invokes handleResponseComplete: |
| @@ -169,6 +189,10 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| // was rejected. |
| - (void)setUpdateEventTimeoutTimer; |
| +// Called when the relevant addresses from a Payment Request have been |
| +// normalized. Resolves the request promise with a PaymentResponse. |
| +- (void)paymentRequestAddressNormalizationDidComplete; |
| + |
| @end |
| @implementation PaymentRequestManager |
| @@ -322,6 +346,43 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| return NO; |
| } |
| +- (void)startAddressNormalizer { |
| + autofill::PersonalDataManager* personalDataManager = |
| + _paymentRequest->GetPersonalDataManager(); |
| + |
| + std::unique_ptr<i18n::addressinput::Source> addressNormalizerSource = |
| + base::MakeUnique<autofill::ChromeMetadataSource>( |
| + I18N_ADDRESS_VALIDATION_DATA_URL, |
| + personalDataManager->GetURLRequestContextGetter()); |
| + |
| + std::unique_ptr<i18n::addressinput::Storage> addressNormalizerStorage = |
| + autofill::ValidationRulesStorageFactory::CreateStorage(); |
| + |
| + std::unique_ptr<payments::AddressNormalizer> addressNormalizer = |
| + base::MakeUnique<payments::AddressNormalizerImpl>( |
| + std::move(addressNormalizerSource), |
| + std::move(addressNormalizerStorage)); |
| + |
| + // Kickoff the process of loading the rules (which is asynchronous) for each |
| + // profile's country, to get faster address normalization later. |
| + for (const autofill::AutofillProfile* profile : |
| + personalDataManager->GetProfilesToSuggest()) { |
| + std::string countryCode = |
| + base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)); |
| + if (autofill::data_util::IsValidCountryCode(countryCode)) { |
| + addressNormalizer->LoadRulesForRegion(countryCode); |
| + } |
| + } |
| + |
| + const std::string default_country_code = |
| + autofill::AutofillCountry::CountryCodeForLocale( |
| + GetApplicationContext()->GetApplicationLocale()); |
| + |
| + _addressNormalizationManager = |
| + base::MakeUnique<payments::AddressNormalizationManager>( |
| + std::move(addressNormalizer), default_country_code); |
| +} |
| + |
| // Ensures that |_paymentRequest| is set to the correct value for |message|. |
| // Returns YES if |_paymentRequest| was already set to the right value, or if it |
| // was updated to match |message|. |
| @@ -359,6 +420,8 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| return NO; |
| } |
| + [self startAddressNormalizer]; |
| + |
| UIImage* pageFavicon = nil; |
| web::NavigationItem* navigationItem = |
| [self webState]->GetNavigationManager()->GetVisibleItem(); |
| @@ -569,22 +632,10 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| didCompletePaymentRequest:(PaymentRequest*)paymentRequest |
| card:(const autofill::CreditCard&)card |
| verificationCode:(const base::string16&)verificationCode { |
| - web::PaymentResponse paymentResponse; |
| - |
| - // If the merchant specified the card network as part of the "basic-card" |
| - // payment method, return "basic-card" as the method_name. Otherwise, return |
| - // the name of the network directly. |
| - std::string issuer_network = |
| - autofill::data_util::GetPaymentRequestData(card.network()) |
| - .basic_card_issuer_network; |
| - paymentResponse.method_name = |
| - paymentRequest->basic_card_specified_networks().find(issuer_network) != |
| - paymentRequest->basic_card_specified_networks().end() |
| - ? base::ASCIIToUTF16("basic-card") |
| - : base::ASCIIToUTF16(issuer_network); |
| + DCHECK_EQ(_paymentRequest.get(), paymentRequest); |
|
Moe
2017/05/17 18:12:38
nit: I prefer if |paymentRequest| wasn't part of t
macourteau
2017/05/17 19:15:16
Done.
|
| - // Get the billing address |
| - autofill::AutofillProfile billingAddress; |
| + _fullCard.creditCard = card; |
| + _fullCard.verificationCode = verificationCode; |
| // TODO(crbug.com/714768): Make sure the billing address is set and valid |
| // before getting here. Once the bug is addressed, there will be no need to |
| @@ -594,18 +645,52 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| autofill::AutofillProfile* billingAddressPtr = |
| autofill::PersonalDataManager::GetProfileFromProfilesByGUID( |
| card.billing_address_id(), paymentRequest->billing_profiles()); |
| - if (billingAddressPtr) |
| - billingAddress = *billingAddressPtr; |
| + if (billingAddressPtr) { |
| + _fullCard.billingAddress = *billingAddressPtr; |
| + _addressNormalizationManager->StartNormalizingAddress( |
| + &_fullCard.billingAddress); |
| + } |
| } |
| + if (_paymentRequest->request_shipping()) { |
| + _addressNormalizationManager->StartNormalizingAddress( |
| + _paymentRequest->selected_shipping_profile()); |
| + } |
| + |
| + _addressNormalizationManager->StartNormalizingAddress( |
| + _paymentRequest->selected_contact_profile()); |
| + |
| + __weak PaymentRequestManager* weakSelf = self; |
| + _addressNormalizationManager->FinalizeWithCompletionCallback( |
| + base::BindBlockArc(^(const payments::AddressNormalizationManager&) { |
| + [weakSelf paymentRequestAddressNormalizationDidComplete]; |
| + })); |
| +} |
| + |
| +- (void)paymentRequestAddressNormalizationDidComplete { |
| + web::PaymentResponse paymentResponse; |
| + |
| + // If the merchant specified the card network as part of the "basic-card" |
| + // payment method, return "basic-card" as the method_name. Otherwise, return |
| + // the name of the network directly. |
| + std::string issuer_network = |
| + autofill::data_util::GetPaymentRequestData(_fullCard.creditCard.network()) |
| + .basic_card_issuer_network; |
| + paymentResponse.method_name = |
| + _paymentRequest->basic_card_specified_networks().find(issuer_network) != |
| + _paymentRequest->basic_card_specified_networks().end() |
| + ? base::ASCIIToUTF16("basic-card") |
| + : base::ASCIIToUTF16(issuer_network); |
| + |
| paymentResponse.details = |
| payments::data_util::GetBasicCardResponseFromAutofillCreditCard( |
| - card, verificationCode, billingAddress, |
| + _fullCard.creditCard, _fullCard.verificationCode, |
| + _fullCard.billingAddress, |
| GetApplicationContext()->GetApplicationLocale()); |
| - if (paymentRequest->request_shipping()) { |
| + if (_paymentRequest->request_shipping()) { |
| autofill::AutofillProfile* shippingAddress = |
| - paymentRequest->selected_shipping_profile(); |
| + _paymentRequest->selected_shipping_profile(); |
| // TODO(crbug.com/602666): User should get here only if they have selected |
| // a shipping address. |
| DCHECK(shippingAddress); |
| @@ -614,14 +699,14 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| *shippingAddress, GetApplicationContext()->GetApplicationLocale()); |
| web::PaymentShippingOption* shippingOption = |
| - paymentRequest->selected_shipping_option(); |
| + _paymentRequest->selected_shipping_option(); |
| DCHECK(shippingOption); |
| paymentResponse.shipping_option = shippingOption->id; |
| } |
| - if (paymentRequest->request_payer_name()) { |
| + if (_paymentRequest->request_payer_name()) { |
| autofill::AutofillProfile* contactInfo = |
| - paymentRequest->selected_contact_profile(); |
| + _paymentRequest->selected_contact_profile(); |
| // TODO(crbug.com/602666): User should get here only if they have selected |
| // a contact info. |
| DCHECK(contactInfo); |
| @@ -630,9 +715,9 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| GetApplicationContext()->GetApplicationLocale()); |
| } |
| - if (paymentRequest->request_payer_email()) { |
| + if (_paymentRequest->request_payer_email()) { |
| autofill::AutofillProfile* contactInfo = |
| - paymentRequest->selected_contact_profile(); |
| + _paymentRequest->selected_contact_profile(); |
| // TODO(crbug.com/602666): User should get here only if they have selected |
| // a contact info. |
| DCHECK(contactInfo); |
| @@ -640,9 +725,9 @@ NSString* kCancelMessage = @"The payment request was canceled."; |
| contactInfo->GetRawInfo(autofill::EMAIL_ADDRESS); |
| } |
| - if (paymentRequest->request_payer_phone()) { |
| + if (_paymentRequest->request_payer_phone()) { |
| autofill::AutofillProfile* contactInfo = |
| - paymentRequest->selected_contact_profile(); |
| + _paymentRequest->selected_contact_profile(); |
| // TODO(crbug.com/602666): User should get here only if they have selected |
| // a contact info. |
| DCHECK(contactInfo); |