tor-browser

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

crashReport-test.html (7167B)


      1 <!DOCTYPE html>
      2 <meta charset=utf-8>
      3 <title>CrashReportStorage API</title>
      4 <link rel="author" title="Dominic Farolino" href="mailto:dom@chromium.org">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <body>
      8 <script>
      9 'use strict';
     10 
     11 // These tests verify the throwing and promise rejection behavior of the
     12 // crashReport API. Each test is run in an iframe to ensure a fresh state.
     13 
     14 promise_test(async t => {
     15  const iframe = document.createElement('iframe');
     16  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     17  document.body.appendChild(iframe);
     18  await loadPromise;
     19 
     20  const child_window = iframe.contentWindow;
     21  // Detach the document.
     22  iframe.remove();
     23  assert_equals(child_window.crashReport, null, "getter returns null");
     24 }, 'crashReport getter returns null in detached Documents');
     25 
     26 promise_test(async t => {
     27  const iframe = document.createElement('iframe');
     28  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     29  document.body.appendChild(iframe);
     30  await loadPromise;
     31 
     32  // Cache the iframe's `crashReport` and other important things for the
     33  // following assertions.
     34  const child_window = iframe.contentWindow;
     35  const cachedCrashReport = child_window.crashReport;
     36  const cachedDOMExceptionConstructor = child_window.DOMException;
     37 
     38  iframe.remove();
     39  const createRejection = cachedCrashReport.initialize(256);
     40  try {
     41    await createRejection;
     42    assert_unreached('createRejection must reject');
     43  } catch (e) {
     44    // Note that we should be using `promise_rejects_dom` here, but this does
     45    // not reliably work with detached Windows/event loops, so we have to run
     46    // some manual assertions here.
     47    assert_true(e instanceof cachedDOMExceptionConstructor,
     48        "promise rejects with DOMException");
     49    assert_equals(e.code, cachedDOMExceptionConstructor.INVALID_STATE_ERR,
     50        "promise rejects with InvalidStateError specifically");
     51  }
     52 }, 'crashReport initialize() throws InvalidStateError in detached Documents');
     53 
     54 promise_test(async t => {
     55  const iframe = document.createElement('iframe');
     56  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     57  document.body.appendChild(iframe);
     58  await loadPromise;
     59 
     60  const child_window = iframe.contentWindow;
     61  const cachedCrashReport = child_window.crashReport;
     62  await cachedCrashReport.initialize(256);
     63  assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
     64    // Detach the document.
     65    iframe.remove();
     66    cachedCrashReport.set('key', 'value');
     67  });
     68 }, 'crashReport.set() throws InvalidStateError in detached Documents');
     69 
     70 promise_test(async t => {
     71  const iframe = document.createElement('iframe');
     72  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     73  document.body.appendChild(iframe);
     74  await loadPromise;
     75 
     76  const child_window = iframe.contentWindow;
     77  const cachedCrashReport = child_window.crashReport;
     78  await cachedCrashReport.initialize(256);
     79  cachedCrashReport.set('key', 'value');
     80 
     81  assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
     82    // Detach the document.
     83    iframe.remove();
     84    cachedCrashReport.remove('key', 'value');
     85  });
     86 }, 'crashReport.remove() throws InvalidStateError in detached Documents');
     87 
     88 promise_test(async t => {
     89  const iframe = document.createElement('iframe');
     90  const loadPromise = new Promise(resolve => iframe.onload = resolve);
     91  document.body.appendChild(iframe);
     92  t.add_cleanup(() => iframe.remove());
     93  await loadPromise;
     94 
     95  const child_window = iframe.contentWindow;
     96  // The maximum allowed size is 5MB.
     97  const large_size = 5 * 1024 * 1024 + 1;
     98  await promise_rejects_dom(t, 'NotAllowedError', child_window.DOMException,
     99      child_window.crashReport.initialize(large_size));
    100 }, 'crashReport.initialize() with size > 5MB rejects with NotAllowedError');
    101 
    102 promise_test(async t => {
    103  const iframe = document.createElement('iframe');
    104  const loadPromise = new Promise(resolve => iframe.onload = resolve);
    105  document.body.appendChild(iframe);
    106  t.add_cleanup(() => iframe.remove());
    107  await loadPromise;
    108 
    109  const child_window = iframe.contentWindow;
    110  child_window.crashReport.initialize(1024);
    111  await promise_rejects_dom(t, 'InvalidStateError', child_window.DOMException,
    112      child_window.crashReport.initialize(1024));
    113 }, 'Calling crashReport.initialize() a second time throws InvalidStateError');
    114 
    115 promise_test(async t => {
    116  const iframe = document.createElement('iframe');
    117  const loadPromise = new Promise(resolve => iframe.onload = resolve);
    118  document.body.appendChild(iframe);
    119  t.add_cleanup(() => iframe.remove());
    120  await loadPromise;
    121 
    122  const child_window = iframe.contentWindow;
    123  child_window.crashReport.initialize(1024);
    124  assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
    125    child_window.crashReport.set('key', 'value');
    126  });
    127 }, 'crashReport.set() throws before initialize() resolves');
    128 
    129 promise_test(async t => {
    130  const iframe = document.createElement('iframe');
    131  const loadPromise = new Promise(resolve => iframe.onload = resolve);
    132  document.body.appendChild(iframe);
    133  t.add_cleanup(() => iframe.remove());
    134  await loadPromise;
    135 
    136  const child_window = iframe.contentWindow;
    137  await child_window.crashReport.initialize(1024);
    138  child_window.crashReport.set('key', 'value');
    139  child_window.crashReport.remove('key');
    140 }, 'crashReport.set() and .remove() succeed after initialize() resolves');
    141 
    142 promise_test(async t => {
    143  const iframe = document.createElement('iframe');
    144  const loadPromise = new Promise(resolve => iframe.onload = resolve);
    145  document.body.appendChild(iframe);
    146  t.add_cleanup(() => iframe.remove());
    147  await loadPromise;
    148 
    149  const child_window = iframe.contentWindow;
    150 
    151  // 8 bytes is too small for the key/value pair "a"/"a" to be written; the
    152  // memory required is 9 bytes, to support the JSONified format:
    153  //
    154  // {"a":"a"}
    155  //
    156  // Similarly, 17 bytes is required for "a"/"a" *and* "b"/"b" to be written, to
    157  // support the format:
    158  //
    159  // {"a":"a","b":"b"}
    160  await child_window.crashReport.initialize(8);
    161  assert_throws_dom('NotAllowedError', child_window.DOMException, () => {
    162    child_window.crashReport.set('a', 'a');
    163  });
    164 
    165  // This just fits in our 8-byte buffer though!
    166  child_window.crashReport.set('b', '');
    167 }, 'crashReport.set() throws when there is not enough memory');
    168 
    169 promise_test(async t => {
    170  const iframe = document.createElement('iframe');
    171  const loadPromise = new Promise(resolve => iframe.onload = resolve);
    172  document.body.appendChild(iframe);
    173  t.add_cleanup(() => iframe.remove());
    174  await loadPromise;
    175 
    176  const child_window = iframe.contentWindow;
    177 
    178  await child_window.crashReport.initialize(9);
    179  child_window.crashReport.set('a', 'a');
    180  assert_throws_dom('NotAllowedError', child_window.DOMException, () => {
    181    child_window.crashReport.set('b', 'b');
    182  });
    183  child_window.crashReport.remove('a');
    184  // Now `set()` will work again.
    185  child_window.crashReport.set('b', 'b');
    186 }, 'crashReport.remove() properly frees memory, and allows you to invoke ' +
    187   'set() again, assigning bytes to memory that was previously full');
    188 </script>
    189 </body>