| // META: script=/common/get-host-info.sub.js |
| // META: script=/common/utils.js |
| // META: script=/pending-beacon/resources/pending_beacon-helper.js |
| |
| 'use strict'; |
| |
| const kQuotaPerOrigin = 64 * 1024; // 64 kilobytes per spec. |
| const {ORIGIN, HTTPS_NOTSAMESITE_ORIGIN} = get_host_info(); |
| |
| // Runs a test case that cover a single fetchLater() call with `body` in its |
| // request payload. The call is not expected to throw any errors. |
| function fetchLaterPostTest(body, description) { |
| test(() => { |
| const controller = new AbortController(); |
| const result = fetchLater( |
| '/fetch-later', |
| {method: 'POST', signal: controller.signal, body: body}); |
| assert_false(result.activated); |
| // Release quota taken by the pending request for subsequent tests. |
| controller.abort(); |
| }, description); |
| } |
| |
| // Test small payload for each supported data types. |
| for (const [dataType, skipCharset] of Object.entries( |
| BeaconDataTypeToSkipCharset)) { |
| fetchLaterPostTest( |
| makeBeaconData(generateSequentialData(0, 1024, skipCharset), dataType), |
| `A fetchLater() call accept small data in POST request of ${dataType}.`); |
| } |
| |
| // Test various size of payloads for the same origin. |
| for (const dataType in BeaconDataType) { |
| if (dataType !== BeaconDataType.FormData && |
| dataType !== BeaconDataType.URLSearchParams) { |
| // Skips FormData & URLSearchParams, as browser adds extra bytes to them |
| // in addition to the user-provided content. It is difficult to test a |
| // request right at the quota limit. |
| fetchLaterPostTest( |
| // Generates data that is exactly 64 kilobytes. |
| makeBeaconData(generatePayload(kQuotaPerOrigin), dataType), |
| `A single fetchLater() call takes up the per-origin quota for its ` + |
| `body of ${dataType}.`); |
| } |
| } |
| |
| // Test empty payload. |
| for (const dataType in BeaconDataType) { |
| test( |
| () => { |
| assert_throws_js( |
| TypeError, () => fetchLater('/', {method: 'POST', body: ''})); |
| }, |
| `A single fetchLater() call does not accept empty data in POST request ` + |
| `of ${dataType}.`); |
| } |
| |
| // Test oversized payload. |
| for (const dataType in BeaconDataType) { |
| test( |
| () => { |
| assert_throws_dom( |
| 'QuotaExceededError', |
| () => fetchLater('/fetch-later', { |
| method: 'POST', |
| // Generates data that exceeds 64 kilobytes. |
| body: |
| makeBeaconData(generatePayload(kQuotaPerOrigin + 1), dataType) |
| })); |
| }, |
| `A single fetchLater() call is not allowed to exceed per-origin quota ` + |
| `for its body of ${dataType}.`); |
| } |
| |
| // Test accumulated oversized request. |
| for (const dataType in BeaconDataType) { |
| test( |
| () => { |
| const controller = new AbortController(); |
| // Makes the 1st call that sends only half of allowed quota. |
| fetchLater('/fetch-later', { |
| method: 'POST', |
| signal: controller.signal, |
| body: makeBeaconData(generatePayload(kQuotaPerOrigin / 2), dataType) |
| }); |
| |
| // Makes the 2nd call that sends half+1 of allowed quota. |
| assert_throws_dom('QuotaExceededError', () => { |
| fetchLater('/fetch-later', { |
| method: 'POST', |
| signal: controller.signal, |
| body: makeBeaconData( |
| generatePayload(kQuotaPerOrigin / 2 + 1), dataType) |
| }); |
| }); |
| // Release quota taken by the pending requests for subsequent tests. |
| controller.abort(); |
| }, |
| `The 2nd fetchLater() call is not allowed to exceed per-origin quota ` + |
| `for its body of ${dataType}.`); |
| } |
| |
| // Test various size of payloads across different origins. |
| for (const dataType in BeaconDataType) { |
| test( |
| () => { |
| const controller = new AbortController(); |
| // Makes the 1st call that sends only half of allowed quota. |
| fetchLater('/fetch-later', { |
| method: 'POST', |
| signal: controller.signal, |
| body: makeBeaconData(generatePayload(kQuotaPerOrigin / 2), dataType) |
| }); |
| |
| // Makes the 2nd call that sends half+1 of allowed quota, but to a |
| // different origin. |
| fetchLater(`${HTTPS_NOTSAMESITE_ORIGIN}/fetch-later`, { |
| method: 'POST', |
| signal: controller.signal, |
| body: |
| makeBeaconData(generatePayload(kQuotaPerOrigin / 2 + 1), dataType) |
| }); |
| // Release quota taken by the pending requests for subsequent tests. |
| controller.abort(); |
| }, |
| `The 2nd fetchLater() call to another origin does not exceed per-origin` + |
| ` quota for its body of ${dataType}.`); |
| } |