mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1489968 - Implement BasicCardErrors for PaymentRequest. r=edenchuang,baku
Differential Revision: https://phabricator.services.mozilla.com/D6378 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
495837c33c
commit
ce4c75065c
@ -343,6 +343,19 @@ BasicCardService::DecodeBasicCardData(const nsAString& aData,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
BasicCardService::IsValidBasicCardErrors(JSContext* aCx,
|
||||
JSObject* aData)
|
||||
{
|
||||
if (!aData) {
|
||||
return true;
|
||||
}
|
||||
JS::RootedValue data(aCx, JS::ObjectValue(*aData));
|
||||
|
||||
BasicCardErrors bcError;
|
||||
return !bcError.Init(aCx, data);
|
||||
}
|
||||
|
||||
#ifdef PaymentBasicCardMacros
|
||||
#undef PaymentBasicCardMacros
|
||||
#undef EncodeBasicCardProperty
|
||||
|
@ -24,9 +24,9 @@ public:
|
||||
|
||||
bool IsBasicCardPayment(const nsAString& aSupportedMethods);
|
||||
bool IsValidBasicCardRequest(JSContext* aCx, JSObject* aData, nsAString& aErrorMsg);
|
||||
bool IsValidBasicCardErrors(JSContext* aCx, JSObject* aData);
|
||||
bool IsValidExpiryMonth(const nsAString& aExpiryMonth);
|
||||
bool IsValidExpiryYear(const nsAString& aExpiryYear);
|
||||
|
||||
/*
|
||||
To let BasicCardResponse using the same data type with non-BasicCard response
|
||||
in IPC transferring, following two methods is used to Encode/Decode the raw
|
||||
|
@ -248,6 +248,18 @@ PaymentResponse::Retry(JSContext* aCx,
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Depending on the PMI, try to do IDL type conversion
|
||||
// (e.g., basic-card expects at BasicCardErrors dictionary)
|
||||
nsAutoString errorMsg;
|
||||
rv = ConvertPaymentMethodErrors(aCx, aErrors, errorMsg);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
MOZ_ASSERT(!errorMsg.IsEmpty());
|
||||
ErrorResult error;
|
||||
error.ThrowTypeError<MSG_NOT_DICTIONARY>(errorMsg);
|
||||
promise->MaybeReject(error);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mRequest);
|
||||
rv = mRequest->RetryPayment(aCx, aErrors);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -298,6 +310,27 @@ PaymentResponse::RejectRetry(nsresult aRejectReason)
|
||||
mRetryPromise = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentResponse::ConvertPaymentMethodErrors(
|
||||
JSContext* aCx,
|
||||
const PaymentValidationErrors& aErrors,
|
||||
nsAString& errorMsg) const
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
if (!aErrors.mPaymentMethod.WasPassed()) {
|
||||
return NS_OK;
|
||||
}
|
||||
RefPtr<BasicCardService> service = BasicCardService::GetService();
|
||||
MOZ_ASSERT(service);
|
||||
if (service->IsBasicCardPayment(mMethodName)) {
|
||||
if (service->IsValidBasicCardErrors(aCx, aErrors.mPaymentMethod.Value())) {
|
||||
errorMsg.Assign(NS_LITERAL_STRING("paymentMethod"));
|
||||
return NS_ERROR_TYPE_ERR;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PaymentResponse::ValidatePaymentValidationErrors(
|
||||
const PaymentValidationErrors& aErrors)
|
||||
|
@ -89,7 +89,12 @@ public:
|
||||
protected:
|
||||
~PaymentResponse();
|
||||
|
||||
nsresult ValidatePaymentValidationErrors(const PaymentValidationErrors& aErrors);
|
||||
nsresult ValidatePaymentValidationErrors(
|
||||
const PaymentValidationErrors& aErrors);
|
||||
|
||||
nsresult ConvertPaymentMethodErrors(JSContext* aCx,
|
||||
const PaymentValidationErrors& aErrors,
|
||||
nsAString& aErrorMsg) const;
|
||||
|
||||
nsresult DispatchUpdateEvent(const nsAString& aType);
|
||||
|
||||
|
129
dom/payments/test/BasicCardErrorsChromeScript.js
Normal file
129
dom/payments/test/BasicCardErrorsChromeScript.js
Normal file
@ -0,0 +1,129 @@
|
||||
/* -*- 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 defaultCard = {
|
||||
cardholderName: "",
|
||||
cardNumber: "4111111111111111",
|
||||
expiryMonth: "",
|
||||
expiryYear: "",
|
||||
cardSecurityCode: "",
|
||||
billingAddress: null,
|
||||
};
|
||||
|
||||
function makeBillingAddress() {
|
||||
const billingAddress = Cc[
|
||||
"@mozilla.org/dom/payments/payment-address;1"
|
||||
].createInstance(Ci.nsIPaymentAddress);
|
||||
const addressLine = Cc["@mozilla.org/array;1"].createInstance(
|
||||
Ci.nsIMutableArray
|
||||
);
|
||||
const address = Cc["@mozilla.org/supports-string;1"].createInstance(
|
||||
Ci.nsISupportsString
|
||||
);
|
||||
address.data = "Easton Ave";
|
||||
addressLine.appendElement(address);
|
||||
const addressArgs = [
|
||||
"USA", // country
|
||||
addressLine, // address line
|
||||
"CA", // region
|
||||
"San Bruno", // city
|
||||
"", // dependent locality
|
||||
"94066", // postal code
|
||||
"123456", // sorting code
|
||||
"", // organization
|
||||
"Bill A. Pacheco", // recipient
|
||||
"+14344413879", // phone
|
||||
];
|
||||
billingAddress.init(...addressArgs);
|
||||
return billingAddress;
|
||||
}
|
||||
|
||||
function makeBasicCardResponse(details) {
|
||||
const basicCardResponseData = Cc[
|
||||
"@mozilla.org/dom/payments/basiccard-response-data;1"
|
||||
].createInstance(Ci.nsIBasicCardResponseData);
|
||||
const {
|
||||
cardholderName,
|
||||
cardNumber,
|
||||
expiryMonth,
|
||||
expiryYear,
|
||||
cardSecurityCode,
|
||||
billingAddress,
|
||||
} = details;
|
||||
|
||||
const address =
|
||||
billingAddress !== undefined ? billingAddress : makeBillingAddress();
|
||||
|
||||
basicCardResponseData.initData(
|
||||
cardholderName,
|
||||
cardNumber,
|
||||
expiryMonth,
|
||||
expiryYear,
|
||||
cardSecurityCode,
|
||||
address
|
||||
);
|
||||
|
||||
return basicCardResponseData;
|
||||
}
|
||||
|
||||
const TestingUIService = {
|
||||
showPayment(requestId, details = { ...defaultCard }) {
|
||||
const showResponse = Cc[
|
||||
"@mozilla.org/dom/payments/payment-show-action-response;1"
|
||||
].createInstance(Ci.nsIPaymentShowActionResponse);
|
||||
|
||||
showResponse.init(
|
||||
requestId,
|
||||
Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
|
||||
"basic-card", // payment method
|
||||
makeBasicCardResponse(details),
|
||||
"Person name",
|
||||
"Person email",
|
||||
"Person phone"
|
||||
);
|
||||
|
||||
paymentSrv.respondPayment(
|
||||
showResponse.QueryInterface(Ci.nsIPaymentActionResponse)
|
||||
);
|
||||
},
|
||||
// Handles response.retry({ paymentMethod }):
|
||||
updatePayment(requestId) {
|
||||
// Let's echo what was sent in by the error...
|
||||
const request = paymentSrv.getPaymentRequestById(requestId);
|
||||
this.showPayment(requestId, request.paymentDetails.paymentMethod);
|
||||
},
|
||||
// Handles response.complete()
|
||||
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");
|
||||
});
|
@ -9,6 +9,7 @@ support-files =
|
||||
echo_payment_request.html
|
||||
BasiccardChromeScript.js
|
||||
Bug1478740ChromeScript.js
|
||||
BasicCardErrorsChromeScript.js
|
||||
Bug1490698ChromeScript.js
|
||||
ClosePaymentChromeScript.js
|
||||
ConstructorChromeScript.js
|
||||
@ -26,6 +27,7 @@ support-files =
|
||||
[test_abortPayment.html]
|
||||
run-if = nightly_build # Bug 1390018: Depends on the Nightly-only UI service
|
||||
[test_basiccard.html]
|
||||
[test_basiccarderrors.html]
|
||||
[test_block_none10s.html]
|
||||
skip-if = e10s # Bug 1408250: Don't expose PaymentRequest Constructor in non-e10s
|
||||
[test_bug1478740.html]
|
||||
|
85
dom/payments/test/test_basiccarderrors.html
Normal file
85
dom/payments/test/test_basiccarderrors.html
Normal file
@ -0,0 +1,85 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1489968
|
||||
-->
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1489968</title>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="./DefaultData.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const gUrl = SimpleTest.getTestFileURL("BasicCardErrorsChromeScript.js");
|
||||
const gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
|
||||
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 teardown() {
|
||||
await sendTearDown();
|
||||
gScript.destroy();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
async function testBasicCardErrors() {
|
||||
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(
|
||||
true
|
||||
);
|
||||
const request = new PaymentRequest(
|
||||
[{ supportedMethods: "basic-card" }],
|
||||
defaultDetails
|
||||
);
|
||||
const response = await request.show();
|
||||
// Smoke test the initial state
|
||||
is(response.details.cardNumber, "4111111111111111", "Expected cardNumber to initially be 4111111111111111");
|
||||
// We send these up and have the chrome script echo them back to us.
|
||||
const expected = {
|
||||
cardholderName: "PASS",
|
||||
cardNumber: "3566002020360505",
|
||||
cardSecurityCode: "666",
|
||||
expiryMonth: "02",
|
||||
expiryYear: "2020",
|
||||
};
|
||||
await response.retry({ paymentMethod: expected });
|
||||
// the values of the response would have been updated with the expected
|
||||
for (const [member, expectedValue] of Object.entries(expected)) {
|
||||
const actual = response.details[member];
|
||||
is(
|
||||
actual,
|
||||
expectedValue,
|
||||
`Expected member ${member} to be "${expectedValue}, but got "${actual}"`
|
||||
);
|
||||
}
|
||||
await response.complete("success");
|
||||
handler.destruct();
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
try {
|
||||
await testBasicCardErrors();
|
||||
} catch (err) {
|
||||
ok(false, `Unexpected error: ${err} ${err.stack}.`);
|
||||
} finally {
|
||||
await teardown();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const prefs = [["dom.payments.request.enabled", true]];
|
||||
SpecialPowers.pushPrefEnv({ set: prefs }, runTests);
|
||||
});
|
||||
</script>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1489968">Mozilla Bug 1489968</a>
|
@ -25,3 +25,12 @@ dictionary BasicCardResponse {
|
||||
DOMString cardSecurityCode;
|
||||
PaymentAddress? billingAddress;
|
||||
};
|
||||
|
||||
dictionary BasicCardErrors {
|
||||
DOMString cardNumber;
|
||||
DOMString cardholderName;
|
||||
DOMString cardSecurityCode;
|
||||
DOMString expiryMonth;
|
||||
DOMString expiryYear;
|
||||
AddressErrors billingAddress;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user