Bug 1470584 - Send PAYMENT_REJECTED response if window is unexpectedly closed. r=MattN

* Use onWindowClose to spot closing windows associated with live payment requests and send a reject response
* Test to verify expected show() promise rejection behavior when closing the PR dialog

MozReview-Commit-ID: 2TJYN5NMrE6

--HG--
extra : rebase_source : 83cdfbe760f5df7e4786ac277e1ecabd3a4b08d8
This commit is contained in:
Sam Foster 2018-07-16 17:21:51 -07:00
Родитель 55494981b1
Коммит 417a086f25
3 изменённых файлов: 66 добавлений и 0 удалений

Просмотреть файл

@ -32,6 +32,7 @@ function PaymentUIService() {
prefix: "Payment UI Service",
});
});
Services.wm.addListener(this);
this.log.debug("constructor");
}
@ -41,6 +42,19 @@ PaymentUIService.prototype = {
DIALOG_URL: "chrome://payments/content/paymentDialogWrapper.xul",
REQUEST_ID_PREFIX: "paymentRequest-",
// nsIWindowMediatorListener implementation:
onOpenWindow(aWindow) {},
onCloseWindow(aWindow) {
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
let requestId = this.requestIdForWindow(domWindow);
if (!requestId || !paymentSrv.getPaymentRequestById(requestId)) {
return;
}
this.log.debug(`onCloseWindow, close of window for active requestId: ${requestId}`);
this.rejectPaymentForClosedDialog(requestId);
},
// nsIPaymentUIService implementation:
showPayment(requestId) {
@ -67,6 +81,20 @@ PaymentUIService.prototype = {
paymentSrv.respondPayment(abortResponse);
},
rejectPaymentForClosedDialog(requestId) {
this.log.debug("rejectPaymentForClosedDialog:", requestId);
const rejectResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"]
.createInstance(Ci.nsIPaymentShowActionResponse);
rejectResponse.init(requestId,
Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
"", // payment method
null, // payment method data
"", // payer name
"", // payer email
"");// payer phone
paymentSrv.respondPayment(rejectResponse);
},
completePayment(requestId) {
// completeStatus should be one of "timeout", "success", "fail", ""
let {completeStatus} = paymentSrv.getPaymentRequestById(requestId);

Просмотреть файл

@ -91,6 +91,19 @@ var PaymentTestUtils = {
handle.destruct();
},
/**
* Add a rejection handler for the `showPromise` created by createAndShowRequest
* and stash details of any eventual exception or response in `rqResult`
*/
catchShowPromiseRejection: () => {
content.rqResult = {};
content.showPromise.then(res => content.rqResult.response = res)
.catch(ex => content.rqResult.showException = {
name: ex.name,
message: ex.message,
});
},
},
DialogContentTasks: {

Просмотреть файл

@ -137,3 +137,28 @@ add_task(async function test_show_completePayment2() {
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
});
});
add_task(async function test_show_closeReject_dialog() {
await BrowserTestUtils.withNewTab({
gBrowser,
url: BLANK_PAGE_URL,
}, async browser => {
let {win} =
await setupPaymentDialog(browser, {
methodData,
details,
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
}
);
await ContentTask.spawn(browser, null, PTU.ContentTasks.catchShowPromiseRejection);
info("Closing the dialog to reject the payment request");
BrowserTestUtils.closeWindow(win);
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
let result = await ContentTask.spawn(browser, null, async () => content.rqResult);
ok(result.showException, "Expected promise rejection from the rq.show() promise");
ok(!result.response,
"rq.show() shouldn't resolve to a response");
});
});