blob: 3cfe66c7e157a3babfe9abdb0af79c838fa59edd [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),
mathpf1a7a3752017-03-15 11:23:3749 selected_shipping_profile_(nullptr),
Mathieu Perreault04b4c662017-06-02 13:35:1350 selected_shipping_option_error_profile_(nullptr),
mathpf1a7a3752017-03-15 11:23:3751 selected_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0052 selected_instrument_(nullptr),
gogeraldac15d2362017-11-15 01:04:1953 number_of_pending_sw_payment_instruments_(0),
tmartino01c3eb82017-04-29 15:18:3954 payment_request_delegate_(payment_request_delegate),
gogerald8189d522017-09-15 17:52:1855 profile_comparator_(app_locale, *spec),
56 weak_ptr_factory_(this) {
Mathieu Perreault157f3992018-06-29 18:48:0657 if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
gogerald12a4e4ff2018-08-08 12:16:2558 DCHECK(web_contents);
gogerald8189d522017-09-15 17:52:1859 get_all_instruments_finished_ = false;
gogerald97e1b3312017-11-21 23:31:1060 ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps(
Rouslan Solomakhindbf593d92017-11-21 19:20:5761 web_contents,
Rouslan Solomakhin438d8c92017-10-26 21:33:1862 payment_request_delegate_->GetPaymentManifestWebDataService(),
Rouslan Solomakhin06df42d2017-11-14 20:35:1163 spec_->method_data(),
Rouslan Solomakhine36f41f2018-03-19 16:27:0964 /*may_crawl_for_installable_payment_apps=*/
65 !spec_->supports_basic_card(),
Rouslan Solomakhin438d8c92017-10-26 21:33:1866 base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback,
gogerald3f1cabf2018-02-08 14:19:1867 weak_ptr_factory_.GetWeakPtr(), web_contents,
68 top_level_origin, frame_origin),
gogerald97e1b3312017-11-21 23:31:1069 base::BindOnce([]() {
70 /* Nothing needs to be done after writing cache. This callback is used
71 * only in tests. */
72 }));
gogerald8189d522017-09-15 17:52:1873 } else {
74 PopulateProfileCache();
75 SetDefaultProfileSelections();
76 }
sebsg7e619132017-04-27 16:07:1077 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3778}
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5179
mathp151bd312017-04-03 21:07:2480PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3781
gogerald8189d522017-09-15 17:52:1882void PaymentRequestState::GetAllPaymentAppsCallback(
gogerald3f1cabf2018-02-08 14:19:1883 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4884 const GURL& top_level_origin,
85 const GURL& frame_origin,
gogerald84ae6262018-02-06 06:21:4686 content::PaymentAppProvider::PaymentApps apps,
87 ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps) {
gogerald3f1cabf2018-02-08 14:19:1888 number_of_pending_sw_payment_instruments_ =
89 apps.size() + installable_apps.size();
gogeraldac15d2362017-11-15 01:04:1990 if (number_of_pending_sw_payment_instruments_ == 0U) {
91 FinishedGetAllSWPaymentInstruments();
92 return;
gogerald8189d522017-09-15 17:52:1893 }
94
gogeraldac15d2362017-11-15 01:04:1995 for (auto& app : apps) {
96 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
97 std::make_unique<ServiceWorkerPaymentInstrument>(
gogerald3f1cabf2018-02-08 14:19:1898 web_contents->GetBrowserContext(), top_level_origin, frame_origin,
99 spec_, std::move(app.second), payment_request_delegate_);
100 instrument->ValidateCanMakePayment(
101 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
102 weak_ptr_factory_.GetWeakPtr()));
103 available_instruments_.push_back(std::move(instrument));
104 }
105
106 for (auto& installable_app : installable_apps) {
107 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
108 std::make_unique<ServiceWorkerPaymentInstrument>(
109 web_contents, top_level_origin, frame_origin, spec_,
110 std::move(installable_app.second), installable_app.first.spec(),
111 payment_request_delegate_);
gogeraldac15d2362017-11-15 01:04:19112 instrument->ValidateCanMakePayment(
113 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
114 weak_ptr_factory_.GetWeakPtr()));
115 available_instruments_.push_back(std::move(instrument));
116 }
117}
118
119void PaymentRequestState::OnSWPaymentInstrumentValidated(
120 ServiceWorkerPaymentInstrument* instrument,
121 bool result) {
122 // Remove service worker payment instruments failed on validation.
123 if (!result) {
124 for (size_t i = 0; i < available_instruments_.size(); i++) {
125 if (available_instruments_[i].get() == instrument) {
126 available_instruments_.erase(available_instruments_.begin() + i);
127 break;
128 }
129 }
130 }
131
132 if (--number_of_pending_sw_payment_instruments_ > 0)
133 return;
134
135 FinishedGetAllSWPaymentInstruments();
136}
137
138void PaymentRequestState::FinishedGetAllSWPaymentInstruments() {
gogerald8189d522017-09-15 17:52:18139 PopulateProfileCache();
140 SetDefaultProfileSelections();
141
142 get_all_instruments_finished_ = true;
143 NotifyOnGetAllPaymentInstrumentsFinished();
144
gogerald0a7ee6c2017-11-13 18:23:19145 // Fullfill the pending CanMakePayment call.
gogerald8189d522017-09-15 17:52:18146 if (can_make_payment_callback_)
147 CheckCanMakePayment(std::move(can_make_payment_callback_));
gogerald0a7ee6c2017-11-13 18:23:19148
149 // Fullfill the pending AreRequestedMethodsSupported call.
150 if (are_requested_methods_supported_callback_)
151 CheckRequestedMethodsSupported(
152 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18153}
154
sebsg695799a2017-04-11 16:29:06155void PaymentRequestState::OnPaymentResponseReady(
156 mojom::PaymentResponsePtr payment_response) {
157 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
158}
159
sebsg7e619132017-04-27 16:07:10160void PaymentRequestState::OnSpecUpdated() {
Mathieu Perreault04b4c662017-06-02 13:35:13161 if (spec_->selected_shipping_option_error().empty()) {
162 selected_shipping_option_error_profile_ = nullptr;
163 } else {
164 selected_shipping_option_error_profile_ = selected_shipping_profile_;
165 selected_shipping_profile_ = nullptr;
166 }
sebsg7e619132017-04-27 16:07:10167 is_waiting_for_merchant_validation_ = false;
168 UpdateIsReadyToPayAndNotifyObservers();
169}
170
gogerald0a7ee6c2017-11-13 18:23:19171void PaymentRequestState::CanMakePayment(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18172 if (!get_all_instruments_finished_) {
173 can_make_payment_callback_ = std::move(callback);
174 return;
175 }
176
177 base::ThreadTaskRunnerHandle::Get()->PostTask(
178 FROM_HERE,
179 base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
180 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
181}
182
gogerald0a7ee6c2017-11-13 18:23:19183void PaymentRequestState::CheckCanMakePayment(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18184 bool can_make_payment_value = false;
Rouslan Solomakhin25d708b2017-06-23 17:12:03185 for (const auto& instrument : available_instruments_) {
rouslan6e3cf7c62017-04-17 21:23:28186 if (instrument->IsValidForCanMakePayment()) {
gogerald8189d522017-09-15 17:52:18187 can_make_payment_value = true;
188 break;
mathp1a5be4f2017-03-24 18:09:19189 }
190 }
gogerald8189d522017-09-15 17:52:18191 std::move(callback).Run(can_make_payment_value);
mathp1a5be4f2017-03-24 18:09:19192}
193
gogerald0a7ee6c2017-11-13 18:23:19194void PaymentRequestState::AreRequestedMethodsSupported(
195 StatusCallback callback) {
196 if (!get_all_instruments_finished_) {
197 are_requested_methods_supported_callback_ = std::move(callback);
198 return;
199 }
200
201 base::ThreadTaskRunnerHandle::Get()->PostTask(
202 FROM_HERE,
203 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
204 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
205}
206
207void PaymentRequestState::CheckRequestedMethodsSupported(
208 StatusCallback callback) {
209 DCHECK(get_all_instruments_finished_);
210
211 std::move(callback).Run(!spec_->supported_card_networks().empty() ||
212 !available_instruments_.empty());
rouslan6e3cf7c62017-04-17 21:23:28213}
214
anthonyvd6a43b932017-05-11 18:39:27215std::string PaymentRequestState::GetAuthenticatedEmail() const {
216 return payment_request_delegate_->GetAuthenticatedEmail();
217}
218
mathpf1a7a3752017-03-15 11:23:37219void PaymentRequestState::AddObserver(Observer* observer) {
220 CHECK(observer);
221 observers_.AddObserver(observer);
222}
mathpf1a7a3752017-03-15 11:23:37223
224void PaymentRequestState::RemoveObserver(Observer* observer) {
225 observers_.RemoveObserver(observer);
226}
227
mathpf1a7a3752017-03-15 11:23:37228void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05229 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06230
231 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51232 response_helper_ = std::make_unique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15233 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
234 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37235}
236
sebsg8a93b272017-05-11 19:30:22237void PaymentRequestState::RecordUseStats() {
238 if (spec_->request_shipping()) {
239 DCHECK(selected_shipping_profile_);
240 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
241 }
242
243 if (spec_->request_payer_name() || spec_->request_payer_email() ||
244 spec_->request_payer_phone()) {
245 DCHECK(selected_contact_profile_);
246
247 // If the same address was used for both contact and shipping, the stats
248 // should only be updated once.
249 if (!spec_->request_shipping() || (selected_shipping_profile_->guid() !=
250 selected_contact_profile_->guid())) {
251 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
252 }
253 }
254
255 selected_instrument_->RecordUse();
256}
257
mathp24ce4cd2017-04-12 20:56:42258void PaymentRequestState::AddAutofillPaymentInstrument(
259 bool selected,
260 const autofill::CreditCard& card) {
261 std::string basic_card_network =
rouslan4e981bd32017-05-01 17:49:16262 autofill::data_util::GetPaymentRequestData(card.network())
263 .basic_card_issuer_network;
Rouslan Solomakhin25d708b2017-06-23 17:12:03264 if (!spec_->supported_card_networks_set().count(basic_card_network) ||
265 !spec_->supported_card_types_set().count(card.card_type())) {
mathp24ce4cd2017-04-12 20:56:42266 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03267 }
268
269 // The total number of card types: credit, debit, prepaid, unknown.
270 constexpr size_t kTotalNumberOfCardTypes = 4U;
271
272 // Whether the card type (credit, debit, prepaid) matches thetype that the
273 // merchant has requested exactly. This should be false for unknown card
274 // types, if the merchant cannot accept some card types.
275 bool matches_merchant_card_type_exactly =
276 card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN ||
277 spec_->supported_card_types_set().size() == kTotalNumberOfCardTypes;
mathp24ce4cd2017-04-12 20:56:42278
279 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
280 // owned by this object.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51281 auto instrument = std::make_unique<AutofillPaymentInstrument>(
Rouslan Solomakhin25d708b2017-06-23 17:12:03282 basic_card_network, card, matches_merchant_card_type_exactly,
283 shipping_profiles_, app_locale_, payment_request_delegate_);
mathp24ce4cd2017-04-12 20:56:42284 available_instruments_.push_back(std::move(instrument));
285
286 if (selected)
287 SetSelectedInstrument(available_instruments_.back().get());
288}
289
madf9904ea2017-04-25 18:39:12290void PaymentRequestState::AddAutofillShippingProfile(
291 bool selected,
292 const autofill::AutofillProfile& profile) {
293 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51294 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12295 // TODO(tmartino): Implement deduplication rules specific to shipping
296 // profiles.
297 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
298 shipping_profiles_.push_back(new_cached_profile);
299
300 if (selected)
301 SetSelectedShippingProfile(new_cached_profile);
302}
303
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23304void PaymentRequestState::AddAutofillContactProfile(
305 bool selected,
306 const autofill::AutofillProfile& profile) {
307 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51308 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23309 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
310 contact_profiles_.push_back(new_cached_profile);
311
312 if (selected)
313 SetSelectedContactProfile(new_cached_profile);
314}
315
anthonyvd0116ce332017-03-21 21:29:01316void PaymentRequestState::SetSelectedShippingOption(
mathp151bd312017-04-03 21:07:24317 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50318 spec_->StartWaitingForUpdateWith(
319 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd312017-04-03 21:07:24320 // This will inform the merchant and will lead to them calling updateWith with
321 // new PaymentDetails.
322 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01323}
324
mathpf1a7a3752017-03-15 11:23:37325void PaymentRequestState::SetSelectedShippingProfile(
326 autofill::AutofillProfile* profile) {
anthonyvd2f30baa12017-04-13 22:30:50327 spec_->StartWaitingForUpdateWith(
328 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37329 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10330
331 // The user should not be able to click on pay until the callback from the
332 // merchant.
333 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10334
335 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f2017-10-23 20:28:39336 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29337 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00338 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
339 weak_ptr_factory_.GetWeakPtr()));
mathpf1a7a3752017-03-15 11:23:37340}
341
342void PaymentRequestState::SetSelectedContactProfile(
343 autofill::AutofillProfile* profile) {
344 selected_contact_profile_ = profile;
345 UpdateIsReadyToPayAndNotifyObservers();
346}
347
mathp363735b2017-03-16 18:08:05348void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
349 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37350 UpdateIsReadyToPayAndNotifyObservers();
351}
352
mathpc0d616a2017-03-15 14:09:33353const std::string& PaymentRequestState::GetApplicationLocale() {
354 return app_locale_;
355}
356
357autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
358 return personal_data_manager_;
359}
360
mad763ed2b2017-04-24 20:28:47361autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
362 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38363}
364
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56365bool PaymentRequestState::IsPaymentAppInvoked() const {
366 return !!response_helper_;
367}
368
Mathieu Perreaulteea046d12017-09-28 15:51:21369autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45370 return payment_request_delegate_->GetAddressNormalizer();
371}
372
mathpf1a7a3752017-03-15 11:23:37373void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37374 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33375 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37376
tmartinocd131b32017-05-24 19:40:59377 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
378 raw_profiles_for_filtering.reserve(profiles.size());
379
mathpf1a7a3752017-03-15 11:23:37380 // PaymentRequest may outlive the Profiles returned by the Data Manager.
381 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30382 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37383 for (size_t i = 0; i < profiles.size(); i++) {
384 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51385 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59386 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37387 }
388
tmartino01c3eb82017-04-29 15:18:39389 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
390 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59391 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
392 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24393
sebsgc6719b32017-07-05 19:54:47394 // Set the number of suggestions shown for the sections requested by the
395 // merchant.
396 if (spec_->request_payer_name() || spec_->request_payer_phone() ||
397 spec_->request_payer_email()) {
sebsgce700484d2017-07-19 23:25:38398 bool has_complete_contact =
399 contact_profiles_.empty()
400 ? false
401 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47402 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38403 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
404 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47405 }
406 if (spec_->request_shipping()) {
sebsgce700484d2017-07-19 23:25:38407 bool has_complete_shipping =
408 shipping_profiles_.empty()
409 ? false
410 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47411 journey_logger_->SetNumberOfSuggestionsShown(
412 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38413 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47414 }
415
mathpf14c1e32017-05-12 16:37:30416 // Create the list of available instruments. A copy of each card will be made
417 // by their respective AutofillPaymentInstrument.
mathpf1a7a3752017-03-15 11:23:37418 const std::vector<autofill::CreditCard*>& cards =
Amirhossein Simjourd3b7ba4a2018-05-07 15:27:21419 personal_data_manager_->GetCreditCardsToSuggest(
Mathieu Perreault157f3992018-06-29 18:48:06420 /*include_server_cards=*/base::FeatureList::IsEnabled(
421 payments::features::kReturnGooglePayInBasicCard));
mathp24ce4cd2017-04-12 20:56:42422 for (autofill::CreditCard* card : cards)
423 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37424}
425
426void PaymentRequestState::SetDefaultProfileSelections() {
mathp151bd312017-04-03 21:07:24427 // Only pre-select an address if the merchant provided at least one selected
tmartinocd131b32017-05-24 19:40:59428 // shipping option, and the top profile is complete. Assumes that profiles
429 // have already been sorted for completeness and frecency.
430 if (!shipping_profiles().empty() && spec_->selected_shipping_option() &&
431 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
432 selected_shipping_profile_ = shipping_profiles()[0];
mathpf14c1e32017-05-12 16:37:30433 }
mathpf1a7a3752017-03-15 11:23:37434
mathpf14c1e32017-05-12 16:37:30435 // Contact profiles were ordered by completeness in addition to frecency;
436 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59437 if (!contact_profiles().empty() &&
438 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37439 selected_contact_profile_ = contact_profiles()[0];
440
mathp363735b2017-03-16 18:08:05441 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
442 // count and other means, and implement a way to modify this function's return
443 // value.
444 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
445 available_instruments();
446 auto first_complete_instrument =
447 std::find_if(instruments.begin(), instruments.end(),
448 [](const std::unique_ptr<PaymentInstrument>& instrument) {
Rouslan Solomakhin25d708b2017-06-23 17:12:03449 return instrument->IsCompleteForPayment() &&
450 instrument->IsExactlyMatchingMerchantRequest();
mathp363735b2017-03-16 18:08:05451 });
mathp363735b2017-03-16 18:08:05452 selected_instrument_ = first_complete_instrument == instruments.end()
453 ? nullptr
454 : first_complete_instrument->get();
mathpf1a7a3752017-03-15 11:23:37455 UpdateIsReadyToPayAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18456
457 bool has_complete_instrument =
458 available_instruments().empty()
459 ? false
460 : available_instruments()[0]->IsCompleteForPayment();
461
462 journey_logger_->SetNumberOfSuggestionsShown(
463 JourneyLogger::Section::SECTION_PAYMENT_METHOD,
464 available_instruments().size(), has_complete_instrument);
mathpf1a7a3752017-03-15 11:23:37465}
466
467void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
468 is_ready_to_pay_ =
469 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
470 NotifyOnSelectedInformationChanged();
471}
472
gogerald8189d522017-09-15 17:52:18473void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() {
474 for (auto& observer : observers_)
475 observer.OnGetAllPaymentInstrumentsFinished();
476}
477
mathpf1a7a3752017-03-15 11:23:37478void PaymentRequestState::NotifyOnSelectedInformationChanged() {
479 for (auto& observer : observers_)
480 observer.OnSelectedInformationChanged();
481}
482
483bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05484 // There is no need to check for supported networks, because only supported
485 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29486 return selected_instrument_ != nullptr &&
487 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37488}
489
490bool PaymentRequestState::ArePaymentOptionsSatisfied() {
sebsg7e619132017-04-27 16:07:10491 if (is_waiting_for_merchant_validation_)
492 return false;
493
tmartino01c3eb82017-04-29 15:18:39494 if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_))
495 return false;
496
Anthony Vallee-Duboisa8814672017-06-01 18:43:20497 if (spec_->request_shipping() && !spec_->selected_shipping_option())
498 return false;
499
tmartino01c3eb82017-04-29 15:18:39500 return profile_comparator()->IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37501}
502
Mathieu Perreault17c1ae92017-10-20 17:16:00503void PaymentRequestState::OnAddressNormalized(
504 bool success,
505 const autofill::AutofillProfile& normalized_profile) {
506 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22507 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
508 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00509}
510
mathpf1a7a3752017-03-15 11:23:37511} // namespace payments