File: compression-dictionary-util.sub.js

package info (click to toggle)
firefox 147.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,484 kB
  • sloc: cpp: 7,607,246; javascript: 6,533,185; ansic: 3,775,227; python: 1,415,393; xml: 634,561; asm: 438,951; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (145 lines) | stat: -rw-r--r-- 5,698 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
const SAME_ORIGIN = "https://{{host}}:{{ports[https][0]}}";
const CROSS_ORIGIN = "https://{{hosts[alt][www]}}:{{ports[https][0]}}";

const RESOURCES_PATH = "/fetch/compression-dictionary/resources";
const SAME_ORIGIN_RESOURCES_URL = SAME_ORIGIN + RESOURCES_PATH;
const CROSS_ORIGIN_RESOURCES_URL = CROSS_ORIGIN + RESOURCES_PATH;

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 kCheckHeaderMaxRetry = 10;
const kCheckHeaderRetryTimeout = 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, use_alt_path = false}) {
  let url = use_alt_path ? './resources/echo-headers2.py' :
                           './resources/echo-headers.py';
  if (check_remote) {
    url = getRemoteHostUrl(url);
  }
  return await (await fetch(url)).json();
}

// Checks the specified header in the HTTP request headers.
async function checkHeader(header, {
    check_remote = false,
    use_alt_path = false}) {
  return (await checkHeaders({check_remote: check_remote, use_alt_path: use_alt_path}))[header];
}

// Waits until the specified 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 waitUntilHeader(test, header, {
  max_retry = kCheckHeaderMaxRetry,
  expected_header = undefined,
  check_remote = false,
  use_alt_path = false
}) {
  for (let retry_count = 0; retry_count <= max_retry; retry_count++) {
    const response_header = await checkHeader(header, {check_remote: check_remote,
                                                       use_alt_path: use_alt_path});
    if (response_header) {
      if (expected_header === undefined || response_header == expected_header) {
        return response_header;
      }
    }
    await new Promise(
        (resolve) => test.step_timeout(
            resolve, kCheckHeaderRetryTimeout));
  }
  return `"${header}" header is not available`;
}

async function waitUntilAvailableDictionaryHeader(test, {
  max_retry = kCheckHeaderMaxRetry,
  expected_header = undefined,
  check_remote = false,
  use_alt_path = false
}) {
  return waitUntilHeader(test, 'available-dictionary', {
    max_retry: max_retry,
    expected_header: expected_header,
    check_remote: check_remote,
    use_alt_path: use_alt_path
  });
}

// 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);
}