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

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: Rebase 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::onTimerFired(TimerBase*)
490 {
491 m_completeTimer.stop();
492 m_paymentProvider->Complete(mojom::blink::PaymentComplete(Fail));
493 clearResolversAndCloseMojoConnection();
494 }
495
480 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState) 496 PaymentRequest::PaymentRequest(ScriptState* scriptState, const HeapVector<Paymen tMethodData>& methodData, const PaymentDetails& details, const PaymentOptions& o ptions, ExceptionState& exceptionState)
481 : ContextLifecycleObserver(scriptState->getExecutionContext()) 497 : ContextLifecycleObserver(scriptState->getExecutionContext())
482 , ActiveScriptWrappable(this) 498 , ActiveScriptWrappable(this)
483 , m_options(options) 499 , m_options(options)
484 , m_clientBinding(this) 500 , m_clientBinding(this)
501 , m_completeTimer(this, &PaymentRequest::onTimerFired)
485 { 502 {
486 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat e); 503 validateAndConvertPaymentMethodData(methodData, &m_methodData, exceptionStat e);
487 if (exceptionState.hadException()) 504 if (exceptionState.hadException())
488 return; 505 return;
489 506
490 if (!scriptState->getExecutionContext()->isSecureContext()) { 507 if (!scriptState->getExecutionContext()->isSecureContext()) {
491 exceptionState.throwSecurityError("Must be in a secure context"); 508 exceptionState.throwSecurityError("Must be in a secure context");
492 return; 509 return;
493 } 510 }
494 511
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 event->setPaymentDetailsUpdater(this); 564 event->setPaymentDetailsUpdater(this);
548 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); 565 bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event);
549 DCHECK(success); 566 DCHECK(success);
550 ALLOW_UNUSED_LOCAL(success); 567 ALLOW_UNUSED_LOCAL(success);
551 } 568 }
552 569
553 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response ) 570 void PaymentRequest::OnPaymentResponse(mojom::blink::PaymentResponsePtr response )
554 { 571 {
555 DCHECK(m_showResolver); 572 DCHECK(m_showResolver);
556 DCHECK(!m_completeResolver); 573 DCHECK(!m_completeResolver);
574 DCHECK(!m_completeTimer.isActive());
557 575
558 if (m_options.requestShipping()) { 576 if (m_options.requestShipping()) {
559 if (!response->shipping_address || response->shipping_option.isEmpty()) { 577 if (!response->shipping_address || response->shipping_option.isEmpty()) {
560 m_showResolver->reject(DOMException::create(SyntaxError)); 578 m_showResolver->reject(DOMException::create(SyntaxError));
561 clearResolversAndCloseMojoConnection(); 579 clearResolversAndCloseMojoConnection();
562 return; 580 return;
563 } 581 }
564 582
565 String errorMessage; 583 String errorMessage;
566 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre ss, &errorMessage)) { 584 if (!PaymentsValidators::isValidShippingAddress(response->shipping_addre ss, &errorMessage)) {
(...skipping 14 matching lines...) Expand all
581 599
582 if ((m_options.requestPayerEmail() && response->payer_email.isEmpty()) 600 if ((m_options.requestPayerEmail() && response->payer_email.isEmpty())
583 || (m_options.requestPayerPhone() && response->payer_phone.isEmpty()) 601 || (m_options.requestPayerPhone() && response->payer_phone.isEmpty())
584 || (!m_options.requestPayerEmail() && !response->payer_email.isNull()) 602 || (!m_options.requestPayerEmail() && !response->payer_email.isNull())
585 || (!m_options.requestPayerPhone() && !response->payer_phone.isNull())) { 603 || (!m_options.requestPayerPhone() && !response->payer_phone.isNull())) {
586 m_showResolver->reject(DOMException::create(SyntaxError)); 604 m_showResolver->reject(DOMException::create(SyntaxError));
587 clearResolversAndCloseMojoConnection(); 605 clearResolversAndCloseMojoConnection();
588 return; 606 return;
589 } 607 }
590 608
609 m_completeTimer.startOneShot(completeTimeoutSeconds, BLINK_FROM_HERE);
610
591 m_showResolver->resolve(new PaymentResponse(std::move(response), this)); 611 m_showResolver->resolve(new PaymentResponse(std::move(response), this));
592 612
593 // Do not close the mojo connection here. The merchant website should call 613 // Do not close the mojo connection here. The merchant website should call
594 // PaymentResponse::complete(boolean), which will be forwarded over the mojo 614 // PaymentResponse::complete(String), which will be forwarded over the mojo
595 // connection to display a success or failure message to the user. 615 // connection to display a success or failure message to the user.
596 m_showResolver.clear(); 616 m_showResolver.clear();
597 } 617 }
598 618
599 void PaymentRequest::OnError(mojo::PaymentErrorReason error) 619 void PaymentRequest::OnError(mojo::PaymentErrorReason error)
600 { 620 {
601 bool isError = false; 621 bool isError = false;
602 ExceptionCode ec = UnknownError; 622 ExceptionCode ec = UnknownError;
603 String message; 623 String message;
604 624
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 { 690 {
671 m_completeResolver.clear(); 691 m_completeResolver.clear();
672 m_showResolver.clear(); 692 m_showResolver.clear();
673 m_abortResolver.clear(); 693 m_abortResolver.clear();
674 if (m_clientBinding.is_bound()) 694 if (m_clientBinding.is_bound())
675 m_clientBinding.Close(); 695 m_clientBinding.Close();
676 m_paymentProvider.reset(); 696 m_paymentProvider.reset();
677 } 697 }
678 698
679 } // namespace blink 699 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698