Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_in_memory_cache.h" | 5 #include "net/tools/quic/quic_in_memory_cache.h" |
| 6 | 6 |
| 7 #include "base/files/file_enumerator.h" | 7 #include "base/files/file_enumerator.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "net/tools/balsa/balsa_frame.h" | 11 #include "net/tools/balsa/balsa_frame.h" |
| 12 #include "net/tools/balsa/balsa_headers.h" | 12 #include "net/tools/balsa/balsa_headers.h" |
| 13 #include "net/tools/balsa/noop_balsa_visitor.h" | 13 #include "net/tools/balsa/noop_balsa_visitor.h" |
| 14 #include "net/tools/quic/spdy_utils.h" | 14 #include "net/tools/quic/spdy_utils.h" |
| 15 | 15 |
| 16 using base::FilePath; | 16 using base::FilePath; |
| 17 using base::StringPiece; | 17 using base::StringPiece; |
| 18 using std::string; | 18 using std::string; |
| 19 | 19 |
| 20 namespace net { | 20 namespace net { |
| 21 namespace tools { | 21 namespace tools { |
| 22 | 22 |
| 23 // Specifies the directory used during QuicInMemoryCache | |
| 24 // construction to seed the cache. Cache directory can be | |
| 25 // generated using `wget -p --save-headers <url> | |
| 26 string FLAGS_quic_in_memory_cache_dir = ""; | |
| 27 | |
| 28 namespace { | 23 namespace { |
| 29 | 24 |
| 30 // BalsaVisitor implementation (glue) which caches response bodies. | 25 // BalsaVisitor implementation (glue) which caches response bodies. |
| 31 class CachingBalsaVisitor : public NoOpBalsaVisitor { | 26 class CachingBalsaVisitor : public NoOpBalsaVisitor { |
| 32 public: | 27 public: |
| 33 CachingBalsaVisitor() : done_framing_(false) {} | 28 CachingBalsaVisitor() : done_framing_(false) {} |
| 34 void ProcessBodyData(const char* input, size_t size) override { | 29 void ProcessBodyData(const char* input, size_t size) override { |
| 35 AppendToBody(input, size); | 30 AppendToBody(input, size); |
| 36 } | 31 } |
| 37 void MessageDone() override { done_framing_ = true; } | 32 void MessageDone() override { done_framing_ = true; } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, | 90 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, |
| 96 response_body); | 91 response_body); |
| 97 } | 92 } |
| 98 | 93 |
| 99 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, | 94 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, |
| 100 StringPiece path, | 95 StringPiece path, |
| 101 SpecialResponseType response_type) { | 96 SpecialResponseType response_type) { |
| 102 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), ""); | 97 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), ""); |
| 103 } | 98 } |
| 104 | 99 |
| 105 QuicInMemoryCache::QuicInMemoryCache() { | 100 QuicInMemoryCache::QuicInMemoryCache() {} |
| 106 Initialize(); | |
| 107 } | |
| 108 | 101 |
| 109 void QuicInMemoryCache::ResetForTests() { | 102 void QuicInMemoryCache::ResetForTests() { |
| 110 STLDeleteValues(&responses_); | 103 STLDeleteValues(&responses_); |
| 111 Initialize(); | |
| 112 } | 104 } |
| 113 | 105 |
| 114 void QuicInMemoryCache::Initialize() { | 106 void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) { |
| 115 // If there's no defined cache dir, we have no initialization to do. | 107 if (cache_directory.empty()) { |
| 116 if (FLAGS_quic_in_memory_cache_dir.empty()) { | 108 LOG(DFATAL) << "cache_directory must not be empty."; |
| 117 VLOG(1) << "No cache directory found. Skipping initialization."; | |
| 118 return; | 109 return; |
| 119 } | 110 } |
| 120 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " | 111 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " |
| 121 << FLAGS_quic_in_memory_cache_dir; | 112 << cache_directory; |
|
ramant (doing other things)
2015/03/24 21:49:36
nit: indentation.
Ryan Hamilton
2015/03/24 22:03:09
Done. (In final CL)
| |
| 122 | 113 FilePath directory(cache_directory); |
| 123 FilePath directory(FLAGS_quic_in_memory_cache_dir); | |
| 124 base::FileEnumerator file_list(directory, | 114 base::FileEnumerator file_list(directory, |
| 125 true, | 115 true, |
| 126 base::FileEnumerator::FILES); | 116 base::FileEnumerator::FILES); |
| 127 | 117 |
| 128 for (FilePath file = file_list.Next(); !file.empty(); | 118 for (FilePath file_iter = file_list.Next(); !file_iter.empty(); |
| 129 file = file_list.Next()) { | 119 file_iter = file_list.Next()) { |
| 120 BalsaHeaders request_headers, response_headers; | |
| 130 // Need to skip files in .svn directories | 121 // Need to skip files in .svn directories |
| 131 if (file.value().find("/.svn/") != string::npos) { | 122 if (file_iter.value().find("/.svn/") != string::npos) { |
| 132 continue; | 123 continue; |
| 133 } | 124 } |
| 134 | 125 |
| 135 BalsaHeaders request_headers, response_headers; | 126 // Tease apart filename into host and path. |
| 127 StringPiece file(file_iter.value()); | |
| 128 file.remove_prefix(cache_directory.length()); | |
| 129 if (file[0] == '/') { | |
| 130 file.remove_prefix(1); | |
| 131 } | |
| 136 | 132 |
| 137 string file_contents; | 133 string file_contents; |
| 138 base::ReadFileToString(file, &file_contents); | 134 base::ReadFileToString(file_iter, &file_contents); |
| 139 | 135 |
| 140 // Frame HTTP. | 136 // Frame HTTP. |
| 141 CachingBalsaVisitor caching_visitor; | 137 CachingBalsaVisitor caching_visitor; |
| 142 BalsaFrame framer; | 138 BalsaFrame framer; |
| 143 framer.set_balsa_headers(&response_headers); | 139 framer.set_balsa_headers(&response_headers); |
| 144 framer.set_balsa_visitor(&caching_visitor); | 140 framer.set_balsa_visitor(&caching_visitor); |
| 145 size_t processed = 0; | 141 size_t processed = 0; |
| 146 while (processed < file_contents.length() && | 142 while (processed < file_contents.length() && |
| 147 !caching_visitor.done_framing()) { | 143 !caching_visitor.done_framing()) { |
| 148 processed += framer.ProcessInput(file_contents.c_str() + processed, | 144 processed += framer.ProcessInput(file_contents.c_str() + processed, |
| 149 file_contents.length() - processed); | 145 file_contents.length() - processed); |
| 150 } | 146 } |
| 151 | 147 |
| 152 if (!caching_visitor.done_framing()) { | 148 if (!caching_visitor.done_framing()) { |
| 153 LOG(DFATAL) << "Did not frame entire message from file: " << file.value() | 149 LOG(DFATAL) << "Did not frame entire message from file: " << file |
| 154 << " (" << processed << " of " << file_contents.length() | 150 << " (" << processed << " of " << file_contents.length() |
| 155 << " bytes)."; | 151 << " bytes)."; |
| 156 } | 152 } |
| 157 if (processed < file_contents.length()) { | 153 if (processed < file_contents.length()) { |
| 158 // Didn't frame whole file. Assume remainder is body. | 154 // Didn't frame whole file. Assume remainder is body. |
| 159 // This sometimes happens as a result of incompatibilities between | 155 // This sometimes happens as a result of incompatibilities between |
| 160 // BalsaFramer and wget's serialization of HTTP sans content-length. | 156 // BalsaFramer and wget's serialization of HTTP sans content-length. |
| 161 caching_visitor.AppendToBody(file_contents.c_str() + processed, | 157 caching_visitor.AppendToBody(file_contents.c_str() + processed, |
| 162 file_contents.length() - processed); | 158 file_contents.length() - processed); |
| 163 processed += file_contents.length(); | 159 processed += file_contents.length(); |
| 164 } | 160 } |
| 165 | 161 |
| 166 StringPiece base = file.value(); | 162 StringPiece base = file; |
| 167 if (response_headers.HasHeader("X-Original-Url")) { | 163 if (response_headers.HasHeader("X-Original-Url")) { |
| 168 base = response_headers.GetHeader("X-Original-Url"); | 164 base = response_headers.GetHeader("X-Original-Url"); |
| 169 response_headers.RemoveAllOfHeader("X-Original-Url"); | 165 response_headers.RemoveAllOfHeader("X-Original-Url"); |
| 170 // Remove the protocol so that the string is of the form host + path, | 166 // Remove the protocol so that the string is of the form host + path, |
| 171 // which is parsed properly below. | 167 // which is parsed properly below. |
| 172 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { | 168 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { |
| 173 base.remove_prefix(8); | 169 base.remove_prefix(8); |
| 174 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { | 170 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { |
| 175 base.remove_prefix(7); | 171 base.remove_prefix(7); |
| 176 } | 172 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 new_response->set_body(response_body); | 206 new_response->set_body(response_body); |
| 211 responses_[key] = new_response; | 207 responses_[key] = new_response; |
| 212 } | 208 } |
| 213 | 209 |
| 214 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { | 210 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { |
| 215 return host.as_string() + path.as_string(); | 211 return host.as_string() + path.as_string(); |
| 216 } | 212 } |
| 217 | 213 |
| 218 } // namespace tools | 214 } // namespace tools |
| 219 } // namespace net | 215 } // namespace net |
| OLD | NEW |