Chromium Code Reviews| Index: components/payments/payment_details_validation.cc |
| diff --git a/components/payments/payment_details_validation.cc b/components/payments/payment_details_validation.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..eac7c85b286d1234eafa6f9deaa682faf19c73c7 |
| --- /dev/null |
| +++ b/components/payments/payment_details_validation.cc |
| @@ -0,0 +1,172 @@ |
| +// 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 <set> |
| +#include <vector> |
| + |
| +#include "components/payments/payment_details_validation.h" |
| + |
| +#include "components/payments/payment_request.mojom.h" |
| +#include "components/payments/payments_validators.h" |
| + |
| +namespace payments { |
| + |
| +// Validates ShippingOption or PaymentItem, which happen to have identical |
| +// fields, except for "id", which is present only in ShippingOption. |
| +template <typename T> |
| +void validateShippingOptionOrPaymentItem(const T& item, |
| + ExceptionState& exceptionState) { |
| + if (item->label.empty()) { |
| + exceptionState.throwTypeError("Item label required"); |
| + return; |
| + } |
| + |
| + if (!item->amount) { |
| + exceptionState.throwTypeError("Currency amount required"); |
| + return; |
| + } |
| + |
| + if (item->amount->currency.empty()) { |
| + exceptionState.throwTypeError("Currency code required"); |
| + return; |
| + } |
| + |
| + if (item->amount->value.empty()) { |
| + exceptionState.throwTypeError("Currency value required"); |
| + return; |
| + } |
| + |
| + std::string errorMessage; |
| + if (!PaymentsValidators::isValidCurrencyCodeFormat(item->amount->currency, |
| + &errorMessage)) { |
| + exceptionState.throwTypeError(errorMessage); |
| + return; |
| + } |
| + |
| + if (!PaymentsValidators::isValidAmountFormat(item->amount->value, |
| + &errorMessage)) { |
| + exceptionState.throwTypeError(errorMessage); |
| + return; |
| + } |
| +} |
| + |
| +void validateDisplayItems( |
| + const std::vector<blink::mojom::PaymentItemPtr>& items, |
| + ExceptionState& exceptionState) { |
| + for (const auto& item : items) { |
| + validateShippingOptionOrPaymentItem(item, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + } |
| +} |
| + |
| +void validateShippingOptions( |
| + const std::vector<blink::mojom::PaymentShippingOptionPtr>& options, |
| + ExceptionState& exceptionState) { |
| + std::set<std::string> uniqueIds; |
| + for (const auto& option : options) { |
| + if (option->id.empty()) { |
| + exceptionState.throwTypeError("ShippingOption id required"); |
| + return; |
| + } |
| + |
| + if (uniqueIds.find(option->id) != uniqueIds.end()) { |
| + exceptionState.throwTypeError( |
| + "Duplicate shipping option identifiers are not allowed"); |
| + return; |
| + } |
| + uniqueIds.insert(option->id); |
| + |
| + validateShippingOptionOrPaymentItem(option, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + } |
| +} |
| + |
| +void validatePaymentDetailsModifiers( |
| + const std::vector<blink::mojom::PaymentDetailsModifierPtr>& modifiers, |
| + ExceptionState& exceptionState) { |
| + if (modifiers.empty()) { |
| + exceptionState.throwTypeError( |
| + "Must specify at least one payment details modifier"); |
| + return; |
| + } |
| + |
| + std::set<mojo::String> uniqueMethods; |
| + for (const auto& modifier : modifiers) { |
| + if (modifier->supported_methods.empty()) { |
| + exceptionState.throwTypeError( |
| + "Must specify at least one payment method identifier"); |
| + return; |
| + } |
| + |
| + for (const auto& method : modifier->supported_methods) { |
| + if (uniqueMethods.find(method) != uniqueMethods.end()) { |
| + exceptionState.throwTypeError( |
| + "Duplicate payment method identifiers are not allowed"); |
| + return; |
| + } |
| + uniqueMethods.insert(method); |
| + } |
| + |
| + if (modifier->total) { |
| + validateShippingOptionOrPaymentItem(modifier->total, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + |
| + if (modifier->total->amount->value[0] == '-') { |
| + exceptionState.throwTypeError( |
| + "Total amount value should be non-negative"); |
| + return; |
| + } |
| + } |
| + |
| + if (modifier->additional_display_items.size()) { |
| + validateDisplayItems(modifier->additional_display_items, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + } |
| + } |
| +} |
| + |
|
please use gerrit instead
2016/10/27 17:14:25
The functions above can be in anonymous namespace
Kevin Bailey
2016/10/27 22:17:53
Done.
|
| +void validatePaymentDetails(const blink::mojom::PaymentDetailsPtr& details, |
| + ExceptionState& exceptionState) { |
| + if (details->total.is_null()) { |
| + exceptionState.throwTypeError("Must specify total"); |
| + return; |
| + } |
| + |
| + validateShippingOptionOrPaymentItem(details->total, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + |
| + if (details->total->amount->value[0] == '-') { |
| + exceptionState.throwTypeError("Total amount value should be non-negative"); |
| + return; |
| + } |
| + |
| + if (details->display_items.size()) { |
| + validateDisplayItems(details->display_items, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + } |
| + |
| + if (details->shipping_options.size()) { |
| + validateShippingOptions(details->shipping_options, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + } |
| + |
| + if (details->modifiers.size()) { |
| + validatePaymentDetailsModifiers(details->modifiers, exceptionState); |
| + } |
| +} |
| + |
| +bool validatePaymentDetails(const blink::mojom::PaymentDetailsPtr& details) { |
| + ExceptionState exceptionState; |
| + validatePaymentDetails(details, exceptionState); |
| + return exceptionState.hadException(); |
| +} |
| + |
| +} // namespace payments |