Skip to content

Commit 80d249c

Browse files
marcoscacereskristentr
authored andcommitted
Payment Request: reject with InvalidStateError when document is not fully active
rdar://171593464 https://bugs.webkit.org/show_bug.cgi?id=309027 Reviewed by Abrar Rahman Protyasha and Anne van Kesteren. Uses InvalidStateError for when the API is called from a detached document, and AbortError if script itself destroyed the script execution context/document. Spec change: w3c/payment-request#1056 Upstream WPT commit: web-platform-tests/wpt@05fdf81 Test: imported/w3c/web-platform-tests/payment-request/rejects_if_not_active.https.html * LayoutTests/TestExpectations: * LayoutTests/http/tests/paymentrequest/page-cache-created-payment-response.https-expected.txt: * LayoutTests/http/tests/paymentrequest/page-cache-created-payment-response.https.html: * LayoutTests/http/tests/paymentrequest/page-cache-retried-payment-response.https-expected.txt: * LayoutTests/http/tests/paymentrequest/page-cache-retried-payment-response.https.html: * LayoutTests/http/tests/paymentrequest/payment-response-rejects-if-not-active.https.html: * LayoutTests/http/tests/paymentrequest/rejects_if_not_active.https-expected.txt: * LayoutTests/http/tests/paymentrequest/rejects_if_not_active.https.html: * LayoutTests/imported/w3c/resources/resource-files.json: * LayoutTests/imported/w3c/web-platform-tests/payment-request/rejects_if_not_active.https-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-allowed-by-permissions-policy.https.sub-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-allowed-by-permissions-policy.https.sub.html: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-disabled-by-permissions-policy.https.sub-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-disabled-by-permissions-policy.https.sub.html: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-supported-by-permissions-policy.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/payment-supported-by-permissions-policy.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy-payment-extension.html: Added. * LayoutTests/platform/ios/TestExpectations: * LayoutTests/platform/mac-wk2/TestExpectations: * LayoutTests/platform/mac/TestExpectations: * Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp: (WebCore::PaymentRequest::show): (WebCore::PaymentRequest::canMakePayment): * Source/WebCore/Modules/paymentrequest/PaymentResponse.cpp: (WebCore::PaymentResponse::complete): (WebCore::PaymentResponse::retry): * Source/WebCore/Modules/paymentrequest/PaymentResponse.h: * Source/WebCore/Modules/paymentrequest/PaymentResponse.idl: Canonical link: https://commits.webkit.org/309150@main
1 parent 8245c6a commit 80d249c

26 files changed

+243
-50
lines changed

LayoutTests/TestExpectations

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,8 @@ webkit.org/b/253126 imported/w3c/web-platform-tests/screen-wake-lock/wakelock-en
12691269
webkit.org/b/253126 imported/w3c/web-platform-tests/screen-wake-lock/wakelock-enabled-by-permissions-policy.https.html [ Skip ]
12701270
webkit.org/b/253126 imported/w3c/web-platform-tests/screen-wake-lock/wakelock-enabled-on-self-origin-by-permissions-policy.https.html [ Skip ]
12711271
webkit.org/b/253126 imported/w3c/web-platform-tests/screen-wake-lock/wakelock-supported-by-permissions-policy.html [ Skip ]
1272+
webkit.org/b/253126 imported/w3c/web-platform-tests/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Skip ]
1273+
webkit.org/b/253126 imported/w3c/web-platform-tests/permissions-policy/payment-supported-by-permissions-policy.tentative.html [ Skip ]
12721274

12731275
webkit.org/b/182292 imported/w3c/web-platform-tests/css/cssom-view/scrollingElement-quirks-dynamic-001.html [ ImageOnlyFailure ]
12741276
webkit.org/b/182292 imported/w3c/web-platform-tests/css/cssom-view/scrollingElement-quirks-dynamic-002.html [ ImageOnlyFailure ]

LayoutTests/http/tests/paymentrequest/page-cache-created-payment-response.https-expected.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pagehide - entering cache
99
pageshow - from cache
1010
PASS Page did enter and was restored from the back/forward cache
1111
Testing that PaymentResponse is now in the Closed state.
12-
PASS response.complete() rejected promise with AbortError: The operation was aborted..
13-
PASS response.retry() rejected promise with AbortError: The operation was aborted..
12+
PASS response.complete() rejected promise with InvalidStateError: The payment response object is closed..
13+
PASS response.retry() rejected promise with InvalidStateError: The payment response object is closed..
1414
PASS successfullyParsed is true
1515

1616
TEST COMPLETE

LayoutTests/http/tests/paymentrequest/page-cache-created-payment-response.https.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
testPassed('Page did enter and was restored from the back/forward cache');
1919

2020
debug('Testing that PaymentResponse is now in the Closed state.');
21-
await shouldRejectWithErrorName('response.complete()', 'AbortError');
22-
await shouldRejectWithErrorName('response.retry()', 'AbortError');
21+
await shouldRejectWithErrorName('response.complete()', 'InvalidStateError');
22+
await shouldRejectWithErrorName('response.retry()', 'InvalidStateError');
2323

2424
finishJSTest();
2525
}, false);

LayoutTests/http/tests/paymentrequest/page-cache-retried-payment-response.https-expected.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ PASS Page did enter and was restored from the back/forward cache
1111
Testing that the promise returned by retry() was rejected with "AbortError".
1212
PASS retryPromise rejected promise with AbortError: The operation was aborted..
1313
Testing that PaymentResponse is now in the Closed state.
14-
PASS response.complete() rejected promise with AbortError: The operation was aborted..
15-
PASS response.retry() rejected promise with AbortError: The operation was aborted..
14+
PASS response.complete() rejected promise with InvalidStateError: The payment response object is closed..
15+
PASS response.retry() rejected promise with InvalidStateError: The payment response object is closed..
1616
PASS successfullyParsed is true
1717

1818
TEST COMPLETE

LayoutTests/http/tests/paymentrequest/page-cache-retried-payment-response.https.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
await shouldRejectWithErrorName('retryPromise', 'AbortError');
2222

2323
debug('Testing that PaymentResponse is now in the Closed state.');
24-
await shouldRejectWithErrorName('response.complete()', 'AbortError');
25-
await shouldRejectWithErrorName('response.retry()', 'AbortError');
24+
await shouldRejectWithErrorName('response.complete()', 'InvalidStateError');
25+
await shouldRejectWithErrorName('response.retry()', 'InvalidStateError');
2626

2727
finishJSTest();
2828
}, false);

LayoutTests/http/tests/paymentrequest/payment-response-rejects-if-not-active.https.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@
6666
const promise = response[methodName](...args);
6767
await promise_rejects_dom(
6868
t,
69-
"AbortError",
69+
"InvalidStateError",
7070
iframeDOMException,
7171
promise,
72-
"Inactive document, so must throw AbortError"
72+
"Inactive document, so must throw InvalidStateError"
7373
);
7474
// We are done, so clean up.
7575
iframe.remove();
@@ -105,7 +105,7 @@
105105
"AbortError",
106106
iframeDOMException,
107107
promise,
108-
"Inactive document, so must throw AbortError"
108+
"Document became inactive, so must throw AbortError"
109109
);
110110
// We are done, so clean up.
111111
iframe.remove();

LayoutTests/http/tests/paymentrequest/rejects_if_not_active.https-expected.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
PASS PaymentRequest.show() aborts if the document is not active
33
PASS PaymentRequest.show() aborts if the document is active, but not fully active
44
PASS If a payment request is showing, but its document is navigated away (so no longer fully active), the payment request aborts.
5+
PASS PaymentRequest.canMakePayment() rejects if the document is not active
6+
PASS PaymentRequest.canMakePayment() rejects if the document is active, but not fully active
57

LayoutTests/http/tests/paymentrequest/rejects_if_not_active.https.html

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<!DOCTYPE html>
22
<meta charset=utf-8>
33
<link rel="help" href="https://w3c.github.io/payment-request/#show()-method">
4-
<title>PaymentRequest show() rejects if doc is not fully active</title>
4+
<link rel="help" href="https://w3c.github.io/payment-request/#canmakepayment-method">
5+
<title>PaymentRequest methods reject if doc is not fully active</title>
56
<script src="/js-test-resources/ui-helper.js"></script>
67
<script src="/resources/payment-request.js"></script>
78
<script src="/resources/testharness.js"></script>
@@ -74,10 +75,10 @@
7475
// So, call .show(), and make sure it rejects appropriately.
7576
await promise_rejects_dom(
7677
t,
77-
"AbortError",
78+
"InvalidStateError",
7879
firstCtor,
7980
request1.show(),
80-
"Inactive document, so must throw AbortError"
81+
"Inactive document, so must throw InvalidStateError"
8182
);
8283

8384
// request2 has an active document tho, so confirm it's working as expected:
@@ -141,10 +142,10 @@
141142
// So, call request.show() and make sure it rejects appropriately.
142143
await promise_rejects_dom(
143144
t,
144-
"AbortError",
145+
"InvalidStateError",
145146
requestWindow.DOMException,
146147
request.show(),
147-
"Active, but not fully active, so must throw AbortError"
148+
"Active, but not fully active, so must throw InvalidStateError"
148149
);
149150

150151
// We are done, so clean up.
@@ -183,4 +184,92 @@
183184
// We are done, so clean up.
184185
iframe.remove();
185186
}, "If a payment request is showing, but its document is navigated away (so no longer fully active), the payment request aborts.");
187+
188+
promise_test(async t => {
189+
// Check that PaymentRequests can be constructed.
190+
new PaymentRequest(validMethods, validDetails);
191+
const iframe = document.createElement("iframe");
192+
iframe.allowPaymentRequest = true;
193+
document.body.appendChild(iframe);
194+
195+
// We first go to page1.html, grab a PaymentRequest instance.
196+
const request1 = await getLoadedPaymentRequest(
197+
iframe,
198+
"resources/page1.html"
199+
);
200+
const firstCtor = iframe.contentWindow.DOMException;
201+
202+
// We navigate the iframe again, putting request1's document into an inactive state.
203+
const request2 = await getLoadedPaymentRequest(
204+
iframe,
205+
"resources/page2.html"
206+
);
207+
208+
// Now, request1's relevant global object's document is no longer active.
209+
// So, call .canMakePayment(), and make sure it rejects appropriately.
210+
await promise_rejects_dom(
211+
t,
212+
"InvalidStateError",
213+
firstCtor,
214+
request1.canMakePayment(),
215+
"Inactive document, so must throw InvalidStateError"
216+
);
217+
218+
// request2 has an active document, so confirm it's working as expected:
219+
const result = await request2.canMakePayment();
220+
assert_true(typeof result === "boolean", "canMakePayment() should return a boolean");
221+
222+
// We are done, so clean up.
223+
iframe.remove();
224+
}, "PaymentRequest.canMakePayment() rejects if the document is not active");
225+
226+
promise_test(async t => {
227+
// check that PaymentRequests can be constructed (smoke test).
228+
new PaymentRequest(validMethods, validDetails);
229+
230+
// We nest two iframes and wait for them to load.
231+
const outerIframe = document.createElement("iframe");
232+
outerIframe.allowPaymentRequest = true;
233+
document.body.appendChild(outerIframe);
234+
// Load the outer iframe (we don't care about the awaited request)
235+
await getLoadedPaymentRequest(
236+
outerIframe,
237+
"resources/page1.html"
238+
);
239+
240+
// Now we create the inner iframe
241+
const innerIframe = outerIframe.contentDocument.createElement("iframe");
242+
innerIframe.allowPaymentRequest = true;
243+
244+
// nest them
245+
outerIframe.contentDocument.body.appendChild(innerIframe);
246+
247+
// load innerIframe, and get the PaymentRequest instance
248+
const request = await getLoadedPaymentRequest(
249+
innerIframe,
250+
"resources/page2.html"
251+
);
252+
const requestWindow = innerIframe.contentWindow;
253+
254+
// Navigate the outer iframe to a new location.
255+
// Wait for the load event to fire.
256+
await new Promise(resolve => {
257+
outerIframe.addEventListener("load", resolve);
258+
outerIframe.src = "resources/page2.html";
259+
});
260+
// Now, request's relevant global object's document is still active
261+
// (it is the active document of the inner iframe), but is not fully active
262+
// (since the parent of the inner iframe is itself no longer active).
263+
// So, call request.canMakePayment() and make sure it rejects appropriately.
264+
await promise_rejects_dom(
265+
t,
266+
"InvalidStateError",
267+
requestWindow.DOMException,
268+
request.canMakePayment(),
269+
"Active, but not fully active, so must throw InvalidStateError"
270+
);
271+
272+
// We are done, so clean up.
273+
outerIframe.remove();
274+
}, "PaymentRequest.canMakePayment() rejects if the document is active, but not fully active");
186275
</script>

LayoutTests/imported/w3c/resources/resource-files.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12873,6 +12873,8 @@
1287312873
"web-platform-tests/mimesniff/sniffing/support/rss.html",
1287412874
"web-platform-tests/page-lifecycle/set-composited-layer-position-ref.html",
1287512875
"web-platform-tests/payment-request/show-method-postmessage-iframe.html",
12876+
"web-platform-tests/permissions-policy/resources/permissions-policy-payment-extension.html",
12877+
"web-platform-tests/permissions-policy/resources/permissions-policy-payment.html",
1287612878
"web-platform-tests/permissions/feature-policy-permissions-query.html",
1287712879
"web-platform-tests/quirks/body-fills-html-quirk-ref.html",
1287812880
"web-platform-tests/quirks/body-fills-html-quirk-ref2.html",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

2-
FAIL PaymentRequest.show() aborts if the document is not active. promise_rejects_dom: Inactive document, so must throw InvalidStateError function "function() { throw e; }" threw object "AbortError: The operation was aborted." that is not a DOMException InvalidStateError: property "code" is equal to 20, expected 11
3-
FAIL PaymentRequest.show() aborts if the document is active, but not fully active. promise_rejects_dom: Active, but not fully active, so must throw InvalidStateError function "function() { throw e; }" threw object "AbortError: The operation was aborted." that is not a DOMException InvalidStateError: property "code" is equal to 20, expected 11
2+
PASS PaymentRequest.show() aborts if the document is not active.
3+
PASS PaymentRequest.show() aborts if the document is active, but not fully active.
44
PASS PaymentRequest.canMakePayment() rejects if the document is not active.
55
PASS PaymentRequest.canMakePayment() rejects if the document is active, but not fully active.
66

0 commit comments

Comments
 (0)