diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-04-05 17:15:33 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-04-11 07:47:18 +0000 |
commit | 7324afb043a0b1e623d8e8eb906cdc53bdeb4685 (patch) | |
tree | a3fe2d74ea9c9e142c390dac4ca0e219382ace46 /chromium/components/payments | |
parent | 6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (diff) | |
download | qtwebengine-chromium-7324afb043a0b1e623d8e8eb906cdc53bdeb4685.tar.gz |
BASELINE: Update Chromium to 58.0.3029.54
Change-Id: I67f57065a7afdc8e4614adb5c0230281428df4d1
Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/components/payments')
33 files changed, 1274 insertions, 356 deletions
diff --git a/chromium/components/payments/OWNERS b/chromium/components/payments/OWNERS index dc78259ee7a..2ff5e3b38df 100644 --- a/chromium/components/payments/OWNERS +++ b/chromium/components/payments/OWNERS @@ -1,6 +1,4 @@ -jdonnelly@chromium.org -krb@chromium.org +mathp@chromium.org rouslan@chromium.org -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS +# COMPONENT: UI>Browser>Autofill>Payments diff --git a/chromium/components/payments/BUILD.gn b/chromium/components/payments/content/BUILD.gn index 8df0365533d..a6f75fe71c8 100644 --- a/chromium/components/payments/BUILD.gn +++ b/chromium/components/payments/content/BUILD.gn @@ -26,33 +26,28 @@ mojom("payment_app") { ] } -# TODO(crbug.com/679381): Create a layered component to that we can remove the -# iOS check here (iOS strict DEPS checker doesn't like the //content dependency -# below). -if (!is_ios) { - static_library("payment_request_impl") { - sources = [ - "payment_request.cc", - "payment_request.h", - "payment_request_delegate.h", - "payment_request_web_contents_manager.cc", - "payment_request_web_contents_manager.h", - ] +static_library("payment_request_impl") { + sources = [ + "payment_request.cc", + "payment_request.h", + "payment_request_delegate.h", + "payment_request_dialog.h", + "payment_request_web_contents_manager.cc", + "payment_request_web_contents_manager.h", + ] - deps = [ - ":payment_request", - ":payment_validation", - "//components/autofill/core/browser", - "//content/public/browser", - "//mojo/public/cpp/bindings", - ] - } + deps = [ + ":payment_request", + ":payment_validation", + "//components/autofill/core/browser", + "//components/payments/core", + "//content/public/browser", + "//mojo/public/cpp/bindings", + ] } static_library("payment_validation") { sources = [ - "currency_formatter.cc", - "currency_formatter.h", "payment_details_validation.cc", "payment_details_validation.h", "payments_validators.cc", @@ -62,26 +57,31 @@ static_library("payment_validation") { deps = [ ":payment_request", "//base", - "//third_party/re2:re2", - "//url:url", + "//components/autofill/core/browser", + "//components/payments/core", + "//third_party/re2", + "//url", ] public_deps = [ - "//third_party/icu:icu", + "//third_party/icu", + "//third_party/libaddressinput", ] } source_set("unit_tests") { testonly = true sources = [ - "currency_formatter_unittest.cc", "payments_validators_test.cc", ] deps = [ ":payment_validation", "//base", + "//base/test:test_support", + "//components/autofill/core/browser", "//testing/gtest", - "//third_party/icu:icu", + "//third_party/icu", + "//third_party/libaddressinput:test_support", ] } diff --git a/chromium/components/payments/DEPS b/chromium/components/payments/content/DEPS index 151fdf5f8b6..ec8a11647d6 100644 --- a/chromium/components/payments/DEPS +++ b/chromium/components/payments/content/DEPS @@ -1,8 +1,6 @@ include_rules = [ "+components/autofill", - # TODO(crbug.com/679381): Move this to components/payments/content. "+content/public/browser", - "+mojo/public/cpp", "+third_party/re2", ] diff --git a/chromium/components/payments/content/OWNERS b/chromium/components/payments/content/OWNERS new file mode 100644 index 00000000000..82559c92e72 --- /dev/null +++ b/chromium/components/payments/content/OWNERS @@ -0,0 +1,4 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# COMPONENT: UI>Browser>Autofill>Payments diff --git a/chromium/components/payments/android/BUILD.gn b/chromium/components/payments/content/android/BUILD.gn index a1949e547df..8dafb9b75d6 100644 --- a/chromium/components/payments/android/BUILD.gn +++ b/chromium/components/payments/content/android/BUILD.gn @@ -5,17 +5,19 @@ import("//build/config/android/config.gni") import("//build/config/android/rules.gni") -static_library("payments_jni") { +static_library("android") { sources = [ "currency_formatter_android.cc", "currency_formatter_android.h", - "payments_jni_registrar.cc", + "payment_details_validation_android.cc", + "payment_details_validation_android.h", ] deps = [ ":jni_headers", "//base", - "//components/payments:payment_request", - "//components/payments:payment_validation", + "//components/payments/content:payment_request", + "//components/payments/content:payment_validation", + "//components/payments/core", ] } diff --git a/chromium/components/payments/android/DEPS b/chromium/components/payments/content/android/DEPS index c80012b5621..c80012b5621 100644 --- a/chromium/components/payments/android/DEPS +++ b/chromium/components/payments/content/android/DEPS diff --git a/chromium/components/payments/android/currency_formatter_android.cc b/chromium/components/payments/content/android/currency_formatter_android.cc index 00143f3214e..0ea0f912033 100644 --- a/chromium/components/payments/android/currency_formatter_android.cc +++ b/chromium/components/payments/content/android/currency_formatter_android.cc @@ -2,18 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/android/currency_formatter_android.h" +#include "components/payments/content/android/currency_formatter_android.h" #include "base/android/jni_string.h" -#include "base/optional.h" #include "base/strings/string16.h" -#include "components/payments/currency_formatter.h" +#include "components/payments/core/currency_formatter.h" #include "jni/CurrencyFormatter_jni.h" -using base::android::JavaParamRef; -using base::android::ConvertJavaStringToUTF8; - namespace payments { +namespace { + +using ::base::android::JavaParamRef; +using ::base::android::ConvertJavaStringToUTF8; + +} // namespace CurrencyFormatterAndroid::CurrencyFormatterAndroid( JNIEnv* env, @@ -25,10 +27,7 @@ CurrencyFormatterAndroid::CurrencyFormatterAndroid( ConvertJavaStringToUTF8(env, currency_system); currency_formatter_.reset(new CurrencyFormatter( - ConvertJavaStringToUTF8(env, currency_code), - currency_system_str.empty() - ? base::Optional<std::string>() - : base::Optional<std::string>(currency_system_str), + ConvertJavaStringToUTF8(env, currency_code), currency_system_str, ConvertJavaStringToUTF8(env, locale_name))); } diff --git a/chromium/components/payments/android/currency_formatter_android.h b/chromium/components/payments/content/android/currency_formatter_android.h index f6e6b33e28f..9693c200b83 100644 --- a/chromium/components/payments/android/currency_formatter_android.h +++ b/chromium/components/payments/content/android/currency_formatter_android.h @@ -2,17 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PAYMENTS_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ -#define COMPONENTS_PAYMENTS_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ +#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ +#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ +#include <jni.h> #include <memory> #include "base/android/scoped_java_ref.h" #include "base/macros.h" -#include "components/payments/currency_formatter.h" namespace payments { +class CurrencyFormatter; + // Forwarding calls to payments::CurrencyFormatter. class CurrencyFormatterAndroid { public: @@ -48,4 +50,4 @@ class CurrencyFormatterAndroid { } // namespace payments -#endif // COMPONENTS_PAYMENTS_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ +#endif // COMPONENTS_PAYMENTS_CONTENT_ANDROID_CURRENCY_FORMATTER_ANDROID_H_ diff --git a/chromium/components/payments/content/android/payment_details_validation_android.cc b/chromium/components/payments/content/android/payment_details_validation_android.cc new file mode 100644 index 00000000000..072dda083a4 --- /dev/null +++ b/chromium/components/payments/content/android/payment_details_validation_android.cc @@ -0,0 +1,35 @@ +// 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/android/payment_details_validation_android.h" + +#include <string> +#include <utility> + +#include "components/payments/content/payment_details_validation.h" +#include "components/payments/content/payment_request.mojom.h" +#include "jni/PaymentValidator_jni.h" + +namespace payments { + +jboolean ValidatePaymentDetails( + JNIEnv* env, + const base::android::JavaParamRef<jclass>& jcaller, + const base::android::JavaParamRef<jobject>& buffer) { + jbyte* buf_in = static_cast<jbyte*>(env->GetDirectBufferAddress(buffer)); + jlong buf_size = env->GetDirectBufferCapacity(buffer); + std::vector<uint8_t> mojo_buffer(buf_size); + memcpy(&mojo_buffer[0], buf_in, buf_size); + mojom::PaymentDetailsPtr details; + if (!mojom::PaymentDetails::Deserialize(std::move(mojo_buffer), &details)) + return false; + std::string unused_error_message; + return payments::validatePaymentDetails(details, &unused_error_message); +} + +} // namespace payments + +bool RegisterPaymentValidator(JNIEnv* env) { + return payments::RegisterNativesImpl(env); +} diff --git a/chromium/components/payments/content/android/payment_details_validation_android.h b/chromium/components/payments/content/android/payment_details_validation_android.h new file mode 100644 index 00000000000..88367ae1e8e --- /dev/null +++ b/chromium/components/payments/content/android/payment_details_validation_android.h @@ -0,0 +1,12 @@ +// 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. + +#ifndef COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_DETAILS_VALIDATION_ANDROID_H_ +#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_DETAILS_VALIDATION_ANDROID_H_ + +#include <jni.h> + +bool RegisterPaymentValidator(JNIEnv* env); + +#endif // COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_DETAILS_VALIDATION_ANDROID_H_ diff --git a/chromium/components/payments/payment_app.mojom b/chromium/components/payments/content/payment_app.mojom index a3e9715b769..0d9f7c655ad 100644 --- a/chromium/components/payments/payment_app.mojom +++ b/chromium/components/payments/content/payment_app.mojom @@ -4,7 +4,7 @@ module payments.mojom; -import "components/payments/payment_request.mojom"; +import "components/payments/content/payment_request.mojom"; import "url/mojo/url.mojom"; enum PaymentAppManifestError { @@ -35,7 +35,7 @@ interface PaymentAppManager { => (PaymentAppManifest payment_app_manifest, PaymentAppManifestError error); }; -struct PaymentAppRequestData { +struct PaymentAppRequest { url.mojom.Url origin; array<PaymentMethodData> methodData; PaymentItem total; diff --git a/chromium/components/payments/payment_details_validation.cc b/chromium/components/payments/content/payment_details_validation.cc index 81c42cdbb49..3933c1c3337 100644 --- a/chromium/components/payments/payment_details_validation.cc +++ b/chromium/components/payments/content/payment_details_validation.cc @@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/payment_details_validation.h" +#include "components/payments/content/payment_details_validation.h" #include <set> #include <vector> -#include "components/payments/payment_request.mojom.h" -#include "components/payments/payments_validators.h" +#include "components/payments/content/payment_request.mojom.h" +#include "components/payments/content/payments_validators.h" +namespace payments { namespace { // Validates ShippingOption or PaymentItem, which happen to have identical @@ -44,16 +45,13 @@ bool validateShippingOptionOrPaymentItem( return false; } - if (item->amount->currency_system.has_value() && - item->amount->currency_system.value().empty()) { + if (item->amount->currency_system.empty()) { *error_message = "Currency system can't be empty"; return false; } if (!payments::PaymentsValidators::isValidCurrencyCodeFormat( - item->amount->currency, item->amount->currency_system.has_value() - ? item->amount->currency_system.value() - : "", + item->amount->currency, item->amount->currency_system, error_message)) { return false; } @@ -142,8 +140,6 @@ bool validatePaymentDetailsModifiers( } // namespace -namespace payments { - bool validatePaymentDetails(const mojom::PaymentDetailsPtr& details, std::string* error_message) { if (details->total.is_null()) { diff --git a/chromium/components/payments/payment_details_validation.h b/chromium/components/payments/content/payment_details_validation.h index 804602c0134..e6230876a1c 100644 --- a/chromium/components/payments/payment_details_validation.h +++ b/chromium/components/payments/content/payment_details_validation.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PAYMENTS_PAYMENT_DETAILS_VALIDATION_H_ -#define COMPONENTS_PAYMENTS_PAYMENT_DETAILS_VALIDATION_H_ +#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_DETAILS_VALIDATION_H_ +#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_DETAILS_VALIDATION_H_ #include <string> -#include "components/payments/payment_request.mojom.h" +#include "components/payments/content/payment_request.mojom.h" namespace payments { @@ -16,4 +16,4 @@ bool validatePaymentDetails(const mojom::PaymentDetailsPtr& details, } // namespace payments -#endif // COMPONENTS_PAYMENTS_PAYMENT_DETAILS_VALIDATION_H_ +#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_DETAILS_VALIDATION_H_ diff --git a/chromium/components/payments/content/payment_request.cc b/chromium/components/payments/content/payment_request.cc new file mode 100644 index 00000000000..e55e68b272a --- /dev/null +++ b/chromium/components/payments/content/payment_request.cc @@ -0,0 +1,333 @@ +// 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.h" + +#include <algorithm> +#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/currency_formatter.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" + +namespace payments { + +PaymentRequest::PaymentRequest( + content::WebContents* web_contents, + std::unique_ptr<PaymentRequestDelegate> delegate, + PaymentRequestWebContentsManager* manager, + mojo::InterfaceRequest<payments::mojom::PaymentRequest> request) + : 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) { + // 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). + // TODO(crbug.com/683636): Investigate using + // set_connection_error_with_reason_handler with Binding::CloseWithReason. + binding_.set_connection_error_handler(base::Bind( + &PaymentRequest::OnConnectionTerminated, base::Unretained(this))); +} + +PaymentRequest::~PaymentRequest() {} + +void PaymentRequest::Init( + payments::mojom::PaymentRequestClientPtr client, + std::vector<payments::mojom::PaymentMethodDataPtr> method_data, + payments::mojom::PaymentDetailsPtr details, + payments::mojom::PaymentOptionsPtr options) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::string error; + if (!payments::validatePaymentDetails(details, &error)) { + LOG(ERROR) << error; + OnConnectionTerminated(); + return; + } + client_ = std::move(client); + details_ = std::move(details); + options_ = std::move(options); + PopulateValidatedMethodData(method_data); + PopulateProfileCache(); + SetDefaultProfileSelections(); +} + +void PaymentRequest::Show() { + if (!client_.is_bound() || !binding_.is_bound()) { + LOG(ERROR) << "Attempted Show(), but binding(s) missing."; + OnConnectionTerminated(); + return; + } + delegate_->ShowDialog(this); +} + +void PaymentRequest::Abort() { + // The API user has decided to abort. We return a successful abort message to + // the renderer, which closes the Mojo message pipe, which triggers + // PaymentRequest::OnConnectionTerminated, which destroys this object. + if (client_.is_bound()) + client_->OnAbort(true /* aborted_successfully */); +} + +void PaymentRequest::UserCancelled() { + // If |client_| is not bound, then the object is already being destroyed as + // a result of a renderer event. + if (!client_.is_bound()) + return; + + // This sends an error to the renderer, which informs the API user. + client_->OnError(payments::mojom::PaymentErrorReason::USER_CANCEL); + + // We close all bindings and ask to be destroyed. + client_.reset(); + binding_.Close(); + manager_->DestroyRequest(this); +} + +void PaymentRequest::OnConnectionTerminated() { + // We are here because of a browser-side error, or likely as a result of the + // connection_error_handler on |binding_|, which can mean that the renderer + // has decided to close the pipe for various reasons (see all uses of + // PaymentRequest::clearResolversAndCloseMojoConnection() in Blink). We close + // the binding and the dialog, and ask to be deleted. + client_.reset(); + binding_.Close(); + delegate_->CloseDialog(); + manager_->DestroyRequest(this); +} + +void PaymentRequest::Pay() { + DCHECK(is_ready_to_pay_); + + // TODO(mathp): Return the PaymentResponse to the |client_|. + OnConnectionTerminated(); +} + +void PaymentRequest::AddObserver(Observer* observer) { + CHECK(observer); + observers_.AddObserver(observer); +} + +void PaymentRequest::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter( + const std::string& currency_code, + const std::string& currency_system, + const std::string& locale_name) { + if (!currency_formatter_) { + currency_formatter_.reset( + new CurrencyFormatter(currency_code, currency_system, locale_name)); + } + return currency_formatter_.get(); +} + +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; + } + + // Identifier for the basic card payment method in the PaymentMethodData. + const char* const kBasicCardMethodName = "basic-card"; + 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; +} + +} // namespace payments diff --git a/chromium/components/payments/content/payment_request.h b/chromium/components/payments/content/payment_request.h new file mode 100644 index 00000000000..18d3f94229b --- /dev/null +++ b/chromium/components/payments/content/payment_request.h @@ -0,0 +1,199 @@ +// 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. + +#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ +#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/observer_list.h" +#include "components/payments/content/payment_request.mojom.h" +#include "components/payments/content/payment_request_delegate.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace autofill { +class AutofillProfile; +class CreditCard; +class PersonalDataManager; +} + +namespace content { +class WebContents; +} + +namespace payments { + +class CurrencyFormatter; +class PaymentRequestWebContentsManager; + +class PaymentRequest : payments::mojom::PaymentRequest { + public: + class Observer { + public: + // Called when the information (payment method, address/contact info, + // shipping option) changes. + virtual void OnSelectedInformationChanged() = 0; + + protected: + virtual ~Observer() {} + }; + + PaymentRequest( + content::WebContents* web_contents, + std::unique_ptr<PaymentRequestDelegate> delegate, + PaymentRequestWebContentsManager* manager, + mojo::InterfaceRequest<payments::mojom::PaymentRequest> request); + ~PaymentRequest() override; + + // payments::mojom::PaymentRequest "stub" + void Init(payments::mojom::PaymentRequestClientPtr client, + std::vector<payments::mojom::PaymentMethodDataPtr> method_data, + payments::mojom::PaymentDetailsPtr details, + payments::mojom::PaymentOptionsPtr options) override; + void Show() override; + void UpdateWith(payments::mojom::PaymentDetailsPtr details) override {} + void Abort() override; + void Complete(payments::mojom::PaymentComplete result) override {} + void CanMakePayment() override {} + + // Called when the user explicitely cancelled the flow. Will send a message + // to the renderer which will indirectly destroy this object (through + // OnConnectionTerminated). + void UserCancelled(); + + // As a result of a browser-side error or renderer-initiated mojo channel + // closure (e.g. there was an error on the renderer side, or payment was + // successful), this method is called. It is responsible for cleaning up, + // such as possibly closing the dialog. + void OnConnectionTerminated(); + + // Called when the user clicks on the "Pay" button. + void Pay(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Returns the CurrencyFormatter instance for this PaymentRequest. + // |locale_name| should be the result of the browser's GetApplicationLocale(). + // Note: Having multiple currencies per PaymentRequest is not supported; hence + // the CurrencyFormatter is cached here. + CurrencyFormatter* GetOrCreateCurrencyFormatter( + const std::string& currency_code, + const std::string& currency_system, + const std::string& locale_name); + + // Returns the appropriate Autofill Profiles for this user. On the first + // invocation of either getter, the profiles are fetched from the + // PersonalDataManager; on subsequent invocations, a cached version is + // returned. The profiles returned are owned by the request object. + const std::vector<autofill::AutofillProfile*>& shipping_profiles() { + return shipping_profiles_; + } + const std::vector<autofill::AutofillProfile*>& contact_profiles() { + return contact_profiles_; + } + const std::vector<autofill::CreditCard*>& credit_cards() { + return credit_cards_; + } + + // Gets the Autofill Profile representing the shipping address or contact + // information currently selected for this PaymentRequest flow. Can return + // null. + autofill::AutofillProfile* selected_shipping_profile() const { + return selected_shipping_profile_; + } + autofill::AutofillProfile* selected_contact_profile() const { + return selected_contact_profile_; + } + // Returns the currently selected credit card for this PaymentRequest flow. + // It's not guaranteed to be complete. Returns nullptr if there is no selected + // card. + autofill::CreditCard* selected_credit_card() { return selected_credit_card_; } + + // Sets the |profile| to be the selected one and will update state and notify + // observers. + void SetSelectedShippingProfile(autofill::AutofillProfile* profile); + void SetSelectedContactProfile(autofill::AutofillProfile* profile); + void SetSelectedCreditCard(autofill::CreditCard* card); + + autofill::PersonalDataManager* personal_data_manager() { + return delegate_->GetPersonalDataManager(); + } + + payments::mojom::PaymentDetails* details() { return details_.get(); } + const std::vector<std::string>& supported_card_networks() { + return supported_card_networks_; + } + content::WebContents* web_contents() { return web_contents_; } + + bool request_shipping() const { return options_->request_shipping; } + bool request_payer_name() const { return options_->request_payer_name; } + bool request_payer_phone() const { return options_->request_payer_phone; } + bool request_payer_email() const { return options_->request_payer_email; } + + bool is_ready_to_pay() { return is_ready_to_pay_; } + + private: + // Fetches the Autofill Profiles for this user from the PersonalDataManager, + // and stores copies of them, owned by this Request, in profile_cache_. + void PopulateProfileCache(); + + // Sets the default values for the selected Shipping and Contact profiles, as + // well as the selected Credit Card. + void SetDefaultProfileSelections(); + + // Validates the |method_data| and fills |supported_card_networks_|. + void PopulateValidatedMethodData( + const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data); + + // Updates |is_ready_to_pay_| with the current state, by validating that all + // the required information is available and notify observers. + void UpdateIsReadyToPayAndNotifyObservers(); + + // Notifies all observers that selected information has changed. + void NotifyOnSelectedInformationChanged(); + + // Returns whether the selected data satisfies the PaymentDetails requirements + // (payment methods). + bool ArePaymentDetailsSatisfied(); + // Returns whether the selected data satisfies the PaymentOptions requirements + // (contact info, shipping address). + bool ArePaymentOptionsSatisfied(); + + content::WebContents* web_contents_; + std::unique_ptr<PaymentRequestDelegate> delegate_; + // |manager_| owns this PaymentRequest. + PaymentRequestWebContentsManager* manager_; + mojo::Binding<payments::mojom::PaymentRequest> binding_; + payments::mojom::PaymentRequestClientPtr client_; + payments::mojom::PaymentDetailsPtr details_; + payments::mojom::PaymentOptionsPtr options_; + std::unique_ptr<CurrencyFormatter> currency_formatter_; + // A set of supported basic card networks. + std::vector<std::string> supported_card_networks_; + bool is_ready_to_pay_; + + base::ObserverList<Observer> observers_; + + // Profiles may change due to (e.g.) sync events, so profiles are cached after + // loading and owned here. They are populated once only, and ordered by + // frecency. + std::vector<std::unique_ptr<autofill::AutofillProfile>> profile_cache_; + std::vector<autofill::AutofillProfile*> shipping_profiles_; + std::vector<autofill::AutofillProfile*> contact_profiles_; + autofill::AutofillProfile* selected_shipping_profile_; + autofill::AutofillProfile* selected_contact_profile_; + std::vector<std::unique_ptr<autofill::CreditCard>> card_cache_; + std::vector<autofill::CreditCard*> credit_cards_; + autofill::CreditCard* selected_credit_card_; + + DISALLOW_COPY_AND_ASSIGN(PaymentRequest); +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_H_ diff --git a/chromium/components/payments/payment_request.mojom b/chromium/components/payments/content/payment_request.mojom index 5b1abcdea23..d8ad5833f48 100644 --- a/chromium/components/payments/payment_request.mojom +++ b/chromium/components/payments/content/payment_request.mojom @@ -48,7 +48,7 @@ struct PaymentCurrencyAmount { // currency identifier belongs to. By default, the value is // urn:iso:std:iso:4217 indicating that currency is defined by [ISO4217] // (for example, USD for US Dollars). - string? currency_system; + string currency_system = "urn:iso:std:iso:4217"; }; struct PaymentResponse { diff --git a/chromium/components/payments/payment_request_delegate.h b/chromium/components/payments/content/payment_request_delegate.h index 9e666541661..46faaaea93a 100644 --- a/chromium/components/payments/payment_request_delegate.h +++ b/chromium/components/payments/content/payment_request_delegate.h @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PAYMENTS_PAYMENT_REQUEST_DELEGATE_H_ -#define COMPONENTS_PAYMENTS_PAYMENT_REQUEST_DELEGATE_H_ +#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DELEGATE_H_ +#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DELEGATE_H_ + +#include <string> namespace autofill { class PersonalDataManager; @@ -18,12 +20,19 @@ class PaymentRequestDelegate { virtual ~PaymentRequestDelegate() {} // Shows the Payment Request dialog for the given |request|. - virtual void ShowPaymentRequestDialog(PaymentRequest* request) = 0; + virtual void ShowDialog(PaymentRequest* request) = 0; + + // Closes the same dialog that was opened by this delegate. Must be safe to + // call when the dialog is not showing. + virtual void CloseDialog() = 0; // Gets the PersonalDataManager associated with this PaymentRequest flow. + // Cannot be null. virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0; + + virtual const std::string& GetApplicationLocale() const = 0; }; } // namespace payments -#endif // COMPONENTS_PAYMENTS_PAYMENT_REQUEST_DELEGATE_H_ +#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DELEGATE_H_ diff --git a/chromium/components/payments/content/payment_request_dialog.h b/chromium/components/payments/content/payment_request_dialog.h new file mode 100644 index 00000000000..5befff8d08f --- /dev/null +++ b/chromium/components/payments/content/payment_request_dialog.h @@ -0,0 +1,22 @@ +// Copyright 2017 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. + +#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DIALOG_H_ +#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DIALOG_H_ + +namespace payments { + +// Used to interact with a cross-platform Payment Request dialog. +class PaymentRequestDialog { + public: + virtual ~PaymentRequestDialog() {} + + virtual void ShowDialog() = 0; + + virtual void CloseDialog() = 0; +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_DIALOG_H_ diff --git a/chromium/components/payments/payment_request_web_contents_manager.cc b/chromium/components/payments/content/payment_request_web_contents_manager.cc index ca893723f6f..db68134c47c 100644 --- a/chromium/components/payments/payment_request_web_contents_manager.cc +++ b/chromium/components/payments/content/payment_request_web_contents_manager.cc @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/payment_request_web_contents_manager.h" +#include "components/payments/content/payment_request_web_contents_manager.h" -#include <memory> #include <utility> #include "base/logging.h" -#include "components/payments/payment_request_delegate.h" +#include "base/memory/ptr_util.h" +#include "components/payments/content/payment_request.h" +#include "components/payments/content/payment_request_delegate.h" +#include "content/public/browser/web_contents.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(payments::PaymentRequestWebContentsManager); @@ -29,8 +31,8 @@ void PaymentRequestWebContentsManager::CreatePaymentRequest( content::WebContents* web_contents, std::unique_ptr<PaymentRequestDelegate> delegate, mojo::InterfaceRequest<payments::mojom::PaymentRequest> request) { - std::unique_ptr<PaymentRequest> new_request(new PaymentRequest( - web_contents, std::move(delegate), this, std::move(request))); + auto new_request = base::MakeUnique<PaymentRequest>( + web_contents, std::move(delegate), this, std::move(request)); PaymentRequest* request_ptr = new_request.get(); payment_requests_.insert(std::make_pair(request_ptr, std::move(new_request))); } diff --git a/chromium/components/payments/payment_request_web_contents_manager.h b/chromium/components/payments/content/payment_request_web_contents_manager.h index 42e26f4a9ce..52323140d10 100644 --- a/chromium/components/payments/payment_request_web_contents_manager.h +++ b/chromium/components/payments/content/payment_request_web_contents_manager.h @@ -5,15 +5,21 @@ #ifndef COMPONENTS_PAYMENTS_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_ #define COMPONENTS_PAYMENTS_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_ +#include <memory> #include <unordered_map> -#include "components/payments/payment_request.h" -#include "components/payments/payment_request.mojom.h" +#include "base/macros.h" +#include "components/payments/content/payment_request.mojom.h" #include "content/public/browser/web_contents_user_data.h" #include "mojo/public/cpp/bindings/binding.h" +namespace content { +class WebContents; +} + namespace payments { +class PaymentRequest; class PaymentRequestDelegate; // This class owns the PaymentRequest associated with a given WebContents. @@ -54,6 +60,8 @@ class PaymentRequestWebContentsManager // the requests themselves call DestroyRequest(). std::unordered_map<PaymentRequest*, std::unique_ptr<PaymentRequest>> payment_requests_; + + DISALLOW_COPY_AND_ASSIGN(PaymentRequestWebContentsManager); }; } // namespace payments diff --git a/chromium/components/payments/payments_validators.cc b/chromium/components/payments/content/payments_validators.cc index 1d83c237c6e..ed2b448c205 100644 --- a/chromium/components/payments/payments_validators.cc +++ b/chromium/components/payments/content/payments_validators.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/payments_validators.h" +#include "components/payments/content/payments_validators.h" #include "third_party/re2/src/re2/re2.h" #include "url/gurl.h" @@ -15,29 +15,29 @@ static const int maximumStringLength = 2048; bool PaymentsValidators::isValidCurrencyCodeFormat( const std::string& code, const std::string& system, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (system == "urn:iso:std:iso:4217") { if (RE2::FullMatch(code, "[A-Z]{3}")) return true; - if (optionalErrorMessage) - *optionalErrorMessage = "'" + code + - "' is not a valid ISO 4217 currency code, should " - "be 3 upper case letters [A-Z]"; + if (optional_error_message) + *optional_error_message = + "'" + code + + "' is not a valid ISO 4217 currency code, should " + "be 3 upper case letters [A-Z]"; return false; } if (code.size() > maximumStringLength) { - if (optionalErrorMessage) - *optionalErrorMessage = + if (optional_error_message) + *optional_error_message = "The currency code should be at most 2048 characters long"; return false; } if (!GURL(system).is_valid()) { - if (optionalErrorMessage) - *optionalErrorMessage = - "The system should be a valid URL"; + if (optional_error_message) + *optional_error_message = "The system should be a valid URL"; return false; } return true; @@ -45,74 +45,77 @@ bool PaymentsValidators::isValidCurrencyCodeFormat( bool PaymentsValidators::isValidAmountFormat( const std::string& amount, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (RE2::FullMatch(amount, "-?[0-9]+(\\.[0-9]+)?")) return true; - if (optionalErrorMessage) - *optionalErrorMessage = "'" + amount + "' is not a valid amount format"; + if (optional_error_message) + *optional_error_message = "'" + amount + "' is not a valid amount format"; return false; } bool PaymentsValidators::isValidCountryCodeFormat( const std::string& code, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (RE2::FullMatch(code, "[A-Z]{2}")) return true; - if (optionalErrorMessage) - *optionalErrorMessage = "'" + code + - "' is not a valid CLDR country code, should be 2 " - "upper case letters [A-Z]"; + if (optional_error_message) + *optional_error_message = "'" + code + + "' is not a valid CLDR country code, should be 2 " + "upper case letters [A-Z]"; return false; } bool PaymentsValidators::isValidLanguageCodeFormat( const std::string& code, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (RE2::FullMatch(code, "([a-z]{2,3})?")) return true; - if (optionalErrorMessage) - *optionalErrorMessage = "'" + code + - "' is not a valid BCP-47 language code, should be " - "2-3 lower case letters [a-z]"; + if (optional_error_message) + *optional_error_message = + "'" + code + + "' is not a valid BCP-47 language code, should be " + "2-3 lower case letters [a-z]"; return false; } bool PaymentsValidators::isValidScriptCodeFormat( const std::string& code, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (RE2::FullMatch(code, "([A-Z][a-z]{3})?")) return true; - if (optionalErrorMessage) - *optionalErrorMessage = "'" + code + - "' is not a valid ISO 15924 script code, should be " - "an upper case letter [A-Z] followed by 3 lower " - "case letters [a-z]"; + if (optional_error_message) + *optional_error_message = + "'" + code + + "' is not a valid ISO 15924 script code, should be " + "an upper case letter [A-Z] followed by 3 lower " + "case letters [a-z]"; return false; } bool PaymentsValidators::isValidShippingAddress( const mojom::PaymentAddressPtr& address, - std::string* optionalErrorMessage) { - if (!isValidCountryCodeFormat(address->country, optionalErrorMessage)) + std::string* optional_error_message) { + if (!isValidCountryCodeFormat(address->country, optional_error_message)) return false; - if (!isValidLanguageCodeFormat(address->language_code, optionalErrorMessage)) + if (!isValidLanguageCodeFormat(address->language_code, + optional_error_message)) return false; - if (!isValidScriptCodeFormat(address->script_code, optionalErrorMessage)) + if (!isValidScriptCodeFormat(address->script_code, optional_error_message)) return false; if (address->language_code.empty() && !address->script_code.empty()) { - if (optionalErrorMessage) - *optionalErrorMessage = + if (optional_error_message) + *optional_error_message = "If language code is empty, then script code should also be empty"; return false; @@ -123,12 +126,12 @@ bool PaymentsValidators::isValidShippingAddress( bool PaymentsValidators::isValidErrorMsgFormat( const std::string& error, - std::string* optionalErrorMessage) { + std::string* optional_error_message) { if (error.length() <= maximumStringLength) return true; - if (optionalErrorMessage) - *optionalErrorMessage = + if (optional_error_message) + *optional_error_message = "Error message should be at most 2048 characters long"; return false; diff --git a/chromium/components/payments/payments_validators.h b/chromium/components/payments/content/payments_validators.h index 133eecb7c7e..135074cc1aa 100644 --- a/chromium/components/payments/payments_validators.h +++ b/chromium/components/payments/content/payments_validators.h @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PAYMENTS_PAYMENTS_VALIDATORS_H_ -#define COMPONENTS_PAYMENTS_PAYMENTS_VALIDATORS_H_ +#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENTS_VALIDATORS_H_ +#define COMPONENTS_PAYMENTS_CONTENT_PAYMENTS_VALIDATORS_H_ #include <string> -#include "components/payments/payment_request.mojom.h" +#include "base/macros.h" +#include "components/payments/content/payment_request.mojom.h" namespace payments { @@ -22,38 +23,41 @@ class PaymentsValidators { // false if currency |code| is too long (greater than 2048). static bool isValidCurrencyCodeFormat(const std::string& code, const std::string& system, - std::string* optionalErrorMessage); + std::string* optional_error_message); // Returns true if |amount| is a valid currency code as defined in ISO 20022 // CurrencyAnd30Amount. static bool isValidAmountFormat(const std::string& amount, - std::string* optionalErrorMessage); + std::string* optional_error_message); // Returns true if |code| is a valid ISO 3166 country code. static bool isValidCountryCodeFormat(const std::string& code, - std::string* optionalErrorMessage); + std::string* optional_error_message); // Returns true if |code| is a valid ISO 639 language code. static bool isValidLanguageCodeFormat(const std::string& code, - std::string* optionalErrorMessage); + std::string* optional_error_message); // Returns true if |code| is a valid ISO 15924 script code. static bool isValidScriptCodeFormat(const std::string& code, - std::string* optionalErrorMessage); + std::string* optional_error_message); // Returns true if the payment address is valid: // - Has a valid region code // - Has a valid language code, if any. // - Has a valid script code, if any. // A script code should be present only if language code is present. - static bool isValidShippingAddress(const mojom::PaymentAddressPtr&, - std::string* optionalErrorMessage); + static bool isValidShippingAddress(const mojom::PaymentAddressPtr& address, + std::string* optional_error_message); // Returns false if |error| is too long (greater than 2048). static bool isValidErrorMsgFormat(const std::string& code, - std::string* optionalErrorMessage); + std::string* optional_error_message); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(PaymentsValidators); }; } // namespace payments -#endif // COMPONENTS_PAYMENTS_PAYMENTS_VALIDATORS_H_ +#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENTS_VALIDATORS_H_ diff --git a/chromium/components/payments/payments_validators_test.cc b/chromium/components/payments/content/payments_validators_test.cc index 16fedd0e811..8214ce148dc 100644 --- a/chromium/components/payments/payments_validators_test.cc +++ b/chromium/components/payments/content/payments_validators_test.cc @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/payments_validators.h" +#include "components/payments/content/payments_validators.h" -#include "testing/gtest/include/gtest/gtest.h" #include <ostream> // NOLINT +#include "testing/gtest/include/gtest/gtest.h" namespace payments { namespace { diff --git a/chromium/components/payments/core/BUILD.gn b/chromium/components/payments/core/BUILD.gn new file mode 100644 index 00000000000..e0a51dfc193 --- /dev/null +++ b/chromium/components/payments/core/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright 2017 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. + +static_library("core") { + sources = [ + "address_normalizer.cc", + "address_normalizer.h", + "currency_formatter.cc", + "currency_formatter.h", + ] + + deps = [ + "//base", + "//components/autofill/core/browser", + ] + + public_deps = [ + "//third_party/icu", + "//third_party/libaddressinput", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "address_normalizer_unittest.cc", + "currency_formatter_unittest.cc", + ] + + deps = [ + ":core", + "//base", + "//base/test:test_support", + "//components/autofill/core/browser", + "//testing/gtest", + "//third_party/libaddressinput:test_support", + ] +} diff --git a/chromium/components/payments/core/DEPS b/chromium/components/payments/core/DEPS new file mode 100644 index 00000000000..77981288756 --- /dev/null +++ b/chromium/components/payments/core/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + "-content", + "+components/autofill/core", + "+third_party/libaddressinput", +] diff --git a/chromium/components/payments/core/address_normalizer.cc b/chromium/components/payments/core/address_normalizer.cc new file mode 100644 index 00000000000..3114c5a8922 --- /dev/null +++ b/chromium/components/payments/core/address_normalizer.cc @@ -0,0 +1,169 @@ +// Copyright 2017 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/core/address_normalizer.h" + +#include <stddef.h> +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/cancelable_callback.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" +#include "components/autofill/core/browser/address_i18n.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "third_party/libaddressinput/chromium/chrome_address_validator.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" + +namespace payments { +namespace { + +using ::autofill::AutofillProfile; +using ::i18n::addressinput::Source; +using ::i18n::addressinput::Storage; + +class AddressNormalizationRequest : public AddressNormalizer::Request { + public: + // The |delegate| and |address_validator| need to outlive this Request. + AddressNormalizationRequest(const AutofillProfile& profile, + const std::string& region_code, + int timeout_seconds, + AddressNormalizer::Delegate* delegate, + autofill::AddressValidator* address_validator) + : profile_(profile), + region_code_(region_code), + delegate_(delegate), + address_validator_(address_validator), + has_responded_(false), + on_timeout_( + base::Bind(&::payments::AddressNormalizationRequest::OnRulesLoaded, + base::Unretained(this), + false)) { + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, on_timeout_.callback(), + base::TimeDelta::FromSeconds(timeout_seconds)); + } + + ~AddressNormalizationRequest() override {} + + void OnRulesLoaded(bool success) override { + on_timeout_.Cancel(); + + // Check if the timeout happened before the rules were loaded. + if (has_responded_) + return; + has_responded_ = true; + + if (!success) { + delegate_->OnCouldNotNormalize(profile_); + return; + } + + // The rules should be loaded. + DCHECK(address_validator_->AreRulesLoadedForRegion(region_code_)); + + // Create the AddressData from the profile. + ::i18n::addressinput::AddressData address_data = + *autofill::i18n::CreateAddressDataFromAutofillProfile(profile_, + region_code_); + + // Normalize the address. + if (address_validator_ && + address_validator_->NormalizeAddress(&address_data)) { + profile_.SetRawInfo(autofill::ADDRESS_HOME_STATE, + base::UTF8ToUTF16(address_data.administrative_area)); + profile_.SetRawInfo(autofill::ADDRESS_HOME_CITY, + base::UTF8ToUTF16(address_data.locality)); + profile_.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY, + base::UTF8ToUTF16(address_data.dependent_locality)); + } + + delegate_->OnAddressNormalized(profile_); + } + + private: + AutofillProfile profile_; + std::string region_code_; + AddressNormalizer::Delegate* delegate_; + autofill::AddressValidator* address_validator_; + + bool has_responded_; + base::CancelableCallback<void()> on_timeout_; + + DISALLOW_COPY_AND_ASSIGN(AddressNormalizationRequest); +}; + +} // namespace + +AddressNormalizer::AddressNormalizer(std::unique_ptr<Source> source, + std::unique_ptr<Storage> storage) + : address_validator_(std::move(source), std::move(storage), this) {} + +AddressNormalizer::~AddressNormalizer() {} + +void AddressNormalizer::LoadRulesForRegion(const std::string& region_code) { + address_validator_.LoadRules(region_code); +} + +bool AddressNormalizer::AreRulesLoadedForRegion( + const std::string& region_code) { + return address_validator_.AreRulesLoadedForRegion(region_code); +} + +void AddressNormalizer::StartAddressNormalization( + const AutofillProfile& profile, + const std::string& region_code, + int timeout_seconds, + AddressNormalizer::Delegate* requester) { + DCHECK(timeout_seconds >= 0); + + std::unique_ptr<AddressNormalizationRequest> request( + base::MakeUnique<AddressNormalizationRequest>(profile, region_code, + timeout_seconds, requester, + &address_validator_)); + + // Check if the rules are already loaded. + if (AreRulesLoadedForRegion(region_code)) { + request->OnRulesLoaded(true); + } else { + // Setup the variables so the profile gets normalized when the rules have + // finished loading. + auto it = pending_normalization_.find(region_code); + if (it == pending_normalization_.end()) { + // If no entry exists yet, create the entry and assign it to |it|. + it = pending_normalization_ + .insert(std::make_pair(region_code, + std::vector<std::unique_ptr<Request>>())) + .first; + } + + it->second.push_back(std::move(request)); + + // Start loading the rules for that region. If the rules were already in the + // process of being loaded, this call will do nothing. + LoadRulesForRegion(region_code); + } +} + +void AddressNormalizer::OnAddressValidationRulesLoaded( + const std::string& region_code, + bool success) { + // Check if an address normalization is pending. + auto it = pending_normalization_.find(region_code); + if (it != pending_normalization_.end()) { + for (size_t i = 0; i < it->second.size(); ++i) { + it->second[i]->OnRulesLoaded(success); + } + pending_normalization_.erase(it); + } +} + +} // namespace payments
\ No newline at end of file diff --git a/chromium/components/payments/core/address_normalizer.h b/chromium/components/payments/core/address_normalizer.h new file mode 100644 index 00000000000..0280d82b1e3 --- /dev/null +++ b/chromium/components/payments/core/address_normalizer.h @@ -0,0 +1,94 @@ +// Copyright 2017 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. + +#ifndef COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_ +#define COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_ + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "third_party/libaddressinput/chromium/chrome_address_validator.h" + +namespace autofill { +class AutofillProfile; +} + +namespace i18n { +namespace libadderssinput { +class Source; +class Storage; +} +} + +namespace payments { + +// A class used to normalize addresses. +class AddressNormalizer : public autofill::LoadRulesListener { + public: + // The interface for the normalization delegates. + class Delegate { + public: + virtual void OnAddressNormalized( + const autofill::AutofillProfile& normalized_profile) = 0; + + virtual void OnCouldNotNormalize( + const autofill::AutofillProfile& profile) = 0; + + protected: + virtual ~Delegate() {} + }; + + // The interface for the normalization request. + class Request { + public: + virtual void OnRulesLoaded(bool success) = 0; + virtual ~Request() {} + }; + + AddressNormalizer(std::unique_ptr<i18n::addressinput::Source> source, + std::unique_ptr<i18n::addressinput::Storage> storage); + ~AddressNormalizer() override; + + // Start loading the validation rules for the specified |region_code|. + virtual void LoadRulesForRegion(const std::string& region_code); + + // Returns whether the rules for the specified |region_code| have finished + // loading. + bool AreRulesLoadedForRegion(const std::string& region_code); + + // Starts the normalization of the |profile| based on the |region_code|. The + // normalized profile will be returned to the |requester| possibly + // asynchronously. If the normalization is not completed in |timeout_seconds| + // the requester will be informed and the request cancelled. This value should + // be greater or equal to 0, for which it means that the normalization should + // happen synchronously, or not at all if the rules are not already loaded. + // Will start loading the rules for the |region_code| if they had not started + // loading. + void StartAddressNormalization(const autofill::AutofillProfile& profile, + const std::string& region_code, + int timeout_seconds, + Delegate* requester); + + private: + // Called when the validation rules for the |region_code| have finished + // loading. Implementation of the LoadRulesListener interface. + void OnAddressValidationRulesLoaded(const std::string& region_code, + bool success) override; + + // Map associating a region code to pending normalizations. + std::map<std::string, std::vector<std::unique_ptr<Request>>> + pending_normalization_; + + // The address validator used to normalize addresses. + autofill::AddressValidator address_validator_; + + DISALLOW_COPY_AND_ASSIGN(AddressNormalizer); +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CORE_ADDRESS_NORMALIZER_H_ diff --git a/chromium/components/payments/core/address_normalizer_unittest.cc b/chromium/components/payments/core/address_normalizer_unittest.cc new file mode 100644 index 00000000000..0d2f3fae5fc --- /dev/null +++ b/chromium/components/payments/core/address_normalizer_unittest.cc @@ -0,0 +1,191 @@ +// Copyright 2017 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/core/address_normalizer.h" + +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_scheduler.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" +#include "third_party/libaddressinput/src/cpp/test/testdata_source.h" + +namespace payments { +namespace { + +using ::autofill::AutofillProfile; +using ::i18n::addressinput::NullStorage; +using ::i18n::addressinput::Source; +using ::i18n::addressinput::Storage; +using ::i18n::addressinput::TestdataSource; + +// The requester of normalization for this test. +class NormalizationDelegate : public AddressNormalizer::Delegate { + public: + NormalizationDelegate() + : normalized_called_(false), not_normalized_called_(false) {} + + ~NormalizationDelegate() override {} + + void OnAddressNormalized( + const autofill::AutofillProfile& normalized_profile) override { + normalized_called_ = true; + } + + void OnCouldNotNormalize(const autofill::AutofillProfile& profile) override { + not_normalized_called_ = true; + } + + bool normalized_called() { return normalized_called_; } + + bool not_normalized_called() { return not_normalized_called_; } + + private: + bool normalized_called_; + bool not_normalized_called_; + + DISALLOW_COPY_AND_ASSIGN(NormalizationDelegate); +}; + +// Used to load region rules for this test. +class ChromiumTestdataSource : public TestdataSource { + public: + ChromiumTestdataSource() : TestdataSource(true) {} + + ~ChromiumTestdataSource() override {} + + // For this test, only load the rules for the "US". + void Get(const std::string& key, const Callback& data_ready) const override { + data_ready( + true, key, + new std::string("{\"data/US\": " + "{\"id\":\"data/US\",\"key\":\"US\",\"name\":\"UNITED " + "STATES\",\"lang\":\"en\",\"languages\":\"en\"}}")); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource); +}; + +// A test subclass of the AddressNormalizer. Used to simulate rules not being +// loaded. +class TestAddressNormalizer : public AddressNormalizer { + public: + TestAddressNormalizer(std::unique_ptr<i18n::addressinput::Source> source, + std::unique_ptr<i18n::addressinput::Storage> storage) + : AddressNormalizer(std::move(source), std::move(storage)), + should_load_rules_(true) {} + + ~TestAddressNormalizer() override {} + + void ShouldLoadRules(bool should_load_rules) { + should_load_rules_ = should_load_rules; + } + + void LoadRulesForRegion(const std::string& region_code) override { + if (should_load_rules_) { + AddressNormalizer::LoadRulesForRegion(region_code); + } + } + + private: + bool should_load_rules_; + + DISALLOW_COPY_AND_ASSIGN(TestAddressNormalizer); +}; + +} // namespace + +class AddressNormalizerTest : public testing::Test { + protected: + AddressNormalizerTest() + : normalizer_(new TestAddressNormalizer( + std::unique_ptr<Source>(new ChromiumTestdataSource), + std::unique_ptr<Storage>(new NullStorage))) {} + + ~AddressNormalizerTest() override {} + + const std::unique_ptr<TestAddressNormalizer> normalizer_; + + base::test::ScopedTaskScheduler scoped_task_scheduler_; + + private: + DISALLOW_COPY_AND_ASSIGN(AddressNormalizerTest); +}; + +// Tests that rules are not loaded by default. +TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_NotLoaded) { + EXPECT_FALSE(normalizer_->AreRulesLoadedForRegion("US")); +} + +// Tests that the rules are loaded correctly. +TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_Loaded) { + normalizer_->LoadRulesForRegion("US"); + EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion("US")); +} + +// Tests that if the rules are loaded before the normalization is started, the +// normalized profile will be returned to the delegate synchronously. +TEST_F(AddressNormalizerTest, StartNormalization_RulesLoaded) { + NormalizationDelegate delegate; + AutofillProfile profile; + + // Load the rules. + normalizer_->LoadRulesForRegion("US"); + EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion("US")); + + // Start the normalization. + normalizer_->StartAddressNormalization(profile, "US", 0, &delegate); + + // Since the rules are already loaded, the address should be normalized + // synchronously. + EXPECT_TRUE(delegate.normalized_called()); + EXPECT_FALSE(delegate.not_normalized_called()); +} + +// Tests that if the rules are not loaded before the normalization and cannot be +// loaded after, the address will not be normalized and the delegate will be +// notified. +TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillNotLoad) { + NormalizationDelegate delegate; + AutofillProfile profile; + + // Make sure the rules will not be loaded in the StartAddressNormalization + // call. + normalizer_->ShouldLoadRules(false); + + // Start the normalization. + normalizer_->StartAddressNormalization(profile, "US", 0, &delegate); + + // Let the timeout execute. + base::RunLoop().RunUntilIdle(); + + // Since the rules are never loaded and the timeout is 0, the delegate should + // get notified that the address could not be normalized. + EXPECT_FALSE(delegate.normalized_called()); + EXPECT_TRUE(delegate.not_normalized_called()); +} + +// Tests that if the rules are not loaded before the call to +// StartAddressNormalization, they will be loaded in the call. +TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillLoad) { + NormalizationDelegate delegate; + AutofillProfile profile; + + // Start the normalization. + normalizer_->StartAddressNormalization(profile, "US", 0, &delegate); + + // Even if the rules are not loaded before the call to + // StartAddressNormalization, they should get loaded in the call. Since our + // test source is synchronous, the normalization will happen synchronously + // too. + EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion("US")); + EXPECT_TRUE(delegate.normalized_called()); + EXPECT_FALSE(delegate.not_normalized_called()); +} + +} // namespace payments
\ No newline at end of file diff --git a/chromium/components/payments/currency_formatter.cc b/chromium/components/payments/core/currency_formatter.cc index d6d4bc04769..4eb4f74ea06 100644 --- a/chromium/components/payments/currency_formatter.cc +++ b/chromium/components/payments/core/currency_formatter.cc @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/currency_formatter.h" - -#include <memory> +#include "components/payments/core/currency_formatter.h" +#include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "third_party/icu/source/common/unicode/stringpiece.h" #include "third_party/icu/source/common/unicode/uchar.h" -#include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/common/unicode/utypes.h" namespace payments { @@ -36,9 +34,9 @@ const char kEllipsis[] = "\xE2\x80\xA6"; // Returns whether the |currency_code| is valid to be used in ICU. bool ShouldUseCurrencyCode(const std::string& currency_code, - const base::Optional<std::string> currency_system) { - return currency_system.value_or(kIso4217CurrencySystem) == - kIso4217CurrencySystem && + const std::string& currency_system) { + return (currency_system.empty() || + currency_system == kIso4217CurrencySystem) && !currency_code.empty() && currency_code.size() <= kMaxCurrencyCodeLength; } @@ -52,10 +50,9 @@ std::string FormatCurrencyCode(const std::string& currency_code) { } // namespace -CurrencyFormatter::CurrencyFormatter( - const std::string& currency_code, - const base::Optional<std::string> currency_system, - const std::string& locale_name) +CurrencyFormatter::CurrencyFormatter(const std::string& currency_code, + const std::string& currency_system, + const std::string& locale_name) : locale_(locale_name.c_str()), formatted_currency_code_(FormatCurrencyCode(currency_code)) { UErrorCode error_code = U_ZERO_ERROR; diff --git a/chromium/components/payments/currency_formatter.h b/chromium/components/payments/core/currency_formatter.h index 2794b37dcce..eec9d66bf17 100644 --- a/chromium/components/payments/currency_formatter.h +++ b/chromium/components/payments/core/currency_formatter.h @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PAYMENTS_CURRENCY_FORMATTER_H_ -#define COMPONENTS_PAYMENTS_CURRENCY_FORMATTER_H_ +#ifndef COMPONENTS_PAYMENTS_CORE_CURRENCY_FORMATTER_H_ +#define COMPONENTS_PAYMENTS_CORE_CURRENCY_FORMATTER_H_ #include <memory> #include <string> #include "base/macros.h" -#include "base/optional.h" #include "base/strings/string16.h" #include "third_party/icu/source/common/unicode/locid.h" +#include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/i18n/unicode/numfmt.h" namespace payments { @@ -29,7 +29,7 @@ class CurrencyFormatter { // |currency_system| should have been validated (as part of // payment_details_validation.h) before this is created. CurrencyFormatter(const std::string& currency_code, - const base::Optional<std::string> currency_system, + const std::string& currency_system, const std::string& locale_name); ~CurrencyFormatter(); @@ -43,7 +43,9 @@ class CurrencyFormatter { // Returns the formatted currency code (<= 6 characters including ellipsis if // applicable). - std::string formatted_currency_code() { return formatted_currency_code_; } + const std::string& formatted_currency_code() const { + return formatted_currency_code_; + } private: const icu::Locale locale_; @@ -56,4 +58,4 @@ class CurrencyFormatter { } // namespace payments -#endif // COMPONENTS_PAYMENTS_CURRENCY_FORMATTER_H_ +#endif // COMPONENTS_PAYMENTS_CORE_CURRENCY_FORMATTER_H_ diff --git a/chromium/components/payments/currency_formatter_unittest.cc b/chromium/components/payments/core/currency_formatter_unittest.cc index ad679c62460..e55a2fe29a5 100644 --- a/chromium/components/payments/currency_formatter_unittest.cc +++ b/chromium/components/payments/core/currency_formatter_unittest.cc @@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/payments/currency_formatter.h" +#include "components/payments/core/currency_formatter.h" -#include "base/optional.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,7 +30,7 @@ struct TestCase { const char* const locale_name; const std::string expected_amount; const char* const expected_currency_code; - const base::Optional<std::string> currency_system; + const char* const currency_system; }; class PaymentsCurrencyFormatterTest : public testing::TestWithParam<TestCase> { diff --git a/chromium/components/payments/payment_request.cc b/chromium/components/payments/payment_request.cc deleted file mode 100644 index 282b3fa38af..00000000000 --- a/chromium/components/payments/payment_request.cc +++ /dev/null @@ -1,110 +0,0 @@ -// 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/payment_request.h" - -#include "base/memory/ptr_util.h" -#include "components/autofill/core/browser/personal_data_manager.h" -#include "components/payments/payment_details_validation.h" -#include "components/payments/payment_request_delegate.h" -#include "components/payments/payment_request_web_contents_manager.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/web_contents.h" - -namespace payments { - -PaymentRequest::PaymentRequest( - content::WebContents* web_contents, - std::unique_ptr<PaymentRequestDelegate> delegate, - PaymentRequestWebContentsManager* manager, - mojo::InterfaceRequest<payments::mojom::PaymentRequest> request) - : web_contents_(web_contents), - delegate_(std::move(delegate)), - manager_(manager), - binding_(this, std::move(request)) { - binding_.set_connection_error_handler( - base::Bind(&PaymentRequest::OnError, base::Unretained(this))); -} - -PaymentRequest::~PaymentRequest() {} - -void PaymentRequest::Init( - payments::mojom::PaymentRequestClientPtr client, - std::vector<payments::mojom::PaymentMethodDataPtr> methodData, - payments::mojom::PaymentDetailsPtr details, - payments::mojom::PaymentOptionsPtr options) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::string error; - if (!payments::validatePaymentDetails(details, &error)) { - LOG(ERROR) << error; - OnError(); - client_.reset(); - return; - } - client_ = std::move(client); - details_ = std::move(details); -} - -void PaymentRequest::Show() { - if (!client_.is_bound() || !binding_.is_bound()) { - OnError(); - return; - } - delegate_->ShowPaymentRequestDialog(this); -} - -void PaymentRequest::Cancel() { - client_->OnError(payments::mojom::PaymentErrorReason::USER_CANCEL); -} - -void PaymentRequest::OnError() { - binding_.Close(); - manager_->DestroyRequest(this); -} - -CurrencyFormatter* PaymentRequest::GetOrCreateCurrencyFormatter( - const std::string& currency_code, - const base::Optional<std::string> currency_system, - const std::string& locale_name) { - if (!currency_formatter_) { - currency_formatter_.reset( - new CurrencyFormatter(currency_code, currency_system, locale_name)); - } - - return currency_formatter_.get(); -} - -autofill::AutofillProfile* PaymentRequest::GetCurrentlySelectedProfile() { - // TODO(tmartino): Implement more sophisticated algorithm for populating - // this when it starts empty. - if (!profile_) { - autofill::PersonalDataManager* data_manager = - delegate_->GetPersonalDataManager(); - auto profiles = data_manager->GetProfiles(); - if (!profiles.empty()) - profile_ = base::MakeUnique<autofill::AutofillProfile>(*profiles[0]); - } - return profile_ ? profile_.get() : nullptr; -} - -autofill::CreditCard* PaymentRequest::GetCurrentlySelectedCreditCard() { - // TODO(anthonyvd): Change this code to prioritize server cards and implement - // a way to modify this function's return value. - autofill::PersonalDataManager* data_manager = - delegate_->GetPersonalDataManager(); - - const std::vector<autofill::CreditCard*> cards = - data_manager->GetCreditCardsToSuggest(); - - auto first_complete_card = std::find_if( - cards.begin(), - cards.end(), - [] (autofill::CreditCard* card) { - return card->IsValid(); - }); - - return first_complete_card == cards.end() ? nullptr : *first_complete_card; -} - -} // namespace payments diff --git a/chromium/components/payments/payment_request.h b/chromium/components/payments/payment_request.h deleted file mode 100644 index 6c55cca9ae4..00000000000 --- a/chromium/components/payments/payment_request.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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. - -#ifndef COMPONENTS_PAYMENTS_PAYMENT_REQUEST_H_ -#define COMPONENTS_PAYMENTS_PAYMENT_REQUEST_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "components/payments/currency_formatter.h" -#include "components/payments/payment_request.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" - -namespace autofill { -class AutofillProfile; -class CreditCard; -} - -namespace content { -class WebContents; -} - -namespace payments { - -class PaymentRequestDelegate; -class PaymentRequestWebContentsManager; - -class PaymentRequest : payments::mojom::PaymentRequest { - public: - PaymentRequest( - content::WebContents* web_contents, - std::unique_ptr<PaymentRequestDelegate> delegate, - PaymentRequestWebContentsManager* manager, - mojo::InterfaceRequest<payments::mojom::PaymentRequest> request); - ~PaymentRequest() override; - - // payments::mojom::PaymentRequest "stub" - void Init(payments::mojom::PaymentRequestClientPtr client, - std::vector<payments::mojom::PaymentMethodDataPtr> methodData, - payments::mojom::PaymentDetailsPtr details, - payments::mojom::PaymentOptionsPtr options) override; - void Show() override; - void UpdateWith(payments::mojom::PaymentDetailsPtr details) override {} - void Abort() override {} - void Complete(payments::mojom::PaymentComplete result) override {} - void CanMakePayment() override {} - - void Cancel(); - void OnError(); - - // Returns the CurrencyFormatter instance for this PaymentRequest. - // |locale_name| should be the result of the browser's GetApplicationLocale(). - // Note: Having multiple currencies per PaymentRequest is not supported; hence - // the CurrencyFormatter is cached here. - CurrencyFormatter* GetOrCreateCurrencyFormatter( - const std::string& currency_code, - const base::Optional<std::string> currency_system, - const std::string& locale_name); - - // Returns the Autofill Profile, representing the shipping address and contact - // information, currently selected for this PaymentRequest flow. If - // unpopulated, populates with and returns the 0th profile on record for this - // user, if it exists; or nullptr otherwise. Profile is owned by the request - // object, not the caller. - autofill::AutofillProfile* GetCurrentlySelectedProfile(); - - // Returns the currently selected credit card for this PaymentRequest flow. - // It's not guaranteed to be complete. Returns nullptr if there is no selected - // card. - autofill::CreditCard* GetCurrentlySelectedCreditCard(); - - payments::mojom::PaymentDetails* details() { return details_.get(); } - content::WebContents* web_contents() { return web_contents_; } - - private: - content::WebContents* web_contents_; - std::unique_ptr<PaymentRequestDelegate> delegate_; - // |manager_| owns this PaymentRequest. - PaymentRequestWebContentsManager* manager_; - mojo::Binding<payments::mojom::PaymentRequest> binding_; - payments::mojom::PaymentRequestClientPtr client_; - payments::mojom::PaymentDetailsPtr details_; - std::unique_ptr<CurrencyFormatter> currency_formatter_; - std::unique_ptr<autofill::AutofillProfile> profile_; - - DISALLOW_COPY_AND_ASSIGN(PaymentRequest); -}; - -} // namespace payments - -#endif // COMPONENTS_PAYMENTS_PAYMENT_REQUEST_H_ |