tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

close.https.any.js (6863B)


      1 // META: global=window,worker
      2 // META: script=/common/get-host-info.sub.js
      3 // META: script=resources/webtransport-test-helpers.sub.js
      4 // META: script=/common/utils.js
      5 
      6 promise_test(async t => {
      7  const id = token();
      8  const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
      9  add_completion_callback(() => wt.close());
     10  await wt.ready;
     11 
     12  wt.close();
     13 
     14  const close_info = await wt.closed;
     15 
     16  assert_equals(close_info.closeCode, 0, 'code');
     17  assert_equals(close_info.reason, '', 'reason');
     18 
     19  await wait(10);
     20  const data = await query(id);
     21 
     22  assert_own_property(data, 'session-close-info');
     23  const info = data['session-close-info']
     24 
     25  assert_false(info.abruptly, 'abruptly');
     26  assert_equals(info.close_info.code, 0, 'code');
     27  assert_equals(info.close_info.reason, '', 'reason');
     28 }, 'close');
     29 
     30 promise_test(async t => {
     31  const wt = new WebTransport(webtransport_url('echo.py'));
     32  wt.close();
     33  try {
     34    await wt.closed;
     35  } catch(e) {
     36    await promise_rejects_exactly(t, e, wt.ready, 'ready promise should be rejected');
     37    assert_true(e instanceof WebTransportError);
     38    assert_equals(e.source, 'session', 'source');
     39    assert_equals(e.streamErrorCode, null, 'streamErrorCode');
     40  }
     41 }, 'close without waiting for ready');
     42 
     43 promise_test(async t => {
     44  const id = token();
     45  const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
     46  add_completion_callback(() => wt.close());
     47  await wt.ready;
     48 
     49  wt.close({closeCode: 99, reason: 'reason X'});
     50 
     51  const close_info = await wt.closed;
     52 
     53  assert_equals(close_info.closeCode, 99, 'code');
     54  assert_equals(close_info.reason, 'reason X', 'reason');
     55 
     56  await wait(10);
     57  const data = await query(id);
     58 
     59  assert_own_property(data, 'session-close-info');
     60  const info = data['session-close-info']
     61 
     62  assert_false(info.abruptly, 'abruptly');
     63  assert_equals(info.close_info.code, 99, 'code');
     64  assert_equals(info.close_info.reason, 'reason X', 'reason');
     65 }, 'close with code and reason');
     66 
     67 promise_test(async t => {
     68  const id = token();
     69  const wt = new WebTransport(webtransport_url(`client-close.py?token=${id}`));
     70  add_completion_callback(() => wt.close());
     71  await wt.ready;
     72  const reason = 'あいうえお'.repeat(1000);
     73 
     74  wt.close({closeCode: 11, reason});
     75 
     76  const close_info = await wt.closed;
     77 
     78  assert_equals(close_info.closeCode, 11, 'code');
     79  // `close_info.reason` should report the original, non-truncated reason as
     80  // step 9 of https://w3c.github.io/webtransport/#dom-webtransport-close
     81  // uses the original `closeInfo` to perform `Cleanup`.
     82  assert_equals(close_info.reason, reason, 'reason');
     83 
     84  await wait(10);
     85  const data = await query(id);
     86 
     87  assert_own_property(data, 'session-close-info');
     88  const info = data['session-close-info']
     89 
     90  // Server should have received truncated reason as step 6 of
     91  // https://w3c.github.io/webtransport/#dom-webtransport-close specifies.
     92  const expected_reason =
     93    new TextDecoder().decode(
     94      new TextEncoder().encode(reason).slice(0, 1024)).replaceAll('\ufffd', '');
     95  assert_false(info.abruptly, 'abruptly');
     96  assert_equals(info.close_info.code, 11, 'code');
     97  assert_equals(info.close_info.reason, expected_reason, 'reason');
     98 }, 'close with code and long reason');
     99 
    100 promise_test(async t => {
    101  const wt = new WebTransport(webtransport_url('server-close.py'));
    102 
    103  const close_info = await wt.closed;
    104  assert_equals(close_info.closeCode, 0, 'code');
    105  assert_equals(close_info.reason, '', 'reason');
    106 }, 'server initiated closure without code and reason');
    107 
    108 promise_test(async t => {
    109  const code = 32;
    110  const reason = 'abc';
    111  const wt = new WebTransport(
    112    webtransport_url(`server-close.py?code=${code}&reason=${reason}`));
    113  add_completion_callback(() => wt.close());
    114 
    115  const close_info = await wt.closed;
    116  assert_equals(close_info.closeCode, code, 'code');
    117  assert_equals(close_info.reason, reason, 'reason');
    118 }, 'server initiated closure with code and reason');
    119 
    120 promise_test(async t => {
    121  const wt = new WebTransport(webtransport_url('server-connection-close.py'));
    122  add_completion_callback(() => wt.close());
    123 
    124  const streams_reader = wt.incomingBidirectionalStreams.getReader();
    125  const { value: bidi } = await streams_reader.read();
    126  const writer = bidi.writable.getWriter();
    127  const reader = bidi.readable.getReader();
    128  try {
    129    writer.write(new Uint8Array([65]));
    130  } catch (e) {
    131  }
    132 
    133  // Sadly we cannot use promise_rejects_dom as the error constructor is
    134  // WebTransportError rather than DOMException.
    135  // We get a possible error, and then make sure wt.closed is rejected with it.
    136  const e = await wt.closed.catch(e => e);
    137  await promise_rejects_exactly(t, e, wt.closed, 'wt.closed');
    138  await promise_rejects_exactly(t, e, writer.closed, 'writer.closed');
    139  await promise_rejects_exactly(t, e, reader.closed, 'reader.closed');
    140  assert_true(e instanceof WebTransportError);
    141  assert_equals(e.source, 'session', 'source');
    142  assert_equals(e.streamErrorCode, null, 'streamErrorCode');
    143 }, 'server initiated connection closure');
    144 
    145 promise_test(async t => {
    146  const wt = new WebTransport(webtransport_url('echo.py'));
    147  const stream = await wt.createUnidirectionalStream();
    148  await wt.ready;
    149 }, 'opening unidirectional stream before ready');
    150 
    151 promise_test(async t => {
    152  const wt = new WebTransport(webtransport_url('echo.py'));
    153  const stream = await wt.createBidirectionalStream();
    154  await wt.ready;
    155 }, 'opening bidirectional stream before ready');
    156 
    157 promise_test(async t => {
    158  const wt = new WebTransport(webtransport_url('server-close.py'));
    159  await promise_rejects_dom(t, "InvalidStateError",
    160                            wt.createUnidirectionalStream());
    161 }, 'server initiated closure while opening unidirectional stream before ready');
    162 
    163 promise_test(async t => {
    164  const wt = new WebTransport(webtransport_url('server-close.py'));
    165  await promise_rejects_dom(t, "InvalidStateError",
    166                            wt.createBidirectionalStream());
    167 }, 'server initiated closure while opening bidirectional stream before ready');
    168 
    169 // Regression test for https://crbug.com/347710668.
    170 promise_test(async t => {
    171  const wt = new WebTransport(webtransport_url('server-read-then-close.py'));
    172  add_completion_callback(() => wt.close());
    173  await wt.ready;
    174 
    175  const bidi_reader = wt.incomingBidirectionalStreams.getReader();
    176  const { value: bidi } = await bidi_reader.read();
    177 
    178  bidi.writable.getWriter().write(new TextEncoder().encode('some data'));
    179  const reader = bidi.readable.getReader();
    180  await reader.closed.catch(t.step_func(
    181      e => assert_true(e instanceof WebTransportError)));
    182 
    183  // The WebTransport session will already be closed.
    184  const {reason, closeCode} = await wt.closed;
    185 
    186  assert_equals(reason, '', 'reason should be default');
    187  assert_equals(closeCode, 0, 'closeCode should be default');
    188 }, 'reading closed property after close should work');