blob: 8a6b7304452eb3ac890b056130cb62e0050e32a2 [file] [log] [blame]
mathpf1a7a3752017-03-15 11:23:371// Copyright 2016 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/payments/content/payment_request_state.h"
6
mad45271932017-04-13 16:07:387#include <algorithm>
anthonyvd0116ce332017-03-21 21:29:018#include <set>
mad45271932017-04-13 16:07:389#include <utility>
anthonyvd0116ce332017-03-21 21:29:0110
sebsgad86bd002017-03-29 16:39:1211#include "base/strings/utf_string_conversions.h"
sebsg7e619132017-04-27 16:07:1012#include "components/autofill/core/browser/autofill_country.h"
mathpf1a7a3752017-03-15 11:23:3713#include "components/autofill/core/browser/autofill_data_util.h"
14#include "components/autofill/core/browser/autofill_profile.h"
15#include "components/autofill/core/browser/credit_card.h"
mathpc0d616a2017-03-15 14:09:3316#include "components/autofill/core/browser/personal_data_manager.h"
sebsgad86bd002017-03-29 16:39:1217#include "components/payments/content/payment_response_helper.h"
mathpf1a7a3752017-03-15 11:23:3718#include "components/payments/core/autofill_payment_instrument.h"
sebsg695799a2017-04-11 16:29:0619#include "components/payments/core/payment_instrument.h"
tmartino01c3eb82017-04-29 15:18:3920#include "components/payments/core/payment_request_data_util.h"
anthonyvdd23ed702017-04-05 15:29:0021#include "components/payments/core/payment_request_delegate.h"
mathpf1a7a3752017-03-15 11:23:3722
23namespace payments {
24
mathpc0d616a2017-03-15 14:09:3325PaymentRequestState::PaymentRequestState(
26 PaymentRequestSpec* spec,
27 Delegate* delegate,
28 const std::string& app_locale,
anthonyvdd23ed702017-04-05 15:29:0029 autofill::PersonalDataManager* personal_data_manager,
30 PaymentRequestDelegate* payment_request_delegate)
mathpf1a7a3752017-03-15 11:23:3731 : is_ready_to_pay_(false),
sebsg7e619132017-04-27 16:07:1032 is_waiting_for_merchant_validation_(false),
mathpc0d616a2017-03-15 14:09:3333 app_locale_(app_locale),
mathpf1a7a3752017-03-15 11:23:3734 spec_(spec),
35 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3336 personal_data_manager_(personal_data_manager),
mathpf1a7a3752017-03-15 11:23:3737 selected_shipping_profile_(nullptr),
38 selected_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0039 selected_instrument_(nullptr),
tmartino01c3eb82017-04-29 15:18:3940 payment_request_delegate_(payment_request_delegate),
41 profile_comparator_(app_locale, *spec) {
mathpf1a7a3752017-03-15 11:23:3742 PopulateProfileCache();
mathpf1a7a3752017-03-15 11:23:3743 SetDefaultProfileSelections();
sebsg7e619132017-04-27 16:07:1044 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3745}
mathp151bd31e2017-04-03 21:07:2446PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3747
sebsg695799a2017-04-11 16:29:0648void PaymentRequestState::OnPaymentResponseReady(
49 mojom::PaymentResponsePtr payment_response) {
50 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
51}
52
sebsg7e619132017-04-27 16:07:1053void PaymentRequestState::OnAddressNormalized(
54 const autofill::AutofillProfile& normalized_profile) {
55 delegate_->OnShippingAddressSelected(
56 PaymentResponseHelper::GetMojomPaymentAddressFromAutofillProfile(
57 normalized_profile, app_locale_));
58}
59
60void PaymentRequestState::OnCouldNotNormalize(
61 const autofill::AutofillProfile& profile) {
62 // Since the phone number is formatted in either case, this profile should be
63 // used.
64 OnAddressNormalized(profile);
65}
66
67void PaymentRequestState::OnSpecUpdated() {
68 is_waiting_for_merchant_validation_ = false;
69 UpdateIsReadyToPayAndNotifyObservers();
70}
71
mathp1a5be4f2017-03-24 18:09:1972bool PaymentRequestState::CanMakePayment() const {
mathp1a5be4f2017-03-24 18:09:1973 for (const std::unique_ptr<PaymentInstrument>& instrument :
74 available_instruments_) {
rouslan6e3cf7c62017-04-17 21:23:2875 if (instrument->IsValidForCanMakePayment()) {
76 // AddAutofillPaymentInstrument() filters out available instruments based
77 // on supported card networks.
78 DCHECK(spec_->supported_card_networks_set().find(
79 instrument->method_name()) !=
80 spec_->supported_card_networks_set().end());
mathp1a5be4f2017-03-24 18:09:1981 return true;
82 }
83 }
84 return false;
85}
86
rouslan6e3cf7c62017-04-17 21:23:2887bool PaymentRequestState::AreRequestedMethodsSupported() const {
88 return !spec_->supported_card_networks().empty();
89}
90
mathpf1a7a3752017-03-15 11:23:3791void PaymentRequestState::AddObserver(Observer* observer) {
92 CHECK(observer);
93 observers_.AddObserver(observer);
94}
mathpf1a7a3752017-03-15 11:23:3795
96void PaymentRequestState::RemoveObserver(Observer* observer) {
97 observers_.RemoveObserver(observer);
98}
99
mathpf1a7a3752017-03-15 11:23:37100void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05101 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06102
103 // Once the response is ready, will call back into OnPaymentResponseReady.
104 response_helper_ = base::MakeUnique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15105 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
106 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37107}
108
mathp24ce4cd2017-04-12 20:56:42109void PaymentRequestState::AddAutofillPaymentInstrument(
110 bool selected,
111 const autofill::CreditCard& card) {
112 std::string basic_card_network =
rouslan4e981bd32017-05-01 17:49:16113 autofill::data_util::GetPaymentRequestData(card.network())
114 .basic_card_issuer_network;
mathp24ce4cd2017-04-12 20:56:42115 if (!spec_->supported_card_networks_set().count(basic_card_network))
116 return;
117
118 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
119 // owned by this object.
120 std::unique_ptr<PaymentInstrument> instrument =
121 base::MakeUnique<AutofillPaymentInstrument>(
122 basic_card_network, card, shipping_profiles_, app_locale_,
123 payment_request_delegate_);
124 available_instruments_.push_back(std::move(instrument));
125
126 if (selected)
127 SetSelectedInstrument(available_instruments_.back().get());
128}
129
madf9904ea2017-04-25 18:39:12130void PaymentRequestState::AddAutofillShippingProfile(
131 bool selected,
132 const autofill::AutofillProfile& profile) {
133 profile_cache_.push_back(
134 base::MakeUnique<autofill::AutofillProfile>(profile));
135 // TODO(tmartino): Implement deduplication rules specific to shipping
136 // profiles.
137 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
138 shipping_profiles_.push_back(new_cached_profile);
139
140 if (selected)
141 SetSelectedShippingProfile(new_cached_profile);
142}
143
anthonyvd0116ce332017-03-21 21:29:01144void PaymentRequestState::SetSelectedShippingOption(
mathp151bd31e2017-04-03 21:07:24145 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50146 spec_->StartWaitingForUpdateWith(
147 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd31e2017-04-03 21:07:24148 // This will inform the merchant and will lead to them calling updateWith with
149 // new PaymentDetails.
150 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01151}
152
mathpf1a7a3752017-03-15 11:23:37153void PaymentRequestState::SetSelectedShippingProfile(
154 autofill::AutofillProfile* profile) {
anthonyvd2f30baa12017-04-13 22:30:50155 spec_->StartWaitingForUpdateWith(
156 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37157 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10158
159 // The user should not be able to click on pay until the callback from the
160 // merchant.
161 is_waiting_for_merchant_validation_ = true;
mathpf1a7a3752017-03-15 11:23:37162 UpdateIsReadyToPayAndNotifyObservers();
sebsg7e619132017-04-27 16:07:10163
164 // Start the normalization of the shipping address.
165 // Use the country code from the profile if it is set, otherwise infer it
166 // from the |app_locale_|.
tmartino01c3eb82017-04-29 15:18:39167 std::string country_code = data_util::GetCountryCodeWithFallback(
168 selected_shipping_profile_, app_locale_);
sebsg7e619132017-04-27 16:07:10169 payment_request_delegate_->GetAddressNormalizer()->StartAddressNormalization(
170 *selected_shipping_profile_, country_code, /*timeout_seconds=*/2, this);
mathpf1a7a3752017-03-15 11:23:37171}
172
173void PaymentRequestState::SetSelectedContactProfile(
174 autofill::AutofillProfile* profile) {
175 selected_contact_profile_ = profile;
176 UpdateIsReadyToPayAndNotifyObservers();
177}
178
mathp363735b2017-03-16 18:08:05179void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
180 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37181 UpdateIsReadyToPayAndNotifyObservers();
182}
183
mathpc0d616a2017-03-15 14:09:33184const std::string& PaymentRequestState::GetApplicationLocale() {
185 return app_locale_;
186}
187
188autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
189 return personal_data_manager_;
190}
191
mad763ed2b2017-04-24 20:28:47192autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
193 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38194}
195
mathpf1a7a3752017-03-15 11:23:37196void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37197 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33198 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37199
200 // PaymentRequest may outlive the Profiles returned by the Data Manager.
201 // Thus, we store copies, and return a vector of pointers to these copies
202 // whenever Profiles are requested. The same is true for credit cards.
203 for (size_t i = 0; i < profiles.size(); i++) {
204 profile_cache_.push_back(
205 base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
206
tmartinoa6eb22f2017-04-06 20:16:24207 // TODO(tmartino): Implement deduplication rules specific to shipping
208 // profiles.
mathpf1a7a3752017-03-15 11:23:37209 shipping_profiles_.push_back(profile_cache_[i].get());
mathpf1a7a3752017-03-15 11:23:37210 }
211
tmartinoa6eb22f2017-04-06 20:16:24212 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering(
213 profile_cache_.size());
214 std::transform(profile_cache_.begin(), profile_cache_.end(),
215 raw_profiles_for_filtering.begin(),
216 [](const std::unique_ptr<autofill::AutofillProfile>& p) {
217 return p.get();
218 });
219
tmartino01c3eb82017-04-29 15:18:39220 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
221 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24222
mathp363735b2017-03-16 18:08:05223 // Create the list of available instruments.
mathpf1a7a3752017-03-15 11:23:37224 const std::vector<autofill::CreditCard*>& cards =
mathpc0d616a2017-03-15 14:09:33225 personal_data_manager_->GetCreditCardsToSuggest();
mathp24ce4cd2017-04-12 20:56:42226 for (autofill::CreditCard* card : cards)
227 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37228}
229
230void PaymentRequestState::SetDefaultProfileSelections() {
mathp151bd31e2017-04-03 21:07:24231 // Only pre-select an address if the merchant provided at least one selected
232 // shipping option.
233 if (!shipping_profiles().empty() && spec_->selected_shipping_option())
mathpf1a7a3752017-03-15 11:23:37234 selected_shipping_profile_ = shipping_profiles()[0];
235
236 if (!contact_profiles().empty())
237 selected_contact_profile_ = contact_profiles()[0];
238
mathp363735b2017-03-16 18:08:05239 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
240 // count and other means, and implement a way to modify this function's return
241 // value.
242 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
243 available_instruments();
244 auto first_complete_instrument =
245 std::find_if(instruments.begin(), instruments.end(),
246 [](const std::unique_ptr<PaymentInstrument>& instrument) {
mathp4baea332017-04-10 21:42:29247 return instrument->IsCompleteForPayment();
mathp363735b2017-03-16 18:08:05248 });
mathpf1a7a3752017-03-15 11:23:37249
mathp363735b2017-03-16 18:08:05250 selected_instrument_ = first_complete_instrument == instruments.end()
251 ? nullptr
252 : first_complete_instrument->get();
mathpf1a7a3752017-03-15 11:23:37253
254 UpdateIsReadyToPayAndNotifyObservers();
255}
256
257void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
258 is_ready_to_pay_ =
259 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
260 NotifyOnSelectedInformationChanged();
261}
262
263void PaymentRequestState::NotifyOnSelectedInformationChanged() {
264 for (auto& observer : observers_)
265 observer.OnSelectedInformationChanged();
266}
267
268bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05269 // There is no need to check for supported networks, because only supported
270 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29271 return selected_instrument_ != nullptr &&
272 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37273}
274
275bool PaymentRequestState::ArePaymentOptionsSatisfied() {
sebsg7e619132017-04-27 16:07:10276 if (is_waiting_for_merchant_validation_)
277 return false;
278
tmartino01c3eb82017-04-29 15:18:39279 if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_))
280 return false;
281
282 return profile_comparator()->IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37283}
284
mathpf1a7a3752017-03-15 11:23:37285} // namespace payments