Changeset 182059 in webkit


Ignore:
Timestamp:
Mar 27, 2015, 8:13:02 AM (11 years ago)
Author:
Antti Koivisto
Message:

Respect cache-control directives in request
https://bugs.webkit.org/show_bug.cgi?id=143121
Source/WebCore:

rdar://problem/19714040

Reviewed by Chris Dumez.

Test: http/tests/cache/disk-cache/disk-cache-request-headers.html

  • loader/cache/CacheValidation.cpp:

(WebCore::isCacheHeaderSeparator):
(WebCore::isControlCharacter):
(WebCore::trimToNextSeparator):
(WebCore::parseCacheHeader):
(WebCore::parseCacheControlDirectives):

Factor Cache-control parsing here so it can be used for both requests and responses.

  • loader/cache/CacheValidation.h:
  • platform/network/ResourceRequestBase.h:
  • platform/network/ResourceResponseBase.cpp:

(WebCore::ResourceResponseBase::ResourceResponseBase):
(WebCore::ResourceResponseBase::parseCacheControlDirectives):
(WebCore::ResourceResponseBase::cacheControlContainsNoCache):
(WebCore::ResourceResponseBase::cacheControlContainsNoStore):
(WebCore::ResourceResponseBase::cacheControlContainsMustRevalidate):
(WebCore::ResourceResponseBase::cacheControlMaxAge):
(WebCore::isCacheHeaderSeparator): Deleted.
(WebCore::isControlCharacter): Deleted.
(WebCore::trimToNextSeparator): Deleted.
(WebCore::parseCacheHeader): Deleted.

  • platform/network/ResourceResponseBase.h:

Source/WebKit2:

rdar://problem/19714040

Reviewed by Chris Dumez.

Better support for https://tools.ietf.org/html/rfc7234#section-5.2.1

  • NetworkProcess/cache/NetworkCache.cpp:

(WebKit::NetworkCache::canUse):

Consider requests with Cache-control: no-cache and max-age=0 expired.

(WebKit::NetworkCache::canStore):

Don't store requests with Cache-control: no-store.

(WebKit::NetworkCache::Cache::store):

  • NetworkProcess/cache/NetworkCache.h:
  • NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm:

(WebKit::NetworkCache::storeDecisionToDiagnosticKey):

LayoutTests:

Reviewed by Chris Dumez.

  • http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt: Added.
  • http/tests/cache/disk-cache/disk-cache-request-headers.html: Added.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r182058 r182059  
     12015-03-26  Antti Koivisto  <antti@apple.com>
     2
     3        Respect cache-control directives in request
     4        https://bugs.webkit.org/show_bug.cgi?id=143121
     5
     6        Reviewed by Chris Dumez.
     7
     8        * http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt: Added.
     9        * http/tests/cache/disk-cache/disk-cache-request-headers.html: Added.
     10
    1112015-03-27  Michael Saboff  <msaboff@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r182056 r182059  
     12015-03-26  Antti Koivisto  <antti@apple.com>
     2
     3        Respect cache-control directives in request
     4        https://bugs.webkit.org/show_bug.cgi?id=143121
     5        rdar://problem/19714040
     6
     7        Reviewed by Chris Dumez.
     8
     9        Test: http/tests/cache/disk-cache/disk-cache-request-headers.html
     10
     11        * loader/cache/CacheValidation.cpp:
     12        (WebCore::isCacheHeaderSeparator):
     13        (WebCore::isControlCharacter):
     14        (WebCore::trimToNextSeparator):
     15        (WebCore::parseCacheHeader):
     16        (WebCore::parseCacheControlDirectives):
     17
     18            Factor Cache-control parsing here so it can be used for both requests and responses.
     19
     20        * loader/cache/CacheValidation.h:
     21        * platform/network/ResourceRequestBase.h:
     22        * platform/network/ResourceResponseBase.cpp:
     23        (WebCore::ResourceResponseBase::ResourceResponseBase):
     24        (WebCore::ResourceResponseBase::parseCacheControlDirectives):
     25        (WebCore::ResourceResponseBase::cacheControlContainsNoCache):
     26        (WebCore::ResourceResponseBase::cacheControlContainsNoStore):
     27        (WebCore::ResourceResponseBase::cacheControlContainsMustRevalidate):
     28        (WebCore::ResourceResponseBase::cacheControlMaxAge):
     29        (WebCore::isCacheHeaderSeparator): Deleted.
     30        (WebCore::isControlCharacter): Deleted.
     31        (WebCore::trimToNextSeparator): Deleted.
     32        (WebCore::parseCacheHeader): Deleted.
     33        * platform/network/ResourceResponseBase.h:
     34
    1352015-03-27  Víctor Manuel Jáquez Leal  <vjaquez@igalia.com>
    236
  • trunk/Source/WebCore/loader/cache/CacheValidation.cpp

    r178012 r182059  
    2727#include "CacheValidation.h"
    2828
     29#include "HTTPHeaderMap.h"
    2930#include "ResourceResponse.h"
    3031#include <wtf/CurrentTime.h>
     
    150151}
    151152
    152 }
     153inline bool isCacheHeaderSeparator(UChar c)
     154{
     155    // See RFC 2616, Section 2.2
     156    switch (c) {
     157    case '(':
     158    case ')':
     159    case '<':
     160    case '>':
     161    case '@':
     162    case ',':
     163    case ';':
     164    case ':':
     165    case '\\':
     166    case '"':
     167    case '/':
     168    case '[':
     169    case ']':
     170    case '?':
     171    case '=':
     172    case '{':
     173    case '}':
     174    case ' ':
     175    case '\t':
     176        return true;
     177    default:
     178        return false;
     179    }
     180}
     181
     182inline bool isControlCharacter(UChar c)
     183{
     184    return c < ' ' || c == 127;
     185}
     186
     187inline String trimToNextSeparator(const String& str)
     188{
     189    return str.substring(0, str.find(isCacheHeaderSeparator));
     190}
     191
     192static Vector<std::pair<String, String>> parseCacheHeader(const String& header)
     193{
     194    Vector<std::pair<String, String>> result;
     195
     196    const String safeHeader = header.removeCharacters(isControlCharacter);
     197    unsigned max = safeHeader.length();
     198    unsigned pos = 0;
     199    while (pos < max) {
     200        size_t nextCommaPosition = safeHeader.find(',', pos);
     201        size_t nextEqualSignPosition = safeHeader.find('=', pos);
     202        if (nextEqualSignPosition == notFound && nextCommaPosition == notFound) {
     203            // Add last directive to map with empty string as value
     204            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
     205            return result;
     206        }
     207        if (nextCommaPosition != notFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == notFound)) {
     208            // Add directive to map with empty string as value
     209            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
     210            pos += nextCommaPosition - pos + 1;
     211            continue;
     212        }
     213        // Get directive name, parse right hand side of equal sign, then add to map
     214        String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
     215        pos += nextEqualSignPosition - pos + 1;
     216
     217        String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
     218        if (value[0] == '"') {
     219            // The value is a quoted string
     220            size_t nextDoubleQuotePosition = value.find('"', 1);
     221            if (nextDoubleQuotePosition == notFound) {
     222                // Parse error; just use the rest as the value
     223                result.append(std::make_pair(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
     224                return result;
     225            }
     226            // Store the value as a quoted string without quotes
     227            result.append(std::make_pair(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
     228            pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePosition + 1;
     229            // Move past next comma, if there is one
     230            size_t nextCommaPosition2 = safeHeader.find(',', pos);
     231            if (nextCommaPosition2 == notFound)
     232                return result; // Parse error if there is anything left with no comma
     233            pos += nextCommaPosition2 - pos + 1;
     234            continue;
     235        }
     236        // The value is a token until the next comma
     237        size_t nextCommaPosition2 = value.find(',');
     238        if (nextCommaPosition2 == notFound) {
     239            // The rest is the value; no change to value needed
     240            result.append(std::make_pair(directive, trimToNextSeparator(value)));
     241            return result;
     242        }
     243        // The value is delimited by the next comma
     244        result.append(std::make_pair(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
     245        pos += (safeHeader.find(',', pos) - pos) + 1;
     246    }
     247    return result;
     248}
     249
     250CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap& headers)
     251{
     252    CacheControlDirectives result;
     253
     254    String cacheControlValue = headers.get(HTTPHeaderName::CacheControl);
     255    if (!cacheControlValue.isEmpty()) {
     256        auto directives = parseCacheHeader(cacheControlValue);
     257
     258        size_t directivesSize = directives.size();
     259        for (size_t i = 0; i < directivesSize; ++i) {
     260            // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
     261            // It should be ignored by a browser level cache.
     262            if (equalIgnoringCase(directives[i].first, "no-cache") && directives[i].second.isEmpty())
     263                result.noCache = true;
     264            else if (equalIgnoringCase(directives[i].first, "no-store"))
     265                result.noStore = true;
     266            else if (equalIgnoringCase(directives[i].first, "must-revalidate"))
     267                result.mustRevalidate = true;
     268            else if (equalIgnoringCase(directives[i].first, "max-age")) {
     269                if (!std::isnan(result.maxAge)) {
     270                    // First max-age directive wins if there are multiple ones.
     271                    continue;
     272                }
     273                bool ok;
     274                double maxAge = directives[i].second.toDouble(&ok);
     275                if (ok)
     276                    result.maxAge = maxAge;
     277            }
     278        }
     279    }
     280
     281    if (!result.noCache) {
     282        // Handle Pragma: no-cache
     283        // This is deprecated and equivalent to Cache-control: no-cache
     284        // Don't bother tokenizing the value, it is not important
     285        String pragmaValue = headers.get(HTTPHeaderName::Pragma);
     286
     287        result.noCache = pragmaValue.contains("no-cache", false);
     288    }
     289
     290    return result;
     291}
     292
     293}
  • trunk/Source/WebCore/loader/cache/CacheValidation.h

    r179861 r182059  
    2929namespace WebCore {
    3030
     31class HTTPHeaderMap;
    3132class ResourceResponse;
    3233
     
    5354WEBCORE_EXPORT bool redirectChainAllowsReuse(RedirectChainCacheStatus, ReuseExpiredRedirectionOrNot);
    5455
     56struct CacheControlDirectives {
     57    double maxAge { std::numeric_limits<double>::quiet_NaN() };
     58    bool noCache { false };
     59    bool noStore { false };
     60    bool mustRevalidate { false };
     61};
     62WEBCORE_EXPORT CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&);
     63
    5564}
    5665
  • trunk/Source/WebCore/platform/network/ResourceRequestBase.h

    r181136 r182059  
    8080        WEBCORE_EXPORT void setHTTPMethod(const String& httpMethod);
    8181       
    82         const HTTPHeaderMap& httpHeaderFields() const;
     82        WEBCORE_EXPORT const HTTPHeaderMap& httpHeaderFields() const;
    8383        WEBCORE_EXPORT void setHTTPHeaderFields(HTTPHeaderMap);
    8484
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp

    r178019 r182059  
    2828#include "ResourceResponseBase.h"
    2929
     30#include "CacheValidation.h"
    3031#include "HTTPHeaderNames.h"
    3132#include "HTTPParsers.h"
     
    3839namespace WebCore {
    3940
    40 static void parseCacheHeader(const String& header, Vector<std::pair<String, String>>& result);
    41 
    4241inline const ResourceResponse& ResourceResponseBase::asResourceResponse() const
    4342{
     
    4948    , m_includesCertificateInfo(false)
    5049    , m_httpStatusCode(0)
    51     , m_cacheControlMaxAge(0)
    5250    , m_age(0)
    5351    , m_date(0)
     
    6058    , m_haveParsedExpiresHeader(false)
    6159    , m_haveParsedLastModifiedHeader(false)
    62     , m_cacheControlContainsNoCache(false)
    63     , m_cacheControlContainsNoStore(false)
    64     , m_cacheControlContainsMustRevalidate(false)
    6560    , m_source(Source::Unknown)
    6661{
     
    7469    , m_includesCertificateInfo(true) // Empty but valid for synthetic responses.
    7570    , m_httpStatusCode(0)
    76     , m_cacheControlMaxAge(0)
    7771    , m_age(0)
    7872    , m_date(0)
     
    8579    , m_haveParsedExpiresHeader(false)
    8680    , m_haveParsedLastModifiedHeader(false)
    87     , m_cacheControlContainsNoCache(false)
    88     , m_cacheControlContainsNoStore(false)
    89     , m_cacheControlContainsMustRevalidate(false)
    9081    , m_source(Source::Unknown)
    9182{
     
    359350    lazyInit(CommonFieldsOnly);
    360351
     352    m_cacheControlDirectives = WebCore::parseCacheControlDirectives(m_httpHeaderFields);
    361353    m_haveParsedCacheControlHeader = true;
    362 
    363     m_cacheControlContainsMustRevalidate = false;
    364     m_cacheControlContainsNoCache = false;
    365     m_cacheControlMaxAge = std::numeric_limits<double>::quiet_NaN();
    366 
    367     String cacheControlValue = m_httpHeaderFields.get(HTTPHeaderName::CacheControl);
    368     if (!cacheControlValue.isEmpty()) {
    369         Vector<std::pair<String, String>> directives;
    370         parseCacheHeader(cacheControlValue, directives);
    371 
    372         size_t directivesSize = directives.size();
    373         for (size_t i = 0; i < directivesSize; ++i) {
    374             // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
    375             // It should be ignored by a browser level cache.
    376             if (equalIgnoringCase(directives[i].first, "no-cache") && directives[i].second.isEmpty())
    377                 m_cacheControlContainsNoCache = true;
    378             else if (equalIgnoringCase(directives[i].first, "no-store"))
    379                 m_cacheControlContainsNoStore = true;
    380             else if (equalIgnoringCase(directives[i].first, "must-revalidate"))
    381                 m_cacheControlContainsMustRevalidate = true;
    382             else if (equalIgnoringCase(directives[i].first, "max-age")) {
    383                 if (!std::isnan(m_cacheControlMaxAge)) {
    384                     // First max-age directive wins if there are multiple ones.
    385                     continue;
    386                 }
    387                 bool ok;
    388                 double maxAge = directives[i].second.toDouble(&ok);
    389                 if (ok)
    390                     m_cacheControlMaxAge = maxAge;
    391             }
    392         }
    393     }
    394 
    395     if (!m_cacheControlContainsNoCache) {
    396         // Handle Pragma: no-cache
    397         // This is deprecated and equivalent to Cache-control: no-cache
    398         // Don't bother tokenizing the value, it is not important
    399         String pragmaValue = m_httpHeaderFields.get(HTTPHeaderName::Pragma);
    400 
    401         m_cacheControlContainsNoCache = pragmaValue.contains("no-cache", false);
    402     }
    403354}
    404355   
     
    407358    if (!m_haveParsedCacheControlHeader)
    408359        parseCacheControlDirectives();
    409     return m_cacheControlContainsNoCache;
     360    return m_cacheControlDirectives.noCache;
    410361}
    411362
     
    414365    if (!m_haveParsedCacheControlHeader)
    415366        parseCacheControlDirectives();
    416     return m_cacheControlContainsNoStore;
     367    return m_cacheControlDirectives.noStore;
    417368}
    418369
     
    421372    if (!m_haveParsedCacheControlHeader)
    422373        parseCacheControlDirectives();
    423     return m_cacheControlContainsMustRevalidate;
     374    return m_cacheControlDirectives.mustRevalidate;
    424375}
    425376
     
    435386    if (!m_haveParsedCacheControlHeader)
    436387        parseCacheControlDirectives();
    437     return m_cacheControlMaxAge;
     388    return m_cacheControlDirectives.maxAge;
    438389}
    439390
     
    556507}
    557508
    558 static bool isCacheHeaderSeparator(UChar c)
    559 {
    560     // See RFC 2616, Section 2.2
    561     switch (c) {
    562         case '(':
    563         case ')':
    564         case '<':
    565         case '>':
    566         case '@':
    567         case ',':
    568         case ';':
    569         case ':':
    570         case '\\':
    571         case '"':
    572         case '/':
    573         case '[':
    574         case ']':
    575         case '?':
    576         case '=':
    577         case '{':
    578         case '}':
    579         case ' ':
    580         case '\t':
    581             return true;
    582         default:
    583             return false;
    584     }
    585 }
    586 
    587 static bool isControlCharacter(UChar c)
    588 {
    589     return c < ' ' || c == 127;
    590 }
    591 
    592 static inline String trimToNextSeparator(const String& str)
    593 {
    594     return str.substring(0, str.find(isCacheHeaderSeparator));
    595 }
    596 
    597 static void parseCacheHeader(const String& header, Vector<std::pair<String, String>>& result)
    598 {
    599     const String safeHeader = header.removeCharacters(isControlCharacter);
    600     unsigned max = safeHeader.length();
    601     for (unsigned pos = 0; pos < max; /* pos incremented in loop */) {
    602         size_t nextCommaPosition = safeHeader.find(',', pos);
    603         size_t nextEqualSignPosition = safeHeader.find('=', pos);
    604         if (nextEqualSignPosition != notFound && (nextEqualSignPosition < nextCommaPosition || nextCommaPosition == notFound)) {
    605             // Get directive name, parse right hand side of equal sign, then add to map
    606             String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
    607             pos += nextEqualSignPosition - pos + 1;
    608 
    609             String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
    610             if (value[0] == '"') {
    611                 // The value is a quoted string
    612                 size_t nextDoubleQuotePosition = value.find('"', 1);
    613                 if (nextDoubleQuotePosition != notFound) {
    614                     // Store the value as a quoted string without quotes
    615                     result.append(std::pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
    616                     pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePosition + 1;
    617                     // Move past next comma, if there is one
    618                     size_t nextCommaPosition2 = safeHeader.find(',', pos);
    619                     if (nextCommaPosition2 != notFound)
    620                         pos += nextCommaPosition2 - pos + 1;
    621                     else
    622                         return; // Parse error if there is anything left with no comma
    623                 } else {
    624                     // Parse error; just use the rest as the value
    625                     result.append(std::pair<String, String>(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
    626                     return;
    627                 }
    628             } else {
    629                 // The value is a token until the next comma
    630                 size_t nextCommaPosition2 = value.find(',');
    631                 if (nextCommaPosition2 != notFound) {
    632                     // The value is delimited by the next comma
    633                     result.append(std::pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
    634                     pos += (safeHeader.find(',', pos) - pos) + 1;
    635                 } else {
    636                     // The rest is the value; no change to value needed
    637                     result.append(std::pair<String, String>(directive, trimToNextSeparator(value)));
    638                     return;
    639                 }
    640             }
    641         } else if (nextCommaPosition != notFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == notFound)) {
    642             // Add directive to map with empty string as value
    643             result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
    644             pos += nextCommaPosition - pos + 1;
    645         } else {
    646             // Add last directive to map with empty string as value
    647             result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
    648             return;
    649         }
    650     }
    651 }
    652 
    653 }
     509}
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.h

    r179861 r182059  
    2828#define ResourceResponseBase_h
    2929
     30#include "CacheValidation.h"
    3031#include "CertificateInfo.h"
    3132#include "HTTPHeaderMap.h"
     
    161162
    162163private:
    163     mutable double m_cacheControlMaxAge;
    164164    mutable double m_age;
    165165    mutable double m_date;
    166166    mutable double m_expires;
    167167    mutable double m_lastModified;
     168    mutable CacheControlDirectives m_cacheControlDirectives;
    168169
    169170public:
     
    180181    mutable bool m_haveParsedExpiresHeader : 1;
    181182    mutable bool m_haveParsedLastModifiedHeader : 1;
    182 
    183     mutable bool m_cacheControlContainsNoCache : 1;
    184     mutable bool m_cacheControlContainsNoStore : 1;
    185     mutable bool m_cacheControlContainsMustRevalidate : 1;
    186183
    187184    Source m_source;
  • trunk/Source/WebKit2/ChangeLog

    r182049 r182059  
     12015-03-26  Antti Koivisto  <antti@apple.com>
     2
     3        Respect cache-control directives in request
     4        https://bugs.webkit.org/show_bug.cgi?id=143121
     5        rdar://problem/19714040
     6
     7        Reviewed by Chris Dumez.
     8
     9        Better support for https://tools.ietf.org/html/rfc7234#section-5.2.1
     10
     11        * NetworkProcess/cache/NetworkCache.cpp:
     12        (WebKit::NetworkCache::canUse):
     13
     14            Consider requests with Cache-control: no-cache and max-age=0 expired.
     15
     16        (WebKit::NetworkCache::canStore):
     17
     18            Don't store requests with Cache-control: no-store.
     19
     20        (WebKit::NetworkCache::Cache::store):
     21        * NetworkProcess/cache/NetworkCache.h:
     22        * NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm:
     23        (WebKit::NetworkCache::storeDecisionToDiagnosticKey):
     24
    1252015-03-25  Jon Honeycutt  <jhoneycutt@apple.com>
    226
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp

    r182019 r182059  
    151151}
    152152
    153 static inline bool responseHasExpired(const WebCore::ResourceResponse& response, std::chrono::milliseconds timestamp)
     153static bool responseHasExpired(const WebCore::ResourceResponse& response, std::chrono::milliseconds timestamp)
    154154{
    155155    if (response.cacheControlContainsNoCache())
     
    170170}
    171171
     172static bool requestNeedsRevalidation(const WebCore::ResourceRequest& request)
     173{
     174    auto requestDirectives = WebCore::parseCacheControlDirectives(request.httpHeaderFields());
     175    if (requestDirectives.noCache)
     176        return true;
     177    // For requests we ignore max-age values other than zero.
     178    if (requestDirectives.maxAge == 0)
     179        return true;
     180
     181    return false;
     182}
     183
    172184static UseDecision canUse(const Entry& entry, const WebCore::ResourceRequest& request)
    173185{
     
    177189    }
    178190
    179     // We never revalidate in the case of a history navigation (i.e. cachePolicyAllowsExpired() returns true).
    180     bool needsRevalidation = !cachePolicyAllowsExpired(request.cachePolicy()) && responseHasExpired(entry.response(), entry.timeStamp());
     191    // We never revalidate in the case of a history navigation.
     192    if (cachePolicyAllowsExpired(request.cachePolicy()))
     193        return UseDecision::Use;
     194
     195    bool needsRevalidation = requestNeedsRevalidation(request) || responseHasExpired(entry.response(), entry.timeStamp());
    181196    if (!needsRevalidation)
    182197        return UseDecision::Use;
     
    267282static StoreDecision canStore(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response)
    268283{
    269     if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP()) {
    270         LOG(NetworkCache, "(NetworkProcess) not HTTP");
     284    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
    271285        return StoreDecision::NoDueToProtocol;
    272     }
    273     if (originalRequest.httpMethod() != "GET") {
    274         LOG(NetworkCache, "(NetworkProcess) method %s", originalRequest.httpMethod().utf8().data());
     286
     287    if (originalRequest.httpMethod() != "GET")
    275288        return StoreDecision::NoDueToHTTPMethod;
    276     }
     289
     290    auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields());
     291    if (requestDirectives.noStore)
     292        return StoreDecision::NoDueToNoStoreRequest;
     293
     294    if (response.cacheControlContainsNoStore())
     295        return StoreDecision::NoDueToNoStoreResponse;
    277296
    278297    switch (response.httpStatusCode()) {
     
    285304    case 404: // Not Found
    286305    case 410: // Gone
    287         if (response.cacheControlContainsNoStore()) {
    288             LOG(NetworkCache, "(NetworkProcess) Cache-control:no-store");
    289             return StoreDecision::NoDueToNoStoreResponse;
    290         }
    291306        return StoreDecision::Yes;
    292307    default:
     
    306321    StoreDecision storeDecision = canStore(originalRequest, response);
    307322    if (storeDecision != StoreDecision::Yes) {
    308         LOG(NetworkCache, "(NetworkProcess) didn't store");
     323        LOG(NetworkCache, "(NetworkProcess) didn't store, storeDecision=%d", storeDecision);
    309324        if (m_statistics) {
    310325            auto key = makeCacheKey(originalRequest);
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h

    r181970 r182059  
    6969    NoDueToAttachmentResponse,
    7070    NoDueToNoStoreResponse,
    71     NoDueToHTTPStatusCode
     71    NoDueToHTTPStatusCode,
     72    NoDueToNoStoreRequest
    7273};
    7374
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm

    r181970 r182059  
    237237        return WebCore::DiagnosticLoggingKeys::isAttachmentKey();
    238238    case StoreDecision::NoDueToNoStoreResponse:
     239    case StoreDecision::NoDueToNoStoreRequest:
    239240        return WebCore::DiagnosticLoggingKeys::cacheControlNoStoreKey();
    240241    case StoreDecision::NoDueToHTTPStatusCode:
Note: See TracChangeset for help on using the changeset viewer.