blob: 7d86f594a802c221077ce471393f6c9fabba7f2e [file] [log] [blame]
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);
}