Changeset 173173 in webkit


Ignore:
Timestamp:
Sep 2, 2014 9:00:14 AM (10 years ago)
Author:
commit-queue@webkit.org
Message:

CachedResourceLoader should check redirections to reuse or not cached resources
https://bugs.webkit.org/show_bug.cgi?id=131757

Patch by Youenn Fablet <youenn.fablet@crf.canon.fr> on 2014-09-02
Reviewed by Antti Koivisto.

Source/WebCore:

Added cache-control redirection check to properly determine revalidation policy.
Tightened redirection cache-control header check by testing for no-cache and must-revalidate directives.
Added redirection freshness check.

Test: http/tests/cache/cache-redirections.html

  • loader/cache/CachedRawResource.cpp:

(WebCore::CachedRawResource::canReuse): Removed redirection check (now handled by CachedResource::redirectChainAllowsReuse).

  • loader/cache/CachedResource.cpp:

(WebCore::currentAge): Moved from WebCore::CachedResource::currentAge method to static function. Added response and responseTimestamp as parameters.
(WebCore::CachedResource::CachedResource): Initialized redirection chain status (no redirection and expiracy date set to never).
(WebCore::CachedResource::isExpired): Updated according new currentAge/freshnessLifetime method parameters.
(WebCore::CachedResource::freshnessLifetime): Added response as parameter.
(WebCore::CachedResource::willSendRequest): Computes whether a redirection can be cached, and if cached for how long it will remain fresh.
(WebCore::CachedResource::redirectChainAllowsReuse): Return false if any of the redirection in the redirection chain cannot be cached or expired.

  • loader/cache/CachedResource.h: Added cache chain member that stores whether the redirection chain can be cached and if so when it will be expired.
  • loader/cache/CachedResourceLoader.cpp:

(WebCore::CachedResourceLoader::determineRevalidationPolicy): Added check of the redirection chain.

LayoutTests:

Added test checks that fresh redirections allow reuse of cached resoure and expired or not cacheable redirections trigger reloading of resources.

  • http/tests/cache/cache-redirections-expected.txt: Added.
  • http/tests/cache/cache-redirections.html: Added.
  • http/tests/cache/resources/cache-control-redirect.php: Added.
  • http/tests/cache/resources/cacheable-random-text.php: Added.
Location:
trunk
Files:
4 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r173169 r173173  
     12014-09-02  Youenn Fablet  <youenn.fablet@crf.canon.fr>
     2
     3        CachedResourceLoader should check redirections to reuse or not cached resources
     4        https://bugs.webkit.org/show_bug.cgi?id=131757
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Added test checks that fresh redirections allow reuse of cached resoure and expired or not cacheable redirections trigger reloading of resources.
     9
     10        * http/tests/cache/cache-redirections-expected.txt: Added.
     11        * http/tests/cache/cache-redirections.html: Added.
     12        * http/tests/cache/resources/cache-control-redirect.php: Added.
     13        * http/tests/cache/resources/cacheable-random-text.php: Added.
     14
    1152014-09-02  Manuel Rego Casasnovas  <rego@igalia.com>
    216
  • trunk/Source/WebCore/ChangeLog

    r173172 r173173  
     12014-09-02  Youenn Fablet  <youenn.fablet@crf.canon.fr>
     2
     3        CachedResourceLoader should check redirections to reuse or not cached resources
     4        https://bugs.webkit.org/show_bug.cgi?id=131757
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Added cache-control redirection check to properly determine revalidation policy.
     9        Tightened redirection cache-control header check by testing for no-cache and must-revalidate directives.
     10        Added redirection freshness check.
     11
     12        Test: http/tests/cache/cache-redirections.html
     13
     14        * loader/cache/CachedRawResource.cpp:
     15        (WebCore::CachedRawResource::canReuse): Removed redirection check (now handled by CachedResource::redirectChainAllowsReuse).
     16        * loader/cache/CachedResource.cpp:
     17        (WebCore::currentAge): Moved from WebCore::CachedResource::currentAge method to static function. Added response and responseTimestamp as parameters.
     18        (WebCore::CachedResource::CachedResource): Initialized redirection chain status (no redirection and expiracy date set to never).
     19        (WebCore::CachedResource::isExpired): Updated according new currentAge/freshnessLifetime method parameters.
     20        (WebCore::CachedResource::freshnessLifetime): Added response as parameter.
     21        (WebCore::CachedResource::willSendRequest): Computes whether a redirection can be cached, and if cached for how long it will remain fresh.
     22        (WebCore::CachedResource::redirectChainAllowsReuse): Return false if any of the redirection in the redirection chain cannot be cached or expired.
     23        * loader/cache/CachedResource.h: Added cache chain member that stores whether the redirection chain can be cached and if so when it will be expired.
     24        * loader/cache/CachedResourceLoader.cpp:
     25        (WebCore::CachedResourceLoader::determineRevalidationPolicy): Added check of the redirection chain.
     26
    1272014-09-02  Daewoong Jang  <daewoong.jang@navercorp.com>
    228
  • trunk/Source/WebCore/loader/cache/CachedRawResource.cpp

    r171993 r173173  
    256256    }
    257257
    258     for (size_t i = 0; i < m_redirectChain.size(); i++) {
    259         if (m_redirectChain[i].m_redirectResponse.cacheControlContainsNoStore())
    260             return false;
    261     }
    262 
    263258    return true;
    264259}
  • trunk/Source/WebCore/loader/cache/CachedResource.cpp

    r172946 r173173  
    147147}
    148148
     149static double currentAge(const ResourceResponse& response, double responseTimestamp)
     150{
     151    // RFC2616 13.2.3
     152    // No compensation for latency as that is not terribly important in practice
     153    double dateValue = response.date();
     154    double apparentAge = std::isfinite(dateValue) ? std::max(0., responseTimestamp - dateValue) : 0;
     155    double ageValue = response.age();
     156    double correctedReceivedAge = std::isfinite(ageValue) ? std::max(apparentAge, ageValue) : apparentAge;
     157    double residentTime = currentTime() - responseTimestamp;
     158    return correctedReceivedAge + residentTime;
     159}
     160
    149161DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, cachedResourceLeakCounter, ("CachedResource"));
    150162
     
    181193    , m_resourceToRevalidate(0)
    182194    , m_proxyResource(0)
     195    , m_redirectChainCacheStatus(NoRedirection)
     196    , m_redirectChainEndOfValidity(std::numeric_limits<double>::max())
    183197{
    184198    ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests careless updates of the enum.
     
    387401        return false;
    388402
    389     return currentAge() > freshnessLifetime();
    390 }
    391 
    392 double CachedResource::currentAge() const
    393 {
    394     // RFC2616 13.2.3
    395     // No compensation for latency as that is not terribly important in practice
    396     double dateValue = m_response.date();
    397     double apparentAge = std::isfinite(dateValue) ? std::max(0., m_responseTimestamp - dateValue) : 0;
    398     double ageValue = m_response.age();
    399     double correctedReceivedAge = std::isfinite(ageValue) ? std::max(apparentAge, ageValue) : apparentAge;
    400     double residentTime = currentTime() - m_responseTimestamp;
    401     return correctedReceivedAge + residentTime;
    402 }
    403 
    404 double CachedResource::freshnessLifetime() const
    405 {
    406     if (!m_response.url().protocolIsInHTTPFamily()) {
     403    return currentAge(m_response, m_responseTimestamp) > freshnessLifetime(m_response);
     404}
     405
     406double CachedResource::freshnessLifetime(const ResourceResponse& response) const
     407{
     408    if (!response.url().protocolIsInHTTPFamily()) {
    407409        // Don't cache non-HTTP main resources since we can't check for freshness.
    408410        // FIXME: We should not cache subresources either, but when we tried this
    409411        // it caused performance and flakiness issues in our test infrastructure.
    410         if (m_type == MainResource && !SchemeRegistry::shouldCacheResponsesFromURLSchemeIndefinitely(m_response.url().protocol()))
     412        if (m_type == MainResource && !SchemeRegistry::shouldCacheResponsesFromURLSchemeIndefinitely(response.url().protocol()))
    411413            return 0;
    412414
     
    415417
    416418    // RFC2616 13.2.4
    417     double maxAgeValue = m_response.cacheControlMaxAge();
     419    double maxAgeValue = response.cacheControlMaxAge();
    418420    if (std::isfinite(maxAgeValue))
    419421        return maxAgeValue;
    420     double expiresValue = m_response.expires();
    421     double dateValue = m_response.date();
     422    double expiresValue = response.expires();
     423    double dateValue = response.date();
    422424    double creationTime = std::isfinite(dateValue) ? dateValue : m_responseTimestamp;
    423425    if (std::isfinite(expiresValue))
    424426        return expiresValue - creationTime;
    425     double lastModifiedValue = m_response.lastModified();
     427    double lastModifiedValue = response.lastModified();
    426428    if (std::isfinite(lastModifiedValue))
    427429        return (creationTime - lastModifiedValue) * 0.1;
    428430    // If no cache headers are present, the specification leaves the decision to the UA. Other browsers seem to opt for 0.
    429431    return 0;
     432}
     433
     434void CachedResource::willSendRequest(ResourceRequest&, const ResourceResponse& response)
     435{
     436    m_requestedFromNetworkingLayer = true;
     437    if (response.isNull())
     438        return;
     439    if (m_redirectChainCacheStatus == NotCachedRedirection)
     440        return;
     441    if (response.cacheControlContainsNoStore()
     442        || response.cacheControlContainsNoCache()
     443        || response.cacheControlContainsMustRevalidate())
     444        m_redirectChainCacheStatus = NotCachedRedirection;
     445    else {
     446        m_redirectChainCacheStatus = CachedRedirection;
     447        double responseTimestamp = currentTime();
     448        // Store the nearest end of cache validity date
     449        m_redirectChainEndOfValidity = std::min(m_redirectChainEndOfValidity,
     450            responseTimestamp + freshnessLifetime(response) - currentAge(response, responseTimestamp));
     451    }
    430452}
    431453
     
    784806}
    785807
     808bool CachedResource::redirectChainAllowsReuse() const
     809{
     810    switch (m_redirectChainCacheStatus) {
     811    case NoRedirection:
     812        return true;
     813    case NotCachedRedirection:
     814        return false;
     815    case CachedRedirection:
     816        return currentTime() <= m_redirectChainEndOfValidity;
     817    }
     818    return true;
     819}
     820
    786821unsigned CachedResource::overheadSize() const
    787822{
  • trunk/Source/WebCore/loader/cache/CachedResource.h

    r172814 r173173  
    8989    };
    9090
     91    enum RedirectChainCacheStatus {
     92        NoRedirection,
     93        NotCachedRedirection,
     94        CachedRedirection
     95    };
     96
    9197    CachedResource(const ResourceRequest&, Type, SessionID);
    9298    virtual ~CachedResource();
     
    189195    ResourceBuffer* resourceBuffer() const { return m_data.get(); }
    190196
    191     virtual void willSendRequest(ResourceRequest&, const ResourceResponse&) { m_requestedFromNetworkingLayer = true; }
     197    virtual void willSendRequest(ResourceRequest&, const ResourceResponse&);
    192198    virtual void responseReceived(const ResourceResponse&);
    193199    void setResponse(const ResourceResponse& response) { m_response = response; }
     
    226232
    227233    virtual bool mustRevalidateDueToCacheHeaders(CachePolicy) const;
     234    bool redirectChainAllowsReuse() const;
    228235
    229236    bool isCacheValidator() const { return m_resourceToRevalidate; }
     
    300307    virtual bool mayTryReplaceEncodedData() const { return false; }
    301308
    302     double currentAge() const;
    303     double freshnessLifetime() const;
     309    double freshnessLifetime(const ResourceResponse&) const;
    304310
    305311    void addAdditionalRequestHeaders(CachedResourceLoader*);
     
    356362    // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response.
    357363    HashSet<CachedResourceHandleBase*> m_handlesToRevalidate;
     364
     365    RedirectChainCacheStatus m_redirectChainCacheStatus;
     366    double m_redirectChainEndOfValidity;
    358367};
    359368
  • trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp

    r171708 r173173  
    595595    }
    596596
     597    // Validate the redirect chain
     598    if (!existingResource->redirectChainAllowsReuse()) {
     599        LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to not cached or expired redirections.");
     600        return Reload;
     601    }
     602
    597603    // If credentials were sent with the previous request and won't be
    598604    // with this one, or vice versa, re-fetch the resource.
Note: See TracChangeset for help on using the changeset viewer.