blob: 0f5d84acf8724849a3170485bdfb4c7e94b2f5d4 [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"
sebsgad86bd002017-03-29 16:39:1213#include "base/strings/utf_string_conversions.h"
sebsg7e619132017-04-27 16:07:1014#include "components/autofill/core/browser/autofill_country.h"
mathpf1a7a3752017-03-15 11:23:3715#include "components/autofill/core/browser/autofill_data_util.h"
16#include "components/autofill/core/browser/autofill_profile.h"
17#include "components/autofill/core/browser/credit_card.h"
mathpc0d616a2017-03-15 14:09:3318#include "components/autofill/core/browser/personal_data_manager.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5119#include "components/payments/content/content_payment_request_delegate.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5120#include "components/payments/content/payment_manifest_web_data_service.h"
sebsgad86bd002017-03-29 16:39:1221#include "components/payments/content/payment_response_helper.h"
gogerald8189d522017-09-15 17:52:1822#include "components/payments/content/service_worker_payment_instrument.h"
mathpf1a7a3752017-03-15 11:23:3723#include "components/payments/core/autofill_payment_instrument.h"
Mathieu Perreault157f3992018-06-29 18:48:0624#include "components/payments/core/features.h"
sebsg695799a2017-04-11 16:29:0625#include "components/payments/core/payment_instrument.h"
tmartino01c3eb82017-04-29 15:18:3926#include "components/payments/core/payment_request_data_util.h"
gogerald8189d522017-09-15 17:52:1827#include "content/public/common/content_features.h"
mathpf1a7a3752017-03-15 11:23:3728
29namespace payments {
30
mathpc0d616a2017-03-15 14:09:3331PaymentRequestState::PaymentRequestState(
Rouslan Solomakhindbf593d92017-11-21 19:20:5732 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4833 const GURL& top_level_origin,
34 const GURL& frame_origin,
mathpc0d616a2017-03-15 14:09:3335 PaymentRequestSpec* spec,
36 Delegate* delegate,
37 const std::string& app_locale,
anthonyvdd23ed702017-04-05 15:29:0038 autofill::PersonalDataManager* personal_data_manager,
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5139 ContentPaymentRequestDelegate* payment_request_delegate,
sebsgc6719b32017-07-05 19:54:4740 JourneyLogger* journey_logger)
mathpf1a7a3752017-03-15 11:23:3741 : is_ready_to_pay_(false),
gogerald8189d522017-09-15 17:52:1842 get_all_instruments_finished_(true),
sebsg7e619132017-04-27 16:07:1043 is_waiting_for_merchant_validation_(false),
mathpc0d616a2017-03-15 14:09:3344 app_locale_(app_locale),
mathpf1a7a3752017-03-15 11:23:3745 spec_(spec),
46 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3347 personal_data_manager_(personal_data_manager),
sebsgc6719b32017-07-05 19:54:4748 journey_logger_(journey_logger),
Rouslan Solomakhind2cae95a2018-08-09 00:16:1049 are_requested_methods_supported_(
50 !spec_->supported_card_networks().empty()),
mathpf1a7a3752017-03-15 11:23:3751 selected_shipping_profile_(nullptr),
Mathieu Perreault04b4c662017-06-02 13:35:1352 selected_shipping_option_error_profile_(nullptr),
mathpf1a7a3752017-03-15 11:23:3753 selected_contact_profile_(nullptr),
Jinho Bangcac8d9a02018-08-23 19:47:2254 invalid_shipping_profile_(nullptr),
55 invalid_contact_profile_(nullptr),
anthonyvdd23ed702017-04-05 15:29:0056 selected_instrument_(nullptr),
gogeraldac15d2362017-11-15 01:04:1957 number_of_pending_sw_payment_instruments_(0),
tmartino01c3eb82017-04-29 15:18:3958 payment_request_delegate_(payment_request_delegate),
gogerald8189d522017-09-15 17:52:1859 profile_comparator_(app_locale, *spec),
60 weak_ptr_factory_(this) {
Mathieu Perreault157f3992018-06-29 18:48:0661 if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
gogerald12a4e4ff2018-08-08 12:16:2562 DCHECK(web_contents);
gogerald8189d522017-09-15 17:52:1863 get_all_instruments_finished_ = false;
gogerald97e1b3312017-11-21 23:31:1064 ServiceWorkerPaymentAppFactory::GetInstance()->GetAllPaymentApps(
Rouslan Solomakhindbf593d92017-11-21 19:20:5765 web_contents,
Rouslan Solomakhin438d8c92017-10-26 21:33:1866 payment_request_delegate_->GetPaymentManifestWebDataService(),
Rouslan Solomakhin06df42d2017-11-14 20:35:1167 spec_->method_data(),
Rouslan Solomakhine36f41f2018-03-19 16:27:0968 /*may_crawl_for_installable_payment_apps=*/
69 !spec_->supports_basic_card(),
Rouslan Solomakhin438d8c92017-10-26 21:33:1870 base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback,
gogerald3f1cabf2018-02-08 14:19:1871 weak_ptr_factory_.GetWeakPtr(), web_contents,
72 top_level_origin, frame_origin),
gogerald97e1b3312017-11-21 23:31:1073 base::BindOnce([]() {
74 /* Nothing needs to be done after writing cache. This callback is used
75 * only in tests. */
76 }));
gogerald8189d522017-09-15 17:52:1877 } else {
78 PopulateProfileCache();
79 SetDefaultProfileSelections();
80 }
sebsg7e619132017-04-27 16:07:1081 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3782}
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5183
mathp151bd312017-04-03 21:07:2484PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3785
gogerald8189d522017-09-15 17:52:1886void PaymentRequestState::GetAllPaymentAppsCallback(
gogerald3f1cabf2018-02-08 14:19:1887 content::WebContents* web_contents,
gogerald7a0cc3e2017-09-19 03:35:4888 const GURL& top_level_origin,
89 const GURL& frame_origin,
gogerald84ae6262018-02-06 06:21:4690 content::PaymentAppProvider::PaymentApps apps,
91 ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps) {
gogerald3f1cabf2018-02-08 14:19:1892 number_of_pending_sw_payment_instruments_ =
93 apps.size() + installable_apps.size();
gogeraldac15d2362017-11-15 01:04:1994 if (number_of_pending_sw_payment_instruments_ == 0U) {
95 FinishedGetAllSWPaymentInstruments();
96 return;
gogerald8189d522017-09-15 17:52:1897 }
98
gogeraldac15d2362017-11-15 01:04:1999 for (auto& app : apps) {
100 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
101 std::make_unique<ServiceWorkerPaymentInstrument>(
gogerald3f1cabf2018-02-08 14:19:18102 web_contents->GetBrowserContext(), top_level_origin, frame_origin,
103 spec_, std::move(app.second), payment_request_delegate_);
104 instrument->ValidateCanMakePayment(
105 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
106 weak_ptr_factory_.GetWeakPtr()));
107 available_instruments_.push_back(std::move(instrument));
108 }
109
110 for (auto& installable_app : installable_apps) {
111 std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
112 std::make_unique<ServiceWorkerPaymentInstrument>(
113 web_contents, top_level_origin, frame_origin, spec_,
114 std::move(installable_app.second), installable_app.first.spec(),
115 payment_request_delegate_);
gogeraldac15d2362017-11-15 01:04:19116 instrument->ValidateCanMakePayment(
117 base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
118 weak_ptr_factory_.GetWeakPtr()));
119 available_instruments_.push_back(std::move(instrument));
120 }
121}
122
123void PaymentRequestState::OnSWPaymentInstrumentValidated(
124 ServiceWorkerPaymentInstrument* instrument,
125 bool result) {
126 // Remove service worker payment instruments failed on validation.
127 if (!result) {
128 for (size_t i = 0; i < available_instruments_.size(); i++) {
129 if (available_instruments_[i].get() == instrument) {
130 available_instruments_.erase(available_instruments_.begin() + i);
131 break;
132 }
133 }
134 }
135
136 if (--number_of_pending_sw_payment_instruments_ > 0)
137 return;
138
139 FinishedGetAllSWPaymentInstruments();
140}
141
142void PaymentRequestState::FinishedGetAllSWPaymentInstruments() {
gogerald8189d522017-09-15 17:52:18143 PopulateProfileCache();
144 SetDefaultProfileSelections();
145
146 get_all_instruments_finished_ = true;
Rouslan Solomakhind2cae95a2018-08-09 00:16:10147 are_requested_methods_supported_ |= !available_instruments_.empty();
gogerald8189d522017-09-15 17:52:18148 NotifyOnGetAllPaymentInstrumentsFinished();
Rouslan Solomakhin9788d4b2019-04-09 13:10:23149 NotifyInitialized();
gogerald8189d522017-09-15 17:52:18150
Danyao Wang4bc0606a2018-12-27 16:54:53151 // Fulfill the pending CanMakePayment call.
Danyao Wang57aa0442019-01-31 04:06:41152 if (can_make_payment_callback_) {
153 CheckCanMakePayment(can_make_payment_legacy_mode_,
154 std::move(can_make_payment_callback_));
155 }
Danyao Wang4bc0606a2018-12-27 16:54:53156
Danyao Wangce175bf2018-12-21 22:35:58157 // Fulfill the pending HasEnrolledInstrument call.
158 if (has_enrolled_instrument_callback_)
159 CheckHasEnrolledInstrument(std::move(has_enrolled_instrument_callback_));
gogerald0a7ee6c2017-11-13 18:23:19160
Danyao Wangce175bf2018-12-21 22:35:58161 // Fulfill the pending AreRequestedMethodsSupported call.
gogerald0a7ee6c2017-11-13 18:23:19162 if (are_requested_methods_supported_callback_)
163 CheckRequestedMethodsSupported(
164 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18165}
166
sebsg695799a2017-04-11 16:29:06167void PaymentRequestState::OnPaymentResponseReady(
168 mojom::PaymentResponsePtr payment_response) {
169 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
170}
171
sebsg7e619132017-04-27 16:07:10172void PaymentRequestState::OnSpecUpdated() {
Jinho Bangcac8d9a02018-08-23 19:47:22173 autofill::AutofillProfile* selected_shipping_profile =
174 selected_shipping_profile_;
175 autofill::AutofillProfile* selected_contact_profile =
176 selected_contact_profile_;
177
178 if (spec_->current_update_reason() ==
179 PaymentRequestSpec::UpdateReason::RETRY) {
180 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
181 invalid_shipping_profile_ = selected_shipping_profile;
182 selected_shipping_profile_ = nullptr;
183 }
Jinho Bang092e7162018-09-06 23:41:19184
Jinho Bangcac8d9a02018-08-23 19:47:22185 if (spec_->has_payer_error() && selected_contact_profile) {
186 invalid_contact_profile_ = selected_contact_profile;
187 selected_contact_profile_ = nullptr;
188 }
189 }
190
Mathieu Perreault04b4c662017-06-02 13:35:13191 if (spec_->selected_shipping_option_error().empty()) {
192 selected_shipping_option_error_profile_ = nullptr;
193 } else {
Jinho Bangcac8d9a02018-08-23 19:47:22194 selected_shipping_option_error_profile_ = selected_shipping_profile;
Mathieu Perreault04b4c662017-06-02 13:35:13195 selected_shipping_profile_ = nullptr;
Jinho Bang092e7162018-09-06 23:41:19196 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
197 invalid_shipping_profile_ = selected_shipping_profile;
198 }
Mathieu Perreault04b4c662017-06-02 13:35:13199 }
Jinho Bangcac8d9a02018-08-23 19:47:22200
sebsg7e619132017-04-27 16:07:10201 is_waiting_for_merchant_validation_ = false;
202 UpdateIsReadyToPayAndNotifyObservers();
203}
204
Danyao Wang57aa0442019-01-31 04:06:41205void PaymentRequestState::CanMakePayment(bool legacy_mode,
206 StatusCallback callback) {
Danyao Wang4bc0606a2018-12-27 16:54:53207 if (!get_all_instruments_finished_) {
208 DCHECK(!can_make_payment_callback_);
209 can_make_payment_callback_ = std::move(callback);
Danyao Wang57aa0442019-01-31 04:06:41210 can_make_payment_legacy_mode_ = legacy_mode;
Danyao Wang4bc0606a2018-12-27 16:54:53211 return;
212 }
213
214 base::ThreadTaskRunnerHandle::Get()->PostTask(
Danyao Wang57aa0442019-01-31 04:06:41215 FROM_HERE, base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
216 weak_ptr_factory_.GetWeakPtr(), legacy_mode,
217 std::move(callback)));
Danyao Wangce175bf2018-12-21 22:35:58218}
219
Danyao Wang57aa0442019-01-31 04:06:41220void PaymentRequestState::CheckCanMakePayment(bool legacy_mode,
221 StatusCallback callback) {
Danyao Wang4bc0606a2018-12-27 16:54:53222 DCHECK(get_all_instruments_finished_);
Danyao Wang57aa0442019-01-31 04:06:41223 if (!legacy_mode) {
224 std::move(callback).Run(are_requested_methods_supported_);
225 return;
226 }
227
228 // Legacy mode: fall back to also checking if an instrument is enrolled.
229 bool can_make_payment_value = false;
230 for (const auto& instrument : available_instruments_) {
231 if (instrument->IsValidForCanMakePayment()) {
232 can_make_payment_value = true;
233 break;
234 }
235 }
236 std::move(callback).Run(can_make_payment_value);
Danyao Wangce175bf2018-12-21 22:35:58237}
238
239void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) {
gogerald8189d522017-09-15 17:52:18240 if (!get_all_instruments_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53241 DCHECK(!has_enrolled_instrument_callback_);
Danyao Wangce175bf2018-12-21 22:35:58242 has_enrolled_instrument_callback_ = std::move(callback);
gogerald8189d522017-09-15 17:52:18243 return;
244 }
245
246 base::ThreadTaskRunnerHandle::Get()->PostTask(
247 FROM_HERE,
Danyao Wangce175bf2018-12-21 22:35:58248 base::BindOnce(&PaymentRequestState::CheckHasEnrolledInstrument,
gogerald8189d522017-09-15 17:52:18249 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
250}
251
Danyao Wangce175bf2018-12-21 22:35:58252void PaymentRequestState::CheckHasEnrolledInstrument(StatusCallback callback) {
Danyao Wang486739212019-02-04 17:08:59253 DCHECK(get_all_instruments_finished_);
254 bool has_enrolled_instrument_value = false;
255 for (const auto& instrument : available_instruments_) {
256 if (instrument->IsValidForCanMakePayment()) {
257 has_enrolled_instrument_value = true;
258 break;
259 }
260 }
261 std::move(callback).Run(has_enrolled_instrument_value);
mathp1a5be4f2017-03-24 18:09:19262}
263
gogerald0a7ee6c2017-11-13 18:23:19264void PaymentRequestState::AreRequestedMethodsSupported(
265 StatusCallback callback) {
266 if (!get_all_instruments_finished_) {
267 are_requested_methods_supported_callback_ = std::move(callback);
268 return;
269 }
270
271 base::ThreadTaskRunnerHandle::Get()->PostTask(
272 FROM_HERE,
273 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
274 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
275}
276
277void PaymentRequestState::CheckRequestedMethodsSupported(
278 StatusCallback callback) {
279 DCHECK(get_all_instruments_finished_);
280
Rouslan Solomakhind2cae95a2018-08-09 00:16:10281 std::move(callback).Run(are_requested_methods_supported_);
rouslan6e3cf7c62017-04-17 21:23:28282}
283
anthonyvd6a43b932017-05-11 18:39:27284std::string PaymentRequestState::GetAuthenticatedEmail() const {
285 return payment_request_delegate_->GetAuthenticatedEmail();
286}
287
mathpf1a7a3752017-03-15 11:23:37288void PaymentRequestState::AddObserver(Observer* observer) {
289 CHECK(observer);
290 observers_.AddObserver(observer);
291}
mathpf1a7a3752017-03-15 11:23:37292
293void PaymentRequestState::RemoveObserver(Observer* observer) {
294 observers_.RemoveObserver(observer);
295}
296
mathpf1a7a3752017-03-15 11:23:37297void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05298 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06299
300 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51301 response_helper_ = std::make_unique<PaymentResponseHelper>(
sebsg8a9c2342017-04-21 17:05:15302 app_locale_, spec_, selected_instrument_, payment_request_delegate_,
303 selected_shipping_profile_, selected_contact_profile_, this);
mathpf1a7a3752017-03-15 11:23:37304}
305
Rouslan Solomakhin761d65eb2019-04-29 20:08:01306void PaymentRequestState::OnPaymentAppWindowClosed() {
307 DCHECK(selected_instrument_);
308 response_helper_.reset();
309 selected_instrument_->OnPaymentAppWindowClosed();
310}
311
sebsg8a93b272017-05-11 19:30:22312void PaymentRequestState::RecordUseStats() {
313 if (spec_->request_shipping()) {
314 DCHECK(selected_shipping_profile_);
315 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
316 }
317
318 if (spec_->request_payer_name() || spec_->request_payer_email() ||
319 spec_->request_payer_phone()) {
320 DCHECK(selected_contact_profile_);
321
322 // If the same address was used for both contact and shipping, the stats
323 // should only be updated once.
324 if (!spec_->request_shipping() || (selected_shipping_profile_->guid() !=
325 selected_contact_profile_->guid())) {
326 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
327 }
328 }
329
330 selected_instrument_->RecordUse();
331}
332
mathp24ce4cd2017-04-12 20:56:42333void PaymentRequestState::AddAutofillPaymentInstrument(
334 bool selected,
335 const autofill::CreditCard& card) {
336 std::string basic_card_network =
rouslan4e981bd32017-05-01 17:49:16337 autofill::data_util::GetPaymentRequestData(card.network())
338 .basic_card_issuer_network;
Rouslan Solomakhin25d708b2017-06-23 17:12:03339 if (!spec_->supported_card_networks_set().count(basic_card_network) ||
340 !spec_->supported_card_types_set().count(card.card_type())) {
mathp24ce4cd2017-04-12 20:56:42341 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03342 }
343
344 // The total number of card types: credit, debit, prepaid, unknown.
345 constexpr size_t kTotalNumberOfCardTypes = 4U;
346
347 // Whether the card type (credit, debit, prepaid) matches thetype that the
348 // merchant has requested exactly. This should be false for unknown card
349 // types, if the merchant cannot accept some card types.
350 bool matches_merchant_card_type_exactly =
351 card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN ||
352 spec_->supported_card_types_set().size() == kTotalNumberOfCardTypes;
mathp24ce4cd2017-04-12 20:56:42353
354 // AutofillPaymentInstrument makes a copy of |card| so it is effectively
355 // owned by this object.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51356 auto instrument = std::make_unique<AutofillPaymentInstrument>(
Rouslan Solomakhin25d708b2017-06-23 17:12:03357 basic_card_network, card, matches_merchant_card_type_exactly,
358 shipping_profiles_, app_locale_, payment_request_delegate_);
mathp24ce4cd2017-04-12 20:56:42359 available_instruments_.push_back(std::move(instrument));
360
Sahel Sharifybc4173f2019-05-09 21:03:57361 if (selected) {
362 SetSelectedInstrument(available_instruments_.back().get(),
363 SectionSelectionStatus::kAddedSelected);
364 }
mathp24ce4cd2017-04-12 20:56:42365}
366
madf9904ea2017-04-25 18:39:12367void PaymentRequestState::AddAutofillShippingProfile(
368 bool selected,
369 const autofill::AutofillProfile& profile) {
370 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51371 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12372 // TODO(tmartino): Implement deduplication rules specific to shipping
373 // profiles.
374 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
375 shipping_profiles_.push_back(new_cached_profile);
376
Sahel Sharifybc4173f2019-05-09 21:03:57377 if (selected) {
378 SetSelectedShippingProfile(new_cached_profile,
379 SectionSelectionStatus::kAddedSelected);
380 }
madf9904ea2017-04-25 18:39:12381}
382
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23383void PaymentRequestState::AddAutofillContactProfile(
384 bool selected,
385 const autofill::AutofillProfile& profile) {
386 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51387 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23388 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
389 contact_profiles_.push_back(new_cached_profile);
390
Sahel Sharifybc4173f2019-05-09 21:03:57391 if (selected) {
392 SetSelectedContactProfile(new_cached_profile,
393 SectionSelectionStatus::kAddedSelected);
394 }
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23395}
396
anthonyvd0116ce332017-03-21 21:29:01397void PaymentRequestState::SetSelectedShippingOption(
mathp151bd312017-04-03 21:07:24398 const std::string& shipping_option_id) {
anthonyvd2f30baa12017-04-13 22:30:50399 spec_->StartWaitingForUpdateWith(
400 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
mathp151bd312017-04-03 21:07:24401 // This will inform the merchant and will lead to them calling updateWith with
402 // new PaymentDetails.
403 delegate_->OnShippingOptionIdSelected(shipping_option_id);
anthonyvd0116ce332017-03-21 21:29:01404}
405
mathpf1a7a3752017-03-15 11:23:37406void PaymentRequestState::SetSelectedShippingProfile(
Sahel Sharifybc4173f2019-05-09 21:03:57407 autofill::AutofillProfile* profile,
408 SectionSelectionStatus selection_status) {
anthonyvd2f30baa12017-04-13 22:30:50409 spec_->StartWaitingForUpdateWith(
410 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37411 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10412
Jinho Bangcac8d9a02018-08-23 19:47:22413 // Changing the shipping address clears shipping address validation errors
414 // from retry().
415 invalid_shipping_profile_ = nullptr;
416
sebsg7e619132017-04-27 16:07:10417 // The user should not be able to click on pay until the callback from the
418 // merchant.
419 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10420
421 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f2017-10-23 20:28:39422 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29423 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00424 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
425 weak_ptr_factory_.GetWeakPtr()));
Sahel Sharifybc4173f2019-05-09 21:03:57426 IncrementSelectionStatus(JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
427 selection_status);
mathpf1a7a3752017-03-15 11:23:37428}
429
430void PaymentRequestState::SetSelectedContactProfile(
Sahel Sharifybc4173f2019-05-09 21:03:57431 autofill::AutofillProfile* profile,
432 SectionSelectionStatus selection_status) {
mathpf1a7a3752017-03-15 11:23:37433 selected_contact_profile_ = profile;
Jinho Bangcac8d9a02018-08-23 19:47:22434
435 // Changing the contact information clears contact information validation
436 // errors from retry().
437 invalid_contact_profile_ = nullptr;
438
mathpf1a7a3752017-03-15 11:23:37439 UpdateIsReadyToPayAndNotifyObservers();
Jinho Bangbb178152018-09-13 09:44:43440
441 if (IsPaymentAppInvoked()) {
Jinho Bang21d6be92018-12-18 15:30:31442 delegate_->OnPayerInfoSelected(
443 response_helper_->GeneratePayerDetail(profile));
Jinho Bangbb178152018-09-13 09:44:43444 }
Sahel Sharifybc4173f2019-05-09 21:03:57445 IncrementSelectionStatus(JourneyLogger::Section::SECTION_CONTACT_INFO,
446 selection_status);
mathpf1a7a3752017-03-15 11:23:37447}
448
Sahel Sharifybc4173f2019-05-09 21:03:57449void PaymentRequestState::SetSelectedInstrument(
450 PaymentInstrument* instrument,
451 SectionSelectionStatus selection_status) {
mathp363735b2017-03-16 18:08:05452 selected_instrument_ = instrument;
mathpf1a7a3752017-03-15 11:23:37453 UpdateIsReadyToPayAndNotifyObservers();
Sahel Sharifybc4173f2019-05-09 21:03:57454 IncrementSelectionStatus(JourneyLogger::Section::SECTION_PAYMENT_METHOD,
455 selection_status);
456}
457
458void PaymentRequestState::IncrementSelectionStatus(
459 JourneyLogger::Section section,
460 SectionSelectionStatus selection_status) {
461 switch (selection_status) {
462 case SectionSelectionStatus::kSelected:
463 journey_logger_->IncrementSelectionChanges(section);
464 break;
465 case SectionSelectionStatus::kEditedSelected:
466 journey_logger_->IncrementSelectionEdits(section);
467 break;
468 case SectionSelectionStatus::kAddedSelected:
469 journey_logger_->IncrementSelectionAdds(section);
470 break;
471 default:
472 NOTREACHED();
473 }
mathpf1a7a3752017-03-15 11:23:37474}
475
mathpc0d616a2017-03-15 14:09:33476const std::string& PaymentRequestState::GetApplicationLocale() {
477 return app_locale_;
478}
479
480autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
481 return personal_data_manager_;
482}
483
mad763ed2b2017-04-24 20:28:47484autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
485 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38486}
487
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56488bool PaymentRequestState::IsPaymentAppInvoked() const {
489 return !!response_helper_;
490}
491
Mathieu Perreaulteea046d12017-09-28 15:51:21492autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45493 return payment_request_delegate_->GetAddressNormalizer();
494}
495
Rouslan Solomakhin48fd6e872019-02-22 17:23:10496bool PaymentRequestState::IsInitialized() const {
497 return get_all_instruments_finished_;
498}
499
Rouslan Solomakhin9788d4b2019-04-09 13:10:23500void PaymentRequestState::SelectDefaultShippingAddressAndNotifyObservers() {
501 // Only pre-select an address if the merchant provided at least one selected
502 // shipping option, and the top profile is complete. Assumes that profiles
503 // have already been sorted for completeness and frecency.
504 if (!shipping_profiles().empty() && spec_->selected_shipping_option() &&
505 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
506 selected_shipping_profile_ = shipping_profiles()[0];
507 }
508
509 UpdateIsReadyToPayAndNotifyObservers();
510}
511
mathpf1a7a3752017-03-15 11:23:37512void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37513 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33514 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37515
tmartinocd131b32017-05-24 19:40:59516 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
517 raw_profiles_for_filtering.reserve(profiles.size());
518
mathpf1a7a3752017-03-15 11:23:37519 // PaymentRequest may outlive the Profiles returned by the Data Manager.
520 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30521 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37522 for (size_t i = 0; i < profiles.size(); i++) {
523 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51524 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59525 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37526 }
527
tmartino01c3eb82017-04-29 15:18:39528 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
529 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59530 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
531 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24532
sebsgc6719b32017-07-05 19:54:47533 // Set the number of suggestions shown for the sections requested by the
534 // merchant.
535 if (spec_->request_payer_name() || spec_->request_payer_phone() ||
536 spec_->request_payer_email()) {
sebsgce700484d2017-07-19 23:25:38537 bool has_complete_contact =
538 contact_profiles_.empty()
539 ? false
540 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47541 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38542 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
543 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47544 }
545 if (spec_->request_shipping()) {
sebsgce700484d2017-07-19 23:25:38546 bool has_complete_shipping =
547 shipping_profiles_.empty()
548 ? false
549 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
sebsgc6719b32017-07-05 19:54:47550 journey_logger_->SetNumberOfSuggestionsShown(
551 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38552 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47553 }
554
mathpf14c1e32017-05-12 16:37:30555 // Create the list of available instruments. A copy of each card will be made
556 // by their respective AutofillPaymentInstrument.
mathpf1a7a3752017-03-15 11:23:37557 const std::vector<autofill::CreditCard*>& cards =
Amirhossein Simjourd3b7ba4a2018-05-07 15:27:21558 personal_data_manager_->GetCreditCardsToSuggest(
Mathieu Perreault157f3992018-06-29 18:48:06559 /*include_server_cards=*/base::FeatureList::IsEnabled(
560 payments::features::kReturnGooglePayInBasicCard));
mathp24ce4cd2017-04-12 20:56:42561 for (autofill::CreditCard* card : cards)
562 AddAutofillPaymentInstrument(/*selected=*/false, *card);
mathpf1a7a3752017-03-15 11:23:37563}
564
565void PaymentRequestState::SetDefaultProfileSelections() {
mathpf14c1e32017-05-12 16:37:30566 // Contact profiles were ordered by completeness in addition to frecency;
567 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59568 if (!contact_profiles().empty() &&
569 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37570 selected_contact_profile_ = contact_profiles()[0];
571
mathp363735b2017-03-16 18:08:05572 // TODO(crbug.com/702063): Change this code to prioritize instruments by use
573 // count and other means, and implement a way to modify this function's return
574 // value.
575 const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
576 available_instruments();
577 auto first_complete_instrument =
578 std::find_if(instruments.begin(), instruments.end(),
579 [](const std::unique_ptr<PaymentInstrument>& instrument) {
Rouslan Solomakhin25d708b2017-06-23 17:12:03580 return instrument->IsCompleteForPayment() &&
581 instrument->IsExactlyMatchingMerchantRequest();
mathp363735b2017-03-16 18:08:05582 });
mathp363735b2017-03-16 18:08:05583 selected_instrument_ = first_complete_instrument == instruments.end()
584 ? nullptr
585 : first_complete_instrument->get();
Rouslan Solomakhin9788d4b2019-04-09 13:10:23586
587 SelectDefaultShippingAddressAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18588
589 bool has_complete_instrument =
590 available_instruments().empty()
591 ? false
592 : available_instruments()[0]->IsCompleteForPayment();
593
594 journey_logger_->SetNumberOfSuggestionsShown(
595 JourneyLogger::Section::SECTION_PAYMENT_METHOD,
596 available_instruments().size(), has_complete_instrument);
mathpf1a7a3752017-03-15 11:23:37597}
598
599void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
600 is_ready_to_pay_ =
601 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
602 NotifyOnSelectedInformationChanged();
603}
604
gogerald8189d522017-09-15 17:52:18605void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() {
606 for (auto& observer : observers_)
607 observer.OnGetAllPaymentInstrumentsFinished();
gogerald8189d522017-09-15 17:52:18608}
609
mathpf1a7a3752017-03-15 11:23:37610void PaymentRequestState::NotifyOnSelectedInformationChanged() {
611 for (auto& observer : observers_)
612 observer.OnSelectedInformationChanged();
613}
614
615bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05616 // There is no need to check for supported networks, because only supported
617 // instruments are listed/created in the flow.
mathp4baea332017-04-10 21:42:29618 return selected_instrument_ != nullptr &&
619 selected_instrument_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37620}
621
622bool PaymentRequestState::ArePaymentOptionsSatisfied() {
sebsg7e619132017-04-27 16:07:10623 if (is_waiting_for_merchant_validation_)
624 return false;
625
tmartino01c3eb82017-04-29 15:18:39626 if (!profile_comparator()->IsShippingComplete(selected_shipping_profile_))
627 return false;
628
Anthony Vallee-Duboisa8814672017-06-01 18:43:20629 if (spec_->request_shipping() && !spec_->selected_shipping_option())
630 return false;
631
tmartino01c3eb82017-04-29 15:18:39632 return profile_comparator()->IsContactInfoComplete(selected_contact_profile_);
mathpf1a7a3752017-03-15 11:23:37633}
634
Mathieu Perreault17c1ae92017-10-20 17:16:00635void PaymentRequestState::OnAddressNormalized(
636 bool success,
637 const autofill::AutofillProfile& normalized_profile) {
638 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22639 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
640 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00641}
642
mathpf1a7a3752017-03-15 11:23:37643} // namespace payments