Perf: Update size expectations on linux-rel
[chromium-blink-merge.git] / net / quic / quic_in_memory_cache.cc
blob58c6e90f89cd6c1a77f6feb6bc299b9ed8a842ba
1 // Copyright 2014 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 "net/quic/quic_in_memory_cache.h"
7 #include "base/files/file_enumerator.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "net/http/http_util.h"
12 #include "url/gurl.h"
14 using base::FilePath;
15 using base::StringPiece;
16 using std::string;
18 // Specifies the directory used during QuicInMemoryCache
19 // construction to seed the cache. Cache directory can be
20 // generated using `wget -p --save-headers <url>
22 namespace net {
24 FilePath::StringType g_quic_in_memory_cache_dir = FILE_PATH_LITERAL("");
26 QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {
29 QuicInMemoryCache::Response::~Response() {
32 // static
33 QuicInMemoryCache* QuicInMemoryCache::GetInstance() {
34 return Singleton<QuicInMemoryCache>::get();
37 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
38 const GURL& url) const {
39 ResponseMap::const_iterator it = responses_.find(GetKey(url));
40 if (it == responses_.end()) {
41 return NULL;
43 return it->second;
46 void QuicInMemoryCache::AddSimpleResponse(StringPiece path,
47 StringPiece version,
48 StringPiece response_code,
49 StringPiece response_detail,
50 StringPiece body) {
51 GURL url("http://" + path.as_string());
53 string status_line = version.as_string() + " " +
54 response_code.as_string() + " " +
55 response_detail.as_string();
57 string header = "content-length: " +
58 base::Uint64ToString(static_cast<uint64>(body.length()));
60 scoped_refptr<HttpResponseHeaders> response_headers =
61 new HttpResponseHeaders(status_line + '\0' + header + '\0' + '\0');
63 AddResponse(url, response_headers, body);
66 void QuicInMemoryCache::AddResponse(
67 const GURL& url,
68 scoped_refptr<HttpResponseHeaders> response_headers,
69 StringPiece response_body) {
70 string key = GetKey(url);
71 VLOG(1) << "Adding response for: " << key;
72 if (ContainsKey(responses_, key)) {
73 LOG(DFATAL) << "Response for given request already exists!";
74 return;
76 Response* new_response = new Response();
77 new_response->set_headers(response_headers);
78 new_response->set_body(response_body);
79 responses_[key] = new_response;
82 void QuicInMemoryCache::AddSpecialResponse(StringPiece path,
83 SpecialResponseType response_type) {
84 GURL url("http://" + path.as_string());
86 AddResponse(url, NULL, string());
87 responses_[GetKey(url)]->response_type_ = response_type;
90 QuicInMemoryCache::QuicInMemoryCache() {
91 Initialize();
94 void QuicInMemoryCache::ResetForTests() {
95 STLDeleteValues(&responses_);
96 Initialize();
99 void QuicInMemoryCache::Initialize() {
100 // If there's no defined cache dir, we have no initialization to do.
101 if (g_quic_in_memory_cache_dir.size() == 0) {
102 VLOG(1) << "No cache directory found. Skipping initialization.";
103 return;
105 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: "
106 << g_quic_in_memory_cache_dir;
108 FilePath directory(g_quic_in_memory_cache_dir);
109 base::FileEnumerator file_list(directory,
110 true,
111 base::FileEnumerator::FILES);
113 FilePath file = file_list.Next();
114 for (; !file.empty(); file = file_list.Next()) {
115 // Need to skip files in .svn directories
116 if (file.value().find(FILE_PATH_LITERAL("/.svn/")) != string::npos) {
117 continue;
120 string file_contents;
121 base::ReadFileToString(file, &file_contents);
123 if (file_contents.length() > INT_MAX) {
124 LOG(WARNING) << "File '" << file.value() << "' too large: "
125 << file_contents.length();
126 continue;
128 int file_len = static_cast<int>(file_contents.length());
130 int headers_end = HttpUtil::LocateEndOfHeaders(file_contents.data(),
131 file_len);
132 if (headers_end < 1) {
133 LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file.value();
134 continue;
137 string raw_headers =
138 HttpUtil::AssembleRawHeaders(file_contents.data(), headers_end);
140 scoped_refptr<HttpResponseHeaders> response_headers =
141 new HttpResponseHeaders(raw_headers);
143 string base;
144 if (response_headers->GetNormalizedHeader("X-Original-Url", &base)) {
145 response_headers->RemoveHeader("X-Original-Url");
146 // Remove the protocol so we can add it below.
147 if (StartsWithASCII(base, "https://", false)) {
148 base = base.substr(8);
149 } else if (StartsWithASCII(base, "http://", false)) {
150 base = base.substr(7);
152 } else {
153 base = file.AsUTF8Unsafe();
155 if (base.length() == 0 || base[0] == '/') {
156 LOG(DFATAL) << "Invalid path, ignoring: " << base;
157 continue;
159 if (base[base.length() - 1] == ',') {
160 base = base.substr(0, base.length() - 1);
163 GURL url("http://" + base);
165 VLOG(1) << "Inserting '" << GetKey(url) << "' into QuicInMemoryCache.";
167 StringPiece body(file_contents.data() + headers_end,
168 file_contents.size() - headers_end);
170 AddResponse(url, response_headers, body);
174 QuicInMemoryCache::~QuicInMemoryCache() {
175 STLDeleteValues(&responses_);
178 string QuicInMemoryCache::GetKey(const GURL& url) const {
179 // Take everything but the scheme portion of the URL.
180 return url.host() + url.PathForRequest();
183 } // namespace net