blob: 413e180a5ffacad8aa451a39b4454e4d87c770b9 [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"
gogerald8189d522017-09-15 17:52:1837#include "content/public/common/content_features.h"
mathpf1a7a3752017-03-15 11:23:3738
39namespace payments {
Rouslan Solomakhin1dca2a922019-09-06 22:25:0740namespace {
41
Rouslan Solomakhin1dca2a922019-09-06 22:25:0742// Invokes the |callback| with |status|.
43void CallStatusCallback(PaymentRequestState::StatusCallback callback,
44 bool status) {
45 std::move(callback).Run(status);
46}
47
48// Posts the |callback| to be invoked with |status| asynchronously.
49void PostStatusCallback(PaymentRequestState::StatusCallback callback,
50 bool status) {
51 base::ThreadTaskRunnerHandle::Get()->PostTask(
52 FROM_HERE,
53 base::BindOnce(&CallStatusCallback, std::move(callback), status));
54}
55
56} // namespace
mathpf1a7a3752017-03-15 11:23:3757
mathpc0d616a2017-03-15 14:09:3358PaymentRequestState::PaymentRequestState(
Rouslan Solomakhindbf593d92017-11-21 19:20:5759 content::WebContents* web_contents,
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 Solomakhin6d4c1c272019-11-22 17:09:2770 : web_contents_(web_contents),
Danyao Wang4f2ba632020-03-11 13:56:5471 initiator_render_frame_host_(initiator_render_frame_host),
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2772 top_origin_(top_level_origin),
73 frame_origin_(frame_origin),
Rouslan Solomakhinc71cca622020-01-31 22:15:3574 frame_security_origin_(frame_security_origin),
mathpc0d616a2017-03-15 14:09:3375 app_locale_(app_locale),
DongJun Kim54690d52020-09-26 12:07:5476 spec_(spec),
mathpf1a7a3752017-03-15 11:23:3777 delegate_(delegate),
mathpc0d616a2017-03-15 14:09:3378 personal_data_manager_(personal_data_manager),
sebsgc6719b32017-07-05 19:54:4779 journey_logger_(journey_logger),
Rouslan Solomakhind2cae95a2018-08-09 00:16:1080 are_requested_methods_supported_(
81 !spec_->supported_card_networks().empty()),
tmartino01c3eb82017-04-29 15:18:3982 payment_request_delegate_(payment_request_delegate),
Jeremy Roman5c341f6d2019-07-15 15:56:1083 profile_comparator_(app_locale, *spec) {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2784 PopulateProfileCache();
Danyao Wang761739b2019-06-27 23:59:3285
Rouslan Solomakhin6d4c1c272019-11-22 17:09:2786 // |web_contents_| is null in unit tests.
Danyao Wange865a302020-04-01 18:35:1487 PaymentAppService* service = PaymentAppServiceFactory::GetForContext(
88 web_contents_ ? web_contents_->GetBrowserContext() : nullptr);
89 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() {
98 return web_contents_;
gogeraldac15d2362017-11-15 01:04:1999}
100
Danyao Wangaed5b0a92020-04-01 22:43:14101ContentPaymentRequestDelegate* PaymentRequestState::GetPaymentRequestDelegate()
102 const {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27103 return payment_request_delegate_;
104}
Rouslan Solomakhin1dca2a922019-09-06 22:25:07105
Rouslan Solomakhin535fe302020-06-02 20:17:39106void PaymentRequestState::ShowProcessingSpinner() {
107 GetPaymentRequestDelegate()->ShowProcessingSpinner();
108}
109
DongJun Kim54690d52020-09-26 12:07:54110base::WeakPtr<PaymentRequestSpec> PaymentRequestState::GetSpec() const {
111 return spec_;
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27112}
gogeraldac15d2362017-11-15 01:04:19113
Rouslan Solomakhincbdeef92020-08-15 12:39:30114std::string PaymentRequestState::GetTwaPackageName() const {
115 return GetPaymentRequestDelegate()->GetTwaPackageName();
116}
117
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27118const GURL& PaymentRequestState::GetTopOrigin() {
119 return top_origin_;
120}
121
122const GURL& PaymentRequestState::GetFrameOrigin() {
123 return frame_origin_;
124}
125
Rouslan Solomakhinc71cca622020-01-31 22:15:35126const url::Origin& PaymentRequestState::GetFrameSecurityOrigin() {
127 return frame_security_origin_;
128}
129
Danyao Wang4f2ba632020-03-11 13:56:54130content::RenderFrameHost* PaymentRequestState::GetInitiatorRenderFrameHost()
131 const {
132 return initiator_render_frame_host_;
133}
134
Danyao Wangaed5b0a92020-04-01 22:43:14135const std::vector<mojom::PaymentMethodDataPtr>&
136PaymentRequestState::GetMethodData() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22137 DCHECK(GetSpec());
Danyao Wangaed5b0a92020-04-01 22:43:14138 return GetSpec()->method_data();
139}
140
Rouslan Solomakhin914686c52020-08-21 15:15:41141std::unique_ptr<autofill::InternalAuthenticator>
142PaymentRequestState::CreateInternalAuthenticator() const {
Rouslan Solomakhin54e0d1e2020-08-30 20:23:31143 return GetPaymentRequestDelegate()->CreateInternalAuthenticator();
Rouslan Solomakhin914686c52020-08-21 15:15:41144}
145
Danyao Wangaed5b0a92020-04-01 22:43:14146scoped_refptr<PaymentManifestWebDataService>
147PaymentRequestState::GetPaymentManifestWebDataService() const {
148 return GetPaymentRequestDelegate()->GetPaymentManifestWebDataService();
149}
150
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27151const std::vector<autofill::AutofillProfile*>&
152PaymentRequestState::GetBillingProfiles() {
153 return shipping_profiles_;
154}
155
156bool PaymentRequestState::IsRequestedAutofillDataAvailable() {
157 return is_requested_autofill_data_available_;
158}
159
160bool PaymentRequestState::MayCrawlForInstallablePaymentApps() {
161 return PaymentsExperimentalFeatures::IsEnabled(
162 features::kAlwaysAllowJustInTimePaymentApp) ||
Rouslan Solomakhin75450a42020-09-24 18:44:22163 !spec_ || !spec_->supports_basic_card();
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27164}
165
Rouslan Solomakhin535fe302020-06-02 20:17:39166bool PaymentRequestState::IsOffTheRecord() const {
167 return GetPaymentRequestDelegate()->IsOffTheRecord();
168}
169
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27170void PaymentRequestState::OnPaymentAppCreated(std::unique_ptr<PaymentApp> app) {
171 if (app->type() == PaymentApp::Type::AUTOFILL) {
172 journey_logger_->SetEventOccurred(
173 JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
174 } else if (base::Contains(app->GetAppMethodNames(), methods::kGooglePay) ||
175 base::Contains(app->GetAppMethodNames(), methods::kAndroidPay)) {
Danyao Wang25f72dc2019-10-18 05:11:32176 journey_logger_->SetEventOccurred(
177 JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE);
178 } else {
179 journey_logger_->SetEventOccurred(
180 JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER);
181 }
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27182 available_apps_.emplace_back(std::move(app));
gogeraldac15d2362017-11-15 01:04:19183}
184
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27185void PaymentRequestState::OnPaymentAppCreationError(
186 const std::string& error_message) {
187 get_all_payment_apps_error_ = error_message;
188}
189
Danyao Wangaed5b0a92020-04-01 22:43:14190bool PaymentRequestState::SkipCreatingNativePaymentApps() const {
191 return false;
192}
193
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27194void PaymentRequestState::OnDoneCreatingPaymentApps() {
195 DCHECK_NE(0U, number_of_payment_app_factories_);
196 if (--number_of_payment_app_factories_ > 0U)
197 return;
198
Nick Burrisfca090832020-07-28 00:17:42199 if (IsInTwa()) {
200 // If a preferred payment app is present (e.g. Play Billing within a TWA),
201 // all other payment apps are ignored.
202 bool has_preferred_app =
203 std::any_of(available_apps_.begin(), available_apps_.end(),
204 [](const auto& app) { return app->IsPreferred(); });
205 if (has_preferred_app) {
206 available_apps_.erase(
207 std::remove_if(available_apps_.begin(), available_apps_.end(),
208 [](const auto& app) { return !app->IsPreferred(); }),
209 available_apps_.end());
210
211 // By design, only one payment app can be preferred.
212 DCHECK_EQ(available_apps_.size(), 1u);
213 if (available_apps_.size() > 1)
214 available_apps_.resize(1);
215 }
216 }
217
gogerald8189d522017-09-15 17:52:18218 SetDefaultProfileSelections();
219
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39220 get_all_apps_finished_ = true;
Danyao Wang5a14e982020-02-12 21:34:09221 has_enrolled_instrument_ =
222 std::any_of(available_apps_.begin(), available_apps_.end(),
223 [](const auto& app) { return app->HasEnrolledInstrument(); });
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39224 are_requested_methods_supported_ |= !available_apps_.empty();
225 NotifyOnGetAllPaymentAppsFinished();
Rouslan Solomakhin9788d4b2019-04-09 13:10:23226 NotifyInitialized();
gogerald8189d522017-09-15 17:52:18227
Danyao Wang4bc0606a2018-12-27 16:54:53228 // Fulfill the pending CanMakePayment call.
Rouslan Solomakhin1dca2a922019-09-06 22:25:07229 if (can_make_payment_callback_)
Rouslan Solomakhinebf9f162020-08-27 15:28:13230 std::move(can_make_payment_callback_).Run(GetCanMakePaymentValue());
Danyao Wang4bc0606a2018-12-27 16:54:53231
Danyao Wangce175bf2018-12-21 22:35:58232 // Fulfill the pending HasEnrolledInstrument call.
233 if (has_enrolled_instrument_callback_)
Rouslan Solomakhinebf9f162020-08-27 15:28:13234 std::move(has_enrolled_instrument_callback_)
235 .Run(GetHasEnrolledInstrumentValue());
gogerald0a7ee6c2017-11-13 18:23:19236
Danyao Wangce175bf2018-12-21 22:35:58237 // Fulfill the pending AreRequestedMethodsSupported call.
gogerald0a7ee6c2017-11-13 18:23:19238 if (are_requested_methods_supported_callback_)
239 CheckRequestedMethodsSupported(
240 std::move(are_requested_methods_supported_callback_));
gogerald8189d522017-09-15 17:52:18241}
242
Rouslan Solomakhinebf9f162020-08-27 15:28:13243void PaymentRequestState::SetCanMakePaymentEvenWithoutApps() {
244 can_make_payment_even_without_apps_ = true;
245}
246
sebsg695799a2017-04-11 16:29:06247void PaymentRequestState::OnPaymentResponseReady(
248 mojom::PaymentResponsePtr payment_response) {
Kyungsun Leecdbdade2020-08-25 18:06:12249 if (!delegate_)
250 return;
251
sebsg695799a2017-04-11 16:29:06252 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
253}
254
Rouslan Solomakhin68429b72019-06-27 15:12:39255void PaymentRequestState::OnPaymentResponseError(
256 const std::string& error_message) {
Kyungsun Leecdbdade2020-08-25 18:06:12257 if (!delegate_)
258 return;
259
Rouslan Solomakhin68429b72019-06-27 15:12:39260 delegate_->OnPaymentResponseError(error_message);
261}
262
sebsg7e619132017-04-27 16:07:10263void PaymentRequestState::OnSpecUpdated() {
Rouslan Solomakhin75450a42020-09-24 18:44:22264 if (!spec_)
265 return;
266
Jinho Bangcac8d9a02018-08-23 19:47:22267 autofill::AutofillProfile* selected_shipping_profile =
268 selected_shipping_profile_;
269 autofill::AutofillProfile* selected_contact_profile =
270 selected_contact_profile_;
271
272 if (spec_->current_update_reason() ==
273 PaymentRequestSpec::UpdateReason::RETRY) {
274 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
275 invalid_shipping_profile_ = selected_shipping_profile;
276 selected_shipping_profile_ = nullptr;
277 }
Jinho Bang092e7162018-09-06 23:41:19278
Jinho Bangcac8d9a02018-08-23 19:47:22279 if (spec_->has_payer_error() && selected_contact_profile) {
280 invalid_contact_profile_ = selected_contact_profile;
281 selected_contact_profile_ = nullptr;
282 }
283 }
284
Mathieu Perreault04b4c662017-06-02 13:35:13285 if (spec_->selected_shipping_option_error().empty()) {
286 selected_shipping_option_error_profile_ = nullptr;
287 } else {
Jinho Bangcac8d9a02018-08-23 19:47:22288 selected_shipping_option_error_profile_ = selected_shipping_profile;
Mathieu Perreault04b4c662017-06-02 13:35:13289 selected_shipping_profile_ = nullptr;
Jinho Bang092e7162018-09-06 23:41:19290 if (spec_->has_shipping_address_error() && selected_shipping_profile) {
291 invalid_shipping_profile_ = selected_shipping_profile;
292 }
Mathieu Perreault04b4c662017-06-02 13:35:13293 }
Jinho Bangcac8d9a02018-08-23 19:47:22294
sebsg7e619132017-04-27 16:07:10295 is_waiting_for_merchant_validation_ = false;
296 UpdateIsReadyToPayAndNotifyObservers();
297}
298
Danyao Wang03a4cbd2019-08-15 23:47:11299void PaymentRequestState::CanMakePayment(StatusCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39300 if (!get_all_apps_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53301 DCHECK(!can_make_payment_callback_);
302 can_make_payment_callback_ = std::move(callback);
303 return;
304 }
305
Rouslan Solomakhin159e5132020-08-29 21:05:02306 PostStatusCallback(std::move(callback), GetCanMakePaymentValue());
Danyao Wangce175bf2018-12-21 22:35:58307}
308
309void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39310 if (!get_all_apps_finished_) {
Danyao Wang4bc0606a2018-12-27 16:54:53311 DCHECK(!has_enrolled_instrument_callback_);
Danyao Wangce175bf2018-12-21 22:35:58312 has_enrolled_instrument_callback_ = std::move(callback);
gogerald8189d522017-09-15 17:52:18313 return;
314 }
315
Rouslan Solomakhinebf9f162020-08-27 15:28:13316 PostStatusCallback(std::move(callback), GetHasEnrolledInstrumentValue());
mathp1a5be4f2017-03-24 18:09:19317}
318
gogerald0a7ee6c2017-11-13 18:23:19319void PaymentRequestState::AreRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20320 MethodsSupportedCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39321 if (!get_all_apps_finished_) {
gogerald0a7ee6c2017-11-13 18:23:19322 are_requested_methods_supported_callback_ = std::move(callback);
323 return;
324 }
325
326 base::ThreadTaskRunnerHandle::Get()->PostTask(
327 FROM_HERE,
328 base::BindOnce(&PaymentRequestState::CheckRequestedMethodsSupported,
329 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
330}
331
Sahel Sharifyd3418222020-02-19 21:50:02332void PaymentRequestState::OnAbort() {
333 // Reset supported method callback when the merchant calls abort before
334 // OnDoneCreatingPaymentApps().
335 if (are_requested_methods_supported_callback_)
336 are_requested_methods_supported_callback_.Reset();
337}
338
gogerald0a7ee6c2017-11-13 18:23:19339void PaymentRequestState::CheckRequestedMethodsSupported(
Rouslan Solomakhind5dcc322019-07-11 21:47:20340 MethodsSupportedCallback callback) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39341 DCHECK(get_all_apps_finished_);
gogerald0a7ee6c2017-11-13 18:23:19342
Rouslan Solomakhin75450a42020-09-24 18:44:22343 if (!spec_)
344 return;
345
Rouslan Solomakhin1dca2a922019-09-06 22:25:07346 // Don't modify the value of |are_requested_methods_supported_|, because it's
347 // used for canMakePayment().
348 bool supported = are_requested_methods_supported_;
349 if (supported && is_show_user_gesture_ &&
Rouslan Solomakhin85b10da2019-11-05 20:03:17350 base::Contains(spec_->payment_method_identifiers_set(),
351 methods::kBasicCard) &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39352 !has_non_autofill_app_ && !has_enrolled_instrument_ &&
Rouslan Solomakhin1dca2a922019-09-06 22:25:07353 PaymentsExperimentalFeatures::IsEnabled(
354 features::kStrictHasEnrolledAutofillInstrument)) {
355 supported = false;
356 get_all_payment_apps_error_ = errors::kStrictBasicCardShowReject;
357 }
358
Liquan (Max) Gua3db8c072020-06-22 16:24:21359 if (!supported && get_all_payment_apps_error_.empty() &&
360 base::Contains(spec_->payment_method_identifiers_set(),
Rouslan Solomakhina1ff81502020-06-26 00:56:00361 methods::kGooglePlayBilling) &&
Nick Burrisfca090832020-07-28 00:17:42362 !IsInTwa()) {
Liquan (Max) Gua3db8c072020-06-22 16:24:21363 get_all_payment_apps_error_ = errors::kAppStoreMethodOnlySupportedInTwa;
364 }
365
Rouslan Solomakhin1dca2a922019-09-06 22:25:07366 std::move(callback).Run(supported, get_all_payment_apps_error_);
rouslan6e3cf7c62017-04-17 21:23:28367}
368
anthonyvd6a43b932017-05-11 18:39:27369std::string PaymentRequestState::GetAuthenticatedEmail() const {
370 return payment_request_delegate_->GetAuthenticatedEmail();
371}
372
mathpf1a7a3752017-03-15 11:23:37373void PaymentRequestState::AddObserver(Observer* observer) {
374 CHECK(observer);
375 observers_.AddObserver(observer);
376}
mathpf1a7a3752017-03-15 11:23:37377
378void PaymentRequestState::RemoveObserver(Observer* observer) {
379 observers_.RemoveObserver(observer);
380}
381
mathpf1a7a3752017-03-15 11:23:37382void PaymentRequestState::GeneratePaymentResponse() {
mathp363735b2017-03-16 18:08:05383 DCHECK(is_ready_to_pay());
sebsg695799a2017-04-11 16:29:06384
Rouslan Solomakhin75450a42020-09-24 18:44:22385 if (!spec_)
386 return;
387
sebsg695799a2017-04-11 16:29:06388 // Once the response is ready, will call back into OnPaymentResponseReady.
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51389 response_helper_ = std::make_unique<PaymentResponseHelper>(
DongJun Kim54690d52020-09-26 12:07:54390 app_locale_, spec_, selected_app_, payment_request_delegate_,
391 selected_shipping_profile_, selected_contact_profile_,
392 weak_ptr_factory_.GetWeakPtr());
mathpf1a7a3752017-03-15 11:23:37393}
394
Rouslan Solomakhin761d65eb2019-04-29 20:08:01395void PaymentRequestState::OnPaymentAppWindowClosed() {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39396 DCHECK(selected_app_);
Rouslan Solomakhin761d65eb2019-04-29 20:08:01397 response_helper_.reset();
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39398 selected_app_->OnPaymentAppWindowClosed();
Rouslan Solomakhin761d65eb2019-04-29 20:08:01399}
400
sebsg8a93b272017-05-11 19:30:22401void PaymentRequestState::RecordUseStats() {
Sahel Sharifyfef3d922019-09-11 01:41:22402 if (ShouldShowShippingSection()) {
sebsg8a93b272017-05-11 19:30:22403 DCHECK(selected_shipping_profile_);
404 personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
405 }
406
Sahel Sharifyfef3d922019-09-11 01:41:22407 if (ShouldShowContactSection()) {
sebsg8a93b272017-05-11 19:30:22408 DCHECK(selected_contact_profile_);
409
410 // If the same address was used for both contact and shipping, the stats
411 // should only be updated once.
Sahel Sharifyfef3d922019-09-11 01:41:22412 if (!ShouldShowShippingSection() || (selected_shipping_profile_->guid() !=
413 selected_contact_profile_->guid())) {
sebsg8a93b272017-05-11 19:30:22414 personal_data_manager_->RecordUseOf(*selected_contact_profile_);
415 }
416 }
417
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39418 selected_app_->RecordUse();
sebsg8a93b272017-05-11 19:30:22419}
420
Sahel Sharifycf4e2132020-01-24 23:59:08421void PaymentRequestState::SetAvailablePaymentAppForRetry() {
422 DCHECK(selected_app_);
423 base::EraseIf(available_apps_, [this](const auto& payment_app) {
424 // Remove the app if it is not selected.
425 return payment_app.get() != selected_app_;
426 });
427 is_retry_called_ = true;
428}
429
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39430void PaymentRequestState::AddAutofillPaymentApp(
mathp24ce4cd2017-04-12 20:56:42431 bool selected,
432 const autofill::CreditCard& card) {
Rouslan Solomakhin6d4c1c272019-11-22 17:09:27433 auto app =
434 AutofillPaymentAppFactory::ConvertCardToPaymentAppIfSupportedNetwork(
435 card, weak_ptr_factory_.GetWeakPtr());
436 if (!app)
mathp24ce4cd2017-04-12 20:56:42437 return;
Rouslan Solomakhin25d708b2017-06-23 17:12:03438
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39439 available_apps_.push_back(std::move(app));
Danyao Wang25f72dc2019-10-18 05:11:32440 journey_logger_->SetEventOccurred(
441 JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD);
mathp24ce4cd2017-04-12 20:56:42442
Sahel Sharifybc4173f2019-05-09 21:03:57443 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18444 SetSelectedApp(available_apps_.back().get());
Sahel Sharifybc4173f2019-05-09 21:03:57445 }
mathp24ce4cd2017-04-12 20:56:42446}
447
madf9904ea2017-04-25 18:39:12448void PaymentRequestState::AddAutofillShippingProfile(
449 bool selected,
450 const autofill::AutofillProfile& profile) {
451 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51452 std::make_unique<autofill::AutofillProfile>(profile));
madf9904ea2017-04-25 18:39:12453 // TODO(tmartino): Implement deduplication rules specific to shipping
454 // profiles.
455 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
456 shipping_profiles_.push_back(new_cached_profile);
457
Sahel Sharifybc4173f2019-05-09 21:03:57458 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18459 SetSelectedShippingProfile(new_cached_profile);
Sahel Sharifybc4173f2019-05-09 21:03:57460 }
madf9904ea2017-04-25 18:39:12461}
462
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23463void PaymentRequestState::AddAutofillContactProfile(
464 bool selected,
465 const autofill::AutofillProfile& profile) {
466 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51467 std::make_unique<autofill::AutofillProfile>(profile));
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23468 autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get();
469 contact_profiles_.push_back(new_cached_profile);
470
Sahel Sharifybc4173f2019-05-09 21:03:57471 if (selected) {
Danyao Wang46e7d942020-09-25 15:45:18472 SetSelectedContactProfile(new_cached_profile);
Sahel Sharifybc4173f2019-05-09 21:03:57473 }
Anthony Vallee-Duboisf1e88b42017-05-15 15:09:23474}
475
anthonyvd0116ce332017-03-21 21:29:01476void PaymentRequestState::SetSelectedShippingOption(
mathp151bd312017-04-03 21:07:24477 const std::string& shipping_option_id) {
Rouslan Solomakhin75450a42020-09-24 18:44:22478 if (!spec_)
479 return;
480
anthonyvd2f30baa12017-04-13 22:30:50481 spec_->StartWaitingForUpdateWith(
482 PaymentRequestSpec::UpdateReason::SHIPPING_OPTION);
Kyungsun Leecdbdade2020-08-25 18:06:12483 if (delegate_) {
484 // This will inform the merchant and will lead to them calling updateWith
485 // with new PaymentDetails.
486 delegate_->OnShippingOptionIdSelected(shipping_option_id);
487 }
anthonyvd0116ce332017-03-21 21:29:01488}
489
mathpf1a7a3752017-03-15 11:23:37490void PaymentRequestState::SetSelectedShippingProfile(
Danyao Wang46e7d942020-09-25 15:45:18491 autofill::AutofillProfile* profile) {
Rouslan Solomakhin75450a42020-09-24 18:44:22492 if (!spec_)
493 return;
494
anthonyvd2f30baa12017-04-13 22:30:50495 spec_->StartWaitingForUpdateWith(
496 PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS);
mathpf1a7a3752017-03-15 11:23:37497 selected_shipping_profile_ = profile;
sebsg7e619132017-04-27 16:07:10498
Jinho Bangcac8d9a02018-08-23 19:47:22499 // Changing the shipping address clears shipping address validation errors
500 // from retry().
501 invalid_shipping_profile_ = nullptr;
502
sebsg7e619132017-04-27 16:07:10503 // The user should not be able to click on pay until the callback from the
504 // merchant.
505 is_waiting_for_merchant_validation_ = true;
sebsg7e619132017-04-27 16:07:10506
507 // Start the normalization of the shipping address.
Mathieu Perreaultc94700f2017-10-23 20:28:39508 payment_request_delegate_->GetAddressNormalizer()->NormalizeAddressAsync(
Mathieu Perreault9b40d5102017-11-21 20:51:29509 *selected_shipping_profile_, /*timeout_seconds=*/2,
Mathieu Perreault17c1ae92017-10-20 17:16:00510 base::BindOnce(&PaymentRequestState::OnAddressNormalized,
511 weak_ptr_factory_.GetWeakPtr()));
mathpf1a7a3752017-03-15 11:23:37512}
513
514void PaymentRequestState::SetSelectedContactProfile(
Danyao Wang46e7d942020-09-25 15:45:18515 autofill::AutofillProfile* profile) {
mathpf1a7a3752017-03-15 11:23:37516 selected_contact_profile_ = profile;
Jinho Bangcac8d9a02018-08-23 19:47:22517
518 // Changing the contact information clears contact information validation
519 // errors from retry().
520 invalid_contact_profile_ = nullptr;
521
mathpf1a7a3752017-03-15 11:23:37522 UpdateIsReadyToPayAndNotifyObservers();
Jinho Bangbb178152018-09-13 09:44:43523
Kyungsun Leecdbdade2020-08-25 18:06:12524 if (IsPaymentAppInvoked() && delegate_) {
Jinho Bang21d6be92018-12-18 15:30:31525 delegate_->OnPayerInfoSelected(
526 response_helper_->GeneratePayerDetail(profile));
Jinho Bangbb178152018-09-13 09:44:43527 }
mathpf1a7a3752017-03-15 11:23:37528}
529
Danyao Wang46e7d942020-09-25 15:45:18530void PaymentRequestState::SetSelectedApp(PaymentApp* app) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39531 selected_app_ = app;
mathpf1a7a3752017-03-15 11:23:37532 UpdateIsReadyToPayAndNotifyObservers();
533}
534
mathpc0d616a2017-03-15 14:09:33535const std::string& PaymentRequestState::GetApplicationLocale() {
536 return app_locale_;
537}
538
539autofill::PersonalDataManager* PaymentRequestState::GetPersonalDataManager() {
540 return personal_data_manager_;
541}
542
mad763ed2b2017-04-24 20:28:47543autofill::RegionDataLoader* PaymentRequestState::GetRegionDataLoader() {
544 return payment_request_delegate_->GetRegionDataLoader();
mad45271932017-04-13 16:07:38545}
546
Anthony Vallee-Dubois6813c1442017-05-17 19:32:56547bool PaymentRequestState::IsPaymentAppInvoked() const {
548 return !!response_helper_;
549}
550
Mathieu Perreaulteea046d12017-09-28 15:51:21551autofill::AddressNormalizer* PaymentRequestState::GetAddressNormalizer() {
Anthony Vallee-Dubois71bf349462017-07-20 23:56:45552 return payment_request_delegate_->GetAddressNormalizer();
553}
554
Rouslan Solomakhin48fd6e872019-02-22 17:23:10555bool PaymentRequestState::IsInitialized() const {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39556 return get_all_apps_finished_;
Rouslan Solomakhin48fd6e872019-02-22 17:23:10557}
558
Rouslan Solomakhin9788d4b2019-04-09 13:10:23559void PaymentRequestState::SelectDefaultShippingAddressAndNotifyObservers() {
560 // Only pre-select an address if the merchant provided at least one selected
561 // shipping option, and the top profile is complete. Assumes that profiles
562 // have already been sorted for completeness and frecency.
Rouslan Solomakhin75450a42020-09-24 18:44:22563 if (!shipping_profiles().empty() && spec_ &&
564 spec_->selected_shipping_option() &&
Rouslan Solomakhin9788d4b2019-04-09 13:10:23565 profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
566 selected_shipping_profile_ = shipping_profiles()[0];
567 }
Sahel Sharify6efdfb32019-07-02 16:12:16568 // Record the missing required fields (if any) of the most complete shipping
569 // profile.
570 profile_comparator()->RecordMissingFieldsOfShippingProfile(
571 shipping_profiles().empty() ? nullptr : shipping_profiles()[0]);
Rouslan Solomakhin9788d4b2019-04-09 13:10:23572 UpdateIsReadyToPayAndNotifyObservers();
573}
574
Sahel Sharifyfef3d922019-09-11 01:41:22575bool PaymentRequestState::ShouldShowShippingSection() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22576 if (!spec_ || !spec_->request_shipping())
Sahel Sharifyfef3d922019-09-11 01:41:22577 return false;
578
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39579 return selected_app_ ? !selected_app_->HandlesShippingAddress() : true;
Sahel Sharifyfef3d922019-09-11 01:41:22580}
581
582bool PaymentRequestState::ShouldShowContactSection() const {
Rouslan Solomakhin75450a42020-09-24 18:44:22583 if (!spec_)
584 return false;
585
Sahel Sharifyfef3d922019-09-11 01:41:22586 if (spec_->request_payer_name() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39587 (!selected_app_ || !selected_app_->HandlesPayerName())) {
Sahel Sharifyfef3d922019-09-11 01:41:22588 return true;
589 }
590 if (spec_->request_payer_email() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39591 (!selected_app_ || !selected_app_->HandlesPayerEmail())) {
Sahel Sharifyfef3d922019-09-11 01:41:22592 return true;
593 }
594 if (spec_->request_payer_phone() &&
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39595 (!selected_app_ || !selected_app_->HandlesPayerPhone())) {
Sahel Sharifyfef3d922019-09-11 01:41:22596 return true;
597 }
598
599 return false;
600}
601
Rouslan Solomakhin65552292019-08-29 17:28:21602base::WeakPtr<PaymentRequestState> PaymentRequestState::AsWeakPtr() {
603 return weak_ptr_factory_.GetWeakPtr();
604}
605
mathpf1a7a3752017-03-15 11:23:37606void PaymentRequestState::PopulateProfileCache() {
mathpf1a7a3752017-03-15 11:23:37607 std::vector<autofill::AutofillProfile*> profiles =
mathpc0d616a2017-03-15 14:09:33608 personal_data_manager_->GetProfilesToSuggest();
mathpf1a7a3752017-03-15 11:23:37609
tmartinocd131b32017-05-24 19:40:59610 std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
611 raw_profiles_for_filtering.reserve(profiles.size());
612
mathpf1a7a3752017-03-15 11:23:37613 // PaymentRequest may outlive the Profiles returned by the Data Manager.
614 // Thus, we store copies, and return a vector of pointers to these copies
mathpf14c1e32017-05-12 16:37:30615 // whenever Profiles are requested.
mathpf1a7a3752017-03-15 11:23:37616 for (size_t i = 0; i < profiles.size(); i++) {
617 profile_cache_.push_back(
Rouslan Solomakhin4eea9bc22017-10-10 15:18:51618 std::make_unique<autofill::AutofillProfile>(*profiles[i]));
tmartinocd131b32017-05-24 19:40:59619 raw_profiles_for_filtering.push_back(profile_cache_.back().get());
mathpf1a7a3752017-03-15 11:23:37620 }
621
tmartino01c3eb82017-04-29 15:18:39622 contact_profiles_ = profile_comparator()->FilterProfilesForContact(
623 raw_profiles_for_filtering);
tmartinocd131b32017-05-24 19:40:59624 shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
625 raw_profiles_for_filtering);
tmartinoa6eb22f2017-04-06 20:16:24626
sebsgc6719b32017-07-05 19:54:47627 // Set the number of suggestions shown for the sections requested by the
628 // merchant.
Sahel Sharifyfef3d922019-09-11 01:41:22629 if (ShouldShowContactSection()) {
sebsgce700484d2017-07-19 23:25:38630 bool has_complete_contact =
631 contact_profiles_.empty()
632 ? false
633 : profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
Rouslan Solomakhincb29c4f2019-08-16 22:49:39634 is_requested_autofill_data_available_ &= has_complete_contact;
sebsgc6719b32017-07-05 19:54:47635 journey_logger_->SetNumberOfSuggestionsShown(
sebsgce700484d2017-07-19 23:25:38636 JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
637 has_complete_contact);
sebsgc6719b32017-07-05 19:54:47638 }
Sahel Sharifyfef3d922019-09-11 01:41:22639 if (ShouldShowShippingSection()) {
sebsgce700484d2017-07-19 23:25:38640 bool has_complete_shipping =
641 shipping_profiles_.empty()
642 ? false
643 : profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
Rouslan Solomakhincb29c4f2019-08-16 22:49:39644 is_requested_autofill_data_available_ &= has_complete_shipping;
sebsgc6719b32017-07-05 19:54:47645 journey_logger_->SetNumberOfSuggestionsShown(
646 JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
sebsgce700484d2017-07-19 23:25:38647 shipping_profiles_.size(), has_complete_shipping);
sebsgc6719b32017-07-05 19:54:47648 }
mathpf1a7a3752017-03-15 11:23:37649}
650
651void PaymentRequestState::SetDefaultProfileSelections() {
mathpf14c1e32017-05-12 16:37:30652 // Contact profiles were ordered by completeness in addition to frecency;
653 // the first one is the best default selection.
tmartinocd131b32017-05-24 19:40:59654 if (!contact_profiles().empty() &&
655 profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
mathpf1a7a3752017-03-15 11:23:37656 selected_contact_profile_ = contact_profiles()[0];
657
Sahel Sharify6efdfb32019-07-02 16:12:16658 // Record the missing required fields (if any) of the most complete contact
659 // profile.
660 profile_comparator()->RecordMissingFieldsOfContactProfile(
661 contact_profiles().empty() ? nullptr : contact_profiles()[0]);
662
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39663 // Sort apps.
664 PaymentApp::SortApps(&available_apps_);
Sahel Sharify13331e82019-07-12 01:00:30665
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39666 selected_app_ = nullptr;
Sahel Sharify90307872019-12-02 17:28:14667 if (!available_apps_.empty() && available_apps_[0]->CanPreselect()) {
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39668 selected_app_ = available_apps_[0].get();
Sahel Sharify9be7b292020-03-13 17:37:46669 UpdateIsReadyToPayAndNotifyObservers();
Sahel Sharify13331e82019-07-12 01:00:30670 }
Rouslan Solomakhin9788d4b2019-04-09 13:10:23671
Sahel Sharify6efdfb32019-07-02 16:12:16672 // Record the missing required payment fields when no complete payment
673 // info exists.
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39674 if (available_apps_.empty()) {
Rouslan Solomakhin75450a42020-09-24 18:44:22675 if (spec_ && spec_->supports_basic_card()) {
Sahel Sharify6efdfb32019-07-02 16:12:16676 // All fields are missing when basic-card is requested but no card exits.
677 base::UmaHistogramSparse("PaymentRequest.MissingPaymentFields",
Sahel Sharify13331e82019-07-12 01:00:30678 CREDIT_CARD_EXPIRED | CREDIT_CARD_NO_CARDHOLDER |
679 CREDIT_CARD_NO_NUMBER |
680 CREDIT_CARD_NO_BILLING_ADDRESS);
Sahel Sharify6efdfb32019-07-02 16:12:16681 }
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39682 } else if (available_apps_[0]->type() == PaymentApp::Type::AUTOFILL) {
683 // Record the missing fields (if any) of the most complete app when
684 // it's autofill based. SW based apps are always complete.
685 static_cast<const AutofillPaymentApp*>(available_apps_[0].get())
686 ->RecordMissingFieldsForApp();
Sahel Sharify6efdfb32019-07-02 16:12:16687 }
gogerald8189d522017-09-15 17:52:18688
Sahel Sharify6efdfb32019-07-02 16:12:16689 SelectDefaultShippingAddressAndNotifyObservers();
gogerald8189d522017-09-15 17:52:18690
691 journey_logger_->SetNumberOfSuggestionsShown(
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39692 JourneyLogger::Section::SECTION_PAYMENT_METHOD, available_apps().size(),
693 selected_app_);
mathpf1a7a3752017-03-15 11:23:37694}
695
696void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
697 is_ready_to_pay_ =
698 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
699 NotifyOnSelectedInformationChanged();
700}
701
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39702void PaymentRequestState::NotifyOnGetAllPaymentAppsFinished() {
gogerald8189d522017-09-15 17:52:18703 for (auto& observer : observers_)
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39704 observer.OnGetAllPaymentAppsFinished();
gogerald8189d522017-09-15 17:52:18705}
706
mathpf1a7a3752017-03-15 11:23:37707void PaymentRequestState::NotifyOnSelectedInformationChanged() {
708 for (auto& observer : observers_)
709 observer.OnSelectedInformationChanged();
710}
711
712bool PaymentRequestState::ArePaymentDetailsSatisfied() {
mathp363735b2017-03-16 18:08:05713 // There is no need to check for supported networks, because only supported
Rouslan Solomakhin5d15cb1f2019-11-11 18:11:39714 // apps are listed/created in the flow.
715 return selected_app_ != nullptr && selected_app_->IsCompleteForPayment();
mathpf1a7a3752017-03-15 11:23:37716}
717
718bool PaymentRequestState::ArePaymentOptionsSatisfied() {
Rouslan Solomakhin75450a42020-09-24 18:44:22719 if (is_waiting_for_merchant_validation_ || !spec_)
sebsg7e619132017-04-27 16:07:10720 return false;
721
Sahel Sharifyfef3d922019-09-11 01:41:22722 if (ShouldShowShippingSection() &&
723 (!spec_->selected_shipping_option() ||
724 !profile_comparator()->IsShippingComplete(selected_shipping_profile_))) {
tmartino01c3eb82017-04-29 15:18:39725 return false;
Sahel Sharifyfef3d922019-09-11 01:41:22726 }
tmartino01c3eb82017-04-29 15:18:39727
Sahel Sharifyfef3d922019-09-11 01:41:22728 if (ShouldShowContactSection() &&
729 !profile_comparator()->IsContactInfoComplete(selected_contact_profile_)) {
Anthony Vallee-Duboisa8814672017-06-01 18:43:20730 return false;
Sahel Sharifyfef3d922019-09-11 01:41:22731 }
Anthony Vallee-Duboisa8814672017-06-01 18:43:20732
Sahel Sharifyfef3d922019-09-11 01:41:22733 return true;
mathpf1a7a3752017-03-15 11:23:37734}
735
Mathieu Perreault17c1ae92017-10-20 17:16:00736void PaymentRequestState::OnAddressNormalized(
737 bool success,
738 const autofill::AutofillProfile& normalized_profile) {
Kyungsun Leecdbdade2020-08-25 18:06:12739 if (!delegate_)
740 return;
741
Mathieu Perreault17c1ae92017-10-20 17:16:00742 delegate_->OnShippingAddressSelected(
Tommy Martino21d415f2018-01-12 20:08:22743 data_util::GetPaymentAddressFromAutofillProfile(normalized_profile,
744 app_locale_));
Mathieu Perreault17c1ae92017-10-20 17:16:00745}
746
Nick Burrisfca090832020-07-28 00:17:42747bool PaymentRequestState::IsInTwa() const {
748 return !payment_request_delegate_->GetTwaPackageName().empty();
749}
750
Rouslan Solomakhinebf9f162020-08-27 15:28:13751bool PaymentRequestState::GetCanMakePaymentValue() const {
752 return are_requested_methods_supported_ ||
753 can_make_payment_even_without_apps_;
754}
755
756bool PaymentRequestState::GetHasEnrolledInstrumentValue() const {
757 return has_enrolled_instrument_ || can_make_payment_even_without_apps_;
758}
759
mathpf1a7a3752017-03-15 11:23:37760} // namespace payments