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

Unified Diff: components/payments/content/payment_request_state.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
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..9c0c9253cd251d75567b03491eccce78dc05e475
--- /dev/null
+++ b/components/payments/content/payment_request_state.cc
@@ -0,0 +1,209 @@
+// 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) {
+ PopulateProfileCache();
+ UpdateSelectedShippingOption();
+ SetDefaultProfileSelections();
+}
+
+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_, shipping_profiles_,
+ 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::PopulateProfileCache() {
+ autofill::PersonalDataManager* personal_data_manager =
+ delegate_->GetPersonalDataManager();
+ DCHECK(personal_data_manager);
+ 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 PaymentRequestState::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 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
« no previous file with comments | « components/payments/content/payment_request_state.h ('k') | components/payments/content/payment_request_state_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698