| Index: components/payments/content/payment_request.cc
|
| diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc
|
| index fe5827b0d4ac9c9b3edb0951df3e46986c647d8d..89a424f40d4c3e3f1a059796648b6b6eb1adb20f 100644
|
| --- a/components/payments/content/payment_request.cc
|
| +++ b/components/payments/content/payment_request.cc
|
| @@ -4,29 +4,18 @@
|
|
|
| #include "components/payments/content/payment_request.h"
|
|
|
| -#include <algorithm>
|
| -#include <set>
|
| -#include <unordered_map>
|
| #include <utility>
|
|
|
| #include "base/memory/ptr_util.h"
|
| -#include "components/autofill/core/browser/autofill_data_util.h"
|
| -#include "components/autofill/core/browser/field_types.h"
|
| #include "components/autofill/core/browser/personal_data_manager.h"
|
| #include "components/payments/content/payment_details_validation.h"
|
| #include "components/payments/content/payment_request_web_contents_manager.h"
|
| -#include "components/payments/core/autofill_payment_instrument.h"
|
| #include "components/payments/core/currency_formatter.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/web_contents.h"
|
|
|
| namespace payments {
|
|
|
| -namespace {
|
| -// Identifier for the basic card payment method in the PaymentMethodData.
|
| -static const char* const kBasicCardMethodName = "basic-card";
|
| -} // namespace
|
| -
|
| PaymentRequest::PaymentRequest(
|
| content::WebContents* web_contents,
|
| std::unique_ptr<PaymentRequestDelegate> delegate,
|
| @@ -35,12 +24,7 @@ PaymentRequest::PaymentRequest(
|
| : web_contents_(web_contents),
|
| delegate_(std::move(delegate)),
|
| manager_(manager),
|
| - binding_(this, std::move(request)),
|
| - is_ready_to_pay_(false),
|
| - selected_shipping_profile_(nullptr),
|
| - selected_contact_profile_(nullptr),
|
| - selected_credit_card_(nullptr),
|
| - selected_shipping_option_(nullptr) {
|
| + binding_(this, std::move(request)) {
|
| // OnConnectionTerminated will be called when the Mojo pipe is closed. This
|
| // will happen as a result of many renderer-side events (both successful and
|
| // erroneous in nature).
|
| @@ -65,12 +49,9 @@ void PaymentRequest::Init(
|
| return;
|
| }
|
| client_ = std::move(client);
|
| - details_ = std::move(details);
|
| - options_ = std::move(options);
|
| - PopulateValidatedMethodData(method_data);
|
| - PopulateProfileCache();
|
| - SetDefaultProfileSelections();
|
| - UpdateSelectedShippingOptionFromDetails();
|
| + spec_ = base::MakeUnique<PaymentRequestSpec>(
|
| + std::move(options), std::move(details), std::move(method_data), this);
|
| + state_ = base::MakeUnique<PaymentRequestState>(spec_.get(), this);
|
| }
|
|
|
| void PaymentRequest::Show() {
|
| @@ -106,12 +87,21 @@ void PaymentRequest::CanMakePayment() {
|
| client_->OnCanMakePayment(mojom::CanMakePaymentQueryResult::CAN_MAKE_PAYMENT);
|
| }
|
|
|
| -void PaymentRequest::OnInstrumentDetailsReady(
|
| - const std::string& method_name,
|
| - const std::string& stringified_details) {
|
| - payment_response_->method_name = method_name;
|
| - payment_response_->stringified_details = stringified_details;
|
| - client_->OnPaymentResponse(std::move(payment_response_));
|
| +void PaymentRequest::OnInvalidSpecProvided() {
|
| + OnConnectionTerminated();
|
| +}
|
| +
|
| +const std::string& PaymentRequest::GetApplicationLocale() {
|
| + return delegate_->GetApplicationLocale();
|
| +}
|
| +
|
| +autofill::PersonalDataManager* PaymentRequest::GetPersonalDataManager() {
|
| + return delegate_->GetPersonalDataManager();
|
| +}
|
| +
|
| +void PaymentRequest::OnPaymentResponseAvailable(
|
| + mojom::PaymentResponsePtr response) {
|
| + client_->OnPaymentResponse(std::move(response));
|
| }
|
|
|
| void PaymentRequest::UserCancelled() {
|
| @@ -142,30 +132,9 @@ void PaymentRequest::OnConnectionTerminated() {
|
| }
|
|
|
| void PaymentRequest::Pay() {
|
| - DCHECK(is_ready_to_pay_);
|
| -
|
| - // TODO(mathp): Fill other fields in the PaymentResponsePtr object.
|
| - payment_response_ = mojom::PaymentResponse::New();
|
| + DCHECK(state_->is_ready_to_pay());
|
|
|
| - // 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_, shipping_profiles_,
|
| - delegate_->GetApplicationLocale()));
|
| - // Fetch the instrument details, will call back into
|
| - // PaymentRequest::OnInstrumentsDetailsReady.
|
| - selected_payment_instrument_->InvokePaymentApp(this);
|
| -}
|
| -
|
| -void PaymentRequest::AddObserver(Observer* observer) {
|
| - CHECK(observer);
|
| - observers_.AddObserver(observer);
|
| -}
|
| -
|
| -void PaymentRequest::RemoveObserver(Observer* observer) {
|
| - observers_.RemoveObserver(observer);
|
| + state_->GeneratePaymentResponse();
|
| }
|
|
|
| CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter(
|
| @@ -181,228 +150,18 @@ CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter(
|
|
|
| base::string16 PaymentRequest::GetFormattedCurrencyAmount(
|
| const std::string& amount) {
|
| - CurrencyFormatter* formatter =
|
| - GetOrCreateCurrencyFormatter(details()->total->amount->currency,
|
| - details()->total->amount->currency_system,
|
| - delegate_->GetApplicationLocale());
|
| + CurrencyFormatter* formatter = GetOrCreateCurrencyFormatter(
|
| + spec_->details().total->amount->currency,
|
| + spec_->details().total->amount->currency_system, GetApplicationLocale());
|
| return formatter->Format(amount);
|
| }
|
|
|
| std::string PaymentRequest::GetFormattedCurrencyCode() {
|
| - CurrencyFormatter* formatter =
|
| - GetOrCreateCurrencyFormatter(details()->total->amount->currency,
|
| - details()->total->amount->currency_system,
|
| - delegate_->GetApplicationLocale());
|
| + CurrencyFormatter* formatter = GetOrCreateCurrencyFormatter(
|
| + spec_->details().total->amount->currency,
|
| + spec_->details().total->amount->currency_system, GetApplicationLocale());
|
|
|
| return formatter->formatted_currency_code();
|
| }
|
|
|
| -void PaymentRequest::SetSelectedShippingProfile(
|
| - autofill::AutofillProfile* profile) {
|
| - selected_shipping_profile_ = profile;
|
| - UpdateIsReadyToPayAndNotifyObservers();
|
| -}
|
| -
|
| -void PaymentRequest::SetSelectedContactProfile(
|
| - autofill::AutofillProfile* profile) {
|
| - selected_contact_profile_ = profile;
|
| - UpdateIsReadyToPayAndNotifyObservers();
|
| -}
|
| -
|
| -void PaymentRequest::SetSelectedCreditCard(autofill::CreditCard* card) {
|
| - selected_credit_card_ = card;
|
| - UpdateIsReadyToPayAndNotifyObservers();
|
| -}
|
| -
|
| -void PaymentRequest::PopulateProfileCache() {
|
| - std::vector<autofill::AutofillProfile*> profiles =
|
| - personal_data_manager()->GetProfilesToSuggest();
|
| -
|
| - // PaymentRequest may outlive the Profiles returned by the Data Manager.
|
| - // Thus, we store copies, and return a vector of pointers to these copies
|
| - // whenever Profiles are requested. The same is true for credit cards.
|
| - for (size_t i = 0; i < profiles.size(); i++) {
|
| - profile_cache_.push_back(
|
| - base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
|
| -
|
| - // TODO(tmartino): Implement deduplication rules specific to shipping and
|
| - // contact profiles.
|
| - shipping_profiles_.push_back(profile_cache_[i].get());
|
| - contact_profiles_.push_back(profile_cache_[i].get());
|
| - }
|
| -
|
| - const std::vector<autofill::CreditCard*>& cards =
|
| - personal_data_manager()->GetCreditCardsToSuggest();
|
| - for (autofill::CreditCard* card : cards) {
|
| - card_cache_.push_back(base::MakeUnique<autofill::CreditCard>(*card));
|
| - credit_cards_.push_back(card_cache_.back().get());
|
| - }
|
| -}
|
| -
|
| -void PaymentRequest::SetDefaultProfileSelections() {
|
| - if (!shipping_profiles().empty())
|
| - selected_shipping_profile_ = shipping_profiles()[0];
|
| -
|
| - if (!contact_profiles().empty())
|
| - selected_contact_profile_ = contact_profiles()[0];
|
| -
|
| - // TODO(anthonyvd): Change this code to prioritize server cards and implement
|
| - // a way to modify this function's return value.
|
| - const std::vector<autofill::CreditCard*> cards = credit_cards();
|
| - auto first_complete_card =
|
| - std::find_if(cards.begin(), cards.end(),
|
| - [](autofill::CreditCard* card) { return card->IsValid(); });
|
| -
|
| - selected_credit_card_ =
|
| - first_complete_card == cards.end() ? nullptr : *first_complete_card;
|
| -
|
| - UpdateIsReadyToPayAndNotifyObservers();
|
| -}
|
| -
|
| -void PaymentRequest::PopulateValidatedMethodData(
|
| - const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data) {
|
| - if (method_data.empty()) {
|
| - LOG(ERROR) << "Invalid payment methods or data";
|
| - OnConnectionTerminated();
|
| - return;
|
| - }
|
| -
|
| - std::set<std::string> card_networks{"amex", "diners", "discover",
|
| - "jcb", "mastercard", "mir",
|
| - "unionpay", "visa"};
|
| - for (const payments::mojom::PaymentMethodDataPtr& method_data_entry :
|
| - method_data) {
|
| - std::vector<std::string> supported_methods =
|
| - method_data_entry->supported_methods;
|
| - if (supported_methods.empty()) {
|
| - LOG(ERROR) << "Invalid payment methods or data";
|
| - OnConnectionTerminated();
|
| - return;
|
| - }
|
| -
|
| - for (const std::string& method : supported_methods) {
|
| - if (method.empty())
|
| - continue;
|
| -
|
| - // If a card network is specified right in "supportedMethods", add it.
|
| - auto card_it = card_networks.find(method);
|
| - if (card_it != card_networks.end()) {
|
| - supported_card_networks_.push_back(method);
|
| - // |method| removed from |card_networks| so that it is not doubly added
|
| - // to |supported_card_networks_| if "basic-card" is specified with no
|
| - // supported networks.
|
| - card_networks.erase(card_it);
|
| - } else if (method == kBasicCardMethodName) {
|
| - // For the "basic-card" method, check "supportedNetworks".
|
| - if (method_data_entry->supported_networks.empty()) {
|
| - // Empty |supported_networks| means all networks are supported.
|
| - supported_card_networks_.insert(supported_card_networks_.end(),
|
| - card_networks.begin(),
|
| - card_networks.end());
|
| - // Clear the set so that no further networks are added to
|
| - // |supported_card_networks_|.
|
| - card_networks.clear();
|
| - } else {
|
| - // The merchant has specified a few basic card supported networks. Use
|
| - // the mapping to transform to known basic-card types.
|
| - using ::payments::mojom::BasicCardNetwork;
|
| - std::unordered_map<BasicCardNetwork, std::string> networks = {
|
| - {BasicCardNetwork::AMEX, "amex"},
|
| - {BasicCardNetwork::DINERS, "diners"},
|
| - {BasicCardNetwork::DISCOVER, "discover"},
|
| - {BasicCardNetwork::JCB, "jcb"},
|
| - {BasicCardNetwork::MASTERCARD, "mastercard"},
|
| - {BasicCardNetwork::MIR, "mir"},
|
| - {BasicCardNetwork::UNIONPAY, "unionpay"},
|
| - {BasicCardNetwork::VISA, "visa"}};
|
| - for (const BasicCardNetwork& supported_network :
|
| - method_data_entry->supported_networks) {
|
| - // Make sure that the network was not already added to
|
| - // |supported_card_networks_|.
|
| - auto card_it = card_networks.find(networks[supported_network]);
|
| - if (card_it != card_networks.end()) {
|
| - supported_card_networks_.push_back(networks[supported_network]);
|
| - card_networks.erase(card_it);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void PaymentRequest::UpdateIsReadyToPayAndNotifyObservers() {
|
| - is_ready_to_pay_ =
|
| - ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
|
| - NotifyOnSelectedInformationChanged();
|
| -}
|
| -
|
| -void PaymentRequest::NotifyOnSelectedInformationChanged() {
|
| - for (auto& observer : observers_)
|
| - observer.OnSelectedInformationChanged();
|
| -}
|
| -
|
| -bool PaymentRequest::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 !supported_card_networks_.empty() &&
|
| - std::find(supported_card_networks_.begin(),
|
| - supported_card_networks_.end(),
|
| - basic_card_payment_type) != supported_card_networks_.end();
|
| -}
|
| -
|
| -bool PaymentRequest::ArePaymentOptionsSatisfied() {
|
| - // TODO(mathp): Have a measure of shipping address completeness.
|
| - if (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 (request_payer_name() &&
|
| - (selected_contact_profile_ == nullptr ||
|
| - selected_contact_profile_
|
| - ->GetInfo(autofill::AutofillType(autofill::NAME_FULL), app_locale)
|
| - .empty())) {
|
| - return false;
|
| - }
|
| - if (request_payer_email() &&
|
| - (selected_contact_profile_ == nullptr ||
|
| - selected_contact_profile_
|
| - ->GetInfo(autofill::AutofillType(autofill::EMAIL_ADDRESS),
|
| - app_locale)
|
| - .empty())) {
|
| - return false;
|
| - }
|
| - if (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 PaymentRequest::UpdateSelectedShippingOptionFromDetails() {
|
| - 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(
|
| - details()->shipping_options.rbegin(), details()->shipping_options.rend(),
|
| - [](const payments::mojom::PaymentShippingOptionPtr& element) {
|
| - return element->selected;
|
| - });
|
| - if (selected_shipping_option_it != details()->shipping_options.rend()) {
|
| - selected_shipping_option_ = selected_shipping_option_it->get();
|
| - }
|
| -}
|
| -
|
| } // namespace payments
|
|
|