blob: c61946e216bc42aa0903feea3bd23588dd91c994 [file] [log] [blame]
// 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_details_validation.h"
#include <set>
#include <vector>
#include "components/payments/content/payments_validators.h"
#include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
namespace payments {
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,
const payments::mojom::PaymentItemPtr& total,
std::string* error_message) {
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 (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,
error_message)) {
return false;
}
if (!payments::PaymentsValidators::isValidAmountFormat(item->amount->value,
error_message)) {
return false;
}
return true;
}
bool validateDisplayItems(
const std::vector<payments::mojom::PaymentItemPtr>& items,
const payments::mojom::PaymentItemPtr& total,
std::string* error_message) {
for (const auto& item : items) {
if (!validateShippingOptionOrPaymentItem(item, total, error_message))
return false;
}
return true;
}
bool validateShippingOptions(
const std::vector<payments::mojom::PaymentShippingOptionPtr>& options,
const payments::mojom::PaymentItemPtr& total,
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, total, error_message))
return false;
}
return true;
}
bool validatePaymentDetailsModifiers(
const std::vector<payments::mojom::PaymentDetailsModifierPtr>& modifiers,
const payments::mojom::PaymentItemPtr& total,
std::string* error_message) {
if (modifiers.empty()) {
*error_message = "Must specify at least one payment details modifier";
return false;
}
for (const auto& modifier : modifiers) {
if (!modifier->method_data) {
*error_message = "Method data required";
return false;
}
if (modifier->method_data->supported_methods.empty()) {
*error_message = "Must specify at least one payment method identifier";
return false;
}
if (modifier->total) {
if (!validateShippingOptionOrPaymentItem(modifier->total, 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, total,
error_message)) {
return false;
}
}
}
return true;
}
} // namespace
bool validatePaymentDetails(const mojom::PaymentDetailsPtr& details,
std::string* error_message) {
if (details->total) {
if (!validateShippingOptionOrPaymentItem(details->total, 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, details->total,
error_message))
return false;
}
if (details->shipping_options.size()) {
if (!validateShippingOptions(details->shipping_options, details->total,
error_message))
return false;
}
if (details->modifiers.size()) {
if (!validatePaymentDetailsModifiers(details->modifiers, details->total,
error_message))
return false;
}
if (!PaymentsValidators::isValidErrorMsgFormat(details->error, error_message))
return false;
return true;
}
} // namespace payments