• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "media/blink/cache_util.h"
6 
7 #include <string>
8 
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"
17 
18 using base::Time;
19 using base::TimeDelta;
20 using net::HttpVersion;
21 using blink::WebURLResponse;
22 
23 namespace media {
24 
25 enum { kHttpOK = 200, kHttpPartialContent = 206 };
26 
GetReasonsForUncacheability(const WebURLResponse & response)27 uint32 GetReasonsForUncacheability(const WebURLResponse& response) {
28   uint32 reasons = 0;
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) :
35       HttpVersion();
36   if (code != kHttpOK && code != kHttpPartialContent)
37     reasons |= kNoData;
38   if (http_version < HttpVersion(1, 1) && code == kHttpPartialContent)
39     reasons |= kPre11PartialResponse;
40   if (code == kHttpPartialContent &&
41       !net::HttpUtil::HasStrongValidators(
42           http_version,
43           response.httpHeaderField("etag").utf8(),
44           response.httpHeaderField("Last-Modified").utf8(),
45           response.httpHeaderField("Date").utf8())) {
46     reasons |= kNoStrongValidatorOnPartialResponse;
47   }
48 
49   std::string cache_control_header =
50       response.httpHeaderField("cache-control").utf8();
51   base::StringToLowerASCII(&cache_control_header);
52   if (cache_control_header.find("no-cache") != std::string::npos)
53     reasons |= kNoCache;
54   if (cache_control_header.find("no-store") != std::string::npos)
55     reasons |= kNoStore;
56   if (cache_control_header.find("must-revalidate") != std::string::npos)
57     reasons |= kHasMustRevalidate;
58 
59   const TimeDelta kMinimumAgeForUsefulness =
60       TimeDelta::FromSeconds(3600);  // Arbitrary value.
61 
62   const char kMaxAgePrefix[] = "max-age=";
63   const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
64   if (cache_control_header.substr(0, kMaxAgePrefixLen) == kMaxAgePrefix) {
65     int64 max_age_seconds;
66     base::StringToInt64(
67         base::StringPiece(cache_control_header.begin() + kMaxAgePrefixLen,
68                           cache_control_header.end()),
69         &max_age_seconds);
70     if (TimeDelta::FromSeconds(max_age_seconds) < kMinimumAgeForUsefulness)
71       reasons |= kShortMaxAge;
72   }
73 
74   Time date;
75   Time expires;
76   if (Time::FromString(response.httpHeaderField("Date").utf8().data(), &date) &&
77       Time::FromString(response.httpHeaderField("Expires").utf8().data(),
78                        &expires) &&
79       date > Time() && expires > Time() &&
80       (expires - date) < kMinimumAgeForUsefulness) {
81     reasons |= kExpiresTooSoon;
82   }
83 
84   return reasons;
85 }
86 
87 }  // namespace media
88