| Index: components/payments/content/payment_request_state.cc
|
| diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..32043f7ae4eb87da066912a92470a91a0f0b07a5
|
| --- /dev/null
|
| +++ b/components/payments/content/payment_request_state.cc
|
| @@ -0,0 +1,172 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/payments/content/payment_request_state.h"
|
| +
|
| +#include "components/autofill/core/browser/autofill_data_util.h"
|
| +#include "components/autofill/core/browser/autofill_profile.h"
|
| +#include "components/autofill/core/browser/credit_card.h"
|
| +#include "components/payments/content/payment_request_spec.h"
|
| +#include "components/payments/core/autofill_payment_instrument.h"
|
| +
|
| +namespace payments {
|
| +
|
| +namespace {
|
| +// Identifier for the basic card payment method in the PaymentMethodData.
|
| +static const char* const kBasicCardMethodName = "basic-card";
|
| +} // namespace
|
| +
|
| +PaymentRequestState::PaymentRequestState(PaymentRequestSpec* spec,
|
| + Delegate* delegate)
|
| + : is_ready_to_pay_(false),
|
| + spec_(spec),
|
| + delegate_(delegate),
|
| + selected_shipping_profile_(nullptr),
|
| + selected_contact_profile_(nullptr),
|
| + selected_credit_card_(nullptr),
|
| + selected_shipping_option_(nullptr) {
|
| + UpdateSelectedShippingOption();
|
| +}
|
| +
|
| +void PaymentRequestState::AddObserver(Observer* observer) {
|
| + CHECK(observer);
|
| + observers_.AddObserver(observer);
|
| +}
|
| +PaymentRequestState::~PaymentRequestState() {}
|
| +
|
| +void PaymentRequestState::RemoveObserver(Observer* observer) {
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void PaymentRequestState::OnInstrumentDetailsReady(
|
| + const std::string& method_name,
|
| + const std::string& stringified_details) {
|
| + // TODO(mathp): Fill other fields in the PaymentResponsePtr object.
|
| + mojom::PaymentResponsePtr payment_response = mojom::PaymentResponse::New();
|
| +
|
| + payment_response->method_name = method_name;
|
| + payment_response->stringified_details = stringified_details;
|
| + delegate_->OnPaymentResponseAvailable(std::move(payment_response));
|
| +}
|
| +
|
| +void PaymentRequestState::GeneratePaymentResponse() {
|
| + // TODO(mathp): PaymentRequest should know about the currently selected
|
| + // instrument, and not |selected_credit_card_| which is too specific.
|
| + // TODO(mathp): The method_name should reflect what the merchant asked, and
|
| + // not necessarily basic-card.
|
| + selected_payment_instrument_.reset(new AutofillPaymentInstrument(
|
| + kBasicCardMethodName, *selected_credit_card_,
|
| + delegate_->GetBillingProfiles(), delegate_->GetApplicationLocale()));
|
| + // Fetch the instrument details, will call back into
|
| + // PaymentRequest::OnInstrumentsDetailsReady.
|
| + selected_payment_instrument_->InvokePaymentApp(this);
|
| +}
|
| +
|
| +void PaymentRequestState::SetSelectedShippingProfile(
|
| + autofill::AutofillProfile* profile) {
|
| + selected_shipping_profile_ = profile;
|
| + UpdateIsReadyToPayAndNotifyObservers();
|
| +}
|
| +
|
| +void PaymentRequestState::SetSelectedContactProfile(
|
| + autofill::AutofillProfile* profile) {
|
| + selected_contact_profile_ = profile;
|
| + UpdateIsReadyToPayAndNotifyObservers();
|
| +}
|
| +
|
| +void PaymentRequestState::SetSelectedCreditCard(autofill::CreditCard* card) {
|
| + selected_credit_card_ = card;
|
| + UpdateIsReadyToPayAndNotifyObservers();
|
| +}
|
| +
|
| +void PaymentRequestState::SetInitialSelections(
|
| + autofill::AutofillProfile* shipping,
|
| + autofill::AutofillProfile* contact,
|
| + autofill::CreditCard* card) {
|
| + // Setting directly instead of using their setters to avoid recomputing the
|
| + // "ready to pay" state.
|
| + selected_shipping_profile_ = shipping;
|
| + selected_contact_profile_ = contact;
|
| + selected_credit_card_ = card;
|
| + UpdateIsReadyToPayAndNotifyObservers();
|
| +}
|
| +
|
| +void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
|
| + is_ready_to_pay_ =
|
| + ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
|
| + NotifyOnSelectedInformationChanged();
|
| +}
|
| +
|
| +void PaymentRequestState::NotifyOnSelectedInformationChanged() {
|
| + for (auto& observer : observers_)
|
| + observer.OnSelectedInformationChanged();
|
| +}
|
| +
|
| +bool PaymentRequestState::ArePaymentDetailsSatisfied() {
|
| + // TODO(mathp): A masked card may not satisfy IsValid().
|
| + if (selected_credit_card_ == nullptr || !selected_credit_card_->IsValid())
|
| + return false;
|
| +
|
| + const std::string basic_card_payment_type =
|
| + autofill::data_util::GetPaymentRequestData(selected_credit_card_->type())
|
| + .basic_card_payment_type;
|
| + return !spec_->supported_card_networks().empty() &&
|
| + std::find(spec_->supported_card_networks().begin(),
|
| + spec_->supported_card_networks().end(),
|
| + basic_card_payment_type) !=
|
| + spec_->supported_card_networks().end();
|
| +}
|
| +
|
| +bool PaymentRequestState::ArePaymentOptionsSatisfied() {
|
| + // TODO(mathp): Have a measure of shipping address completeness.
|
| + if (spec_->request_shipping() && selected_shipping_profile_ == nullptr)
|
| + return false;
|
| +
|
| + // TODO(mathp): Make an encompassing class to validate contact info.
|
| + const std::string& app_locale = delegate_->GetApplicationLocale();
|
| + if (spec_->request_payer_name() &&
|
| + (selected_contact_profile_ == nullptr ||
|
| + selected_contact_profile_
|
| + ->GetInfo(autofill::AutofillType(autofill::NAME_FULL), app_locale)
|
| + .empty())) {
|
| + return false;
|
| + }
|
| + if (spec_->request_payer_email() &&
|
| + (selected_contact_profile_ == nullptr ||
|
| + selected_contact_profile_
|
| + ->GetInfo(autofill::AutofillType(autofill::EMAIL_ADDRESS),
|
| + app_locale)
|
| + .empty())) {
|
| + return false;
|
| + }
|
| + if (spec_->request_payer_phone() &&
|
| + (selected_contact_profile_ == nullptr ||
|
| + selected_contact_profile_
|
| + ->GetInfo(autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
|
| + app_locale)
|
| + .empty())) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void PaymentRequestState::UpdateSelectedShippingOption() {
|
| + selected_shipping_option_ = nullptr;
|
| +
|
| + // As per the spec, the selected shipping option should initially be the last
|
| + // one in the array that has its selected field set to true.
|
| + auto selected_shipping_option_it = std::find_if(
|
| + spec_->details()->shipping_options.rbegin(),
|
| + spec_->details()->shipping_options.rend(),
|
| + [](const payments::mojom::PaymentShippingOptionPtr& element) {
|
| + return element->selected;
|
| + });
|
| + if (selected_shipping_option_it !=
|
| + spec_->details()->shipping_options.rend()) {
|
| + selected_shipping_option_ = selected_shipping_option_it->get();
|
| + }
|
| +}
|
| +
|
| +} // namespace payments
|
|
|