mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 1 | // 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 | |
mad | 4527193 | 2017-04-13 16:07:38 | [diff] [blame] | 7 | #include <algorithm> |
anthonyvd | 0116ce33 | 2017-03-21 21:29:01 | [diff] [blame] | 8 | #include <set> |
mad | 4527193 | 2017-04-13 16:07:38 | [diff] [blame] | 9 | #include <utility> |
anthonyvd | 0116ce33 | 2017-03-21 21:29:01 | [diff] [blame] | 10 | |
Sebastien Marchand | 53801a3 | 2019-01-25 16:26:11 | [diff] [blame] | 11 | #include "base/bind.h" |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 12 | #include "base/feature_list.h" |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 13 | #include "base/metrics/histogram_functions.h" |
sebsg | ad86bd00 | 2017-03-29 16:39:12 | [diff] [blame] | 14 | #include "base/strings/utf_string_conversions.h" |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 15 | #include "components/autofill/core/browser/autofill_data_util.h" |
Dominic Battre | aed20f9f | 2019-05-10 19:09:52 | [diff] [blame] | 16 | #include "components/autofill/core/browser/data_model/autofill_profile.h" |
| 17 | #include "components/autofill/core/browser/data_model/credit_card.h" |
Dominic Battre | dd73d26 | 2019-05-15 20:10:38 | [diff] [blame] | 18 | #include "components/autofill/core/browser/geo/autofill_country.h" |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 19 | #include "components/autofill/core/browser/personal_data_manager.h" |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 20 | #include "components/autofill/core/browser/validation.h" |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 21 | #include "components/payments/content/content_payment_request_delegate.h" |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 22 | #include "components/payments/content/payment_manifest_web_data_service.h" |
sebsg | ad86bd00 | 2017-03-29 16:39:12 | [diff] [blame] | 23 | #include "components/payments/content/payment_response_helper.h" |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 24 | #include "components/payments/content/service_worker_payment_instrument.h" |
Sahel Sharify | 13331e8 | 2019-07-12 01:00:30 | [diff] [blame] | 25 | #include "components/payments/core/autofill_card_validation.h" |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 26 | #include "components/payments/core/autofill_payment_instrument.h" |
Mathieu Perreault | 157f399 | 2018-06-29 18:48:06 | [diff] [blame] | 27 | #include "components/payments/core/features.h" |
sebsg | 695799a | 2017-04-11 16:29:06 | [diff] [blame] | 28 | #include "components/payments/core/payment_instrument.h" |
tmartino | 01c3eb8 | 2017-04-29 15:18:39 | [diff] [blame] | 29 | #include "components/payments/core/payment_request_data_util.h" |
Danyao Wang | 761739b | 2019-06-27 23:59:32 | [diff] [blame] | 30 | #include "components/payments/core/payments_experimental_features.h" |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 31 | #include "content/public/common/content_features.h" |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 32 | |
| 33 | namespace payments { |
| 34 | |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 35 | PaymentRequestState::PaymentRequestState( |
Rouslan Solomakhin | dbf593d9 | 2017-11-21 19:20:57 | [diff] [blame] | 36 | content::WebContents* web_contents, |
gogerald | 7a0cc3e | 2017-09-19 03:35:48 | [diff] [blame] | 37 | const GURL& top_level_origin, |
| 38 | const GURL& frame_origin, |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 39 | PaymentRequestSpec* spec, |
| 40 | Delegate* delegate, |
| 41 | const std::string& app_locale, |
anthonyvd | d23ed70 | 2017-04-05 15:29:00 | [diff] [blame] | 42 | autofill::PersonalDataManager* personal_data_manager, |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 43 | ContentPaymentRequestDelegate* payment_request_delegate, |
Rouslan Solomakhin | 1f95f09 | 2019-08-09 12:28:51 | [diff] [blame^] | 44 | ServiceWorkerPaymentInstrument::IdentityObserver* sw_identity_observer, |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 45 | JourneyLogger* journey_logger) |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 46 | : is_ready_to_pay_(false), |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 47 | get_all_instruments_finished_(true), |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 48 | is_waiting_for_merchant_validation_(false), |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 49 | app_locale_(app_locale), |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 50 | spec_(spec), |
| 51 | delegate_(delegate), |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 52 | personal_data_manager_(personal_data_manager), |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 53 | journey_logger_(journey_logger), |
Rouslan Solomakhin | d2cae95a | 2018-08-09 00:16:10 | [diff] [blame] | 54 | are_requested_methods_supported_( |
| 55 | !spec_->supported_card_networks().empty()), |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 56 | selected_shipping_profile_(nullptr), |
Mathieu Perreault | 04b4c66 | 2017-06-02 13:35:13 | [diff] [blame] | 57 | selected_shipping_option_error_profile_(nullptr), |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 58 | selected_contact_profile_(nullptr), |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 59 | invalid_shipping_profile_(nullptr), |
| 60 | invalid_contact_profile_(nullptr), |
anthonyvd | d23ed70 | 2017-04-05 15:29:00 | [diff] [blame] | 61 | selected_instrument_(nullptr), |
gogerald | ac15d236 | 2017-11-15 01:04:19 | [diff] [blame] | 62 | number_of_pending_sw_payment_instruments_(0), |
tmartino | 01c3eb8 | 2017-04-29 15:18:39 | [diff] [blame] | 63 | payment_request_delegate_(payment_request_delegate), |
Rouslan Solomakhin | 1f95f09 | 2019-08-09 12:28:51 | [diff] [blame^] | 64 | sw_identity_observer_(sw_identity_observer), |
Jeremy Roman | 5c341f6d | 2019-07-15 15:56:10 | [diff] [blame] | 65 | profile_comparator_(app_locale, *spec) { |
Rouslan Solomakhin | 1f95f09 | 2019-08-09 12:28:51 | [diff] [blame^] | 66 | DCHECK(sw_identity_observer_); |
Mathieu Perreault | 157f399 | 2018-06-29 18:48:06 | [diff] [blame] | 67 | if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) { |
gogerald | 12a4e4ff | 2018-08-08 12:16:25 | [diff] [blame] | 68 | DCHECK(web_contents); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 69 | get_all_instruments_finished_ = false; |
Danyao Wang | 761739b | 2019-06-27 23:59:32 | [diff] [blame] | 70 | bool may_crawl_for_installable_payment_apps = |
| 71 | PaymentsExperimentalFeatures::IsEnabled( |
| 72 | features::kAlwaysAllowJustInTimePaymentApp) || |
| 73 | !spec_->supports_basic_card(); |
| 74 | |
gogerald | 97e1b331 | 2017-11-21 23:31:10 | [diff] [blame] | 75 | ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps( |
Rouslan Solomakhin | dbf593d9 | 2017-11-21 19:20:57 | [diff] [blame] | 76 | web_contents, |
Rouslan Solomakhin | 438d8c9 | 2017-10-26 21:33:18 | [diff] [blame] | 77 | payment_request_delegate_->GetPaymentManifestWebDataService(), |
Danyao Wang | 761739b | 2019-06-27 23:59:32 | [diff] [blame] | 78 | spec_->method_data(), may_crawl_for_installable_payment_apps, |
Rouslan Solomakhin | 438d8c9 | 2017-10-26 21:33:18 | [diff] [blame] | 79 | base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback, |
gogerald | 3f1cabf | 2018-02-08 14:19:18 | [diff] [blame] | 80 | weak_ptr_factory_.GetWeakPtr(), web_contents, |
| 81 | top_level_origin, frame_origin), |
gogerald | 97e1b331 | 2017-11-21 23:31:10 | [diff] [blame] | 82 | base::BindOnce([]() { |
| 83 | /* Nothing needs to be done after writing cache. This callback is used |
| 84 | * only in tests. */ |
| 85 | })); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 86 | } else { |
| 87 | PopulateProfileCache(); |
| 88 | SetDefaultProfileSelections(); |
| 89 | } |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 90 | spec_->AddObserver(this); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 91 | } |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 92 | |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 93 | PaymentRequestState::~PaymentRequestState() {} |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 94 | |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 95 | void PaymentRequestState::GetAllPaymentAppsCallback( |
gogerald | 3f1cabf | 2018-02-08 14:19:18 | [diff] [blame] | 96 | content::WebContents* web_contents, |
gogerald | 7a0cc3e | 2017-09-19 03:35:48 | [diff] [blame] | 97 | const GURL& top_level_origin, |
| 98 | const GURL& frame_origin, |
gogerald | 84ae626 | 2018-02-06 06:21:46 | [diff] [blame] | 99 | content::PaymentAppProvider::PaymentApps apps, |
Rouslan Solomakhin | d5dcc32 | 2019-07-11 21:47:20 | [diff] [blame] | 100 | ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps, |
| 101 | const std::string& error_message) { |
gogerald | 3f1cabf | 2018-02-08 14:19:18 | [diff] [blame] | 102 | number_of_pending_sw_payment_instruments_ = |
| 103 | apps.size() + installable_apps.size(); |
Rouslan Solomakhin | d5dcc32 | 2019-07-11 21:47:20 | [diff] [blame] | 104 | get_all_payment_apps_error_ = error_message; |
gogerald | ac15d236 | 2017-11-15 01:04:19 | [diff] [blame] | 105 | if (number_of_pending_sw_payment_instruments_ == 0U) { |
| 106 | FinishedGetAllSWPaymentInstruments(); |
| 107 | return; |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 108 | } |
| 109 | |
gogerald | ac15d236 | 2017-11-15 01:04:19 | [diff] [blame] | 110 | for (auto& app : apps) { |
| 111 | std::unique_ptr<ServiceWorkerPaymentInstrument> instrument = |
| 112 | std::make_unique<ServiceWorkerPaymentInstrument>( |
gogerald | 3f1cabf | 2018-02-08 14:19:18 | [diff] [blame] | 113 | web_contents->GetBrowserContext(), top_level_origin, frame_origin, |
Rouslan Solomakhin | 1f95f09 | 2019-08-09 12:28:51 | [diff] [blame^] | 114 | spec_, std::move(app.second), payment_request_delegate_, |
| 115 | sw_identity_observer_); |
gogerald | 3f1cabf | 2018-02-08 14:19:18 | [diff] [blame] | 116 | 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 Solomakhin | 1f95f09 | 2019-08-09 12:28:51 | [diff] [blame^] | 127 | payment_request_delegate_, sw_identity_observer_); |
gogerald | ac15d236 | 2017-11-15 01:04:19 | [diff] [blame] | 128 | instrument->ValidateCanMakePayment( |
| 129 | base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated, |
| 130 | weak_ptr_factory_.GetWeakPtr())); |
| 131 | available_instruments_.push_back(std::move(instrument)); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | void 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 | |
| 154 | void PaymentRequestState::FinishedGetAllSWPaymentInstruments() { |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 155 | PopulateProfileCache(); |
| 156 | SetDefaultProfileSelections(); |
| 157 | |
| 158 | get_all_instruments_finished_ = true; |
Rouslan Solomakhin | d2cae95a | 2018-08-09 00:16:10 | [diff] [blame] | 159 | are_requested_methods_supported_ |= !available_instruments_.empty(); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 160 | NotifyOnGetAllPaymentInstrumentsFinished(); |
Rouslan Solomakhin | 9788d4b | 2019-04-09 13:10:23 | [diff] [blame] | 161 | NotifyInitialized(); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 162 | |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 163 | // Fulfill the pending CanMakePayment call. |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 164 | if (can_make_payment_callback_) { |
| 165 | CheckCanMakePayment(can_make_payment_legacy_mode_, |
| 166 | std::move(can_make_payment_callback_)); |
| 167 | } |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 168 | |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 169 | // Fulfill the pending HasEnrolledInstrument call. |
| 170 | if (has_enrolled_instrument_callback_) |
| 171 | CheckHasEnrolledInstrument(std::move(has_enrolled_instrument_callback_)); |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 172 | |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 173 | // Fulfill the pending AreRequestedMethodsSupported call. |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 174 | if (are_requested_methods_supported_callback_) |
| 175 | CheckRequestedMethodsSupported( |
| 176 | std::move(are_requested_methods_supported_callback_)); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 177 | } |
| 178 | |
sebsg | 695799a | 2017-04-11 16:29:06 | [diff] [blame] | 179 | void PaymentRequestState::OnPaymentResponseReady( |
| 180 | mojom::PaymentResponsePtr payment_response) { |
| 181 | delegate_->OnPaymentResponseAvailable(std::move(payment_response)); |
| 182 | } |
| 183 | |
Rouslan Solomakhin | 68429b7 | 2019-06-27 15:12:39 | [diff] [blame] | 184 | void PaymentRequestState::OnPaymentResponseError( |
| 185 | const std::string& error_message) { |
| 186 | delegate_->OnPaymentResponseError(error_message); |
| 187 | } |
| 188 | |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 189 | void PaymentRequestState::OnSpecUpdated() { |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 190 | 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 Bang | 092e716 | 2018-09-06 23:41:19 | [diff] [blame] | 201 | |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 202 | if (spec_->has_payer_error() && selected_contact_profile) { |
| 203 | invalid_contact_profile_ = selected_contact_profile; |
| 204 | selected_contact_profile_ = nullptr; |
| 205 | } |
| 206 | } |
| 207 | |
Mathieu Perreault | 04b4c66 | 2017-06-02 13:35:13 | [diff] [blame] | 208 | if (spec_->selected_shipping_option_error().empty()) { |
| 209 | selected_shipping_option_error_profile_ = nullptr; |
| 210 | } else { |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 211 | selected_shipping_option_error_profile_ = selected_shipping_profile; |
Mathieu Perreault | 04b4c66 | 2017-06-02 13:35:13 | [diff] [blame] | 212 | selected_shipping_profile_ = nullptr; |
Jinho Bang | 092e716 | 2018-09-06 23:41:19 | [diff] [blame] | 213 | if (spec_->has_shipping_address_error() && selected_shipping_profile) { |
| 214 | invalid_shipping_profile_ = selected_shipping_profile; |
| 215 | } |
Mathieu Perreault | 04b4c66 | 2017-06-02 13:35:13 | [diff] [blame] | 216 | } |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 217 | |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 218 | is_waiting_for_merchant_validation_ = false; |
| 219 | UpdateIsReadyToPayAndNotifyObservers(); |
| 220 | } |
| 221 | |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 222 | void PaymentRequestState::CanMakePayment(bool legacy_mode, |
| 223 | StatusCallback callback) { |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 224 | if (!get_all_instruments_finished_) { |
| 225 | DCHECK(!can_make_payment_callback_); |
| 226 | can_make_payment_callback_ = std::move(callback); |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 227 | can_make_payment_legacy_mode_ = legacy_mode; |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 228 | return; |
| 229 | } |
| 230 | |
| 231 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 232 | FROM_HERE, base::BindOnce(&PaymentRequestState::CheckCanMakePayment, |
| 233 | weak_ptr_factory_.GetWeakPtr(), legacy_mode, |
| 234 | std::move(callback))); |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 235 | } |
| 236 | |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 237 | void PaymentRequestState::CheckCanMakePayment(bool legacy_mode, |
| 238 | StatusCallback callback) { |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 239 | DCHECK(get_all_instruments_finished_); |
Danyao Wang | 57aa044 | 2019-01-31 04:06:41 | [diff] [blame] | 240 | 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 Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 254 | } |
| 255 | |
| 256 | void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) { |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 257 | if (!get_all_instruments_finished_) { |
Danyao Wang | 4bc0606a | 2018-12-27 16:54:53 | [diff] [blame] | 258 | DCHECK(!has_enrolled_instrument_callback_); |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 259 | has_enrolled_instrument_callback_ = std::move(callback); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 260 | return; |
| 261 | } |
| 262 | |
| 263 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 264 | FROM_HERE, |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 265 | base::BindOnce(&PaymentRequestState::CheckHasEnrolledInstrument, |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 266 | weak_ptr_factory_.GetWeakPtr(), std::move(callback))); |
| 267 | } |
| 268 | |
Danyao Wang | ce175bf | 2018-12-21 22:35:58 | [diff] [blame] | 269 | void PaymentRequestState::CheckHasEnrolledInstrument(StatusCallback callback) { |
Danyao Wang | 48673921 | 2019-02-04 17:08:59 | [diff] [blame] | 270 | 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); |
mathp | 1a5be4f | 2017-03-24 18:09:19 | [diff] [blame] | 279 | } |
| 280 | |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 281 | void PaymentRequestState::AreRequestedMethodsSupported( |
Rouslan Solomakhin | d5dcc32 | 2019-07-11 21:47:20 | [diff] [blame] | 282 | MethodsSupportedCallback callback) { |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 283 | 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 | |
| 294 | void PaymentRequestState::CheckRequestedMethodsSupported( |
Rouslan Solomakhin | d5dcc32 | 2019-07-11 21:47:20 | [diff] [blame] | 295 | MethodsSupportedCallback callback) { |
gogerald | 0a7ee6c | 2017-11-13 18:23:19 | [diff] [blame] | 296 | DCHECK(get_all_instruments_finished_); |
| 297 | |
Rouslan Solomakhin | d5dcc32 | 2019-07-11 21:47:20 | [diff] [blame] | 298 | std::move(callback).Run(are_requested_methods_supported_, |
| 299 | get_all_payment_apps_error_); |
rouslan | 6e3cf7c6 | 2017-04-17 21:23:28 | [diff] [blame] | 300 | } |
| 301 | |
anthonyvd | 6a43b93 | 2017-05-11 18:39:27 | [diff] [blame] | 302 | std::string PaymentRequestState::GetAuthenticatedEmail() const { |
| 303 | return payment_request_delegate_->GetAuthenticatedEmail(); |
| 304 | } |
| 305 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 306 | void PaymentRequestState::AddObserver(Observer* observer) { |
| 307 | CHECK(observer); |
| 308 | observers_.AddObserver(observer); |
| 309 | } |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 310 | |
| 311 | void PaymentRequestState::RemoveObserver(Observer* observer) { |
| 312 | observers_.RemoveObserver(observer); |
| 313 | } |
| 314 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 315 | void PaymentRequestState::GeneratePaymentResponse() { |
mathp | 363735b | 2017-03-16 18:08:05 | [diff] [blame] | 316 | DCHECK(is_ready_to_pay()); |
sebsg | 695799a | 2017-04-11 16:29:06 | [diff] [blame] | 317 | |
| 318 | // Once the response is ready, will call back into OnPaymentResponseReady. |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 319 | response_helper_ = std::make_unique<PaymentResponseHelper>( |
sebsg | 8a9c234 | 2017-04-21 17:05:15 | [diff] [blame] | 320 | app_locale_, spec_, selected_instrument_, payment_request_delegate_, |
| 321 | selected_shipping_profile_, selected_contact_profile_, this); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 322 | } |
| 323 | |
Rouslan Solomakhin | 761d65eb | 2019-04-29 20:08:01 | [diff] [blame] | 324 | void PaymentRequestState::OnPaymentAppWindowClosed() { |
| 325 | DCHECK(selected_instrument_); |
| 326 | response_helper_.reset(); |
| 327 | selected_instrument_->OnPaymentAppWindowClosed(); |
| 328 | } |
| 329 | |
sebsg | 8a93b27 | 2017-05-11 19:30:22 | [diff] [blame] | 330 | void 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 | |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 351 | void PaymentRequestState::AddAutofillPaymentInstrument( |
| 352 | bool selected, |
| 353 | const autofill::CreditCard& card) { |
| 354 | std::string basic_card_network = |
rouslan | 4e981bd3 | 2017-05-01 17:49:16 | [diff] [blame] | 355 | autofill::data_util::GetPaymentRequestData(card.network()) |
| 356 | .basic_card_issuer_network; |
Rouslan Solomakhin | 25d708b | 2017-06-23 17:12:03 | [diff] [blame] | 357 | if (!spec_->supported_card_networks_set().count(basic_card_network) || |
| 358 | !spec_->supported_card_types_set().count(card.card_type())) { |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 359 | return; |
Rouslan Solomakhin | 25d708b | 2017-06-23 17:12:03 | [diff] [blame] | 360 | } |
| 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; |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 371 | |
| 372 | // AutofillPaymentInstrument makes a copy of |card| so it is effectively |
| 373 | // owned by this object. |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 374 | auto instrument = std::make_unique<AutofillPaymentInstrument>( |
Rouslan Solomakhin | 25d708b | 2017-06-23 17:12:03 | [diff] [blame] | 375 | basic_card_network, card, matches_merchant_card_type_exactly, |
| 376 | shipping_profiles_, app_locale_, payment_request_delegate_); |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 377 | available_instruments_.push_back(std::move(instrument)); |
| 378 | |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 379 | if (selected) { |
| 380 | SetSelectedInstrument(available_instruments_.back().get(), |
| 381 | SectionSelectionStatus::kAddedSelected); |
| 382 | } |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 383 | } |
| 384 | |
mad | f9904ea | 2017-04-25 18:39:12 | [diff] [blame] | 385 | void PaymentRequestState::AddAutofillShippingProfile( |
| 386 | bool selected, |
| 387 | const autofill::AutofillProfile& profile) { |
| 388 | profile_cache_.push_back( |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 389 | std::make_unique<autofill::AutofillProfile>(profile)); |
mad | f9904ea | 2017-04-25 18:39:12 | [diff] [blame] | 390 | // 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 Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 395 | if (selected) { |
| 396 | SetSelectedShippingProfile(new_cached_profile, |
| 397 | SectionSelectionStatus::kAddedSelected); |
| 398 | } |
mad | f9904ea | 2017-04-25 18:39:12 | [diff] [blame] | 399 | } |
| 400 | |
Anthony Vallee-Dubois | f1e88b4 | 2017-05-15 15:09:23 | [diff] [blame] | 401 | void PaymentRequestState::AddAutofillContactProfile( |
| 402 | bool selected, |
| 403 | const autofill::AutofillProfile& profile) { |
| 404 | profile_cache_.push_back( |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 405 | std::make_unique<autofill::AutofillProfile>(profile)); |
Anthony Vallee-Dubois | f1e88b4 | 2017-05-15 15:09:23 | [diff] [blame] | 406 | autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get(); |
| 407 | contact_profiles_.push_back(new_cached_profile); |
| 408 | |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 409 | if (selected) { |
| 410 | SetSelectedContactProfile(new_cached_profile, |
| 411 | SectionSelectionStatus::kAddedSelected); |
| 412 | } |
Anthony Vallee-Dubois | f1e88b4 | 2017-05-15 15:09:23 | [diff] [blame] | 413 | } |
| 414 | |
anthonyvd | 0116ce33 | 2017-03-21 21:29:01 | [diff] [blame] | 415 | void PaymentRequestState::SetSelectedShippingOption( |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 416 | const std::string& shipping_option_id) { |
anthonyvd | 2f30baa1 | 2017-04-13 22:30:50 | [diff] [blame] | 417 | spec_->StartWaitingForUpdateWith( |
| 418 | PaymentRequestSpec::UpdateReason::SHIPPING_OPTION); |
mathp | 151bd31e | 2017-04-03 21:07:24 | [diff] [blame] | 419 | // This will inform the merchant and will lead to them calling updateWith with |
| 420 | // new PaymentDetails. |
| 421 | delegate_->OnShippingOptionIdSelected(shipping_option_id); |
anthonyvd | 0116ce33 | 2017-03-21 21:29:01 | [diff] [blame] | 422 | } |
| 423 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 424 | void PaymentRequestState::SetSelectedShippingProfile( |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 425 | autofill::AutofillProfile* profile, |
| 426 | SectionSelectionStatus selection_status) { |
anthonyvd | 2f30baa1 | 2017-04-13 22:30:50 | [diff] [blame] | 427 | spec_->StartWaitingForUpdateWith( |
| 428 | PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 429 | selected_shipping_profile_ = profile; |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 430 | |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 431 | // Changing the shipping address clears shipping address validation errors |
| 432 | // from retry(). |
| 433 | invalid_shipping_profile_ = nullptr; |
| 434 | |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 435 | // The user should not be able to click on pay until the callback from the |
| 436 | // merchant. |
| 437 | is_waiting_for_merchant_validation_ = true; |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 438 | |
| 439 | // Start the normalization of the shipping address. |
Mathieu Perreault | c94700f11 | 2017-10-23 20:28:39 | [diff] [blame] | 440 | payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync( |
Mathieu Perreault | 9b40d510 | 2017-11-21 20:51:29 | [diff] [blame] | 441 | *selected_shipping_profile_, /*timeout_seconds=*/2, |
Mathieu Perreault | 17c1ae9 | 2017-10-20 17:16:00 | [diff] [blame] | 442 | base::BindOnce(&PaymentRequestState::OnAddressNormalized, |
| 443 | weak_ptr_factory_.GetWeakPtr())); |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 444 | IncrementSelectionStatus(JourneyLogger::Section::SECTION_SHIPPING_ADDRESS, |
| 445 | selection_status); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 446 | } |
| 447 | |
| 448 | void PaymentRequestState::SetSelectedContactProfile( |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 449 | autofill::AutofillProfile* profile, |
| 450 | SectionSelectionStatus selection_status) { |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 451 | selected_contact_profile_ = profile; |
Jinho Bang | cac8d9a0 | 2018-08-23 19:47:22 | [diff] [blame] | 452 | |
| 453 | // Changing the contact information clears contact information validation |
| 454 | // errors from retry(). |
| 455 | invalid_contact_profile_ = nullptr; |
| 456 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 457 | UpdateIsReadyToPayAndNotifyObservers(); |
Jinho Bang | bb17815 | 2018-09-13 09:44:43 | [diff] [blame] | 458 | |
| 459 | if (IsPaymentAppInvoked()) { |
Jinho Bang | 21d6be9 | 2018-12-18 15:30:31 | [diff] [blame] | 460 | delegate_->OnPayerInfoSelected( |
| 461 | response_helper_->GeneratePayerDetail(profile)); |
Jinho Bang | bb17815 | 2018-09-13 09:44:43 | [diff] [blame] | 462 | } |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 463 | IncrementSelectionStatus(JourneyLogger::Section::SECTION_CONTACT_INFO, |
| 464 | selection_status); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 465 | } |
| 466 | |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 467 | void PaymentRequestState::SetSelectedInstrument( |
| 468 | PaymentInstrument* instrument, |
| 469 | SectionSelectionStatus selection_status) { |
mathp | 363735b | 2017-03-16 18:08:05 | [diff] [blame] | 470 | selected_instrument_ = instrument; |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 471 | UpdateIsReadyToPayAndNotifyObservers(); |
Sahel Sharify | bc4173f | 2019-05-09 21:03:57 | [diff] [blame] | 472 | IncrementSelectionStatus(JourneyLogger::Section::SECTION_PAYMENT_METHOD, |
| 473 | selection_status); |
| 474 | } |
| 475 | |
| 476 | void 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 | } |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 492 | } |
| 493 | |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 494 | const std::string& PaymentRequestState::GetApplicationLocale() { |
| 495 | return app_locale_; |
| 496 | } |
| 497 | |
| 498 | autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() { |
| 499 | return personal_data_manager_; |
| 500 | } |
| 501 | |
mad | 763ed2b | 2017-04-24 20:28:47 | [diff] [blame] | 502 | autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() { |
| 503 | return payment_request_delegate_->GetRegionDataLoader(); |
mad | 4527193 | 2017-04-13 16:07:38 | [diff] [blame] | 504 | } |
| 505 | |
Anthony Vallee-Dubois | 6813c144 | 2017-05-17 19:32:56 | [diff] [blame] | 506 | bool PaymentRequestState::IsPaymentAppInvoked() const { |
| 507 | return !!response_helper_; |
| 508 | } |
| 509 | |
Mathieu Perreault | eea046d1 | 2017-09-28 15:51:21 | [diff] [blame] | 510 | autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() { |
Anthony Vallee-Dubois | 71bf34946 | 2017-07-20 23:56:45 | [diff] [blame] | 511 | return payment_request_delegate_->GetAddressNormalizer(); |
| 512 | } |
| 513 | |
Rouslan Solomakhin | 48fd6e87 | 2019-02-22 17:23:10 | [diff] [blame] | 514 | bool PaymentRequestState::IsInitialized() const { |
| 515 | return get_all_instruments_finished_; |
| 516 | } |
| 517 | |
Rouslan Solomakhin | 9788d4b | 2019-04-09 13:10:23 | [diff] [blame] | 518 | void 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 Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 526 | // 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 Solomakhin | 9788d4b | 2019-04-09 13:10:23 | [diff] [blame] | 530 | UpdateIsReadyToPayAndNotifyObservers(); |
| 531 | } |
| 532 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 533 | void PaymentRequestState::PopulateProfileCache() { |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 534 | std::vector<autofill::AutofillProfile*> profiles = |
mathp | c0d616a | 2017-03-15 14:09:33 | [diff] [blame] | 535 | personal_data_manager_->GetProfilesToSuggest(); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 536 | |
tmartino | cd131b3 | 2017-05-24 19:40:59 | [diff] [blame] | 537 | std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering; |
| 538 | raw_profiles_for_filtering.reserve(profiles.size()); |
| 539 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 540 | // PaymentRequest may outlive the Profiles returned by the Data Manager. |
| 541 | // Thus, we store copies, and return a vector of pointers to these copies |
mathp | f14c1e3 | 2017-05-12 16:37:30 | [diff] [blame] | 542 | // whenever Profiles are requested. |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 543 | for (size_t i = 0; i < profiles.size(); i++) { |
| 544 | profile_cache_.push_back( |
Rouslan Solomakhin | 4eea9bc2 | 2017-10-10 15:18:51 | [diff] [blame] | 545 | std::make_unique<autofill::AutofillProfile>(*profiles[i])); |
tmartino | cd131b3 | 2017-05-24 19:40:59 | [diff] [blame] | 546 | raw_profiles_for_filtering.push_back(profile_cache_.back().get()); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 547 | } |
| 548 | |
tmartino | 01c3eb8 | 2017-04-29 15:18:39 | [diff] [blame] | 549 | contact_profiles_ = profile_comparator()->FilterProfilesForContact( |
| 550 | raw_profiles_for_filtering); |
tmartino | cd131b3 | 2017-05-24 19:40:59 | [diff] [blame] | 551 | shipping_profiles_ = profile_comparator()->FilterProfilesForShipping( |
| 552 | raw_profiles_for_filtering); |
tmartino | a6eb22f | 2017-04-06 20:16:24 | [diff] [blame] | 553 | |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 554 | // 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()) { |
sebsg | ce700484d | 2017-07-19 23:25:38 | [diff] [blame] | 558 | bool has_complete_contact = |
| 559 | contact_profiles_.empty() |
| 560 | ? false |
| 561 | : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]); |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 562 | journey_logger_->SetNumberOfSuggestionsShown( |
sebsg | ce700484d | 2017-07-19 23:25:38 | [diff] [blame] | 563 | JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(), |
| 564 | has_complete_contact); |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 565 | } |
| 566 | if (spec_->request_shipping()) { |
sebsg | ce700484d | 2017-07-19 23:25:38 | [diff] [blame] | 567 | bool has_complete_shipping = |
| 568 | shipping_profiles_.empty() |
| 569 | ? false |
| 570 | : profile_comparator()->IsShippingComplete(shipping_profiles_[0]); |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 571 | journey_logger_->SetNumberOfSuggestionsShown( |
| 572 | JourneyLogger::Section::SECTION_SHIPPING_ADDRESS, |
sebsg | ce700484d | 2017-07-19 23:25:38 | [diff] [blame] | 573 | shipping_profiles_.size(), has_complete_shipping); |
sebsg | c6719b3 | 2017-07-05 19:54:47 | [diff] [blame] | 574 | } |
| 575 | |
mathp | f14c1e3 | 2017-05-12 16:37:30 | [diff] [blame] | 576 | // Create the list of available instruments. A copy of each card will be made |
| 577 | // by their respective AutofillPaymentInstrument. |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 578 | const std::vector<autofill::CreditCard*>& cards = |
Amirhossein Simjour | d3b7ba4a | 2018-05-07 15:27:21 | [diff] [blame] | 579 | personal_data_manager_->GetCreditCardsToSuggest( |
Mathieu Perreault | 157f399 | 2018-06-29 18:48:06 | [diff] [blame] | 580 | /*include_server_cards=*/base::FeatureList::IsEnabled( |
| 581 | payments::features::kReturnGooglePayInBasicCard)); |
mathp | 24ce4cd | 2017-04-12 20:56:42 | [diff] [blame] | 582 | for (autofill::CreditCard* card : cards) |
| 583 | AddAutofillPaymentInstrument(/*selected=*/false, *card); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 584 | } |
| 585 | |
| 586 | void PaymentRequestState::SetDefaultProfileSelections() { |
mathp | f14c1e3 | 2017-05-12 16:37:30 | [diff] [blame] | 587 | // Contact profiles were ordered by completeness in addition to frecency; |
| 588 | // the first one is the best default selection. |
tmartino | cd131b3 | 2017-05-24 19:40:59 | [diff] [blame] | 589 | if (!contact_profiles().empty() && |
| 590 | profile_comparator()->IsContactInfoComplete(contact_profiles_[0])) |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 591 | selected_contact_profile_ = contact_profiles()[0]; |
| 592 | |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 593 | // 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 Sharify | 13331e8 | 2019-07-12 01:00:30 | [diff] [blame] | 598 | // 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 Solomakhin | 9788d4b | 2019-04-09 13:10:23 | [diff] [blame] | 607 | |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 608 | // Record the missing required payment fields when no complete payment |
| 609 | // info exists. |
Sahel Sharify | 13331e8 | 2019-07-12 01:00:30 | [diff] [blame] | 610 | if (available_instruments_.empty()) { |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 611 | 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 Sharify | 13331e8 | 2019-07-12 01:00:30 | [diff] [blame] | 614 | CREDIT_CARD_EXPIRED | CREDIT_CARD_NO_CARDHOLDER | |
| 615 | CREDIT_CARD_NO_NUMBER | |
| 616 | CREDIT_CARD_NO_BILLING_ADDRESS); |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 617 | } |
Sahel Sharify | 13331e8 | 2019-07-12 01:00:30 | [diff] [blame] | 618 | } 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 Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 624 | ->RecordMissingFieldsForInstrument(); |
| 625 | } |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 626 | |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 627 | SelectDefaultShippingAddressAndNotifyObservers(); |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 628 | |
| 629 | journey_logger_->SetNumberOfSuggestionsShown( |
| 630 | JourneyLogger::Section::SECTION_PAYMENT_METHOD, |
Sahel Sharify | 6efdfb3 | 2019-07-02 16:12:16 | [diff] [blame] | 631 | available_instruments().size(), selected_instrument_); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 632 | } |
| 633 | |
| 634 | void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() { |
| 635 | is_ready_to_pay_ = |
| 636 | ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied(); |
| 637 | NotifyOnSelectedInformationChanged(); |
| 638 | } |
| 639 | |
gogerald | 8189d52 | 2017-09-15 17:52:18 | [diff] [blame] | 640 | void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() { |
| 641 | for (auto& observer : observers_) |
| 642 | observer.OnGetAllPaymentInstrumentsFinished(); |
| 643 | } |
| 644 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 645 | void PaymentRequestState::NotifyOnSelectedInformationChanged() { |
| 646 | for (auto& observer : observers_) |
| 647 | observer.OnSelectedInformationChanged(); |
| 648 | } |
| 649 | |
| 650 | bool PaymentRequestState::ArePaymentDetailsSatisfied() { |
mathp | 363735b | 2017-03-16 18:08:05 | [diff] [blame] | 651 | // There is no need to check for supported networks, because only supported |
| 652 | // instruments are listed/created in the flow. |
mathp | 4baea33 | 2017-04-10 21:42:29 | [diff] [blame] | 653 | return selected_instrument_ != nullptr && |
| 654 | selected_instrument_->IsCompleteForPayment(); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | bool PaymentRequestState::ArePaymentOptionsSatisfied() { |
sebsg | 7e61913 | 2017-04-27 16:07:10 | [diff] [blame] | 658 | if (is_waiting_for_merchant_validation_) |
| 659 | return false; |
| 660 | |
tmartino | 01c3eb8 | 2017-04-29 15:18:39 | [diff] [blame] | 661 | if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_)) |
| 662 | return false; |
| 663 | |
Anthony Vallee-Dubois | a881467 | 2017-06-01 18:43:20 | [diff] [blame] | 664 | if (spec_->request_shipping() && !spec_->selected_shipping_option()) |
| 665 | return false; |
| 666 | |
tmartino | 01c3eb8 | 2017-04-29 15:18:39 | [diff] [blame] | 667 | return profile_comparator()->IsContactInfoComplete(selected_contact_profile_); |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 668 | } |
| 669 | |
Mathieu Perreault | 17c1ae9 | 2017-10-20 17:16:00 | [diff] [blame] | 670 | void PaymentRequestState::OnAddressNormalized( |
| 671 | bool success, |
| 672 | const autofill::AutofillProfile& normalized_profile) { |
| 673 | delegate_->OnShippingAddressSelected( |
Tommy Martino | 21d415f | 2018-01-12 20:08:22 | [diff] [blame] | 674 | data_util::GetPaymentAddressFromAutofillProfile(normalized_profile, |
| 675 | app_locale_)); |
Mathieu Perreault | 17c1ae9 | 2017-10-20 17:16:00 | [diff] [blame] | 676 | } |
| 677 | |
mathp | f1a7a375 | 2017-03-15 11:23:37 | [diff] [blame] | 678 | } // namespace payments |