tor-browser

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

cache-match.https.any.js (17212B)


      1 // META: title=Cache.match
      2 // META: global=window,worker
      3 // META: script=./resources/test-helpers.js
      4 // META: script=/common/get-host-info.sub.js
      5 // META: timeout=long
      6 
      7 prepopulated_cache_test(simple_entries, function(cache, entries) {
      8    return cache.match('not-present-in-the-cache')
      9      .then(function(result) {
     10          assert_equals(result, undefined,
     11                        'Cache.match failures should resolve with undefined.');
     12        });
     13  }, 'Cache.match with no matching entries');
     14 
     15 prepopulated_cache_test(simple_entries, function(cache, entries) {
     16    return cache.match(entries.a.request.url)
     17      .then(function(result) {
     18          assert_response_equals(result, entries.a.response,
     19                                 'Cache.match should match by URL.');
     20        });
     21  }, 'Cache.match with URL');
     22 
     23 prepopulated_cache_test(simple_entries, function(cache, entries) {
     24    return cache.match(entries.a.request)
     25      .then(function(result) {
     26          assert_response_equals(result, entries.a.response,
     27                                 'Cache.match should match by Request.');
     28        });
     29  }, 'Cache.match with Request');
     30 
     31 prepopulated_cache_test(simple_entries, function(cache, entries) {
     32    var alt_response = new Response('', {status: 201});
     33 
     34    return self.caches.open('second_matching_cache')
     35      .then(function(cache) {
     36          return cache.put(entries.a.request, alt_response.clone());
     37        })
     38      .then(function() {
     39          return cache.match(entries.a.request);
     40        })
     41      .then(function(result) {
     42          assert_response_equals(
     43            result, entries.a.response,
     44            'Cache.match should match the first cache.');
     45        });
     46  }, 'Cache.match with multiple cache hits');
     47 
     48 prepopulated_cache_test(simple_entries, function(cache, entries) {
     49    return cache.match(new Request(entries.a.request.url))
     50      .then(function(result) {
     51          assert_response_equals(result, entries.a.response,
     52                                 'Cache.match should match by Request.');
     53        });
     54  }, 'Cache.match with new Request');
     55 
     56 prepopulated_cache_test(simple_entries, function(cache, entries) {
     57    return cache.match(new Request(entries.a.request.url, {method: 'HEAD'}))
     58      .then(function(result) {
     59          assert_equals(result, undefined,
     60                        'Cache.match should not match HEAD Request.');
     61        });
     62  }, 'Cache.match with HEAD');
     63 
     64 prepopulated_cache_test(simple_entries, function(cache, entries) {
     65    return cache.match(entries.a.request,
     66                       {ignoreSearch: true})
     67      .then(function(result) {
     68          assert_response_in_array(
     69            result,
     70            [
     71              entries.a.response,
     72              entries.a_with_query.response
     73            ],
     74            'Cache.match with ignoreSearch should ignore the ' +
     75            'search parameters of cached request.');
     76        });
     77  },
     78  'Cache.match with ignoreSearch option (request with no search ' +
     79  'parameters)');
     80 
     81 prepopulated_cache_test(simple_entries, function(cache, entries) {
     82    return cache.match(entries.a_with_query.request,
     83                       {ignoreSearch: true})
     84      .then(function(result) {
     85          assert_response_in_array(
     86            result,
     87            [
     88              entries.a.response,
     89              entries.a_with_query.response
     90            ],
     91            'Cache.match with ignoreSearch should ignore the ' +
     92            'search parameters of request.');
     93        });
     94  },
     95  'Cache.match with ignoreSearch option (request with search parameter)');
     96 
     97 cache_test(function(cache) {
     98    var request = new Request('http://example.com/');
     99    var head_request = new Request('http://example.com/', {method: 'HEAD'});
    100    var response = new Response('foo');
    101    return cache.put(request.clone(), response.clone())
    102      .then(function() {
    103          return cache.match(head_request.clone());
    104        })
    105      .then(function(result) {
    106          assert_equals(
    107            result, undefined,
    108            'Cache.match should resolve as undefined with a ' +
    109            'mismatched method.');
    110          return cache.match(head_request.clone(),
    111                             {ignoreMethod: true});
    112        })
    113      .then(function(result) {
    114          assert_response_equals(
    115            result, response,
    116            'Cache.match with ignoreMethod should ignore the ' +
    117            'method of request.');
    118        });
    119  }, 'Cache.match supports ignoreMethod');
    120 
    121 cache_test(function(cache) {
    122    var vary_request = new Request('http://example.com/c',
    123                                   {headers: {'Cookies': 'is-for-cookie'}});
    124    var vary_response = new Response('', {headers: {'Vary': 'Cookies'}});
    125    var mismatched_vary_request = new Request('http://example.com/c');
    126 
    127    return cache.put(vary_request.clone(), vary_response.clone())
    128      .then(function() {
    129          return cache.match(mismatched_vary_request.clone());
    130        })
    131      .then(function(result) {
    132          assert_equals(
    133            result, undefined,
    134            'Cache.match should resolve as undefined with a ' +
    135            'mismatched vary.');
    136          return cache.match(mismatched_vary_request.clone(),
    137                              {ignoreVary: true});
    138        })
    139      .then(function(result) {
    140          assert_response_equals(
    141            result, vary_response,
    142            'Cache.match with ignoreVary should ignore the ' +
    143            'vary of request.');
    144        });
    145  }, 'Cache.match supports ignoreVary');
    146 
    147 cache_test(function(cache) {
    148    let has_cache_name = false;
    149    const opts = {
    150      get cacheName() {
    151        has_cache_name = true;
    152        return undefined;
    153      }
    154    };
    155    return self.caches.open('foo')
    156      .then(function() {
    157          return cache.match('bar', opts);
    158        })
    159      .then(function() {
    160          assert_false(has_cache_name,
    161                       'Cache.match does not support cacheName option ' +
    162                       'which was removed in CacheQueryOptions.');
    163        });
    164  }, 'Cache.match does not support cacheName option');
    165 
    166 prepopulated_cache_test(simple_entries, function(cache, entries) {
    167    return cache.match(entries.cat.request.url + '#mouse')
    168      .then(function(result) {
    169          assert_response_equals(result, entries.cat.response,
    170                                 'Cache.match should ignore URL fragment.');
    171        });
    172  }, 'Cache.match with URL containing fragment');
    173 
    174 prepopulated_cache_test(simple_entries, function(cache, entries) {
    175    return cache.match('http')
    176      .then(function(result) {
    177          assert_equals(
    178            result, undefined,
    179            'Cache.match should treat query as a URL and not ' +
    180            'just a string fragment.');
    181        });
    182  }, 'Cache.match with string fragment "http" as query');
    183 
    184 prepopulated_cache_test(vary_entries, function(cache, entries) {
    185    return cache.match('http://example.com/c')
    186      .then(function(result) {
    187          assert_response_in_array(
    188            result,
    189            [
    190              entries.vary_cookie_absent.response
    191            ],
    192            'Cache.match should honor "Vary" header.');
    193        });
    194  }, 'Cache.match with responses containing "Vary" header');
    195 
    196 cache_test(function(cache) {
    197    var request = new Request('http://example.com');
    198    var response;
    199    var request_url = new URL('./resources/simple.txt', location.href).href;
    200    return fetch(request_url)
    201      .then(function(fetch_result) {
    202          response = fetch_result;
    203          assert_equals(
    204            response.url, request_url,
    205            '[https://fetch.spec.whatwg.org/#dom-response-url] ' +
    206            'Reponse.url should return the URL of the response.');
    207          return cache.put(request, response.clone());
    208        })
    209      .then(function() {
    210          return cache.match(request.url);
    211        })
    212      .then(function(result) {
    213          assert_response_equals(
    214            result, response,
    215            'Cache.match should return a Response object that has the same ' +
    216            'properties as the stored response.');
    217          return cache.match(response.url);
    218        })
    219      .then(function(result) {
    220          assert_equals(
    221            result, undefined,
    222            'Cache.match should not match cache entry based on response URL.');
    223        });
    224  }, 'Cache.match with Request and Response objects with different URLs');
    225 
    226 cache_test(function(cache) {
    227    var request_url = new URL('./resources/simple.txt', location.href).href;
    228    return fetch(request_url)
    229      .then(function(fetch_result) {
    230          return cache.put(new Request(request_url), fetch_result);
    231        })
    232      .then(function() {
    233          return cache.match(request_url);
    234        })
    235      .then(function(result) {
    236          return result.text();
    237        })
    238      .then(function(body_text) {
    239          assert_equals(body_text, 'a simple text file\n',
    240                        'Cache.match should return a Response object with a ' +
    241                        'valid body.');
    242        })
    243      .then(function() {
    244          return cache.match(request_url);
    245        })
    246      .then(function(result) {
    247          return result.text();
    248        })
    249      .then(function(body_text) {
    250          assert_equals(body_text, 'a simple text file\n',
    251                        'Cache.match should return a Response object with a ' +
    252                        'valid body each time it is called.');
    253        });
    254  }, 'Cache.match invoked multiple times for the same Request/Response');
    255 
    256 cache_test(function(cache) {
    257    var request_url = new URL('./resources/simple.txt', location.href).href;
    258    return fetch(request_url)
    259      .then(function(fetch_result) {
    260          return cache.put(new Request(request_url), fetch_result);
    261        })
    262      .then(function() {
    263          return cache.match(request_url);
    264        })
    265      .then(function(result) {
    266          return result.blob();
    267        })
    268      .then(function(blob) {
    269          var sliced = blob.slice(2,8);
    270 
    271          return new Promise(function (resolve, reject) {
    272              var reader = new FileReader();
    273              reader.onloadend = function(event) {
    274                resolve(event.target.result);
    275              };
    276              reader.readAsText(sliced);
    277            });
    278        })
    279      .then(function(text) {
    280          assert_equals(text, 'simple',
    281                        'A Response blob returned by Cache.match should be ' +
    282                        'sliceable.' );
    283        });
    284  }, 'Cache.match blob should be sliceable');
    285 
    286 prepopulated_cache_test(simple_entries, function(cache, entries) {
    287    var request = new Request(entries.a.request.clone(), {method: 'POST'});
    288    return cache.match(request)
    289      .then(function(result) {
    290          assert_equals(result, undefined,
    291                        'Cache.match should not find a match');
    292        });
    293  }, 'Cache.match with POST Request');
    294 
    295 prepopulated_cache_test(simple_entries, function(cache, entries) {
    296    var response = entries.non_2xx_response.response;
    297    return cache.match(entries.non_2xx_response.request.url)
    298      .then(function(result) {
    299          assert_response_equals(
    300              result, entries.non_2xx_response.response,
    301              'Cache.match should return a Response object that has the ' +
    302                  'same properties as a stored non-2xx response.');
    303        });
    304  }, 'Cache.match with a non-2xx Response');
    305 
    306 prepopulated_cache_test(simple_entries, function(cache, entries) {
    307    var response = entries.error_response.response;
    308    return cache.match(entries.error_response.request.url)
    309      .then(function(result) {
    310          assert_response_equals(
    311              result, entries.error_response.response,
    312              'Cache.match should return a Response object that has the ' +
    313                  'same properties as a stored network error response.');
    314        });
    315  }, 'Cache.match with a network error Response');
    316 
    317 cache_test(function(cache) {
    318    // This test validates that we can get a Response from the Cache API,
    319    // clone it, and read just one side of the clone.  This was previously
    320    // bugged in FF for Responses with large bodies.
    321    var data = [];
    322    data.length = 80 * 1024;
    323    data.fill('F');
    324    var response;
    325    return cache.put('/', new Response(data.toString()))
    326      .then(function(result) {
    327          return cache.match('/');
    328        })
    329      .then(function(r) {
    330          // Make sure the original response is not GC'd.
    331          response = r;
    332          // Return only the clone.  We purposefully test that the other
    333          // half of the clone does not need to be read here.
    334          return response.clone().text();
    335        })
    336      .then(function(text) {
    337          assert_equals(text, data.toString(), 'cloned body text can be read correctly');
    338        });
    339  }, 'Cache produces large Responses that can be cloned and read correctly.');
    340 
    341 cache_test(async (cache) => {
    342    const url = get_host_info().HTTPS_REMOTE_ORIGIN +
    343      '/service-workers/cache-storage/resources/simple.txt?pipe=' +
    344      'header(access-control-allow-origin,*)|' +
    345      'header(access-control-expose-headers,*)|' +
    346      'header(foo,bar)|' +
    347      'header(set-cookie,X)';
    348 
    349    const response = await fetch(url);
    350    await cache.put(new Request(url), response);
    351    const cached_response = await cache.match(url);
    352 
    353    const headers = cached_response.headers;
    354    assert_equals(headers.get('access-control-expose-headers'), '*');
    355    assert_equals(headers.get('foo'), 'bar');
    356    assert_equals(headers.get('set-cookie'), null);
    357  }, 'cors-exposed header should be stored correctly.');
    358 
    359 cache_test(async (cache) => {
    360    // A URL that should load a resource with a known mime type.
    361    const url = '/service-workers/cache-storage/resources/blank.html';
    362    const expected_mime_type = 'text/html';
    363 
    364    // Verify we get the expected mime type from the network.  Note,
    365    // we cannot use an exact match here since some browsers append
    366    // character encoding information to the blob.type value.
    367    const net_response = await fetch(url);
    368    const net_mime_type = (await net_response.blob()).type;
    369    assert_true(net_mime_type.includes(expected_mime_type),
    370                'network response should include the expected mime type');
    371 
    372    // Verify we get the exact same mime type when reading the same
    373    // URL resource back out of the cache.
    374    await cache.add(url);
    375    const cache_response = await cache.match(url);
    376    const cache_mime_type = (await cache_response.blob()).type;
    377    assert_equals(cache_mime_type, net_mime_type,
    378                  'network and cache response mime types should match');
    379  }, 'MIME type should be set from content-header correctly.');
    380 
    381 cache_test(async (cache) => {
    382    const url = '/dummy';
    383    const original_type = 'text/html';
    384    const override_type = 'text/plain';
    385    const init_with_headers = {
    386      headers: {
    387        'content-type': original_type
    388      }
    389    }
    390 
    391    // Verify constructing a synthetic response with a content-type header
    392    // gets the correct mime type.
    393    const response = new Response('hello world', init_with_headers);
    394    const original_response_type = (await response.blob()).type;
    395    assert_true(original_response_type.includes(original_type),
    396                'original response should include the expected mime type');
    397 
    398    // Verify overwriting the content-type header changes the mime type.
    399    const overwritten_response = new Response('hello world', init_with_headers);
    400    overwritten_response.headers.set('content-type', override_type);
    401    const overwritten_response_type = (await overwritten_response.blob()).type;
    402    assert_equals(overwritten_response_type, override_type,
    403                  'mime type can be overridden');
    404 
    405    // Verify the Response read from Cache uses the original mime type
    406    // computed when it was first constructed.
    407    const tmp = new Response('hello world', init_with_headers);
    408    tmp.headers.set('content-type', override_type);
    409    await cache.put(url, tmp);
    410    const cache_response = await cache.match(url);
    411    const cache_mime_type = (await cache_response.blob()).type;
    412    assert_equals(cache_mime_type, override_type,
    413                  'overwritten and cached response mime types should match');
    414  }, 'MIME type should reflect Content-Type headers of response.');
    415 
    416 cache_test(async (cache) => {
    417  const url = new URL('./resources/vary.py?vary=foo',
    418      get_host_info().HTTPS_REMOTE_ORIGIN + self.location.pathname);
    419  const original_request = new Request(url, { mode: 'no-cors',
    420                                              headers: { 'foo': 'bar' } });
    421  const fetch_response = await fetch(original_request);
    422  assert_equals(fetch_response.type, 'opaque');
    423 
    424  await cache.put(original_request, fetch_response);
    425 
    426  const match_response_1 = await cache.match(original_request);
    427  assert_not_equals(match_response_1, undefined);
    428 
    429  // Verify that cache.match() finds the entry even if queried with a varied
    430  // header that does not match the cache key.  Vary headers should be ignored
    431  // for opaque responses.
    432  const different_request = new Request(url, { headers: { 'foo': 'CHANGED' } });
    433  const match_response_2 = await cache.match(different_request);
    434  assert_not_equals(match_response_2, undefined);
    435 }, 'Cache.match ignores vary headers on opaque response.');
    436 
    437 done();