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 |