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 "content/renderer/media/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 content { 24 25 enum { kHttpOK = 200, kHttpPartialContent = 206 }; 26 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 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 content 88