blob: 7d3afca23b6cf11c64fa4e0a133ee6af5ba791a7 [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
gogerald8189d522017-09-15 17:52:1811#include "base/feature_list.h"
sebsgad86bd002017-03-29 16:39:1212#include "base/strings/utf_string_conversions.h"
sebsg7e619132017-04-27 16:07:1013#include "components/autofill/core/browser/autofill_country.h"
mathpf1a7a3752017-03-15 11:23:3714#include "components/autofill/core/browser/autofill_data_util.h"
15#include "components/autofill/core/browser/autofill_profile.h"
16#include "components/autofill/core/browser/credit_card.h"
mathpc0d616a2017-03-15 14:09:3317#include "components/autofill/core/browser/personal_data_manager.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5118#include "components/payments/content/content_payment_request_delegate.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5119#include "components/payments/content/payment_manifest_web_data_service.h"
sebsgad86bd002017-03-29 16:39:1220#include "components/payments/content/payment_response_helper.h"
gogerald8189d522017-09-15 17:52:1821#include "components/payments/content/service_worker_payment_instrument.h"
mathpf1a7a3752017-03-15 11:23:3722#include "components/payments/core/autofill_payment_instrument.h"
Mathieu Perreault157f3992018-06-29 18:48:0623#include "components/payments/core/features.h"
sebsgc6719b32017-07-05 19:54:4724#include "components/payments/core/journey_logger.h"
sebsg695799a2017-04-11 16:29:0625#include "components/payments/core/payment_instrument.h"
tmartino01c3eb82017-04-29 15:18:3926#include "components/payments/core/payment_request_data_util.h"
gogerald8189d522017-09-15 17:52:1827#include "content/public/common/content_features.h"
mathpf1a7a3752017-03-15 11:23:3728
29namespace payments {
30
mathpc0d616a2017-03-15 14:09:3331PaymentRequestState::PaymentRequestState(
Rouslan Solomakhindbf593d92017-11-21 19:20:5732 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4833 const GURL& top_level_origin,
34 const GURL& frame_origin,
mathpc0d616a2017-03-15 14:09:3335 PaymentRequestSpec* spec,
36 Delegate* delegate,
37 const std::string& app_locale,
anthonyvdd23ed702017-04-05 15:29:0038 autofill::PersonalDataManager* personal_data_manager,
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5139 ContentPaymentRequestDelegate* payment_request_delegate,
sebsgc6719b32017-07-05 19:54:4740 JourneyLogger* journey_logger)
mathpf1a7a3752017-03-15 11:23:3741 : is_ready_to_pay_(false),
gogerald8189d522017-09-15 17:52:1842 get_all_instruments_finished_(true),
sebsg7e619132017-04-27 16:07:1043 is_waiting_for_merchant_validation_(false),
mathpc0d616a2017-03-15 14:09:3344 app_locale_(app_locale),
mathpf1a7a3752017-03-15 11:23:3745 spec_(spec),
46 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3347 personal_data_manager_(personal_data_manager),
sebsgc6719b32017-07-05 19:54:4748 journey_logger_(journey_logger),
Rouslan Solomakhind2cae95a2018-08-09 00:16:1049 are_requested_methods_supported_(
50 !spec_->supported_card_networks().empty()),
mathpf1a7a3752017-03-15 11:23:3751 selected_shipping_profile_(nullptr),
Mathieu Perreault04b4c662017-06-02 13:35:1352 selected_shipping_option_error_profile_(nullptr),
mathpf1a7a3752017-03-15 11:23:3753 selected_contact_profile_(nullptr),
Jinho Bangcac8d9a02018-08-23 19:47:2254 invalid_shipping_profile_(nullptr),
55 invalid_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0056 selected_instrument_(nullptr),
gogeraldac15d2362017-11-15 01:04:1957 number_of_pending_sw_payment_instruments_(0),
tmartino01c3eb82017-04-29 15:18:3958 payment_request_delegate_(payment_request_delegate),
gogerald8189d522017-09-15 17:52:1859 profile_comparator_(app_locale, *spec),
60 weak_ptr_factory_(this) {
Mathieu Perreault157f3992018-06-29 18:48:0661 if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
gogerald12a4e4ff2018-08-08 12:16:2562 DCHECK(web_contents);
gogerald8189d522017-09-15 17:52:1863 get_all_instruments_finished_ = false;
gogerald97e1b3312017-11-21 23:31:1064 ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps(
Rouslan Solomakhindbf593d92017-11-21 19:20:5765 web_contents,
Rouslan Solomakhin438d8c92017-10-26 21:33:1866 payment_request_delegate_->GetPaymentManifestWebDataService(),
Rouslan Solomakhin06df42d2017-11-14 20:35:1167 spec_->method_data(),
Rouslan Solomakhine36f41f2018-03-19 16:27:0968 /*may_crawl_for_installable_payment_apps=*/
69 !spec_->supports_basic_card(),
Rouslan Solomakhin438d8c92017-10-26 21:33:1870 base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback,
gogerald3f1cabf2018-02-08 14:19:1871 weak_ptr_factory_.GetWeakPtr(), web_contents,
72 top_level_origin, frame_origin),
gogerald97e1b3312017-11-21 23:31:1073 base::BindOnce([]() {
74 /* Nothing needs to be done after writing cache. This callback is used
75 * only in tests. */
76 }));
gogerald8189d522017-09-15 17:52:1877 } else {
78 PopulateProfileCache();
79 SetDefaultProfileSelections();
80 }
sebsg7e619132017-04-27 16:07:1081 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3782}
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5183
mathp151bd31e2017-04-03 21:07:2484PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3785
gogerald8189d522017-09-15 17:52:1886void PaymentRequestState::GetAllPaymentAppsCallback(
gogerald3f1cabf2018-02-08 14:19:1887 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4888 const GURL& top_level_origin,
89 const GURL& frame_origin,
gogerald84ae6262018-02-06 06:21:4690 content::PaymentAppProvider::PaymentApps apps,
91 ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps) {
gogerald3f1cabf2018-02-08 14:19:1892 number_of_pending_sw_payment_instruments_ =
93 apps.size() + installable_apps.size();
gogeraldac15d2362017-11-15 01:04:1994 if (number_of_pending_sw_payment_instruments_ == 0U) {
95 FinishedGetAllSWPaymentInstruments();
96 return;
gogerald8189d522017-09-15 17:52:1897 }
98
gogeraldac15d2362017-11-15 01:04:1999 for (auto& app : apps) {
100 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
101 std::make_unique<ServiceWorkerPaymentInstrument>(
gogerald3f1cabf2018-02-08 14:19:18102 web_contents->GetBrowserContext(), top_level_origin, frame_origin,
103 spec_, std::move(app.second), payment_request_delegate_);
104 instrument->ValidateCanMakePayment(
105 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
106 weak_ptr_factory_.GetWeakPtr()));
107 available_instruments_.push_back(std::move(instrument));
108 }
109
110 for (auto& installable_app : installable_apps) {
111 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
112 std::make_unique<ServiceWorkerPaymentInstrument>(
113 web_contents, top_level_origin, frame_origin, spec_,
114 std::move(installable_app.second), installable_app.first.spec(),
115 payment_request_delegate_);
gogeraldac15d2362017-11-15 01:04:19116 instrument->ValidateCanMakePayment(
117 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
118 weak_ptr_factory_.GetWeakPtr()));
119 available_instruments_.push_back(std::move(instrument));
120 }
121}
122
123void PaymentRequestState::OnSWPaymentInstrumentValidated(
124 ServiceWorkerPaymentInstrument* instrument,
125 bool result) {
126 // Remove service worker payment instruments failed on validation.
127 if (!result) {
128 for (size_t i = 0; i < available_instruments_.size(); i++) {
129 if (available_instruments_[i].get() == instrument) {
130 available_instruments_.erase(available_instruments_.begin() + i);
131 break;
132 }
133 }
134 }
135
136 if (--number_of_pending_sw_payment_instruments_ > 0)
137 return;
138
139 FinishedGetAllSWPaymentInstruments();
140}
141
142void PaymentRequestState::FinishedGetAllSWPaymentInstruments() {
gogerald8189d522017-09-15 17:52:18143 PopulateProfileCache();
144 SetDefaultProfileSelections();
145
146 get_all_instruments_finished_ = true;
Rouslan Solomakhind2cae95a2018-08-09 00:16:10147 are_requested_methods_supported_ |= !available_instruments_.empty();
gogerald8189d522017-09-15 17:52:18148 NotifyOnGetAllPaymentInstrumentsFinished();
149
gogerald0a7ee6c2017-11-13 18:23:19150 // Fullfill the pending CanMakePayment call.
gogerald8189d522017-09-15 17:52:18151 if (can_make_payment_callback_)
152 CheckCanMakePayment(std::move(can_make_payment_callback_));
gogerald0a7ee6c2017-11-13 18:23:19153
154 // Fullfill the pending AreRequestedMethodsSupported call.
155 if (are_requested_methods_supported_callback_)
156 CheckRequestedMethodsSupported(
157 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18158}
159
sebsg695799a2017-04-11 16:29:06160void PaymentRequestState::OnPaymentResponseReady(
161 mojom::PaymentResponsePtr payment_response) {
162 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
163}
164
sebsg7e619132017-04-27 16:07:10165void PaymentRequestState::OnSpecUpdated() {
Jinho Bangcac8d9a02018-08-23 19:47:22166 autofill::AutofillProfile* selected_shipping_profile =
167 selected_shipping_profile_;
168 autofill::AutofillProfile* selected_contact_profile =
169 selected_contact_profile_;
170
171 if (spec_->current_update_reason() ==
172 PaymentRequestSpec::UpdateReason::RETRY) {
173 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
174 invalid_shipping_profile_ = selected_shipping_profile;
175 selected_shipping_profile_ = nullptr;
176 }
Jinho Bang092e7162018-09-06 23:41:19177
Jinho Bangcac8d9a02018-08-23 19:47:22178 if (spec_->has_payer_error() && selected_contact_profile) {
179 invalid_contact_profile_ = selected_contact_profile;
180 selected_contact_profile_ = nullptr;
181 }
182 }
183
Mathieu Perreault04b4c662017-06-02 13:35:13184 if (spec_->selected_shipping_option_error().empty()) {
185 selected_shipping_option_error_profile_ = nullptr;
186 } else {
Jinho Bangcac8d9a02018-08-23 19:47:22187 selected_shipping_option_error_profile_ = selected_shipping_profile;
Mathieu Perreault04b4c662017-06-02 13:35:13188 selected_shipping_profile_ = nullptr;
Jinho Bang092e7162018-09-06 23:41:19189 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
190 invalid_shipping_profile_ = selected_shipping_profile;
191 }
Mathieu Perreault04b4c662017-06-02 13:35:13192 }
Jinho Bangcac8d9a02018-08-23 19:47:22193
sebsg7e619132017-04-27 16:07:10194 is_waiting_for_merchant_validation_ = false;
195 UpdateIsReadyToPayAndNotifyObservers();
196}
197
gogerald0a7ee6c2017-11-13 18:23:19198void PaymentRequestState::CanMakePayment(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18199 if (!get_all_instruments_finished_) {
200 can_make_payment_callback_ = std::move(callback);
201 return;
202 }
203
204 base::ThreadTaskRunnerHandle::Get()->PostTask(
205 FROM_HERE,
206 base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
207 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
208}
209
gogerald0a7ee6c2017-11-13 18:23:19210void PaymentRequestState::CheckCanMakePayment(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18211 bool can_make_payment_value = false;
Rouslan Solomakhin25d708b2017-06-23 17:12:03212 for (const auto& instrument : available_instruments_) {
rouslan6e3cf7c62017-04-17 21:23:28213 if (instrument->IsValidForCanMakePayment()) {
gogerald8189d522017-09-15 17:52:18214 can_make_payment_value = true;
215 break;
mathp1a5be4f2017-03-24 18:09:19216 }
217 }
gogerald8189d522017-09-15 17:52:18218 std::move(callback).Run(can_make_payment_value);
mathp1a5be4f2017-03-24 18:09:19219}
220
gogerald0a7ee6c2017-11-13 18:23:19221void PaymentRequestState::AreRequestedMethodsSupported(
222 StatusCallback callback) {
223 if (!get_all_instruments_finished_) {
224 are_requested_methods_supported_callback_ = std::move(callback);
225 return;
226 }
227
228 base::ThreadTaskRunnerHandle::Get()->PostTask(
229 FROM_HERE,
230 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
231 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
232}
233
234void PaymentRequestState::CheckRequestedMethodsSupported(
235 StatusCallback callback) {
236 DCHECK(get_all_instruments_finished_);
237
Rouslan Solomakhind2cae95a2018-08-09 00:16:10238 std::move(callback).Run(are_requested_methods_supported_);
rouslan6e3cf7c62017-04-17 21:23:28239}
240
anthonyvd6a43b932017-05-11 18:39:27241std::string PaymentRequestState::GetAuthenticatedEmail() const {
242 return payment_request_delegate_->GetAuthenticatedEmail();
243}
244
mathpf1a7a3752017-03-15 11:23:37245void PaymentRequestState::AddObserver(Observer* observer) {
246 CHECK(observer);
247 observers_.AddObserver(observer);
248}
mathpf1a7a3752017-03-15 11:23:37249
250void PaymentRequestState::RemoveObserver(Observer* observer) {
251 observers_.RemoveObserver(observer);
252}
253
mathpf1a7a3752017-03-15 11:23:37254void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05255 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06256
257 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51258 response_helper_ = std::make_unique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15259 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
260 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37261}
262
sebsg8a93b272017-05-11 19:30:22263void PaymentRequestState::RecordUseStats() {
264 if (spec_->request_shipping()) {
265 DCHECK(selected_shipping_profile_);
266 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
267 }
268
269 if (spec_->request_payer_name() || spec_->request_payer_email() ||
270 spec_->request_payer_phone()) {
271 DCHECK(selected_contact_profile_);
272
273 // If the same address was used for both contact and shipping, the stats
274 // should only be updated once.
275 if (!spec_->request_shipping() || (selected_shipping_profile_->guid() !=
276 selected_contact_profile_->guid())) {
277 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
278 }
279 }
280
281 selected_instrument_->RecordUse();
282}
283
mathp24ce4cd2017-04-12 20:56:42284void PaymentRequestState::AddAutofillPaymentInstrument(
285 bool selected,
286 const autofill::CreditCard& card) {
287 std::string basic_card_network =
rouslan4e981bd32017-05-01 17:49:16288 autofill::data_util::GetPaymentRequestData(card.network())
289 .basic_card_issuer_network;
Rouslan Solomakhin25d708b2017-06-23 17:12:03290 if (!spec_->supported_card_networks_set().count(basic_card_network) ||
291 !spec_->supported_card_types_set().count(card.card_type())) {
mathp24ce4cd2017-04-12 20:56:42292 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03293 }
294
295 // The total number of card types: credit, debit, prepaid, unknown.
296 constexpr size_t kTotalNumberOfCardTypes = 4U;
297
298 // Whether the card type (credit, debit, prepaid) matches thetype that the
299 // merchant has requested exactly. This should be false for unknown card
300 // types, if the merchant cannot accept some card types.
301 bool matches_merchant_card_type_exactly =
302 card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN ||
303 spec_->supported_card_types_set().size() == kTotalNumberOfCardTypes;
mathp24ce4cd2017-04-12 20:56:42304
305 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
306 // owned by this object.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51307 auto instrument = std::make_unique<AutofillPaymentInstrument>(
Rouslan Solomakhin25d708b2017-06-23 17:12:03308 basic_card_network, card, matches_merchant_card_type_exactly,
309 shipping_profiles_, app_locale_, payment_request_delegate_);
mathp24ce4cd2017-04-12 20:56:42310 available_instruments_.push_back(std::move(instrument));
311
312 if (selected)
313 SetSelectedInstrument(available_instruments_.back().get());
314}
315
madf9904ea2017-04-25 18:39:12316void PaymentRequestState::AddAutofillShippingProfile(
317 bool selected,
318 const autofill::AutofillProfile& profile) {
319 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51320 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12321 // TODO(tmartino): Implement deduplication rules specific to shipping
322 // profiles.
323 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
324 shipping_profiles_.push_back(new_cached_profile);
325
326 if (selected)
327 SetSelectedShippingProfile(new_cached_profile);
328}
329
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23330void PaymentRequestState::AddAutofillContactProfile(
331 bool selected,
332 const autofill::AutofillProfile& profile) {
333 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51334 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23335 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
336 contact_profiles_.push_back(new_cached_profile);
337
338 if (selected)
339 SetSelectedContactProfile(new_cached_profile);
340}
341
anthonyvd0116ce332017-03-21 21:29:01342void PaymentRequestState::SetSelectedShippingOption(
mathp151bd31e2017-04-03 21:07:24343 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50344 spec_->StartWaitingForUpdateWith(
345 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd31e2017-04-03 21:07:24346 // This will inform the merchant and will lead to them calling updateWith with
347 // new PaymentDetails.
348 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01349}
350
mathpf1a7a3752017-03-15 11:23:37351void PaymentRequestState::SetSelectedShippingProfile(
352 autofill::AutofillProfile* profile) {
anthonyvd2f30baa12017-04-13 22:30:50353 spec_->StartWaitingForUpdateWith(
354 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37355 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10356
Jinho Bangcac8d9a02018-08-23 19:47:22357 // Changing the shipping address clears shipping address validation errors
358 // from retry().
359 invalid_shipping_profile_ = nullptr;
360
sebsg7e619132017-04-27 16:07:10361 // The user should not be able to click on pay until the callback from the
362 // merchant.
363 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10364
365 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f112017-10-23 20:28:39366 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29367 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00368 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
369 weak_ptr_factory_.GetWeakPtr()));
mathpf1a7a3752017-03-15 11:23:37370}
371
372void PaymentRequestState::SetSelectedContactProfile(
373 autofill::AutofillProfile* profile) {
374 selected_contact_profile_ = profile;
Jinho Bangcac8d9a02018-08-23 19:47:22375
376 // Changing the contact information clears contact information validation
377 // errors from retry().
378 invalid_contact_profile_ = nullptr;
379
mathpf1a7a3752017-03-15 11:23:37380 UpdateIsReadyToPayAndNotifyObservers();
Jinho Bangbb178152018-09-13 09:44:43381
382 if (IsPaymentAppInvoked()) {
383 delegate_->OnPayerInfoSelected(response_helper_->GeneratePayerDetail());
384 }
mathpf1a7a3752017-03-15 11:23:37385}
386
mathp363735b2017-03-16 18:08:05387void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
388 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37389 UpdateIsReadyToPayAndNotifyObservers();
390}
391
mathpc0d616a2017-03-15 14:09:33392const std::string& PaymentRequestState::GetApplicationLocale() {
393 return app_locale_;
394}
395
396autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
397 return personal_data_manager_;
398}
399
mad763ed2b2017-04-24 20:28:47400autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
401 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38402}
403
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56404bool PaymentRequestState::IsPaymentAppInvoked() const {
405 return !!response_helper_;
406}
407
Mathieu Perreaulteea046d12017-09-28 15:51:21408autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45409 return payment_request_delegate_->GetAddressNormalizer();
410}
411
mathpf1a7a3752017-03-15 11:23:37412void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37413 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33414 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37415
tmartinocd131b32017-05-24 19:40:59416 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
417 raw_profiles_for_filtering.reserve(profiles.size());
418
mathpf1a7a3752017-03-15 11:23:37419 // PaymentRequest may outlive the Profiles returned by the Data Manager.
420 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30421 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37422 for (size_t i = 0; i < profiles.size(); i++) {
423 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51424 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59425 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37426 }
427
tmartino01c3eb82017-04-29 15:18:39428 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
429 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59430 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
431 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24432
sebsgc6719b32017-07-05 19:54:47433 // Set the number of suggestions shown for the sections requested by the
434 // merchant.
435 if (spec_->request_payer_name() || spec_->request_payer_phone() ||
436 spec_->request_payer_email()) {
sebsgce700484d2017-07-19 23:25:38437 bool has_complete_contact =
438 contact_profiles_.empty()
439 ? false
440 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47441 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38442 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
443 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47444 }
445 if (spec_->request_shipping()) {
sebsgce700484d2017-07-19 23:25:38446 bool has_complete_shipping =
447 shipping_profiles_.empty()
448 ? false
449 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47450 journey_logger_->SetNumberOfSuggestionsShown(
451 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38452 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47453 }
454
mathpf14c1e32017-05-12 16:37:30455 // Create the list of available instruments. A copy of each card will be made
456 // by their respective AutofillPaymentInstrument.
mathpf1a7a3752017-03-15 11:23:37457 const std::vector<autofill::CreditCard*>& cards =
Amirhossein Simjourd3b7ba4a2018-05-07 15:27:21458 personal_data_manager_->GetCreditCardsToSuggest(
Mathieu Perreault157f3992018-06-29 18:48:06459 /*include_server_cards=*/base::FeatureList::IsEnabled(
460 payments::features::kReturnGooglePayInBasicCard));
mathp24ce4cd2017-04-12 20:56:42461 for (autofill::CreditCard* card : cards)
462 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37463}
464
465void PaymentRequestState::SetDefaultProfileSelections() {
mathp151bd31e2017-04-03 21:07:24466 // Only pre-select an address if the merchant provided at least one selected
tmartinocd131b32017-05-24 19:40:59467 // shipping option, and the top profile is complete. Assumes that profiles
468 // have already been sorted for completeness and frecency.
469 if (!shipping_profiles().empty() && spec_->selected_shipping_option() &&
470 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
471 selected_shipping_profile_ = shipping_profiles()[0];
mathpf14c1e32017-05-12 16:37:30472 }
mathpf1a7a3752017-03-15 11:23:37473
mathpf14c1e32017-05-12 16:37:30474 // Contact profiles were ordered by completeness in addition to frecency;
475 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59476 if (!contact_profiles().empty() &&
477 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37478 selected_contact_profile_ = contact_profiles()[0];
479
mathp363735b2017-03-16 18:08:05480 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
481 // count and other means, and implement a way to modify this function's return
482 // value.
483 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
484 available_instruments();
485 auto first_complete_instrument =
486 std::find_if(instruments.begin(), instruments.end(),
487 [](const std::unique_ptr<PaymentInstrument>& instrument) {
Rouslan Solomakhin25d708b2017-06-23 17:12:03488 return instrument->IsCompleteForPayment() &&
489 instrument->IsExactlyMatchingMerchantRequest();
mathp363735b2017-03-16 18:08:05490 });
mathp363735b2017-03-16 18:08:05491 selected_instrument_ = first_complete_instrument == instruments.end()
492 ? nullptr
493 : first_complete_instrument->get();
mathpf1a7a3752017-03-15 11:23:37494 UpdateIsReadyToPayAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18495
496 bool has_complete_instrument =
497 available_instruments().empty()
498 ? false
499 : available_instruments()[0]->IsCompleteForPayment();
500
501 journey_logger_->SetNumberOfSuggestionsShown(
502 JourneyLogger::Section::SECTION_PAYMENT_METHOD,
503 available_instruments().size(), has_complete_instrument);
mathpf1a7a3752017-03-15 11:23:37504}
505
506void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
507 is_ready_to_pay_ =
508 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
509 NotifyOnSelectedInformationChanged();
510}
511
gogerald8189d522017-09-15 17:52:18512void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() {
513 for (auto& observer : observers_)
514 observer.OnGetAllPaymentInstrumentsFinished();
515}
516
mathpf1a7a3752017-03-15 11:23:37517void PaymentRequestState::NotifyOnSelectedInformationChanged() {
518 for (auto& observer : observers_)
519 observer.OnSelectedInformationChanged();
520}
521
522bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05523 // There is no need to check for supported networks, because only supported
524 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29525 return selected_instrument_ != nullptr &&
526 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37527}
528
529bool PaymentRequestState::ArePaymentOptionsSatisfied() {
sebsg7e619132017-04-27 16:07:10530 if (is_waiting_for_merchant_validation_)
531 return false;
532
tmartino01c3eb82017-04-29 15:18:39533 if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_))
534 return false;
535
Anthony Vallee-Duboisa8814672017-06-01 18:43:20536 if (spec_->request_shipping() && !spec_->selected_shipping_option())
537 return false;
538
tmartino01c3eb82017-04-29 15:18:39539 return profile_comparator()->IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37540}
541
Mathieu Perreault17c1ae92017-10-20 17:16:00542void PaymentRequestState::OnAddressNormalized(
543 bool success,
544 const autofill::AutofillProfile& normalized_profile) {
545 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22546 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
547 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00548}
549
mathpf1a7a3752017-03-15 11:23:37550} // namespace payments