Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Unified Diff: third_party/WebKit/Source/modules/payments/PaymentRequest.cpp

Issue 2851383002: Verify behavior of PaymentRequest constructor. (Closed)
Patch Set: Comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index c1601547e2a5b1d3a52af87e69387c472846ada0..3304e37667e3189e454e3d3249c96a5491e8a4b7 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -136,47 +136,44 @@ static const int kCompleteTimeoutSeconds = 60;
// fields, except for "id", which is present only in ShippingOption.
template <typename T>
void ValidateShippingOptionOrPaymentItem(const T& item,
+ const String& item_name,
+ ExecutionContext& execution_context,
ExceptionState& exception_state) {
- if (!item.hasLabel() || item.label().IsEmpty()) {
- exception_state.ThrowTypeError("Item label required");
- return;
- }
-
- if (!item.hasAmount()) {
- exception_state.ThrowTypeError("Currency amount required");
- return;
- }
+ DCHECK(item.hasLabel());
+ DCHECK(item.hasAmount());
+ DCHECK(item.amount().hasValue());
+ DCHECK(item.amount().hasCurrency());
- if (!item.amount().hasCurrency()) {
- exception_state.ThrowTypeError("Currency code required");
+ String error_message;
+ if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(), item_name,
+ &error_message)) {
+ exception_state.ThrowTypeError(error_message);
return;
}
- if (!item.amount().hasValue()) {
- exception_state.ThrowTypeError("Currency value required");
+ if (item.label().IsEmpty()) {
+ execution_context.AddConsoleMessage(
+ ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel,
Marijn Kruisselbrink 2017/05/03 23:10:59 nit: would it make sense for this message to expla
please use gerrit instead 2017/05/04 15:17:15 Done.
+ "Empty " + item_name + " label is discouraged"));
return;
}
- String error_message;
if (!PaymentsValidators::IsValidCurrencyCodeFormat(
item.amount().currency(), item.amount().currencySystem(),
&error_message)) {
exception_state.ThrowTypeError(error_message);
return;
}
-
- if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(),
- &error_message)) {
- exception_state.ThrowTypeError(error_message);
- return;
- }
}
void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input,
+ const String& item_names,
Vector<PaymentItemPtr>& output,
+ ExecutionContext& execution_context,
ExceptionState& exception_state) {
for (const PaymentItem& item : input) {
- ValidateShippingOptionOrPaymentItem(item, exception_state);
+ ValidateShippingOptionOrPaymentItem(item, item_names, execution_context,
+ exception_state);
if (exception_state.HadException())
return;
output.push_back(payments::mojom::blink::PaymentItem::From(item));
@@ -191,12 +188,21 @@ void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input,
void ValidateAndConvertShippingOptions(
const HeapVector<PaymentShippingOption>& input,
Vector<PaymentShippingOptionPtr>& output,
+ String& shipping_option_output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
HashSet<String> unique_ids;
for (const PaymentShippingOption& option : input) {
- if (!option.hasId() || option.id().IsEmpty()) {
- exception_state.ThrowTypeError("ShippingOption id required");
+ ValidateShippingOptionOrPaymentItem(option, "shippingOptions",
+ execution_context, exception_state);
+ if (exception_state.HadException())
+ return;
+
+ DCHECK(option.hasId());
+ if (option.id().IsEmpty()) {
+ execution_context.AddConsoleMessage(
+ ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
+ "Empty shipping option ID is discouraged"));
Marijn Kruisselbrink 2017/05/03 23:10:59 nit: same here, why is an empty ID a problem? If I
please use gerrit instead 2017/05/04 15:17:15 Done.
return;
}
@@ -207,14 +213,14 @@ void ValidateAndConvertShippingOptions(
"' is treated as an invalid address indicator."));
// Clear |output| instead of throwing an exception.
output.clear();
+ shipping_option_output = String();
return;
}
- unique_ids.insert(option.id());
+ if (option.selected())
+ shipping_option_output = option.id();
- ValidateShippingOptionOrPaymentItem(option, exception_state);
- if (exception_state.HadException())
- return;
+ unique_ids.insert(option.id());
output.push_back(
payments::mojom::blink::PaymentShippingOption::From(option));
@@ -222,9 +228,12 @@ void ValidateAndConvertShippingOptions(
}
void ValidateAndConvertTotal(const PaymentItem& input,
+ const String& item_name,
PaymentItemPtr& output,
+ ExecutionContext& execution_context,
ExceptionState& exception_state) {
- ValidateShippingOptionOrPaymentItem(input, exception_state);
+ ValidateShippingOptionOrPaymentItem(input, item_name, execution_context,
+ exception_state);
if (exception_state.HadException())
return;
@@ -398,16 +407,12 @@ void StringifyAndParseMethodSpecificData(
ExecutionContext& execution_context,
ExceptionState& exception_state) {
DCHECK(!input.IsEmpty());
- if (!input.V8Value()->IsObject() || input.V8Value()->IsArray()) {
- exception_state.ThrowTypeError("Data should be a JSON-serializable object");
- return;
- }
-
v8::Local<v8::String> value;
- if (!v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
+ if (!input.V8Value()->IsObject() || input.V8Value()->IsArray() ||
haraken 2017/05/04 09:47:51 Is it worth checking IsArray? To check whether the
please use gerrit instead 2017/05/04 15:17:15 Good point, the spec does prohibit arrays. Added a
+ !v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
.ToLocal(&value)) {
exception_state.ThrowTypeError(
- "Unable to parse payment method specific data");
+ "Payment method data should be a JSON-serializable object");
return;
}
@@ -435,16 +440,11 @@ void ValidateAndConvertPaymentDetailsModifiers(
Vector<PaymentDetailsModifierPtr>& output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
- if (input.IsEmpty()) {
- exception_state.ThrowTypeError(
- "Must specify at least one payment details modifier");
- return;
- }
-
for (const PaymentDetailsModifier& modifier : input) {
output.push_back(payments::mojom::blink::PaymentDetailsModifier::New());
if (modifier.hasTotal()) {
- ValidateAndConvertTotal(modifier.total(), output.back()->total,
+ ValidateAndConvertTotal(modifier.total(), "modifier total",
+ output.back()->total, execution_context,
exception_state);
if (exception_state.HadException())
return;
@@ -452,8 +452,9 @@ void ValidateAndConvertPaymentDetailsModifiers(
if (modifier.hasAdditionalDisplayItems()) {
ValidateAndConvertDisplayItems(modifier.additionalDisplayItems(),
+ "additional display items in modifier",
output.back()->additional_display_items,
- exception_state);
+ execution_context, exception_state);
if (exception_state.HadException())
return;
}
@@ -478,39 +479,29 @@ void ValidateAndConvertPaymentDetailsModifiers(
}
}
-String GetSelectedShippingOption(
- const Vector<PaymentShippingOptionPtr>& shipping_options) {
- String result;
- for (const PaymentShippingOptionPtr& shipping_option : shipping_options) {
- if (shipping_option->selected)
- result = shipping_option->id;
- }
- return result;
-}
-
void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input,
- bool request_shipping,
PaymentDetailsPtr& output,
String& shipping_option_output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
if (input.hasDisplayItems()) {
- ValidateAndConvertDisplayItems(input.displayItems(), output->display_items,
+ ValidateAndConvertDisplayItems(input.displayItems(), "display items",
+ output->display_items, execution_context,
exception_state);
if (exception_state.HadException())
return;
}
- if (input.hasShippingOptions() && request_shipping) {
- ValidateAndConvertShippingOptions(input.shippingOptions(),
- output->shipping_options,
- execution_context, exception_state);
+ if (input.hasShippingOptions()) {
+ ValidateAndConvertShippingOptions(
+ input.shippingOptions(), output->shipping_options,
+ shipping_option_output, execution_context, exception_state);
if (exception_state.HadException())
return;
+ } else {
+ shipping_option_output = String();
}
- shipping_option_output = GetSelectedShippingOption(output->shipping_options);
-
if (input.hasModifiers()) {
ValidateAndConvertPaymentDetailsModifiers(
input.modifiers(), output->modifiers, execution_context,
@@ -521,44 +512,35 @@ void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input,
}
void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit& input,
- bool request_shipping,
PaymentDetailsPtr& output,
String& shipping_option_output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
- ValidateAndConvertPaymentDetailsBase(input, request_shipping, output,
- shipping_option_output,
- execution_context, exception_state);
+ DCHECK(input.hasTotal());
+ ValidateAndConvertTotal(input.total(), "total", output->total,
+ execution_context, exception_state);
if (exception_state.HadException())
return;
- if (!input.hasTotal()) {
- exception_state.ThrowTypeError("Must specify total");
+ ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
+ execution_context, exception_state);
+ if (exception_state.HadException())
return;
- }
-
- if (input.hasId())
- output->id = input.id();
- else
- output->id = CreateCanonicalUUIDString();
-
- ValidateAndConvertTotal(input.total(), output->total, exception_state);
}
void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate& input,
- bool request_shipping,
PaymentDetailsPtr& output,
String& shipping_option_output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
- ValidateAndConvertPaymentDetailsBase(input, request_shipping, output,
- shipping_option_output,
+ ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
execution_context, exception_state);
if (exception_state.HadException())
return;
if (input.hasTotal()) {
- ValidateAndConvertTotal(input.total(), output->total, exception_state);
+ ValidateAndConvertTotal(input.total(), "total", output->total,
+ execution_context, exception_state);
if (exception_state.HadException())
return;
}
@@ -582,15 +564,15 @@ void ValidateAndConvertPaymentMethodData(
ExecutionContext& execution_context,
ExceptionState& exception_state) {
if (input.IsEmpty()) {
- exception_state.ThrowTypeError(
- "Must specify at least one payment method identifier");
+ exception_state.ThrowTypeError("At least one payment method is required");
return;
}
for (const PaymentMethodData payment_method_data : input) {
if (payment_method_data.supportedMethods().IsEmpty()) {
exception_state.ThrowTypeError(
- "Must specify at least one payment method identifier");
+ "Each payment method needs to include at least one payment method "
+ "identifier");
return;
}
@@ -608,17 +590,6 @@ void ValidateAndConvertPaymentMethodData(
}
}
-String GetValidShippingType(const String& shipping_type) {
- static const char* const kValidValues[] = {
- "shipping", "delivery", "pickup",
- };
- for (size_t i = 0; i < arraysize(kValidValues); i++) {
- if (shipping_type == kValidValues[i])
- return shipping_type;
- }
- return kValidValues[0];
-}
-
bool AllowedToUsePaymentRequest(const Frame* frame) {
// To determine whether a Document object |document| is allowed to use the
// feature indicated by attribute name |allowpaymentrequest|, run these steps:
@@ -812,8 +783,8 @@ void PaymentRequest::OnUpdatePaymentDetails(
PaymentDetailsPtr validated_details =
payments::mojom::blink::PaymentDetails::New();
ValidateAndConvertPaymentDetailsUpdate(
- details, options_.requestShipping(), validated_details, shipping_option_,
- *GetExecutionContext(), exception_state);
+ details, validated_details, shipping_option_, *GetExecutionContext(),
+ exception_state);
if (exception_state.HadException()) {
show_resolver_->Reject(
DOMException::Create(kSyntaxError, exception_state.Message()));
@@ -821,6 +792,9 @@ void PaymentRequest::OnUpdatePaymentDetails(
return;
}
+ if (!options_.requestShipping())
+ validated_details->shipping_options.clear();
+
payment_provider_->UpdateWith(std::move(validated_details));
}
@@ -860,12 +834,6 @@ PaymentRequest::PaymentRequest(ExecutionContext* execution_context,
TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetFrame()),
this,
&PaymentRequest::OnCompleteTimeout) {
- Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
- ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
- *GetExecutionContext(), exception_state);
- if (exception_state.HadException())
- return;
-
if (!GetExecutionContext()->IsSecureContext()) {
exception_state.ThrowSecurityError("Must be in a secure context");
return;
@@ -880,16 +848,28 @@ PaymentRequest::PaymentRequest(ExecutionContext* execution_context,
PaymentDetailsPtr validated_details =
payments::mojom::blink::PaymentDetails::New();
- ValidateAndConvertPaymentDetailsInit(details, options_.requestShipping(),
- validated_details, shipping_option_,
- *GetExecutionContext(), exception_state);
+ validated_details->id = id_ =
+ details.hasId() ? details.id() : CreateCanonicalUUIDString();
+
+ Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
+ ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
+ *GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;
- id_ = validated_details->id;
+ ValidateAndConvertPaymentDetailsInit(details, validated_details,
+ shipping_option_, *GetExecutionContext(),
+ exception_state);
+ if (exception_state.HadException())
+ return;
if (options_.requestShipping())
- shipping_type_ = GetValidShippingType(options_.shippingType());
+ shipping_type_ = options_.shippingType();
+ else
+ validated_details->shipping_options.clear();
+
+ DCHECK(shipping_type_.IsNull() || shipping_type_ == "shipping" ||
+ shipping_type_ == "delivery" || shipping_type_ == "pickup");
GetFrame()->GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&payment_provider_));

Powered by Google App Engine
This is Rietveld 408576698