diff --git a/dom/interfaces/payments/nsIPaymentRequest.idl b/dom/interfaces/payments/nsIPaymentRequest.idl index af48daedf58d..4f7cd9175296 100644 --- a/dom/interfaces/payments/nsIPaymentRequest.idl +++ b/dom/interfaces/payments/nsIPaymentRequest.idl @@ -81,9 +81,11 @@ interface nsIPaymentRequest : nsISupports readonly attribute uint64_t tabId; readonly attribute nsIPrincipal topLevelPrincipal; readonly attribute AString requestId; + readonly attribute AString completeStatus; readonly attribute nsIArray paymentMethods; readonly attribute nsIPaymentDetails paymentDetails; readonly attribute nsIPaymentOptions paymentOptions; + [noscript] void setCompleteStatus(in AString aCompleteStatus); void updatePaymentDetails(in nsIPaymentDetails aDetails); }; diff --git a/dom/payments/PaymentRequestData.cpp b/dom/payments/PaymentRequestData.cpp index 59893d0a1865..13501a72cdc2 100644 --- a/dom/payments/PaymentRequestData.cpp +++ b/dom/payments/PaymentRequestData.cpp @@ -681,6 +681,20 @@ PaymentRequest::UpdatePaymentDetails(nsIPaymentDetails* aPaymentDetails) return mPaymentDetails->Update(aPaymentDetails); } +NS_IMETHODIMP +PaymentRequest::SetCompleteStatus(const nsAString& aCompleteStatus) +{ + mCompleteStatus = aCompleteStatus; + return NS_OK; +} + +NS_IMETHODIMP +PaymentRequest::GetCompleteStatus(nsAString& aCompleteStatus) +{ + aCompleteStatus = mCompleteStatus; + return NS_OK; +} + /* PaymentAddress */ NS_IMPL_ISUPPORTS(PaymentAddress, nsIPaymentAddress) diff --git a/dom/payments/PaymentRequestData.h b/dom/payments/PaymentRequestData.h index 5eb5298f2796..08237aef5d4b 100644 --- a/dom/payments/PaymentRequestData.h +++ b/dom/payments/PaymentRequestData.h @@ -191,6 +191,7 @@ private: uint64_t mTabId; nsString mRequestId; + nsString mCompleteStatus; nsCOMPtr mTopLevelPrincipal; nsCOMPtr mPaymentMethods; nsCOMPtr mPaymentDetails; diff --git a/dom/payments/PaymentRequestService.cpp b/dom/payments/PaymentRequestService.cpp index c7ae0b3ade98..e9b69d46a972 100644 --- a/dom/payments/PaymentRequestService.cpp +++ b/dom/payments/PaymentRequestService.cpp @@ -318,8 +318,31 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest) } break; } - case nsIPaymentActionRequest::ABORT_ACTION: + case nsIPaymentActionRequest::ABORT_ACTION: { + rv = LaunchUIAction(requestId, type); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } + break; + } case nsIPaymentActionRequest::COMPLETE_ACTION: { + nsCOMPtr request = + do_QueryInterface(aRequest); + MOZ_ASSERT(request); + nsAutoString completeStatus; + rv = request->GetCompleteStatus(completeStatus); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } + nsCOMPtr payment; + rv = GetPaymentRequestById(requestId, getter_AddRefs(payment)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } + rv = payment->SetCompleteStatus(completeStatus); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } rv = LaunchUIAction(requestId, type); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_FAILURE; diff --git a/dom/payments/test/ShowPaymentChromeScript.js b/dom/payments/test/ShowPaymentChromeScript.js index cb533acf7065..89f36065acd4 100644 --- a/dom/payments/test/ShowPaymentChromeScript.js +++ b/dom/payments/test/ShowPaymentChromeScript.js @@ -6,10 +6,14 @@ const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService); +let expectedCompleteStatus; function emitTestFail(message) { sendAsyncMessage("test-fail", message); } +function emitTestPass(message) { + sendAsyncMessage("test-pass", message); +} const shippingAddress = Cc["@mozilla.org/dom/payments/payment-address;1"]. createInstance(Ci.nsIPaymentAddress); @@ -29,6 +33,47 @@ shippingAddress.init("USA", // country "Bill A. Pacheco", // recipient "+1-434-441-3879"); // phone +const DummyUIService = { + showPayment: function(requestId) { + const showResponseData = Cc["@mozilla.org/dom/payments/general-response-data;1"]. + createInstance(Ci.nsIGeneralResponseData); + try { + showResponseData.initData({ paymentToken: "6880281f-0df3-4b8e-916f-66575e2457c1",}); + } catch (e) { + emitTestFail("Fail to initialize response data with { paymentToken: \"6880281f-0df3-4b8e-916f-66575e2457c1\",}"); + } + let 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 + "Bill A. Pacheco", // payer name + "", // payer email + ""); // payer phone + paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse)); + }, + abortPayment: function(requestId) { + }, + completePayment: function(requestId) { + let payRequest = paymentSrv.getPaymentRequestById(requestId); + if (payRequest.completeStatus == expectedCompleteStatus) { + emitTestPass("request.completeStatus matches expectation of " + expectedCompleteStatus); + } else { + emitTestFail("request.completeStatus incorrect. Expected " + + expectedCompleteStatus + ", got " + payRequest.completeStatus); + } + + let 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)); + }, + updatePayment: function(requestId) { + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), +}; + const NormalUIService = { shippingOptionChanged: false, showPayment: function(requestId) { @@ -37,6 +82,14 @@ const NormalUIService = { abortPayment: function(requestId) { }, completePayment: function(requestId) { + let payRequest = paymentSrv.getPaymentRequestById(requestId); + if (payRequest.completeStatus == expectedCompleteStatus) { + emitTestPass("request.completeStatus matches expectation of " + expectedCompleteStatus); + } else { + emitTestFail("request.completeStatus incorrect. Expected " + + expectedCompleteStatus + ", got " + payRequest.completeStatus); + } + let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]. createInstance(Ci.nsIPaymentCompleteActionResponse); completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED); @@ -208,6 +261,10 @@ function testInitDataAndResponse() { sendAsyncMessage("test-init-data-and-response-complete"); } +addMessageListener("set-dummy-ui-service", function() { + paymentSrv.setTestingUIService(DummyUIService.QueryInterface(Ci.nsIPaymentUIService)); +}); + addMessageListener("set-normal-ui-service", function() { paymentSrv.setTestingUIService(NormalUIService.QueryInterface(Ci.nsIPaymentUIService)); }); @@ -222,6 +279,17 @@ addMessageListener("set-update-with-error-ui-service", function() { addMessageListener("test-init-data-and-response", testInitDataAndResponse); +addMessageListener("set-complete-status-success", function() { + expectedCompleteStatus = "success"; +}); + +addMessageListener("set-complete-status-fail", function() { + expectedCompleteStatus = "fail"; +}); + +addMessageListener("set-complete-status-unknown", function() { + expectedCompleteStatus = "unknown"; +}); addMessageListener("teardown", function() { paymentSrv.cleanup(); diff --git a/dom/payments/test/test_showPayment.html b/dom/payments/test/test_showPayment.html index 687ddeee5883..8e248fd25dcf 100644 --- a/dom/payments/test/test_showPayment.html +++ b/dom/payments/test/test_showPayment.html @@ -19,7 +19,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345366 function testFailHandler(message) { ok(false, message); } + function testPassHandler(message) { + ok(true, message); + } gScript.addMessageListener("test-fail", testFailHandler); + gScript.addMessageListener("test-pass", testPassHandler); const defaultMethods = [{ supportedMethods: "basic-card", @@ -155,8 +159,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345366 }); } - function testShow() { + function testShowWithSuccess() { + info("starting testShowWithSuccess"); gScript.sendAsyncMessage("set-normal-ui-service"); + gScript.sendAsyncMessage("set-complete-status-success"); return new Promise((resolve, reject) => { const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions); payRequest.addEventListener("shippingaddresschange", event => { @@ -218,6 +224,66 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345366 }); } + function testShowWithFail() { + info("starting testShowWithFail"); + gScript.sendAsyncMessage("set-dummy-ui-service"); + gScript.sendAsyncMessage("set-complete-status-fail"); + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions); + payRequest.show().then(response => { + response.complete("fail").then(() => { + resolve(); + }).catch(e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }).catch( e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }); + } + + function testShowWithUnknown() { + info("starting testShowWithUnknown"); + gScript.sendAsyncMessage("set-dummy-ui-service"); + gScript.sendAsyncMessage("set-complete-status-unknown"); + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions); + payRequest.show().then(response => { + response.complete("unknown").then(() => { + resolve(); + }).catch(e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }).catch( e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }); + } + + function testShowWithEmpty() { + info("starting testShowWithEmpty"); + gScript.sendAsyncMessage("set-dummy-ui-service"); + gScript.sendAsyncMessage("set-complete-status-unknown"); + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(defaultMethods, defaultDetails, defaultOptions); + payRequest.show().then(response => { + response.complete().then(() => { + resolve(); + }).catch(e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }).catch( e => { + ok(false, "Unexpected error: " + e.name); + resolve(); + }); + }); + } + function testCannotMakePaymentShow() { return new Promise((resolve, reject) => { const payRequest = new PaymentRequest(nonSupportedMethods, defaultDetails); @@ -289,7 +355,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345366 function teardown() { gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() { gScript.removeMessageListener("teardown-complete", teardownCompleteHandler); - gScript.removeMessageListener("test-fail", testFailHandler) + gScript.removeMessageListener("test-fail", testFailHandler); + gScript.removeMessageListener("test-pass", testPassHandler); gScript.destroy(); SimpleTest.finish(); }); @@ -299,7 +366,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345366 function runTests() { testCannotMakePaymentShow() .then(testRejectShow) - .then(testShow) + .then(testShowWithSuccess) + .then(testShowWithFail) + .then(testShowWithUnknown) + .then(testShowWithEmpty) .then(testUpdateWithError) .then(testNullDetailsResponse) .then(teardown)