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

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

Issue 2192413002: Timeout if website never completes the transaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Marijn's comments Created 4 years, 4 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 "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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698