| Index: net/http/http_response_headers.cc
|
| diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc
|
| index 3a9f7e04fe0c4bad6a232ae52270e55427532d03..5e0223a4235140333a26d7a6f1616fd08bc820fc 100644
|
| --- a/net/http/http_response_headers.cc
|
| +++ b/net/http/http_response_headers.cc
|
| @@ -956,15 +956,28 @@ bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) {
|
| // Of course, there are other factors that can force a response to always be
|
| // validated or re-fetched.
|
| //
|
| -bool HttpResponseHeaders::RequiresValidation(const Time& request_time,
|
| - const Time& response_time,
|
| - const Time& current_time) const {
|
| - TimeDelta lifetime =
|
| - GetFreshnessLifetime(response_time);
|
| - if (lifetime == TimeDelta())
|
| - return true;
|
| +// From RFC 5861 section 3, a stale response may be used while revalidation is
|
| +// performed in the background if
|
| +//
|
| +// freshness_lifetime + stale_while_revalidate > current_age
|
| +//
|
| +ValidationType HttpResponseHeaders::RequiresValidation(
|
| + const Time& request_time,
|
| + const Time& response_time,
|
| + const Time& current_time) const {
|
| + FreshnessLifetimes lifetimes = GetFreshnessLifetimes(response_time);
|
| + if (lifetimes.fresh == TimeDelta() && lifetimes.stale == TimeDelta())
|
| + return VALIDATION_SYNCHRONOUS;
|
| +
|
| + TimeDelta age = GetCurrentAge(request_time, response_time, current_time);
|
| +
|
| + if (lifetimes.fresh > age)
|
| + return VALIDATION_NONE;
|
| +
|
| + if (lifetimes.fresh + lifetimes.stale > age)
|
| + return VALIDATION_ASYNCHRONOUS;
|
|
|
| - return lifetime <= GetCurrentAge(request_time, response_time, current_time);
|
| + return VALIDATION_SYNCHRONOUS;
|
| }
|
|
|
| // From RFC 2616 section 13.2.4:
|
| @@ -987,25 +1000,35 @@ bool HttpResponseHeaders::RequiresValidation(const Time& request_time,
|
| //
|
| // freshness_lifetime = (date_value - last_modified_value) * 0.10
|
| //
|
| -TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
|
| - const Time& response_time) const {
|
| +// If the stale-while-revalidate directive is present, then it is used to set
|
| +// the |stale| time, unless it overridden by another directive.
|
| +//
|
| +HttpResponseHeaders::FreshnessLifetimes
|
| +HttpResponseHeaders::GetFreshnessLifetimes(const Time& response_time) const {
|
| + FreshnessLifetimes lifetimes;
|
| // Check for headers that force a response to never be fresh. For backwards
|
| // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
|
| // no-cache" even though RFC 2616 does not specify it.
|
| if (HasHeaderValue("cache-control", "no-cache") ||
|
| HasHeaderValue("cache-control", "no-store") ||
|
| HasHeaderValue("pragma", "no-cache") ||
|
| - HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6
|
| - return TimeDelta(); // not fresh
|
| + // Vary: * is never usable: see RFC 2616 section 13.6.
|
| + HasHeaderValue("vary", "*")) {
|
| + return lifetimes;
|
| + }
|
| +
|
| + // Cache-Control directive must_revalidate overrides stale-while-revalidate.
|
| + bool must_revalidate = HasHeaderValue("cache-control", "must-revalidate");
|
| +
|
| + if (must_revalidate || !GetStaleWhileRevalidateValue(&lifetimes.stale))
|
| + DCHECK(lifetimes.stale == TimeDelta());
|
|
|
| // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
|
| - // Expires header after checking for max-age in GetFreshnessLifetime. This
|
| + // Expires header after checking for max-age in GetFreshnessLifetimes. This
|
| // is important since "Expires: <date in the past>" means not fresh, but
|
| // it should not trump a max-age value.
|
| -
|
| - TimeDelta max_age_value;
|
| - if (GetMaxAgeValue(&max_age_value))
|
| - return max_age_value;
|
| + if (GetMaxAgeValue(&lifetimes.fresh))
|
| + return lifetimes;
|
|
|
| // If there is no Date header, then assume that the server response was
|
| // generated at the time when we received the response.
|
| @@ -1016,10 +1039,13 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
|
| Time expires_value;
|
| if (GetExpiresValue(&expires_value)) {
|
| // The expires value can be a date in the past!
|
| - if (expires_value > date_value)
|
| - return expires_value - date_value;
|
| + if (expires_value > date_value) {
|
| + lifetimes.fresh = expires_value - date_value;
|
| + return lifetimes;
|
| + }
|
|
|
| - return TimeDelta(); // not fresh
|
| + DCHECK(lifetimes.fresh == TimeDelta());
|
| + return lifetimes;
|
| }
|
|
|
| // From RFC 2616 section 13.4:
|
| @@ -1047,24 +1073,31 @@ TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
|
| // experimental RFC that adds 308 permanent redirect as well, for which "any
|
| // future references ... SHOULD use one of the returned URIs."
|
| if ((response_code_ == 200 || response_code_ == 203 ||
|
| - response_code_ == 206) &&
|
| - !HasHeaderValue("cache-control", "must-revalidate")) {
|
| + response_code_ == 206) && !must_revalidate) {
|
| // TODO(darin): Implement a smarter heuristic.
|
| Time last_modified_value;
|
| if (GetLastModifiedValue(&last_modified_value)) {
|
| - // The last-modified value can be a date in the past!
|
| - if (last_modified_value <= date_value)
|
| - return (date_value - last_modified_value) / 10;
|
| + // The last-modified value can be a date in the future!
|
| + if (last_modified_value <= date_value) {
|
| + lifetimes.fresh = (date_value - last_modified_value) / 10;
|
| + return lifetimes;
|
| + }
|
| }
|
| }
|
|
|
| // These responses are implicitly fresh (unless otherwise overruled):
|
| if (response_code_ == 300 || response_code_ == 301 || response_code_ == 308 ||
|
| response_code_ == 410) {
|
| - return TimeDelta::Max();
|
| + lifetimes.fresh = TimeDelta::Max();
|
| + lifetimes.stale = TimeDelta(); // It should never be stale.
|
| + return lifetimes;
|
| }
|
|
|
| - return TimeDelta(); // not fresh
|
| + // Our heuristic freshness estimate for this resource is 0 seconds, in
|
| + // accordance with common browser behaviour. However, stale-while-revalidate
|
| + // may still apply.
|
| + DCHECK(lifetimes.fresh == TimeDelta());
|
| + return lifetimes;
|
| }
|
|
|
| // From RFC 2616 section 13.2.3:
|
|
|