Bug 1385187 - Reject PaymentRequest.show() with NotSupportedError DOMException if no supported method. r=baku

1. Create a new action response status PAYMENT_NOTSUPPORTED and get rid of
   unnecessary method isAccpeted() from nsIPaymentActionResponse.idl.
2. Create canMakePayment() in PaymentRequestService and run it before
   launching UI. If canMakePayment() returns false, send PAYMENT_NOTSUPPORTED
   back to content process.
3. If chrome process returns PAYMENT_NOTSUPPORTED when calling showPayment(),
   throw NotSupportedError DOMException to merchant side.
This commit is contained in:
Eden Chuang 2017-08-28 11:55:59 +08:00
parent 96889965b9
commit af95d86b7f
9 changed files with 88 additions and 67 deletions

View File

@ -66,8 +66,9 @@ interface nsIPaymentActionResponse : nsISupports
const uint32_t ABORT_SUCCEEDED = 1;
const uint32_t ABORT_FAILED = 0;
const uint32_t PAYMENT_ACCEPTED = 1;
const uint32_t PAYMENT_REJECTED = 0;
const uint32_t PAYMENT_ACCEPTED = 1;
const uint32_t PAYMENT_NOTSUPPORTED = 2;
const uint32_t COMPLETE_SUCCEEDED = 1;
const uint32_t COMPLETE_FAILED = 0;
@ -140,11 +141,6 @@ interface nsIPaymentShowActionResponse : nsIPaymentActionResponse
in AString aPayerName,
in AString aPayerEmail,
in AString aPayerPhone);
/*
* Check if the payment is accpeted
*/
bool isAccepted();
};
[builtinclass, scriptable, uuid(8c72bcdb-0c37-4786-a9e5-510afa2f8ede)]

View File

@ -236,7 +236,10 @@ PaymentShowActionResponse::Init(const nsAString& aRequestId,
const nsAString& aPayerEmail,
const nsAString& aPayerPhone)
{
NS_ENSURE_ARG_POINTER(aData);
if (aAcceptStatus == nsIPaymentActionResponse::PAYMENT_ACCEPTED) {
NS_ENSURE_ARG_POINTER(aData);
}
mRequestId = aRequestId;
mAcceptStatus = aAcceptStatus;
mMethodName = aMethodName;
@ -245,49 +248,42 @@ PaymentShowActionResponse::Init(const nsAString& aRequestId,
MOZ_ASSERT(service);
bool isBasicCardPayment = service->IsBasicCardPayment(mMethodName);
uint32_t responseType;
NS_ENSURE_SUCCESS(aData->GetType(&responseType), NS_ERROR_FAILURE);
switch (responseType) {
case nsIPaymentResponseData::GENERAL_RESPONSE: {
if (isBasicCardPayment) {
if (aAcceptStatus == nsIPaymentActionResponse::PAYMENT_ACCEPTED) {
uint32_t responseType;
NS_ENSURE_SUCCESS(aData->GetType(&responseType), NS_ERROR_FAILURE);
switch (responseType) {
case nsIPaymentResponseData::GENERAL_RESPONSE: {
if (isBasicCardPayment) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIGeneralResponseData> data = do_QueryInterface(aData);
MOZ_ASSERT(data);
NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE);
break;
}
case nsIPaymentResponseData::BASICCARD_RESPONSE: {
if (!isBasicCardPayment) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIBasicCardResponseData> data = do_QueryInterface(aData);
MOZ_ASSERT(data);
NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE);
break;
}
default: {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIGeneralResponseData> data = do_QueryInterface(aData);
MOZ_ASSERT(data);
NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE);
break;
}
case nsIPaymentResponseData::BASICCARD_RESPONSE: {
if (!isBasicCardPayment) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIBasicCardResponseData> data = do_QueryInterface(aData);
MOZ_ASSERT(data);
NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE);
break;
}
default: {
if (mData.IsEmpty()) {
return NS_ERROR_FAILURE;
}
}
if (mData.IsEmpty()) {
return NS_ERROR_FAILURE;
}
mPayerName = aPayerName;
mPayerEmail = aPayerEmail;
mPayerPhone = aPayerPhone;
return NS_OK;
}
NS_IMETHODIMP
PaymentShowActionResponse::IsAccepted(bool* aIsAccepted)
{
NS_ENSURE_ARG_POINTER(aIsAccepted);
*aIsAccepted = (mAcceptStatus == nsIPaymentActionResponse::PAYMENT_ACCEPTED);
return NS_OK;
}
/* PaymentAbortActionResponse */
NS_IMPL_ISUPPORTS_INHERITED(PaymentAbortActionResponse,

View File

@ -430,8 +430,7 @@ PaymentRequest::RejectShowPayment(nsresult aRejectReason)
}
void
PaymentRequest::RespondShowPayment(bool aAccept,
const nsAString& aMethodName,
PaymentRequest::RespondShowPayment(const nsAString& aMethodName,
const nsAString& aDetails,
const nsAString& aPayerName,
const nsAString& aPayerEmail,
@ -442,7 +441,7 @@ PaymentRequest::RespondShowPayment(bool aAccept,
MOZ_ASSERT(ReadyForUpdate());
MOZ_ASSERT(mState == eInteractive);
if (!aAccept) {
if (NS_FAILED(aRv)) {
RejectShowPayment(aRv);
return;
}
@ -514,7 +513,7 @@ PaymentRequest::RespondAbortPayment(bool aSuccess)
// - Otherwise, we are handling |Abort| method call from merchant.
// => Resolve/Reject |mAbortPromise| based on |aSuccess|.
if (NS_FAILED(mUpdateError)) {
RespondShowPayment(false, EmptyString(), EmptyString(), EmptyString(),
RespondShowPayment(EmptyString(), EmptyString(), EmptyString(),
EmptyString(), EmptyString(), mUpdateError);
mUpdateError = NS_OK;
return;

View File

@ -71,13 +71,12 @@ public:
void RespondCanMakePayment(bool aResult);
already_AddRefed<Promise> Show(ErrorResult& aRv);
void RespondShowPayment(bool aAccept,
const nsAString& aMethodName,
void RespondShowPayment(const nsAString& aMethodName,
const nsAString& aDetails,
const nsAString& aPayerName,
const nsAString& aPayerEmail,
const nsAString& aPayerPhone,
nsresult aRv = NS_ERROR_DOM_ABORT_ERR);
nsresult aRv);
void RejectShowPayment(nsresult aRejectReason);
void RespondComplete();

View File

@ -594,13 +594,32 @@ PaymentRequestManager::RespondPayment(const IPCPaymentActionResponse& aResponse)
if (NS_WARN_IF(!request)) {
return NS_ERROR_FAILURE;
}
request->RespondShowPayment(response.isAccepted(),
response.methodName(),
nsresult rejectedReason = NS_ERROR_DOM_ABORT_ERR;
switch (response.status()) {
case nsIPaymentActionResponse::PAYMENT_ACCEPTED: {
rejectedReason = NS_OK;
break;
}
case nsIPaymentActionResponse::PAYMENT_REJECTED: {
rejectedReason = NS_ERROR_DOM_ABORT_ERR;
break;
}
case nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED: {
rejectedReason = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
break;
}
default: {
rejectedReason = NS_ERROR_UNEXPECTED;
break;
}
}
request->RespondShowPayment(response.methodName(),
response.data(),
response.payerName(),
response.payerEmail(),
response.payerPhone());
if (!response.isAccepted()) {
response.payerPhone(),
rejectedReason);
if (NS_FAILED(rejectedReason)) {
MOZ_ASSERT(mShowingRequest == request);
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);

View File

@ -262,15 +262,11 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
}
break;
}
/*
* TODO: 1. Check third party payment app support by traversing all
* registered third party payment apps.
*/
case nsIPaymentActionRequest::CANMAKE_ACTION: {
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(canMakeResponse);
if (IsBasicCardPayment(requestId)) {
if (CanMakePayment(requestId)) {
rv = canMakeResponse->Init(requestId, true);
} else {
rv = canMakeResponse->Init(requestId, false);
@ -287,17 +283,20 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
break;
}
case nsIPaymentActionRequest::SHOW_ACTION: {
if (mShowingRequest) {
nsCOMPtr<nsIPaymentResponseData> responseData =
do_CreateInstance(NS_GENERAL_RESPONSE_DATA_CONTRACT_ID);
MOZ_ASSERT(responseData);
if (mShowingRequest || !CanMakePayment(requestId)) {
uint32_t responseStatus;
if (mShowingRequest) {
responseStatus = nsIPaymentActionResponse::PAYMENT_REJECTED;
} else {
responseStatus = nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED;
}
nsCOMPtr<nsIPaymentShowActionResponse> showResponse =
do_CreateInstance(NS_PAYMENT_SHOW_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(showResponse);
rv = showResponse->Init(requestId,
nsIPaymentActionResponse::PAYMENT_REJECTED,
responseStatus,
EmptyString(),
responseData,
nullptr,
EmptyString(),
EmptyString(),
EmptyString());
@ -408,10 +407,10 @@ PaymentRequestService::RespondPayment(nsIPaymentActionResponse* aResponse)
nsCOMPtr<nsIPaymentShowActionResponse> response =
do_QueryInterface(aResponse);
MOZ_ASSERT(response);
bool isAccepted;
rv = response->IsAccepted(&isAccepted);
uint32_t acceptStatus;
rv = response->GetAcceptStatus(&acceptStatus);
NS_ENSURE_SUCCESS(rv, rv);
if (!isAccepted) {
if (acceptStatus != nsIPaymentActionResponse::PAYMENT_ACCEPTED) {
mShowingRequest = nullptr;
mRequestQueue.RemoveElement(request);
}
@ -492,6 +491,16 @@ PaymentRequestService::RemoveActionCallback(const nsAString& aRequestId)
return NS_OK;
}
bool
PaymentRequestService::CanMakePayment(const nsAString& aRequestId)
{
/*
* TODO: Check third party payment app support by traversing all
* registered third party payment apps.
*/
return IsBasicCardPayment(aRequestId);
}
bool
PaymentRequestService::IsBasicCardPayment(const nsAString& aRequestId)
{

View File

@ -46,6 +46,9 @@ private:
nsresult
LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType);
bool
CanMakePayment(const nsAString& aRequestId);
bool
IsBasicCardPayment(const nsAString& aRequestId);

View File

@ -123,7 +123,7 @@ struct IPCPaymentCanMakeActionResponse
struct IPCPaymentShowActionResponse
{
nsString requestId;
bool isAccepted;
uint32_t status;
nsString methodName;
nsString data;
nsString payerName;

View File

@ -202,8 +202,8 @@ PaymentRequestParent::RespondPayment(nsIPaymentActionResponse* aResponse)
nsCOMPtr<nsIPaymentShowActionResponse> response =
do_QueryInterface(aResponse);
MOZ_ASSERT(response);
bool isAccepted;
NS_ENSURE_SUCCESS(response->IsAccepted(&isAccepted), NS_ERROR_FAILURE);
uint32_t acceptStatus;
NS_ENSURE_SUCCESS(response->GetAcceptStatus(&acceptStatus), NS_ERROR_FAILURE);
nsAutoString methodName;
NS_ENSURE_SUCCESS(response->GetMethodName(methodName), NS_ERROR_FAILURE);
nsAutoString data;
@ -215,7 +215,7 @@ PaymentRequestParent::RespondPayment(nsIPaymentActionResponse* aResponse)
nsAutoString payerPhone;
NS_ENSURE_SUCCESS(response->GetPayerPhone(payerPhone), NS_ERROR_FAILURE);
IPCPaymentShowActionResponse actionResponse(requestId,
isAccepted,
acceptStatus,
methodName,
data,
payerName,