| 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_http_response_cache.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/files/file_enumerator.h" | 9 #include "base/files/file_enumerator.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "net/http/http_util.h" | 16 #include "net/http/http_util.h" |
| 17 #include "net/quic/core/quic_bug_tracker.h" | 17 #include "net/quic/core/quic_bug_tracker.h" |
| 18 #include "net/spdy/spdy_http_utils.h" | 18 #include "net/spdy/spdy_http_utils.h" |
| 19 | 19 |
| 20 using base::FilePath; | 20 using base::FilePath; |
| 21 using base::IntToString; | 21 using base::IntToString; |
| 22 using base::StringPiece; | 22 using base::StringPiece; |
| 23 using std::string; | 23 using std::string; |
| 24 | 24 |
| 25 namespace net { | 25 namespace net { |
| 26 | 26 |
| 27 QuicInMemoryCache::ServerPushInfo::ServerPushInfo(GURL request_url, | 27 QuicHttpResponseCache::ServerPushInfo::ServerPushInfo( |
| 28 SpdyHeaderBlock headers, | 28 GURL request_url, |
| 29 net::SpdyPriority priority, | 29 SpdyHeaderBlock headers, |
| 30 string body) | 30 net::SpdyPriority priority, |
| 31 string body) |
| 31 : request_url(request_url), | 32 : request_url(request_url), |
| 32 headers(std::move(headers)), | 33 headers(std::move(headers)), |
| 33 priority(priority), | 34 priority(priority), |
| 34 body(body) {} | 35 body(body) {} |
| 35 | 36 |
| 36 QuicInMemoryCache::ServerPushInfo::ServerPushInfo(const ServerPushInfo& other) | 37 QuicHttpResponseCache::ServerPushInfo::ServerPushInfo( |
| 38 const ServerPushInfo& other) |
| 37 : request_url(other.request_url), | 39 : request_url(other.request_url), |
| 38 headers(other.headers.Clone()), | 40 headers(other.headers.Clone()), |
| 39 priority(other.priority), | 41 priority(other.priority), |
| 40 body(other.body) {} | 42 body(other.body) {} |
| 41 | 43 |
| 42 QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {} | 44 QuicHttpResponseCache::Response::Response() |
| 45 : response_type_(REGULAR_RESPONSE) {} |
| 43 | 46 |
| 44 QuicInMemoryCache::Response::~Response() {} | 47 QuicHttpResponseCache::Response::~Response() {} |
| 45 | 48 |
| 46 void QuicInMemoryCache::ResourceFile::Read() { | 49 void QuicHttpResponseCache::ResourceFile::Read() { |
| 47 base::ReadFileToString(FilePath(file_name_), &file_contents_); | 50 base::ReadFileToString(FilePath(file_name_), &file_contents_); |
| 48 | 51 |
| 49 // First read the headers. | 52 // First read the headers. |
| 50 size_t start = 0; | 53 size_t start = 0; |
| 51 while (start < file_contents_.length()) { | 54 while (start < file_contents_.length()) { |
| 52 size_t pos = file_contents_.find("\n", start); | 55 size_t pos = file_contents_.find("\n", start); |
| 53 if (pos == string::npos) { | 56 if (pos == string::npos) { |
| 54 LOG(DFATAL) << "Headers invalid or empty, ignoring: " | 57 LOG(DFATAL) << "Headers invalid or empty, ignoring: " |
| 55 << file_name_.value(); | 58 << file_name_.value(); |
| 56 return; | 59 return; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 } | 117 } |
| 115 push_urls_.push_back(StringPiece(push_urls.data() + start, pos)); | 118 push_urls_.push_back(StringPiece(push_urls.data() + start, pos)); |
| 116 start += pos + 1; | 119 start += pos + 1; |
| 117 } | 120 } |
| 118 } | 121 } |
| 119 | 122 |
| 120 body_ = | 123 body_ = |
| 121 StringPiece(file_contents_.data() + start, file_contents_.size() - start); | 124 StringPiece(file_contents_.data() + start, file_contents_.size() - start); |
| 122 } | 125 } |
| 123 | 126 |
| 124 QuicInMemoryCache::ResourceFile::ResourceFile(const base::FilePath& file_name) | 127 QuicHttpResponseCache::ResourceFile::ResourceFile( |
| 128 const base::FilePath& file_name) |
| 125 : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {} | 129 : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {} |
| 126 | 130 |
| 127 QuicInMemoryCache::ResourceFile::~ResourceFile() {} | 131 QuicHttpResponseCache::ResourceFile::~ResourceFile() {} |
| 128 | 132 |
| 129 void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) { | 133 void QuicHttpResponseCache::ResourceFile::SetHostPathFromBase( |
| 134 StringPiece base) { |
| 130 size_t path_start = base.find_first_of('/'); | 135 size_t path_start = base.find_first_of('/'); |
| 131 DCHECK_LT(0UL, path_start); | 136 DCHECK_LT(0UL, path_start); |
| 132 host_ = base.substr(0, path_start); | 137 host_ = base.substr(0, path_start); |
| 133 size_t query_start = base.find_first_of(','); | 138 size_t query_start = base.find_first_of(','); |
| 134 if (query_start > 0) { | 139 if (query_start > 0) { |
| 135 path_ = base.substr(path_start, query_start - 1); | 140 path_ = base.substr(path_start, query_start - 1); |
| 136 } else { | 141 } else { |
| 137 path_ = base.substr(path_start); | 142 path_ = base.substr(path_start); |
| 138 } | 143 } |
| 139 } | 144 } |
| 140 | 145 |
| 141 StringPiece QuicInMemoryCache::ResourceFile::RemoveScheme(StringPiece url) { | 146 StringPiece QuicHttpResponseCache::ResourceFile::RemoveScheme(StringPiece url) { |
| 142 if (base::StartsWith(url, "https://", base::CompareCase::INSENSITIVE_ASCII)) { | 147 if (base::StartsWith(url, "https://", base::CompareCase::INSENSITIVE_ASCII)) { |
| 143 url.remove_prefix(8); | 148 url.remove_prefix(8); |
| 144 } else if (base::StartsWith(url, "http://", | 149 } else if (base::StartsWith(url, "http://", |
| 145 base::CompareCase::INSENSITIVE_ASCII)) { | 150 base::CompareCase::INSENSITIVE_ASCII)) { |
| 146 url.remove_prefix(7); | 151 url.remove_prefix(7); |
| 147 } | 152 } |
| 148 return url; | 153 return url; |
| 149 } | 154 } |
| 150 | 155 |
| 151 void QuicInMemoryCache::ResourceFile::HandleXOriginalUrl() { | 156 void QuicHttpResponseCache::ResourceFile::HandleXOriginalUrl() { |
| 152 StringPiece url(x_original_url_); | 157 StringPiece url(x_original_url_); |
| 153 // Remove the protocol so we can add it below. | 158 // Remove the protocol so we can add it below. |
| 154 url = RemoveScheme(url); | 159 url = RemoveScheme(url); |
| 155 SetHostPathFromBase(url); | 160 SetHostPathFromBase(url); |
| 156 } | 161 } |
| 157 | 162 |
| 158 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse( | 163 const QuicHttpResponseCache::Response* QuicHttpResponseCache::GetResponse( |
| 159 StringPiece host, | 164 StringPiece host, |
| 160 StringPiece path) const { | 165 StringPiece path) const { |
| 161 base::AutoLock lock(response_mutex_); | 166 base::AutoLock lock(response_mutex_); |
| 162 | 167 |
| 163 auto it = responses_.find(GetKey(host, path)); | 168 auto it = responses_.find(GetKey(host, path)); |
| 164 if (it == responses_.end()) { | 169 if (it == responses_.end()) { |
| 165 DVLOG(1) << "Get response for resource failed: host " << host << " path " | 170 DVLOG(1) << "Get response for resource failed: host " << host << " path " |
| 166 << path; | 171 << path; |
| 167 if (default_response_.get()) { | 172 if (default_response_.get()) { |
| 168 return default_response_.get(); | 173 return default_response_.get(); |
| 169 } | 174 } |
| 170 return nullptr; | 175 return nullptr; |
| 171 } | 176 } |
| 172 return it->second.get(); | 177 return it->second.get(); |
| 173 } | 178 } |
| 174 | 179 |
| 175 typedef QuicInMemoryCache::ServerPushInfo ServerPushInfo; | 180 typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo; |
| 176 | 181 |
| 177 void QuicInMemoryCache::AddSimpleResponse(StringPiece host, | 182 void QuicHttpResponseCache::AddSimpleResponse(StringPiece host, |
| 178 StringPiece path, | 183 StringPiece path, |
| 179 int response_code, | 184 int response_code, |
| 180 StringPiece body) { | 185 StringPiece body) { |
| 181 SpdyHeaderBlock response_headers; | 186 SpdyHeaderBlock response_headers; |
| 182 response_headers[":status"] = IntToString(response_code); | 187 response_headers[":status"] = IntToString(response_code); |
| 183 response_headers["content-length"] = | 188 response_headers["content-length"] = |
| 184 IntToString(static_cast<int>(body.length())); | 189 IntToString(static_cast<int>(body.length())); |
| 185 AddResponse(host, path, std::move(response_headers), body); | 190 AddResponse(host, path, std::move(response_headers), body); |
| 186 } | 191 } |
| 187 | 192 |
| 188 void QuicInMemoryCache::AddSimpleResponseWithServerPushResources( | 193 void QuicHttpResponseCache::AddSimpleResponseWithServerPushResources( |
| 189 StringPiece host, | 194 StringPiece host, |
| 190 StringPiece path, | 195 StringPiece path, |
| 191 int response_code, | 196 int response_code, |
| 192 StringPiece body, | 197 StringPiece body, |
| 193 std::list<ServerPushInfo> push_resources) { | 198 std::list<ServerPushInfo> push_resources) { |
| 194 AddSimpleResponse(host, path, response_code, body); | 199 AddSimpleResponse(host, path, response_code, body); |
| 195 MaybeAddServerPushResources(host, path, push_resources); | 200 MaybeAddServerPushResources(host, path, push_resources); |
| 196 } | 201 } |
| 197 | 202 |
| 198 void QuicInMemoryCache::AddDefaultResponse(Response* response) { | 203 void QuicHttpResponseCache::AddDefaultResponse(Response* response) { |
| 199 base::AutoLock lock(response_mutex_); | 204 base::AutoLock lock(response_mutex_); |
| 200 default_response_.reset(response); | 205 default_response_.reset(response); |
| 201 } | 206 } |
| 202 | 207 |
| 203 void QuicInMemoryCache::AddResponse(StringPiece host, | 208 void QuicHttpResponseCache::AddResponse(StringPiece host, |
| 204 StringPiece path, | 209 StringPiece path, |
| 205 SpdyHeaderBlock response_headers, | 210 SpdyHeaderBlock response_headers, |
| 206 StringPiece response_body) { | 211 StringPiece response_body) { |
| 207 AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), | 212 AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), |
| 208 response_body, SpdyHeaderBlock()); | 213 response_body, SpdyHeaderBlock()); |
| 209 } | 214 } |
| 210 | 215 |
| 211 void QuicInMemoryCache::AddResponse(StringPiece host, | 216 void QuicHttpResponseCache::AddResponse(StringPiece host, |
| 212 StringPiece path, | 217 StringPiece path, |
| 213 SpdyHeaderBlock response_headers, | 218 SpdyHeaderBlock response_headers, |
| 214 StringPiece response_body, | 219 StringPiece response_body, |
| 215 SpdyHeaderBlock response_trailers) { | 220 SpdyHeaderBlock response_trailers) { |
| 216 AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), | 221 AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), |
| 217 response_body, std::move(response_trailers)); | 222 response_body, std::move(response_trailers)); |
| 218 } | 223 } |
| 219 | 224 |
| 220 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, | 225 void QuicHttpResponseCache::AddSpecialResponse( |
| 221 StringPiece path, | 226 StringPiece host, |
| 222 SpecialResponseType response_type) { | 227 StringPiece path, |
| 228 SpecialResponseType response_type) { |
| 223 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "", | 229 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "", |
| 224 SpdyHeaderBlock()); | 230 SpdyHeaderBlock()); |
| 225 } | 231 } |
| 226 | 232 |
| 227 QuicInMemoryCache::QuicInMemoryCache() {} | 233 QuicHttpResponseCache::QuicHttpResponseCache() {} |
| 228 | 234 |
| 229 void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) { | 235 void QuicHttpResponseCache::InitializeFromDirectory( |
| 236 const string& cache_directory) { |
| 230 if (cache_directory.empty()) { | 237 if (cache_directory.empty()) { |
| 231 QUIC_BUG << "cache_directory must not be empty."; | 238 QUIC_BUG << "cache_directory must not be empty."; |
| 232 return; | 239 return; |
| 233 } | 240 } |
| 234 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " | 241 VLOG(1) << "Attempting to initialize QuicHttpResponseCache from directory: " |
| 235 << cache_directory; | 242 << cache_directory; |
| 236 FilePath directory(FilePath::FromUTF8Unsafe(cache_directory)); | 243 FilePath directory(FilePath::FromUTF8Unsafe(cache_directory)); |
| 237 base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES); | 244 base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES); |
| 238 std::list<std::unique_ptr<ResourceFile>> resource_files; | 245 std::list<std::unique_ptr<ResourceFile>> resource_files; |
| 239 for (FilePath file_iter = file_list.Next(); !file_iter.empty(); | 246 for (FilePath file_iter = file_list.Next(); !file_iter.empty(); |
| 240 file_iter = file_list.Next()) { | 247 file_iter = file_list.Next()) { |
| 241 // Need to skip files in .svn directories | 248 // Need to skip files in .svn directories |
| 242 if (file_iter.value().find(FILE_PATH_LITERAL("/.svn/")) != string::npos) { | 249 if (file_iter.value().find(FILE_PATH_LITERAL("/.svn/")) != string::npos) { |
| 243 continue; | 250 continue; |
| 244 } | 251 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 272 } | 279 } |
| 273 push_resources.push_back(ServerPushInfo(url, response->headers().Clone(), | 280 push_resources.push_back(ServerPushInfo(url, response->headers().Clone(), |
| 274 net::kV3LowestPriority, | 281 net::kV3LowestPriority, |
| 275 response->body().as_string())); | 282 response->body().as_string())); |
| 276 } | 283 } |
| 277 MaybeAddServerPushResources(resource_file->host(), resource_file->path(), | 284 MaybeAddServerPushResources(resource_file->host(), resource_file->path(), |
| 278 push_resources); | 285 push_resources); |
| 279 } | 286 } |
| 280 } | 287 } |
| 281 | 288 |
| 282 std::list<ServerPushInfo> QuicInMemoryCache::GetServerPushResources( | 289 std::list<ServerPushInfo> QuicHttpResponseCache::GetServerPushResources( |
| 283 string request_url) { | 290 string request_url) { |
| 284 base::AutoLock lock(response_mutex_); | 291 base::AutoLock lock(response_mutex_); |
| 285 | 292 |
| 286 std::list<ServerPushInfo> resources; | 293 std::list<ServerPushInfo> resources; |
| 287 auto resource_range = server_push_resources_.equal_range(request_url); | 294 auto resource_range = server_push_resources_.equal_range(request_url); |
| 288 for (auto it = resource_range.first; it != resource_range.second; ++it) { | 295 for (auto it = resource_range.first; it != resource_range.second; ++it) { |
| 289 resources.push_back(it->second); | 296 resources.push_back(it->second); |
| 290 } | 297 } |
| 291 DVLOG(1) << "Found " << resources.size() << " push resources for " | 298 DVLOG(1) << "Found " << resources.size() << " push resources for " |
| 292 << request_url; | 299 << request_url; |
| 293 return resources; | 300 return resources; |
| 294 } | 301 } |
| 295 | 302 |
| 296 QuicInMemoryCache::~QuicInMemoryCache() { | 303 QuicHttpResponseCache::~QuicHttpResponseCache() { |
| 297 { | 304 { |
| 298 base::AutoLock lock(response_mutex_); | 305 base::AutoLock lock(response_mutex_); |
| 299 responses_.clear(); | 306 responses_.clear(); |
| 300 } | 307 } |
| 301 } | 308 } |
| 302 | 309 |
| 303 void QuicInMemoryCache::AddResponseImpl(StringPiece host, | 310 void QuicHttpResponseCache::AddResponseImpl(StringPiece host, |
| 304 StringPiece path, | 311 StringPiece path, |
| 305 SpecialResponseType response_type, | 312 SpecialResponseType response_type, |
| 306 SpdyHeaderBlock response_headers, | 313 SpdyHeaderBlock response_headers, |
| 307 StringPiece response_body, | 314 StringPiece response_body, |
| 308 SpdyHeaderBlock response_trailers) { | 315 SpdyHeaderBlock response_trailers) { |
| 309 base::AutoLock lock(response_mutex_); | 316 base::AutoLock lock(response_mutex_); |
| 310 | 317 |
| 311 DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\""; | 318 DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\""; |
| 312 string key = GetKey(host, path); | 319 string key = GetKey(host, path); |
| 313 if (base::ContainsKey(responses_, key)) { | 320 if (base::ContainsKey(responses_, key)) { |
| 314 QUIC_BUG << "Response for '" << key << "' already exists!"; | 321 QUIC_BUG << "Response for '" << key << "' already exists!"; |
| 315 return; | 322 return; |
| 316 } | 323 } |
| 317 std::unique_ptr<Response> new_response = base::MakeUnique<Response>(); | 324 std::unique_ptr<Response> new_response = base::MakeUnique<Response>(); |
| 318 new_response->set_response_type(response_type); | 325 new_response->set_response_type(response_type); |
| 319 new_response->set_headers(std::move(response_headers)); | 326 new_response->set_headers(std::move(response_headers)); |
| 320 new_response->set_body(response_body); | 327 new_response->set_body(response_body); |
| 321 new_response->set_trailers(std::move(response_trailers)); | 328 new_response->set_trailers(std::move(response_trailers)); |
| 322 DVLOG(1) << "Add response with key " << key; | 329 DVLOG(1) << "Add response with key " << key; |
| 323 responses_[key] = std::move(new_response); | 330 responses_[key] = std::move(new_response); |
| 324 } | 331 } |
| 325 | 332 |
| 326 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { | 333 string QuicHttpResponseCache::GetKey(StringPiece host, StringPiece path) const { |
| 327 return host.as_string() + path.as_string(); | 334 return host.as_string() + path.as_string(); |
| 328 } | 335 } |
| 329 | 336 |
| 330 void QuicInMemoryCache::MaybeAddServerPushResources( | 337 void QuicHttpResponseCache::MaybeAddServerPushResources( |
| 331 StringPiece request_host, | 338 StringPiece request_host, |
| 332 StringPiece request_path, | 339 StringPiece request_path, |
| 333 std::list<ServerPushInfo> push_resources) { | 340 std::list<ServerPushInfo> push_resources) { |
| 334 string request_url = GetKey(request_host, request_path); | 341 string request_url = GetKey(request_host, request_path); |
| 335 | 342 |
| 336 for (const auto& push_resource : push_resources) { | 343 for (const auto& push_resource : push_resources) { |
| 337 if (PushResourceExistsInCache(request_url, push_resource)) { | 344 if (PushResourceExistsInCache(request_url, push_resource)) { |
| 338 continue; | 345 continue; |
| 339 } | 346 } |
| 340 | 347 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 359 if (!found_existing_response) { | 366 if (!found_existing_response) { |
| 360 // Add a server push response to responses map, if it is not in the map. | 367 // Add a server push response to responses map, if it is not in the map. |
| 361 StringPiece body = push_resource.body; | 368 StringPiece body = push_resource.body; |
| 362 DVLOG(1) << "Add response for push resource: host " << host << " path " | 369 DVLOG(1) << "Add response for push resource: host " << host << " path " |
| 363 << path; | 370 << path; |
| 364 AddResponse(host, path, push_resource.headers.Clone(), body); | 371 AddResponse(host, path, push_resource.headers.Clone(), body); |
| 365 } | 372 } |
| 366 } | 373 } |
| 367 } | 374 } |
| 368 | 375 |
| 369 bool QuicInMemoryCache::PushResourceExistsInCache(string original_request_url, | 376 bool QuicHttpResponseCache::PushResourceExistsInCache( |
| 370 ServerPushInfo resource) { | 377 string original_request_url, |
| 378 ServerPushInfo resource) { |
| 371 base::AutoLock lock(response_mutex_); | 379 base::AutoLock lock(response_mutex_); |
| 372 auto resource_range = | 380 auto resource_range = |
| 373 server_push_resources_.equal_range(original_request_url); | 381 server_push_resources_.equal_range(original_request_url); |
| 374 for (auto it = resource_range.first; it != resource_range.second; ++it) { | 382 for (auto it = resource_range.first; it != resource_range.second; ++it) { |
| 375 ServerPushInfo push_resource = it->second; | 383 ServerPushInfo push_resource = it->second; |
| 376 if (push_resource.request_url.spec() == resource.request_url.spec()) { | 384 if (push_resource.request_url.spec() == resource.request_url.spec()) { |
| 377 return true; | 385 return true; |
| 378 } | 386 } |
| 379 } | 387 } |
| 380 return false; | 388 return false; |
| 381 } | 389 } |
| 382 | 390 |
| 383 } // namespace net | 391 } // namespace net |
| OLD | NEW |