tor-browser

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

fetch-response-taint.https.html (8920B)


      1 <!DOCTYPE html>
      2 <title>Service Worker: Tainting of responses fetched via SW.</title>
      3 <!-- This test makes a large number of requests sequentially. -->
      4 <meta name="timeout" content="long">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/common/get-host-info.sub.js"></script>
      8 <script src="resources/test-helpers.sub.js"></script>
      9 <body>
     10 <script>
     11 var host_info = get_host_info();
     12 var BASE_ORIGIN = host_info.HTTPS_ORIGIN;
     13 var OTHER_ORIGIN = host_info.HTTPS_REMOTE_ORIGIN;
     14 var BASE_URL = BASE_ORIGIN + base_path() +
     15               'resources/fetch-access-control.py?';
     16 var OTHER_BASE_URL = OTHER_ORIGIN + base_path() +
     17                     'resources/fetch-access-control.py?';
     18 
     19 function frame_fetch(frame, url, mode, credentials) {
     20  var foreignPromise = frame.contentWindow.fetch(
     21      new Request(url, {mode: mode, credentials: credentials}))
     22 
     23  // Event loops should be shared between contexts of similar origin, not all
     24  // browsers adhere to this expectation at the time of this writing. Incorrect
     25  // behavior in this regard can interfere with test execution when the
     26  // provided iframe is removed from the document.
     27  //
     28  // WPT maintains a test dedicated the expected treatment of event loops, so
     29  // the following workaround is acceptable in this context.
     30  return Promise.resolve(foreignPromise);
     31 }
     32 
     33 var login_and_register;
     34 promise_test(function(t) {
     35    var SCOPE = 'resources/fetch-response-taint-iframe.html';
     36    var SCRIPT = 'resources/fetch-rewrite-worker.js';
     37    var registration;
     38 
     39    login_and_register = login_https(t, host_info.HTTPS_ORIGIN, host_info.HTTPS_REMOTE_ORIGIN)
     40      .then(function() {
     41          return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
     42        })
     43      .then(function(r) {
     44          registration = r;
     45          return wait_for_state(t, registration.installing, 'activated');
     46        })
     47      .then(function() { return with_iframe(SCOPE); })
     48      .then(function(f) {
     49          // This test should not be considered complete until after the
     50          // service worker has been unregistered. Currently, `testharness.js`
     51          // does not support asynchronous global "tear down" logic, so this
     52          // must be expressed using a dedicated `promise_test`. Because the
     53          // other sub-tests in this file are declared synchronously, this
     54          // test will be the final test executed.
     55          promise_test(function(t) {
     56              f.remove();
     57              return registration.unregister();
     58            }, 'restore global state');
     59 
     60          return f;
     61        });
     62    return login_and_register;
     63  }, 'initialize global state');
     64 
     65 function ng_test(url, mode, credentials) {
     66  promise_test(function(t) {
     67      return login_and_register
     68        .then(function(frame) {
     69            var fetchRequest = frame_fetch(frame, url, mode, credentials);
     70            return promise_rejects_js(t, frame.contentWindow.TypeError, fetchRequest);
     71          });
     72    }, 'url:\"' + url + '\" mode:\"' + mode +
     73       '\" credentials:\"' + credentials + '\" should fail.');
     74 }
     75 
     76 function ok_test(url, mode, credentials, expected_type, expected_username) {
     77  promise_test(function() {
     78      return login_and_register.then(function(frame) {
     79            return frame_fetch(frame, url, mode, credentials)
     80          })
     81        .then(function(res) {
     82            assert_equals(res.type, expected_type, 'response type');
     83            return res.text();
     84          })
     85        .then(function(text) {
     86            if (expected_type == 'opaque') {
     87              assert_equals(text, '');
     88            } else {
     89              return new Promise(function(resolve) {
     90                    var report = resolve;
     91                    // text must contain report() call.
     92                    eval(text);
     93                  })
     94                .then(function(result) {
     95                    assert_equals(result.username, expected_username);
     96                  });
     97            }
     98          });
     99    }, 'fetching url:\"' + url + '\" mode:\"' + mode +
    100                        '\" credentials:\"' + credentials + '\" should ' +
    101                        'succeed.');
    102 }
    103 
    104 function build_rewrite_url(origin, url, mode, credentials) {
    105  return origin + '/?url=' + encodeURIComponent(url) + '&mode=' + mode +
    106      '&credentials=' + credentials + '&';
    107 }
    108 
    109 function for_each_origin_mode_credentials(callback) {
    110  [BASE_ORIGIN, OTHER_ORIGIN].forEach(function(origin) {
    111      ['same-origin', 'no-cors', 'cors'].forEach(function(mode) {
    112          ['omit', 'same-origin', 'include'].forEach(function(credentials) {
    113              callback(origin, mode, credentials);
    114            });
    115        });
    116    });
    117 }
    118 
    119 ok_test(BASE_URL, 'same-origin', 'omit', 'basic', 'undefined');
    120 ok_test(BASE_URL, 'same-origin', 'same-origin', 'basic', 'username2s');
    121 ok_test(BASE_URL, 'same-origin', 'include', 'basic', 'username2s');
    122 ok_test(BASE_URL, 'no-cors', 'omit', 'basic', 'undefined');
    123 ok_test(BASE_URL, 'no-cors', 'same-origin', 'basic', 'username2s');
    124 ok_test(BASE_URL, 'no-cors', 'include', 'basic', 'username2s');
    125 ok_test(BASE_URL, 'cors', 'omit', 'basic', 'undefined');
    126 ok_test(BASE_URL, 'cors', 'same-origin', 'basic', 'username2s');
    127 ok_test(BASE_URL, 'cors', 'include', 'basic', 'username2s');
    128 ng_test(OTHER_BASE_URL, 'same-origin', 'omit');
    129 ng_test(OTHER_BASE_URL, 'same-origin', 'same-origin');
    130 ng_test(OTHER_BASE_URL, 'same-origin', 'include');
    131 ok_test(OTHER_BASE_URL, 'no-cors', 'omit', 'opaque');
    132 ok_test(OTHER_BASE_URL, 'no-cors', 'same-origin', 'opaque');
    133 ok_test(OTHER_BASE_URL, 'no-cors', 'include', 'opaque');
    134 ng_test(OTHER_BASE_URL, 'cors', 'omit');
    135 ng_test(OTHER_BASE_URL, 'cors', 'same-origin');
    136 ng_test(OTHER_BASE_URL, 'cors', 'include');
    137 ok_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit', 'cors', 'undefined');
    138 ok_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'same-origin', 'cors',
    139        'undefined');
    140 ng_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'include');
    141 ok_test(OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + '&ACACredentials=true',
    142        'cors', 'include', 'cors', 'username1s')
    143 
    144 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    145  var url = build_rewrite_url(
    146      origin, BASE_URL, 'same-origin', 'omit');
    147  // Fetch to the other origin with same-origin mode should fail.
    148  if (origin == OTHER_ORIGIN && mode == 'same-origin') {
    149    ng_test(url, mode, credentials);
    150  } else {
    151    // The response type from the SW should be basic
    152    ok_test(url, mode, credentials, 'basic', 'undefined');
    153  }
    154 });
    155 
    156 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    157  var url = build_rewrite_url(
    158      origin, BASE_URL, 'same-origin', 'same-origin');
    159 
    160  // Fetch to the other origin with same-origin mode should fail.
    161  if (origin == OTHER_ORIGIN && mode == 'same-origin') {
    162    ng_test(url, mode, credentials);
    163  } else {
    164    // The response type from the SW should be basic.
    165    ok_test(url, mode, credentials, 'basic', 'username2s');
    166  }
    167 });
    168 
    169 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    170  var url = build_rewrite_url(
    171      origin, OTHER_BASE_URL, 'same-origin', 'omit');
    172  // The response from the SW should be an error.
    173  ng_test(url, mode, credentials);
    174 });
    175 
    176 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    177  var url = build_rewrite_url(
    178      origin, OTHER_BASE_URL, 'no-cors', 'omit');
    179 
    180  // SW can respond only to no-cors requests.
    181  if (mode != 'no-cors') {
    182    ng_test(url, mode, credentials);
    183  } else {
    184    // The response type from the SW should be opaque.
    185    ok_test(url, mode, credentials, 'opaque');
    186  }
    187 });
    188 
    189 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    190  var url = build_rewrite_url(
    191      origin, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit');
    192 
    193  // Fetch to the other origin with same-origin mode should fail.
    194  if (origin == OTHER_ORIGIN && mode == 'same-origin') {
    195    ng_test(url, mode, credentials);
    196  } else if (origin == BASE_ORIGIN && mode == 'same-origin') {
    197    // Cors type response to a same-origin mode request should fail
    198    ng_test(url, mode, credentials);
    199  } else {
    200    // The response from the SW should be cors.
    201    ok_test(url, mode, credentials, 'cors', 'undefined');
    202  }
    203 });
    204 
    205 for_each_origin_mode_credentials(function(origin, mode, credentials) {
    206  var url = build_rewrite_url(
    207      origin,
    208      OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN +
    209      '&ACACredentials=true',
    210      'cors', 'include');
    211  // Fetch to the other origin with same-origin mode should fail.
    212  if (origin == OTHER_ORIGIN && mode == 'same-origin') {
    213    ng_test(url, mode, credentials);
    214  } else if (origin == BASE_ORIGIN && mode == 'same-origin') {
    215    // Cors type response to a same-origin mode request should fail
    216    ng_test(url, mode, credentials);
    217  } else {
    218    // The response from the SW should be cors.
    219    ok_test(url, mode, credentials, 'cors', 'username1s');
    220  }
    221 });
    222 </script>
    223 </body>