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 "content/browser/service_worker/service_worker_cache.pb.h" | 12 #include "content/browser/service_worker/service_worker_cache.pb.h" |
13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
14 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
16 #include "net/disk_cache/disk_cache.h" | 16 #include "net/disk_cache/disk_cache.h" |
17 #include "net/url_request/url_request_context.h" | 17 #include "net/url_request/url_request_context.h" |
18 #include "webkit/browser/blob/blob_data_handle.h" | 18 #include "webkit/browser/blob/blob_data_handle.h" |
19 #include "webkit/browser/blob/blob_storage_context.h" | 19 #include "webkit/browser/blob/blob_storage_context.h" |
20 #include "webkit/browser/blob/blob_url_request_job_factory.h" | 20 #include "webkit/browser/blob/blob_url_request_job_factory.h" |
21 | 21 |
22 namespace content { | 22 namespace content { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr; | 26 typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr; |
27 typedef base::Callback<void(bool)> BoolCallback; | 27 typedef base::Callback<void(bool)> BoolCallback; |
28 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> | 28 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> |
29 EntryBoolCallback; | 29 EntryBoolCallback; |
30 typedef base::Callback<void(scoped_ptr<ServiceWorkerRequestResponseHeaders>)> | |
31 HeadersCallback; | |
32 | |
33 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; | 30 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; |
34 | 31 |
35 // The maximum size of an individual cache. Ultimately cache size is controlled | 32 // The maximum size of an individual cache. Ultimately cache size is controlled |
36 // per-origin. | 33 // per-origin. |
37 const int kMaxCacheBytes = 512 * 1024 * 1024; | 34 const int kMaxCacheBytes = 512 * 1024 * 1024; |
38 | 35 |
39 // Buffer size for cache and blob reading/writing. | 36 // Buffer size for cache and blob reading/writing. |
40 const int kBufferSize = 1024 * 512; | 37 const int kBufferSize = 1024 * 512; |
41 | 38 |
42 struct ResponseReadContext { | 39 struct ResponseReadContext { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 void MatchDidOpenEntry(ServiceWorkerFetchRequest* request, | 182 void MatchDidOpenEntry(ServiceWorkerFetchRequest* request, |
186 const ServiceWorkerCache::ResponseCallback& callback, | 183 const ServiceWorkerCache::ResponseCallback& callback, |
187 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 184 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
188 scoped_ptr<disk_cache::Entry*> entryptr, | 185 scoped_ptr<disk_cache::Entry*> entryptr, |
189 int rv); | 186 int rv); |
190 void MatchDidReadHeaderData( | 187 void MatchDidReadHeaderData( |
191 ServiceWorkerFetchRequest* request, | 188 ServiceWorkerFetchRequest* request, |
192 const ServiceWorkerCache::ResponseCallback& callback, | 189 const ServiceWorkerCache::ResponseCallback& callback, |
193 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 190 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
194 disk_cache::ScopedEntryPtr entry, | 191 disk_cache::ScopedEntryPtr entry, |
195 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers); | 192 const scoped_refptr<net::IOBufferWithSize>& buffer, |
| 193 int rv); |
196 void MatchDidReadResponseBodyData( | 194 void MatchDidReadResponseBodyData( |
197 ServiceWorkerFetchRequest* request, | 195 ServiceWorkerFetchRequest* request, |
198 const ServiceWorkerCache::ResponseCallback& callback, | 196 const ServiceWorkerCache::ResponseCallback& callback, |
199 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 197 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
200 disk_cache::ScopedEntryPtr entry, | 198 disk_cache::ScopedEntryPtr entry, |
201 scoped_ptr<ServiceWorkerResponse> response, | 199 scoped_ptr<ServiceWorkerResponse> response, |
202 scoped_ptr<ResponseReadContext> response_context, | 200 scoped_ptr<ResponseReadContext> response_context, |
203 int rv); | 201 int rv); |
204 void MatchDoneWithBody(ServiceWorkerFetchRequest* request, | 202 void MatchDoneWithBody(ServiceWorkerFetchRequest* request, |
205 const ServiceWorkerCache::ResponseCallback& callback, | 203 const ServiceWorkerCache::ResponseCallback& callback, |
206 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 204 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
207 scoped_ptr<ServiceWorkerResponse> response, | 205 scoped_ptr<ServiceWorkerResponse> response, |
208 scoped_ptr<ResponseReadContext> response_context); | 206 scoped_ptr<ResponseReadContext> response_context); |
209 | 207 |
210 // Delete callbacks | 208 // Delete callbacks |
211 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request, | 209 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request, |
212 const ServiceWorkerCache::ErrorCallback& callback, | 210 const ServiceWorkerCache::ErrorCallback& callback, |
213 scoped_ptr<disk_cache::Entry*> entryptr, | 211 scoped_ptr<disk_cache::Entry*> entryptr, |
214 int rv); | 212 int rv); |
215 | 213 |
216 // Copy headers out of a cache entry and into a protobuf. The callback is | |
217 // guaranteed to be run. | |
218 void ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback); | |
219 void ReadHeadersDidReadHeaderData( | |
220 disk_cache::Entry* entry, | |
221 const HeadersCallback& callback, | |
222 const scoped_refptr<net::IOBufferWithSize>& buffer, | |
223 int rv); | |
224 | |
225 // CreateBackend callbacks | 214 // CreateBackend callbacks |
226 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, | 215 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, |
227 scoped_ptr<ScopedBackendPtr> backend_ptr, | 216 scoped_ptr<ScopedBackendPtr> backend_ptr, |
228 base::WeakPtr<ServiceWorkerCache> cache, | 217 base::WeakPtr<ServiceWorkerCache> cache, |
229 int rv); | 218 int rv); |
230 | 219 |
231 void PutDidCreateEntry(ServiceWorkerFetchRequest* request, | 220 void PutDidCreateEntry(ServiceWorkerFetchRequest* request, |
232 ServiceWorkerResponse* response, | 221 ServiceWorkerResponse* response, |
233 const ServiceWorkerCache::ErrorCallback& callback, | 222 const ServiceWorkerCache::ErrorCallback& callback, |
234 scoped_ptr<disk_cache::Entry*> entryptr, | 223 scoped_ptr<disk_cache::Entry*> entryptr, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 if (rv != net::OK) { | 343 if (rv != net::OK) { |
355 callback.Run(ServiceWorkerCache::ErrorTypeNotFound, | 344 callback.Run(ServiceWorkerCache::ErrorTypeNotFound, |
356 scoped_ptr<ServiceWorkerResponse>(), | 345 scoped_ptr<ServiceWorkerResponse>(), |
357 scoped_ptr<storage::BlobDataHandle>()); | 346 scoped_ptr<storage::BlobDataHandle>()); |
358 return; | 347 return; |
359 } | 348 } |
360 | 349 |
361 DCHECK(entryptr); | 350 DCHECK(entryptr); |
362 disk_cache::ScopedEntryPtr entry(*entryptr); | 351 disk_cache::ScopedEntryPtr entry(*entryptr); |
363 | 352 |
| 353 scoped_refptr<net::IOBufferWithSize> buffer( |
| 354 new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS))); |
| 355 |
364 // Copy the entry pointer before passing it in base::Bind. | 356 // Copy the entry pointer before passing it in base::Bind. |
365 disk_cache::Entry* tmp_entry_ptr = entry.get(); | 357 disk_cache::Entry* tmp_entry_ptr = entry.get(); |
366 | 358 |
367 HeadersCallback headers_callback = base::Bind(MatchDidReadHeaderData, | 359 net::CompletionCallback read_header_callback = |
368 request, | 360 base::Bind(MatchDidReadHeaderData, |
369 callback, | 361 request, |
370 blob_storage, | 362 callback, |
371 base::Passed(entry.Pass())); | 363 blob_storage, |
| 364 base::Passed(entry.Pass()), |
| 365 buffer); |
372 | 366 |
373 ReadHeaders(tmp_entry_ptr, headers_callback); | 367 int read_rv = tmp_entry_ptr->ReadData( |
| 368 INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback); |
| 369 |
| 370 if (read_rv != net::ERR_IO_PENDING) |
| 371 read_header_callback.Run(read_rv); |
374 } | 372 } |
375 | 373 |
376 void MatchDidReadHeaderData( | 374 void MatchDidReadHeaderData( |
377 ServiceWorkerFetchRequest* request, | 375 ServiceWorkerFetchRequest* request, |
378 const ServiceWorkerCache::ResponseCallback& callback, | 376 const ServiceWorkerCache::ResponseCallback& callback, |
379 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 377 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
380 disk_cache::ScopedEntryPtr entry, | 378 disk_cache::ScopedEntryPtr entry, |
381 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) { | 379 const scoped_refptr<net::IOBufferWithSize>& buffer, |
382 if (!headers) { | 380 int rv) { |
| 381 if (rv != buffer->size()) { |
383 callback.Run(ServiceWorkerCache::ErrorTypeStorage, | 382 callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
384 scoped_ptr<ServiceWorkerResponse>(), | 383 scoped_ptr<ServiceWorkerResponse>(), |
385 scoped_ptr<storage::BlobDataHandle>()); | 384 scoped_ptr<storage::BlobDataHandle>()); |
| 385 |
| 386 return; |
| 387 } |
| 388 |
| 389 ServiceWorkerRequestResponseHeaders headers; |
| 390 |
| 391 if (!headers.ParseFromArray(buffer->data(), buffer->size())) { |
| 392 callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
| 393 scoped_ptr<ServiceWorkerResponse>(), |
| 394 scoped_ptr<storage::BlobDataHandle>()); |
| 395 |
386 return; | 396 return; |
387 } | 397 } |
388 | 398 |
389 scoped_ptr<ServiceWorkerResponse> response( | 399 scoped_ptr<ServiceWorkerResponse> response( |
390 new ServiceWorkerResponse(request->url, | 400 new ServiceWorkerResponse(request->url, |
391 headers->status_code(), | 401 headers.status_code(), |
392 headers->status_text(), | 402 headers.status_text(), |
393 std::map<std::string, std::string>(), | 403 std::map<std::string, std::string>(), |
394 "")); | 404 "")); |
395 | 405 |
396 for (int i = 0; i < headers->response_headers_size(); ++i) { | 406 for (int i = 0; i < headers.response_headers_size(); ++i) { |
397 const ServiceWorkerRequestResponseHeaders::HeaderMap header = | 407 const ServiceWorkerRequestResponseHeaders::HeaderMap header = |
398 headers->response_headers(i); | 408 headers.response_headers(i); |
399 response->headers.insert(std::make_pair(header.name(), header.value())); | 409 response->headers.insert(std::make_pair(header.name(), header.value())); |
400 } | 410 } |
401 | 411 |
402 // TODO(jkarlin): Insert vary validation here. | 412 // TODO(jkarlin): Insert vary validation here. |
403 | 413 |
404 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { | 414 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { |
405 callback.Run(ServiceWorkerCache::ErrorTypeOK, | 415 callback.Run(ServiceWorkerCache::ErrorTypeOK, |
406 response.Pass(), | 416 response.Pass(), |
407 scoped_ptr<storage::BlobDataHandle>()); | 417 scoped_ptr<storage::BlobDataHandle>()); |
408 return; | 418 return; |
409 } | 419 } |
410 | 420 |
411 // Stream the response body into a blob. | 421 // Stream the response body into a blob. |
412 if (!blob_storage) { | 422 if (!blob_storage) { |
413 callback.Run(ServiceWorkerCache::ErrorTypeStorage, | 423 callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
414 scoped_ptr<ServiceWorkerResponse>(), | 424 scoped_ptr<ServiceWorkerResponse>(), |
415 scoped_ptr<storage::BlobDataHandle>()); | 425 scoped_ptr<storage::BlobDataHandle>()); |
| 426 |
416 return; | 427 return; |
417 } | 428 } |
418 | 429 |
419 response->blob_uuid = base::GenerateGUID(); | 430 response->blob_uuid = base::GenerateGUID(); |
420 | 431 |
421 scoped_refptr<storage::BlobData> blob_data = | 432 scoped_refptr<storage::BlobData> blob_data = |
422 new storage::BlobData(response->blob_uuid); | 433 new storage::BlobData(response->blob_uuid); |
423 scoped_refptr<net::IOBufferWithSize> response_body_buffer( | 434 scoped_refptr<net::IOBufferWithSize> response_body_buffer( |
424 new net::IOBufferWithSize(kBufferSize)); | 435 new net::IOBufferWithSize(kBufferSize)); |
425 | 436 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 return; | 542 return; |
532 } | 543 } |
533 | 544 |
534 DCHECK(entryptr); | 545 DCHECK(entryptr); |
535 disk_cache::ScopedEntryPtr entry(*entryptr); | 546 disk_cache::ScopedEntryPtr entry(*entryptr); |
536 | 547 |
537 entry->Doom(); | 548 entry->Doom(); |
538 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 549 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
539 } | 550 } |
540 | 551 |
541 void ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback) { | |
542 DCHECK(entry); | |
543 | |
544 scoped_refptr<net::IOBufferWithSize> buffer( | |
545 new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS))); | |
546 | |
547 net::CompletionCallback read_header_callback = | |
548 base::Bind(ReadHeadersDidReadHeaderData, entry, callback, buffer); | |
549 | |
550 int read_rv = entry->ReadData( | |
551 INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback); | |
552 | |
553 if (read_rv != net::ERR_IO_PENDING) | |
554 read_header_callback.Run(read_rv); | |
555 } | |
556 | |
557 void ReadHeadersDidReadHeaderData( | |
558 disk_cache::Entry* entry, | |
559 const HeadersCallback& callback, | |
560 const scoped_refptr<net::IOBufferWithSize>& buffer, | |
561 int rv) { | |
562 if (rv != buffer->size()) { | |
563 callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>()); | |
564 return; | |
565 } | |
566 | |
567 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers( | |
568 new ServiceWorkerRequestResponseHeaders()); | |
569 | |
570 if (!headers->ParseFromArray(buffer->data(), buffer->size())) { | |
571 callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>()); | |
572 return; | |
573 } | |
574 | |
575 callback.Run(headers.Pass()); | |
576 } | |
577 | |
578 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, | 552 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, |
579 scoped_ptr<ScopedBackendPtr> backend_ptr, | 553 scoped_ptr<ScopedBackendPtr> backend_ptr, |
580 base::WeakPtr<ServiceWorkerCache> cache, | 554 base::WeakPtr<ServiceWorkerCache> cache, |
581 int rv) { | 555 int rv) { |
582 if (rv != net::OK || !cache) { | 556 if (rv != net::OK || !cache) { |
583 callback.Run(ServiceWorkerCache::ErrorTypeStorage); | 557 callback.Run(ServiceWorkerCache::ErrorTypeStorage); |
584 return; | 558 return; |
585 } | 559 } |
586 | |
587 cache->set_backend(backend_ptr->Pass()); | 560 cache->set_backend(backend_ptr->Pass()); |
588 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 561 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
589 } | 562 } |
590 | 563 |
591 } // namespace | 564 } // namespace |
592 | 565 |
593 // The state needed to pass between ServiceWorkerCache::Keys callbacks. | |
594 struct ServiceWorkerCache::KeysContext { | |
595 KeysContext(const ServiceWorkerCache::RequestsCallback& callback, | |
596 base::WeakPtr<ServiceWorkerCache> cache) | |
597 : original_callback(callback), | |
598 cache(cache), | |
599 out_keys(new ServiceWorkerCache::Requests()), | |
600 backend_iterator(NULL), | |
601 enumerated_entry(NULL) {} | |
602 | |
603 ~KeysContext() { | |
604 for (size_t i = 0, max = entries.size(); i < max; ++i) | |
605 entries[i]->Close(); | |
606 if (enumerated_entry) | |
607 enumerated_entry->Close(); | |
608 } | |
609 | |
610 // The callback passed to the Keys() function. | |
611 ServiceWorkerCache::RequestsCallback original_callback; | |
612 | |
613 // The ServiceWorkerCache that Keys was called on. | |
614 base::WeakPtr<ServiceWorkerCache> cache; | |
615 | |
616 // The vector of open entries in the backend. | |
617 Entries entries; | |
618 | |
619 // The output of the Keys function. | |
620 scoped_ptr<ServiceWorkerCache::Requests> out_keys; | |
621 | |
622 // Used for enumerating cache entries. | |
623 void* backend_iterator; | |
624 disk_cache::Entry* enumerated_entry; | |
625 }; | |
626 | |
627 // static | 566 // static |
628 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( | 567 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( |
629 net::URLRequestContext* request_context, | 568 net::URLRequestContext* request_context, |
630 base::WeakPtr<storage::BlobStorageContext> blob_context) { | 569 base::WeakPtr<storage::BlobStorageContext> blob_context) { |
631 return make_scoped_ptr( | 570 return make_scoped_ptr( |
632 new ServiceWorkerCache(base::FilePath(), request_context, blob_context)); | 571 new ServiceWorkerCache(base::FilePath(), request_context, blob_context)); |
633 } | 572 } |
634 | 573 |
635 // static | 574 // static |
636 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache( | 575 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache( |
(...skipping 28 matching lines...) Expand all Loading... |
665 callback, | 604 callback, |
666 base::Passed(backend_ptr.Pass()), | 605 base::Passed(backend_ptr.Pass()), |
667 weak_ptr_factory_.GetWeakPtr()); | 606 weak_ptr_factory_.GetWeakPtr()); |
668 | 607 |
669 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore | 608 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore |
670 // has for disk caches. | 609 // has for disk caches. |
671 // TODO(jkarlin): Switch to SimpleCache after it supports APP_CACHE and after | 610 // TODO(jkarlin): Switch to SimpleCache after it supports APP_CACHE and after |
672 // debugging why the QuickStressBody unittest fails with it. | 611 // debugging why the QuickStressBody unittest fails with it. |
673 int rv = disk_cache::CreateCacheBackend( | 612 int rv = disk_cache::CreateCacheBackend( |
674 cache_type, | 613 cache_type, |
675 net::CACHE_BACKEND_SIMPLE, | 614 net::CACHE_BACKEND_DEFAULT, |
676 path_, | 615 path_, |
677 kMaxCacheBytes, | 616 kMaxCacheBytes, |
678 false, /* force */ | 617 false, /* force */ |
679 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), | 618 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), |
680 NULL, | 619 NULL, |
681 backend, | 620 backend, |
682 create_cache_callback); | 621 create_cache_callback); |
683 if (rv != net::ERR_IO_PENDING) | 622 if (rv != net::ERR_IO_PENDING) |
684 create_cache_callback.Run(rv); | 623 create_cache_callback.Run(rv); |
685 } | 624 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 | 694 |
756 net::CompletionCallback open_entry_callback = base::Bind( | 695 net::CompletionCallback open_entry_callback = base::Bind( |
757 DeleteDidOpenEntry, request, callback, base::Passed(entry.Pass())); | 696 DeleteDidOpenEntry, request, callback, base::Passed(entry.Pass())); |
758 | 697 |
759 int rv = | 698 int rv = |
760 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback); | 699 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback); |
761 if (rv != net::ERR_IO_PENDING) | 700 if (rv != net::ERR_IO_PENDING) |
762 open_entry_callback.Run(rv); | 701 open_entry_callback.Run(rv); |
763 } | 702 } |
764 | 703 |
765 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | |
766 DCHECK(backend_); | |
767 | |
768 // 1. Iterate through all of the entries, open them, and add them to a vector. | |
769 // 2. For each open entry: | |
770 // 2.1. Read the headers into a protobuf. | |
771 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | |
772 // 2.3. Push the response into a vector of requests to be returned. | |
773 // 3. Return the vector of requests (keys). | |
774 | |
775 // The entries have to be loaded into a vector first because enumeration loops | |
776 // forever if you read data from a cache entry while enumerating. | |
777 | |
778 scoped_ptr<KeysContext> keys_context( | |
779 new KeysContext(callback, weak_ptr_factory_.GetWeakPtr())); | |
780 | |
781 void** backend_iterator = &keys_context->backend_iterator; | |
782 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | |
783 | |
784 net::CompletionCallback open_entry_callback = | |
785 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); | |
786 | |
787 int rv = backend_->OpenNextEntry( | |
788 backend_iterator, enumerated_entry, open_entry_callback); | |
789 | |
790 if (rv != net::ERR_IO_PENDING) | |
791 open_entry_callback.Run(rv); | |
792 } | |
793 | |
794 bool ServiceWorkerCache::HasCreatedBackend() const { | 704 bool ServiceWorkerCache::HasCreatedBackend() const { |
795 return backend_; | 705 return backend_; |
796 } | 706 } |
797 | 707 |
798 ServiceWorkerCache::ServiceWorkerCache( | 708 ServiceWorkerCache::ServiceWorkerCache( |
799 const base::FilePath& path, | 709 const base::FilePath& path, |
800 net::URLRequestContext* request_context, | 710 net::URLRequestContext* request_context, |
801 base::WeakPtr<storage::BlobStorageContext> blob_context) | 711 base::WeakPtr<storage::BlobStorageContext> blob_context) |
802 : path_(path), | 712 : path_(path), |
803 request_context_(request_context), | 713 request_context_(request_context), |
804 blob_storage_context_(blob_context), | 714 blob_storage_context_(blob_context), |
805 weak_ptr_factory_(this) { | 715 weak_ptr_factory_(this) { |
806 } | 716 } |
807 | 717 |
808 // static | |
809 void ServiceWorkerCache::KeysDidOpenNextEntry( | |
810 scoped_ptr<KeysContext> keys_context, | |
811 int rv) { | |
812 if (rv == net::ERR_FAILED) { | |
813 DCHECK(!keys_context->enumerated_entry); | |
814 // Enumeration is complete, extract the requests from the entries. | |
815 Entries::iterator iter = keys_context->entries.begin(); | |
816 KeysProcessNextEntry(keys_context.Pass(), iter); | |
817 return; | |
818 } | |
819 | |
820 base::WeakPtr<ServiceWorkerCache> cache = keys_context->cache; | |
821 if (rv < 0 || !cache) { | |
822 keys_context->original_callback.Run(ErrorTypeStorage, | |
823 scoped_ptr<Requests>()); | |
824 return; | |
825 } | |
826 | |
827 // Store the entry. | |
828 keys_context->entries.push_back(keys_context->enumerated_entry); | |
829 keys_context->enumerated_entry = NULL; | |
830 | |
831 // Enumerate the next entry. | |
832 void** backend_iterator = &keys_context->backend_iterator; | |
833 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | |
834 | |
835 net::CompletionCallback open_entry_callback = | |
836 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); | |
837 | |
838 rv = cache->backend_->OpenNextEntry( | |
839 backend_iterator, enumerated_entry, open_entry_callback); | |
840 | |
841 if (rv != net::ERR_IO_PENDING) | |
842 open_entry_callback.Run(rv); | |
843 } | |
844 | |
845 // static | |
846 void ServiceWorkerCache::KeysProcessNextEntry( | |
847 scoped_ptr<KeysContext> keys_context, | |
848 const Entries::iterator& iter) { | |
849 if (iter == keys_context->entries.end()) { | |
850 // All done. Return all of the keys. | |
851 keys_context->original_callback.Run(ErrorTypeOK, | |
852 keys_context->out_keys.Pass()); | |
853 return; | |
854 } | |
855 | |
856 ReadHeaders( | |
857 *iter, | |
858 base::Bind(KeysDidReadHeaders, base::Passed(keys_context.Pass()), iter)); | |
859 } | |
860 | |
861 // static | |
862 void ServiceWorkerCache::KeysDidReadHeaders( | |
863 scoped_ptr<KeysContext> keys_context, | |
864 const Entries::iterator& iter, | |
865 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) { | |
866 disk_cache::Entry* entry = *iter; | |
867 | |
868 if (headers) { | |
869 keys_context->out_keys->push_back( | |
870 ServiceWorkerFetchRequest(GURL(entry->GetKey()), | |
871 headers->method(), | |
872 std::map<std::string, std::string>(), | |
873 GURL(), | |
874 false)); | |
875 | |
876 std::map<std::string, std::string>& req_headers = | |
877 keys_context->out_keys->back().headers; | |
878 | |
879 for (int i = 0; i < headers->request_headers_size(); ++i) { | |
880 const ServiceWorkerRequestResponseHeaders::HeaderMap header = | |
881 headers->request_headers(i); | |
882 req_headers.insert(std::make_pair(header.name(), header.value())); | |
883 } | |
884 } else { | |
885 entry->Doom(); | |
886 } | |
887 | |
888 KeysProcessNextEntry(keys_context.Pass(), iter + 1); | |
889 } | |
890 | |
891 } // namespace content | 718 } // namespace content |
OLD | NEW |