tor-browser

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

worker-interception.https.html (9784B)


      1 <!DOCTYPE html>
      2 <title>Service Worker: intercepting Worker script loads</title>
      3 <meta name="timeout" content="long">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="resources/test-helpers.sub.js"></script>
      7 <body>
      8 <script>
      9 
     10 // ========== Worker main resource interception tests ==========
     11 
     12 async function setup_service_worker(t, service_worker_url, scope) {
     13  const r = await service_worker_unregister_and_register(
     14      t, service_worker_url, scope);
     15  t.add_cleanup(() => service_worker_unregister(t, scope));
     16  await wait_for_state(t, r.installing, 'activated');
     17  return r.active;
     18 }
     19 
     20 promise_test(async t => {
     21  const worker_url = 'resources/sample-synthesized-worker.js?dedicated';
     22  const service_worker_url = 'resources/sample-worker-interceptor.js';
     23  const scope = worker_url;
     24 
     25  const serviceWorker = await setup_service_worker(t, service_worker_url, scope);
     26 
     27  const channels = new MessageChannel();
     28  serviceWorker.postMessage({port: channels.port1}, [channels.port1]);
     29 
     30  const clientId = await new Promise(resolve => channels.port2.onmessage = (e) => resolve(e.data.id));
     31 
     32  const resultPromise =  new Promise(resolve => channels.port2.onmessage = (e) => resolve(e.data));
     33 
     34  const w = new Worker(worker_url);
     35  const data = await new Promise((resolve, reject) => {
     36    w.onmessage = e => resolve(e.data);
     37    w.onerror = e => reject(e.message);
     38  });
     39  assert_equals(data, 'worker loading intercepted by service worker');
     40 
     41  const results = await resultPromise;
     42  assert_equals(results.clientId, clientId);
     43  assert_true(!!results.resultingClientId.length);
     44 
     45  channels.port2.postMessage("done");
     46 }, `Verify a dedicated worker script request gets correct client Ids`);
     47 
     48 promise_test(async t => {
     49  const worker_url = 'resources/sample-synthesized-worker.js?dedicated';
     50  const service_worker_url = 'resources/sample-worker-interceptor.js';
     51  const scope = worker_url;
     52 
     53  await setup_service_worker(t, service_worker_url, scope);
     54  const w = new Worker(worker_url);
     55  const data = await new Promise((resolve, reject) => {
     56    w.onmessage = e => resolve(e.data);
     57    w.onerror = e => reject(e.message);
     58  });
     59  assert_equals(data, 'worker loading intercepted by service worker');
     60 }, `Verify a dedicated worker script request issued from a uncontrolled ` +
     61   `document is intercepted by worker's own service worker.`);
     62 
     63 promise_test(async t => {
     64  const frame_url = 'resources/create-out-of-scope-worker.html';
     65  const service_worker_url = 'resources/sample-worker-interceptor.js';
     66  const scope = frame_url;
     67 
     68  const registration = await service_worker_unregister_and_register(
     69      t, service_worker_url, scope);
     70  t.add_cleanup(() => service_worker_unregister(t, scope));
     71  await wait_for_state(t, registration.installing, 'activated');
     72 
     73  const frame = await with_iframe(frame_url);
     74  t.add_cleanup(_ => frame.remove());
     75 
     76  assert_equals(
     77    frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
     78    get_newest_worker(registration).scriptURL,
     79    'the frame should be controlled by a service worker'
     80  );
     81 
     82  const result = await frame.contentWindow.getWorkerPromise();
     83 
     84  assert_equals(result,
     85                'worker loading was not intercepted by service worker');
     86 }, `Verify an out-of-scope dedicated worker script request issued from a ` +
     87   `controlled document should not be intercepted by document's service ` +
     88   `worker.`);
     89 
     90 promise_test(async t => {
     91  const worker_url = 'resources/sample-synthesized-worker.js?shared';
     92  const service_worker_url = 'resources/sample-worker-interceptor.js';
     93  const scope = worker_url;
     94 
     95  await setup_service_worker(t, service_worker_url, scope);
     96  const w = new SharedWorker(worker_url);
     97  const data = await new Promise((resolve, reject) => {
     98    w.port.onmessage = e => resolve(e.data);
     99    w.onerror = e => reject(e.message);
    100  });
    101  assert_equals(data, 'worker loading intercepted by service worker');
    102 }, `Verify a shared worker script request issued from a uncontrolled ` +
    103   `document is intercepted by worker's own service worker.`);
    104 
    105 promise_test(async t => {
    106  const worker_url = 'resources/sample-same-origin-worker.js?dedicated';
    107  const service_worker_url = 'resources/sample-worker-interceptor.js';
    108  const scope = worker_url;
    109 
    110  await setup_service_worker(t, service_worker_url, scope);
    111  const w = new Worker(worker_url);
    112  const data = await new Promise((resolve, reject) => {
    113    w.onmessage = e => resolve(e.data);
    114    w.onerror = e => reject(e.message);
    115  });
    116  assert_equals(data, 'dedicated worker script loaded');
    117 }, 'Verify a same-origin worker script served by a service worker succeeds ' +
    118   'in starting a dedicated worker.');
    119 
    120 promise_test(async t => {
    121  const worker_url = 'resources/sample-same-origin-worker.js?shared';
    122  const service_worker_url = 'resources/sample-worker-interceptor.js';
    123  const scope = worker_url;
    124 
    125  await setup_service_worker(t, service_worker_url, scope);
    126  const w = new SharedWorker(worker_url);
    127  const data = await new Promise((resolve, reject) => {
    128    w.port.onmessage = e => resolve(e.data);
    129    w.onerror = e => reject(e.message);
    130  });
    131  assert_equals(data, 'shared worker script loaded');
    132 }, 'Verify a same-origin worker script served by a service worker succeeds ' +
    133   'in starting a shared worker.');
    134 
    135 promise_test(async t => {
    136  const worker_url = 'resources/sample-cors-worker.js?dedicated';
    137  const service_worker_url = 'resources/sample-worker-interceptor.js';
    138  const scope = worker_url;
    139 
    140  await setup_service_worker(t, service_worker_url, scope);
    141  const w = new Worker(worker_url);
    142  const watcher = new EventWatcher(t, w, ['message', 'error']);
    143  await watcher.wait_for('error');
    144 }, 'Verify a cors worker script served by a service worker fails dedicated ' +
    145   'worker start.');
    146 
    147 promise_test(async t => {
    148  const worker_url = 'resources/sample-cors-worker.js?shared';
    149  const service_worker_url = 'resources/sample-worker-interceptor.js';
    150  const scope = worker_url;
    151 
    152  await setup_service_worker(t, service_worker_url, scope);
    153  const w = new SharedWorker(worker_url);
    154  const watcher = new EventWatcher(t, w, ['message', 'error']);
    155  await watcher.wait_for('error');
    156 }, 'Verify a cors worker script served by a service worker fails shared ' +
    157   'worker start.');
    158 
    159 promise_test(async t => {
    160  const worker_url = 'resources/sample-no-cors-worker.js?dedicated';
    161  const service_worker_url = 'resources/sample-worker-interceptor.js';
    162  const scope = worker_url;
    163 
    164  await setup_service_worker(t, service_worker_url, scope);
    165  const w = new Worker(worker_url);
    166  const watcher = new EventWatcher(t, w, ['message', 'error']);
    167  await watcher.wait_for('error');
    168 }, 'Verify a no-cors cross-origin worker script served by a service worker ' +
    169   'fails dedicated worker start.');
    170 
    171 promise_test(async t => {
    172  const worker_url = 'resources/sample-no-cors-worker.js?shared';
    173  const service_worker_url = 'resources/sample-worker-interceptor.js';
    174  const scope = worker_url;
    175 
    176  await setup_service_worker(t, service_worker_url, scope);
    177  const w = new SharedWorker(worker_url);
    178  const watcher = new EventWatcher(t, w, ['message', 'error']);
    179  await watcher.wait_for('error');
    180 }, 'Verify a no-cors cross-origin worker script served by a service worker ' +
    181   'fails shared worker start.');
    182 
    183 // ========== Worker subresource interception tests ==========
    184 
    185 const scope_for_subresource_interception = 'resources/load_worker.js';
    186 
    187 promise_test(async t => {
    188  const service_worker_url = 'resources/worker-load-interceptor.js';
    189  const r = await service_worker_unregister_and_register(
    190      t, service_worker_url, scope_for_subresource_interception);
    191  await wait_for_state(t, r.installing, 'activated');
    192 }, 'Register a service worker for worker subresource interception tests.');
    193 
    194 // Do not call this function multiple times without waiting for the promise
    195 // resolution because this sets new event handlers on |worker|.
    196 // TODO(nhiroki): To isolate multiple function calls, use MessagePort instead of
    197 // worker's onmessage event handler.
    198 async function request_on_worker(worker, resource_type) {
    199  const data = await new Promise((resolve, reject) => {
    200    if (worker instanceof Worker) {
    201      worker.onmessage = e => resolve(e.data);
    202      worker.onerror = e => reject(e);
    203      worker.postMessage(resource_type);
    204    } else if (worker instanceof SharedWorker) {
    205      worker.port.onmessage = e => resolve(e.data);
    206      worker.onerror = e => reject(e);
    207      worker.port.postMessage(resource_type);
    208    } else {
    209      reject('Unexpected worker type!');
    210    }
    211  });
    212  assert_equals(data, 'This load was successfully intercepted.');
    213 }
    214 
    215 async function subresource_test(worker) {
    216  await request_on_worker(worker, 'xhr');
    217  await request_on_worker(worker, 'fetch');
    218  await request_on_worker(worker, 'importScripts');
    219 }
    220 
    221 promise_test(async t => {
    222  await subresource_test(new Worker('resources/load_worker.js'));
    223 }, 'Requests on a dedicated worker controlled by a service worker.');
    224 
    225 promise_test(async t => {
    226  await subresource_test(new SharedWorker('resources/load_worker.js'));
    227 }, 'Requests on a shared worker controlled by a service worker.');
    228 
    229 promise_test(async t => {
    230  await subresource_test(new Worker('resources/nested_load_worker.js'));
    231 }, 'Requests on a dedicated worker nested in a dedicated worker and ' +
    232       'controlled by a service worker');
    233 
    234 promise_test(async t => {
    235  await subresource_test(new SharedWorker('resources/nested_load_worker.js'));
    236 }, 'Requests on a dedicated worker nested in a shared worker and controlled ' +
    237       'by a service worker');
    238 
    239 promise_test(async t => {
    240  await service_worker_unregister(t, scope_for_subresource_interception);
    241 }, 'Unregister a service worker for subresource interception tests.');
    242 
    243 </script>
    244 </body>