blob: 236650e361dd7774208fa66bf9d20edd0fa2d96a [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"
mathpf1a7a3752017-03-15 11:23:3712#include "components/autofill/core/browser/autofill_data_util.h"
13#include "components/autofill/core/browser/autofill_profile.h"
14#include "components/autofill/core/browser/credit_card.h"
mathpc0d616a2017-03-15 14:09:3315#include "components/autofill/core/browser/personal_data_manager.h"
mathpf1a7a3752017-03-15 11:23:3716#include "components/payments/content/payment_request_spec.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),
mathpc0d616a2017-03-15 14:09:3332 app_locale_(app_locale),
mathpf1a7a3752017-03-15 11:23:3733 spec_(spec),
34 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3335 personal_data_manager_(personal_data_manager),
mathpf1a7a3752017-03-15 11:23:3736 selected_shipping_profile_(nullptr),
37 selected_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0038 selected_instrument_(nullptr),
39 payment_request_delegate_(payment_request_delegate) {
mathpf1a7a3752017-03-15 11:23:3740 PopulateProfileCache();
mathpf1a7a3752017-03-15 11:23:3741 SetDefaultProfileSelections();
42}
mathp151bd31e2017-04-03 21:07:2443PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3744
sebsg695799a2017-04-11 16:29:0645void PaymentRequestState::OnPaymentResponseReady(
46 mojom::PaymentResponsePtr payment_response) {
47 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
48}
49
mathp1a5be4f2017-03-24 18:09:1950bool PaymentRequestState::CanMakePayment() const {
mathp1a5be4f2017-03-24 18:09:1951 for (const std::unique_ptr<PaymentInstrument>& instrument :
52 available_instruments_) {
rouslan6e3cf7c62017-04-17 21:23:2853 if (instrument->IsValidForCanMakePayment()) {
54 // AddAutofillPaymentInstrument() filters out available instruments based
55 // on supported card networks.
56 DCHECK(spec_->supported_card_networks_set().find(
57 instrument->method_name()) !=
58 spec_->supported_card_networks_set().end());
mathp1a5be4f2017-03-24 18:09:1959 return true;
60 }
61 }
62 return false;
63}
64
rouslan6e3cf7c62017-04-17 21:23:2865bool PaymentRequestState::AreRequestedMethodsSupported() const {
66 return !spec_->supported_card_networks().empty();
67}
68
mathpf1a7a3752017-03-15 11:23:3769void PaymentRequestState::AddObserver(Observer* observer) {
70 CHECK(observer);
71 observers_.AddObserver(observer);
72}
mathpf1a7a3752017-03-15 11:23:3773
74void PaymentRequestState::RemoveObserver(Observer* observer) {
75 observers_.RemoveObserver(observer);
76}
77
mathpf1a7a3752017-03-15 11:23:3778void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:0579 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:0680
81 // Once the response is ready, will call back into OnPaymentResponseReady.
82 response_helper_ = base::MakeUnique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:1583 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
84 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:3785}
86
mathp24ce4cd2017-04-12 20:56:4287void PaymentRequestState::AddAutofillPaymentInstrument(
88 bool selected,
89 const autofill::CreditCard& card) {
90 std::string basic_card_network =
91 autofill::data_util::GetPaymentRequestData(card.type())
92 .basic_card_payment_type;
93 if (!spec_->supported_card_networks_set().count(basic_card_network))
94 return;
95
96 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
97 // owned by this object.
98 std::unique_ptr<PaymentInstrument> instrument =
99 base::MakeUnique<AutofillPaymentInstrument>(
100 basic_card_network, card, shipping_profiles_, app_locale_,
101 payment_request_delegate_);
102 available_instruments_.push_back(std::move(instrument));
103
104 if (selected)
105 SetSelectedInstrument(available_instruments_.back().get());
106}
107
anthonyvd0116ce332017-03-21 21:29:01108void PaymentRequestState::SetSelectedShippingOption(
mathp151bd31e2017-04-03 21:07:24109 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50110 spec_->StartWaitingForUpdateWith(
111 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd31e2017-04-03 21:07:24112 // This will inform the merchant and will lead to them calling updateWith with
113 // new PaymentDetails.
114 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01115}
116
mathpf1a7a3752017-03-15 11:23:37117void PaymentRequestState::SetSelectedShippingProfile(
118 autofill::AutofillProfile* profile) {
anthonyvd2f30baa12017-04-13 22:30:50119 spec_->StartWaitingForUpdateWith(
120 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37121 selected_shipping_profile_ = profile;
122 UpdateIsReadyToPayAndNotifyObservers();
mathp151bd31e2017-04-03 21:07:24123 delegate_->OnShippingAddressSelected(
124 PaymentResponseHelper::GetMojomPaymentAddressFromAutofillProfile(
125 selected_shipping_profile_, app_locale_));
mathpf1a7a3752017-03-15 11:23:37126}
127
128void PaymentRequestState::SetSelectedContactProfile(
129 autofill::AutofillProfile* profile) {
130 selected_contact_profile_ = profile;
131 UpdateIsReadyToPayAndNotifyObservers();
132}
133
mathp363735b2017-03-16 18:08:05134void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
135 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37136 UpdateIsReadyToPayAndNotifyObservers();
137}
138
mathpc0d616a2017-03-15 14:09:33139const std::string& PaymentRequestState::GetApplicationLocale() {
140 return app_locale_;
141}
142
143autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
144 return personal_data_manager_;
145}
146
mad45271932017-04-13 16:07:38147std::unique_ptr<const ::i18n::addressinput::Source>
148PaymentRequestState::GetAddressInputSource() {
149 return payment_request_delegate_->GetAddressInputSource();
150}
151
152std::unique_ptr<::i18n::addressinput::Storage>
153PaymentRequestState::GetAddressInputStorage() {
154 return payment_request_delegate_->GetAddressInputStorage();
155}
156
mathpf1a7a3752017-03-15 11:23:37157void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37158 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33159 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37160
161 // PaymentRequest may outlive the Profiles returned by the Data Manager.
162 // Thus, we store copies, and return a vector of pointers to these copies
163 // whenever Profiles are requested. The same is true for credit cards.
164 for (size_t i = 0; i < profiles.size(); i++) {
165 profile_cache_.push_back(
166 base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
167
tmartinoa6eb22f2017-04-06 20:16:24168 // TODO(tmartino): Implement deduplication rules specific to shipping
169 // profiles.
mathpf1a7a3752017-03-15 11:23:37170 shipping_profiles_.push_back(profile_cache_[i].get());
mathpf1a7a3752017-03-15 11:23:37171 }
172
tmartinoa6eb22f2017-04-06 20:16:24173 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering(
174 profile_cache_.size());
175 std::transform(profile_cache_.begin(), profile_cache_.end(),
176 raw_profiles_for_filtering.begin(),
177 [](const std::unique_ptr<autofill::AutofillProfile>& p) {
178 return p.get();
179 });
180
181 contact_profiles_ = profile_util::FilterProfilesForContact(
182 raw_profiles_for_filtering, GetApplicationLocale(), *spec_);
183
mathp363735b2017-03-16 18:08:05184 // Create the list of available instruments.
mathpf1a7a3752017-03-15 11:23:37185 const std::vector<autofill::CreditCard*>& cards =
mathpc0d616a2017-03-15 14:09:33186 personal_data_manager_->GetCreditCardsToSuggest();
mathp24ce4cd2017-04-12 20:56:42187 for (autofill::CreditCard* card : cards)
188 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37189}
190
191void PaymentRequestState::SetDefaultProfileSelections() {
mathp151bd31e2017-04-03 21:07:24192 // Only pre-select an address if the merchant provided at least one selected
193 // shipping option.
194 if (!shipping_profiles().empty() && spec_->selected_shipping_option())
mathpf1a7a3752017-03-15 11:23:37195 selected_shipping_profile_ = shipping_profiles()[0];
196
197 if (!contact_profiles().empty())
198 selected_contact_profile_ = contact_profiles()[0];
199
mathp363735b2017-03-16 18:08:05200 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
201 // count and other means, and implement a way to modify this function's return
202 // value.
203 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
204 available_instruments();
205 auto first_complete_instrument =
206 std::find_if(instruments.begin(), instruments.end(),
207 [](const std::unique_ptr<PaymentInstrument>& instrument) {
mathp4baea332017-04-10 21:42:29208 return instrument->IsCompleteForPayment();
mathp363735b2017-03-16 18:08:05209 });
mathpf1a7a3752017-03-15 11:23:37210
mathp363735b2017-03-16 18:08:05211 selected_instrument_ = first_complete_instrument == instruments.end()
212 ? nullptr
213 : first_complete_instrument->get();
mathpf1a7a3752017-03-15 11:23:37214
215 UpdateIsReadyToPayAndNotifyObservers();
216}
217
218void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
219 is_ready_to_pay_ =
220 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
221 NotifyOnSelectedInformationChanged();
222}
223
224void PaymentRequestState::NotifyOnSelectedInformationChanged() {
225 for (auto& observer : observers_)
226 observer.OnSelectedInformationChanged();
227}
228
229bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05230 // There is no need to check for supported networks, because only supported
231 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29232 return selected_instrument_ != nullptr &&
233 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37234}
235
236bool PaymentRequestState::ArePaymentOptionsSatisfied() {
237 // TODO(mathp): Have a measure of shipping address completeness.
238 if (spec_->request_shipping() && selected_shipping_profile_ == nullptr)
239 return false;
240
tmartinoa6eb22f2017-04-06 20:16:24241 profile_util::PaymentsProfileComparator comparator(app_locale_, *spec_);
242 return comparator.IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37243}
244
mathpf1a7a3752017-03-15 11:23:37245} // namespace payments