blob: 6c550ab00f0065279f2b1b62b035eefa959f3b1b [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 Solomakhin2039a342020-05-21 19:21:0421#include "components/payments/content/autofill_payment_app.h"
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2722#include "components/payments/content/autofill_payment_app_factory.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5123#include "components/payments/content/content_payment_request_delegate.h"
Rouslan Solomakhin2039a342020-05-21 19:21:0424#include "components/payments/content/payment_app.h"
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2725#include "components/payments/content/payment_app_service.h"
26#include "components/payments/content/payment_app_service_factory.h"
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5127#include "components/payments/content/payment_manifest_web_data_service.h"
sebsgad86bd002017-03-29 16:39:1228#include "components/payments/content/payment_response_helper.h"
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:3929#include "components/payments/content/service_worker_payment_app.h"
Sahel Sharify13331e82019-07-12 01:00:3030#include "components/payments/core/autofill_card_validation.h"
Rouslan Solomakhin1dca2a922019-09-06 22:25:0731#include "components/payments/core/error_strings.h"
Mathieu Perreault157f3992018-06-29 18:48:0632#include "components/payments/core/features.h"
Rouslan Solomakhin85b10da2019-11-05 20:03:1733#include "components/payments/core/method_strings.h"
tmartino01c3eb82017-04-29 15:18:3934#include "components/payments/core/payment_request_data_util.h"
Danyao Wang761739b2019-06-27 23:59:3235#include "components/payments/core/payments_experimental_features.h"
Danyao Wang4f2ba632020-03-11 13:56:5436#include "content/public/browser/render_frame_host.h"
Rouslan Solomakhina4a9b8c2020-10-15 21:16:2437#include "content/public/browser/render_process_host.h"
gogerald8189d522017-09-15 17:52:1838#include "content/public/common/content_features.h"
mathpf1a7a3752017-03-15 11:23:3739
40namespace payments {
Rouslan Solomakhin1dca2a922019-09-06 22:25:0741namespace {
42
Rouslan Solomakhin1dca2a922019-09-06 22:25:0743// Invokes the |callback| with |status|.
44void CallStatusCallback(PaymentRequestState::StatusCallback callback,
45 bool status) {
46 std::move(callback).Run(status);
47}
48
49// Posts the |callback| to be invoked with |status| asynchronously.
50void PostStatusCallback(PaymentRequestState::StatusCallback callback,
51 bool status) {
52 base::ThreadTaskRunnerHandle::Get()->PostTask(
53 FROM_HERE,
54 base::BindOnce(&CallStatusCallback, std::move(callback), status));
55}
56
57} // namespace
mathpf1a7a3752017-03-15 11:23:3758
mathpc0d616a2017-03-15 14:09:3359PaymentRequestState::PaymentRequestState(
Danyao Wang4f2ba632020-03-11 13:56:5460 content::RenderFrameHost* initiator_render_frame_host,
gogerald7a0cc3e2017-09-19 03:35:4861 const GURL& top_level_origin,
62 const GURL& frame_origin,
Rouslan Solomakhinc71cca622020-01-31 22:15:3563 const url::Origin& frame_security_origin,
DongJun Kim54690d52020-09-26 12:07:5464 base::WeakPtr<PaymentRequestSpec> spec,
Kyungsun Leecdbdade2020-08-25 18:06:1265 base::WeakPtr<Delegate> delegate,
mathpc0d616a2017-03-15 14:09:3366 const std::string& app_locale,
anthonyvdd23ed702017-04-05 15:29:0067 autofill::PersonalDataManager* personal_data_manager,
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5168 ContentPaymentRequestDelegate* payment_request_delegate,
sebsgc6719b32017-07-05 19:54:4769 JourneyLogger* journey_logger)
Rouslan Solomakhina4a9b8c2020-10-15 21:16:2470 : frame_routing_id_(content::GlobalFrameRoutingId(
71 initiator_render_frame_host->GetProcess()->GetID(),
72 initiator_render_frame_host->GetRoutingID())),
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2773 top_origin_(top_level_origin),
74 frame_origin_(frame_origin),
Rouslan Solomakhinc71cca622020-01-31 22:15:3575 frame_security_origin_(frame_security_origin),
mathpc0d616a2017-03-15 14:09:3376 app_locale_(app_locale),
DongJun Kim54690d52020-09-26 12:07:5477 spec_(spec),
mathpf1a7a3752017-03-15 11:23:3778 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3379 personal_data_manager_(personal_data_manager),
sebsgc6719b32017-07-05 19:54:4780 journey_logger_(journey_logger),
Rouslan Solomakhind2cae95a2018-08-09 00:16:1081 are_requested_methods_supported_(
82 !spec_->supported_card_networks().empty()),
tmartino01c3eb82017-04-29 15:18:3983 payment_request_delegate_(payment_request_delegate),
Jeremy Roman5c341f6d2019-07-15 15:56:1084 profile_comparator_(app_locale, *spec) {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2785 PopulateProfileCache();
Danyao Wang761739b2019-06-27 23:59:3286
Danyao Wange865a302020-04-01 18:35:1487 PaymentAppService* service = PaymentAppServiceFactory::GetForContext(
Rouslan Solomakhina4a9b8c2020-10-15 21:16:2488 initiator_render_frame_host->GetBrowserContext());
Danyao Wange865a302020-04-01 18:35:1489 number_of_payment_app_factories_ = service->GetNumberOfFactories();
90 service->Create(weak_ptr_factory_.GetWeakPtr());
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2791
sebsg7e619132017-04-27 16:07:1092 spec_->AddObserver(this);
mathpf1a7a3752017-03-15 11:23:3793}
Rouslan Solomakhin4eea9bc22017-10-10 15:18:5194
mathp151bd312017-04-03 21:07:2495PaymentRequestState::~PaymentRequestState() {}
mathpf1a7a3752017-03-15 11:23:3796
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2797content::WebContents* PaymentRequestState::GetWebContents() {
Rouslan Solomakhina4a9b8c2020-10-15 21:16:2498 auto* rfh = content::RenderFrameHost::FromID(frame_routing_id_);
99 return rfh && rfh->IsCurrent()
100 ? content::WebContents::FromRenderFrameHost(rfh)
101 : nullptr;
gogeraldac15d2362017-11-15 01:04:19102}
103
Danyao Wangaed5b0a92020-04-01 22:43:14104ContentPaymentRequestDelegate* PaymentRequestState::GetPaymentRequestDelegate()
105 const {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27106 return payment_request_delegate_;
107}
Rouslan Solomakhin1dca2a922019-09-06 22:25:07108
Rouslan Solomakhin535fe302020-06-02 20:17:39109void PaymentRequestState::ShowProcessingSpinner() {
110 GetPaymentRequestDelegate()->ShowProcessingSpinner();
111}
112
DongJun Kim54690d52020-09-26 12:07:54113base::WeakPtr<PaymentRequestSpec> PaymentRequestState::GetSpec() const {
114 return spec_;
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27115}
gogeraldac15d2362017-11-15 01:04:19116
Rouslan Solomakhincbdeef92020-08-15 12:39:30117std::string PaymentRequestState::GetTwaPackageName() const {
118 return GetPaymentRequestDelegate()->GetTwaPackageName();
119}
120
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27121const GURL& PaymentRequestState::GetTopOrigin() {
122 return top_origin_;
123}
124
125const GURL& PaymentRequestState::GetFrameOrigin() {
126 return frame_origin_;
127}
128
Rouslan Solomakhinc71cca622020-01-31 22:15:35129const url::Origin& PaymentRequestState::GetFrameSecurityOrigin() {
130 return frame_security_origin_;
131}
132
Danyao Wang4f2ba632020-03-11 13:56:54133content::RenderFrameHost* PaymentRequestState::GetInitiatorRenderFrameHost()
134 const {
Rouslan Solomakhina4a9b8c2020-10-15 21:16:24135 return content::RenderFrameHost::FromID(frame_routing_id_);
Danyao Wang4f2ba632020-03-11 13:56:54136}
137
Danyao Wangaed5b0a92020-04-01 22:43:14138const std::vector<mojom::PaymentMethodDataPtr>&
139PaymentRequestState::GetMethodData() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22140 DCHECK(GetSpec());
Danyao Wangaed5b0a92020-04-01 22:43:14141 return GetSpec()->method_data();
142}
143
Rouslan Solomakhin914686c52020-08-21 15:15:41144std::unique_ptr<autofill::InternalAuthenticator>
145PaymentRequestState::CreateInternalAuthenticator() const {
Rouslan Solomakhin54e0d1e2020-08-30 20:23:31146 return GetPaymentRequestDelegate()->CreateInternalAuthenticator();
Rouslan Solomakhin914686c52020-08-21 15:15:41147}
148
Danyao Wangaed5b0a92020-04-01 22:43:14149scoped_refptr<PaymentManifestWebDataService>
150PaymentRequestState::GetPaymentManifestWebDataService() const {
151 return GetPaymentRequestDelegate()->GetPaymentManifestWebDataService();
152}
153
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27154const std::vector<autofill::AutofillProfile*>&
155PaymentRequestState::GetBillingProfiles() {
156 return shipping_profiles_;
157}
158
159bool PaymentRequestState::IsRequestedAutofillDataAvailable() {
160 return is_requested_autofill_data_available_;
161}
162
163bool PaymentRequestState::MayCrawlForInstallablePaymentApps() {
164 return PaymentsExperimentalFeatures::IsEnabled(
165 features::kAlwaysAllowJustInTimePaymentApp) ||
Rouslan Solomakhin75450a42020-09-24 18:44:22166 !spec_ || !spec_->supports_basic_card();
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27167}
168
Rouslan Solomakhin535fe302020-06-02 20:17:39169bool PaymentRequestState::IsOffTheRecord() const {
170 return GetPaymentRequestDelegate()->IsOffTheRecord();
171}
172
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27173void PaymentRequestState::OnPaymentAppCreated(std::unique_ptr<PaymentApp> app) {
174 if (app->type() == PaymentApp::Type::AUTOFILL) {
175 journey_logger_->SetEventOccurred(
176 JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
177 } else if (base::Contains(app->GetAppMethodNames(), methods::kGooglePay) ||
178 base::Contains(app->GetAppMethodNames(), methods::kAndroidPay)) {
Danyao Wang25f72dc2019-10-18 05:11:32179 journey_logger_->SetEventOccurred(
180 JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE);
181 } else {
182 journey_logger_->SetEventOccurred(
183 JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER);
184 }
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27185 available_apps_.emplace_back(std::move(app));
gogeraldac15d2362017-11-15 01:04:19186}
187
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27188void PaymentRequestState::OnPaymentAppCreationError(
189 const std::string& error_message) {
190 get_all_payment_apps_error_ = error_message;
191}
192
Danyao Wangaed5b0a92020-04-01 22:43:14193bool PaymentRequestState::SkipCreatingNativePaymentApps() const {
194 return false;
195}
196
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27197void PaymentRequestState::OnDoneCreatingPaymentApps() {
198 DCHECK_NE(0U, number_of_payment_app_factories_);
199 if (--number_of_payment_app_factories_ > 0U)
200 return;
201
Nick Burrisfca090832020-07-28 00:17:42202 if (IsInTwa()) {
203 // If a preferred payment app is present (e.g. Play Billing within a TWA),
204 // all other payment apps are ignored.
205 bool has_preferred_app =
206 std::any_of(available_apps_.begin(), available_apps_.end(),
207 [](const auto& app) { return app->IsPreferred(); });
208 if (has_preferred_app) {
209 available_apps_.erase(
210 std::remove_if(available_apps_.begin(), available_apps_.end(),
211 [](const auto& app) { return !app->IsPreferred(); }),
212 available_apps_.end());
213
214 // By design, only one payment app can be preferred.
215 DCHECK_EQ(available_apps_.size(), 1u);
216 if (available_apps_.size() > 1)
217 available_apps_.resize(1);
218 }
219 }
220
gogerald8189d522017-09-15 17:52:18221 SetDefaultProfileSelections();
222
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39223 get_all_apps_finished_ = true;
Danyao Wang5a14e982020-02-12 21:34:09224 has_enrolled_instrument_ =
225 std::any_of(available_apps_.begin(), available_apps_.end(),
226 [](const auto& app) { return app->HasEnrolledInstrument(); });
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39227 are_requested_methods_supported_ |= !available_apps_.empty();
228 NotifyOnGetAllPaymentAppsFinished();
Rouslan Solomakhin9788d4b2019-04-09 13:10:23229 NotifyInitialized();
gogerald8189d522017-09-15 17:52:18230
Danyao Wang4bc0606a2018-12-27 16:54:53231 // Fulfill the pending CanMakePayment call.
Rouslan Solomakhin1dca2a922019-09-06 22:25:07232 if (can_make_payment_callback_)
Rouslan Solomakhinebf9f162020-08-27 15:28:13233 std::move(can_make_payment_callback_).Run(GetCanMakePaymentValue());
Danyao Wang4bc0606a2018-12-27 16:54:53234
Danyao Wangce175bf2018-12-21 22:35:58235 // Fulfill the pending HasEnrolledInstrument call.
236 if (has_enrolled_instrument_callback_)
Rouslan Solomakhinebf9f162020-08-27 15:28:13237 std::move(has_enrolled_instrument_callback_)
238 .Run(GetHasEnrolledInstrumentValue());
gogerald0a7ee6c2017-11-13 18:23:19239
Danyao Wangce175bf2018-12-21 22:35:58240 // Fulfill the pending AreRequestedMethodsSupported call.
gogerald0a7ee6c2017-11-13 18:23:19241 if (are_requested_methods_supported_callback_)
242 CheckRequestedMethodsSupported(
243 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18244}
245
Rouslan Solomakhinebf9f162020-08-27 15:28:13246void PaymentRequestState::SetCanMakePaymentEvenWithoutApps() {
247 can_make_payment_even_without_apps_ = true;
248}
249
sebsg695799a2017-04-11 16:29:06250void PaymentRequestState::OnPaymentResponseReady(
251 mojom::PaymentResponsePtr payment_response) {
Kyungsun Leecdbdade2020-08-25 18:06:12252 if (!delegate_)
253 return;
254
sebsg695799a2017-04-11 16:29:06255 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
256}
257
Rouslan Solomakhin68429b72019-06-27 15:12:39258void PaymentRequestState::OnPaymentResponseError(
259 const std::string& error_message) {
Kyungsun Leecdbdade2020-08-25 18:06:12260 if (!delegate_)
261 return;
262
Rouslan Solomakhin68429b72019-06-27 15:12:39263 delegate_->OnPaymentResponseError(error_message);
264}
265
sebsg7e619132017-04-27 16:07:10266void PaymentRequestState::OnSpecUpdated() {
Rouslan Solomakhin75450a42020-09-24 18:44:22267 if (!spec_)
268 return;
269
Jinho Bangcac8d9a02018-08-23 19:47:22270 autofill::AutofillProfile* selected_shipping_profile =
271 selected_shipping_profile_;
272 autofill::AutofillProfile* selected_contact_profile =
273 selected_contact_profile_;
274
275 if (spec_->current_update_reason() ==
276 PaymentRequestSpec::UpdateReason::RETRY) {
277 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
278 invalid_shipping_profile_ = selected_shipping_profile;
279 selected_shipping_profile_ = nullptr;
280 }
Jinho Bang092e7162018-09-06 23:41:19281
Jinho Bangcac8d9a02018-08-23 19:47:22282 if (spec_->has_payer_error() && selected_contact_profile) {
283 invalid_contact_profile_ = selected_contact_profile;
284 selected_contact_profile_ = nullptr;
285 }
286 }
287
Mathieu Perreault04b4c662017-06-02 13:35:13288 if (spec_->selected_shipping_option_error().empty()) {
289 selected_shipping_option_error_profile_ = nullptr;
290 } else {
Jinho Bangcac8d9a02018-08-23 19:47:22291 selected_shipping_option_error_profile_ = selected_shipping_profile;
Mathieu Perreault04b4c662017-06-02 13:35:13292 selected_shipping_profile_ = nullptr;
Jinho Bang092e7162018-09-06 23:41:19293 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
294 invalid_shipping_profile_ = selected_shipping_profile;
295 }
Mathieu Perreault04b4c662017-06-02 13:35:13296 }
Jinho Bangcac8d9a02018-08-23 19:47:22297
sebsg7e619132017-04-27 16:07:10298 is_waiting_for_merchant_validation_ = false;
299 UpdateIsReadyToPayAndNotifyObservers();
300}
301
Danyao Wang03a4cbd2019-08-15 23:47:11302void PaymentRequestState::CanMakePayment(StatusCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39303 if (!get_all_apps_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53304 DCHECK(!can_make_payment_callback_);
305 can_make_payment_callback_ = std::move(callback);
306 return;
307 }
308
Rouslan Solomakhin159e5132020-08-29 21:05:02309 PostStatusCallback(std::move(callback), GetCanMakePaymentValue());
Danyao Wangce175bf2018-12-21 22:35:58310}
311
312void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39313 if (!get_all_apps_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53314 DCHECK(!has_enrolled_instrument_callback_);
Danyao Wangce175bf2018-12-21 22:35:58315 has_enrolled_instrument_callback_ = std::move(callback);
gogerald8189d522017-09-15 17:52:18316 return;
317 }
318
Rouslan Solomakhinebf9f162020-08-27 15:28:13319 PostStatusCallback(std::move(callback), GetHasEnrolledInstrumentValue());
mathp1a5be4f2017-03-24 18:09:19320}
321
gogerald0a7ee6c2017-11-13 18:23:19322void PaymentRequestState::AreRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20323 MethodsSupportedCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39324 if (!get_all_apps_finished_) {
gogerald0a7ee6c2017-11-13 18:23:19325 are_requested_methods_supported_callback_ = std::move(callback);
326 return;
327 }
328
329 base::ThreadTaskRunnerHandle::Get()->PostTask(
330 FROM_HERE,
331 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
332 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
333}
334
Sahel Sharifyd3418222020-02-19 21:50:02335void PaymentRequestState::OnAbort() {
336 // Reset supported method callback when the merchant calls abort before
337 // OnDoneCreatingPaymentApps().
338 if (are_requested_methods_supported_callback_)
339 are_requested_methods_supported_callback_.Reset();
340}
341
gogerald0a7ee6c2017-11-13 18:23:19342void PaymentRequestState::CheckRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20343 MethodsSupportedCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39344 DCHECK(get_all_apps_finished_);
gogerald0a7ee6c2017-11-13 18:23:19345
Rouslan Solomakhin75450a42020-09-24 18:44:22346 if (!spec_)
347 return;
348
Rouslan Solomakhin1dca2a922019-09-06 22:25:07349 // Don't modify the value of |are_requested_methods_supported_|, because it's
350 // used for canMakePayment().
351 bool supported = are_requested_methods_supported_;
352 if (supported && is_show_user_gesture_ &&
Rouslan Solomakhin85b10da2019-11-05 20:03:17353 base::Contains(spec_->payment_method_identifiers_set(),
354 methods::kBasicCard) &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39355 !has_non_autofill_app_ && !has_enrolled_instrument_ &&
Rouslan Solomakhin1dca2a922019-09-06 22:25:07356 PaymentsExperimentalFeatures::IsEnabled(
357 features::kStrictHasEnrolledAutofillInstrument)) {
358 supported = false;
359 get_all_payment_apps_error_ = errors::kStrictBasicCardShowReject;
360 }
361
Liquan (Max) Gua3db8c072020-06-22 16:24:21362 if (!supported && get_all_payment_apps_error_.empty() &&
363 base::Contains(spec_->payment_method_identifiers_set(),
Rouslan Solomakhina1ff81502020-06-26 00:56:00364 methods::kGooglePlayBilling) &&
Nick Burrisfca090832020-07-28 00:17:42365 !IsInTwa()) {
Liquan (Max) Gua3db8c072020-06-22 16:24:21366 get_all_payment_apps_error_ = errors::kAppStoreMethodOnlySupportedInTwa;
367 }
368
Rouslan Solomakhin1dca2a922019-09-06 22:25:07369 std::move(callback).Run(supported, get_all_payment_apps_error_);
rouslan6e3cf7c62017-04-17 21:23:28370}
371
anthonyvd6a43b932017-05-11 18:39:27372std::string PaymentRequestState::GetAuthenticatedEmail() const {
373 return payment_request_delegate_->GetAuthenticatedEmail();
374}
375
mathpf1a7a3752017-03-15 11:23:37376void PaymentRequestState::AddObserver(Observer* observer) {
377 CHECK(observer);
378 observers_.AddObserver(observer);
379}
mathpf1a7a3752017-03-15 11:23:37380
381void PaymentRequestState::RemoveObserver(Observer* observer) {
382 observers_.RemoveObserver(observer);
383}
384
mathpf1a7a3752017-03-15 11:23:37385void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05386 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06387
Rouslan Solomakhin75450a42020-09-24 18:44:22388 if (!spec_)
389 return;
390
sebsg695799a2017-04-11 16:29:06391 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51392 response_helper_ = std::make_unique<PaymentResponseHelper>(
DongJun Kim54690d52020-09-26 12:07:54393 app_locale_, spec_, selected_app_, payment_request_delegate_,
394 selected_shipping_profile_, selected_contact_profile_,
395 weak_ptr_factory_.GetWeakPtr());
mathpf1a7a3752017-03-15 11:23:37396}
397
Rouslan Solomakhin761d65eb2019-04-29 20:08:01398void PaymentRequestState::OnPaymentAppWindowClosed() {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39399 DCHECK(selected_app_);
Rouslan Solomakhin761d65eb2019-04-29 20:08:01400 response_helper_.reset();
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39401 selected_app_->OnPaymentAppWindowClosed();
Rouslan Solomakhin761d65eb2019-04-29 20:08:01402}
403
sebsg8a93b272017-05-11 19:30:22404void PaymentRequestState::RecordUseStats() {
Sahel Sharifyfef3d922019-09-11 01:41:22405 if (ShouldShowShippingSection()) {
sebsg8a93b272017-05-11 19:30:22406 DCHECK(selected_shipping_profile_);
407 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
408 }
409
Sahel Sharifyfef3d922019-09-11 01:41:22410 if (ShouldShowContactSection()) {
sebsg8a93b272017-05-11 19:30:22411 DCHECK(selected_contact_profile_);
412
413 // If the same address was used for both contact and shipping, the stats
414 // should only be updated once.
Sahel Sharifyfef3d922019-09-11 01:41:22415 if (!ShouldShowShippingSection() || (selected_shipping_profile_->guid() !=
416 selected_contact_profile_->guid())) {
sebsg8a93b272017-05-11 19:30:22417 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
418 }
419 }
420
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39421 selected_app_->RecordUse();
sebsg8a93b272017-05-11 19:30:22422}
423
Sahel Sharifycf4e2132020-01-24 23:59:08424void PaymentRequestState::SetAvailablePaymentAppForRetry() {
425 DCHECK(selected_app_);
426 base::EraseIf(available_apps_, [this](const auto& payment_app) {
427 // Remove the app if it is not selected.
428 return payment_app.get() != selected_app_;
429 });
430 is_retry_called_ = true;
431}
432
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39433void PaymentRequestState::AddAutofillPaymentApp(
mathp24ce4cd2017-04-12 20:56:42434 bool selected,
435 const autofill::CreditCard& card) {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27436 auto app =
437 AutofillPaymentAppFactory::ConvertCardToPaymentAppIfSupportedNetwork(
438 card, weak_ptr_factory_.GetWeakPtr());
439 if (!app)
mathp24ce4cd2017-04-12 20:56:42440 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03441
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39442 available_apps_.push_back(std::move(app));
Danyao Wang25f72dc2019-10-18 05:11:32443 journey_logger_->SetEventOccurred(
444 JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
mathp24ce4cd2017-04-12 20:56:42445
Sahel Sharifybc4173f2019-05-09 21:03:57446 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18447 SetSelectedApp(available_apps_.back().get());
Sahel Sharifybc4173f2019-05-09 21:03:57448 }
mathp24ce4cd2017-04-12 20:56:42449}
450
madf9904ea2017-04-25 18:39:12451void PaymentRequestState::AddAutofillShippingProfile(
452 bool selected,
453 const autofill::AutofillProfile& profile) {
454 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51455 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12456 // TODO(tmartino): Implement deduplication rules specific to shipping
457 // profiles.
458 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
459 shipping_profiles_.push_back(new_cached_profile);
460
Sahel Sharifybc4173f2019-05-09 21:03:57461 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18462 SetSelectedShippingProfile(new_cached_profile);
Sahel Sharifybc4173f2019-05-09 21:03:57463 }
madf9904ea2017-04-25 18:39:12464}
465
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23466void PaymentRequestState::AddAutofillContactProfile(
467 bool selected,
468 const autofill::AutofillProfile& profile) {
469 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51470 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23471 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
472 contact_profiles_.push_back(new_cached_profile);
473
Sahel Sharifybc4173f2019-05-09 21:03:57474 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18475 SetSelectedContactProfile(new_cached_profile);
Sahel Sharifybc4173f2019-05-09 21:03:57476 }
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23477}
478
anthonyvd0116ce332017-03-21 21:29:01479void PaymentRequestState::SetSelectedShippingOption(
mathp151bd312017-04-03 21:07:24480 const std::string& shipping_option_id) {
Rouslan Solomakhin75450a42020-09-24 18:44:22481 if (!spec_)
482 return;
483
anthonyvd2f30baa12017-04-13 22:30:50484 spec_->StartWaitingForUpdateWith(
485 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
Kyungsun Leecdbdade2020-08-25 18:06:12486 if (delegate_) {
487 // This will inform the merchant and will lead to them calling updateWith
488 // with new PaymentDetails.
489 delegate_->OnShippingOptionIdSelected(shipping_option_id);
490 }
anthonyvd0116ce332017-03-21 21:29:01491}
492
mathpf1a7a3752017-03-15 11:23:37493void PaymentRequestState::SetSelectedShippingProfile(
Danyao Wang46e7d942020-09-25 15:45:18494 autofill::AutofillProfile* profile) {
Rouslan Solomakhin75450a42020-09-24 18:44:22495 if (!spec_)
496 return;
497
anthonyvd2f30baa12017-04-13 22:30:50498 spec_->StartWaitingForUpdateWith(
499 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37500 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10501
Jinho Bangcac8d9a02018-08-23 19:47:22502 // Changing the shipping address clears shipping address validation errors
503 // from retry().
504 invalid_shipping_profile_ = nullptr;
505
sebsg7e619132017-04-27 16:07:10506 // The user should not be able to click on pay until the callback from the
507 // merchant.
508 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10509
510 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f2017-10-23 20:28:39511 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29512 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00513 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
514 weak_ptr_factory_.GetWeakPtr()));
mathpf1a7a3752017-03-15 11:23:37515}
516
517void PaymentRequestState::SetSelectedContactProfile(
Danyao Wang46e7d942020-09-25 15:45:18518 autofill::AutofillProfile* profile) {
mathpf1a7a3752017-03-15 11:23:37519 selected_contact_profile_ = profile;
Jinho Bangcac8d9a02018-08-23 19:47:22520
521 // Changing the contact information clears contact information validation
522 // errors from retry().
523 invalid_contact_profile_ = nullptr;
524
mathpf1a7a3752017-03-15 11:23:37525 UpdateIsReadyToPayAndNotifyObservers();
Jinho Bangbb178152018-09-13 09:44:43526
Kyungsun Leecdbdade2020-08-25 18:06:12527 if (IsPaymentAppInvoked() && delegate_) {
Jinho Bang21d6be92018-12-18 15:30:31528 delegate_->OnPayerInfoSelected(
529 response_helper_->GeneratePayerDetail(profile));
Jinho Bangbb178152018-09-13 09:44:43530 }
mathpf1a7a3752017-03-15 11:23:37531}
532
Danyao Wang46e7d942020-09-25 15:45:18533void PaymentRequestState::SetSelectedApp(PaymentApp* app) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39534 selected_app_ = app;
mathpf1a7a3752017-03-15 11:23:37535 UpdateIsReadyToPayAndNotifyObservers();
536}
537
mathpc0d616a2017-03-15 14:09:33538const std::string& PaymentRequestState::GetApplicationLocale() {
539 return app_locale_;
540}
541
542autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
543 return personal_data_manager_;
544}
545
mad763ed2b2017-04-24 20:28:47546autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
547 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38548}
549
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56550bool PaymentRequestState::IsPaymentAppInvoked() const {
551 return !!response_helper_;
552}
553
Mathieu Perreaulteea046d12017-09-28 15:51:21554autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45555 return payment_request_delegate_->GetAddressNormalizer();
556}
557
Rouslan Solomakhin48fd6e872019-02-22 17:23:10558bool PaymentRequestState::IsInitialized() const {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39559 return get_all_apps_finished_;
Rouslan Solomakhin48fd6e872019-02-22 17:23:10560}
561
Rouslan Solomakhin9788d4b2019-04-09 13:10:23562void PaymentRequestState::SelectDefaultShippingAddressAndNotifyObservers() {
563 // Only pre-select an address if the merchant provided at least one selected
564 // shipping option, and the top profile is complete. Assumes that profiles
565 // have already been sorted for completeness and frecency.
Rouslan Solomakhin75450a42020-09-24 18:44:22566 if (!shipping_profiles().empty() && spec_ &&
567 spec_->selected_shipping_option() &&
Rouslan Solomakhin9788d4b2019-04-09 13:10:23568 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
569 selected_shipping_profile_ = shipping_profiles()[0];
570 }
Sahel Sharify6efdfb32019-07-02 16:12:16571 // Record the missing required fields (if any) of the most complete shipping
572 // profile.
573 profile_comparator()->RecordMissingFieldsOfShippingProfile(
574 shipping_profiles().empty() ? nullptr : shipping_profiles()[0]);
Rouslan Solomakhin9788d4b2019-04-09 13:10:23575 UpdateIsReadyToPayAndNotifyObservers();
576}
577
Sahel Sharifyfef3d922019-09-11 01:41:22578bool PaymentRequestState::ShouldShowShippingSection() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22579 if (!spec_ || !spec_->request_shipping())
Sahel Sharifyfef3d922019-09-11 01:41:22580 return false;
581
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39582 return selected_app_ ? !selected_app_->HandlesShippingAddress() : true;
Sahel Sharifyfef3d922019-09-11 01:41:22583}
584
585bool PaymentRequestState::ShouldShowContactSection() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22586 if (!spec_)
587 return false;
588
Sahel Sharifyfef3d922019-09-11 01:41:22589 if (spec_->request_payer_name() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39590 (!selected_app_ || !selected_app_->HandlesPayerName())) {
Sahel Sharifyfef3d922019-09-11 01:41:22591 return true;
592 }
593 if (spec_->request_payer_email() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39594 (!selected_app_ || !selected_app_->HandlesPayerEmail())) {
Sahel Sharifyfef3d922019-09-11 01:41:22595 return true;
596 }
597 if (spec_->request_payer_phone() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39598 (!selected_app_ || !selected_app_->HandlesPayerPhone())) {
Sahel Sharifyfef3d922019-09-11 01:41:22599 return true;
600 }
601
602 return false;
603}
604
Rouslan Solomakhin65552292019-08-29 17:28:21605base::WeakPtr<PaymentRequestState> PaymentRequestState::AsWeakPtr() {
606 return weak_ptr_factory_.GetWeakPtr();
607}
608
mathpf1a7a3752017-03-15 11:23:37609void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37610 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33611 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37612
tmartinocd131b32017-05-24 19:40:59613 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
614 raw_profiles_for_filtering.reserve(profiles.size());
615
mathpf1a7a3752017-03-15 11:23:37616 // PaymentRequest may outlive the Profiles returned by the Data Manager.
617 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30618 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37619 for (size_t i = 0; i < profiles.size(); i++) {
620 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51621 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59622 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37623 }
624
tmartino01c3eb82017-04-29 15:18:39625 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
626 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59627 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
628 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24629
sebsgc6719b32017-07-05 19:54:47630 // Set the number of suggestions shown for the sections requested by the
631 // merchant.
Sahel Sharifyfef3d922019-09-11 01:41:22632 if (ShouldShowContactSection()) {
sebsgce700484d2017-07-19 23:25:38633 bool has_complete_contact =
634 contact_profiles_.empty()
635 ? false
636 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
Rouslan Solomakhincb29c4f2019-08-16 22:49:39637 is_requested_autofill_data_available_ &= has_complete_contact;
sebsgc6719b32017-07-05 19:54:47638 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38639 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
640 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47641 }
Sahel Sharifyfef3d922019-09-11 01:41:22642 if (ShouldShowShippingSection()) {
sebsgce700484d2017-07-19 23:25:38643 bool has_complete_shipping =
644 shipping_profiles_.empty()
645 ? false
646 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
Rouslan Solomakhincb29c4f2019-08-16 22:49:39647 is_requested_autofill_data_available_ &= has_complete_shipping;
sebsgc6719b32017-07-05 19:54:47648 journey_logger_->SetNumberOfSuggestionsShown(
649 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38650 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47651 }
mathpf1a7a3752017-03-15 11:23:37652}
653
654void PaymentRequestState::SetDefaultProfileSelections() {
mathpf14c1e32017-05-12 16:37:30655 // Contact profiles were ordered by completeness in addition to frecency;
656 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59657 if (!contact_profiles().empty() &&
658 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37659 selected_contact_profile_ = contact_profiles()[0];
660
Sahel Sharify6efdfb32019-07-02 16:12:16661 // Record the missing required fields (if any) of the most complete contact
662 // profile.
663 profile_comparator()->RecordMissingFieldsOfContactProfile(
664 contact_profiles().empty() ? nullptr : contact_profiles()[0]);
665
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39666 // Sort apps.
667 PaymentApp::SortApps(&available_apps_);
Sahel Sharify13331e82019-07-12 01:00:30668
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39669 selected_app_ = nullptr;
Sahel Sharify90307872019-12-02 17:28:14670 if (!available_apps_.empty() && available_apps_[0]->CanPreselect()) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39671 selected_app_ = available_apps_[0].get();
Sahel Sharify9be7b292020-03-13 17:37:46672 UpdateIsReadyToPayAndNotifyObservers();
Sahel Sharify13331e82019-07-12 01:00:30673 }
Rouslan Solomakhin9788d4b2019-04-09 13:10:23674
Sahel Sharify6efdfb32019-07-02 16:12:16675 // Record the missing required payment fields when no complete payment
676 // info exists.
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39677 if (available_apps_.empty()) {
Rouslan Solomakhin75450a42020-09-24 18:44:22678 if (spec_ && spec_->supports_basic_card()) {
Sahel Sharify6efdfb32019-07-02 16:12:16679 // All fields are missing when basic-card is requested but no card exits.
680 base::UmaHistogramSparse("PaymentRequest.MissingPaymentFields",
Sahel Sharify13331e82019-07-12 01:00:30681 CREDIT_CARD_EXPIRED | CREDIT_CARD_NO_CARDHOLDER |
682 CREDIT_CARD_NO_NUMBER |
683 CREDIT_CARD_NO_BILLING_ADDRESS);
Sahel Sharify6efdfb32019-07-02 16:12:16684 }
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39685 } else if (available_apps_[0]->type() == PaymentApp::Type::AUTOFILL) {
686 // Record the missing fields (if any) of the most complete app when
687 // it's autofill based. SW based apps are always complete.
688 static_cast<const AutofillPaymentApp*>(available_apps_[0].get())
689 ->RecordMissingFieldsForApp();
Sahel Sharify6efdfb32019-07-02 16:12:16690 }
gogerald8189d522017-09-15 17:52:18691
Sahel Sharify6efdfb32019-07-02 16:12:16692 SelectDefaultShippingAddressAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18693
694 journey_logger_->SetNumberOfSuggestionsShown(
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39695 JourneyLogger::Section::SECTION_PAYMENT_METHOD, available_apps().size(),
696 selected_app_);
mathpf1a7a3752017-03-15 11:23:37697}
698
699void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
700 is_ready_to_pay_ =
701 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
702 NotifyOnSelectedInformationChanged();
703}
704
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39705void PaymentRequestState::NotifyOnGetAllPaymentAppsFinished() {
gogerald8189d522017-09-15 17:52:18706 for (auto& observer : observers_)
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39707 observer.OnGetAllPaymentAppsFinished();
gogerald8189d522017-09-15 17:52:18708}
709
mathpf1a7a3752017-03-15 11:23:37710void PaymentRequestState::NotifyOnSelectedInformationChanged() {
711 for (auto& observer : observers_)
712 observer.OnSelectedInformationChanged();
713}
714
715bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05716 // There is no need to check for supported networks, because only supported
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39717 // apps are listed/created in the flow.
718 return selected_app_ != nullptr && selected_app_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37719}
720
721bool PaymentRequestState::ArePaymentOptionsSatisfied() {
Rouslan Solomakhin75450a42020-09-24 18:44:22722 if (is_waiting_for_merchant_validation_ || !spec_)
sebsg7e619132017-04-27 16:07:10723 return false;
724
Sahel Sharifyfef3d922019-09-11 01:41:22725 if (ShouldShowShippingSection() &&
726 (!spec_->selected_shipping_option() ||
727 !profile_comparator()->IsShippingComplete(selected_shipping_profile_))) {
tmartino01c3eb82017-04-29 15:18:39728 return false;
Sahel Sharifyfef3d922019-09-11 01:41:22729 }
tmartino01c3eb82017-04-29 15:18:39730
Sahel Sharifyfef3d922019-09-11 01:41:22731 if (ShouldShowContactSection() &&
732 !profile_comparator()->IsContactInfoComplete(selected_contact_profile_)) {
Anthony Vallee-Duboisa8814672017-06-01 18:43:20733 return false;
Sahel Sharifyfef3d922019-09-11 01:41:22734 }
Anthony Vallee-Duboisa8814672017-06-01 18:43:20735
Sahel Sharifyfef3d922019-09-11 01:41:22736 return true;
mathpf1a7a3752017-03-15 11:23:37737}
738
Mathieu Perreault17c1ae92017-10-20 17:16:00739void PaymentRequestState::OnAddressNormalized(
740 bool success,
741 const autofill::AutofillProfile& normalized_profile) {
Kyungsun Leecdbdade2020-08-25 18:06:12742 if (!delegate_)
743 return;
744
Mathieu Perreault17c1ae92017-10-20 17:16:00745 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22746 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
747 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00748}
749
Nick Burrisfca090832020-07-28 00:17:42750bool PaymentRequestState::IsInTwa() const {
751 return !payment_request_delegate_->GetTwaPackageName().empty();
752}
753
Rouslan Solomakhinebf9f162020-08-27 15:28:13754bool PaymentRequestState::GetCanMakePaymentValue() const {
755 return are_requested_methods_supported_ ||
756 can_make_payment_even_without_apps_;
757}
758
759bool PaymentRequestState::GetHasEnrolledInstrumentValue() const {
760 return has_enrolled_instrument_ || can_make_payment_even_without_apps_;
761}
762
mathpf1a7a3752017-03-15 11:23:37763} // namespace payments