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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // 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
7 #include "components/autofill/core/browser/autofill_data_util.h"
8 #include "components/autofill/core/browser/autofill_profile.h"
9 #include "components/autofill/core/browser/credit_card.h"
10 #include "components/payments/content/payment_request_spec.h"
11 #include "components/payments/core/autofill_payment_instrument.h"
12
13 namespace payments {
14
15 namespace {
16 // Identifier for the basic card payment method in the PaymentMethodData.
17 static const char* const kBasicCardMethodName = "basic-card";
18 } // namespace
19
20 PaymentRequestState::PaymentRequestState(PaymentRequestSpec* spec,
21 Delegate* delegate)
22 : is_ready_to_pay_(false),
23 spec_(spec),
24 delegate_(delegate),
25 selected_shipping_profile_(nullptr),
26 selected_contact_profile_(nullptr),
27 selected_credit_card_(nullptr),
28 selected_shipping_option_(nullptr) {
29 PopulateProfileCache();
30 UpdateSelectedShippingOption();
31 SetDefaultProfileSelections();
32 }
33
34 void PaymentRequestState::AddObserver(Observer* observer) {
35 CHECK(observer);
36 observers_.AddObserver(observer);
37 }
38 PaymentRequestState::~PaymentRequestState() {}
39
40 void PaymentRequestState::RemoveObserver(Observer* observer) {
41 observers_.RemoveObserver(observer);
42 }
43
44 void PaymentRequestState::OnInstrumentDetailsReady(
45 const std::string& method_name,
46 const std::string& stringified_details) {
47 // TODO(mathp): Fill other fields in the PaymentResponsePtr object.
48 mojom::PaymentResponsePtr payment_response = mojom::PaymentResponse::New();
49
50 payment_response->method_name = method_name;
51 payment_response->stringified_details = stringified_details;
52 delegate_->OnPaymentResponseAvailable(std::move(payment_response));
53 }
54
55 void PaymentRequestState::GeneratePaymentResponse() {
56 // TODO(mathp): PaymentRequest should know about the currently selected
57 // instrument, and not |selected_credit_card_| which is too specific.
58 // TODO(mathp): The method_name should reflect what the merchant asked, and
59 // not necessarily basic-card.
60 selected_payment_instrument_.reset(new AutofillPaymentInstrument(
61 kBasicCardMethodName, *selected_credit_card_, shipping_profiles_,
62 delegate_->GetApplicationLocale()));
63 // Fetch the instrument details, will call back into
64 // PaymentRequest::OnInstrumentsDetailsReady.
65 selected_payment_instrument_->InvokePaymentApp(this);
66 }
67
68 void PaymentRequestState::SetSelectedShippingProfile(
69 autofill::AutofillProfile* profile) {
70 selected_shipping_profile_ = profile;
71 UpdateIsReadyToPayAndNotifyObservers();
72 }
73
74 void PaymentRequestState::SetSelectedContactProfile(
75 autofill::AutofillProfile* profile) {
76 selected_contact_profile_ = profile;
77 UpdateIsReadyToPayAndNotifyObservers();
78 }
79
80 void PaymentRequestState::SetSelectedCreditCard(autofill::CreditCard* card) {
81 selected_credit_card_ = card;
82 UpdateIsReadyToPayAndNotifyObservers();
83 }
84
85 void PaymentRequestState::PopulateProfileCache() {
86 autofill::PersonalDataManager* personal_data_manager =
87 delegate_->GetPersonalDataManager();
88 DCHECK(personal_data_manager);
89 std::vector<autofill::AutofillProfile*> profiles =
90 personal_data_manager->GetProfilesToSuggest();
91
92 // PaymentRequest may outlive the Profiles returned by the Data Manager.
93 // Thus, we store copies, and return a vector of pointers to these copies
94 // whenever Profiles are requested. The same is true for credit cards.
95 for (size_t i = 0; i < profiles.size(); i++) {
96 profile_cache_.push_back(
97 base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
98
99 // TODO(tmartino): Implement deduplication rules specific to shipping and
100 // contact profiles.
101 shipping_profiles_.push_back(profile_cache_[i].get());
102 contact_profiles_.push_back(profile_cache_[i].get());
103 }
104
105 const std::vector<autofill::CreditCard*>& cards =
106 personal_data_manager->GetCreditCardsToSuggest();
107 for (autofill::CreditCard* card : cards) {
108 card_cache_.push_back(base::MakeUnique<autofill::CreditCard>(*card));
109 credit_cards_.push_back(card_cache_.back().get());
110 }
111 }
112
113 void PaymentRequestState::SetDefaultProfileSelections() {
114 if (!shipping_profiles().empty())
115 selected_shipping_profile_ = shipping_profiles()[0];
116
117 if (!contact_profiles().empty())
118 selected_contact_profile_ = contact_profiles()[0];
119
120 // TODO(anthonyvd): Change this code to prioritize server cards and implement
121 // a way to modify this function's return value.
122 const std::vector<autofill::CreditCard*> cards = credit_cards();
123 auto first_complete_card =
124 std::find_if(cards.begin(), cards.end(),
125 [](autofill::CreditCard* card) { return card->IsValid(); });
126
127 selected_credit_card_ =
128 first_complete_card == cards.end() ? nullptr : *first_complete_card;
129
130 UpdateIsReadyToPayAndNotifyObservers();
131 }
132
133 void PaymentRequestState::UpdateIsReadyToPayAndNotifyObservers() {
134 is_ready_to_pay_ =
135 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
136 NotifyOnSelectedInformationChanged();
137 }
138
139 void PaymentRequestState::NotifyOnSelectedInformationChanged() {
140 for (auto& observer : observers_)
141 observer.OnSelectedInformationChanged();
142 }
143
144 bool PaymentRequestState::ArePaymentDetailsSatisfied() {
145 // TODO(mathp): A masked card may not satisfy IsValid().
146 if (selected_credit_card_ == nullptr || !selected_credit_card_->IsValid())
147 return false;
148
149 const std::string basic_card_payment_type =
150 autofill::data_util::GetPaymentRequestData(selected_credit_card_->type())
151 .basic_card_payment_type;
152 return !spec_->supported_card_networks().empty() &&
153 std::find(spec_->supported_card_networks().begin(),
154 spec_->supported_card_networks().end(),
155 basic_card_payment_type) !=
156 spec_->supported_card_networks().end();
157 }
158
159 bool PaymentRequestState::ArePaymentOptionsSatisfied() {
160 // TODO(mathp): Have a measure of shipping address completeness.
161 if (spec_->request_shipping() && selected_shipping_profile_ == nullptr)
162 return false;
163
164 // TODO(mathp): Make an encompassing class to validate contact info.
165 const std::string& app_locale = delegate_->GetApplicationLocale();
166 if (spec_->request_payer_name() &&
167 (selected_contact_profile_ == nullptr ||
168 selected_contact_profile_
169 ->GetInfo(autofill::AutofillType(autofill::NAME_FULL), app_locale)
170 .empty())) {
171 return false;
172 }
173 if (spec_->request_payer_email() &&
174 (selected_contact_profile_ == nullptr ||
175 selected_contact_profile_
176 ->GetInfo(autofill::AutofillType(autofill::EMAIL_ADDRESS),
177 app_locale)
178 .empty())) {
179 return false;
180 }
181 if (spec_->request_payer_phone() &&
182 (selected_contact_profile_ == nullptr ||
183 selected_contact_profile_
184 ->GetInfo(autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
185 app_locale)
186 .empty())) {
187 return false;
188 }
189
190 return true;
191 }
192
193 void PaymentRequestState::UpdateSelectedShippingOption() {
194 selected_shipping_option_ = nullptr;
195
196 // As per the spec, the selected shipping option should initially be the last
197 // one in the array that has its selected field set to true.
198 auto selected_shipping_option_it = std::find_if(
199 spec_->details().shipping_options.rbegin(),
200 spec_->details().shipping_options.rend(),
201 [](const payments::mojom::PaymentShippingOptionPtr& element) {
202 return element->selected;
203 });
204 if (selected_shipping_option_it != spec_->details().shipping_options.rend()) {
205 selected_shipping_option_ = selected_shipping_option_it->get();
206 }
207 }
208
209 } // namespace payments
OLDNEW
« 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