120 lines
4.7 KiB
JavaScript
120 lines
4.7 KiB
JavaScript
|
|
const kDefaultDictionaryContent = 'This is a test dictionary.\n';
|
|
const kDefaultDictionaryHashBase64 =
|
|
':U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:';
|
|
const kRegisterDictionaryPath = './resources/register-dictionary.py';
|
|
const kCompressedDataPath = './resources/compressed-data.py';
|
|
const kExpectedCompressedData =
|
|
`This is compressed test data using a test dictionary`;
|
|
const kCheckAvailableDictionaryHeaderMaxRetry = 10;
|
|
const kCheckAvailableDictionaryHeaderRetryTimeout = 200;
|
|
const kCheckPreviousRequestHeadersMaxRetry = 5;
|
|
const kCheckPreviousRequestHeadersRetryTimeout = 250;
|
|
|
|
// Gets the remote URL corresponding to `relative_path`.
|
|
function getRemoteHostUrl(relative_path) {
|
|
const remote_origin = new URL(get_host_info().HTTPS_REMOTE_ORIGIN);
|
|
let result = new URL(relative_path, location.href);
|
|
result.protocol = remote_origin.protocol;
|
|
result.hostname = remote_origin.hostname;
|
|
result.port = remote_origin.port;
|
|
return result.href;
|
|
}
|
|
|
|
// Calculates the Structured Field Byte Sequence containing the SHA-256 hash of
|
|
// the contents of the dictionary text.
|
|
async function calculateDictionaryHash(dictionary_text) {
|
|
const encoded = (new TextEncoder()).encode(dictionary_text);
|
|
const digest = await crypto.subtle.digest('SHA-256', encoded)
|
|
return ':' + btoa(String.fromCharCode(...new Uint8Array(digest))) + ':';
|
|
}
|
|
|
|
// Checks the HTTP request headers which is sent to the server.
|
|
async function checkHeaders(check_remote = false) {
|
|
let url = './resources/echo-headers.py';
|
|
if (check_remote) {
|
|
url = getRemoteHostUrl(url);
|
|
}
|
|
return await (await fetch(url)).json();
|
|
}
|
|
|
|
// Checks the "available-dictionary" header in the HTTP request headers.
|
|
async function checkAvailableDictionaryHeader(check_remote = false) {
|
|
return (await checkHeaders(check_remote))['available-dictionary'];
|
|
}
|
|
|
|
// Waits until the "available-dictionary" header is available in the HTTP
|
|
// request headers, and returns the header. If the header is not available after
|
|
// the specified number of retries, returns an error message. If the
|
|
// `expected_header` is specified, this method waits until the header is
|
|
// available and matches the `expected_header`.
|
|
async function waitUntilAvailableDictionaryHeader(test, {
|
|
max_retry = kCheckAvailableDictionaryHeaderMaxRetry,
|
|
expected_header = undefined,
|
|
check_remote = false
|
|
}) {
|
|
for (let retry_count = 0; retry_count <= max_retry; retry_count++) {
|
|
const header = await checkAvailableDictionaryHeader(check_remote);
|
|
if (header) {
|
|
if (expected_header === undefined || header == expected_header) {
|
|
return header;
|
|
}
|
|
}
|
|
await new Promise(
|
|
(resolve) => test.step_timeout(
|
|
resolve, kCheckAvailableDictionaryHeaderRetryTimeout));
|
|
}
|
|
return '"available-dictionary" header is not available';
|
|
}
|
|
|
|
// Checks the HTTP request headers which was sent to the server with `token`
|
|
// to register a dictionary.
|
|
async function checkPreviousRequestHeaders(token, check_remote = false) {
|
|
let url = `./resources/register-dictionary.py?get_previous_header=${token}`;
|
|
if (check_remote) {
|
|
url = getRemoteHostUrl(url);
|
|
}
|
|
return await (await fetch(url)).json();
|
|
}
|
|
|
|
// Waits until the HTTP request headers which was sent to the server with
|
|
// `token` to register a dictionary is available, and returns the header. If the
|
|
// header is not available after the specified number of retries, returns
|
|
// `undefined`.
|
|
async function waitUntilPreviousRequestHeaders(
|
|
test, token, check_remote = false) {
|
|
for (let retry_count = 0; retry_count <= kCheckPreviousRequestHeadersMaxRetry;
|
|
retry_count++) {
|
|
const header =
|
|
(await checkPreviousRequestHeaders(token, check_remote))['headers'];
|
|
if (header) {
|
|
return header;
|
|
}
|
|
await new Promise(
|
|
(resolve) => test.step_timeout(
|
|
resolve, kCheckPreviousRequestHeadersRetryTimeout));
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
// Clears the site data for the specified directive by sending a request to
|
|
// `./resources/clear-site-data.py` which returns `Clear-Site-Data` response
|
|
// header.
|
|
// Note: When `directive` is 'cache' or 'cookies' is specified, registered
|
|
// compression dictionaries should be also cleared.
|
|
async function clearSiteData(directive = 'cache') {
|
|
return await (await fetch(
|
|
`./resources/clear-site-data.py?directive=${directive}`))
|
|
.text();
|
|
}
|
|
|
|
// A utility test method that adds the `clearSiteData()` method to the
|
|
// testharness cleanup function. This is intended to ensure that registered
|
|
// dictionaries are cleared in tests and that registered dictionaries do not
|
|
// interfere with subsequent tests.
|
|
function compression_dictionary_promise_test(func, name, properties) {
|
|
promise_test(async (test) => {
|
|
test.add_cleanup(clearSiteData);
|
|
await func(test);
|
|
}, name, properties);
|
|
}
|