Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1556)

Unified Diff: components/payments/content/payment_request.cc

Issue 2742813004: [Payments] Refactor into PaymentRequestState and Spec (Closed)
Patch Set: don't stop rebasin' Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/payments/content/payment_request.h ('k') | components/payments/content/payment_request_spec.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « components/payments/content/payment_request.h ('k') | components/payments/content/payment_request_spec.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698