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

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

Issue 2659083003: Relax card type handling. (Closed)
Patch Set: Clarify comment Created 3 years, 10 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
« no previous file with comments | « chrome/test/data/payments/payment_request_basic_card_test.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "bindings/core/v8/ConditionalFeatures.h" 7 #include "bindings/core/v8/ConditionalFeatures.h"
8 #include "bindings/core/v8/ExceptionState.h" 8 #include "bindings/core/v8/ExceptionState.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h" 9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "bindings/core/v8/ScriptState.h" 10 #include "bindings/core/v8/ScriptState.h"
11 #include "bindings/core/v8/V8StringResource.h" 11 #include "bindings/core/v8/V8StringResource.h"
12 #include "bindings/modules/v8/V8AndroidPayMethodData.h" 12 #include "bindings/modules/v8/V8AndroidPayMethodData.h"
13 #include "bindings/modules/v8/V8BasicCardRequest.h" 13 #include "bindings/modules/v8/V8BasicCardRequest.h"
14 #include "bindings/modules/v8/V8PaymentDetails.h" 14 #include "bindings/modules/v8/V8PaymentDetails.h"
15 #include "core/EventTypeNames.h" 15 #include "core/EventTypeNames.h"
16 #include "core/dom/DOMException.h" 16 #include "core/dom/DOMException.h"
17 #include "core/dom/Document.h"
17 #include "core/dom/ExceptionCode.h" 18 #include "core/dom/ExceptionCode.h"
18 #include "core/dom/TaskRunnerHelper.h" 19 #include "core/dom/TaskRunnerHelper.h"
19 #include "core/events/Event.h" 20 #include "core/events/Event.h"
20 #include "core/events/EventQueue.h" 21 #include "core/events/EventQueue.h"
21 #include "core/frame/FrameOwner.h" 22 #include "core/frame/FrameOwner.h"
22 #include "core/html/HTMLIFrameElement.h" 23 #include "core/html/HTMLIFrameElement.h"
24 #include "core/inspector/ConsoleMessage.h"
25 #include "core/inspector/ConsoleTypes.h"
23 #include "modules/EventTargetModulesNames.h" 26 #include "modules/EventTargetModulesNames.h"
24 #include "modules/payments/AndroidPayMethodData.h" 27 #include "modules/payments/AndroidPayMethodData.h"
25 #include "modules/payments/AndroidPayTokenization.h" 28 #include "modules/payments/AndroidPayTokenization.h"
26 #include "modules/payments/BasicCardRequest.h" 29 #include "modules/payments/BasicCardRequest.h"
27 #include "modules/payments/HTMLIFrameElementPayments.h" 30 #include "modules/payments/HTMLIFrameElementPayments.h"
28 #include "modules/payments/PaymentAddress.h" 31 #include "modules/payments/PaymentAddress.h"
29 #include "modules/payments/PaymentItem.h" 32 #include "modules/payments/PaymentItem.h"
30 #include "modules/payments/PaymentRequestUpdateEvent.h" 33 #include "modules/payments/PaymentRequestUpdateEvent.h"
31 #include "modules/payments/PaymentResponse.h" 34 #include "modules/payments/PaymentResponse.h"
32 #include "modules/payments/PaymentShippingOption.h" 35 #include "modules/payments/PaymentShippingOption.h"
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 payments::mojom::blink::AndroidPayTokenizationParameter::New()); 309 payments::mojom::blink::AndroidPayTokenizationParameter::New());
307 output->parameters.back()->key = key; 310 output->parameters.back()->key = key;
308 output->parameters.back()->value = value; 311 output->parameters.back()->value = value;
309 } 312 }
310 } 313 }
311 } 314 }
312 } 315 }
313 316
314 // Parses basic-card data to avoid parsing JSON in the browser. 317 // Parses basic-card data to avoid parsing JSON in the browser.
315 void setBasicCardMethodData(const ScriptValue& input, 318 void setBasicCardMethodData(const ScriptValue& input,
319 Document& document,
316 PaymentMethodDataPtr& output, 320 PaymentMethodDataPtr& output,
317 ExceptionState& exceptionState) { 321 ExceptionState& exceptionState) {
318 BasicCardRequest basicCard; 322 BasicCardRequest basicCard;
319 V8BasicCardRequest::toImpl(input.isolate(), input.v8Value(), basicCard, 323 V8BasicCardRequest::toImpl(input.isolate(), input.v8Value(), basicCard,
320 exceptionState); 324 exceptionState);
321 if (exceptionState.hadException()) 325 if (exceptionState.hadException())
322 return; 326 return;
323 327
324 if (basicCard.hasSupportedNetworks()) { 328 if (basicCard.hasSupportedNetworks()) {
325 using payments::mojom::blink::BasicCardNetwork; 329 using payments::mojom::blink::BasicCardNetwork;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 {BasicCardType::PREPAID, "prepaid"}}; 361 {BasicCardType::PREPAID, "prepaid"}};
358 362
359 for (const String& type : basicCard.supportedTypes()) { 363 for (const String& type : basicCard.supportedTypes()) {
360 for (size_t i = 0; i < arraysize(basicCardTypes); ++i) { 364 for (size_t i = 0; i < arraysize(basicCardTypes); ++i) {
361 if (type == basicCardTypes[i].name) { 365 if (type == basicCardTypes[i].name) {
362 output->supported_types.push_back(basicCardTypes[i].code); 366 output->supported_types.push_back(basicCardTypes[i].code);
363 break; 367 break;
364 } 368 }
365 } 369 }
366 } 370 }
371
372 if (output->supported_types.size() != arraysize(basicCardTypes)) {
373 document.addConsoleMessage(ConsoleMessage::create(
374 JSMessageSource, WarningMessageLevel,
375 "Cannot yet distinguish credit, debit, and prepaid cards."));
376 }
367 } 377 }
368 } 378 }
369 379
370 void stringifyAndParseMethodSpecificData(const Vector<String>& supportedMethods, 380 void stringifyAndParseMethodSpecificData(const Vector<String>& supportedMethods,
371 const ScriptValue& input, 381 const ScriptValue& input,
382 Document& document,
372 PaymentMethodDataPtr& output, 383 PaymentMethodDataPtr& output,
373 ExceptionState& exceptionState) { 384 ExceptionState& exceptionState) {
374 DCHECK(!input.isEmpty()); 385 DCHECK(!input.isEmpty());
375 if (!input.v8Value()->IsObject() || input.v8Value()->IsArray()) { 386 if (!input.v8Value()->IsObject() || input.v8Value()->IsArray()) {
376 exceptionState.throwTypeError("Data should be a JSON-serializable object"); 387 exceptionState.throwTypeError("Data should be a JSON-serializable object");
377 return; 388 return;
378 } 389 }
379 390
380 v8::Local<v8::String> value; 391 v8::Local<v8::String> value;
381 if (!v8::JSON::Stringify(input.context(), input.v8Value().As<v8::Object>()) 392 if (!v8::JSON::Stringify(input.context(), input.v8Value().As<v8::Object>())
382 .ToLocal(&value)) { 393 .ToLocal(&value)) {
383 exceptionState.throwTypeError( 394 exceptionState.throwTypeError(
384 "Unable to parse payment method specific data"); 395 "Unable to parse payment method specific data");
385 return; 396 return;
386 } 397 }
387 398
388 output->stringified_data = 399 output->stringified_data =
389 v8StringToWebCoreString<String>(value, DoNotExternalize); 400 v8StringToWebCoreString<String>(value, DoNotExternalize);
390 401
391 // Serialize payment method specific data to be sent to the payment apps. The 402 // Serialize payment method specific data to be sent to the payment apps. The
392 // payment apps are responsible for validating and processing their method 403 // payment apps are responsible for validating and processing their method
393 // data asynchronously. Do not throw exceptions here. 404 // data asynchronously. Do not throw exceptions here.
394 if (supportedMethods.contains("https://android.com/pay")) { 405 if (supportedMethods.contains("https://android.com/pay")) {
395 setAndroidPayMethodData(input, output, exceptionState); 406 setAndroidPayMethodData(input, output, exceptionState);
396 if (exceptionState.hadException()) 407 if (exceptionState.hadException())
397 exceptionState.clearException(); 408 exceptionState.clearException();
398 } 409 }
399 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() && 410 if (RuntimeEnabledFeatures::paymentRequestBasicCardEnabled() &&
400 supportedMethods.contains("basic-card")) { 411 supportedMethods.contains("basic-card")) {
401 setBasicCardMethodData(input, output, exceptionState); 412 setBasicCardMethodData(input, document, output, exceptionState);
402 if (exceptionState.hadException()) 413 if (exceptionState.hadException())
403 exceptionState.clearException(); 414 exceptionState.clearException();
404 } 415 }
405 } 416 }
406 417
407 void validateAndConvertPaymentDetailsModifiers( 418 void validateAndConvertPaymentDetailsModifiers(
408 const HeapVector<PaymentDetailsModifier>& input, 419 const HeapVector<PaymentDetailsModifier>& input,
420 Document& document,
409 Vector<PaymentDetailsModifierPtr>& output, 421 Vector<PaymentDetailsModifierPtr>& output,
410 ExceptionState& exceptionState) { 422 ExceptionState& exceptionState) {
411 if (input.isEmpty()) { 423 if (input.isEmpty()) {
412 exceptionState.throwTypeError( 424 exceptionState.throwTypeError(
413 "Must specify at least one payment details modifier"); 425 "Must specify at least one payment details modifier");
414 return; 426 return;
415 } 427 }
416 428
417 for (const PaymentDetailsModifier& modifier : input) { 429 for (const PaymentDetailsModifier& modifier : input) {
418 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New()); 430 output.push_back(payments::mojom::blink::PaymentDetailsModifier::New());
(...skipping 17 matching lines...) Expand all
436 "Must specify at least one payment method identifier"); 448 "Must specify at least one payment method identifier");
437 return; 449 return;
438 } 450 }
439 451
440 output.back()->method_data = 452 output.back()->method_data =
441 payments::mojom::blink::PaymentMethodData::New(); 453 payments::mojom::blink::PaymentMethodData::New();
442 output.back()->method_data->supported_methods = modifier.supportedMethods(); 454 output.back()->method_data->supported_methods = modifier.supportedMethods();
443 455
444 if (modifier.hasData() && !modifier.data().isEmpty()) { 456 if (modifier.hasData() && !modifier.data().isEmpty()) {
445 stringifyAndParseMethodSpecificData( 457 stringifyAndParseMethodSpecificData(
446 modifier.supportedMethods(), modifier.data(), 458 modifier.supportedMethods(), modifier.data(), document,
447 output.back()->method_data, exceptionState); 459 output.back()->method_data, exceptionState);
448 } else { 460 } else {
449 output.back()->method_data->stringified_data = ""; 461 output.back()->method_data->stringified_data = "";
450 } 462 }
451 } 463 }
452 } 464 }
453 465
454 String getSelectedShippingOption( 466 String getSelectedShippingOption(
455 const Vector<PaymentShippingOptionPtr>& shippingOptions) { 467 const Vector<PaymentShippingOptionPtr>& shippingOptions) {
456 String result; 468 String result;
457 for (const PaymentShippingOptionPtr& shippingOption : shippingOptions) { 469 for (const PaymentShippingOptionPtr& shippingOption : shippingOptions) {
458 if (shippingOption->selected) 470 if (shippingOption->selected)
459 result = shippingOption->id; 471 result = shippingOption->id;
460 } 472 }
461 return result; 473 return result;
462 } 474 }
463 475
464 void validateAndConvertPaymentDetails(const PaymentDetails& input, 476 void validateAndConvertPaymentDetails(const PaymentDetails& input,
465 bool requestShipping, 477 bool requestShipping,
478 Document& document,
466 PaymentDetailsPtr& output, 479 PaymentDetailsPtr& output,
467 String& shippingOptionOutput, 480 String& shippingOptionOutput,
468 ExceptionState& exceptionState) { 481 ExceptionState& exceptionState) {
469 if (!input.hasTotal()) { 482 if (!input.hasTotal()) {
470 exceptionState.throwTypeError("Must specify total"); 483 exceptionState.throwTypeError("Must specify total");
471 return; 484 return;
472 } 485 }
473 486
474 validateAndConvertTotal(input.total(), output->total, exceptionState); 487 validateAndConvertTotal(input.total(), output->total, exceptionState);
475 if (exceptionState.hadException()) 488 if (exceptionState.hadException())
(...skipping 10 matching lines...) Expand all
486 validateAndConvertShippingOptions(input.shippingOptions(), 499 validateAndConvertShippingOptions(input.shippingOptions(),
487 output->shipping_options, exceptionState); 500 output->shipping_options, exceptionState);
488 if (exceptionState.hadException()) 501 if (exceptionState.hadException())
489 return; 502 return;
490 } 503 }
491 504
492 shippingOptionOutput = getSelectedShippingOption(output->shipping_options); 505 shippingOptionOutput = getSelectedShippingOption(output->shipping_options);
493 506
494 if (input.hasModifiers()) { 507 if (input.hasModifiers()) {
495 validateAndConvertPaymentDetailsModifiers( 508 validateAndConvertPaymentDetailsModifiers(
496 input.modifiers(), output->modifiers, exceptionState); 509 input.modifiers(), document, output->modifiers, exceptionState);
497 if (exceptionState.hadException()) 510 if (exceptionState.hadException())
498 return; 511 return;
499 } 512 }
500 513
501 if (input.hasError() && !input.error().isNull()) { 514 if (input.hasError() && !input.error().isNull()) {
502 String errorMessage; 515 String errorMessage;
503 if (!PaymentsValidators::isValidErrorMsgFormat(input.error(), 516 if (!PaymentsValidators::isValidErrorMsgFormat(input.error(),
504 &errorMessage)) { 517 &errorMessage)) {
505 exceptionState.throwTypeError(errorMessage); 518 exceptionState.throwTypeError(errorMessage);
506 return; 519 return;
507 } 520 }
508 output->error = input.error(); 521 output->error = input.error();
509 } else { 522 } else {
510 output->error = ""; 523 output->error = "";
511 } 524 }
512 } 525 }
513 526
514 void validateAndConvertPaymentMethodData( 527 void validateAndConvertPaymentMethodData(
515 const HeapVector<PaymentMethodData>& input, 528 const HeapVector<PaymentMethodData>& input,
529 Document& document,
516 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output, 530 Vector<payments::mojom::blink::PaymentMethodDataPtr>& output,
517 ExceptionState& exceptionState) { 531 ExceptionState& exceptionState) {
518 if (input.isEmpty()) { 532 if (input.isEmpty()) {
519 exceptionState.throwTypeError( 533 exceptionState.throwTypeError(
520 "Must specify at least one payment method identifier"); 534 "Must specify at least one payment method identifier");
521 return; 535 return;
522 } 536 }
523 537
524 for (const PaymentMethodData paymentMethodData : input) { 538 for (const PaymentMethodData paymentMethodData : input) {
525 if (paymentMethodData.supportedMethods().isEmpty()) { 539 if (paymentMethodData.supportedMethods().isEmpty()) {
526 exceptionState.throwTypeError( 540 exceptionState.throwTypeError(
527 "Must specify at least one payment method identifier"); 541 "Must specify at least one payment method identifier");
528 return; 542 return;
529 } 543 }
530 544
531 output.push_back(payments::mojom::blink::PaymentMethodData::New()); 545 output.push_back(payments::mojom::blink::PaymentMethodData::New());
532 output.back()->supported_methods = paymentMethodData.supportedMethods(); 546 output.back()->supported_methods = paymentMethodData.supportedMethods();
533 547
534 if (paymentMethodData.hasData() && !paymentMethodData.data().isEmpty()) { 548 if (paymentMethodData.hasData() && !paymentMethodData.data().isEmpty()) {
535 stringifyAndParseMethodSpecificData(paymentMethodData.supportedMethods(), 549 stringifyAndParseMethodSpecificData(paymentMethodData.supportedMethods(),
536 paymentMethodData.data(), 550 paymentMethodData.data(), document,
537 output.back(), exceptionState); 551 output.back(), exceptionState);
538 } else { 552 } else {
539 output.back()->stringified_data = ""; 553 output.back()->stringified_data = "";
540 } 554 }
541 } 555 }
542 } 556 }
543 557
544 String getValidShippingType(const String& shippingType) { 558 String getValidShippingType(const String& shippingType) {
545 static const char* const validValues[] = { 559 static const char* const validValues[] = {
546 "shipping", "delivery", "pickup", 560 "shipping", "delivery", "pickup",
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 exceptionState); 753 exceptionState);
740 if (exceptionState.hadException()) { 754 if (exceptionState.hadException()) {
741 m_showResolver->reject( 755 m_showResolver->reject(
742 DOMException::create(SyntaxError, exceptionState.message())); 756 DOMException::create(SyntaxError, exceptionState.message()));
743 clearResolversAndCloseMojoConnection(); 757 clearResolversAndCloseMojoConnection();
744 return; 758 return;
745 } 759 }
746 760
747 PaymentDetailsPtr validatedDetails = 761 PaymentDetailsPtr validatedDetails =
748 payments::mojom::blink::PaymentDetails::New(); 762 payments::mojom::blink::PaymentDetails::New();
749 validateAndConvertPaymentDetails(details, m_options.requestShipping(), 763 validateAndConvertPaymentDetails(
750 validatedDetails, m_shippingOption, 764 details, m_options.requestShipping(),
751 exceptionState); 765 *detailsScriptValue.getScriptState()->domWindow()->document(),
766 validatedDetails, m_shippingOption, exceptionState);
752 if (exceptionState.hadException()) { 767 if (exceptionState.hadException()) {
753 m_showResolver->reject( 768 m_showResolver->reject(
754 DOMException::create(SyntaxError, exceptionState.message())); 769 DOMException::create(SyntaxError, exceptionState.message()));
755 clearResolversAndCloseMojoConnection(); 770 clearResolversAndCloseMojoConnection();
756 return; 771 return;
757 } 772 }
758 773
759 m_paymentProvider->UpdateWith(std::move(validatedDetails)); 774 m_paymentProvider->UpdateWith(std::move(validatedDetails));
760 } 775 }
761 776
(...skipping 27 matching lines...) Expand all
789 const PaymentOptions& options, 804 const PaymentOptions& options,
790 ExceptionState& exceptionState) 805 ExceptionState& exceptionState)
791 : ContextLifecycleObserver(&document), 806 : ContextLifecycleObserver(&document),
792 m_options(options), 807 m_options(options),
793 m_clientBinding(this), 808 m_clientBinding(this),
794 m_completeTimer( 809 m_completeTimer(
795 TaskRunnerHelper::get(TaskType::MiscPlatformAPI, document.frame()), 810 TaskRunnerHelper::get(TaskType::MiscPlatformAPI, document.frame()),
796 this, 811 this,
797 &PaymentRequest::onCompleteTimeout) { 812 &PaymentRequest::onCompleteTimeout) {
798 Vector<payments::mojom::blink::PaymentMethodDataPtr> validatedMethodData; 813 Vector<payments::mojom::blink::PaymentMethodDataPtr> validatedMethodData;
799 validateAndConvertPaymentMethodData(methodData, validatedMethodData, 814 validateAndConvertPaymentMethodData(methodData, document, validatedMethodData,
800 exceptionState); 815 exceptionState);
801 if (exceptionState.hadException()) 816 if (exceptionState.hadException())
802 return; 817 return;
803 818
804 if (!document.isSecureContext()) { 819 if (!document.isSecureContext()) {
805 exceptionState.throwSecurityError("Must be in a secure context"); 820 exceptionState.throwSecurityError("Must be in a secure context");
806 return; 821 return;
807 } 822 }
808 823
809 if (!allowedToUsePaymentRequest(document.frame())) { 824 if (!allowedToUsePaymentRequest(document.frame())) {
810 exceptionState.throwSecurityError( 825 exceptionState.throwSecurityError(
811 "Must be in a top-level browsing context or an iframe needs to specify " 826 "Must be in a top-level browsing context or an iframe needs to specify "
812 "'allowpaymentrequest' explicitly"); 827 "'allowpaymentrequest' explicitly");
813 return; 828 return;
814 } 829 }
815 830
816 PaymentDetailsPtr validatedDetails = 831 PaymentDetailsPtr validatedDetails =
817 payments::mojom::blink::PaymentDetails::New(); 832 payments::mojom::blink::PaymentDetails::New();
818 validateAndConvertPaymentDetails(details, m_options.requestShipping(), 833 validateAndConvertPaymentDetails(details, m_options.requestShipping(),
819 validatedDetails, m_shippingOption, 834 document, validatedDetails, m_shippingOption,
820 exceptionState); 835 exceptionState);
821 if (exceptionState.hadException()) 836 if (exceptionState.hadException())
822 return; 837 return;
823 838
824 if (details.hasError()) { 839 if (details.hasError()) {
825 exceptionState.throwTypeError("Error message not allowed in constructor"); 840 exceptionState.throwTypeError("Error message not allowed in constructor");
826 return; 841 return;
827 } 842 }
828 843
829 if (m_options.requestShipping()) 844 if (m_options.requestShipping())
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 m_completeResolver.clear(); 1051 m_completeResolver.clear();
1037 m_showResolver.clear(); 1052 m_showResolver.clear();
1038 m_abortResolver.clear(); 1053 m_abortResolver.clear();
1039 m_canMakePaymentResolver.clear(); 1054 m_canMakePaymentResolver.clear();
1040 if (m_clientBinding.is_bound()) 1055 if (m_clientBinding.is_bound())
1041 m_clientBinding.Close(); 1056 m_clientBinding.Close();
1042 m_paymentProvider.reset(); 1057 m_paymentProvider.reset();
1043 } 1058 }
1044 1059
1045 } // namespace blink 1060 } // namespace blink
OLDNEW
« no previous file with comments | « chrome/test/data/payments/payment_request_basic_card_test.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698