Bug 1447773 - Time out PaymentResponse after 5 seconds.
MozReview-Commit-ID: JnoKgLC6yL6
--- a/dom/payments/PaymentRequestManager.cpp
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -473,23 +473,28 @@ PaymentRequestManager::AbortPayment(Paym
// If aDeferredShow is true, then show was called with a promise that was
// rejected. In that case, we need to remember that we called show earlier.
return SendRequestPayment(aRequest, action, aDeferredShow);
}
nsresult
PaymentRequestManager::CompletePayment(PaymentRequest* aRequest,
- const PaymentComplete& aComplete)
+ const PaymentComplete& aComplete,
+ bool aTimedOut)
{
nsString completeStatusString(NS_LITERAL_STRING("unknown"));
- uint8_t completeIndex = static_cast<uint8_t>(aComplete);
- if (completeIndex < ArrayLength(PaymentCompleteValues::strings)) {
- completeStatusString.AssignASCII(
- PaymentCompleteValues::strings[completeIndex].value);
+ if (aTimedOut) {
+ completeStatusString.AssignLiteral("timeout");
+ } else {
+ uint8_t completeIndex = static_cast<uint8_t>(aComplete);
+ if (completeIndex < ArrayLength(PaymentCompleteValues::strings)) {
+ completeStatusString.AssignASCII(
+ PaymentCompleteValues::strings[completeIndex].value);
+ }
}
nsAutoString requestId;
aRequest->GetInternalId(requestId);
IPCPaymentCompleteActionRequest action(requestId, completeStatusString);
return SendRequestPayment(aRequest, action, false);
}
--- a/dom/payments/PaymentRequestManager.h
+++ b/dom/payments/PaymentRequestManager.h
@@ -45,17 +45,18 @@ public:
const PaymentDetailsInit& aDetails,
const PaymentOptions& aOptions,
PaymentRequest** aRequest);
nsresult CanMakePayment(PaymentRequest* aRequest);
nsresult ShowPayment(PaymentRequest* aRequest);
nsresult AbortPayment(PaymentRequest* aRequest, bool aDeferredShow);
nsresult CompletePayment(PaymentRequest* aRequest,
- const PaymentComplete& aComplete);
+ const PaymentComplete& aComplete,
+ bool aTimedOut = false);
nsresult UpdatePayment(JSContext* aCx,
PaymentRequest* aRequest,
const PaymentDetailsUpdate& aDetails,
bool aRequestShipping,
bool aDeferredShow);
nsresult RespondPayment(PaymentRequest* aRequest,
const IPCPaymentActionResponse& aResponse);
--- a/dom/payments/PaymentResponse.cpp
+++ b/dom/payments/PaymentResponse.cpp
@@ -1,14 +1,15 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "mozilla/StaticPrefs.h"
#include "mozilla/dom/PaymentResponse.h"
#include "mozilla/dom/BasicCardPaymentBinding.h"
#include "BasicCardPayment.h"
#include "PaymentAddress.h"
#include "PaymentRequestUtils.h"
namespace mozilla {
namespace dom {
@@ -17,16 +18,17 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Pa
mShippingAddress, mPromise)
NS_IMPL_CYCLE_COLLECTING_ADDREF(PaymentResponse)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PaymentResponse)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PaymentResponse)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
+ NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_END
PaymentResponse::PaymentResponse(nsPIDOMWindowInner* aWindow,
PaymentRequest* aRequest,
const nsAString& aRequestId,
const nsAString& aMethodName,
const nsAString& aShippingOption,
RefPtr<PaymentAddress> aShippingAddress,
@@ -44,16 +46,21 @@ PaymentResponse::PaymentResponse(nsPIDOM
, mPayerName(aPayerName)
, mPayerEmail(aPayerEmail)
, mPayerPhone(aPayerPhone)
, mShippingAddress(aShippingAddress)
{
// TODO: from https://github.com/w3c/browser-payment-api/issues/480
// Add payerGivenName + payerFamilyName to PaymentAddress
+ NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+ this,
+ StaticPrefs::dom_payments_response_timeout(),
+ nsITimer::TYPE_ONE_SHOT,
+ aWindow->EventTargetFor(TaskCategory::Other));
}
PaymentResponse::~PaymentResponse()
{
}
JSObject*
PaymentResponse::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
@@ -131,44 +138,68 @@ PaymentResponse::GetShippingAddress() co
already_AddRefed<Promise>
PaymentResponse::Complete(PaymentComplete result, ErrorResult& aRv)
{
if (mCompleteCalled) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
- nsIGlobalObject* global = mOwner->AsGlobal();
- ErrorResult errResult;
- RefPtr<Promise> promise = Promise::Create(global, errResult);
- if (errResult.Failed()) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
+ mCompleteCalled = true;
+
+ if (mTimer) {
+ mTimer->Cancel();
+ mTimer = nullptr;
}
- mCompleteCalled = true;
-
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
if (NS_WARN_IF(!manager)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsresult rv = manager->CompletePayment(mRequest, result);
if (NS_WARN_IF(NS_FAILED(rv))) {
- promise->MaybeReject(NS_ERROR_FAILURE);
- return promise.forget();
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ nsIGlobalObject* global = mOwner->AsGlobal();
+ ErrorResult errResult;
+ RefPtr<Promise> promise = Promise::Create(global, errResult);
+ if (errResult.Failed()) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
}
mPromise = promise;
return promise.forget();
}
void
PaymentResponse::RespondComplete()
{
- MOZ_ASSERT(mPromise);
+ // mPromise may be null when timing out
+ if (mPromise) {
+ mPromise->MaybeResolve(JS::UndefinedHandleValue);
+ mPromise = nullptr;
+ }
+}
- mPromise->MaybeResolve(JS::UndefinedHandleValue);
- mPromise = nullptr;
+NS_IMETHODIMP
+PaymentResponse::Notify(nsITimer *timer)
+{
+ mTimer = nullptr;
+ if (mCompleteCalled) {
+ return NS_OK;
+ }
+
+ mCompleteCalled = true;
+
+ RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
+ if (NS_WARN_IF(!manager)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return manager->CompletePayment(mRequest, PaymentComplete::Unknown, true);
}
} // namespace dom
} // namespace mozilla
--- a/dom/payments/PaymentResponse.h
+++ b/dom/payments/PaymentResponse.h
@@ -5,31 +5,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PaymentResponse_h
#define mozilla_dom_PaymentResponse_h
#include "mozilla/dom/PaymentResponseBinding.h" // PaymentComplete
#include "nsPIDOMWindow.h"
#include "nsWrapperCache.h"
+#include "nsITimer.h"
namespace mozilla {
namespace dom {
class PaymentAddress;
class PaymentRequest;
class Promise;
-class PaymentResponse final : public nsISupports,
+class PaymentResponse final : public nsITimerCallback,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PaymentResponse)
+ NS_IMETHOD Notify(nsITimer* aTimer) override;
+
PaymentResponse(nsPIDOMWindowInner* aWindow,
PaymentRequest* aRequest,
const nsAString& aRequestId,
const nsAString& aMethodName,
const nsAString& aShippingOption,
RefPtr<PaymentAddress> aShippingAddress,
const nsAString& aDetails,
const nsAString& aPayerName,
@@ -78,14 +81,17 @@ private:
nsString mDetails;
nsString mShippingOption;
nsString mPayerName;
nsString mPayerEmail;
nsString mPayerPhone;
RefPtr<PaymentAddress> mShippingAddress;
// Promise for "PaymentResponse::Complete"
RefPtr<Promise> mPromise;
+ // Timer for timing out if the page doesn't call
+ // complete()
+ nsCOMPtr<nsITimer> mTimer;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PaymentResponse_h
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -111,16 +111,24 @@ VARCACHE_PREF(
RelaxedAtomicBool, false
)
// If true. then the service worker interception and the ServiceWorkerManager
// will live in the parent process. This only takes effect on browser start.
// Note, this is not currently safe to use for normal browsing yet.
PREF("dom.serviceWorkers.parent_intercept", bool, false)
+// Time in milliseconds for PaymentResponse to wait for
+// the Web page to call complete().
+VARCACHE_PREF(
+ "dom.payments.response.timeout",
+ dom_payments_response_timeout,
+ uint32_t, 5000
+)
+
//---------------------------------------------------------------------------
// Clear-Site-Data prefs
//---------------------------------------------------------------------------
#ifdef NIGHTLY
# define PREF_VALUE true
#else
# define PREF_VALUE false