blob: 12695a9d23d3948d1a6396e368d58a7122c9742a [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
Sebastien Marchand53801a32019-01-25 16:26:1111#include "base/bind.h"
gogerald8189d522017-09-15 17:52:1812#include "base/feature_list.h"
Sahel Sharify6efdfb32019-07-02 16:12:1613#include "base/metrics/histogram_functions.h"
sebsgad86bd002017-03-29 16:39:1214#include "base/strings/utf_string_conversions.h"
mathpf1a7a3752017-03-15 11:23:3715#include "components/autofill/core/browser/autofill_data_util.h"
Dominic Battreaed20f9f2019-05-10 19:09:5216#include "components/autofill/core/browser/data_model/autofill_profile.h"
17#include "components/autofill/core/browser/data_model/credit_card.h"
Dominic Battredd73d262019-05-15 20:10:3818#include "components/autofill/core/browser/geo/autofill_country.h"
mathpc0d616a2017-03-15 14:09:3319#include "components/autofill/core/browser/personal_data_manager.h"
Sahel Sharify6efdfb32019-07-02 16:12:1620#include "components/autofill/core/browser/validation.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5121#include "components/payments/content/content_payment_request_delegate.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5122#include "components/payments/content/payment_manifest_web_data_service.h"
sebsgad86bd002017-03-29 16:39:1223#include "components/payments/content/payment_response_helper.h"
gogerald8189d522017-09-15 17:52:1824#include "components/payments/content/service_worker_payment_instrument.h"
Sahel Sharify13331e82019-07-12 01:00:3025#include "components/payments/core/autofill_card_validation.h"
mathpf1a7a3752017-03-15 11:23:3726#include "components/payments/core/autofill_payment_instrument.h"
Mathieu Perreault157f3992018-06-29 18:48:0627#include "components/payments/core/features.h"
sebsg695799a2017-04-11 16:29:0628#include "components/payments/core/payment_instrument.h"
tmartino01c3eb82017-04-29 15:18:3929#include "components/payments/core/payment_request_data_util.h"
Danyao Wang761739b2019-06-27 23:59:3230#include "components/payments/core/payments_experimental_features.h"
gogerald8189d522017-09-15 17:52:1831#include "content/public/common/content_features.h"
mathpf1a7a3752017-03-15 11:23:3732
33namespace payments {
34
mathpc0d616a2017-03-15 14:09:3335PaymentRequestState::PaymentRequestState(
Rouslan Solomakhindbf593d92017-11-21 19:20:5736 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4837 const GURL& top_level_origin,
38 const GURL& frame_origin,
mathpc0d616a2017-03-15 14:09:3339 PaymentRequestSpec* spec,
40 Delegate* delegate,
41 const std::string& app_locale,
anthonyvdd23ed702017-04-05 15:29:0042 autofill::PersonalDataManager* personal_data_manager,
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5143 ContentPaymentRequestDelegate* payment_request_delegate,
Rouslan Solomakhin1f95f092019-08-09 12:28:5144 ServiceWorkerPaymentInstrument::IdentityObserver* sw_identity_observer,
sebsgc6719b32017-07-05 19:54:4745 JourneyLogger* journey_logger)
mathpf1a7a3752017-03-15 11:23:3746 : is_ready_to_pay_(false),
gogerald8189d522017-09-15 17:52:1847 get_all_instruments_finished_(true),
sebsg7e619132017-04-27 16:07:1048 is_waiting_for_merchant_validation_(false),
mathpc0d616a2017-03-15 14:09:3349 app_locale_(app_locale),
mathpf1a7a3752017-03-15 11:23:3750 spec_(spec),
51 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3352 personal_data_manager_(personal_data_manager),
sebsgc6719b32017-07-05 19:54:4753 journey_logger_(journey_logger),
Rouslan Solomakhind2cae95a2018-08-09 00:16:1054 are_requested_methods_supported_(
55 !spec_->supported_card_networks().empty()),
mathpf1a7a3752017-03-15 11:23:3756 selected_shipping_profile_(nullptr),
Mathieu Perreault04b4c662017-06-02 13:35:1357 selected_shipping_option_error_profile_(nullptr),
mathpf1a7a3752017-03-15 11:23:3758 selected_contact_profile_(nullptr),
Jinho Bangcac8d9a02018-08-23 19:47:2259 invalid_shipping_profile_(nullptr),
60 invalid_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0061 selected_instrument_(nullptr),
gogeraldac15d2362017-11-15 01:04:1962 number_of_pending_sw_payment_instruments_(0),
tmartino01c3eb82017-04-29 15:18:3963 payment_request_delegate_(payment_request_delegate),
Rouslan Solomakhin1f95f092019-08-09 12:28:5164 sw_identity_observer_(sw_identity_observer),
Jeremy Roman5c341f6d2019-07-15 15:56:1065 profile_comparator_(app_locale, *spec) {
Rouslan Solomakhin1f95f092019-08-09 12:28:5166 DCHECK(sw_identity_observer_);
Mathieu Perreault157f3992018-06-29 18:48:0667 if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
gogerald12a4e4ff2018-08-08 12:16:2568 DCHECK(web_contents);
gogerald8189d522017-09-15 17:52:1869 get_all_instruments_finished_ = false;
Danyao Wang761739b2019-06-27 23:59:3270 bool may_crawl_for_installable_payment_apps =
71 PaymentsExperimentalFeatures::IsEnabled(
72 features::kAlwaysAllowJustInTimePaymentApp) ||
73 !spec_->supports_basic_card();
74
gogerald97e1b3312017-11-21 23:31:1075 ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps(
Rouslan Solomakhindbf593d92017-11-21 19:20:5776 web_contents,
Rouslan Solomakhin438d8c92017-10-26 21:33:1877 payment_request_delegate_->GetPaymentManifestWebDataService(),
Danyao Wang761739b2019-06-27 23:59:3278 spec_->method_data(), may_crawl_for_installable_payment_apps,
Rouslan Solomakhin438d8c92017-10-26 21:33:1879 base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback,
gogerald3f1cabf2018-02-08 14:19:1880 weak_ptr_factory_.GetWeakPtr(), web_contents,
81 top_level_origin, frame_origin),
gogerald97e1b3312017-11-21 23:31:1082 base::BindOnce([]() {
83 /* Nothing needs to be done after writing cache. This callback is used
84 * only in tests. */
85 }));
gogerald8189d522017-09-15 17:52:1886 } else {
87 PopulateProfileCache();
88 SetDefaultProfileSelections();
89 }
sebsg7e619132017-04-27 16:07:1090 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3791}
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5192
mathp151bd31e2017-04-03 21:07:2493PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3794
gogerald8189d522017-09-15 17:52:1895void PaymentRequestState::GetAllPaymentAppsCallback(
gogerald3f1cabf2018-02-08 14:19:1896 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4897 const GURL& top_level_origin,
98 const GURL& frame_origin,
gogerald84ae6262018-02-06 06:21:4699 content::PaymentAppProvider::PaymentApps apps,
Rouslan Solomakhind5dcc322019-07-11 21:47:20100 ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps,
101 const std::string& error_message) {
gogerald3f1cabf2018-02-08 14:19:18102 number_of_pending_sw_payment_instruments_ =
103 apps.size() + installable_apps.size();
Rouslan Solomakhind5dcc322019-07-11 21:47:20104 get_all_payment_apps_error_ = error_message;
gogeraldac15d2362017-11-15 01:04:19105 if (number_of_pending_sw_payment_instruments_ == 0U) {
106 FinishedGetAllSWPaymentInstruments();
107 return;
gogerald8189d522017-09-15 17:52:18108 }
109
gogeraldac15d2362017-11-15 01:04:19110 for (auto& app : apps) {
111 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
112 std::make_unique<ServiceWorkerPaymentInstrument>(
gogerald3f1cabf2018-02-08 14:19:18113 web_contents->GetBrowserContext(), top_level_origin, frame_origin,
Rouslan Solomakhin1f95f092019-08-09 12:28:51114 spec_, std::move(app.second), payment_request_delegate_,
115 sw_identity_observer_);
gogerald3f1cabf2018-02-08 14:19:18116 instrument->ValidateCanMakePayment(
117 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
118 weak_ptr_factory_.GetWeakPtr()));
119 available_instruments_.push_back(std::move(instrument));
120 }
121
122 for (auto& installable_app : installable_apps) {
123 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
124 std::make_unique<ServiceWorkerPaymentInstrument>(
125 web_contents, top_level_origin, frame_origin, spec_,
126 std::move(installable_app.second), installable_app.first.spec(),
Rouslan Solomakhin1f95f092019-08-09 12:28:51127 payment_request_delegate_, sw_identity_observer_);
gogeraldac15d2362017-11-15 01:04:19128 instrument->ValidateCanMakePayment(
129 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
130 weak_ptr_factory_.GetWeakPtr()));
131 available_instruments_.push_back(std::move(instrument));
132 }
133}
134
135void PaymentRequestState::OnSWPaymentInstrumentValidated(
136 ServiceWorkerPaymentInstrument* instrument,
137 bool result) {
138 // Remove service worker payment instruments failed on validation.
139 if (!result) {
140 for (size_t i = 0; i < available_instruments_.size(); i++) {
141 if (available_instruments_[i].get() == instrument) {
142 available_instruments_.erase(available_instruments_.begin() + i);
143 break;
144 }
145 }
146 }
147
148 if (--number_of_pending_sw_payment_instruments_ > 0)
149 return;
150
151 FinishedGetAllSWPaymentInstruments();
152}
153
154void PaymentRequestState::FinishedGetAllSWPaymentInstruments() {
gogerald8189d522017-09-15 17:52:18155 PopulateProfileCache();
156 SetDefaultProfileSelections();
157
158 get_all_instruments_finished_ = true;
Rouslan Solomakhind2cae95a2018-08-09 00:16:10159 are_requested_methods_supported_ |= !available_instruments_.empty();
gogerald8189d522017-09-15 17:52:18160 NotifyOnGetAllPaymentInstrumentsFinished();
Rouslan Solomakhin9788d4b2019-04-09 13:10:23161 NotifyInitialized();
gogerald8189d522017-09-15 17:52:18162
Danyao Wang4bc0606a2018-12-27 16:54:53163 // Fulfill the pending CanMakePayment call.
Danyao Wang57aa0442019-01-31 04:06:41164 if (can_make_payment_callback_) {
165 CheckCanMakePayment(can_make_payment_legacy_mode_,
166 std::move(can_make_payment_callback_));
167 }
Danyao Wang4bc0606a2018-12-27 16:54:53168
Danyao Wangce175bf2018-12-21 22:35:58169 // Fulfill the pending HasEnrolledInstrument call.
170 if (has_enrolled_instrument_callback_)
171 CheckHasEnrolledInstrument(std::move(has_enrolled_instrument_callback_));
gogerald0a7ee6c2017-11-13 18:23:19172
Danyao Wangce175bf2018-12-21 22:35:58173 // Fulfill the pending AreRequestedMethodsSupported call.
gogerald0a7ee6c2017-11-13 18:23:19174 if (are_requested_methods_supported_callback_)
175 CheckRequestedMethodsSupported(
176 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18177}
178
sebsg695799a2017-04-11 16:29:06179void PaymentRequestState::OnPaymentResponseReady(
180 mojom::PaymentResponsePtr payment_response) {
181 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
182}
183
Rouslan Solomakhin68429b72019-06-27 15:12:39184void PaymentRequestState::OnPaymentResponseError(
185 const std::string& error_message) {
186 delegate_->OnPaymentResponseError(error_message);
187}
188
sebsg7e619132017-04-27 16:07:10189void PaymentRequestState::OnSpecUpdated() {
Jinho Bangcac8d9a02018-08-23 19:47:22190 autofill::AutofillProfile* selected_shipping_profile =
191 selected_shipping_profile_;
192 autofill::AutofillProfile* selected_contact_profile =
193 selected_contact_profile_;
194
195 if (spec_->current_update_reason() ==
196 PaymentRequestSpec::UpdateReason::RETRY) {
197 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
198 invalid_shipping_profile_ = selected_shipping_profile;
199 selected_shipping_profile_ = nullptr;
200 }
Jinho Bang092e7162018-09-06 23:41:19201
Jinho Bangcac8d9a02018-08-23 19:47:22202 if (spec_->has_payer_error() && selected_contact_profile) {
203 invalid_contact_profile_ = selected_contact_profile;
204 selected_contact_profile_ = nullptr;
205 }
206 }
207
Mathieu Perreault04b4c662017-06-02 13:35:13208 if (spec_->selected_shipping_option_error().empty()) {
209 selected_shipping_option_error_profile_ = nullptr;
210 } else {
Jinho Bangcac8d9a02018-08-23 19:47:22211 selected_shipping_option_error_profile_ = selected_shipping_profile;
Mathieu Perreault04b4c662017-06-02 13:35:13212 selected_shipping_profile_ = nullptr;
Jinho Bang092e7162018-09-06 23:41:19213 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
214 invalid_shipping_profile_ = selected_shipping_profile;
215 }
Mathieu Perreault04b4c662017-06-02 13:35:13216 }
Jinho Bangcac8d9a02018-08-23 19:47:22217
sebsg7e619132017-04-27 16:07:10218 is_waiting_for_merchant_validation_ = false;
219 UpdateIsReadyToPayAndNotifyObservers();
220}
221
Danyao Wang57aa0442019-01-31 04:06:41222void PaymentRequestState::CanMakePayment(bool legacy_mode,
223 StatusCallback callback) {
Danyao Wang4bc0606a2018-12-27 16:54:53224 if (!get_all_instruments_finished_) {
225 DCHECK(!can_make_payment_callback_);
226 can_make_payment_callback_ = std::move(callback);
Danyao Wang57aa0442019-01-31 04:06:41227 can_make_payment_legacy_mode_ = legacy_mode;
Danyao Wang4bc0606a2018-12-27 16:54:53228 return;
229 }
230
231 base::ThreadTaskRunnerHandle::Get()->PostTask(
Danyao Wang57aa0442019-01-31 04:06:41232 FROM_HERE, base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
233 weak_ptr_factory_.GetWeakPtr(), legacy_mode,
234 std::move(callback)));
Danyao Wangce175bf2018-12-21 22:35:58235}
236
Danyao Wang57aa0442019-01-31 04:06:41237void PaymentRequestState::CheckCanMakePayment(bool legacy_mode,
238 StatusCallback callback) {
Danyao Wang4bc0606a2018-12-27 16:54:53239 DCHECK(get_all_instruments_finished_);
Danyao Wang57aa0442019-01-31 04:06:41240 if (!legacy_mode) {
241 std::move(callback).Run(are_requested_methods_supported_);
242 return;
243 }
244
245 // Legacy mode: fall back to also checking if an instrument is enrolled.
246 bool can_make_payment_value = false;
247 for (const auto& instrument : available_instruments_) {
248 if (instrument->IsValidForCanMakePayment()) {
249 can_make_payment_value = true;
250 break;
251 }
252 }
253 std::move(callback).Run(can_make_payment_value);
Danyao Wangce175bf2018-12-21 22:35:58254}
255
256void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18257 if (!get_all_instruments_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53258 DCHECK(!has_enrolled_instrument_callback_);
Danyao Wangce175bf2018-12-21 22:35:58259 has_enrolled_instrument_callback_ = std::move(callback);
gogerald8189d522017-09-15 17:52:18260 return;
261 }
262
263 base::ThreadTaskRunnerHandle::Get()->PostTask(
264 FROM_HERE,
Danyao Wangce175bf2018-12-21 22:35:58265 base::BindOnce(&PaymentRequestState::CheckHasEnrolledInstrument,
gogerald8189d522017-09-15 17:52:18266 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
267}
268
Danyao Wangce175bf2018-12-21 22:35:58269void PaymentRequestState::CheckHasEnrolledInstrument(StatusCallback callback) {
Danyao Wang486739212019-02-04 17:08:59270 DCHECK(get_all_instruments_finished_);
271 bool has_enrolled_instrument_value = false;
272 for (const auto& instrument : available_instruments_) {
273 if (instrument->IsValidForCanMakePayment()) {
274 has_enrolled_instrument_value = true;
275 break;
276 }
277 }
278 std::move(callback).Run(has_enrolled_instrument_value);
mathp1a5be4f2017-03-24 18:09:19279}
280
gogerald0a7ee6c2017-11-13 18:23:19281void PaymentRequestState::AreRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20282 MethodsSupportedCallback callback) {
gogerald0a7ee6c2017-11-13 18:23:19283 if (!get_all_instruments_finished_) {
284 are_requested_methods_supported_callback_ = std::move(callback);
285 return;
286 }
287
288 base::ThreadTaskRunnerHandle::Get()->PostTask(
289 FROM_HERE,
290 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
291 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
292}
293
294void PaymentRequestState::CheckRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20295 MethodsSupportedCallback callback) {
gogerald0a7ee6c2017-11-13 18:23:19296 DCHECK(get_all_instruments_finished_);
297
Rouslan Solomakhind5dcc322019-07-11 21:47:20298 std::move(callback).Run(are_requested_methods_supported_,
299 get_all_payment_apps_error_);
rouslan6e3cf7c62017-04-17 21:23:28300}
301
anthonyvd6a43b932017-05-11 18:39:27302std::string PaymentRequestState::GetAuthenticatedEmail() const {
303 return payment_request_delegate_->GetAuthenticatedEmail();
304}
305
mathpf1a7a3752017-03-15 11:23:37306void PaymentRequestState::AddObserver(Observer* observer) {
307 CHECK(observer);
308 observers_.AddObserver(observer);
309}
mathpf1a7a3752017-03-15 11:23:37310
311void PaymentRequestState::RemoveObserver(Observer* observer) {
312 observers_.RemoveObserver(observer);
313}
314
mathpf1a7a3752017-03-15 11:23:37315void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05316 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06317
318 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51319 response_helper_ = std::make_unique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15320 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
321 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37322}
323
Rouslan Solomakhin761d65eb2019-04-29 20:08:01324void PaymentRequestState::OnPaymentAppWindowClosed() {
325 DCHECK(selected_instrument_);
326 response_helper_.reset();
327 selected_instrument_->OnPaymentAppWindowClosed();
328}
329
sebsg8a93b272017-05-11 19:30:22330void PaymentRequestState::RecordUseStats() {
331 if (spec_->request_shipping()) {
332 DCHECK(selected_shipping_profile_);
333 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
334 }
335
336 if (spec_->request_payer_name() || spec_->request_payer_email() ||
337 spec_->request_payer_phone()) {
338 DCHECK(selected_contact_profile_);
339
340 // If the same address was used for both contact and shipping, the stats
341 // should only be updated once.
342 if (!spec_->request_shipping() || (selected_shipping_profile_->guid() !=
343 selected_contact_profile_->guid())) {
344 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
345 }
346 }
347
348 selected_instrument_->RecordUse();
349}
350
mathp24ce4cd2017-04-12 20:56:42351void PaymentRequestState::AddAutofillPaymentInstrument(
352 bool selected,
353 const autofill::CreditCard& card) {
354 std::string basic_card_network =
rouslan4e981bd32017-05-01 17:49:16355 autofill::data_util::GetPaymentRequestData(card.network())
356 .basic_card_issuer_network;
Rouslan Solomakhin25d708b2017-06-23 17:12:03357 if (!spec_->supported_card_networks_set().count(basic_card_network) ||
358 !spec_->supported_card_types_set().count(card.card_type())) {
mathp24ce4cd2017-04-12 20:56:42359 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03360 }
361
362 // The total number of card types: credit, debit, prepaid, unknown.
363 constexpr size_t kTotalNumberOfCardTypes = 4U;
364
365 // Whether the card type (credit, debit, prepaid) matches thetype that the
366 // merchant has requested exactly. This should be false for unknown card
367 // types, if the merchant cannot accept some card types.
368 bool matches_merchant_card_type_exactly =
369 card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN ||
370 spec_->supported_card_types_set().size() == kTotalNumberOfCardTypes;
mathp24ce4cd2017-04-12 20:56:42371
372 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
373 // owned by this object.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51374 auto instrument = std::make_unique<AutofillPaymentInstrument>(
Rouslan Solomakhin25d708b2017-06-23 17:12:03375 basic_card_network, card, matches_merchant_card_type_exactly,
376 shipping_profiles_, app_locale_, payment_request_delegate_);
mathp24ce4cd2017-04-12 20:56:42377 available_instruments_.push_back(std::move(instrument));
378
Sahel Sharifybc4173f2019-05-09 21:03:57379 if (selected) {
380 SetSelectedInstrument(available_instruments_.back().get(),
381 SectionSelectionStatus::kAddedSelected);
382 }
mathp24ce4cd2017-04-12 20:56:42383}
384
madf9904ea2017-04-25 18:39:12385void PaymentRequestState::AddAutofillShippingProfile(
386 bool selected,
387 const autofill::AutofillProfile& profile) {
388 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51389 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12390 // TODO(tmartino): Implement deduplication rules specific to shipping
391 // profiles.
392 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
393 shipping_profiles_.push_back(new_cached_profile);
394
Sahel Sharifybc4173f2019-05-09 21:03:57395 if (selected) {
396 SetSelectedShippingProfile(new_cached_profile,
397 SectionSelectionStatus::kAddedSelected);
398 }
madf9904ea2017-04-25 18:39:12399}
400
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23401void PaymentRequestState::AddAutofillContactProfile(
402 bool selected,
403 const autofill::AutofillProfile& profile) {
404 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51405 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23406 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
407 contact_profiles_.push_back(new_cached_profile);
408
Sahel Sharifybc4173f2019-05-09 21:03:57409 if (selected) {
410 SetSelectedContactProfile(new_cached_profile,
411 SectionSelectionStatus::kAddedSelected);
412 }
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23413}
414
anthonyvd0116ce332017-03-21 21:29:01415void PaymentRequestState::SetSelectedShippingOption(
mathp151bd31e2017-04-03 21:07:24416 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50417 spec_->StartWaitingForUpdateWith(
418 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd31e2017-04-03 21:07:24419 // This will inform the merchant and will lead to them calling updateWith with
420 // new PaymentDetails.
421 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01422}
423
mathpf1a7a3752017-03-15 11:23:37424void PaymentRequestState::SetSelectedShippingProfile(
Sahel Sharifybc4173f2019-05-09 21:03:57425 autofill::AutofillProfile* profile,
426 SectionSelectionStatus selection_status) {
anthonyvd2f30baa12017-04-13 22:30:50427 spec_->StartWaitingForUpdateWith(
428 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37429 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10430
Jinho Bangcac8d9a02018-08-23 19:47:22431 // Changing the shipping address clears shipping address validation errors
432 // from retry().
433 invalid_shipping_profile_ = nullptr;
434
sebsg7e619132017-04-27 16:07:10435 // The user should not be able to click on pay until the callback from the
436 // merchant.
437 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10438
439 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f112017-10-23 20:28:39440 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29441 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00442 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
443 weak_ptr_factory_.GetWeakPtr()));
Sahel Sharifybc4173f2019-05-09 21:03:57444 IncrementSelectionStatus(JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
445 selection_status);
mathpf1a7a3752017-03-15 11:23:37446}
447
448void PaymentRequestState::SetSelectedContactProfile(
Sahel Sharifybc4173f2019-05-09 21:03:57449 autofill::AutofillProfile* profile,
450 SectionSelectionStatus selection_status) {
mathpf1a7a3752017-03-15 11:23:37451 selected_contact_profile_ = profile;
Jinho Bangcac8d9a02018-08-23 19:47:22452
453 // Changing the contact information clears contact information validation
454 // errors from retry().
455 invalid_contact_profile_ = nullptr;
456
mathpf1a7a3752017-03-15 11:23:37457 UpdateIsReadyToPayAndNotifyObservers();
Jinho Bangbb178152018-09-13 09:44:43458
459 if (IsPaymentAppInvoked()) {
Jinho Bang21d6be92018-12-18 15:30:31460 delegate_->OnPayerInfoSelected(
461 response_helper_->GeneratePayerDetail(profile));
Jinho Bangbb178152018-09-13 09:44:43462 }
Sahel Sharifybc4173f2019-05-09 21:03:57463 IncrementSelectionStatus(JourneyLogger::Section::SECTION_CONTACT_INFO,
464 selection_status);
mathpf1a7a3752017-03-15 11:23:37465}
466
Sahel Sharifybc4173f2019-05-09 21:03:57467void PaymentRequestState::SetSelectedInstrument(
468 PaymentInstrument* instrument,
469 SectionSelectionStatus selection_status) {
mathp363735b2017-03-16 18:08:05470 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37471 UpdateIsReadyToPayAndNotifyObservers();
Sahel Sharifybc4173f2019-05-09 21:03:57472 IncrementSelectionStatus(JourneyLogger::Section::SECTION_PAYMENT_METHOD,
473 selection_status);
474}
475
476void PaymentRequestState::IncrementSelectionStatus(
477 JourneyLogger::Section section,
478 SectionSelectionStatus selection_status) {
479 switch (selection_status) {
480 case SectionSelectionStatus::kSelected:
481 journey_logger_->IncrementSelectionChanges(section);
482 break;
483 case SectionSelectionStatus::kEditedSelected:
484 journey_logger_->IncrementSelectionEdits(section);
485 break;
486 case SectionSelectionStatus::kAddedSelected:
487 journey_logger_->IncrementSelectionAdds(section);
488 break;
489 default:
490 NOTREACHED();
491 }
mathpf1a7a3752017-03-15 11:23:37492}
493
mathpc0d616a2017-03-15 14:09:33494const std::string& PaymentRequestState::GetApplicationLocale() {
495 return app_locale_;
496}
497
498autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
499 return personal_data_manager_;
500}
501
mad763ed2b2017-04-24 20:28:47502autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
503 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38504}
505
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56506bool PaymentRequestState::IsPaymentAppInvoked() const {
507 return !!response_helper_;
508}
509
Mathieu Perreaulteea046d12017-09-28 15:51:21510autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45511 return payment_request_delegate_->GetAddressNormalizer();
512}
513
Rouslan Solomakhin48fd6e872019-02-22 17:23:10514bool PaymentRequestState::IsInitialized() const {
515 return get_all_instruments_finished_;
516}
517
Rouslan Solomakhin9788d4b2019-04-09 13:10:23518void PaymentRequestState::SelectDefaultShippingAddressAndNotifyObservers() {
519 // Only pre-select an address if the merchant provided at least one selected
520 // shipping option, and the top profile is complete. Assumes that profiles
521 // have already been sorted for completeness and frecency.
522 if (!shipping_profiles().empty() && spec_->selected_shipping_option() &&
523 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
524 selected_shipping_profile_ = shipping_profiles()[0];
525 }
Sahel Sharify6efdfb32019-07-02 16:12:16526 // Record the missing required fields (if any) of the most complete shipping
527 // profile.
528 profile_comparator()->RecordMissingFieldsOfShippingProfile(
529 shipping_profiles().empty() ? nullptr : shipping_profiles()[0]);
Rouslan Solomakhin9788d4b2019-04-09 13:10:23530 UpdateIsReadyToPayAndNotifyObservers();
531}
532
mathpf1a7a3752017-03-15 11:23:37533void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37534 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33535 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37536
tmartinocd131b32017-05-24 19:40:59537 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
538 raw_profiles_for_filtering.reserve(profiles.size());
539
mathpf1a7a3752017-03-15 11:23:37540 // PaymentRequest may outlive the Profiles returned by the Data Manager.
541 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30542 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37543 for (size_t i = 0; i < profiles.size(); i++) {
544 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51545 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59546 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37547 }
548
tmartino01c3eb82017-04-29 15:18:39549 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
550 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59551 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
552 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24553
sebsgc6719b32017-07-05 19:54:47554 // Set the number of suggestions shown for the sections requested by the
555 // merchant.
556 if (spec_->request_payer_name() || spec_->request_payer_phone() ||
557 spec_->request_payer_email()) {
sebsgce700484d2017-07-19 23:25:38558 bool has_complete_contact =
559 contact_profiles_.empty()
560 ? false
561 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47562 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38563 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
564 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47565 }
566 if (spec_->request_shipping()) {
sebsgce700484d2017-07-19 23:25:38567 bool has_complete_shipping =
568 shipping_profiles_.empty()
569 ? false
570 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47571 journey_logger_->SetNumberOfSuggestionsShown(
572 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38573 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47574 }
575
mathpf14c1e32017-05-12 16:37:30576 // Create the list of available instruments. A copy of each card will be made
577 // by their respective AutofillPaymentInstrument.
mathpf1a7a3752017-03-15 11:23:37578 const std::vector<autofill::CreditCard*>& cards =
Amirhossein Simjourd3b7ba4a2018-05-07 15:27:21579 personal_data_manager_->GetCreditCardsToSuggest(
Mathieu Perreault157f3992018-06-29 18:48:06580 /*include_server_cards=*/base::FeatureList::IsEnabled(
581 payments::features::kReturnGooglePayInBasicCard));
mathp24ce4cd2017-04-12 20:56:42582 for (autofill::CreditCard* card : cards)
583 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37584}
585
586void PaymentRequestState::SetDefaultProfileSelections() {
mathpf14c1e32017-05-12 16:37:30587 // Contact profiles were ordered by completeness in addition to frecency;
588 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59589 if (!contact_profiles().empty() &&
590 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37591 selected_contact_profile_ = contact_profiles()[0];
592
Sahel Sharify6efdfb32019-07-02 16:12:16593 // Record the missing required fields (if any) of the most complete contact
594 // profile.
595 profile_comparator()->RecordMissingFieldsOfContactProfile(
596 contact_profiles().empty() ? nullptr : contact_profiles()[0]);
597
Sahel Sharify13331e82019-07-12 01:00:30598 // Sort instruments.
599 PaymentInstrument::SortInstruments(&available_instruments_);
600
601 selected_instrument_ = nullptr;
602 if (!available_instruments_.empty() &&
603 available_instruments_[0]->IsCompleteForPayment() &&
604 available_instruments_[0]->IsExactlyMatchingMerchantRequest()) {
605 selected_instrument_ = available_instruments_[0].get();
606 }
Rouslan Solomakhin9788d4b2019-04-09 13:10:23607
Sahel Sharify6efdfb32019-07-02 16:12:16608 // Record the missing required payment fields when no complete payment
609 // info exists.
Sahel Sharify13331e82019-07-12 01:00:30610 if (available_instruments_.empty()) {
Sahel Sharify6efdfb32019-07-02 16:12:16611 if (spec_->supports_basic_card()) {
612 // All fields are missing when basic-card is requested but no card exits.
613 base::UmaHistogramSparse("PaymentRequest.MissingPaymentFields",
Sahel Sharify13331e82019-07-12 01:00:30614 CREDIT_CARD_EXPIRED | CREDIT_CARD_NO_CARDHOLDER |
615 CREDIT_CARD_NO_NUMBER |
616 CREDIT_CARD_NO_BILLING_ADDRESS);
Sahel Sharify6efdfb32019-07-02 16:12:16617 }
Sahel Sharify13331e82019-07-12 01:00:30618 } else if (available_instruments_[0]->type() ==
619 PaymentInstrument::Type::AUTOFILL) {
620 // Record the missing fields (if any) of the most complete instrument when
621 // it's autofill based. SW based instruments are always complete.
622 static_cast<const AutofillPaymentInstrument*>(
623 available_instruments_[0].get())
Sahel Sharify6efdfb32019-07-02 16:12:16624 ->RecordMissingFieldsForInstrument();
625 }
gogerald8189d522017-09-15 17:52:18626
Sahel Sharify6efdfb32019-07-02 16:12:16627 SelectDefaultShippingAddressAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18628
629 journey_logger_->SetNumberOfSuggestionsShown(
630 JourneyLogger::Section::SECTION_PAYMENT_METHOD,
Sahel Sharify6efdfb32019-07-02 16:12:16631 available_instruments().size(), selected_instrument_);
mathpf1a7a3752017-03-15 11:23:37632}
633
634void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
635 is_ready_to_pay_ =
636 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
637 NotifyOnSelectedInformationChanged();
638}
639
gogerald8189d522017-09-15 17:52:18640void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() {
641 for (auto& observer : observers_)
642 observer.OnGetAllPaymentInstrumentsFinished();
643}
644
mathpf1a7a3752017-03-15 11:23:37645void PaymentRequestState::NotifyOnSelectedInformationChanged() {
646 for (auto& observer : observers_)
647 observer.OnSelectedInformationChanged();
648}
649
650bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05651 // There is no need to check for supported networks, because only supported
652 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29653 return selected_instrument_ != nullptr &&
654 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37655}
656
657bool PaymentRequestState::ArePaymentOptionsSatisfied() {
sebsg7e619132017-04-27 16:07:10658 if (is_waiting_for_merchant_validation_)
659 return false;
660
tmartino01c3eb82017-04-29 15:18:39661 if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_))
662 return false;
663
Anthony Vallee-Duboisa8814672017-06-01 18:43:20664 if (spec_->request_shipping() && !spec_->selected_shipping_option())
665 return false;
666
tmartino01c3eb82017-04-29 15:18:39667 return profile_comparator()->IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37668}
669
Mathieu Perreault17c1ae92017-10-20 17:16:00670void PaymentRequestState::OnAddressNormalized(
671 bool success,
672 const autofill::AutofillProfile& normalized_profile) {
673 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22674 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
675 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00676}
677
mathpf1a7a3752017-03-15 11:23:37678} // namespace payments