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

Side by Side Diff: components/payments/content/payment_request.cc

Issue 2715213005: [Payments] Add the pay button, and control its enabled state (Closed)
Patch Set: clean the .h 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/payments/content/payment_request.h" 5 #include "components/payments/content/payment_request.h"
6 6
7 #include <algorithm>
7 #include <unordered_map> 8 #include <unordered_map>
8 #include <utility> 9 #include <utility>
9 10
10 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "components/autofill/core/browser/autofill_data_util.h"
13 #include "components/autofill/core/browser/field_types.h"
11 #include "components/autofill/core/browser/personal_data_manager.h" 14 #include "components/autofill/core/browser/personal_data_manager.h"
12 #include "components/payments/content/payment_details_validation.h" 15 #include "components/payments/content/payment_details_validation.h"
13 #include "components/payments/content/payment_request_web_contents_manager.h" 16 #include "components/payments/content/payment_request_web_contents_manager.h"
14 #include "components/payments/core/currency_formatter.h" 17 #include "components/payments/core/currency_formatter.h"
15 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
17 20
18 namespace payments { 21 namespace payments {
19 22
20 PaymentRequest::PaymentRequest( 23 PaymentRequest::PaymentRequest(
21 content::WebContents* web_contents, 24 content::WebContents* web_contents,
22 std::unique_ptr<PaymentRequestDelegate> delegate, 25 std::unique_ptr<PaymentRequestDelegate> delegate,
23 PaymentRequestWebContentsManager* manager, 26 PaymentRequestWebContentsManager* manager,
24 mojo::InterfaceRequest<payments::mojom::PaymentRequest> request) 27 mojo::InterfaceRequest<payments::mojom::PaymentRequest> request)
25 : web_contents_(web_contents), 28 : web_contents_(web_contents),
26 delegate_(std::move(delegate)), 29 delegate_(std::move(delegate)),
27 manager_(manager), 30 manager_(manager),
28 binding_(this, std::move(request)), 31 binding_(this, std::move(request)),
32 is_ready_to_pay_(false),
29 selected_shipping_profile_(nullptr), 33 selected_shipping_profile_(nullptr),
30 selected_contact_profile_(nullptr), 34 selected_contact_profile_(nullptr),
31 selected_credit_card_(nullptr) { 35 selected_credit_card_(nullptr) {
32 // OnConnectionTerminated will be called when the Mojo pipe is closed. This 36 // OnConnectionTerminated will be called when the Mojo pipe is closed. This
33 // will happen as a result of many renderer-side events (both successful and 37 // will happen as a result of many renderer-side events (both successful and
34 // erroneous in nature). 38 // erroneous in nature).
35 // TODO(crbug.com/683636): Investigate using 39 // TODO(crbug.com/683636): Investigate using
36 // set_connection_error_with_reason_handler with Binding::CloseWithReason. 40 // set_connection_error_with_reason_handler with Binding::CloseWithReason.
37 binding_.set_connection_error_handler(base::Bind( 41 binding_.set_connection_error_handler(base::Bind(
38 &PaymentRequest::OnConnectionTerminated, base::Unretained(this))); 42 &PaymentRequest::OnConnectionTerminated, base::Unretained(this)));
39 } 43 }
40 44
41 PaymentRequest::~PaymentRequest() {} 45 PaymentRequest::~PaymentRequest() {}
42 46
43 void PaymentRequest::Init( 47 void PaymentRequest::Init(
44 payments::mojom::PaymentRequestClientPtr client, 48 payments::mojom::PaymentRequestClientPtr client,
45 std::vector<payments::mojom::PaymentMethodDataPtr> method_data, 49 std::vector<payments::mojom::PaymentMethodDataPtr> method_data,
46 payments::mojom::PaymentDetailsPtr details, 50 payments::mojom::PaymentDetailsPtr details,
47 payments::mojom::PaymentOptionsPtr options) { 51 payments::mojom::PaymentOptionsPtr options) {
48 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 52 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
49 std::string error; 53 std::string error;
50 if (!payments::validatePaymentDetails(details, &error)) { 54 if (!payments::validatePaymentDetails(details, &error)) {
51 LOG(ERROR) << error; 55 LOG(ERROR) << error;
52 OnConnectionTerminated(); 56 OnConnectionTerminated();
53 return; 57 return;
54 } 58 }
55 client_ = std::move(client); 59 client_ = std::move(client);
56 details_ = std::move(details); 60 details_ = std::move(details);
61 options_ = std::move(options);
57 PopulateValidatedMethodData(method_data); 62 PopulateValidatedMethodData(method_data);
58 PopulateProfileCache(); 63 PopulateProfileCache();
59 SetDefaultProfileSelections(); 64 SetDefaultProfileSelections();
60 } 65 }
61 66
62 void PaymentRequest::Show() { 67 void PaymentRequest::Show() {
63 if (!client_.is_bound() || !binding_.is_bound()) { 68 if (!client_.is_bound() || !binding_.is_bound()) {
64 LOG(ERROR) << "Attempted Show(), but binding(s) missing."; 69 LOG(ERROR) << "Attempted Show(), but binding(s) missing.";
65 OnConnectionTerminated(); 70 OnConnectionTerminated();
66 return; 71 return;
(...skipping 29 matching lines...) Expand all
96 // connection_error_handler on |binding_|, which can mean that the renderer 101 // connection_error_handler on |binding_|, which can mean that the renderer
97 // has decided to close the pipe for various reasons (see all uses of 102 // has decided to close the pipe for various reasons (see all uses of
98 // PaymentRequest::clearResolversAndCloseMojoConnection() in Blink). We close 103 // PaymentRequest::clearResolversAndCloseMojoConnection() in Blink). We close
99 // the binding and the dialog, and ask to be deleted. 104 // the binding and the dialog, and ask to be deleted.
100 client_.reset(); 105 client_.reset();
101 binding_.Close(); 106 binding_.Close();
102 delegate_->CloseDialog(); 107 delegate_->CloseDialog();
103 manager_->DestroyRequest(this); 108 manager_->DestroyRequest(this);
104 } 109 }
105 110
111 void PaymentRequest::Pay() {
112 DCHECK(is_ready_to_pay_);
113
114 // TODO(mathp): Return the PaymentResponse to the |client_|.
115 UserCancelled();
116 }
117
118 void PaymentRequest::AddObserver(Observer* observer) {
119 CHECK(observer);
120 observers_.AddObserver(observer);
121 }
122
123 void PaymentRequest::RemoveObserver(Observer* observer) {
124 observers_.RemoveObserver(observer);
125 }
126
106 CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter( 127 CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter(
107 const std::string& currency_code, 128 const std::string& currency_code,
108 const std::string& currency_system, 129 const std::string& currency_system,
109 const std::string& locale_name) { 130 const std::string& locale_name) {
110 if (!currency_formatter_) { 131 if (!currency_formatter_) {
111 currency_formatter_.reset( 132 currency_formatter_.reset(
112 new CurrencyFormatter(currency_code, currency_system, locale_name)); 133 new CurrencyFormatter(currency_code, currency_system, locale_name));
113 } 134 }
114 return currency_formatter_.get(); 135 return currency_formatter_.get();
115 } 136 }
116 137
117 const std::vector<autofill::AutofillProfile*>& 138 void PaymentRequest::SetSelectedShippingProfile(
118 PaymentRequest::shipping_profiles() { 139 autofill::AutofillProfile* profile) {
119 return shipping_profiles_; 140 selected_shipping_profile_ = profile;
141 UpdateIsReadyToPayAndNotifyObservers();
120 } 142 }
121 143
122 const std::vector<autofill::AutofillProfile*>& 144 void PaymentRequest::SetSelectedContactProfile(
123 PaymentRequest::contact_profiles() { 145 autofill::AutofillProfile* profile) {
124 return contact_profiles_; 146 selected_contact_profile_ = profile;
147 UpdateIsReadyToPayAndNotifyObservers();
148 }
149
150 void PaymentRequest::SetSelectedCreditCard(autofill::CreditCard* card) {
151 selected_credit_card_ = card;
152 UpdateIsReadyToPayAndNotifyObservers();
125 } 153 }
126 154
127 void PaymentRequest::PopulateProfileCache() { 155 void PaymentRequest::PopulateProfileCache() {
128 std::vector<autofill::AutofillProfile*> profiles = 156 std::vector<autofill::AutofillProfile*> profiles =
129 personal_data_manager()->GetProfilesToSuggest(); 157 personal_data_manager()->GetProfilesToSuggest();
130 158
131 // PaymentRequest may outlive the Profiles returned by the Data Manager. 159 // PaymentRequest may outlive the Profiles returned by the Data Manager.
132 // Thus, we store copies, and return a vector of pointers to these copies 160 // Thus, we store copies, and return a vector of pointers to these copies
133 // whenever Profiles are requested. The same is true for credit cards. 161 // whenever Profiles are requested. The same is true for credit cards.
134 for (size_t i = 0; i < profiles.size(); i++) { 162 for (size_t i = 0; i < profiles.size(); i++) {
135 profile_cache_.push_back( 163 profile_cache_.push_back(
136 base::MakeUnique<autofill::AutofillProfile>(*profiles[i])); 164 base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
137 165
138 // TODO(tmartino): Implement deduplication rules specific to shipping and 166 // TODO(tmartino): Implement deduplication rules specific to shipping and
139 // contact profiles. 167 // contact profiles.
140 shipping_profiles_.push_back(profile_cache_[i].get()); 168 shipping_profiles_.push_back(profile_cache_[i].get());
141 contact_profiles_.push_back(profile_cache_[i].get()); 169 contact_profiles_.push_back(profile_cache_[i].get());
142 } 170 }
143 171
144 const std::vector<autofill::CreditCard*>& cards = 172 const std::vector<autofill::CreditCard*>& cards =
145 personal_data_manager()->GetCreditCardsToSuggest(); 173 personal_data_manager()->GetCreditCardsToSuggest();
146 for (autofill::CreditCard* card : cards) { 174 for (autofill::CreditCard* card : cards) {
147 card_cache_.push_back(base::MakeUnique<autofill::CreditCard>(*card)); 175 card_cache_.push_back(base::MakeUnique<autofill::CreditCard>(*card));
148 credit_cards_.push_back(card_cache_.back().get()); 176 credit_cards_.push_back(card_cache_.back().get());
149 } 177 }
150 } 178 }
151 179
152 void PaymentRequest::SetDefaultProfileSelections() { 180 void PaymentRequest::SetDefaultProfileSelections() {
153 if (!shipping_profiles().empty()) 181 if (!shipping_profiles().empty())
154 set_selected_shipping_profile(shipping_profiles()[0]); 182 selected_shipping_profile_ = shipping_profiles()[0];
155 183
156 if (!contact_profiles().empty()) 184 if (!contact_profiles().empty())
157 set_selected_contact_profile(contact_profiles()[0]); 185 selected_contact_profile_ = contact_profiles()[0];
158 186
159 // TODO(anthonyvd): Change this code to prioritize server cards and implement 187 // TODO(anthonyvd): Change this code to prioritize server cards and implement
160 // a way to modify this function's return value. 188 // a way to modify this function's return value.
161 const std::vector<autofill::CreditCard*> cards = credit_cards(); 189 const std::vector<autofill::CreditCard*> cards = credit_cards();
162 auto first_complete_card = 190 auto first_complete_card =
163 std::find_if(cards.begin(), cards.end(), 191 std::find_if(cards.begin(), cards.end(),
164 [](autofill::CreditCard* card) { return card->IsValid(); }); 192 [](autofill::CreditCard* card) { return card->IsValid(); });
165 193
166 selected_credit_card_ = 194 selected_credit_card_ =
167 first_complete_card == cards.end() ? nullptr : *first_complete_card; 195 first_complete_card == cards.end() ? nullptr : *first_complete_card;
196
197 UpdateIsReadyToPayAndNotifyObservers();
168 } 198 }
169 199
170 void PaymentRequest::PopulateValidatedMethodData( 200 void PaymentRequest::PopulateValidatedMethodData(
171 const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data) { 201 const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data) {
172 if (method_data.empty()) { 202 if (method_data.empty()) {
173 LOG(ERROR) << "Invalid payment methods or data"; 203 LOG(ERROR) << "Invalid payment methods or data";
174 OnConnectionTerminated(); 204 OnConnectionTerminated();
175 return; 205 return;
176 } 206 }
177 207
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 supported_card_networks_.push_back(networks[supported_network]); 264 supported_card_networks_.push_back(networks[supported_network]);
235 card_networks.erase(card_it); 265 card_networks.erase(card_it);
236 } 266 }
237 } 267 }
238 } 268 }
239 } 269 }
240 } 270 }
241 } 271 }
242 } 272 }
243 273
274 void PaymentRequest::UpdateIsReadyToPayAndNotifyObservers() {
275 is_ready_to_pay_ =
276 ArePaymentDetailsSatisfied() && ArePaymentOptionsSatisfied();
277 NotifyOnSelectedInformationChanged();
278 }
279
280 void PaymentRequest::NotifyOnSelectedInformationChanged() {
281 for (auto& observer : observers_)
282 observer.OnSelectedInformationChanged();
283 }
284
285 bool PaymentRequest::ArePaymentDetailsSatisfied() {
286 if (selected_credit_card_ == nullptr || !selected_credit_card_->IsValid())
anthonyvd 2017/02/28 21:07:18 Isn't there a caveat here that server cards aren't
Mathieu 2017/02/28 21:43:27 oh wow good catch
287 return false;
288
289 const std::string basic_card_payment_type =
290 autofill::data_util::GetPaymentRequestData(selected_credit_card_->type())
291 .basic_card_payment_type;
292 return !supported_card_networks_.empty() &&
293 std::find(supported_card_networks_.begin(),
294 supported_card_networks_.end(),
295 basic_card_payment_type) != supported_card_networks_.end();
296 }
297
298 bool PaymentRequest::ArePaymentOptionsSatisfied() {
299 // TODO(mathp): Have a measure of shipping address completeness.
300 if (options_->request_shipping && selected_shipping_profile_ == nullptr)
301 return false;
302
303 // TODO(mathp): Make an encompassing class to validate contact info.
304 const std::string& app_locale = delegate_->GetApplicationLocale();
305 if (options_->request_payer_name &&
306 (selected_contact_profile_ == nullptr ||
307 selected_contact_profile_
308 ->GetInfo(autofill::AutofillType(autofill::NAME_FULL), app_locale)
309 .empty())) {
310 return false;
311 }
312 if (options_->request_payer_email &&
313 (selected_contact_profile_ == nullptr ||
314 selected_contact_profile_
315 ->GetInfo(autofill::AutofillType(autofill::EMAIL_ADDRESS),
316 app_locale)
317 .empty())) {
318 return false;
319 }
320 if (options_->request_payer_phone &&
321 (selected_contact_profile_ == nullptr ||
322 selected_contact_profile_
323 ->GetInfo(autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
324 app_locale)
325 .empty())) {
326 return false;
327 }
328
329 return true;
330 }
331
244 } // namespace payments 332 } // namespace payments
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698