| OLD | NEW |
| 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/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
| 8 #include "bindings/core/v8/JSONValuesForV8.h" | 8 #include "bindings/core/v8/JSONValuesForV8.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" |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 } | 152 } |
| 153 return output; | 153 return output; |
| 154 } | 154 } |
| 155 }; | 155 }; |
| 156 | 156 |
| 157 } // namespace mojo | 157 } // namespace mojo |
| 158 | 158 |
| 159 namespace blink { | 159 namespace blink { |
| 160 namespace { | 160 namespace { |
| 161 | 161 |
| 162 // If the website does not call complete() 60 seconds after show() has been reso
lved, then behave as if |
| 163 // the website called complete("fail"). |
| 164 static const int completeTimeoutSeconds = 60; |
| 165 |
| 162 // Validates ShippingOption or PaymentItem, which happen to have identical field
s, | 166 // Validates ShippingOption or PaymentItem, which happen to have identical field
s, |
| 163 // except for "id", which is present only in ShippingOption. | 167 // except for "id", which is present only in ShippingOption. |
| 164 template <typename T> | 168 template <typename T> |
| 165 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio
nState) | 169 void validateShippingOptionOrPaymentItem(const T& item, ExceptionState& exceptio
nState) |
| 166 { | 170 { |
| 167 if (!item.hasLabel() || item.label().isEmpty()) { | 171 if (!item.hasLabel() || item.label().isEmpty()) { |
| 168 exceptionState.throwTypeError("Item label required"); | 172 exceptionState.throwTypeError("Item label required"); |
| 169 return; | 173 return; |
| 170 } | 174 } |
| 171 | 175 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 ExecutionContext* PaymentRequest::getExecutionContext() const | 415 ExecutionContext* PaymentRequest::getExecutionContext() const |
| 412 { | 416 { |
| 413 return ContextLifecycleObserver::getExecutionContext(); | 417 return ContextLifecycleObserver::getExecutionContext(); |
| 414 } | 418 } |
| 415 | 419 |
| 416 ScriptPromise PaymentRequest::complete(ScriptState* scriptState, PaymentComplete
result) | 420 ScriptPromise PaymentRequest::complete(ScriptState* scriptState, PaymentComplete
result) |
| 417 { | 421 { |
| 418 if (m_completeResolver) | 422 if (m_completeResolver) |
| 419 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "Already called complete() once")); | 423 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "Already called complete() once")); |
| 420 | 424 |
| 425 if (!m_completeTimer.isActive()) |
| 426 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "Timed out after 60 seconds, complete() called too lat
e")); |
| 427 |
| 421 // User has cancelled the transaction while the website was processing it. | 428 // User has cancelled the transaction while the website was processing it. |
| 422 if (!m_paymentProvider) | 429 if (!m_paymentProvider) |
| 423 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "Request cancelled")); | 430 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "Request cancelled")); |
| 424 | 431 |
| 432 m_completeTimer.stop(); |
| 433 |
| 425 // The payment provider should respond in PaymentRequest::OnComplete(). | 434 // The payment provider should respond in PaymentRequest::OnComplete(). |
| 426 m_paymentProvider->Complete(mojom::blink::PaymentComplete(result)); | 435 m_paymentProvider->Complete(mojom::blink::PaymentComplete(result)); |
| 427 | 436 |
| 428 m_completeResolver = ScriptPromiseResolver::create(scriptState); | 437 m_completeResolver = ScriptPromiseResolver::create(scriptState); |
| 429 return m_completeResolver->promise(); | 438 return m_completeResolver->promise(); |
| 430 } | 439 } |
| 431 | 440 |
| 432 void PaymentRequest::onUpdatePaymentDetails(const ScriptValue& detailsScriptValu
e) | 441 void PaymentRequest::onUpdatePaymentDetails(const ScriptValue& detailsScriptValu
e) |
| 433 { | 442 { |
| 434 if (!m_showResolver || !m_paymentProvider) | 443 if (!m_showResolver || !m_paymentProvider) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 visitor->trace(m_details); | 479 visitor->trace(m_details); |
| 471 visitor->trace(m_options); | 480 visitor->trace(m_options); |
| 472 visitor->trace(m_shippingAddress); | 481 visitor->trace(m_shippingAddress); |
| 473 visitor->trace(m_showResolver); | 482 visitor->trace(m_showResolver); |
| 474 visitor->trace(m_completeResolver); | 483 visitor->trace(m_completeResolver); |
| 475 visitor->trace(m_abortResolver); | 484 visitor->trace(m_abortResolver); |
| 476 EventTargetWithInlineData::trace(visitor); | 485 EventTargetWithInlineData::trace(visitor); |
| 477 ContextLifecycleObserver::trace(visitor); | 486 ContextLifecycleObserver::trace(visitor); |
| 478 } | 487 } |
| 479 | 488 |
| 489 void PaymentRequest::onCompleteTimeoutForTesting() |
| 490 { |
| 491 onCompleteTimeout(0); |
| 492 } |
| 493 |
| 480 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen
tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o
ptions, ExceptionState& exceptionState) | 494 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen
tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o
ptions, ExceptionState& exceptionState) |
| 481 : ContextLifecycleObserver(scriptState->getExecutionContext()) | 495 : ContextLifecycleObserver(scriptState->getExecutionContext()) |
| 482 , ActiveScriptWrappable(this) | 496 , ActiveScriptWrappable(this) |
| 483 , m_options(options) | 497 , m_options(options) |
| 484 , m_clientBinding(this) | 498 , m_clientBinding(this) |
| 499 , m_completeTimer(this, &PaymentRequest::onCompleteTimeout) |
| 485 { | 500 { |
| 486 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat
e); | 501 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat
e); |
| 487 if (exceptionState.hadException()) | 502 if (exceptionState.hadException()) |
| 488 return; | 503 return; |
| 489 | 504 |
| 490 if (!scriptState->getExecutionContext()->isSecureContext()) { | 505 if (!scriptState->getExecutionContext()->isSecureContext()) { |
| 491 exceptionState.throwSecurityError("Must be in a secure context"); | 506 exceptionState.throwSecurityError("Must be in a secure context"); |
| 492 return; | 507 return; |
| 493 } | 508 } |
| 494 | 509 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 event->setPaymentDetailsUpdater(this); | 562 event->setPaymentDetailsUpdater(this); |
| 548 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); | 563 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); |
| 549 DCHECK(success); | 564 DCHECK(success); |
| 550 ALLOW_UNUSED_LOCAL(success); | 565 ALLOW_UNUSED_LOCAL(success); |
| 551 } | 566 } |
| 552 | 567 |
| 553 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response
) | 568 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response
) |
| 554 { | 569 { |
| 555 DCHECK(m_showResolver); | 570 DCHECK(m_showResolver); |
| 556 DCHECK(!m_completeResolver); | 571 DCHECK(!m_completeResolver); |
| 572 DCHECK(!m_completeTimer.isActive()); |
| 557 | 573 |
| 558 if (m_options.requestShipping()) { | 574 if (m_options.requestShipping()) { |
| 559 if (!response->shipping_address || response->shipping_option.isEmpty())
{ | 575 if (!response->shipping_address || response->shipping_option.isEmpty())
{ |
| 560 m_showResolver->reject(DOMException::create(SyntaxError)); | 576 m_showResolver->reject(DOMException::create(SyntaxError)); |
| 561 clearResolversAndCloseMojoConnection(); | 577 clearResolversAndCloseMojoConnection(); |
| 562 return; | 578 return; |
| 563 } | 579 } |
| 564 | 580 |
| 565 String errorMessage; | 581 String errorMessage; |
| 566 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre
ss, &errorMessage)) { | 582 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre
ss, &errorMessage)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 581 | 597 |
| 582 if ((m_options.requestPayerEmail() && response->payer_email.isEmpty()) | 598 if ((m_options.requestPayerEmail() && response->payer_email.isEmpty()) |
| 583 || (m_options.requestPayerPhone() && response->payer_phone.isEmpty()) | 599 || (m_options.requestPayerPhone() && response->payer_phone.isEmpty()) |
| 584 || (!m_options.requestPayerEmail() && !response->payer_email.isNull()) | 600 || (!m_options.requestPayerEmail() && !response->payer_email.isNull()) |
| 585 || (!m_options.requestPayerPhone() && !response->payer_phone.isNull()))
{ | 601 || (!m_options.requestPayerPhone() && !response->payer_phone.isNull()))
{ |
| 586 m_showResolver->reject(DOMException::create(SyntaxError)); | 602 m_showResolver->reject(DOMException::create(SyntaxError)); |
| 587 clearResolversAndCloseMojoConnection(); | 603 clearResolversAndCloseMojoConnection(); |
| 588 return; | 604 return; |
| 589 } | 605 } |
| 590 | 606 |
| 607 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE); |
| 608 |
| 591 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); | 609 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); |
| 592 | 610 |
| 593 // Do not close the mojo connection here. The merchant website should call | 611 // Do not close the mojo connection here. The merchant website should call |
| 594 // PaymentResponse::complete(boolean), which will be forwarded over the mojo | 612 // PaymentResponse::complete(String), which will be forwarded over the mojo |
| 595 // connection to display a success or failure message to the user. | 613 // connection to display a success or failure message to the user. |
| 596 m_showResolver.clear(); | 614 m_showResolver.clear(); |
| 597 } | 615 } |
| 598 | 616 |
| 599 void PaymentRequest::OnError(mojo::PaymentErrorReason error) | 617 void PaymentRequest::OnError(mojo::PaymentErrorReason error) |
| 600 { | 618 { |
| 601 bool isError = false; | 619 bool isError = false; |
| 602 ExceptionCode ec = UnknownError; | 620 ExceptionCode ec = UnknownError; |
| 603 String message; | 621 String message; |
| 604 | 622 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 m_abortResolver->reject(DOMException::create(InvalidStateError)); | 677 m_abortResolver->reject(DOMException::create(InvalidStateError)); |
| 660 m_abortResolver.clear(); | 678 m_abortResolver.clear(); |
| 661 return; | 679 return; |
| 662 } | 680 } |
| 663 | 681 |
| 664 m_showResolver->reject(DOMException::create(AbortError)); | 682 m_showResolver->reject(DOMException::create(AbortError)); |
| 665 m_abortResolver->resolve(); | 683 m_abortResolver->resolve(); |
| 666 clearResolversAndCloseMojoConnection(); | 684 clearResolversAndCloseMojoConnection(); |
| 667 } | 685 } |
| 668 | 686 |
| 687 void PaymentRequest::onCompleteTimeout(TimerBase*) |
| 688 { |
| 689 m_completeTimer.stop(); |
| 690 m_paymentProvider->Complete(mojom::blink::PaymentComplete(Fail)); |
| 691 clearResolversAndCloseMojoConnection(); |
| 692 } |
| 693 |
| 669 void PaymentRequest::clearResolversAndCloseMojoConnection() | 694 void PaymentRequest::clearResolversAndCloseMojoConnection() |
| 670 { | 695 { |
| 671 m_completeResolver.clear(); | 696 m_completeResolver.clear(); |
| 672 m_showResolver.clear(); | 697 m_showResolver.clear(); |
| 673 m_abortResolver.clear(); | 698 m_abortResolver.clear(); |
| 674 if (m_clientBinding.is_bound()) | 699 if (m_clientBinding.is_bound()) |
| 675 m_clientBinding.Close(); | 700 m_clientBinding.Close(); |
| 676 m_paymentProvider.reset(); | 701 m_paymentProvider.reset(); |
| 677 } | 702 } |
| 678 | 703 |
| 679 } // namespace blink | 704 } // namespace blink |
| OLD | NEW |