Home | History | Annotate | Download | only in media
      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 WebKit::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