mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 12:35:58 +00:00
Bug 1472026 - Implement PaymentResponse.prototype.onpayerdetailchange. r=edenchuang,baku
Implement PaymentResponse.prototype.onpayerdetailchange, per spec. Differential Revision: https://phabricator.services.mozilla.com/D5841 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
2e78564a84
commit
9dd1b3aeae
@ -54,6 +54,18 @@ interface nsIPaymentRequestService : nsISupports
|
||||
*/
|
||||
void changeShippingOption(in AString requestId, in AString option);
|
||||
|
||||
/**
|
||||
* Inform the merchant the payer's details changed in the PaymentResponse.
|
||||
* @param requestId - the request identifier of the payment request.
|
||||
* @param aPayerName - the changed payer's name.
|
||||
* @param aPayerEmail - the changed payer's email.
|
||||
* @param aPayerPhone - the changed payer's phone.
|
||||
*/
|
||||
void changePayerDetail(in AString requestId,
|
||||
in AString aPayerName,
|
||||
in AString aPayerEmail,
|
||||
in AString aPayerPhone);
|
||||
|
||||
/**
|
||||
* Following APIs are for testing or platform code only. UI implementation
|
||||
* should not use them.
|
||||
|
@ -605,7 +605,6 @@ PaymentRequest::Constructor(const GlobalObject& aGlobal,
|
||||
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
@ -965,6 +964,13 @@ PaymentRequest::SetUpdating(bool aUpdating)
|
||||
mUpdating = aUpdating;
|
||||
}
|
||||
|
||||
already_AddRefed<PaymentResponse>
|
||||
PaymentRequest::GetResponse() const
|
||||
{
|
||||
RefPtr<PaymentResponse> response = mResponse;
|
||||
return response.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentRequest::DispatchUpdateEvent(const nsAString& aType)
|
||||
{
|
||||
@ -1072,6 +1078,16 @@ PaymentRequest::GetShippingType() const
|
||||
return mShippingType;
|
||||
}
|
||||
|
||||
void PaymentRequest::GetOptions(PaymentOptions& aRetVal) const
|
||||
{
|
||||
aRetVal = mOptions;
|
||||
}
|
||||
|
||||
void PaymentRequest::SetOptions(const PaymentOptions& aOptions)
|
||||
{
|
||||
mOptions = aOptions;
|
||||
}
|
||||
|
||||
void
|
||||
PaymentRequest::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
|
@ -24,20 +24,23 @@ class PaymentAddress;
|
||||
class PaymentRequestChild;
|
||||
class PaymentResponse;
|
||||
|
||||
class PaymentRequest final : public DOMEventTargetHelper
|
||||
, public PromiseNativeHandler
|
||||
, public nsIDocumentActivity
|
||||
class PaymentRequest final
|
||||
: public DOMEventTargetHelper
|
||||
, public PromiseNativeHandler
|
||||
, public nsIDocumentActivity
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentRequest, DOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentRequest,
|
||||
DOMEventTargetHelper)
|
||||
NS_DECL_NSIDOCUMENTACTIVITY
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<PaymentRequest>
|
||||
CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv);
|
||||
static already_AddRefed<PaymentRequest> CreatePaymentRequest(
|
||||
nsPIDOMWindowInner* aWindow,
|
||||
nsresult& aRv);
|
||||
|
||||
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
@ -47,56 +50,51 @@ public:
|
||||
static nsresult IsValidPaymentMethodIdentifier(const nsAString& aIdentifier,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult IsValidMethodData(JSContext* aCx,
|
||||
const Sequence<PaymentMethodData>& aMethodData,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidMethodData(
|
||||
JSContext* aCx,
|
||||
const Sequence<PaymentMethodData>& aMethodData,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult
|
||||
IsValidNumber(const nsAString& aItem,
|
||||
const nsAString& aStr,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult
|
||||
IsNonNegativeNumber(const nsAString& aItem,
|
||||
const nsAString& aStr,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidNumber(const nsAString& aItem,
|
||||
const nsAString& aStr,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsNonNegativeNumber(const nsAString& aItem,
|
||||
const nsAString& aStr,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult
|
||||
IsValidCurrencyAmount(const nsAString& aItem,
|
||||
const PaymentCurrencyAmount& aAmount,
|
||||
const bool aIsTotalItem,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidCurrencyAmount(const nsAString& aItem,
|
||||
const PaymentCurrencyAmount& aAmount,
|
||||
const bool aIsTotalItem,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult
|
||||
IsValidCurrency(const nsAString& aItem,
|
||||
const nsAString& aCurrency,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidCurrency(const nsAString& aItem,
|
||||
const nsAString& aCurrency,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult
|
||||
IsValidDetailsInit(const PaymentDetailsInit& aDetails,
|
||||
const bool aRequestShipping,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidDetailsInit(const PaymentDetailsInit& aDetails,
|
||||
const bool aRequestShipping,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static nsresult
|
||||
IsValidDetailsUpdate(const PaymentDetailsUpdate& aDetails,
|
||||
const bool aRequestShipping);
|
||||
static nsresult IsValidDetailsUpdate(const PaymentDetailsUpdate& aDetails,
|
||||
const bool aRequestShipping);
|
||||
|
||||
static nsresult
|
||||
IsValidDetailsBase(const PaymentDetailsBase& aDetails,
|
||||
const bool aRequestShipping,
|
||||
nsAString& aErrorMsg);
|
||||
static nsresult IsValidDetailsBase(const PaymentDetailsBase& aDetails,
|
||||
const bool aRequestShipping,
|
||||
nsAString& aErrorMsg);
|
||||
|
||||
static already_AddRefed<PaymentRequest>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const Sequence<PaymentMethodData>& aMethodData,
|
||||
const PaymentDetailsInit& aDetails,
|
||||
const PaymentOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
static already_AddRefed<PaymentRequest> Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
const Sequence<PaymentMethodData>& aMethodData,
|
||||
const PaymentDetailsInit& aDetails,
|
||||
const PaymentOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> CanMakePayment(ErrorResult& aRv);
|
||||
void RespondCanMakePayment(bool aResult);
|
||||
|
||||
already_AddRefed<Promise> Show(const Optional<OwningNonNull<Promise>>& detailsPromise,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<Promise> Show(
|
||||
const Optional<OwningNonNull<Promise>>& detailsPromise,
|
||||
ErrorResult& aRv);
|
||||
void RespondShowPayment(const nsAString& aMethodName,
|
||||
const nsAString& aDetails,
|
||||
const nsAString& aPayerName,
|
||||
@ -121,6 +119,8 @@ public:
|
||||
bool IsUpdating() const { return mUpdating; }
|
||||
void SetUpdating(bool aUpdating);
|
||||
|
||||
already_AddRefed<PaymentResponse> GetResponse() const;
|
||||
|
||||
already_AddRefed<PaymentAddress> GetShippingAddress() const;
|
||||
// Update mShippingAddress and fire shippingaddresschange event
|
||||
nsresult UpdateShippingAddress(const nsAString& aCountry,
|
||||
@ -134,42 +134,36 @@ public:
|
||||
const nsAString& aRecipient,
|
||||
const nsAString& aPhone);
|
||||
|
||||
|
||||
void SetShippingOption(const nsAString& aShippingOption);
|
||||
void GetShippingOption(nsAString& aRetVal) const;
|
||||
void GetOptions(PaymentOptions& aRetVal) const;
|
||||
void SetOptions(const PaymentOptions& aOptions);
|
||||
nsresult UpdateShippingOption(const nsAString& aShippingOption);
|
||||
|
||||
nsresult UpdatePayment(JSContext* aCx, const PaymentDetailsUpdate& aDetails,
|
||||
nsresult UpdatePayment(JSContext* aCx,
|
||||
const PaymentDetailsUpdate& aDetails,
|
||||
bool aDeferredShow);
|
||||
void AbortUpdate(nsresult aRv, bool aDeferredShow);
|
||||
|
||||
void SetShippingType(const Nullable<PaymentShippingType>& aShippingType);
|
||||
Nullable<PaymentShippingType> GetShippingType() const;
|
||||
|
||||
inline void ShippingWasRequested()
|
||||
{
|
||||
mRequestShipping = true;
|
||||
}
|
||||
inline void ShippingWasRequested() { mRequestShipping = true; }
|
||||
|
||||
void
|
||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
void
|
||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
IMPL_EVENT_HANDLER(merchantvalidation);
|
||||
IMPL_EVENT_HANDLER(shippingaddresschange);
|
||||
IMPL_EVENT_HANDLER(shippingoptionchange);
|
||||
IMPL_EVENT_HANDLER(paymentmethodchange);
|
||||
|
||||
void SetIPC(PaymentRequestChild* aChild)
|
||||
{
|
||||
mIPC = aChild;
|
||||
}
|
||||
void SetIPC(PaymentRequestChild* aChild) { mIPC = aChild; }
|
||||
|
||||
PaymentRequestChild* GetIPC()
|
||||
{
|
||||
return mIPC;
|
||||
}
|
||||
PaymentRequestChild* GetIPC() const { return mIPC; }
|
||||
|
||||
private:
|
||||
PaymentOptions mOptions;
|
||||
|
||||
protected:
|
||||
~PaymentRequest();
|
||||
@ -206,8 +200,8 @@ protected:
|
||||
|
||||
Nullable<PaymentShippingType> mShippingType;
|
||||
|
||||
// "true" when there is a pending updateWith() call to update the payment request
|
||||
// and "false" otherwise.
|
||||
// "true" when there is a pending updateWith() call to update the payment
|
||||
// request and "false" otherwise.
|
||||
bool mUpdating;
|
||||
|
||||
// Whether shipping was requested. This models [[options]].requestShipping,
|
||||
@ -221,7 +215,8 @@ protected:
|
||||
// The error is set in AbortUpdate(). The value is NS_OK by default.
|
||||
nsresult mUpdateError;
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
eUnknown,
|
||||
eCreated,
|
||||
eInteractive,
|
||||
@ -230,7 +225,6 @@ protected:
|
||||
|
||||
PaymentRequestChild* mIPC;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -382,7 +382,7 @@ PaymentRequestManager::CreatePayment(JSContext* aCx,
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
request->SetOptions(aOptions);
|
||||
/*
|
||||
* Set request's |mId| to details.id if details.id exists.
|
||||
* Otherwise, set |mId| to internal id.
|
||||
@ -687,5 +687,20 @@ PaymentRequestManager::ChangeShippingOption(PaymentRequest* aRequest,
|
||||
return aRequest->UpdateShippingOption(aOption);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentRequestManager::ChangePayerDetail(PaymentRequest* aRequest,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone)
|
||||
{
|
||||
MOZ_ASSERT(aRequest);
|
||||
RefPtr<PaymentResponse> response = aRequest->GetResponse();
|
||||
// ignoring the case call changePayerDetail during show().
|
||||
if (!response) {
|
||||
return NS_OK;
|
||||
}
|
||||
return response->UpdatePayerDetail(aPayerName, aPayerEmail, aPayerPhone);
|
||||
}
|
||||
|
||||
} // end of namespace dom
|
||||
} // end of namespace mozilla
|
||||
|
@ -69,6 +69,11 @@ public:
|
||||
nsresult ChangeShippingOption(PaymentRequest* aRequest,
|
||||
const nsAString& aOption);
|
||||
|
||||
nsresult ChangePayerDetail(PaymentRequest* aRequest,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone);
|
||||
|
||||
// Called to ensure that we don't "leak" aRequest if we shut down while it had
|
||||
// an active request to the parent.
|
||||
void RequestIPCOver(PaymentRequest* aRequest);
|
||||
|
@ -564,5 +564,31 @@ PaymentRequestService::IsBasicCardPayment(const nsAString& aRequestId)
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PaymentRequestService::ChangePayerDetail(const nsAString& aRequestId,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone)
|
||||
{
|
||||
nsCOMPtr<nsIPaymentRequest> request;
|
||||
nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(request);
|
||||
payments::PaymentRequest* rowRequest =
|
||||
static_cast<payments::PaymentRequest*>(request.get());
|
||||
if (!rowRequest->GetIPC()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = rowRequest->GetIPC()->ChangePayerDetail(
|
||||
aRequestId, aPayerName, aPayerEmail, aPayerPhone);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // end of namespace dom
|
||||
} // end of namespace mozilla
|
||||
|
@ -7,24 +7,43 @@
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/dom/PaymentResponse.h"
|
||||
#include "mozilla/dom/BasicCardPaymentBinding.h"
|
||||
#include "mozilla/dom/PaymentRequestUpdateEvent.h"
|
||||
#include "BasicCardPayment.h"
|
||||
#include "PaymentAddress.h"
|
||||
#include "PaymentRequestUtils.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PaymentResponse, mOwner,
|
||||
mShippingAddress, mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentResponse)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PaymentResponse)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PaymentResponse)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentResponse,
|
||||
DOMEventTargetHelper)
|
||||
// Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
|
||||
// DOMEventTargetHelper does it for us.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PaymentResponse,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mShippingAddress)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PaymentResponse,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mShippingAddress)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTimer)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
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
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(PaymentResponse, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(PaymentResponse, DOMEventTargetHelper)
|
||||
|
||||
PaymentResponse::PaymentResponse(nsPIDOMWindowInner* aWindow,
|
||||
PaymentRequest* aRequest,
|
||||
@ -36,7 +55,7 @@ PaymentResponse::PaymentResponse(nsPIDOMWindowInner* aWindow,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone)
|
||||
: mOwner(aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mCompleteCalled(false)
|
||||
, mRequest(aRequest)
|
||||
, mRequestId(aRequestId)
|
||||
@ -58,9 +77,7 @@ PaymentResponse::PaymentResponse(nsPIDOMWindowInner* aWindow,
|
||||
aWindow->EventTargetFor(TaskCategory::Other));
|
||||
}
|
||||
|
||||
PaymentResponse::~PaymentResponse()
|
||||
{
|
||||
}
|
||||
PaymentResponse::~PaymentResponse() = default;
|
||||
|
||||
JSObject*
|
||||
PaymentResponse::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
@ -81,7 +98,8 @@ PaymentResponse::GetMethodName(nsString& aRetVal) const
|
||||
}
|
||||
|
||||
void
|
||||
PaymentResponse::GetDetails(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal) const
|
||||
PaymentResponse::GetDetails(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
RefPtr<BasicCardService> service = BasicCardService::GetService();
|
||||
MOZ_ASSERT(service);
|
||||
@ -89,7 +107,7 @@ PaymentResponse::GetDetails(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal
|
||||
DeserializeToJSObject(mDetails, aCx, aRetVal);
|
||||
} else {
|
||||
BasicCardResponse response;
|
||||
nsresult rv = service->DecodeBasicCardData(mDetails, mOwner, response);
|
||||
nsresult rv = service->DecodeBasicCardData(mDetails, GetOwner(), response);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@ -115,12 +133,14 @@ PaymentResponse::GetPayerName(nsString& aRetVal) const
|
||||
aRetVal = mPayerName;
|
||||
}
|
||||
|
||||
void PaymentResponse::GetPayerEmail(nsString& aRetVal) const
|
||||
void
|
||||
PaymentResponse::GetPayerEmail(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mPayerEmail;
|
||||
}
|
||||
|
||||
void PaymentResponse::GetPayerPhone(nsString& aRetVal) const
|
||||
void
|
||||
PaymentResponse::GetPayerPhone(nsString& aRetVal) const
|
||||
{
|
||||
aRetVal = mPayerPhone;
|
||||
}
|
||||
@ -161,7 +181,12 @@ PaymentResponse::Complete(PaymentComplete result, ErrorResult& aRv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject* global = mOwner->AsGlobal();
|
||||
if (NS_WARN_IF(!GetOwner())) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIGlobalObject* global = GetOwner()->AsGlobal();
|
||||
ErrorResult errResult;
|
||||
RefPtr<Promise> promise = Promise::Create(global, errResult);
|
||||
if (errResult.Failed()) {
|
||||
@ -188,7 +213,7 @@ PaymentResponse::Retry(JSContext* aCx,
|
||||
const PaymentValidationErrors& aErrors,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsIGlobalObject* global = mOwner->AsGlobal();
|
||||
nsIGlobalObject* global = GetOwner()->AsGlobal();
|
||||
ErrorResult errResult;
|
||||
RefPtr<Promise> promise = Promise::Create(global, errResult);
|
||||
if (errResult.Failed()) {
|
||||
@ -201,7 +226,12 @@ PaymentResponse::Retry(JSContext* aCx,
|
||||
mTimer = nullptr;
|
||||
}
|
||||
|
||||
nsIDocument* doc = mOwner->GetExtantDoc();
|
||||
if (NS_WARN_IF(!GetOwner())) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetOwner()->GetExtantDoc();
|
||||
if (!doc || !doc->IsCurrentActiveDocument()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
return promise.forget();
|
||||
@ -246,11 +276,15 @@ PaymentResponse::RespondRetry(const nsAString& aMethodName,
|
||||
mPayerEmail = aPayerEmail;
|
||||
mPayerPhone = aPayerPhone;
|
||||
|
||||
if (NS_WARN_IF(!GetOwner())) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_NewTimerWithCallback(getter_AddRefs(mTimer),
|
||||
this,
|
||||
StaticPrefs::dom_payments_response_timeout(),
|
||||
nsITimer::TYPE_ONE_SHOT,
|
||||
mOwner->EventTargetFor(TaskCategory::Other));
|
||||
GetOwner()->EventTargetFor(TaskCategory::Other));
|
||||
MOZ_ASSERT(mRetryPromise);
|
||||
mRetryPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
mRetryPromise = nullptr;
|
||||
@ -265,7 +299,8 @@ PaymentResponse::RejectRetry(nsresult aRejectReason)
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentResponse::ValidatePaymentValidationErrors(const PaymentValidationErrors& aErrors)
|
||||
PaymentResponse::ValidatePaymentValidationErrors(
|
||||
const PaymentValidationErrors& aErrors)
|
||||
{
|
||||
// Should not be empty errors
|
||||
// check PaymentValidationErrors.error
|
||||
@ -318,8 +353,7 @@ PaymentResponse::ValidatePaymentValidationErrors(const PaymentValidationErrors&
|
||||
!addErrors.mRecipient.Value().IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (addErrors.mRegion.WasPassed() &&
|
||||
!addErrors.mRegion.Value().IsEmpty()) {
|
||||
if (addErrors.mRegion.WasPassed() && !addErrors.mRegion.Value().IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (addErrors.mRegionCode.WasPassed() &&
|
||||
@ -334,7 +368,7 @@ PaymentResponse::ValidatePaymentValidationErrors(const PaymentValidationErrors&
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PaymentResponse::Notify(nsITimer *timer)
|
||||
PaymentResponse::Notify(nsITimer* timer)
|
||||
{
|
||||
mTimer = nullptr;
|
||||
if (mCompleteCalled) {
|
||||
@ -351,5 +385,39 @@ PaymentResponse::Notify(nsITimer *timer)
|
||||
return manager->CompletePayment(mRequest, PaymentComplete::Unknown, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentResponse::UpdatePayerDetail(const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone)
|
||||
{
|
||||
MOZ_ASSERT(mRequest->ReadyForUpdate());
|
||||
PaymentOptions options;
|
||||
mRequest->GetOptions(options);
|
||||
if (options.mRequestPayerName) {
|
||||
mPayerName = aPayerName;
|
||||
}
|
||||
if (options.mRequestPayerEmail) {
|
||||
mPayerEmail = aPayerEmail;
|
||||
}
|
||||
if (options.mRequestPayerPhone) {
|
||||
mPayerPhone = aPayerPhone;
|
||||
}
|
||||
return DispatchUpdateEvent(NS_LITERAL_STRING("payerdetailchange"));
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentResponse::DispatchUpdateEvent(const nsAString& aType)
|
||||
{
|
||||
PaymentRequestUpdateEventInit init;
|
||||
RefPtr<PaymentRequestUpdateEvent> event =
|
||||
PaymentRequestUpdateEvent::Constructor(this, aType, init);
|
||||
event->SetTrusted(true);
|
||||
event->SetRequest(mRequest);
|
||||
|
||||
ErrorResult rv;
|
||||
DispatchEvent(*event, rv);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -7,9 +7,9 @@
|
||||
#ifndef mozilla_dom_PaymentResponse_h
|
||||
#define mozilla_dom_PaymentResponse_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/PaymentResponseBinding.h" // PaymentComplete
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -19,12 +19,15 @@ class PaymentAddress;
|
||||
class PaymentRequest;
|
||||
class Promise;
|
||||
|
||||
class PaymentResponse final : public nsITimerCallback,
|
||||
public nsWrapperCache
|
||||
class PaymentResponse final
|
||||
: public DOMEventTargetHelper
|
||||
, public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PaymentResponse)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentResponse,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
NS_IMETHOD Notify(nsITimer* aTimer) override;
|
||||
|
||||
@ -39,11 +42,6 @@ public:
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone);
|
||||
|
||||
nsPIDOMWindowInner* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
@ -69,6 +67,12 @@ public:
|
||||
|
||||
void RespondComplete();
|
||||
|
||||
IMPL_EVENT_HANDLER(payerdetailchange);
|
||||
|
||||
nsresult UpdatePayerDetail(const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone);
|
||||
|
||||
already_AddRefed<Promise> Retry(JSContext* aCx,
|
||||
const PaymentValidationErrors& errorField,
|
||||
ErrorResult& aRv);
|
||||
@ -87,8 +91,9 @@ protected:
|
||||
|
||||
nsresult ValidatePaymentValidationErrors(const PaymentValidationErrors& aErrors);
|
||||
|
||||
nsresult DispatchUpdateEvent(const nsAString& aType);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
||||
bool mCompleteCalled;
|
||||
PaymentRequest* mRequest;
|
||||
nsString mRequestId;
|
||||
|
@ -199,6 +199,10 @@ child:
|
||||
IPCPaymentAddress aAddress);
|
||||
async ChangeShippingOption(nsString aRequestId,
|
||||
nsString aOption);
|
||||
async ChangePayerDetail(nsString aRequestId,
|
||||
nsString aPayerName,
|
||||
nsString aPayerEmail,
|
||||
nsString aPayerPhone);
|
||||
};
|
||||
|
||||
} // end of namespace dom
|
||||
|
@ -82,6 +82,25 @@ PaymentRequestChild::RecvChangeShippingOption(const nsString& aRequestId,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PaymentRequestChild::RecvChangePayerDetail(const nsString& aRequestId,
|
||||
const nsString& aPayerName,
|
||||
const nsString& aPayerEmail,
|
||||
const nsString& aPayerPhone)
|
||||
{
|
||||
if (!mRequest) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
MOZ_ASSERT(manager);
|
||||
RefPtr<PaymentRequest> request(mRequest);
|
||||
nsresult rv = manager->ChangePayerDetail(request, aPayerName, aPayerEmail, aPayerPhone);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
@ -35,6 +35,12 @@ protected:
|
||||
RecvChangeShippingOption(const nsString& aRequestId,
|
||||
const nsString& aOption) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvChangePayerDetail(const nsString& aRequestId,
|
||||
const nsString& aPayerName,
|
||||
const nsString& aPayerEmail,
|
||||
const nsString& aPayerPhone) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
|
@ -299,6 +299,34 @@ PaymentRequestParent::ChangeShippingOption(const nsAString& aRequestId,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentRequestParent::ChangePayerDetail(const nsAString& aRequestId,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone)
|
||||
{
|
||||
nsAutoString requestId(aRequestId);
|
||||
nsAutoString payerName(aPayerName);
|
||||
nsAutoString payerEmail(aPayerEmail);
|
||||
nsAutoString payerPhone(aPayerPhone);
|
||||
if (!NS_IsMainThread()) {
|
||||
RefPtr<PaymentRequestParent> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("dom::PaymentRequestParent::ChangePayerDetail",
|
||||
[self, requestId, payerName, payerEmail, payerPhone] ()
|
||||
{
|
||||
self->ChangePayerDetail(requestId, payerName, payerEmail, payerPhone);
|
||||
});
|
||||
return NS_DispatchToMainThread(r);
|
||||
}
|
||||
if (!mActorAlive) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!SendChangePayerDetail(requestId, payerName, payerEmail, payerPhone)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PaymentRequestParent::Recv__delete__()
|
||||
{
|
||||
|
@ -26,6 +26,10 @@ public:
|
||||
nsIPaymentAddress* aAddress);
|
||||
nsresult ChangeShippingOption(const nsAString& aRequestId,
|
||||
const nsAString& aOption);
|
||||
nsresult ChangePayerDetail(const nsAString& aRequestId,
|
||||
const nsAString& aPayerName,
|
||||
const nsAString& aPayerEmail,
|
||||
const nsAString& aPayerPhone);
|
||||
|
||||
protected:
|
||||
mozilla::ipc::IPCResult
|
||||
|
80
dom/payments/test/PayerDetailsChromeScript.js
Normal file
80
dom/payments/test/PayerDetailsChromeScript.js
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
const paymentSrv = Cc[
|
||||
"@mozilla.org/dom/payments/payment-request-service;1"
|
||||
].getService(Ci.nsIPaymentRequestService);
|
||||
|
||||
const TestingUIService = {
|
||||
showPayment(requestId, name = "", email = "", phone = "") {
|
||||
const showResponseData = Cc[
|
||||
"@mozilla.org/dom/payments/general-response-data;1"
|
||||
].createInstance(Ci.nsIGeneralResponseData);
|
||||
showResponseData.initData({});
|
||||
const showResponse = Cc[
|
||||
"@mozilla.org/dom/payments/payment-show-action-response;1"
|
||||
].createInstance(Ci.nsIPaymentShowActionResponse);
|
||||
showResponse.init(
|
||||
requestId,
|
||||
Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
|
||||
"testing-payment-method", // payment method
|
||||
showResponseData, // payment method data
|
||||
name,
|
||||
email,
|
||||
phone
|
||||
);
|
||||
paymentSrv.respondPayment(
|
||||
showResponse.QueryInterface(Ci.nsIPaymentActionResponse)
|
||||
);
|
||||
},
|
||||
// .retry({ payer }) and .updateWith({payerErrors}) both get routed here:
|
||||
updatePayment(requestId) {
|
||||
// Let's echo what was sent in by the error...
|
||||
const request = paymentSrv.getPaymentRequestById(requestId);
|
||||
const { name, email, phone } = request.paymentDetails.payer;
|
||||
const { error } = request.paymentDetails;
|
||||
// Let's use the .error as the switch
|
||||
switch (error) {
|
||||
case "retry-fire-payerdetaichangeevent": {
|
||||
paymentSrv.changePayerDetail(requestId, name, email, phone);
|
||||
break;
|
||||
}
|
||||
case "update-with": {
|
||||
this.showPayment(requestId, name, email, phone);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
const msg = `Expect details.error value: '${error}'`;
|
||||
sendAsyncMessage("test-fail", msg);
|
||||
}
|
||||
},
|
||||
completePayment(requestId) {
|
||||
const request = paymentSrv.getPaymentRequestById(requestId);
|
||||
const completeResponse = Cc[
|
||||
"@mozilla.org/dom/payments/payment-complete-action-response;1"
|
||||
].createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||
completeResponse.init(
|
||||
requestId,
|
||||
Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED
|
||||
);
|
||||
paymentSrv.respondPayment(
|
||||
completeResponse.QueryInterface(Ci.nsIPaymentActionResponse)
|
||||
);
|
||||
},
|
||||
get QueryInterface() {
|
||||
return ChromeUtils.generateQI([Ci.nsIPaymentUIService]);
|
||||
},
|
||||
};
|
||||
|
||||
paymentSrv.setTestingUIService(
|
||||
TestingUIService.QueryInterface(Ci.nsIPaymentUIService)
|
||||
);
|
||||
|
||||
addMessageListener("teardown", () => {
|
||||
paymentSrv.setTestingUIService(null);
|
||||
sendAsyncMessage("teardown-complete");
|
||||
});
|
@ -13,6 +13,7 @@ support-files =
|
||||
CurrencyAmountValidationChromeScript.js
|
||||
DefaultData.js
|
||||
GeneralChromeScript.js
|
||||
PayerDetailsChromeScript.js
|
||||
PMIValidationChromeScript.js
|
||||
RequestShippingChromeScript.js
|
||||
RetryPaymentChromeScript.js
|
||||
@ -24,6 +25,7 @@ support-files =
|
||||
run-if = nightly_build # Bug 1390018: Depends on the Nightly-only UI service
|
||||
[test_basiccard.html]
|
||||
[test_block_none10s.html]
|
||||
[test_payerDetails.html]
|
||||
skip-if = e10s # Bug 1408250: Don't expose PaymentRequest Constructor in non-e10s
|
||||
[test_bug1490698.html]
|
||||
[test_canMakePayment.html]
|
||||
|
108
dom/payments/test/test_payerDetails.html
Normal file
108
dom/payments/test/test_payerDetails.html
Normal file
@ -0,0 +1,108 @@
|
||||
<!DOCTYPE HTML>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for PaymentResponse.prototype.onpayerdetailchange</title>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="./DefaultData.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(1000);
|
||||
|
||||
const gUrl = SimpleTest.getTestFileURL("PayerDetailsChromeScript.js");
|
||||
const gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
|
||||
function okTester(result) {
|
||||
return message => ok(result, message);
|
||||
}
|
||||
const passListener = okTester(true);
|
||||
const failListener = okTester(false);
|
||||
|
||||
gScript.addMessageListener("test-fail", failListener);
|
||||
gScript.addMessageListener("test-pass", passListener);
|
||||
|
||||
function sendOnce(message) {
|
||||
return data => {
|
||||
return new Promise(resolve => {
|
||||
const doneMsg = `${message}-complete`;
|
||||
gScript.addMessageListener(doneMsg, function listener() {
|
||||
gScript.removeMessageListener(doneMsg, listener);
|
||||
resolve();
|
||||
});
|
||||
gScript.sendAsyncMessage(message, data);
|
||||
});
|
||||
};
|
||||
}
|
||||
const sendTearDown = sendOnce("teardown");
|
||||
|
||||
async function loopTest(iterations) {
|
||||
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(
|
||||
true
|
||||
);
|
||||
const options = {
|
||||
requestPayerName: true,
|
||||
requestPayerEmail: true,
|
||||
requestPayerPhone: true,
|
||||
}
|
||||
const request = new PaymentRequest(defaultMethods, defaultDetails, options);
|
||||
const response = await request.show();
|
||||
is(response.payerName, "", ".payerName must initially be ''");
|
||||
is(response.payerEmail, "", ".payerEmail must initially be ''");
|
||||
is(response.payerPhone, "", ".payerPhone must initially be ''");
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
const payer = {
|
||||
name: `test name ${i}`,
|
||||
phone: `test phone ${i}`,
|
||||
email: `test email ${i}`,
|
||||
}
|
||||
|
||||
// Capture the event to firing
|
||||
const eventPromise = new Promise(resolve => {
|
||||
response.onpayerdetailchange = resolve;
|
||||
});
|
||||
const retryPromise = response.retry({
|
||||
error: "retry-fire-payerdetaichangeevent",
|
||||
payer
|
||||
});
|
||||
const event = await eventPromise;
|
||||
|
||||
// Check things got updated
|
||||
is(response.payerName, payer.name, `.payerName must be "${payer.name}"`);
|
||||
is(response.payerEmail, payer.email, `.payerEmail must be "${payer.email}"`);
|
||||
is(response.payerPhone, payer.phone, `.payerPhone must be "${payer.phone}"`);
|
||||
|
||||
// Finally, let's do an updateWith()
|
||||
event.updateWith({ error: "update-with", payerErrors: payer, ...defaultDetails });
|
||||
|
||||
await retryPromise;
|
||||
}
|
||||
|
||||
await response.complete("success");
|
||||
handler.destruct();
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
await sendTearDown();
|
||||
gScript.removeMessageListener("test-fail", failListener);
|
||||
gScript.removeMessageListener("test-pass", passListener);
|
||||
gScript.destroy();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
try {
|
||||
await loopTest(5); // lets go around 5 times
|
||||
} catch (err) {
|
||||
ok(false, `Unexpected error: ${err}.`);
|
||||
} finally {
|
||||
await teardown();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const prefs = [["dom.payments.request.enabled", true]];
|
||||
SpecialPowers.pushPrefEnv({ set: prefs }, runTests);
|
||||
});
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1472026">Mozilla Bug 1472026</a>
|
@ -18,7 +18,7 @@ enum PaymentComplete {
|
||||
|
||||
[SecureContext,
|
||||
Func="mozilla::dom::PaymentRequest::PrefEnabled"]
|
||||
interface PaymentResponse {
|
||||
interface PaymentResponse : EventTarget {
|
||||
[Default] object toJSON();
|
||||
|
||||
readonly attribute DOMString requestId;
|
||||
@ -36,4 +36,6 @@ interface PaymentResponse {
|
||||
// If the dictionary argument has no required members, it must be optional.
|
||||
[NewObject]
|
||||
Promise<void> retry(optional PaymentValidationErrors errorFields);
|
||||
|
||||
attribute EventHandler onpayerdetailchange;
|
||||
};
|
||||
|
@ -802,6 +802,7 @@ STATIC_ATOMS = [
|
||||
Atom("onpagehide", "onpagehide"),
|
||||
Atom("onpageshow", "onpageshow"),
|
||||
Atom("onpaste", "onpaste"),
|
||||
Atom("onpayerdetailchange", "onpayerdetailchange"),
|
||||
Atom("onpaymentmethodchange", "onpaymentmethodchange"),
|
||||
Atom("onpointerlockchange", "onpointerlockchange"),
|
||||
Atom("onpointerlockerror", "onpointerlockerror"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user