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

Side by Side Diff: third_party/WebKit/Source/modules/payments/PaymentRequest.cpp

Issue 2851383002: Verify behavior of PaymentRequest constructor. (Closed)
Patch Set: Comments Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/payments/PaymentRequest.h" 5 #include "modules/payments/PaymentRequest.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <utility> 8 #include <utility>
9 #include "bindings/core/v8/ExceptionState.h" 9 #include "bindings/core/v8/ExceptionState.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h" 10 #include "bindings/core/v8/ScriptPromiseResolver.h"
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 namespace { 129 namespace {
130 130
131 // If the website does not call complete() 60 seconds after show() has been 131 // If the website does not call complete() 60 seconds after show() has been
132 // resolved, then behave as if the website called complete("fail"). 132 // resolved, then behave as if the website called complete("fail").
133 static const int kCompleteTimeoutSeconds = 60; 133 static const int kCompleteTimeoutSeconds = 60;
134 134
135 // Validates ShippingOption or PaymentItem, which happen to have identical 135 // Validates ShippingOption or PaymentItem, which happen to have identical
136 // fields, except for "id", which is present only in ShippingOption. 136 // fields, except for "id", which is present only in ShippingOption.
137 template <typename T> 137 template <typename T>
138 void ValidateShippingOptionOrPaymentItem(const T& item, 138 void ValidateShippingOptionOrPaymentItem(const T& item,
139 const String& item_name,
140 ExecutionContext& execution_context,
139 ExceptionState& exception_state) { 141 ExceptionState& exception_state) {
140 if (!item.hasLabel() || item.label().IsEmpty()) { 142 DCHECK(item.hasLabel());
141 exception_state.ThrowTypeError("Item label required"); 143 DCHECK(item.hasAmount());
144 DCHECK(item.amount().hasValue());
145 DCHECK(item.amount().hasCurrency());
146
147 String error_message;
148 if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(), item_name,
149 &error_message)) {
150 exception_state.ThrowTypeError(error_message);
142 return; 151 return;
143 } 152 }
144 153
145 if (!item.hasAmount()) { 154 if (item.label().IsEmpty()) {
146 exception_state.ThrowTypeError("Currency amount required"); 155 execution_context.AddConsoleMessage(
156 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.
157 "Empty " + item_name + " label is discouraged"));
147 return; 158 return;
148 } 159 }
149 160
150 if (!item.amount().hasCurrency()) {
151 exception_state.ThrowTypeError("Currency code required");
152 return;
153 }
154
155 if (!item.amount().hasValue()) {
156 exception_state.ThrowTypeError("Currency value required");
157 return;
158 }
159
160 String error_message;
161 if (!PaymentsValidators::IsValidCurrencyCodeFormat( 161 if (!PaymentsValidators::IsValidCurrencyCodeFormat(
162 item.amount().currency(), item.amount().currencySystem(), 162 item.amount().currency(), item.amount().currencySystem(),
163 &error_message)) { 163 &error_message)) {
164 exception_state.ThrowTypeError(error_message); 164 exception_state.ThrowTypeError(error_message);
165 return; 165 return;
166 } 166 }
167
168 if (!PaymentsValidators::IsValidAmountFormat(item.amount().value(),
169 &error_message)) {
170 exception_state.ThrowTypeError(error_message);
171 return;
172 }
173 } 167 }
174 168
175 void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input, 169 void ValidateAndConvertDisplayItems(const HeapVector<PaymentItem>& input,
170 const String& item_names,
176 Vector<PaymentItemPtr>& output, 171 Vector<PaymentItemPtr>& output,
172 ExecutionContext& execution_context,
177 ExceptionState& exception_state) { 173 ExceptionState& exception_state) {
178 for (const PaymentItem& item : input) { 174 for (const PaymentItem& item : input) {
179 ValidateShippingOptionOrPaymentItem(item, exception_state); 175 ValidateShippingOptionOrPaymentItem(item, item_names, execution_context,
176 exception_state);
180 if (exception_state.HadException()) 177 if (exception_state.HadException())
181 return; 178 return;
182 output.push_back(payments::mojom::blink::PaymentItem::From(item)); 179 output.push_back(payments::mojom::blink::PaymentItem::From(item));
183 } 180 }
184 } 181 }
185 182
186 // Validates and converts |input| shipping options into |output|. Throws an 183 // Validates and converts |input| shipping options into |output|. Throws an
187 // exception if the data is not valid, except for duplicate identifiers, which 184 // exception if the data is not valid, except for duplicate identifiers, which
188 // returns an empty |output| instead of throwing an exception. There's no need 185 // returns an empty |output| instead of throwing an exception. There's no need
189 // to clear |output| when an exception is thrown, because the caller takes care 186 // to clear |output| when an exception is thrown, because the caller takes care
190 // of deleting |output|. 187 // of deleting |output|.
191 void ValidateAndConvertShippingOptions( 188 void ValidateAndConvertShippingOptions(
192 const HeapVector<PaymentShippingOption>& input, 189 const HeapVector<PaymentShippingOption>& input,
193 Vector<PaymentShippingOptionPtr>& output, 190 Vector<PaymentShippingOptionPtr>& output,
191 String& shipping_option_output,
194 ExecutionContext& execution_context, 192 ExecutionContext& execution_context,
195 ExceptionState& exception_state) { 193 ExceptionState& exception_state) {
196 HashSet<String> unique_ids; 194 HashSet<String> unique_ids;
197 for (const PaymentShippingOption& option : input) { 195 for (const PaymentShippingOption& option : input) {
198 if (!option.hasId() || option.id().IsEmpty()) { 196 ValidateShippingOptionOrPaymentItem(option, "shippingOptions",
199 exception_state.ThrowTypeError("ShippingOption id required"); 197 execution_context, exception_state);
198 if (exception_state.HadException())
199 return;
200
201 DCHECK(option.hasId());
202 if (option.id().IsEmpty()) {
203 execution_context.AddConsoleMessage(
204 ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
205 "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.
200 return; 206 return;
201 } 207 }
202 208
203 if (unique_ids.Contains(option.id())) { 209 if (unique_ids.Contains(option.id())) {
204 execution_context.AddConsoleMessage(ConsoleMessage::Create( 210 execution_context.AddConsoleMessage(ConsoleMessage::Create(
205 kJSMessageSource, kWarningMessageLevel, 211 kJSMessageSource, kWarningMessageLevel,
206 "Duplicate shipping option identifier '" + option.id() + 212 "Duplicate shipping option identifier '" + option.id() +
207 "' is treated as an invalid address indicator.")); 213 "' is treated as an invalid address indicator."));
208 // Clear |output| instead of throwing an exception. 214 // Clear |output| instead of throwing an exception.
209 output.clear(); 215 output.clear();
216 shipping_option_output = String();
210 return; 217 return;
211 } 218 }
212 219
220 if (option.selected())
221 shipping_option_output = option.id();
222
213 unique_ids.insert(option.id()); 223 unique_ids.insert(option.id());
214 224
215 ValidateShippingOptionOrPaymentItem(option, exception_state);
216 if (exception_state.HadException())
217 return;
218
219 output.push_back( 225 output.push_back(
220 payments::mojom::blink::PaymentShippingOption::From(option)); 226 payments::mojom::blink::PaymentShippingOption::From(option));
221 } 227 }
222 } 228 }
223 229
224 void ValidateAndConvertTotal(const PaymentItem& input, 230 void ValidateAndConvertTotal(const PaymentItem& input,
231 const String& item_name,
225 PaymentItemPtr& output, 232 PaymentItemPtr& output,
233 ExecutionContext& execution_context,
226 ExceptionState& exception_state) { 234 ExceptionState& exception_state) {
227 ValidateShippingOptionOrPaymentItem(input, exception_state); 235 ValidateShippingOptionOrPaymentItem(input, item_name, execution_context,
236 exception_state);
228 if (exception_state.HadException()) 237 if (exception_state.HadException())
229 return; 238 return;
230 239
231 if (input.amount().value()[0] == '-') { 240 if (input.amount().value()[0] == '-') {
232 exception_state.ThrowTypeError("Total amount value should be non-negative"); 241 exception_state.ThrowTypeError("Total amount value should be non-negative");
233 return; 242 return;
234 } 243 }
235 244
236 output = payments::mojom::blink::PaymentItem::From(input); 245 output = payments::mojom::blink::PaymentItem::From(input);
237 } 246 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 } 400 }
392 } 401 }
393 402
394 void StringifyAndParseMethodSpecificData( 403 void StringifyAndParseMethodSpecificData(
395 const Vector<String>& supported_methods, 404 const Vector<String>& supported_methods,
396 const ScriptValue& input, 405 const ScriptValue& input,
397 PaymentMethodDataPtr& output, 406 PaymentMethodDataPtr& output,
398 ExecutionContext& execution_context, 407 ExecutionContext& execution_context,
399 ExceptionState& exception_state) { 408 ExceptionState& exception_state) {
400 DCHECK(!input.IsEmpty()); 409 DCHECK(!input.IsEmpty());
401 if (!input.V8Value()->IsObject() || input.V8Value()->IsArray()) { 410 v8::Local<v8::String> value;
402 exception_state.ThrowTypeError("Data should be a JSON-serializable object"); 411 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
412 !v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
413 .ToLocal(&value)) {
414 exception_state.ThrowTypeError(
415 "Payment method data should be a JSON-serializable object");
403 return; 416 return;
404 } 417 }
405 418
406 v8::Local<v8::String> value;
407 if (!v8::JSON::Stringify(input.GetContext(), input.V8Value().As<v8::Object>())
408 .ToLocal(&value)) {
409 exception_state.ThrowTypeError(
410 "Unable to parse payment method specific data");
411 return;
412 }
413
414 output->stringified_data = 419 output->stringified_data =
415 V8StringToWebCoreString<String>(value, kDoNotExternalize); 420 V8StringToWebCoreString<String>(value, kDoNotExternalize);
416 421
417 // Serialize payment method specific data to be sent to the payment apps. The 422 // Serialize payment method specific data to be sent to the payment apps. The
418 // payment apps are responsible for validating and processing their method 423 // payment apps are responsible for validating and processing their method
419 // data asynchronously. Do not throw exceptions here. 424 // data asynchronously. Do not throw exceptions here.
420 if (supported_methods.Contains("https://android.com/pay")) { 425 if (supported_methods.Contains("https://android.com/pay")) {
421 SetAndroidPayMethodData(input, output, exception_state); 426 SetAndroidPayMethodData(input, output, exception_state);
422 if (exception_state.HadException()) 427 if (exception_state.HadException())
423 exception_state.ClearException(); 428 exception_state.ClearException();
424 } 429 }
425 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() && 430 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() &&
426 supported_methods.Contains("basic-card")) { 431 supported_methods.Contains("basic-card")) {
427 SetBasicCardMethodData(input, output, execution_context, exception_state); 432 SetBasicCardMethodData(input, output, execution_context, exception_state);
428 if (exception_state.HadException()) 433 if (exception_state.HadException())
429 exception_state.ClearException(); 434 exception_state.ClearException();
430 } 435 }
431 } 436 }
432 437
433 void ValidateAndConvertPaymentDetailsModifiers( 438 void ValidateAndConvertPaymentDetailsModifiers(
434 const HeapVector<PaymentDetailsModifier>& input, 439 const HeapVector<PaymentDetailsModifier>& input,
435 Vector<PaymentDetailsModifierPtr>& output, 440 Vector<PaymentDetailsModifierPtr>& output,
436 ExecutionContext& execution_context, 441 ExecutionContext& execution_context,
437 ExceptionState& exception_state) { 442 ExceptionState& exception_state) {
438 if (input.IsEmpty()) {
439 exception_state.ThrowTypeError(
440 "Must specify at least one payment details modifier");
441 return;
442 }
443
444 for (const PaymentDetailsModifier& modifier : input) { 443 for (const PaymentDetailsModifier& modifier : input) {
445 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New()); 444 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New());
446 if (modifier.hasTotal()) { 445 if (modifier.hasTotal()) {
447 ValidateAndConvertTotal(modifier.total(), output.back()->total, 446 ValidateAndConvertTotal(modifier.total(), "modifier total",
447 output.back()->total, execution_context,
448 exception_state); 448 exception_state);
449 if (exception_state.HadException()) 449 if (exception_state.HadException())
450 return; 450 return;
451 } 451 }
452 452
453 if (modifier.hasAdditionalDisplayItems()) { 453 if (modifier.hasAdditionalDisplayItems()) {
454 ValidateAndConvertDisplayItems(modifier.additionalDisplayItems(), 454 ValidateAndConvertDisplayItems(modifier.additionalDisplayItems(),
455 "additional display items in modifier",
455 output.back()->additional_display_items, 456 output.back()->additional_display_items,
456 exception_state); 457 execution_context, exception_state);
457 if (exception_state.HadException()) 458 if (exception_state.HadException())
458 return; 459 return;
459 } 460 }
460 461
461 if (modifier.supportedMethods().IsEmpty()) { 462 if (modifier.supportedMethods().IsEmpty()) {
462 exception_state.ThrowTypeError( 463 exception_state.ThrowTypeError(
463 "Must specify at least one payment method identifier"); 464 "Must specify at least one payment method identifier");
464 return; 465 return;
465 } 466 }
466 467
467 output.back()->method_data = 468 output.back()->method_data =
468 payments::mojom::blink::PaymentMethodData::New(); 469 payments::mojom::blink::PaymentMethodData::New();
469 output.back()->method_data->supported_methods = modifier.supportedMethods(); 470 output.back()->method_data->supported_methods = modifier.supportedMethods();
470 471
471 if (modifier.hasData() && !modifier.data().IsEmpty()) { 472 if (modifier.hasData() && !modifier.data().IsEmpty()) {
472 StringifyAndParseMethodSpecificData( 473 StringifyAndParseMethodSpecificData(
473 modifier.supportedMethods(), modifier.data(), 474 modifier.supportedMethods(), modifier.data(),
474 output.back()->method_data, execution_context, exception_state); 475 output.back()->method_data, execution_context, exception_state);
475 } else { 476 } else {
476 output.back()->method_data->stringified_data = ""; 477 output.back()->method_data->stringified_data = "";
477 } 478 }
478 } 479 }
479 } 480 }
480 481
481 String GetSelectedShippingOption(
482 const Vector<PaymentShippingOptionPtr>& shipping_options) {
483 String result;
484 for (const PaymentShippingOptionPtr& shipping_option : shipping_options) {
485 if (shipping_option->selected)
486 result = shipping_option->id;
487 }
488 return result;
489 }
490
491 void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input, 482 void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase& input,
492 bool request_shipping,
493 PaymentDetailsPtr& output, 483 PaymentDetailsPtr& output,
494 String& shipping_option_output, 484 String& shipping_option_output,
495 ExecutionContext& execution_context, 485 ExecutionContext& execution_context,
496 ExceptionState& exception_state) { 486 ExceptionState& exception_state) {
497 if (input.hasDisplayItems()) { 487 if (input.hasDisplayItems()) {
498 ValidateAndConvertDisplayItems(input.displayItems(), output->display_items, 488 ValidateAndConvertDisplayItems(input.displayItems(), "display items",
489 output->display_items, execution_context,
499 exception_state); 490 exception_state);
500 if (exception_state.HadException()) 491 if (exception_state.HadException())
501 return; 492 return;
502 } 493 }
503 494
504 if (input.hasShippingOptions() && request_shipping) { 495 if (input.hasShippingOptions()) {
505 ValidateAndConvertShippingOptions(input.shippingOptions(), 496 ValidateAndConvertShippingOptions(
506 output->shipping_options, 497 input.shippingOptions(), output->shipping_options,
507 execution_context, exception_state); 498 shipping_option_output, execution_context, exception_state);
508 if (exception_state.HadException()) 499 if (exception_state.HadException())
509 return; 500 return;
501 } else {
502 shipping_option_output = String();
510 } 503 }
511 504
512 shipping_option_output = GetSelectedShippingOption(output->shipping_options);
513
514 if (input.hasModifiers()) { 505 if (input.hasModifiers()) {
515 ValidateAndConvertPaymentDetailsModifiers( 506 ValidateAndConvertPaymentDetailsModifiers(
516 input.modifiers(), output->modifiers, execution_context, 507 input.modifiers(), output->modifiers, execution_context,
517 exception_state); 508 exception_state);
518 if (exception_state.HadException()) 509 if (exception_state.HadException())
519 return; 510 return;
520 } 511 }
521 } 512 }
522 513
523 void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit& input, 514 void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit& input,
524 bool request_shipping,
525 PaymentDetailsPtr& output, 515 PaymentDetailsPtr& output,
526 String& shipping_option_output, 516 String& shipping_option_output,
527 ExecutionContext& execution_context, 517 ExecutionContext& execution_context,
528 ExceptionState& exception_state) { 518 ExceptionState& exception_state) {
529 ValidateAndConvertPaymentDetailsBase(input, request_shipping, output, 519 DCHECK(input.hasTotal());
530 shipping_option_output, 520 ValidateAndConvertTotal(input.total(), "total", output->total,
521 execution_context, exception_state);
522 if (exception_state.HadException())
523 return;
524
525 ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
531 execution_context, exception_state); 526 execution_context, exception_state);
532 if (exception_state.HadException()) 527 if (exception_state.HadException())
533 return; 528 return;
534
535 if (!input.hasTotal()) {
536 exception_state.ThrowTypeError("Must specify total");
537 return;
538 }
539
540 if (input.hasId())
541 output->id = input.id();
542 else
543 output->id = CreateCanonicalUUIDString();
544
545 ValidateAndConvertTotal(input.total(), output->total, exception_state);
546 } 529 }
547 530
548 void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate& input, 531 void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate& input,
549 bool request_shipping,
550 PaymentDetailsPtr& output, 532 PaymentDetailsPtr& output,
551 String& shipping_option_output, 533 String& shipping_option_output,
552 ExecutionContext& execution_context, 534 ExecutionContext& execution_context,
553 ExceptionState& exception_state) { 535 ExceptionState& exception_state) {
554 ValidateAndConvertPaymentDetailsBase(input, request_shipping, output, 536 ValidateAndConvertPaymentDetailsBase(input, output, shipping_option_output,
555 shipping_option_output,
556 execution_context, exception_state); 537 execution_context, exception_state);
557 if (exception_state.HadException()) 538 if (exception_state.HadException())
558 return; 539 return;
559 540
560 if (input.hasTotal()) { 541 if (input.hasTotal()) {
561 ValidateAndConvertTotal(input.total(), output->total, exception_state); 542 ValidateAndConvertTotal(input.total(), "total", output->total,
543 execution_context, exception_state);
562 if (exception_state.HadException()) 544 if (exception_state.HadException())
563 return; 545 return;
564 } 546 }
565 547
566 if (input.hasError() && !input.error().IsNull()) { 548 if (input.hasError() && !input.error().IsNull()) {
567 String error_message; 549 String error_message;
568 if (!PaymentsValidators::IsValidErrorMsgFormat(input.error(), 550 if (!PaymentsValidators::IsValidErrorMsgFormat(input.error(),
569 &error_message)) { 551 &error_message)) {
570 exception_state.ThrowTypeError(error_message); 552 exception_state.ThrowTypeError(error_message);
571 return; 553 return;
572 } 554 }
573 output->error = input.error(); 555 output->error = input.error();
574 } else { 556 } else {
575 output->error = ""; 557 output->error = "";
576 } 558 }
577 } 559 }
578 560
579 void ValidateAndConvertPaymentMethodData( 561 void ValidateAndConvertPaymentMethodData(
580 const HeapVector<PaymentMethodData>& input, 562 const HeapVector<PaymentMethodData>& input,
581 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output, 563 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output,
582 ExecutionContext& execution_context, 564 ExecutionContext& execution_context,
583 ExceptionState& exception_state) { 565 ExceptionState& exception_state) {
584 if (input.IsEmpty()) { 566 if (input.IsEmpty()) {
585 exception_state.ThrowTypeError( 567 exception_state.ThrowTypeError("At least one payment method is required");
586 "Must specify at least one payment method identifier");
587 return; 568 return;
588 } 569 }
589 570
590 for (const PaymentMethodData payment_method_data : input) { 571 for (const PaymentMethodData payment_method_data : input) {
591 if (payment_method_data.supportedMethods().IsEmpty()) { 572 if (payment_method_data.supportedMethods().IsEmpty()) {
592 exception_state.ThrowTypeError( 573 exception_state.ThrowTypeError(
593 "Must specify at least one payment method identifier"); 574 "Each payment method needs to include at least one payment method "
575 "identifier");
594 return; 576 return;
595 } 577 }
596 578
597 output.push_back(payments::mojom::blink::PaymentMethodData::New()); 579 output.push_back(payments::mojom::blink::PaymentMethodData::New());
598 output.back()->supported_methods = payment_method_data.supportedMethods(); 580 output.back()->supported_methods = payment_method_data.supportedMethods();
599 581
600 if (payment_method_data.hasData() && 582 if (payment_method_data.hasData() &&
601 !payment_method_data.data().IsEmpty()) { 583 !payment_method_data.data().IsEmpty()) {
602 StringifyAndParseMethodSpecificData( 584 StringifyAndParseMethodSpecificData(
603 payment_method_data.supportedMethods(), payment_method_data.data(), 585 payment_method_data.supportedMethods(), payment_method_data.data(),
604 output.back(), execution_context, exception_state); 586 output.back(), execution_context, exception_state);
605 } else { 587 } else {
606 output.back()->stringified_data = ""; 588 output.back()->stringified_data = "";
607 } 589 }
608 } 590 }
609 } 591 }
610 592
611 String GetValidShippingType(const String& shipping_type) {
612 static const char* const kValidValues[] = {
613 "shipping", "delivery", "pickup",
614 };
615 for (size_t i = 0; i < arraysize(kValidValues); i++) {
616 if (shipping_type == kValidValues[i])
617 return shipping_type;
618 }
619 return kValidValues[0];
620 }
621
622 bool AllowedToUsePaymentRequest(const Frame* frame) { 593 bool AllowedToUsePaymentRequest(const Frame* frame) {
623 // To determine whether a Document object |document| is allowed to use the 594 // To determine whether a Document object |document| is allowed to use the
624 // feature indicated by attribute name |allowpaymentrequest|, run these steps: 595 // feature indicated by attribute name |allowpaymentrequest|, run these steps:
625 596
626 // 1. If |document| has no browsing context, then return false. 597 // 1. If |document| has no browsing context, then return false.
627 if (!frame) 598 if (!frame)
628 return false; 599 return false;
629 600
630 if (!RuntimeEnabledFeatures::featurePolicyEnabled()) { 601 if (!RuntimeEnabledFeatures::featurePolicyEnabled()) {
631 // 2. If |document|'s browsing context is a top-level browsing context, then 602 // 2. If |document|'s browsing context is a top-level browsing context, then
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 if (exception_state.HadException()) { 776 if (exception_state.HadException()) {
806 show_resolver_->Reject( 777 show_resolver_->Reject(
807 DOMException::Create(kSyntaxError, exception_state.Message())); 778 DOMException::Create(kSyntaxError, exception_state.Message()));
808 ClearResolversAndCloseMojoConnection(); 779 ClearResolversAndCloseMojoConnection();
809 return; 780 return;
810 } 781 }
811 782
812 PaymentDetailsPtr validated_details = 783 PaymentDetailsPtr validated_details =
813 payments::mojom::blink::PaymentDetails::New(); 784 payments::mojom::blink::PaymentDetails::New();
814 ValidateAndConvertPaymentDetailsUpdate( 785 ValidateAndConvertPaymentDetailsUpdate(
815 details, options_.requestShipping(), validated_details, shipping_option_, 786 details, validated_details, shipping_option_, *GetExecutionContext(),
816 *GetExecutionContext(), exception_state); 787 exception_state);
817 if (exception_state.HadException()) { 788 if (exception_state.HadException()) {
818 show_resolver_->Reject( 789 show_resolver_->Reject(
819 DOMException::Create(kSyntaxError, exception_state.Message())); 790 DOMException::Create(kSyntaxError, exception_state.Message()));
820 ClearResolversAndCloseMojoConnection(); 791 ClearResolversAndCloseMojoConnection();
821 return; 792 return;
822 } 793 }
823 794
795 if (!options_.requestShipping())
796 validated_details->shipping_options.clear();
797
824 payment_provider_->UpdateWith(std::move(validated_details)); 798 payment_provider_->UpdateWith(std::move(validated_details));
825 } 799 }
826 800
827 void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) { 801 void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) {
828 if (show_resolver_) 802 if (show_resolver_)
829 show_resolver_->Reject(DOMException::Create(kAbortError, error)); 803 show_resolver_->Reject(DOMException::Create(kAbortError, error));
830 if (complete_resolver_) 804 if (complete_resolver_)
831 complete_resolver_->Reject(DOMException::Create(kAbortError, error)); 805 complete_resolver_->Reject(DOMException::Create(kAbortError, error));
832 ClearResolversAndCloseMojoConnection(); 806 ClearResolversAndCloseMojoConnection();
833 } 807 }
(...skipping 19 matching lines...) Expand all
853 const PaymentDetailsInit& details, 827 const PaymentDetailsInit& details,
854 const PaymentOptions& options, 828 const PaymentOptions& options,
855 ExceptionState& exception_state) 829 ExceptionState& exception_state)
856 : ContextLifecycleObserver(execution_context), 830 : ContextLifecycleObserver(execution_context),
857 options_(options), 831 options_(options),
858 client_binding_(this), 832 client_binding_(this),
859 complete_timer_( 833 complete_timer_(
860 TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetFrame()), 834 TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetFrame()),
861 this, 835 this,
862 &PaymentRequest::OnCompleteTimeout) { 836 &PaymentRequest::OnCompleteTimeout) {
863 Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
864 ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
865 *GetExecutionContext(), exception_state);
866 if (exception_state.HadException())
867 return;
868
869 if (!GetExecutionContext()->IsSecureContext()) { 837 if (!GetExecutionContext()->IsSecureContext()) {
870 exception_state.ThrowSecurityError("Must be in a secure context"); 838 exception_state.ThrowSecurityError("Must be in a secure context");
871 return; 839 return;
872 } 840 }
873 841
874 if (!AllowedToUsePaymentRequest(GetFrame())) { 842 if (!AllowedToUsePaymentRequest(GetFrame())) {
875 exception_state.ThrowSecurityError( 843 exception_state.ThrowSecurityError(
876 "Must be in a top-level browsing context or an iframe needs to specify " 844 "Must be in a top-level browsing context or an iframe needs to specify "
877 "'allowpaymentrequest' explicitly"); 845 "'allowpaymentrequest' explicitly");
878 return; 846 return;
879 } 847 }
880 848
881 PaymentDetailsPtr validated_details = 849 PaymentDetailsPtr validated_details =
882 payments::mojom::blink::PaymentDetails::New(); 850 payments::mojom::blink::PaymentDetails::New();
883 ValidateAndConvertPaymentDetailsInit(details, options_.requestShipping(), 851 validated_details->id = id_ =
884 validated_details, shipping_option_, 852 details.hasId() ? details.id() : CreateCanonicalUUIDString();
885 *GetExecutionContext(), exception_state); 853
854 Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
855 ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
856 *GetExecutionContext(), exception_state);
886 if (exception_state.HadException()) 857 if (exception_state.HadException())
887 return; 858 return;
888 859
889 id_ = validated_details->id; 860 ValidateAndConvertPaymentDetailsInit(details, validated_details,
861 shipping_option_, *GetExecutionContext(),
862 exception_state);
863 if (exception_state.HadException())
864 return;
890 865
891 if (options_.requestShipping()) 866 if (options_.requestShipping())
892 shipping_type_ = GetValidShippingType(options_.shippingType()); 867 shipping_type_ = options_.shippingType();
868 else
869 validated_details->shipping_options.clear();
870
871 DCHECK(shipping_type_.IsNull() || shipping_type_ == "shipping" ||
872 shipping_type_ == "delivery" || shipping_type_ == "pickup");
893 873
894 GetFrame()->GetInterfaceProvider()->GetInterface( 874 GetFrame()->GetInterfaceProvider()->GetInterface(
895 mojo::MakeRequest(&payment_provider_)); 875 mojo::MakeRequest(&payment_provider_));
896 payment_provider_.set_connection_error_handler(ConvertToBaseCallback( 876 payment_provider_.set_connection_error_handler(ConvertToBaseCallback(
897 WTF::Bind(&PaymentRequest::OnError, WrapWeakPersistent(this), 877 WTF::Bind(&PaymentRequest::OnError, WrapWeakPersistent(this),
898 PaymentErrorReason::UNKNOWN))); 878 PaymentErrorReason::UNKNOWN)));
899 payment_provider_->Init( 879 payment_provider_->Init(
900 client_binding_.CreateInterfacePtrAndBind(), 880 client_binding_.CreateInterfacePtrAndBind(),
901 std::move(validated_method_data), std::move(validated_details), 881 std::move(validated_method_data), std::move(validated_details),
902 payments::mojom::blink::PaymentOptions::From(options_)); 882 payments::mojom::blink::PaymentOptions::From(options_));
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 complete_resolver_.Clear(); 1068 complete_resolver_.Clear();
1089 show_resolver_.Clear(); 1069 show_resolver_.Clear();
1090 abort_resolver_.Clear(); 1070 abort_resolver_.Clear();
1091 can_make_payment_resolver_.Clear(); 1071 can_make_payment_resolver_.Clear();
1092 if (client_binding_.is_bound()) 1072 if (client_binding_.is_bound())
1093 client_binding_.Close(); 1073 client_binding_.Close();
1094 payment_provider_.reset(); 1074 payment_provider_.reset();
1095 } 1075 }
1096 1076
1097 } // namespace blink 1077 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698