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..2cf8cd958990eb1ade34df3775f58b8cb89e3584 | 
| --- /dev/null | 
| +++ b/components/payments/payment_details_validation.cc | 
| @@ -0,0 +1,165 @@ | 
| +// 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_details_validation.h" | 
| + | 
| +#include <set> | 
| +#include <vector> | 
| + | 
| +#include "components/payments/payment_request.mojom.h" | 
| +#include "components/payments/payments_validators.h" | 
| + | 
| +namespace { | 
| + | 
| +// Validates ShippingOption or PaymentItem, which happen to have identical | 
| +// fields, except for "id", which is present only in ShippingOption. | 
| +template <typename T> | 
| +bool validateShippingOptionOrPaymentItem(const T& item, | 
| + std::string* error_message) { | 
| + if (item->label.empty()) { | 
| + *error_message = "Item label required"; | 
| + return false; | 
| + } | 
| + | 
| + if (!item->amount) { | 
| + *error_message = "Currency amount required"; | 
| + return false; | 
| + } | 
| + | 
| + if (item->amount->currency.empty()) { | 
| + *error_message = "Currency code required"; | 
| + return false; | 
| + } | 
| + | 
| + if (item->amount->value.empty()) { | 
| + *error_message = "Currency value required"; | 
| + return false; | 
| + } | 
| + | 
| + if (!payments::PaymentsValidators::isValidCurrencyCodeFormat( | 
| + item->amount->currency, "", error_message)) { | 
| 
 
please use gerrit instead
2016/10/31 14:31:15
Ideally "" would be replaced with item->amount->cu
 
Kevin Bailey
2016/10/31 20:32:00
Sorry, missed this one. Also, really named it 'cur
 
 | 
| + return false; | 
| + } | 
| + | 
| + if (!payments::PaymentsValidators::isValidAmountFormat( | 
| + item->amount->value, error_message)) { | 
| + return false; | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +bool validateDisplayItems( | 
| + const std::vector<blink::mojom::PaymentItemPtr>& items, | 
| + std::string* error_message) { | 
| + for (const auto& item : items) { | 
| + if (!validateShippingOptionOrPaymentItem(item, error_message)) | 
| + return false; | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +bool validateShippingOptions( | 
| + const std::vector<blink::mojom::PaymentShippingOptionPtr>& options, | 
| + std::string* error_message) { | 
| + std::set<std::string> uniqueIds; | 
| + for (const auto& option : options) { | 
| + if (option->id.empty()) { | 
| + *error_message = "ShippingOption id required"; | 
| + return false; | 
| + } | 
| + | 
| + if (uniqueIds.find(option->id) != uniqueIds.end()) { | 
| + *error_message = "Duplicate shipping option identifiers are not allowed"; | 
| + return false; | 
| + } | 
| + uniqueIds.insert(option->id); | 
| + | 
| + if (!validateShippingOptionOrPaymentItem(option, error_message)) | 
| + return false; | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +bool validatePaymentDetailsModifiers( | 
| + const std::vector<blink::mojom::PaymentDetailsModifierPtr>& modifiers, | 
| + std::string* error_message) { | 
| + if (modifiers.empty()) { | 
| + *error_message = | 
| + "Must specify at least one payment details modifier"; | 
| + return false; | 
| + } | 
| + | 
| + std::set<mojo::String> uniqueMethods; | 
| + for (const auto& modifier : modifiers) { | 
| + if (modifier->supported_methods.empty()) { | 
| + *error_message = "Must specify at least one payment method identifier"; | 
| + return false; | 
| + } | 
| + | 
| + for (const auto& method : modifier->supported_methods) { | 
| + if (uniqueMethods.find(method) != uniqueMethods.end()) { | 
| + *error_message = | 
| + "Duplicate payment method identifiers are not allowed"; | 
| + return false; | 
| + } | 
| + uniqueMethods.insert(method); | 
| + } | 
| + | 
| + if (modifier->total) { | 
| + if (!validateShippingOptionOrPaymentItem(modifier->total, error_message)) | 
| + return false; | 
| + | 
| + if (modifier->total->amount->value[0] == '-') { | 
| + *error_message = "Total amount value should be non-negative"; | 
| + return false; | 
| + } | 
| + } | 
| + | 
| + if (modifier->additional_display_items.size()) { | 
| + if (!validateDisplayItems( | 
| + modifier->additional_display_items, error_message)) { | 
| + return false; | 
| + } | 
| + } | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| +namespace payments { | 
| + | 
| +bool validatePaymentDetails(const blink::mojom::PaymentDetailsPtr& details, | 
| + std::string* error_message) { | 
| + if (details->total.is_null()) { | 
| + *error_message = "Must specify total"; | 
| + return false; | 
| + } | 
| + | 
| + if (!validateShippingOptionOrPaymentItem(details->total, error_message)) | 
| + return false; | 
| + | 
| + if (details->total->amount->value[0] == '-') { | 
| + *error_message = "Total amount value should be non-negative"; | 
| + return false; | 
| + } | 
| + | 
| + if (details->display_items.size()) { | 
| + if (!validateDisplayItems(details->display_items, error_message)) | 
| + return false; | 
| + } | 
| + | 
| + if (details->shipping_options.size()) { | 
| + if (!validateShippingOptions(details->shipping_options, error_message)) | 
| + return false; | 
| + } | 
| + | 
| + if (details->modifiers.size()) { | 
| + if (!validatePaymentDetailsModifiers(details->modifiers, error_message)) | 
| + return false; | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +} // namespace payments |