blob: afa32130a63db2460539c8fc7a29487cc0d0cf75 [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"
anthonyvdd23ed702017-04-05 15:29:0020#include "components/payments/core/payment_request_delegate.h"
tmartinoa6eb22f2017-04-06 20:16:2421#include "components/payments/core/profile_util.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),
40 payment_request_delegate_(payment_request_delegate) {
mathpf1a7a3752017-03-15 11:23:3741 PopulateProfileCache();
mathpf1a7a3752017-03-15 11:23:3742 SetDefaultProfileSelections();
sebsg7e619132017-04-27 16:07:1043 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3744}
mathp151bd31e2017-04-03 21:07:2445PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3746
sebsg695799a2017-04-11 16:29:0647void PaymentRequestState::OnPaymentResponseReady(
48 mojom::PaymentResponsePtr payment_response) {
49 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
50}
51
sebsg7e619132017-04-27 16:07:1052void PaymentRequestState::OnAddressNormalized(
53 const autofill::AutofillProfile& normalized_profile) {
54 delegate_->OnShippingAddressSelected(
55 PaymentResponseHelper::GetMojomPaymentAddressFromAutofillProfile(
56 normalized_profile, app_locale_));
57}
58
59void PaymentRequestState::OnCouldNotNormalize(
60 const autofill::AutofillProfile& profile) {
61 // Since the phone number is formatted in either case, this profile should be
62 // used.
63 OnAddressNormalized(profile);
64}
65
66void PaymentRequestState::OnSpecUpdated() {
67 is_waiting_for_merchant_validation_ = false;
68 UpdateIsReadyToPayAndNotifyObservers();
69}
70
mathp1a5be4f2017-03-24 18:09:1971bool PaymentRequestState::CanMakePayment() const {
mathp1a5be4f2017-03-24 18:09:1972 for (const std::unique_ptr<PaymentInstrument>& instrument :
73 available_instruments_) {
rouslan6e3cf7c62017-04-17 21:23:2874 if (instrument->IsValidForCanMakePayment()) {
75 // AddAutofillPaymentInstrument() filters out available instruments based
76 // on supported card networks.
77 DCHECK(spec_->supported_card_networks_set().find(
78 instrument->method_name()) !=
79 spec_->supported_card_networks_set().end());
mathp1a5be4f2017-03-24 18:09:1980 return true;
81 }
82 }
83 return false;
84}
85
rouslan6e3cf7c62017-04-17 21:23:2886bool PaymentRequestState::AreRequestedMethodsSupported() const {
87 return !spec_->supported_card_networks().empty();
88}
89
mathpf1a7a3752017-03-15 11:23:3790void PaymentRequestState::AddObserver(Observer* observer) {
91 CHECK(observer);
92 observers_.AddObserver(observer);
93}
mathpf1a7a3752017-03-15 11:23:3794
95void PaymentRequestState::RemoveObserver(Observer* observer) {
96 observers_.RemoveObserver(observer);
97}
98
mathpf1a7a3752017-03-15 11:23:3799void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05100 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06101
102 // Once the response is ready, will call back into OnPaymentResponseReady.
103 response_helper_ = base::MakeUnique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15104 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
105 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37106}
107
mathp24ce4cd2017-04-12 20:56:42108void PaymentRequestState::AddAutofillPaymentInstrument(
109 bool selected,
110 const autofill::CreditCard& card) {
111 std::string basic_card_network =
112 autofill::data_util::GetPaymentRequestData(card.type())
113 .basic_card_payment_type;
114 if (!spec_->supported_card_networks_set().count(basic_card_network))
115 return;
116
117 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
118 // owned by this object.
119 std::unique_ptr<PaymentInstrument> instrument =
120 base::MakeUnique<AutofillPaymentInstrument>(
121 basic_card_network, card, shipping_profiles_, app_locale_,
122 payment_request_delegate_);
123 available_instruments_.push_back(std::move(instrument));
124
125 if (selected)
126 SetSelectedInstrument(available_instruments_.back().get());
127}
128
madf9904ea2017-04-25 18:39:12129void PaymentRequestState::AddAutofillShippingProfile(
130 bool selected,
131 const autofill::AutofillProfile& profile) {
132 profile_cache_.push_back(
133 base::MakeUnique<autofill::AutofillProfile>(profile));
134 // TODO(tmartino): Implement deduplication rules specific to shipping
135 // profiles.
136 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
137 shipping_profiles_.push_back(new_cached_profile);
138
139 if (selected)
140 SetSelectedShippingProfile(new_cached_profile);
141}
142
anthonyvd0116ce332017-03-21 21:29:01143void PaymentRequestState::SetSelectedShippingOption(
mathp151bd31e2017-04-03 21:07:24144 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50145 spec_->StartWaitingForUpdateWith(
146 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd31e2017-04-03 21:07:24147 // This will inform the merchant and will lead to them calling updateWith with
148 // new PaymentDetails.
149 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01150}
151
mathpf1a7a3752017-03-15 11:23:37152void PaymentRequestState::SetSelectedShippingProfile(
153 autofill::AutofillProfile* profile) {
anthonyvd2f30baa12017-04-13 22:30:50154 spec_->StartWaitingForUpdateWith(
155 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37156 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10157
158 // The user should not be able to click on pay until the callback from the
159 // merchant.
160 is_waiting_for_merchant_validation_ = true;
mathpf1a7a3752017-03-15 11:23:37161 UpdateIsReadyToPayAndNotifyObservers();
sebsg7e619132017-04-27 16:07:10162
163 // Start the normalization of the shipping address.
164 // Use the country code from the profile if it is set, otherwise infer it
165 // from the |app_locale_|.
166 std::string country_code = base::UTF16ToUTF8(
167 selected_shipping_profile_->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
168 if (!autofill::data_util::IsValidCountryCode(country_code))
169 country_code = autofill::AutofillCountry::CountryCodeForLocale(app_locale_);
170 payment_request_delegate_->GetAddressNormalizer()->StartAddressNormalization(
171 *selected_shipping_profile_, country_code, /*timeout_seconds=*/2, this);
mathpf1a7a3752017-03-15 11:23:37172}
173
174void PaymentRequestState::SetSelectedContactProfile(
175 autofill::AutofillProfile* profile) {
176 selected_contact_profile_ = profile;
177 UpdateIsReadyToPayAndNotifyObservers();
178}
179
mathp363735b2017-03-16 18:08:05180void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
181 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37182 UpdateIsReadyToPayAndNotifyObservers();
183}
184
mathpc0d616a2017-03-15 14:09:33185const std::string& PaymentRequestState::GetApplicationLocale() {
186 return app_locale_;
187}
188
189autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
190 return personal_data_manager_;
191}
192
mad763ed2b2017-04-24 20:28:47193autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
194 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38195}
196
mathpf1a7a3752017-03-15 11:23:37197void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37198 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33199 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37200
201 // PaymentRequest may outlive the Profiles returned by the Data Manager.
202 // Thus, we store copies, and return a vector of pointers to these copies
203 // whenever Profiles are requested. The same is true for credit cards.
204 for (size_t i = 0; i < profiles.size(); i++) {
205 profile_cache_.push_back(
206 base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
207
tmartinoa6eb22f2017-04-06 20:16:24208 // TODO(tmartino): Implement deduplication rules specific to shipping
209 // profiles.
mathpf1a7a3752017-03-15 11:23:37210 shipping_profiles_.push_back(profile_cache_[i].get());
mathpf1a7a3752017-03-15 11:23:37211 }
212
tmartinoa6eb22f2017-04-06 20:16:24213 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering(
214 profile_cache_.size());
215 std::transform(profile_cache_.begin(), profile_cache_.end(),
216 raw_profiles_for_filtering.begin(),
217 [](const std::unique_ptr<autofill::AutofillProfile>& p) {
218 return p.get();
219 });
220
221 contact_profiles_ = profile_util::FilterProfilesForContact(
222 raw_profiles_for_filtering, GetApplicationLocale(), *spec_);
223
mathp363735b2017-03-16 18:08:05224 // Create the list of available instruments.
mathpf1a7a3752017-03-15 11:23:37225 const std::vector<autofill::CreditCard*>& cards =
mathpc0d616a2017-03-15 14:09:33226 personal_data_manager_->GetCreditCardsToSuggest();
mathp24ce4cd2017-04-12 20:56:42227 for (autofill::CreditCard* card : cards)
228 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37229}
230
231void PaymentRequestState::SetDefaultProfileSelections() {
mathp151bd31e2017-04-03 21:07:24232 // Only pre-select an address if the merchant provided at least one selected
233 // shipping option.
234 if (!shipping_profiles().empty() && spec_->selected_shipping_option())
mathpf1a7a3752017-03-15 11:23:37235 selected_shipping_profile_ = shipping_profiles()[0];
236
237 if (!contact_profiles().empty())
238 selected_contact_profile_ = contact_profiles()[0];
239
mathp363735b2017-03-16 18:08:05240 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
241 // count and other means, and implement a way to modify this function's return
242 // value.
243 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
244 available_instruments();
245 auto first_complete_instrument =
246 std::find_if(instruments.begin(), instruments.end(),
247 [](const std::unique_ptr<PaymentInstrument>& instrument) {
mathp4baea332017-04-10 21:42:29248 return instrument->IsCompleteForPayment();
mathp363735b2017-03-16 18:08:05249 });
mathpf1a7a3752017-03-15 11:23:37250
mathp363735b2017-03-16 18:08:05251 selected_instrument_ = first_complete_instrument == instruments.end()
252 ? nullptr
253 : first_complete_instrument->get();
mathpf1a7a3752017-03-15 11:23:37254
255 UpdateIsReadyToPayAndNotifyObservers();
256}
257
258void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
259 is_ready_to_pay_ =
260 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
261 NotifyOnSelectedInformationChanged();
262}
263
264void PaymentRequestState::NotifyOnSelectedInformationChanged() {
265 for (auto& observer : observers_)
266 observer.OnSelectedInformationChanged();
267}
268
269bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05270 // There is no need to check for supported networks, because only supported
271 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29272 return selected_instrument_ != nullptr &&
273 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37274}
275
276bool PaymentRequestState::ArePaymentOptionsSatisfied() {
277 // TODO(mathp): Have a measure of shipping address completeness.
278 if (spec_->request_shipping() && selected_shipping_profile_ == nullptr)
279 return false;
280
sebsg7e619132017-04-27 16:07:10281 if (is_waiting_for_merchant_validation_)
282 return false;
283
tmartinoa6eb22f2017-04-06 20:16:24284 profile_util::PaymentsProfileComparator comparator(app_locale_, *spec_);
285 return comparator.IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37286}
287
mathpf1a7a3752017-03-15 11:23:37288} // namespace payments