tor-browser

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

update-not-allowed.https.html (5643B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="resources/test-helpers.sub.js"></script>
      5 <script>
      6 'use strict';
      7 
      8 function send_message_to_worker_and_wait_for_response(worker, message) {
      9  return new Promise(resolve => {
     10    // Use a dedicated channel for every request to avoid race conditions on
     11    // concurrent requests.
     12    const channel = new MessageChannel();
     13    worker.postMessage(channel.port1, [channel.port1]);
     14 
     15    let messageReceived = false;
     16    channel.port2.onmessage = event => {
     17      assert_false(messageReceived, 'Already received response for ' + message);
     18      messageReceived = true;
     19      resolve(event.data);
     20    };
     21    channel.port2.postMessage(message);
     22  });
     23 }
     24 
     25 async function ensure_install_event_fired(worker) {
     26  const response = await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
     27  assert_equals('installEventFired', response);
     28  assert_equals('installing', worker.state, 'Expected worker to be installing.');
     29 }
     30 
     31 async function finish_install(worker) {
     32  await ensure_install_event_fired(worker);
     33  const response = await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
     34  assert_equals('installFinished', response);
     35 }
     36 
     37 async function activate_service_worker(t, worker) {
     38  await finish_install(worker);
     39  // By waiting for both states at the same time, the test fails
     40  // quickly if the installation fails, avoiding a timeout.
     41  await Promise.race([wait_for_state(t, worker, 'activated'),
     42                      wait_for_state(t, worker, 'redundant')]);
     43  assert_equals('activated', worker.state, 'Service worker should be activated.');
     44 }
     45 
     46 async function update_within_service_worker(worker) {
     47  // This function returns a Promise that resolves when update()
     48  // has been called but is not necessarily finished yet.
     49  // Call finish() on the returned object to wait for update() settle.
     50  const port = await send_message_to_worker_and_wait_for_response(worker, 'callUpdate');
     51  let messageReceived = false;
     52  return {
     53    finish: () => {
     54      return new Promise(resolve => {
     55        port.onmessage = event => {
     56          assert_false(messageReceived, 'Update already finished.');
     57          messageReceived = true;
     58          resolve(event.data);
     59        };
     60      });
     61    },
     62  };
     63 }
     64 
     65 async function update_from_client_and_await_installing_version(test, registration) {
     66  const updatefound = wait_for_update(test, registration);
     67  registration.update();
     68  await updatefound;
     69  return registration.installing;
     70 }
     71 
     72 async function spin_up_service_worker(test) {
     73  const script = 'resources/update-during-installation-worker.py';
     74  const scope = 'resources/blank.html';
     75 
     76  const registration = await service_worker_unregister_and_register(test, script, scope);
     77  test.add_cleanup(async () => {
     78    if (registration.installing) {
     79      // If there is an installing worker, we need to finish installing it.
     80      // Otherwise, the tests fails with an timeout because unregister() blocks
     81      // until the install-event-handler finishes.
     82      const worker = registration.installing;
     83      await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
     84      await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
     85    }
     86    return registration.unregister();
     87  });
     88 
     89  return registration;
     90 }
     91 
     92 promise_test(async t => {
     93  const registration = await spin_up_service_worker(t);
     94  const worker = registration.installing;
     95  await ensure_install_event_fired(worker);
     96 
     97  const result = registration.update();
     98  await activate_service_worker(t, worker);
     99  return result;
    100 }, 'ServiceWorkerRegistration.update() from client succeeds while installing service worker.');
    101 
    102 promise_test(async t => {
    103  const registration = await spin_up_service_worker(t);
    104  const worker = registration.installing;
    105  await ensure_install_event_fired(worker);
    106 
    107  // Add event listener to fail the test if update() succeeds.
    108  const updatefound = t.step_func(async () => {
    109    registration.removeEventListener('updatefound', updatefound);
    110    // Activate new worker so non-compliant browsers don't fail with timeout.
    111    await activate_service_worker(t, registration.installing);
    112    assert_unreached("update() should have failed");
    113  });
    114  registration.addEventListener('updatefound', updatefound);
    115 
    116  const update = await update_within_service_worker(worker);
    117  // Activate worker to ensure update() finishes and the test doesn't timeout
    118  // in non-compliant browsers.
    119  await activate_service_worker(t, worker);
    120 
    121  const response = await update.finish();
    122  assert_false(response.success, 'update() should have failed.');
    123  assert_equals('InvalidStateError', response.exception, 'update() should have thrown InvalidStateError.');
    124 }, 'ServiceWorkerRegistration.update() from installing service worker throws.');
    125 
    126 promise_test(async t => {
    127  const registration = await spin_up_service_worker(t);
    128  const worker1 = registration.installing;
    129  await activate_service_worker(t, worker1);
    130 
    131  const worker2 = await update_from_client_and_await_installing_version(t, registration);
    132  await ensure_install_event_fired(worker2);
    133 
    134  const update = await update_within_service_worker(worker1);
    135  // Activate the new version so that update() finishes and the test doesn't timeout.
    136  await activate_service_worker(t, worker2);
    137  const response = await update.finish();
    138  assert_true(response.success, 'update() from active service worker should have succeeded.');
    139 }, 'ServiceWorkerRegistration.update() from active service worker succeeds while installing service worker.');
    140 </script>