Changeset 207086 in webkit


Ignore:
Timestamp:
Oct 11, 2016 3:53:22 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[Fetch API] Support Request cache mode
https://bugs.webkit.org/show_bug.cgi?id=162281

Patch by Youenn Fablet <youenn@apple.com> on 2016-10-11
Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

  • web-platform-tests/fetch/api/request/request-cache-expected.txt: Rebasing test now that more tests are passing.
  • web-platform-tests/fetch/api/request/request-error-expected.txt:
  • web-platform-tests/fetch/api/request/request-error.html: Adding test to ensure only-if-cached is used with same-origin fetch mode.

Source/WebCore:

Covered by updated test.

Added support for only-if-cached mode at Request level.

Added support for cache mode at CachedResourceLoader, by setting HTTP headers and ResourceRequest cache policy
based on https://fetch.spec.whatwg.org/#concept-request-cache-mode and https://fetch.spec.whatwg.org/#http-network-or-cache-fetch.

Disabled default cache policy computation (done in FrameLoader) when cache mode is different from the default.
Activated no-store cache mode for EventSource as per https://html.spec.whatwg.org/#the-eventsource-interface.

  • Modules/fetch/FetchRequest.cpp:

(WebCore::setCache): Adding support for only-if-cached.
(WebCore::buildOptions): Throw if only-if-cached and fetch mode is not same-origin.

  • loader/FetchOptions.h: Adding support for only-if-cached.
  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::defaultRequestCachingPolicy): Introduced to ease readability.
(WebCore::FrameLoader::addExtraFieldsToRequest): Updating cache policy only if request has the default cache policy.
This allows bypassing the default behavior for fetch cache mode different from "default".

  • loader/FrameLoader.h:
  • loader/cache/CachedResourceLoader.cpp:

(WebCore::updateRequestAccordingCacheMode): Introduced to set headers and request cache policy according fetch cache mode.
(WebCore::CachedResourceLoader::requestResource):
(WebCore::CachedResourceLoader::loadResource):
(WebCore::CachedResourceLoader::determineRevalidationPolicy): Ensure bypassing the memory cache in no-store and reload cases.
We reload in case of cache mode=reload to refresh the meory cache entry.

  • loader/cache/CachedResourceRequest.h:

(WebCore::CachedResourceRequest::setCacheModeToNoStore):

  • page/EventSource.cpp:

(WebCore::EventSource::connect): Use no-store cache mode as per https://html.spec.whatwg.org/#the-eventsource-interface.

  • platform/network/HTTPHeaderMap.cpp:

(WebCore::HTTPHeaderMap::addIfNotPresent): Helper routine.

  • platform/network/HTTPHeaderMap.h:
  • platform/network/HTTPHeaderValues.cpp:
  • platform/network/HTTPHeaderValues.h:
  • platform/network/ResourceRequestBase.cpp:

(WebCore::ResourceRequestBase::addHTTPHeaderFieldIfNotPresent):
(WebCore::ResourceRequestBase::addHTTPHeaderField):
(WebCore::ResourceRequestBase::hasHTTPHeaderField):

  • platform/network/ResourceRequestBase.h:

LayoutTests:

Activating request-cache.html tests for WK1, but not yet for WK2.

  • TestExpectations:
  • platform/mac/TestExpectations:
  • platform/wk2/TestExpectations:
Location:
trunk
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r207058 r207086  
     12016-10-11  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Support Request cache mode
     4        https://bugs.webkit.org/show_bug.cgi?id=162281
     5
     6        Reviewed by Alex Christensen.
     7
     8        Activating request-cache.html tests for WK1, but not yet for WK2.
     9
     10        * TestExpectations:
     11        * platform/mac/TestExpectations:
     12        * platform/wk2/TestExpectations:
     13
    1142016-10-11  Chris Dumez  <cdumez@apple.com>
    215
  • trunk/LayoutTests/TestExpectations

    r207032 r207086  
    282282# Failing assertion with dynamic message
    283283imported/w3c/web-platform-tests/XMLHttpRequest/responsexml-document-properties.htm [ Failure ]
    284 
    285 imported/w3c/web-platform-tests/fetch/api/request/request-cache.html [ Skip ]
    286284
    287285webkit.org/b/161176 [ Debug ] imported/w3c/web-platform-tests/url/url-setters.html [ Skip ]
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r207040 r207086  
     12016-10-11  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Support Request cache mode
     4        https://bugs.webkit.org/show_bug.cgi?id=162281
     5
     6        Reviewed by Alex Christensen.
     7
     8        * web-platform-tests/fetch/api/request/request-cache-expected.txt: Rebasing test now that more tests are passing.
     9        * web-platform-tests/fetch/api/request/request-error-expected.txt:
     10        * web-platform-tests/fetch/api/request/request-error.html: Adding test to ensure only-if-cached is used with same-origin fetch mode.
     11
    1122016-10-10  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-cache-expected.txt

    r205743 r207086  
    66PASS RequestCache "no-cache" mode revalidates stale responses found in the cache with Etag and stale response
    77PASS RequestCache "no-cache" mode revalidates stale responses found in the cache with date and stale response
    8 FAIL RequestCache "no-cache" mode revalidates fresh responses found in the cache with Etag and fresh response assert_equals: expected 2 but got 1
    9 FAIL RequestCache "no-cache" mode revalidates fresh responses found in the cache with date and fresh response assert_equals: expected 2 but got 1
    10 FAIL RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for stale responses with Etag and stale response assert_equals: expected 1 but got 2
    11 FAIL RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for stale responses with date and stale response assert_equals: expected 1 but got 2
     8PASS RequestCache "no-cache" mode revalidates fresh responses found in the cache with Etag and fresh response
     9PASS RequestCache "no-cache" mode revalidates fresh responses found in the cache with date and fresh response
     10PASS RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for stale responses with Etag and stale response
     11PASS RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for stale responses with date and stale response
    1212PASS RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for fresh responses with Etag and fresh response
    1313PASS RequestCache "force-cache" mode checks the cache for previously cached content and avoid revalidation for fresh responses with date and fresh response
     
    2424PASS RequestCache "force-cache" stores the response in the cache if it goes to the network with Etag and fresh response
    2525PASS RequestCache "force-cache" stores the response in the cache if it goes to the network with date and fresh response
    26 FAIL RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for stale responses with Etag and stale response promise_test: Unhandled rejection with value: object "TypeError: Type error"
    27 FAIL RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for stale responses with date and stale response promise_test: Unhandled rejection with value: object "TypeError: Type error"
    28 FAIL RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for fresh responses with Etag and fresh response promise_test: Unhandled rejection with value: object "TypeError: Type error"
    29 FAIL RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for fresh responses with date and fresh response promise_test: Unhandled rejection with value: object "TypeError: Type error"
     26PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for stale responses with Etag and stale response
     27PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for stale responses with date and stale response
     28PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for fresh responses with Etag and fresh response
     29PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for fresh responses with date and fresh response
    3030PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and does not go to the network if a cached response is not found with Etag and fresh response
    3131PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and does not go to the network if a cached response is not found with date and fresh response
     
    3838PASS RequestCache "only-if-cached" (with "same-origin") does not follow redirects across origins and rejects with Etag and stale response
    3939PASS RequestCache "only-if-cached" (with "same-origin") does not follow redirects across origins and rejects with date and stale response
    40 FAIL RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with Etag and stale response assert_equals: expected (undefined) undefined but got (string) "\"0.04196530864700354\""
    41 FAIL RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with date and stale response assert_equals: expected (undefined) undefined but got (string) "Fri, 09 Sep 2016 08:49:10 GMT"
    42 FAIL RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with Etag and fresh response assert_equals: expected 2 but got 1
    43 FAIL RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with date and fresh response assert_equals: expected 2 but got 1
    44 FAIL RequestCache "no-store" mode does not store the response in the cache with Etag and stale response assert_equals: expected (undefined) undefined but got (string) "\"0.12846053184726147\""
    45 FAIL RequestCache "no-store" mode does not store the response in the cache with date and stale response assert_equals: expected (undefined) undefined but got (string) "Fri, 09 Sep 2016 08:49:10 GMT"
    46 FAIL RequestCache "no-store" mode does not store the response in the cache with Etag and fresh response assert_equals: expected 2 but got 1
    47 FAIL RequestCache "no-store" mode does not store the response in the cache with date and fresh response assert_equals: expected 2 but got 1
     40PASS RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with Etag and stale response
     41PASS RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with date and stale response
     42PASS RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with Etag and fresh response
     43PASS RequestCache "no-store" mode does not check the cache for previously cached content and goes to the network regardless with date and fresh response
     44PASS RequestCache "no-store" mode does not store the response in the cache with Etag and stale response
     45PASS RequestCache "no-store" mode does not store the response in the cache with date and stale response
     46PASS RequestCache "no-store" mode does not store the response in the cache with Etag and fresh response
     47PASS RequestCache "no-store" mode does not store the response in the cache with date and fresh response
    4848PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with Etag and stale response
    4949PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with date and stale response
     
    5252PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with Etag and stale response
    5353PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with date and stale response
    54 FAIL RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with Etag and fresh response assert_equals: expected 2 but got 1
     54PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with Etag and fresh response
    5555PASS RequestCache "default" mode with an If-Modified-Since header is treated similarly to "no-store" with date and fresh response
    5656PASS RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with Etag and stale response
     
    6060PASS RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with Etag and stale response
    6161PASS RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with date and stale response
    62 FAIL RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with Etag and fresh response assert_equals: expected 2 but got 1
    63 FAIL RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with date and fresh response assert_equals: expected 2 but got 1
     62PASS RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with Etag and fresh response
     63PASS RequestCache "default" mode with an If-None-Match header is treated similarly to "no-store" with date and fresh response
    6464PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with Etag and stale response
    6565PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with date and stale response
     
    6868PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with Etag and stale response
    6969PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with date and stale response
    70 FAIL RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with Etag and fresh response assert_equals: expected 2 but got 1
    71 FAIL RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with date and fresh response assert_equals: expected 2 but got 1
     70PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with Etag and fresh response
     71PASS RequestCache "default" mode with an If-Unmodified-Since header is treated similarly to "no-store" with date and fresh response
    7272PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with Etag and stale response
    7373PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with date and stale response
     
    7676PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with Etag and stale response
    7777PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with date and stale response
    78 FAIL RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with Etag and fresh response assert_equals: expected 2 but got 1
    79 FAIL RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with date and fresh response assert_equals: expected 2 but got 1
     78PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with Etag and fresh response
     79PASS RequestCache "default" mode with an If-Match header is treated similarly to "no-store" with date and fresh response
    8080PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with Etag and stale response
    8181PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with date and stale response
     
    8484PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with Etag and stale response
    8585PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with date and stale response
    86 FAIL RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with Etag and fresh response assert_equals: expected 2 but got 1
    87 FAIL RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with date and fresh response assert_equals: expected 2 but got 1
     86PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with Etag and fresh response
     87PASS RequestCache "default" mode with an If-Range header is treated similarly to "no-store" with date and fresh response
    8888PASS Responses with the "Cache-Control: no-store" header are not stored in the cache with Etag and stale response
    8989PASS Responses with the "Cache-Control: no-store" header are not stored in the cache with date and stale response
    9090PASS Responses with the "Cache-Control: no-store" header are not stored in the cache with Etag and fresh response
    9191PASS Responses with the "Cache-Control: no-store" header are not stored in the cache with date and fresh response
    92 FAIL RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with Etag and stale response assert_equals: expected (undefined) undefined but got (string) "\"0.7894894845056666\""
    93 FAIL RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with date and stale response assert_equals: expected (undefined) undefined but got (string) "Fri, 09 Sep 2016 08:49:10 GMT"
    94 FAIL RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with Etag and fresh response assert_equals: expected 2 but got 1
    95 FAIL RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with date and fresh response assert_equals: expected 2 but got 1
     92PASS RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with Etag and stale response
     93PASS RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with date and stale response
     94PASS RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with Etag and fresh response
     95PASS RequestCache "reload" mode does not check the cache for previously cached content and goes to the network regardless with date and fresh response
    9696PASS RequestCache "reload" mode does store the response in the cache with Etag and stale response
    9797PASS RequestCache "reload" mode does store the response in the cache with date and stale response
    98 PASS RequestCache "reload" mode does store the response in the cache with Etag and fresh response
    99 PASS RequestCache "reload" mode does store the response in the cache with date and fresh response
    100 FAIL RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with Etag and stale response assert_equals: expected (undefined) undefined but got (string) "\"0.49509960167414313\""
    101 FAIL RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with date and stale response assert_equals: expected (undefined) undefined but got (string) "Fri, 09 Sep 2016 08:49:10 GMT"
    102 FAIL RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with Etag and fresh response assert_equals: expected 2 but got 1
    103 FAIL RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with date and fresh response assert_equals: expected 2 but got 1
     98FAIL RequestCache "reload" mode does store the response in the cache with Etag and fresh response assert_equals: expected 1 but got 2
     99FAIL RequestCache "reload" mode does store the response in the cache with date and fresh response assert_equals: expected 1 but got 2
     100PASS RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with Etag and stale response
     101PASS RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with date and stale response
     102PASS RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with Etag and fresh response
     103PASS RequestCache "reload" mode does store the response in the cache even if a previous response is already stored with date and fresh response
    104104
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-error-expected.txt

    r202471 r207086  
    2020PASS Bad cache init parameter value
    2121PASS Bad redirect init parameter value
     22PASS Request with cache mode: only-if-cached and fetch mode: same-origin
     23PASS Request with cache mode: only-if-cached and fetch mode: cors
     24PASS Request with cache mode: only-if-cached and fetch mode: no-cors
     25PASS Request should not get its content-type from the init request if init headers are provided
    2226
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-error.html

    r202471 r207086  
    106106        },"Bad " + parameter +" init parameter value");
    107107      });
     108
     109      function testOnlyIfCachedMode(fetchMode, ok) {
     110        test(function() {
     111          var options = {"cache": "only-if-cached", "mode": fetchMode};
     112          if (ok)
     113            new Request("test", options);
     114          else
     115            assert_throws(new TypeError(), function() { new Request("test", options); });
     116        }, "Request with cache mode: only-if-cached and fetch mode: " + fetchMode);
     117      }
     118      testOnlyIfCachedMode("same-origin", true);
     119      testOnlyIfCachedMode("cors", false);
     120      testOnlyIfCachedMode("no-cors", false);
     121
     122      test(function() {
     123        var initialHeaders = new Headers([["Content-Type", "potato"]]);
     124        var initialRequest = new Request("", {"headers" : initialHeaders});
     125        var headers = new Headers([]);
     126        var request = new Request(initialRequest, {"headers" : headers});
     127        assert_false(request.headers.has("Content-Type"));
     128      }, "Request should not get its content-type from the init request if init headers are provided");
     129
    108130    </script>
    109131  </body>
  • trunk/LayoutTests/platform/mac/TestExpectations

    r207052 r207086  
    14041404webkit.org/b/151287 [ ElCapitan+ ] media/controls/inline-elements-dropoff-order.html [ Failure ]
    14051405
    1406 webkit.org/b/159683 imported/w3c/web-platform-tests/fetch/api/request/request-cache.html [ Pass Failure ]
    1407 
    14081406webkit.org/b/158500 storage/indexeddb/database-close-private.html [ Pass Failure ]
    14091407
  • trunk/LayoutTests/platform/wk2/TestExpectations

    r206965 r207086  
    685685http/tests/misc/will-send-request-with-client-provided-http-body.html [ Pass ]
    686686
     687# bug 162281
     688imported/w3c/web-platform-tests/fetch/api/request/request-cache.html [ Skip ]
     689
    687690### END OF (5) Progressions, expected successes that are expected failures in WebKit1.
    688691########################################
  • trunk/Source/WebCore/ChangeLog

    r207077 r207086  
     12016-10-11  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Support Request cache mode
     4        https://bugs.webkit.org/show_bug.cgi?id=162281
     5
     6        Reviewed by Alex Christensen.
     7
     8        Covered by updated test.
     9
     10        Added support for only-if-cached mode at Request level.
     11
     12        Added support for cache mode at CachedResourceLoader, by setting HTTP headers and ResourceRequest cache policy
     13        based on https://fetch.spec.whatwg.org/#concept-request-cache-mode and https://fetch.spec.whatwg.org/#http-network-or-cache-fetch.
     14
     15        Disabled default cache policy computation (done in FrameLoader) when cache mode is different from the default.
     16        Activated no-store cache mode for EventSource as per https://html.spec.whatwg.org/#the-eventsource-interface.
     17
     18        * Modules/fetch/FetchRequest.cpp:
     19        (WebCore::setCache): Adding support for only-if-cached.
     20        (WebCore::buildOptions): Throw if only-if-cached and fetch mode is not same-origin.
     21        * loader/FetchOptions.h: Adding support for only-if-cached.
     22        * loader/FrameLoader.cpp:
     23        (WebCore::FrameLoader::defaultRequestCachingPolicy): Introduced to ease readability.
     24        (WebCore::FrameLoader::addExtraFieldsToRequest): Updating cache policy only if request has the default cache policy.
     25        This allows bypassing the default behavior for fetch cache mode different from "default".
     26        * loader/FrameLoader.h:
     27        * loader/cache/CachedResourceLoader.cpp:
     28        (WebCore::updateRequestAccordingCacheMode): Introduced to set headers and request cache policy according fetch cache mode.
     29        (WebCore::CachedResourceLoader::requestResource):
     30        (WebCore::CachedResourceLoader::loadResource):
     31        (WebCore::CachedResourceLoader::determineRevalidationPolicy): Ensure bypassing the memory cache in no-store and reload cases.
     32        We reload in case of cache mode=reload to refresh the meory cache entry.
     33        * loader/cache/CachedResourceRequest.h:
     34        (WebCore::CachedResourceRequest::setCacheModeToNoStore):
     35        * page/EventSource.cpp:
     36        (WebCore::EventSource::connect): Use no-store cache mode as per https://html.spec.whatwg.org/#the-eventsource-interface.
     37        * platform/network/HTTPHeaderMap.cpp:
     38        (WebCore::HTTPHeaderMap::addIfNotPresent): Helper routine.
     39        * platform/network/HTTPHeaderMap.h:
     40        * platform/network/HTTPHeaderValues.cpp:
     41        * platform/network/HTTPHeaderValues.h:
     42        * platform/network/ResourceRequestBase.cpp:
     43        (WebCore::ResourceRequestBase::addHTTPHeaderFieldIfNotPresent):
     44        (WebCore::ResourceRequestBase::addHTTPHeaderField):
     45        (WebCore::ResourceRequestBase::hasHTTPHeaderField):
     46        * platform/network/ResourceRequestBase.h:
     47
    1482016-10-10  Antti Koivisto  <antti@apple.com>
    249
  • trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp

    r207037 r207086  
    9999    else if (cache == "force-cache")
    100100        options.cache = FetchOptions::Cache::ForceCache;
     101    else if (cache == "only-if-cached")
     102        options.cache = FetchOptions::Cache::OnlyIfCached;
    101103    else
    102104        return Exception { TypeError, ASCIILiteral("Bad cache mode value.") };
     
    195197            return exception;
    196198    }
     199
     200    if (request.options.cache == FetchOptions::Cache::OnlyIfCached && request.options.mode != FetchOptions::Mode::SameOrigin)
     201        return Exception { TypeError, ASCIILiteral("only-if-cached cache option requires fetch mode to be same-origin.")  };
    197202
    198203    if (init.get("redirect", value)) {
  • trunk/Source/WebCore/loader/FetchOptions.h

    r202323 r207086  
    4444    Credentials credentials { Credentials::Omit };
    4545
    46     enum class Cache { Default, NoStore, Reload, NoCache, ForceCache };
     46    enum class Cache { Default, NoStore, Reload, NoCache, ForceCache, OnlyIfCached };
    4747    Cache cache { Cache::Default };
    4848
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r206869 r207086  
    25632563}
    25642564
    2565 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource)
    2566 {
    2567     Page* page = frame().page();
    2568     bool cachingDisabled = page && page->isResourceCachingDisabled();
    2569 
    2570     if (cachingDisabled)
    2571         request.setCachePolicy(ReloadIgnoringCacheData);
    2572 
    2573     // Don't set the cookie policy URL if it's already been set.
    2574     // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
    2575     if (request.firstPartyForCookies().isEmpty()) {
    2576         if (mainResource && m_frame.isMainFrame())
    2577             request.setFirstPartyForCookies(request.url());
    2578         else if (Document* document = m_frame.document())
    2579             request.setFirstPartyForCookies(document->firstPartyForCookies());
    2580     }
    2581 
    2582     // The remaining modifications are only necessary for HTTP and HTTPS.
    2583     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
    2584         return;
    2585 
    2586     applyUserAgent(request);
    2587 
    2588     if (cachingDisabled) {
    2589         // Cache policy was already set above in the non-HTTP-specific code.
    2590         loadType = FrameLoadType::ReloadFromOrigin;
    2591     } else if (!mainResource) {
     2565ResourceRequestCachePolicy FrameLoader::defaultRequestCachingPolicy(const ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
     2566{
     2567    if (m_overrideCachePolicyForTesting)
     2568        return m_overrideCachePolicyForTesting.value();
     2569    if (!isMainResource) {
    25922570        if (request.isConditional())
    2593             request.setCachePolicy(ReloadIgnoringCacheData);
    2594         else if (documentLoader()->isLoadingInAPISense()) {
     2571            return ReloadIgnoringCacheData;
     2572        if (documentLoader()->isLoadingInAPISense()) {
    25952573            // If we inherit cache policy from a main resource, we use the DocumentLoader's
    25962574            // original request cache policy for two reasons:
     
    26032581            // Back-forward navigations try to load main resource from cache only to avoid re-submitting form data, and start over (with a warning dialog) if that fails.
    26042582            // This policy is set on initial request too, but should not be inherited.
    2605             ResourceRequestCachePolicy subresourceCachePolicy = (mainDocumentOriginalCachePolicy == ReturnCacheDataDontLoad) ? ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
    2606             request.setCachePolicy(subresourceCachePolicy);
    2607         } else
    2608             request.setCachePolicy(UseProtocolCachePolicy);
    2609 
     2583            return (mainDocumentOriginalCachePolicy == ReturnCacheDataDontLoad) ? ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
     2584        }
    26102585    // FIXME: Other FrameLoader functions have duplicated code for setting cache policy of main request when reloading.
    26112586    // It seems better to manage it explicitly than to hide the logic inside addExtraFieldsToRequest().
    26122587    } else if (loadType == FrameLoadType::Reload || loadType == FrameLoadType::ReloadFromOrigin || request.isConditional())
     2588        return ReloadIgnoringCacheData;
     2589
     2590    return UseProtocolCachePolicy;
     2591}
     2592
     2593void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
     2594{
     2595    // Don't set the cookie policy URL if it's already been set.
     2596    // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
     2597    if (request.firstPartyForCookies().isEmpty()) {
     2598        if (isMainResource && m_frame.isMainFrame())
     2599            request.setFirstPartyForCookies(request.url());
     2600        else if (Document* document = m_frame.document())
     2601            request.setFirstPartyForCookies(document->firstPartyForCookies());
     2602    }
     2603
     2604    Page* page = frame().page();
     2605    bool hasSpecificCachePolicy = request.cachePolicy() != UseProtocolCachePolicy;
     2606
     2607    if (page && page->isResourceCachingDisabled()) {
    26132608        request.setCachePolicy(ReloadIgnoringCacheData);
    2614 
    2615     if (m_overrideCachePolicyForTesting)
    2616         request.setCachePolicy(m_overrideCachePolicyForTesting.value());
    2617     if (m_overrideResourceLoadPriorityForTesting)
    2618         request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
    2619 
    2620     if (request.cachePolicy() == ReloadIgnoringCacheData) {
     2609        loadType = FrameLoadType::ReloadFromOrigin;
     2610    } else if (!hasSpecificCachePolicy)
     2611        request.setCachePolicy(defaultRequestCachingPolicy(request, loadType, isMainResource));
     2612
     2613    // The remaining modifications are only necessary for HTTP and HTTPS.
     2614    if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
     2615        return;
     2616
     2617    if (!hasSpecificCachePolicy && request.cachePolicy() == ReloadIgnoringCacheData) {
    26212618        if (loadType == FrameLoadType::Reload)
    26222619            request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
     
    26272624    }
    26282625
    2629     if (mainResource)
     2626    if (m_overrideResourceLoadPriorityForTesting)
     2627        request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
     2628
     2629    applyUserAgent(request);
     2630
     2631    if (isMainResource)
    26302632        request.setHTTPAccept(defaultAcceptHeader);
    26312633
  • trunk/Source/WebCore/loader/FrameLoader.h

    r206132 r207086  
    312312
    313313    void checkTimerFired();
    314    
     314
    315315    void loadSameDocumentItem(HistoryItem&);
    316316    void loadDifferentDocumentItem(HistoryItem&, FrameLoadType, FormSubmissionCacheLoadPolicy);
    317    
     317
    318318    void loadProvisionalItemFromCachedPage();
    319319
    320320    void updateFirstPartyForCookies();
    321321    void setFirstPartyForCookies(const URL&);
    322    
     322
    323323    void addExtraFieldsToRequest(ResourceRequest&, FrameLoadType, bool isMainResource);
     324    ResourceRequestCachePolicy defaultRequestCachingPolicy(const ResourceRequest&, FrameLoadType, bool isMainResource);
    324325
    325326    void clearProvisionalLoad();
  • trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp

    r206994 r207086  
    5252#include "HTMLElement.h"
    5353#include "HTMLFrameOwnerElement.h"
     54#include "HTTPHeaderValues.h"
    5455#include "LoaderStrategy.h"
    5556#include "LocalizedStrings.h"
     
    662663    // Accept-Language value is handled in underlying port-specific code.
    663664    // FIXME: Decide whether to support client hints
     665}
     666
     667static inline void updateRequestAccordingCacheMode(CachedResourceRequest& request)
     668{
     669    if (request.options().cache == FetchOptions::Cache::Default
     670            && (request.resourceRequest().hasHTTPHeaderField(HTTPHeaderName::IfModifiedSince)
     671                || request.resourceRequest().hasHTTPHeaderField(HTTPHeaderName::IfNoneMatch)
     672                || request.resourceRequest().hasHTTPHeaderField(HTTPHeaderName::IfUnmodifiedSince)
     673                || request.resourceRequest().hasHTTPHeaderField(HTTPHeaderName::IfMatch)
     674                || request.resourceRequest().hasHTTPHeaderField(HTTPHeaderName::IfRange)))
     675        request.setCacheModeToNoStore();
     676
     677    switch (request.options().cache) {
     678    case FetchOptions::Cache::NoCache:
     679        request.mutableResourceRequest().setCachePolicy(ReloadIgnoringCacheData);
     680        request.mutableResourceRequest().addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::maxAge0());
     681        break;
     682    case FetchOptions::Cache::NoStore:
     683        request.setCachingPolicy(CachingPolicy::DisallowCaching);
     684        request.mutableResourceRequest().setCachePolicy(ReloadIgnoringCacheData);
     685        request.mutableResourceRequest().addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
     686        request.mutableResourceRequest().addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
     687        break;
     688    case FetchOptions::Cache::Reload:
     689        request.mutableResourceRequest().setCachePolicy(ReloadIgnoringCacheData);
     690        request.mutableResourceRequest().addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
     691        request.mutableResourceRequest().addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
     692        break;
     693    case FetchOptions::Cache::Default:
     694        break;
     695    case FetchOptions::Cache::ForceCache:
     696        request.mutableResourceRequest().setCachePolicy(ReturnCacheDataElseLoad);
     697        break;
     698    case FetchOptions::Cache::OnlyIfCached:
     699        request.mutableResourceRequest().setCachePolicy(ReturnCacheDataDontLoad);
     700        break;
     701    }
     702}
     703
     704void CachedResourceLoader::updateHTTPRequestHeaders(CachedResourceRequest& resourceRequest)
     705{
     706    // Implementing steps 10 to 12 of https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
     707    updateRequestAccordingCacheMode(resourceRequest);
    664708}
    665709
     
    721765#endif
    722766
     767    if (request.resourceRequest().url().protocolIsInHTTPFamily())
     768        updateHTTPRequestHeaders(request);
     769
    723770    auto& memoryCache = MemoryCache::singleton();
    724771    if (request.allowsCaching() && memoryCache.disabled()) {
     
    845892{
    846893    auto& memoryCache = MemoryCache::singleton();
    847     ASSERT(!request.allowsCaching() || !memoryCache.resourceForRequest(request.resourceRequest(), sessionID()));
     894    ASSERT(!request.allowsCaching() || !memoryCache.resourceForRequest(request.resourceRequest(), sessionID())
     895        || request.options().cache == FetchOptions::Cache::NoCache || request.options().cache == FetchOptions::Cache::NoStore || request.options().cache == FetchOptions::Cache::Reload);
    848896
    849897    LOG(ResourceLoading, "Loading CachedResource for '%s'.", request.resourceRequest().url().stringCenterEllipsizedToLength().latin1().data());
     
    897945    if (!existingResource)
    898946        return Load;
     947
     948    if (cachedResourceRequest.options().cache == FetchOptions::Cache::NoStore)
     949        return Load;
     950
     951    if (cachedResourceRequest.options().cache == FetchOptions::Cache::Reload)
     952        return Reload;
    899953
    900954    // We already have a preload going for this URL.
     
    932986        return Reload;
    933987
    934     // Don't reload resources while pasting.
    935     if (m_allowStaleResources)
     988    // Don't reload resources while pasting or if cache mode allows stale resources.
     989    if (m_allowStaleResources || cachedResourceRequest.options().cache == FetchOptions::Cache::ForceCache || cachedResourceRequest.options().cache == FetchOptions::Cache::OnlyIfCached)
    936990        return Use;
     991
     992    ASSERT(cachedResourceRequest.options().cache == FetchOptions::Cache::Default || cachedResourceRequest.options().cache == FetchOptions::Cache::NoCache);
    937993
    938994    // Always use preloads.
  • trunk/Source/WebCore/loader/cache/CachedResourceLoader.h

    r206900 r207086  
    155155    enum class DeferOption { NoDefer, DeferredByClient };
    156156
     157    void updateHTTPRequestHeaders(CachedResourceRequest&);
    157158    CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, CachedResourceRequest&&, ForPreload = ForPreload::No, DeferOption = DeferOption::NoDefer);
    158159    void prepareFetch(CachedResource::Type, CachedResourceRequest&);
  • trunk/Source/WebCore/loader/cache/CachedResourceRequest.h

    r207053 r207086  
    6161    SecurityOrigin* origin() const { return m_origin.get(); }
    6262
     63    void setCacheModeToNoStore() { m_options.cache = FetchOptions::Cache::NoStore; }
     64
    6365private:
    6466    ResourceRequest m_resourceRequest;
  • trunk/Source/WebCore/page/EventSource.cpp

    r206254 r207086  
    109109    options.preflightPolicy = PreventPreflight;
    110110    options.mode = FetchOptions::Mode::Cors;
     111    options.cache = FetchOptions::Cache::NoStore;
    111112    options.dataBufferingPolicy = DoNotBufferData;
    112113    options.contentSecurityPolicyEnforcement = scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy() ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceConnectSrcDirective;
  • trunk/Source/WebCore/platform/network/HTTPHeaderMap.cpp

    r206096 r207086  
    104104}
    105105
     106bool HTTPHeaderMap::addIfNotPresent(HTTPHeaderName headerName, const String& value)
     107{
     108    return m_commonHeaders.add(headerName, value).isNewEntry;
     109}
     110
    106111bool HTTPHeaderMap::contains(const String& name) const
    107112{
  • trunk/Source/WebCore/platform/network/HTTPHeaderMap.h

    r202153 r207086  
    142142    void set(HTTPHeaderName, const String& value);
    143143    void add(HTTPHeaderName, const String& value);
     144    bool addIfNotPresent(HTTPHeaderName, const String&);
    144145    bool contains(HTTPHeaderName) const;
    145146    WEBCORE_EXPORT bool remove(HTTPHeaderName);
  • trunk/Source/WebCore/platform/network/HTTPHeaderValues.cpp

    r207046 r207086  
    4545}
    4646
     47const String& noCache()
     48{
     49    static NeverDestroyed<const String> value(ASCIILiteral("no-cache"));
     50    return value;
     51}
     52
     53const String& maxAge0()
     54{
     55    static NeverDestroyed<const String> value(ASCIILiteral("max-age=0"));
     56    return value;
    4757}
    4858
    4959}
     60
     61}
  • trunk/Source/WebCore/platform/network/HTTPHeaderValues.h

    r207046 r207086  
    3333const String& textPlainContentType();
    3434const String& formURLEncodedContentType();
    35 
     35const String& noCache();
     36const String& maxAge0();
    3637}
    3738
  • trunk/Source/WebCore/platform/network/ResourceRequestBase.cpp

    r206206 r207086  
    465465}
    466466
     467void ResourceRequestBase::addHTTPHeaderFieldIfNotPresent(HTTPHeaderName name, const String& value)
     468{
     469    updateResourceRequest();
     470
     471    if (!m_httpHeaderFields.addIfNotPresent(name, value))
     472        return;
     473
     474    if (url().protocolIsInHTTPFamily())
     475        m_platformRequestUpdated = false;
     476}
     477
    467478void ResourceRequestBase::addHTTPHeaderField(HTTPHeaderName name, const String& value)
    468479{
     
    478489{
    479490    updateResourceRequest();
    480    
     491
    481492    m_httpHeaderFields.add(name, value);
    482    
    483     if (url().protocolIsInHTTPFamily())
    484         m_platformRequestUpdated = false;
    485 }
    486    
     493
     494    if (url().protocolIsInHTTPFamily())
     495        m_platformRequestUpdated = false;
     496}
     497
     498bool ResourceRequestBase::hasHTTPHeaderField(HTTPHeaderName headerName) const
     499{
     500    return m_httpHeaderFields.contains(headerName);
     501}
     502
    487503void ResourceRequestBase::setHTTPHeaderFields(HTTPHeaderMap headerFields)
    488504{
  • trunk/Source/WebCore/platform/network/ResourceRequestBase.h

    r206206 r207086  
    8686    void addHTTPHeaderField(HTTPHeaderName, const String& value);
    8787    void addHTTPHeaderField(const String& name, const String& value);
     88    void addHTTPHeaderFieldIfNotPresent(HTTPHeaderName, const String&);
     89
     90    bool hasHTTPHeaderField(HTTPHeaderName) const;
    8891
    8992    // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
Note: See TracChangeset for help on using the changeset viewer.