tor-browser

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

cache-add.https.any.js (13924B)


      1 // META: title=Cache.add and Cache.addAll
      2 // META: global=window,worker
      3 // META: script=/common/get-host-info.sub.js
      4 // META: script=./resources/test-helpers.js
      5 // META: timeout=long
      6 
      7 const { REMOTE_HOST } = get_host_info();
      8 
      9 cache_test(function(cache, test) {
     10    return promise_rejects_js(
     11      test,
     12      TypeError,
     13      cache.add(),
     14      'Cache.add should throw a TypeError when no arguments are given.');
     15  }, 'Cache.add called with no arguments');
     16 
     17 cache_test(function(cache) {
     18    return cache.add('./resources/simple.txt')
     19      .then(function(result) {
     20          assert_equals(result, undefined,
     21                        'Cache.add should resolve with undefined on success.');
     22          return cache.match('./resources/simple.txt');
     23        })
     24        .then(function(response) {
     25          assert_class_string(response, 'Response',
     26                              'Cache.add should put a resource in the cache.');
     27          return response.text();
     28        })
     29        .then(function(body) {
     30          assert_equals(body, 'a simple text file\n',
     31                        'Cache.add should retrieve the correct body.');
     32        });
     33  }, 'Cache.add called with relative URL specified as a string');
     34 
     35 cache_test(function(cache, test) {
     36    return promise_rejects_js(
     37      test,
     38      TypeError,
     39      cache.add('javascript://this-is-not-http-mmkay'),
     40      'Cache.add should throw a TypeError for non-HTTP/HTTPS URLs.');
     41  }, 'Cache.add called with non-HTTP/HTTPS URL');
     42 
     43 cache_test(function(cache) {
     44    var request = new Request('./resources/simple.txt');
     45    return cache.add(request)
     46      .then(function(result) {
     47          assert_equals(result, undefined,
     48                        'Cache.add should resolve with undefined on success.');
     49        });
     50  }, 'Cache.add called with Request object');
     51 
     52 cache_test(function(cache, test) {
     53    var request = new Request('./resources/simple.txt',
     54                              {method: 'POST', body: 'This is a body.'});
     55    return promise_rejects_js(
     56      test,
     57      TypeError,
     58      cache.add(request),
     59      'Cache.add should throw a TypeError for non-GET requests.');
     60  }, 'Cache.add called with POST request');
     61 
     62 cache_test(function(cache) {
     63    var request = new Request('./resources/simple.txt');
     64    return cache.add(request)
     65      .then(function(result) {
     66          assert_equals(result, undefined,
     67                        'Cache.add should resolve with undefined on success.');
     68        })
     69      .then(function() {
     70          return cache.add(request);
     71        })
     72      .then(function(result) {
     73          assert_equals(result, undefined,
     74                        'Cache.add should resolve with undefined on success.');
     75        });
     76  }, 'Cache.add called twice with the same Request object');
     77 
     78 cache_test(function(cache) {
     79    var request = new Request('./resources/simple.txt');
     80    return request.text()
     81      .then(function() {
     82          assert_false(request.bodyUsed);
     83        })
     84      .then(function() {
     85          return cache.add(request);
     86        });
     87  }, 'Cache.add with request with null body (not consumed)');
     88 
     89 cache_test(function(cache, test) {
     90    return promise_rejects_js(
     91      test,
     92      TypeError,
     93      cache.add('./resources/fetch-status.py?status=206'),
     94      'Cache.add should reject on partial response');
     95  }, 'Cache.add with 206 response');
     96 
     97 cache_test(function(cache, test) {
     98    var urls = ['./resources/fetch-status.py?status=206',
     99                './resources/fetch-status.py?status=200'];
    100    var requests = urls.map(function(url) {
    101        return new Request(url);
    102      });
    103    return promise_rejects_js(
    104      test,
    105      TypeError,
    106      cache.addAll(requests),
    107      'Cache.addAll should reject with TypeError if any request fails');
    108  }, 'Cache.addAll with 206 response');
    109 
    110 cache_test(function(cache, test) {
    111    var urls = ['./resources/fetch-status.py?status=206',
    112                './resources/fetch-status.py?status=200'];
    113    var requests = urls.map(function(url) {
    114        var cross_origin_url = new URL(url, location.href);
    115        cross_origin_url.hostname = REMOTE_HOST;
    116        return new Request(cross_origin_url.href, { mode: 'no-cors' });
    117      });
    118    return promise_rejects_js(
    119      test,
    120      TypeError,
    121      cache.addAll(requests),
    122      'Cache.addAll should reject with TypeError if any request fails');
    123  }, 'Cache.addAll with opaque-filtered 206 response');
    124 
    125 cache_test(function(cache, test) {
    126    return promise_rejects_js(
    127      test,
    128      TypeError,
    129      cache.add('this-does-not-exist-please-dont-create-it'),
    130      'Cache.add should reject if response is !ok');
    131  }, 'Cache.add with request that results in a status of 404');
    132 
    133 
    134 cache_test(function(cache, test) {
    135    return promise_rejects_js(
    136      test,
    137      TypeError,
    138      cache.add('./resources/fetch-status.py?status=500'),
    139      'Cache.add should reject if response is !ok');
    140  }, 'Cache.add with request that results in a status of 500');
    141 
    142 cache_test(function(cache, test) {
    143    return promise_rejects_js(
    144      test,
    145      TypeError,
    146      cache.addAll(),
    147      'Cache.addAll with no arguments should throw TypeError.');
    148  }, 'Cache.addAll with no arguments');
    149 
    150 cache_test(function(cache, test) {
    151    // Assumes the existence of ../resources/simple.txt and ../resources/blank.html
    152    var urls = ['./resources/simple.txt', undefined, './resources/blank.html'];
    153    return promise_rejects_js(
    154      test,
    155      TypeError,
    156      cache.addAll(urls),
    157      'Cache.addAll should throw TypeError for an undefined argument.');
    158  }, 'Cache.addAll with a mix of valid and undefined arguments');
    159 
    160 cache_test(function(cache) {
    161    return cache.addAll([])
    162      .then(function(result) {
    163          assert_equals(result, undefined,
    164                        'Cache.addAll should resolve with undefined on ' +
    165                        'success.');
    166          return cache.keys();
    167        })
    168      .then(function(result) {
    169          assert_equals(result.length, 0,
    170                        'There should be no entry in the cache.');
    171        });
    172  }, 'Cache.addAll with an empty array');
    173 
    174 cache_test(function(cache) {
    175    // Assumes the existence of ../resources/simple.txt and
    176    // ../resources/blank.html
    177    var urls = ['./resources/simple.txt',
    178                self.location.href,
    179                './resources/blank.html'];
    180    return cache.addAll(urls)
    181      .then(function(result) {
    182          assert_equals(result, undefined,
    183                        'Cache.addAll should resolve with undefined on ' +
    184                        'success.');
    185          return Promise.all(
    186            urls.map(function(url) { return cache.match(url); }));
    187        })
    188      .then(function(responses) {
    189          assert_class_string(
    190            responses[0], 'Response',
    191            'Cache.addAll should put a resource in the cache.');
    192          assert_class_string(
    193            responses[1], 'Response',
    194            'Cache.addAll should put a resource in the cache.');
    195          assert_class_string(
    196            responses[2], 'Response',
    197            'Cache.addAll should put a resource in the cache.');
    198          return Promise.all(
    199            responses.map(function(response) { return response.text(); }));
    200        })
    201      .then(function(bodies) {
    202          assert_equals(
    203            bodies[0], 'a simple text file\n',
    204            'Cache.add should retrieve the correct body.');
    205          assert_equals(
    206            bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
    207            'Cache.add should retrieve the correct body.');
    208        });
    209  }, 'Cache.addAll with string URL arguments');
    210 
    211 cache_test(function(cache) {
    212    // Assumes the existence of ../resources/simple.txt and
    213    // ../resources/blank.html
    214    var urls = ['./resources/simple.txt',
    215                self.location.href,
    216                './resources/blank.html'];
    217    var requests = urls.map(function(url) {
    218        return new Request(url);
    219      });
    220    return cache.addAll(requests)
    221      .then(function(result) {
    222          assert_equals(result, undefined,
    223                        'Cache.addAll should resolve with undefined on ' +
    224                        'success.');
    225          return Promise.all(
    226            urls.map(function(url) { return cache.match(url); }));
    227        })
    228      .then(function(responses) {
    229          assert_class_string(
    230            responses[0], 'Response',
    231            'Cache.addAll should put a resource in the cache.');
    232          assert_class_string(
    233            responses[1], 'Response',
    234            'Cache.addAll should put a resource in the cache.');
    235          assert_class_string(
    236            responses[2], 'Response',
    237            'Cache.addAll should put a resource in the cache.');
    238          return Promise.all(
    239            responses.map(function(response) { return response.text(); }));
    240        })
    241      .then(function(bodies) {
    242          assert_equals(
    243            bodies[0], 'a simple text file\n',
    244            'Cache.add should retrieve the correct body.');
    245          assert_equals(
    246            bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
    247            'Cache.add should retrieve the correct body.');
    248        });
    249  }, 'Cache.addAll with Request arguments');
    250 
    251 cache_test(function(cache, test) {
    252    // Assumes that ../resources/simple.txt and ../resources/blank.html exist.
    253    // The second resource does not.
    254    var urls = ['./resources/simple.txt',
    255                'this-resource-should-not-exist',
    256                './resources/blank.html'];
    257    var requests = urls.map(function(url) {
    258        return new Request(url);
    259      });
    260    return promise_rejects_js(
    261      test,
    262      TypeError,
    263      cache.addAll(requests),
    264      'Cache.addAll should reject with TypeError if any request fails')
    265      .then(function() {
    266          return Promise.all(urls.map(function(url) {
    267              return cache.match(url);
    268            }));
    269      })
    270      .then(function(matches) {
    271          assert_array_equals(
    272            matches,
    273            [undefined, undefined, undefined],
    274            'If any response fails, no response should be added to cache');
    275      });
    276  }, 'Cache.addAll with a mix of succeeding and failing requests');
    277 
    278 cache_test(function(cache, test) {
    279    var request = new Request('../resources/simple.txt');
    280    return promise_rejects_dom(
    281      test,
    282      'InvalidStateError',
    283      cache.addAll([request, request]),
    284      'Cache.addAll should throw InvalidStateError if the same request is added ' +
    285      'twice.');
    286  }, 'Cache.addAll called with the same Request object specified twice');
    287 
    288 cache_test(async function(cache, test) {
    289    const url = './resources/vary.py?vary=x-shape';
    290    let requests = [
    291      new Request(url, { headers: { 'x-shape': 'circle' }}),
    292      new Request(url, { headers: { 'x-shape': 'square' }}),
    293    ];
    294    let result = await cache.addAll(requests);
    295    assert_equals(result, undefined, 'Cache.addAll() should succeed');
    296  }, 'Cache.addAll should succeed when entries differ by vary header');
    297 
    298 cache_test(async function(cache, test) {
    299    const url = './resources/vary.py?vary=x-shape';
    300    let requests = [
    301      new Request(url, { headers: { 'x-shape': 'circle' }}),
    302      new Request(url, { headers: { 'x-shape': 'circle' }}),
    303    ];
    304    await promise_rejects_dom(
    305      test,
    306      'InvalidStateError',
    307      cache.addAll(requests),
    308      'Cache.addAll() should reject when entries are duplicate by vary header');
    309  }, 'Cache.addAll should reject when entries are duplicate by vary header');
    310 
    311 // VARY header matching is asymmetric.  Determining if two entries are duplicate
    312 // depends on which entry's response is used in the comparison.  The target
    313 // response's VARY header determines what request headers are examined.  This
    314 // test verifies that Cache.addAll() duplicate checking handles this asymmetric
    315 // behavior correctly.
    316 cache_test(async function(cache, test) {
    317    const base_url = './resources/vary.py';
    318 
    319    // Define a request URL that sets a VARY header in the
    320    // query string to be echoed back by the server.
    321    const url = base_url + '?vary=x-size';
    322 
    323    // Set a cookie to override the VARY header of the response
    324    // when the request is made with credentials.  This will
    325    // take precedence over the query string vary param.  This
    326    // is a bit confusing, but it's necessary to construct a test
    327    // where the URL is the same, but the VARY headers differ.
    328    //
    329    // Note, the test could also pass this information in additional
    330    // request headers.  If the cookie approach becomes too unwieldy
    331    // this test could be rewritten to use that technique.
    332    await fetch(base_url + '?set-vary-value-override-cookie=x-shape');
    333    test.add_cleanup(_ => fetch(base_url + '?clear-vary-value-override-cookie'));
    334 
    335    let requests = [
    336      // This request will result in a Response with a "Vary: x-shape"
    337      // header.  This *will not* result in a duplicate match with the
    338      // other entry.
    339      new Request(url, { headers: { 'x-shape': 'circle',
    340                                    'x-size': 'big' },
    341                         credentials: 'same-origin' }),
    342 
    343      // This request will result in a Response with a "Vary: x-size"
    344      // header.  This *will* result in a duplicate match with the other
    345      // entry.
    346      new Request(url, { headers: { 'x-shape': 'square',
    347                                    'x-size': 'big' },
    348                         credentials: 'omit' }),
    349    ];
    350    await promise_rejects_dom(
    351      test,
    352      'InvalidStateError',
    353      cache.addAll(requests),
    354      'Cache.addAll() should reject when one entry has a vary header ' +
    355      'matching an earlier entry.');
    356 
    357    // Test the reverse order now.
    358    await promise_rejects_dom(
    359      test,
    360      'InvalidStateError',
    361      cache.addAll(requests.reverse()),
    362      'Cache.addAll() should reject when one entry has a vary header ' +
    363      'matching a later entry.');
    364 
    365  }, 'Cache.addAll should reject when one entry has a vary header ' +
    366     'matching another entry');
    367 
    368 done();