Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/service_worker/service_worker_cache.h" | 5 #include "content/browser/service_worker/service_worker_cache.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/guid.h" | 10 #include "base/guid.h" |
| 11 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
| 12 #include "base/strings/string_util.h" | |
| 12 #include "content/browser/service_worker/service_worker_cache.pb.h" | 13 #include "content/browser/service_worker/service_worker_cache.pb.h" |
| 13 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
| 14 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 15 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
| 16 #include "net/disk_cache/disk_cache.h" | 17 #include "net/disk_cache/disk_cache.h" |
| 17 #include "net/url_request/url_request_context.h" | 18 #include "net/url_request/url_request_context.h" |
| 18 #include "storage/browser/blob/blob_data_handle.h" | 19 #include "storage/browser/blob/blob_data_handle.h" |
| 19 #include "storage/browser/blob/blob_storage_context.h" | 20 #include "storage/browser/blob/blob_storage_context.h" |
| 20 #include "storage/browser/blob/blob_url_request_job_factory.h" | 21 #include "storage/browser/blob/blob_url_request_job_factory.h" |
| 21 | 22 |
| 22 namespace content { | 23 namespace content { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr; | 27 typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr; |
| 27 typedef base::Callback<void(bool)> BoolCallback; | 28 typedef base::Callback<void(bool)> BoolCallback; |
| 28 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> | 29 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> |
| 29 EntryBoolCallback; | 30 EntryBoolCallback; |
| 30 typedef base::Callback<void(scoped_ptr<ServiceWorkerRequestResponseHeaders>)> | 31 typedef base::Callback<void(scoped_ptr<ServiceWorkerRequestResponseHeaders>)> |
| 31 HeadersCallback; | 32 HeadersCallback; |
| 33 typedef std::map<std::string, std::string> HeaderMap; | |
| 32 | 34 |
| 33 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; | 35 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; |
| 34 | 36 |
| 35 // The maximum size of an individual cache. Ultimately cache size is controlled | 37 // The maximum size of an individual cache. Ultimately cache size is controlled |
| 36 // per-origin. | 38 // per-origin. |
| 37 const int kMaxCacheBytes = 512 * 1024 * 1024; | 39 const int kMaxCacheBytes = 512 * 1024 * 1024; |
| 38 | 40 |
| 39 // Buffer size for cache and blob reading/writing. | 41 // Buffer size for cache and blob reading/writing. |
| 40 const int kBufferSize = 1024 * 512; | 42 const int kBufferSize = 1024 * 512; |
| 41 | 43 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 | 368 |
| 367 HeadersCallback headers_callback = base::Bind(MatchDidReadHeaderData, | 369 HeadersCallback headers_callback = base::Bind(MatchDidReadHeaderData, |
| 368 base::Passed(request.Pass()), | 370 base::Passed(request.Pass()), |
| 369 callback, | 371 callback, |
| 370 blob_storage, | 372 blob_storage, |
| 371 base::Passed(entry.Pass())); | 373 base::Passed(entry.Pass())); |
| 372 | 374 |
| 373 ReadHeaders(tmp_entry_ptr, headers_callback); | 375 ReadHeaders(tmp_entry_ptr, headers_callback); |
| 374 } | 376 } |
| 375 | 377 |
| 378 bool VaryMatches(const HeaderMap& request, | |
| 379 const HeaderMap& cached_request, | |
| 380 const HeaderMap& response) { | |
| 381 // The headers are assumed to have lower-case keys. This is enforced by | |
| 382 // ASSERTS in WebServiceWorkerRequest and WebServiceWorkerResponse. | |
|
jkarlin
2014/09/17 18:48:10
The ASSERTS this comment speaks of are in review:
| |
| 383 HeaderMap::const_iterator vary_iter = response.find("vary"); | |
| 384 if (vary_iter == response.end()) | |
| 385 return true; | |
| 386 | |
| 387 std::vector<std::string> vary_keys; | |
| 388 Tokenize(vary_iter->second, ",", &vary_keys); | |
| 389 for (size_t i = 0, max = vary_keys.size(); i < max; ++i) { | |
| 390 std::string trimmed; | |
| 391 base::TrimWhitespaceASCII(vary_keys[i], base::TRIM_ALL, &trimmed); | |
| 392 if (trimmed == "*") | |
| 393 return false; | |
| 394 | |
| 395 HeaderMap::const_iterator request_iter = request.find(trimmed); | |
| 396 HeaderMap::const_iterator cached_request_iter = | |
| 397 cached_request.find(trimmed); | |
| 398 | |
| 399 // If the header exists in one but not the other, no match. | |
| 400 if ((request_iter == request.end()) != | |
| 401 (cached_request_iter == cached_request.end())) | |
| 402 return false; | |
| 403 | |
| 404 // If the header exists in one, it exists in both. Verify that the values | |
| 405 // are equal. | |
| 406 if (request_iter != request.end() && | |
| 407 request_iter->second != cached_request_iter->second) | |
| 408 return false; | |
| 409 } | |
| 410 | |
| 411 return true; | |
| 412 } | |
| 413 | |
| 376 void MatchDidReadHeaderData( | 414 void MatchDidReadHeaderData( |
| 377 scoped_ptr<ServiceWorkerFetchRequest> request, | 415 scoped_ptr<ServiceWorkerFetchRequest> request, |
| 378 const ServiceWorkerCache::ResponseCallback& callback, | 416 const ServiceWorkerCache::ResponseCallback& callback, |
| 379 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 417 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
| 380 disk_cache::ScopedEntryPtr entry, | 418 disk_cache::ScopedEntryPtr entry, |
| 381 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) { | 419 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) { |
| 382 if (!headers) { | 420 if (!headers) { |
| 383 callback.Run(ServiceWorkerCache::ErrorTypeStorage, | 421 callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
| 384 scoped_ptr<ServiceWorkerResponse>(), | 422 scoped_ptr<ServiceWorkerResponse>(), |
| 385 scoped_ptr<storage::BlobDataHandle>()); | 423 scoped_ptr<storage::BlobDataHandle>()); |
| 386 return; | 424 return; |
| 387 } | 425 } |
| 388 | 426 |
| 389 scoped_ptr<ServiceWorkerResponse> response( | 427 scoped_ptr<ServiceWorkerResponse> response( |
| 390 new ServiceWorkerResponse(request->url, | 428 new ServiceWorkerResponse(request->url, |
| 391 headers->status_code(), | 429 headers->status_code(), |
| 392 headers->status_text(), | 430 headers->status_text(), |
| 393 std::map<std::string, std::string>(), | 431 std::map<std::string, std::string>(), |
| 394 "")); | 432 "")); |
| 395 | 433 |
| 396 for (int i = 0; i < headers->response_headers_size(); ++i) { | 434 for (int i = 0; i < headers->response_headers_size(); ++i) { |
| 397 const ServiceWorkerRequestResponseHeaders::HeaderMap header = | 435 const ServiceWorkerRequestResponseHeaders::HeaderMap header = |
| 398 headers->response_headers(i); | 436 headers->response_headers(i); |
| 399 response->headers.insert(std::make_pair(header.name(), header.value())); | 437 response->headers.insert(std::make_pair(header.name(), header.value())); |
| 400 } | 438 } |
| 401 | 439 |
| 402 // TODO(jkarlin): Insert vary validation here. | 440 HeaderMap cached_request_headers; |
| 441 for (int i = 0; i < headers->request_headers_size(); ++i) { | |
| 442 const ServiceWorkerRequestResponseHeaders::HeaderMap header = | |
| 443 headers->request_headers(i); | |
| 444 cached_request_headers.insert( | |
| 445 std::make_pair(header.name(), header.value())); | |
| 446 } | |
| 447 | |
| 448 if (!VaryMatches( | |
| 449 request->headers, cached_request_headers, response->headers)) { | |
| 450 callback.Run(ServiceWorkerCache::ErrorTypeNotFound, | |
| 451 scoped_ptr<ServiceWorkerResponse>(), | |
| 452 scoped_ptr<storage::BlobDataHandle>()); | |
| 453 return; | |
| 454 } | |
| 403 | 455 |
| 404 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { | 456 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { |
| 405 callback.Run(ServiceWorkerCache::ErrorTypeOK, | 457 callback.Run(ServiceWorkerCache::ErrorTypeOK, |
| 406 response.Pass(), | 458 response.Pass(), |
| 407 scoped_ptr<storage::BlobDataHandle>()); | 459 scoped_ptr<storage::BlobDataHandle>()); |
| 408 return; | 460 return; |
| 409 } | 461 } |
| 410 | 462 |
| 411 // Stream the response body into a blob. | 463 // Stream the response body into a blob. |
| 412 if (!blob_storage) { | 464 if (!blob_storage) { |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 973 initialized_ = true; | 1025 initialized_ = true; |
| 974 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 1026 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); |
| 975 it != init_callbacks_.end(); | 1027 it != init_callbacks_.end(); |
| 976 ++it) { | 1028 ++it) { |
| 977 it->Run(); | 1029 it->Run(); |
| 978 } | 1030 } |
| 979 init_callbacks_.clear(); | 1031 init_callbacks_.clear(); |
| 980 } | 1032 } |
| 981 | 1033 |
| 982 } // namespace content | 1034 } // namespace content |
| OLD | NEW |