Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |