1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/blink/cache_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/time/time.h"
12 #include "net/http/http_util.h"
13 #include "net/http/http_version.h"
14 #include "third_party/WebKit/public/platform/WebCString.h"
15 #include "third_party/WebKit/public/platform/WebString.h"
16 #include "third_party/WebKit/public/platform/WebURLResponse.h"
19 using base::TimeDelta
;
20 using net::HttpVersion
;
21 using blink::WebURLResponse
;
25 enum { kHttpOK
= 200, kHttpPartialContent
= 206 };
27 uint32
GetReasonsForUncacheability(const WebURLResponse
& response
) {
29 const int code
= response
.httpStatusCode();
30 const int version
= response
.httpVersion();
31 const HttpVersion http_version
=
32 version
== WebURLResponse::HTTP_1_1
? HttpVersion(1, 1) :
33 version
== WebURLResponse::HTTP_1_0
? HttpVersion(1, 0) :
34 version
== WebURLResponse::HTTP_0_9
? HttpVersion(0, 9) :
36 if (code
!= kHttpOK
&& code
!= kHttpPartialContent
)
38 if (http_version
< HttpVersion(1, 1) && code
== kHttpPartialContent
)
39 reasons
|= kPre11PartialResponse
;
40 if (code
== kHttpPartialContent
&&
41 !net::HttpUtil::HasStrongValidators(
43 response
.httpHeaderField("etag").utf8(),
44 response
.httpHeaderField("Last-Modified").utf8(),
45 response
.httpHeaderField("Date").utf8())) {
46 reasons
|= kNoStrongValidatorOnPartialResponse
;
49 std::string cache_control_header
=
50 base::ToLowerASCII(response
.httpHeaderField("cache-control").utf8());
51 if (cache_control_header
.find("no-cache") != std::string::npos
)
53 if (cache_control_header
.find("no-store") != std::string::npos
)
55 if (cache_control_header
.find("must-revalidate") != std::string::npos
)
56 reasons
|= kHasMustRevalidate
;
58 const TimeDelta kMinimumAgeForUsefulness
=
59 TimeDelta::FromSeconds(3600); // Arbitrary value.
61 const char kMaxAgePrefix
[] = "max-age=";
62 const size_t kMaxAgePrefixLen
= arraysize(kMaxAgePrefix
) - 1;
63 if (cache_control_header
.substr(0, kMaxAgePrefixLen
) == kMaxAgePrefix
) {
64 int64 max_age_seconds
;
66 base::StringPiece(cache_control_header
.begin() + kMaxAgePrefixLen
,
67 cache_control_header
.end()),
69 if (TimeDelta::FromSeconds(max_age_seconds
) < kMinimumAgeForUsefulness
)
70 reasons
|= kShortMaxAge
;
75 if (Time::FromString(response
.httpHeaderField("Date").utf8().data(), &date
) &&
76 Time::FromString(response
.httpHeaderField("Expires").utf8().data(),
78 date
> Time() && expires
> Time() &&
79 (expires
- date
) < kMinimumAgeForUsefulness
) {
80 reasons
|= kExpiresTooSoon
;