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
3 // found in the LICENSE file.
5 #include "content/browser/cache_storage/cache_storage_cache.h"
9 #include "base/barrier_closure.h"
10 #include "base/files/file_path.h"
11 #include "base/guid.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "content/browser/cache_storage/cache_storage.pb.h"
16 #include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h"
17 #include "content/browser/cache_storage/cache_storage_scheduler.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/common/referrer.h"
20 #include "net/base/completion_callback.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "net/disk_cache/disk_cache.h"
24 #include "net/url_request/url_request_context_getter.h"
25 #include "storage/browser/blob/blob_data_builder.h"
26 #include "storage/browser/blob/blob_data_handle.h"
27 #include "storage/browser/blob/blob_storage_context.h"
28 #include "storage/browser/blob/blob_url_request_job_factory.h"
29 #include "storage/browser/quota/quota_manager_proxy.h"
30 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponseType.h"
36 // This class ensures that the cache and the entry have a lifetime as long as
37 // the blob that is created to contain them.
38 class CacheStorageCacheDataHandle
39 : public storage::BlobDataBuilder::DataHandle
{
41 CacheStorageCacheDataHandle(const scoped_refptr
<CacheStorageCache
>& cache
,
42 disk_cache::ScopedEntryPtr entry
)
43 : cache_(cache
), entry_(entry
.Pass()) {}
46 ~CacheStorageCacheDataHandle() override
{}
48 scoped_refptr
<CacheStorageCache
> cache_
;
49 disk_cache::ScopedEntryPtr entry_
;
51 DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheDataHandle
);
54 typedef base::Callback
<void(scoped_ptr
<CacheMetadata
>)> MetadataCallback
;
56 enum EntryIndex
{ INDEX_HEADERS
= 0, INDEX_RESPONSE_BODY
};
58 // The maximum size of an individual cache. Ultimately cache size is controlled
60 const int kMaxCacheBytes
= 512 * 1024 * 1024;
62 void NotReachedCompletionCallback(int rv
) {
66 blink::WebServiceWorkerResponseType
ProtoResponseTypeToWebResponseType(
67 CacheResponse::ResponseType response_type
) {
68 switch (response_type
) {
69 case CacheResponse::BASIC_TYPE
:
70 return blink::WebServiceWorkerResponseTypeBasic
;
71 case CacheResponse::CORS_TYPE
:
72 return blink::WebServiceWorkerResponseTypeCORS
;
73 case CacheResponse::DEFAULT_TYPE
:
74 return blink::WebServiceWorkerResponseTypeDefault
;
75 case CacheResponse::ERROR_TYPE
:
76 return blink::WebServiceWorkerResponseTypeError
;
77 case CacheResponse::OPAQUE_TYPE
:
78 return blink::WebServiceWorkerResponseTypeOpaque
;
79 case CacheResponse::OPAQUE_REDIRECT_TYPE
:
80 return blink::WebServiceWorkerResponseTypeOpaqueRedirect
;
83 return blink::WebServiceWorkerResponseTypeOpaque
;
86 CacheResponse::ResponseType
WebResponseTypeToProtoResponseType(
87 blink::WebServiceWorkerResponseType response_type
) {
88 switch (response_type
) {
89 case blink::WebServiceWorkerResponseTypeBasic
:
90 return CacheResponse::BASIC_TYPE
;
91 case blink::WebServiceWorkerResponseTypeCORS
:
92 return CacheResponse::CORS_TYPE
;
93 case blink::WebServiceWorkerResponseTypeDefault
:
94 return CacheResponse::DEFAULT_TYPE
;
95 case blink::WebServiceWorkerResponseTypeError
:
96 return CacheResponse::ERROR_TYPE
;
97 case blink::WebServiceWorkerResponseTypeOpaque
:
98 return CacheResponse::OPAQUE_TYPE
;
99 case blink::WebServiceWorkerResponseTypeOpaqueRedirect
:
100 return CacheResponse::OPAQUE_REDIRECT_TYPE
;
103 return CacheResponse::OPAQUE_TYPE
;
106 // Copy headers out of a cache entry and into a protobuf. The callback is
107 // guaranteed to be run.
108 void ReadMetadata(disk_cache::Entry
* entry
, const MetadataCallback
& callback
);
109 void ReadMetadataDidReadMetadata(
110 disk_cache::Entry
* entry
,
111 const MetadataCallback
& callback
,
112 const scoped_refptr
<net::IOBufferWithSize
>& buffer
,
115 bool VaryMatches(const ServiceWorkerHeaderMap
& request
,
116 const ServiceWorkerHeaderMap
& cached_request
,
117 const ServiceWorkerHeaderMap
& response
) {
118 ServiceWorkerHeaderMap::const_iterator vary_iter
= response
.find("vary");
119 if (vary_iter
== response
.end())
122 for (const std::string
& trimmed
:
123 base::SplitString(vary_iter
->second
, ",",
124 base::TRIM_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
)) {
128 ServiceWorkerHeaderMap::const_iterator request_iter
= request
.find(trimmed
);
129 ServiceWorkerHeaderMap::const_iterator cached_request_iter
=
130 cached_request
.find(trimmed
);
132 // If the header exists in one but not the other, no match.
133 if ((request_iter
== request
.end()) !=
134 (cached_request_iter
== cached_request
.end()))
137 // If the header exists in one, it exists in both. Verify that the values
139 if (request_iter
!= request
.end() &&
140 request_iter
->second
!= cached_request_iter
->second
)
147 void ReadMetadata(disk_cache::Entry
* entry
, const MetadataCallback
& callback
) {
150 scoped_refptr
<net::IOBufferWithSize
> buffer(
151 new net::IOBufferWithSize(entry
->GetDataSize(INDEX_HEADERS
)));
153 net::CompletionCallback read_header_callback
=
154 base::Bind(ReadMetadataDidReadMetadata
, entry
, callback
, buffer
);
156 int read_rv
= entry
->ReadData(INDEX_HEADERS
, 0, buffer
.get(), buffer
->size(),
157 read_header_callback
);
159 if (read_rv
!= net::ERR_IO_PENDING
)
160 read_header_callback
.Run(read_rv
);
163 void ReadMetadataDidReadMetadata(
164 disk_cache::Entry
* entry
,
165 const MetadataCallback
& callback
,
166 const scoped_refptr
<net::IOBufferWithSize
>& buffer
,
168 if (rv
!= buffer
->size()) {
169 callback
.Run(scoped_ptr
<CacheMetadata
>());
173 scoped_ptr
<CacheMetadata
> metadata(new CacheMetadata());
175 if (!metadata
->ParseFromArray(buffer
->data(), buffer
->size())) {
176 callback
.Run(scoped_ptr
<CacheMetadata
>());
180 callback
.Run(metadata
.Pass());
185 // The state needed to iterate all entries in the cache.
186 struct CacheStorageCache::OpenAllEntriesContext
{
187 OpenAllEntriesContext() : enumerated_entry(nullptr) {}
188 ~OpenAllEntriesContext() {
189 for (size_t i
= 0, max
= entries
.size(); i
< max
; ++i
) {
193 if (enumerated_entry
)
194 enumerated_entry
->Close();
197 // The vector of open entries in the backend.
200 // Used for enumerating cache entries.
201 scoped_ptr
<disk_cache::Backend::Iterator
> backend_iterator
;
202 disk_cache::Entry
* enumerated_entry
;
205 DISALLOW_COPY_AND_ASSIGN(OpenAllEntriesContext
);
208 // The state needed to pass between CacheStorageCache::MatchAll callbacks.
209 struct CacheStorageCache::MatchAllContext
{
210 explicit MatchAllContext(const CacheStorageCache::ResponsesCallback
& callback
)
211 : original_callback(callback
),
212 out_responses(new Responses
),
213 out_blob_data_handles(new BlobDataHandles
) {}
214 ~MatchAllContext() {}
216 // The callback passed to the MatchAll() function.
217 ResponsesCallback original_callback
;
219 // The outputs of the MatchAll function.
220 scoped_ptr
<Responses
> out_responses
;
221 scoped_ptr
<BlobDataHandles
> out_blob_data_handles
;
223 // The context holding open entries.
224 scoped_ptr
<OpenAllEntriesContext
> entries_context
;
227 DISALLOW_COPY_AND_ASSIGN(MatchAllContext
);
230 // The state needed to pass between CacheStorageCache::Keys callbacks.
231 struct CacheStorageCache::KeysContext
{
232 explicit KeysContext(const CacheStorageCache::RequestsCallback
& callback
)
233 : original_callback(callback
), out_keys(new Requests()) {}
236 // The callback passed to the Keys() function.
237 RequestsCallback original_callback
;
239 // The output of the Keys function.
240 scoped_ptr
<Requests
> out_keys
;
242 // The context holding open entries.
243 scoped_ptr
<OpenAllEntriesContext
> entries_context
;
246 DISALLOW_COPY_AND_ASSIGN(KeysContext
);
249 // The state needed to pass between CacheStorageCache::Put callbacks.
250 struct CacheStorageCache::PutContext
{
253 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
254 scoped_ptr
<ServiceWorkerResponse
> response
,
255 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
,
256 const CacheStorageCache::ErrorCallback
& callback
,
257 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
258 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
)
260 request(request
.Pass()),
261 response(response
.Pass()),
262 blob_data_handle(blob_data_handle
.Pass()),
264 request_context_getter(request_context_getter
),
265 quota_manager_proxy(quota_manager_proxy
) {}
267 // Input parameters to the Put function.
269 scoped_ptr
<ServiceWorkerFetchRequest
> request
;
270 scoped_ptr
<ServiceWorkerResponse
> response
;
271 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
272 CacheStorageCache::ErrorCallback callback
;
273 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
;
274 scoped_refptr
<storage::QuotaManagerProxy
> quota_manager_proxy
;
275 disk_cache::ScopedEntryPtr cache_entry
;
278 DISALLOW_COPY_AND_ASSIGN(PutContext
);
282 scoped_refptr
<CacheStorageCache
> CacheStorageCache::CreateMemoryCache(
284 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
285 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
286 base::WeakPtr
<storage::BlobStorageContext
> blob_context
) {
287 return make_scoped_refptr(
288 new CacheStorageCache(origin
, base::FilePath(), request_context_getter
,
289 quota_manager_proxy
, blob_context
));
293 scoped_refptr
<CacheStorageCache
> CacheStorageCache::CreatePersistentCache(
295 const base::FilePath
& path
,
296 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
297 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
298 base::WeakPtr
<storage::BlobStorageContext
> blob_context
) {
299 return make_scoped_refptr(new CacheStorageCache(
300 origin
, path
, request_context_getter
, quota_manager_proxy
, blob_context
));
303 CacheStorageCache::~CacheStorageCache() {
306 base::WeakPtr
<CacheStorageCache
> CacheStorageCache::AsWeakPtr() {
307 return weak_ptr_factory_
.GetWeakPtr();
310 void CacheStorageCache::Match(scoped_ptr
<ServiceWorkerFetchRequest
> request
,
311 const ResponseCallback
& callback
) {
312 if (!LazyInitialize()) {
313 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
,
314 scoped_ptr
<ServiceWorkerResponse
>(),
315 scoped_ptr
<storage::BlobDataHandle
>());
319 ResponseCallback pending_callback
=
320 base::Bind(&CacheStorageCache::PendingResponseCallback
,
321 weak_ptr_factory_
.GetWeakPtr(), callback
);
322 scheduler_
->ScheduleOperation(
323 base::Bind(&CacheStorageCache::MatchImpl
, weak_ptr_factory_
.GetWeakPtr(),
324 base::Passed(request
.Pass()), pending_callback
));
327 void CacheStorageCache::MatchAll(const ResponsesCallback
& callback
) {
328 if (!LazyInitialize()) {
329 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
, scoped_ptr
<Responses
>(),
330 scoped_ptr
<BlobDataHandles
>());
334 ResponsesCallback pending_callback
=
335 base::Bind(&CacheStorageCache::PendingResponsesCallback
,
336 weak_ptr_factory_
.GetWeakPtr(), callback
);
337 scheduler_
->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl
,
338 weak_ptr_factory_
.GetWeakPtr(),
342 void CacheStorageCache::BatchOperation(
343 const std::vector
<CacheStorageBatchOperation
>& operations
,
344 const ErrorCallback
& callback
) {
345 if (!LazyInitialize()) {
346 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
350 scoped_ptr
<ErrorCallback
> callback_copy(new ErrorCallback(callback
));
351 ErrorCallback
* callback_ptr
= callback_copy
.get();
352 base::Closure barrier_closure
= base::BarrierClosure(
353 operations
.size(), base::Bind(&CacheStorageCache::BatchDidAllOperations
,
354 this, base::Passed(callback_copy
.Pass())));
355 ErrorCallback completion_callback
=
356 base::Bind(&CacheStorageCache::BatchDidOneOperation
, this,
357 barrier_closure
, callback_ptr
);
359 for (const auto& operation
: operations
) {
360 switch (operation
.operation_type
) {
361 case CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT
:
362 Put(operation
, completion_callback
);
364 case CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE
:
365 DCHECK_EQ(1u, operations
.size());
366 Delete(operation
, completion_callback
);
368 case CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED
:
370 // TODO(nhiroki): This should return "TypeError".
371 // http://crbug.com/425505
372 completion_callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
378 void CacheStorageCache::BatchDidOneOperation(
379 const base::Closure
& barrier_closure
,
380 ErrorCallback
* callback
,
381 CacheStorageError error
) {
382 if (callback
->is_null() || error
== CACHE_STORAGE_OK
) {
383 barrier_closure
.Run();
386 callback
->Run(error
);
387 callback
->Reset(); // Only call the callback once.
389 barrier_closure
.Run();
392 void CacheStorageCache::BatchDidAllOperations(
393 scoped_ptr
<ErrorCallback
> callback
) {
394 if (callback
->is_null())
396 callback
->Run(CACHE_STORAGE_OK
);
399 void CacheStorageCache::Keys(const RequestsCallback
& callback
) {
400 if (!LazyInitialize()) {
401 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
, scoped_ptr
<Requests
>());
405 RequestsCallback pending_callback
=
406 base::Bind(&CacheStorageCache::PendingRequestsCallback
,
407 weak_ptr_factory_
.GetWeakPtr(), callback
);
408 scheduler_
->ScheduleOperation(base::Bind(&CacheStorageCache::KeysImpl
,
409 weak_ptr_factory_
.GetWeakPtr(),
413 void CacheStorageCache::Close(const base::Closure
& callback
) {
414 DCHECK_NE(BACKEND_CLOSED
, backend_state_
)
415 << "Was CacheStorageCache::Close() called twice?";
417 base::Closure pending_callback
=
418 base::Bind(&CacheStorageCache::PendingClosure
,
419 weak_ptr_factory_
.GetWeakPtr(), callback
);
421 scheduler_
->ScheduleOperation(base::Bind(&CacheStorageCache::CloseImpl
,
422 weak_ptr_factory_
.GetWeakPtr(),
426 int64
CacheStorageCache::MemoryBackedSize() const {
427 if (backend_state_
!= BACKEND_OPEN
|| !memory_only_
)
430 scoped_ptr
<disk_cache::Backend::Iterator
> backend_iter
=
431 backend_
->CreateIterator();
432 disk_cache::Entry
* entry
= nullptr;
436 std::vector
<disk_cache::Entry
*> entries
;
438 while ((rv
= backend_iter
->OpenNextEntry(
439 &entry
, base::Bind(NotReachedCompletionCallback
))) == net::OK
) {
440 entries
.push_back(entry
); // Open the entries without mutating them.
442 DCHECK_NE(net::ERR_IO_PENDING
, rv
)
443 << "Memory cache operations should be synchronous.";
445 for (disk_cache::Entry
* entry
: entries
) {
446 sum
+= entry
->GetDataSize(INDEX_HEADERS
) +
447 entry
->GetDataSize(INDEX_RESPONSE_BODY
);
454 CacheStorageCache::CacheStorageCache(
456 const base::FilePath
& path
,
457 const scoped_refptr
<net::URLRequestContextGetter
>& request_context_getter
,
458 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
459 base::WeakPtr
<storage::BlobStorageContext
> blob_context
)
462 request_context_getter_(request_context_getter
),
463 quota_manager_proxy_(quota_manager_proxy
),
464 blob_storage_context_(blob_context
),
465 backend_state_(BACKEND_UNINITIALIZED
),
466 scheduler_(new CacheStorageScheduler()),
467 initializing_(false),
468 memory_only_(path
.empty()),
469 weak_ptr_factory_(this) {
472 bool CacheStorageCache::LazyInitialize() {
473 switch (backend_state_
) {
474 case BACKEND_UNINITIALIZED
:
487 void CacheStorageCache::OpenAllEntries(const OpenAllEntriesCallback
& callback
) {
488 scoped_ptr
<OpenAllEntriesContext
> entries_context(new OpenAllEntriesContext
);
489 entries_context
->backend_iterator
= backend_
->CreateIterator();
490 disk_cache::Backend::Iterator
& iterator
= *entries_context
->backend_iterator
;
491 disk_cache::Entry
** enumerated_entry
= &entries_context
->enumerated_entry
;
493 net::CompletionCallback open_entry_callback
= base::Bind(
494 &CacheStorageCache::DidOpenNextEntry
, weak_ptr_factory_
.GetWeakPtr(),
495 base::Passed(entries_context
.Pass()), callback
);
497 int rv
= iterator
.OpenNextEntry(enumerated_entry
, open_entry_callback
);
499 if (rv
!= net::ERR_IO_PENDING
)
500 open_entry_callback
.Run(rv
);
503 void CacheStorageCache::DidOpenNextEntry(
504 scoped_ptr
<OpenAllEntriesContext
> entries_context
,
505 const OpenAllEntriesCallback
& callback
,
507 if (rv
== net::ERR_FAILED
) {
508 DCHECK(!entries_context
->enumerated_entry
);
509 // Enumeration is complete, extract the requests from the entries.
510 callback
.Run(entries_context
.Pass(), CACHE_STORAGE_OK
);
515 callback
.Run(entries_context
.Pass(), CACHE_STORAGE_ERROR_STORAGE
);
519 if (backend_state_
!= BACKEND_OPEN
) {
520 callback
.Run(entries_context
.Pass(), CACHE_STORAGE_ERROR_NOT_FOUND
);
525 entries_context
->entries
.push_back(entries_context
->enumerated_entry
);
526 entries_context
->enumerated_entry
= nullptr;
528 // Enumerate the next entry.
529 disk_cache::Backend::Iterator
& iterator
= *entries_context
->backend_iterator
;
530 disk_cache::Entry
** enumerated_entry
= &entries_context
->enumerated_entry
;
531 net::CompletionCallback open_entry_callback
= base::Bind(
532 &CacheStorageCache::DidOpenNextEntry
, weak_ptr_factory_
.GetWeakPtr(),
533 base::Passed(entries_context
.Pass()), callback
);
535 rv
= iterator
.OpenNextEntry(enumerated_entry
, open_entry_callback
);
537 if (rv
!= net::ERR_IO_PENDING
)
538 open_entry_callback
.Run(rv
);
541 void CacheStorageCache::MatchImpl(scoped_ptr
<ServiceWorkerFetchRequest
> request
,
542 const ResponseCallback
& callback
) {
543 DCHECK_NE(BACKEND_UNINITIALIZED
, backend_state_
);
544 if (backend_state_
!= BACKEND_OPEN
) {
545 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
,
546 scoped_ptr
<ServiceWorkerResponse
>(),
547 scoped_ptr
<storage::BlobDataHandle
>());
551 scoped_ptr
<disk_cache::Entry
*> scoped_entry_ptr(new disk_cache::Entry
*());
552 disk_cache::Entry
** entry_ptr
= scoped_entry_ptr
.get();
553 ServiceWorkerFetchRequest
* request_ptr
= request
.get();
555 net::CompletionCallback open_entry_callback
=
556 base::Bind(&CacheStorageCache::MatchDidOpenEntry
,
557 weak_ptr_factory_
.GetWeakPtr(), base::Passed(request
.Pass()),
558 callback
, base::Passed(scoped_entry_ptr
.Pass()));
560 int rv
= backend_
->OpenEntry(request_ptr
->url
.spec(), entry_ptr
,
561 open_entry_callback
);
562 if (rv
!= net::ERR_IO_PENDING
)
563 open_entry_callback
.Run(rv
);
566 void CacheStorageCache::MatchDidOpenEntry(
567 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
568 const ResponseCallback
& callback
,
569 scoped_ptr
<disk_cache::Entry
*> entry_ptr
,
572 callback
.Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
573 scoped_ptr
<ServiceWorkerResponse
>(),
574 scoped_ptr
<storage::BlobDataHandle
>());
577 disk_cache::ScopedEntryPtr
entry(*entry_ptr
);
579 MetadataCallback headers_callback
= base::Bind(
580 &CacheStorageCache::MatchDidReadMetadata
, weak_ptr_factory_
.GetWeakPtr(),
581 base::Passed(request
.Pass()), callback
, base::Passed(entry
.Pass()));
583 ReadMetadata(*entry_ptr
, headers_callback
);
586 void CacheStorageCache::MatchDidReadMetadata(
587 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
588 const ResponseCallback
& callback
,
589 disk_cache::ScopedEntryPtr entry
,
590 scoped_ptr
<CacheMetadata
> metadata
) {
592 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
,
593 scoped_ptr
<ServiceWorkerResponse
>(),
594 scoped_ptr
<storage::BlobDataHandle
>());
598 scoped_ptr
<ServiceWorkerResponse
> response(new ServiceWorkerResponse
);
599 PopulateResponseMetadata(*metadata
, response
.get());
601 ServiceWorkerHeaderMap cached_request_headers
;
602 for (int i
= 0; i
< metadata
->request().headers_size(); ++i
) {
603 const CacheHeaderMap header
= metadata
->request().headers(i
);
604 DCHECK_EQ(std::string::npos
, header
.name().find('\0'));
605 DCHECK_EQ(std::string::npos
, header
.value().find('\0'));
606 cached_request_headers
[header
.name()] = header
.value();
609 if (!VaryMatches(request
->headers
, cached_request_headers
,
610 response
->headers
)) {
611 callback
.Run(CACHE_STORAGE_ERROR_NOT_FOUND
,
612 scoped_ptr
<ServiceWorkerResponse
>(),
613 scoped_ptr
<storage::BlobDataHandle
>());
617 if (entry
->GetDataSize(INDEX_RESPONSE_BODY
) == 0) {
618 callback
.Run(CACHE_STORAGE_OK
, response
.Pass(),
619 scoped_ptr
<storage::BlobDataHandle
>());
623 if (!blob_storage_context_
) {
624 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
,
625 scoped_ptr
<ServiceWorkerResponse
>(),
626 scoped_ptr
<storage::BlobDataHandle
>());
630 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
=
631 PopulateResponseBody(entry
.Pass(), response
.get());
632 callback
.Run(CACHE_STORAGE_OK
, response
.Pass(), blob_data_handle
.Pass());
635 void CacheStorageCache::MatchAllImpl(const ResponsesCallback
& callback
) {
636 DCHECK_NE(BACKEND_UNINITIALIZED
, backend_state_
);
637 if (backend_state_
!= BACKEND_OPEN
) {
638 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
, scoped_ptr
<Responses
>(),
639 scoped_ptr
<BlobDataHandles
>());
643 OpenAllEntries(base::Bind(&CacheStorageCache::MatchAllDidOpenAllEntries
,
644 weak_ptr_factory_
.GetWeakPtr(), callback
));
647 void CacheStorageCache::MatchAllDidOpenAllEntries(
648 const ResponsesCallback
& callback
,
649 scoped_ptr
<OpenAllEntriesContext
> entries_context
,
650 CacheStorageError error
) {
651 if (error
!= CACHE_STORAGE_OK
) {
652 callback
.Run(error
, scoped_ptr
<Responses
>(), scoped_ptr
<BlobDataHandles
>());
656 scoped_ptr
<MatchAllContext
> context(new MatchAllContext(callback
));
657 context
->entries_context
.swap(entries_context
);
658 Entries::iterator iter
= context
->entries_context
->entries
.begin();
659 MatchAllProcessNextEntry(context
.Pass(), iter
);
662 void CacheStorageCache::MatchAllProcessNextEntry(
663 scoped_ptr
<MatchAllContext
> context
,
664 const Entries::iterator
& iter
) {
665 if (iter
== context
->entries_context
->entries
.end()) {
666 // All done. Return all of the responses.
667 context
->original_callback
.Run(CACHE_STORAGE_OK
,
668 context
->out_responses
.Pass(),
669 context
->out_blob_data_handles
.Pass());
673 ReadMetadata(*iter
, base::Bind(&CacheStorageCache::MatchAllDidReadMetadata
,
674 weak_ptr_factory_
.GetWeakPtr(),
675 base::Passed(context
.Pass()), iter
));
678 void CacheStorageCache::MatchAllDidReadMetadata(
679 scoped_ptr
<MatchAllContext
> context
,
680 const Entries::iterator
& iter
,
681 scoped_ptr
<CacheMetadata
> metadata
) {
682 // Move ownership of the entry from the context.
683 disk_cache::ScopedEntryPtr
entry(*iter
);
688 MatchAllProcessNextEntry(context
.Pass(), iter
+ 1);
692 ServiceWorkerResponse response
;
693 PopulateResponseMetadata(*metadata
, &response
);
695 if (entry
->GetDataSize(INDEX_RESPONSE_BODY
) == 0) {
696 context
->out_responses
->push_back(response
);
697 MatchAllProcessNextEntry(context
.Pass(), iter
+ 1);
701 if (!blob_storage_context_
) {
702 context
->original_callback
.Run(CACHE_STORAGE_ERROR_STORAGE
,
703 scoped_ptr
<Responses
>(),
704 scoped_ptr
<BlobDataHandles
>());
708 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
=
709 PopulateResponseBody(entry
.Pass(), &response
);
711 context
->out_responses
->push_back(response
);
712 context
->out_blob_data_handles
->push_back(*blob_data_handle
);
713 MatchAllProcessNextEntry(context
.Pass(), iter
+ 1);
716 void CacheStorageCache::Put(const CacheStorageBatchOperation
& operation
,
717 const ErrorCallback
& callback
) {
718 DCHECK(BACKEND_OPEN
== backend_state_
|| initializing_
);
719 DCHECK_EQ(CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT
, operation
.operation_type
);
721 scoped_ptr
<ServiceWorkerFetchRequest
> request(new ServiceWorkerFetchRequest(
722 operation
.request
.url
, operation
.request
.method
,
723 operation
.request
.headers
, operation
.request
.referrer
,
724 operation
.request
.is_reload
));
726 // We don't support streaming for cache.
727 DCHECK(operation
.response
.stream_url
.is_empty());
728 // We don't support the body of redirect response.
729 DCHECK(!(operation
.response
.response_type
==
730 blink::WebServiceWorkerResponseTypeOpaqueRedirect
&&
731 operation
.response
.blob_size
));
732 scoped_ptr
<ServiceWorkerResponse
> response(new ServiceWorkerResponse(
733 operation
.response
.url
, operation
.response
.status_code
,
734 operation
.response
.status_text
, operation
.response
.response_type
,
735 operation
.response
.headers
, operation
.response
.blob_uuid
,
736 operation
.response
.blob_size
, operation
.response
.stream_url
,
737 operation
.response
.error
));
739 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
;
741 if (!response
->blob_uuid
.empty()) {
742 if (!blob_storage_context_
) {
743 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
747 blob_storage_context_
->GetBlobDataFromUUID(response
->blob_uuid
);
748 if (!blob_data_handle
) {
749 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
754 ErrorCallback pending_callback
=
755 base::Bind(&CacheStorageCache::PendingErrorCallback
,
756 weak_ptr_factory_
.GetWeakPtr(), callback
);
758 scoped_ptr
<PutContext
> put_context(new PutContext(
759 origin_
, request
.Pass(), response
.Pass(), blob_data_handle
.Pass(),
760 pending_callback
, request_context_getter_
, quota_manager_proxy_
));
762 scheduler_
->ScheduleOperation(base::Bind(&CacheStorageCache::PutImpl
,
763 weak_ptr_factory_
.GetWeakPtr(),
764 base::Passed(put_context
.Pass())));
767 void CacheStorageCache::PutImpl(scoped_ptr
<PutContext
> put_context
) {
768 DCHECK_NE(BACKEND_UNINITIALIZED
, backend_state_
);
769 if (backend_state_
!= BACKEND_OPEN
) {
770 put_context
->callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
774 scoped_ptr
<ServiceWorkerFetchRequest
> request_copy(
775 new ServiceWorkerFetchRequest(*put_context
->request
));
777 DeleteImpl(request_copy
.Pass(), base::Bind(&CacheStorageCache::PutDidDelete
,
778 weak_ptr_factory_
.GetWeakPtr(),
779 base::Passed(put_context
.Pass())));
782 void CacheStorageCache::PutDidDelete(scoped_ptr
<PutContext
> put_context
,
783 CacheStorageError delete_error
) {
784 if (backend_state_
!= BACKEND_OPEN
) {
785 put_context
->callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
789 scoped_ptr
<disk_cache::Entry
*> scoped_entry_ptr(new disk_cache::Entry
*());
790 disk_cache::Entry
** entry_ptr
= scoped_entry_ptr
.get();
791 ServiceWorkerFetchRequest
* request_ptr
= put_context
->request
.get();
792 disk_cache::Backend
* backend_ptr
= backend_
.get();
794 net::CompletionCallback create_entry_callback
= base::Bind(
795 &CacheStorageCache::PutDidCreateEntry
, weak_ptr_factory_
.GetWeakPtr(),
796 base::Passed(scoped_entry_ptr
.Pass()), base::Passed(put_context
.Pass()));
798 int create_rv
= backend_ptr
->CreateEntry(request_ptr
->url
.spec(), entry_ptr
,
799 create_entry_callback
);
801 if (create_rv
!= net::ERR_IO_PENDING
)
802 create_entry_callback
.Run(create_rv
);
805 void CacheStorageCache::PutDidCreateEntry(
806 scoped_ptr
<disk_cache::Entry
*> entry_ptr
,
807 scoped_ptr
<PutContext
> put_context
,
810 put_context
->callback
.Run(CACHE_STORAGE_ERROR_EXISTS
);
813 put_context
->cache_entry
.reset(*entry_ptr
);
815 CacheMetadata metadata
;
816 CacheRequest
* request_metadata
= metadata
.mutable_request();
817 request_metadata
->set_method(put_context
->request
->method
);
818 for (ServiceWorkerHeaderMap::const_iterator it
=
819 put_context
->request
->headers
.begin();
820 it
!= put_context
->request
->headers
.end(); ++it
) {
821 DCHECK_EQ(std::string::npos
, it
->first
.find('\0'));
822 DCHECK_EQ(std::string::npos
, it
->second
.find('\0'));
823 CacheHeaderMap
* header_map
= request_metadata
->add_headers();
824 header_map
->set_name(it
->first
);
825 header_map
->set_value(it
->second
);
828 CacheResponse
* response_metadata
= metadata
.mutable_response();
829 response_metadata
->set_status_code(put_context
->response
->status_code
);
830 response_metadata
->set_status_text(put_context
->response
->status_text
);
831 response_metadata
->set_response_type(
832 WebResponseTypeToProtoResponseType(put_context
->response
->response_type
));
833 response_metadata
->set_url(put_context
->response
->url
.spec());
834 for (ServiceWorkerHeaderMap::const_iterator it
=
835 put_context
->response
->headers
.begin();
836 it
!= put_context
->response
->headers
.end(); ++it
) {
837 DCHECK_EQ(std::string::npos
, it
->first
.find('\0'));
838 DCHECK_EQ(std::string::npos
, it
->second
.find('\0'));
839 CacheHeaderMap
* header_map
= response_metadata
->add_headers();
840 header_map
->set_name(it
->first
);
841 header_map
->set_value(it
->second
);
844 scoped_ptr
<std::string
> serialized(new std::string());
845 if (!metadata
.SerializeToString(serialized
.get())) {
846 put_context
->callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
850 scoped_refptr
<net::StringIOBuffer
> buffer(
851 new net::StringIOBuffer(serialized
.Pass()));
853 // Get a temporary copy of the entry pointer before passing it in base::Bind.
854 disk_cache::Entry
* temp_entry_ptr
= put_context
->cache_entry
.get();
856 net::CompletionCallback write_headers_callback
= base::Bind(
857 &CacheStorageCache::PutDidWriteHeaders
, weak_ptr_factory_
.GetWeakPtr(),
858 base::Passed(put_context
.Pass()), buffer
->size());
860 rv
= temp_entry_ptr
->WriteData(INDEX_HEADERS
, 0 /* offset */, buffer
.get(),
861 buffer
->size(), write_headers_callback
,
862 true /* truncate */);
864 if (rv
!= net::ERR_IO_PENDING
)
865 write_headers_callback
.Run(rv
);
868 void CacheStorageCache::PutDidWriteHeaders(scoped_ptr
<PutContext
> put_context
,
871 if (rv
!= expected_bytes
) {
872 put_context
->cache_entry
->Doom();
873 put_context
->callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
877 // The metadata is written, now for the response content. The data is streamed
878 // from the blob into the cache entry.
880 if (put_context
->response
->blob_uuid
.empty()) {
881 if (put_context
->quota_manager_proxy
.get()) {
882 put_context
->quota_manager_proxy
->NotifyStorageModified(
883 storage::QuotaClient::kServiceWorkerCache
, put_context
->origin
,
884 storage::kStorageTypeTemporary
,
885 put_context
->cache_entry
->GetDataSize(INDEX_HEADERS
));
888 put_context
->callback
.Run(CACHE_STORAGE_OK
);
892 DCHECK(put_context
->blob_data_handle
);
894 disk_cache::ScopedEntryPtr
entry(put_context
->cache_entry
.Pass());
895 put_context
->cache_entry
= NULL
;
897 CacheStorageBlobToDiskCache
* blob_to_cache
=
898 new CacheStorageBlobToDiskCache();
899 BlobToDiskCacheIDMap::KeyType blob_to_cache_key
=
900 active_blob_to_disk_cache_writers_
.Add(blob_to_cache
);
902 // Grab some pointers before passing put_context in Bind.
903 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter
=
904 put_context
->request_context_getter
;
905 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
=
906 put_context
->blob_data_handle
.Pass();
908 blob_to_cache
->StreamBlobToCache(
909 entry
.Pass(), INDEX_RESPONSE_BODY
, request_context_getter
,
910 blob_data_handle
.Pass(),
911 base::Bind(&CacheStorageCache::PutDidWriteBlobToCache
,
912 weak_ptr_factory_
.GetWeakPtr(),
913 base::Passed(put_context
.Pass()), blob_to_cache_key
));
916 void CacheStorageCache::PutDidWriteBlobToCache(
917 scoped_ptr
<PutContext
> put_context
,
918 BlobToDiskCacheIDMap::KeyType blob_to_cache_key
,
919 disk_cache::ScopedEntryPtr entry
,
922 put_context
->cache_entry
= entry
.Pass();
924 active_blob_to_disk_cache_writers_
.Remove(blob_to_cache_key
);
927 put_context
->cache_entry
->Doom();
928 put_context
->callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
932 if (put_context
->quota_manager_proxy
.get()) {
933 put_context
->quota_manager_proxy
->NotifyStorageModified(
934 storage::QuotaClient::kServiceWorkerCache
, put_context
->origin
,
935 storage::kStorageTypeTemporary
,
936 put_context
->cache_entry
->GetDataSize(INDEX_HEADERS
) +
937 put_context
->cache_entry
->GetDataSize(INDEX_RESPONSE_BODY
));
940 put_context
->callback
.Run(CACHE_STORAGE_OK
);
943 void CacheStorageCache::Delete(const CacheStorageBatchOperation
& operation
,
944 const ErrorCallback
& callback
) {
945 DCHECK(BACKEND_OPEN
== backend_state_
|| initializing_
);
946 DCHECK_EQ(CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE
,
947 operation
.operation_type
);
949 scoped_ptr
<ServiceWorkerFetchRequest
> request(new ServiceWorkerFetchRequest(
950 operation
.request
.url
, operation
.request
.method
,
951 operation
.request
.headers
, operation
.request
.referrer
,
952 operation
.request
.is_reload
));
954 ErrorCallback pending_callback
=
955 base::Bind(&CacheStorageCache::PendingErrorCallback
,
956 weak_ptr_factory_
.GetWeakPtr(), callback
);
957 scheduler_
->ScheduleOperation(
958 base::Bind(&CacheStorageCache::DeleteImpl
, weak_ptr_factory_
.GetWeakPtr(),
959 base::Passed(request
.Pass()), pending_callback
));
962 void CacheStorageCache::DeleteImpl(
963 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
964 const ErrorCallback
& callback
) {
965 DCHECK_NE(BACKEND_UNINITIALIZED
, backend_state_
);
966 if (backend_state_
!= BACKEND_OPEN
) {
967 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
970 scoped_ptr
<disk_cache::Entry
*> entry(new disk_cache::Entry
*);
972 disk_cache::Entry
** entry_ptr
= entry
.get();
974 ServiceWorkerFetchRequest
* request_ptr
= request
.get();
976 net::CompletionCallback open_entry_callback
= base::Bind(
977 &CacheStorageCache::DeleteDidOpenEntry
, weak_ptr_factory_
.GetWeakPtr(),
978 origin_
, base::Passed(request
.Pass()), callback
,
979 base::Passed(entry
.Pass()), quota_manager_proxy_
);
981 int rv
= backend_
->OpenEntry(request_ptr
->url
.spec(), entry_ptr
,
982 open_entry_callback
);
983 if (rv
!= net::ERR_IO_PENDING
)
984 open_entry_callback
.Run(rv
);
987 void CacheStorageCache::DeleteDidOpenEntry(
989 scoped_ptr
<ServiceWorkerFetchRequest
> request
,
990 const CacheStorageCache::ErrorCallback
& callback
,
991 scoped_ptr
<disk_cache::Entry
*> entry_ptr
,
992 const scoped_refptr
<storage::QuotaManagerProxy
>& quota_manager_proxy
,
995 callback
.Run(CACHE_STORAGE_ERROR_NOT_FOUND
);
1000 disk_cache::ScopedEntryPtr
entry(*entry_ptr
);
1002 if (quota_manager_proxy
.get()) {
1003 quota_manager_proxy
->NotifyStorageModified(
1004 storage::QuotaClient::kServiceWorkerCache
, origin
,
1005 storage::kStorageTypeTemporary
,
1006 -1 * (entry
->GetDataSize(INDEX_HEADERS
) +
1007 entry
->GetDataSize(INDEX_RESPONSE_BODY
)));
1011 callback
.Run(CACHE_STORAGE_OK
);
1014 void CacheStorageCache::KeysImpl(const RequestsCallback
& callback
) {
1015 DCHECK_NE(BACKEND_UNINITIALIZED
, backend_state_
);
1016 if (backend_state_
!= BACKEND_OPEN
) {
1017 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
, scoped_ptr
<Requests
>());
1021 // 1. Iterate through all of the entries, open them, and add them to a vector.
1022 // 2. For each open entry:
1023 // 2.1. Read the headers into a protobuf.
1024 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key").
1025 // 2.3. Push the response into a vector of requests to be returned.
1026 // 3. Return the vector of requests (keys).
1028 // The entries have to be loaded into a vector first because enumeration loops
1029 // forever if you read data from a cache entry while enumerating.
1031 OpenAllEntries(base::Bind(&CacheStorageCache::KeysDidOpenAllEntries
,
1032 weak_ptr_factory_
.GetWeakPtr(), callback
));
1035 void CacheStorageCache::KeysDidOpenAllEntries(
1036 const RequestsCallback
& callback
,
1037 scoped_ptr
<OpenAllEntriesContext
> entries_context
,
1038 CacheStorageError error
) {
1039 if (error
!= CACHE_STORAGE_OK
) {
1040 callback
.Run(error
, scoped_ptr
<Requests
>());
1044 scoped_ptr
<KeysContext
> keys_context(new KeysContext(callback
));
1045 keys_context
->entries_context
.swap(entries_context
);
1046 Entries::iterator iter
= keys_context
->entries_context
->entries
.begin();
1047 KeysProcessNextEntry(keys_context
.Pass(), iter
);
1050 void CacheStorageCache::KeysProcessNextEntry(
1051 scoped_ptr
<KeysContext
> keys_context
,
1052 const Entries::iterator
& iter
) {
1053 if (iter
== keys_context
->entries_context
->entries
.end()) {
1054 // All done. Return all of the keys.
1055 keys_context
->original_callback
.Run(CACHE_STORAGE_OK
,
1056 keys_context
->out_keys
.Pass());
1060 ReadMetadata(*iter
, base::Bind(&CacheStorageCache::KeysDidReadMetadata
,
1061 weak_ptr_factory_
.GetWeakPtr(),
1062 base::Passed(keys_context
.Pass()), iter
));
1065 void CacheStorageCache::KeysDidReadMetadata(
1066 scoped_ptr
<KeysContext
> keys_context
,
1067 const Entries::iterator
& iter
,
1068 scoped_ptr
<CacheMetadata
> metadata
) {
1069 disk_cache::Entry
* entry
= *iter
;
1072 keys_context
->out_keys
->push_back(ServiceWorkerFetchRequest(
1073 GURL(entry
->GetKey()), metadata
->request().method(),
1074 ServiceWorkerHeaderMap(), Referrer(), false));
1076 ServiceWorkerHeaderMap
& req_headers
=
1077 keys_context
->out_keys
->back().headers
;
1079 for (int i
= 0; i
< metadata
->request().headers_size(); ++i
) {
1080 const CacheHeaderMap header
= metadata
->request().headers(i
);
1081 DCHECK_EQ(std::string::npos
, header
.name().find('\0'));
1082 DCHECK_EQ(std::string::npos
, header
.value().find('\0'));
1083 req_headers
.insert(std::make_pair(header
.name(), header
.value()));
1089 KeysProcessNextEntry(keys_context
.Pass(), iter
+ 1);
1092 void CacheStorageCache::CloseImpl(const base::Closure
& callback
) {
1093 DCHECK_NE(BACKEND_CLOSED
, backend_state_
);
1095 backend_state_
= BACKEND_CLOSED
;
1100 void CacheStorageCache::CreateBackend(const ErrorCallback
& callback
) {
1103 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
1104 net::CacheType cache_type
= memory_only_
? net::MEMORY_CACHE
: net::APP_CACHE
;
1106 scoped_ptr
<ScopedBackendPtr
> backend_ptr(new ScopedBackendPtr());
1108 // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
1109 ScopedBackendPtr
* backend
= backend_ptr
.get();
1111 net::CompletionCallback create_cache_callback
=
1112 base::Bind(&CacheStorageCache::CreateBackendDidCreate
,
1113 weak_ptr_factory_
.GetWeakPtr(), callback
,
1114 base::Passed(backend_ptr
.Pass()));
1116 // TODO(jkarlin): Use the cache task runner that ServiceWorkerCacheCore
1117 // has for disk caches.
1118 int rv
= disk_cache::CreateCacheBackend(
1119 cache_type
, net::CACHE_BACKEND_SIMPLE
, path_
, kMaxCacheBytes
,
1121 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE
).get(),
1122 NULL
, backend
, create_cache_callback
);
1123 if (rv
!= net::ERR_IO_PENDING
)
1124 create_cache_callback
.Run(rv
);
1127 void CacheStorageCache::CreateBackendDidCreate(
1128 const CacheStorageCache::ErrorCallback
& callback
,
1129 scoped_ptr
<ScopedBackendPtr
> backend_ptr
,
1131 if (rv
!= net::OK
) {
1132 callback
.Run(CACHE_STORAGE_ERROR_STORAGE
);
1136 backend_
= backend_ptr
->Pass();
1137 callback
.Run(CACHE_STORAGE_OK
);
1140 void CacheStorageCache::InitBackend() {
1141 DCHECK_EQ(BACKEND_UNINITIALIZED
, backend_state_
);
1146 DCHECK(!scheduler_
->ScheduledOperations());
1147 initializing_
= true;
1149 scheduler_
->ScheduleOperation(base::Bind(
1150 &CacheStorageCache::CreateBackend
, weak_ptr_factory_
.GetWeakPtr(),
1151 base::Bind(&CacheStorageCache::InitDone
,
1152 weak_ptr_factory_
.GetWeakPtr())));
1155 void CacheStorageCache::InitDone(CacheStorageError error
) {
1156 initializing_
= false;
1157 backend_state_
= (error
== CACHE_STORAGE_OK
&& backend_
&&
1158 backend_state_
== BACKEND_UNINITIALIZED
)
1162 UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", error
,
1163 CACHE_STORAGE_ERROR_LAST
+ 1);
1165 scheduler_
->CompleteOperationAndRunNext();
1168 void CacheStorageCache::PendingClosure(const base::Closure
& callback
) {
1169 base::WeakPtr
<CacheStorageCache
> cache
= weak_ptr_factory_
.GetWeakPtr();
1173 scheduler_
->CompleteOperationAndRunNext();
1176 void CacheStorageCache::PendingErrorCallback(const ErrorCallback
& callback
,
1177 CacheStorageError error
) {
1178 base::WeakPtr
<CacheStorageCache
> cache
= weak_ptr_factory_
.GetWeakPtr();
1180 callback
.Run(error
);
1182 scheduler_
->CompleteOperationAndRunNext();
1185 void CacheStorageCache::PendingResponseCallback(
1186 const ResponseCallback
& callback
,
1187 CacheStorageError error
,
1188 scoped_ptr
<ServiceWorkerResponse
> response
,
1189 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
1190 base::WeakPtr
<CacheStorageCache
> cache
= weak_ptr_factory_
.GetWeakPtr();
1192 callback
.Run(error
, response
.Pass(), blob_data_handle
.Pass());
1194 scheduler_
->CompleteOperationAndRunNext();
1197 void CacheStorageCache::PendingResponsesCallback(
1198 const ResponsesCallback
& callback
,
1199 CacheStorageError error
,
1200 scoped_ptr
<Responses
> responses
,
1201 scoped_ptr
<BlobDataHandles
> blob_data_handles
) {
1202 base::WeakPtr
<CacheStorageCache
> cache
= weak_ptr_factory_
.GetWeakPtr();
1204 callback
.Run(error
, responses
.Pass(), blob_data_handles
.Pass());
1206 scheduler_
->CompleteOperationAndRunNext();
1209 void CacheStorageCache::PendingRequestsCallback(
1210 const RequestsCallback
& callback
,
1211 CacheStorageError error
,
1212 scoped_ptr
<Requests
> requests
) {
1213 base::WeakPtr
<CacheStorageCache
> cache
= weak_ptr_factory_
.GetWeakPtr();
1215 callback
.Run(error
, requests
.Pass());
1217 scheduler_
->CompleteOperationAndRunNext();
1220 void CacheStorageCache::PopulateResponseMetadata(
1221 const CacheMetadata
& metadata
,
1222 ServiceWorkerResponse
* response
) {
1223 *response
= ServiceWorkerResponse(
1224 GURL(metadata
.response().url()), metadata
.response().status_code(),
1225 metadata
.response().status_text(),
1226 ProtoResponseTypeToWebResponseType(metadata
.response().response_type()),
1227 ServiceWorkerHeaderMap(), "", 0, GURL(),
1228 blink::WebServiceWorkerResponseErrorUnknown
);
1230 for (int i
= 0; i
< metadata
.response().headers_size(); ++i
) {
1231 const CacheHeaderMap header
= metadata
.response().headers(i
);
1232 DCHECK_EQ(std::string::npos
, header
.name().find('\0'));
1233 DCHECK_EQ(std::string::npos
, header
.value().find('\0'));
1234 response
->headers
.insert(std::make_pair(header
.name(), header
.value()));
1238 scoped_ptr
<storage::BlobDataHandle
> CacheStorageCache::PopulateResponseBody(
1239 disk_cache::ScopedEntryPtr entry
,
1240 ServiceWorkerResponse
* response
) {
1241 DCHECK(blob_storage_context_
);
1243 // Create a blob with the response body data.
1244 response
->blob_size
= entry
->GetDataSize(INDEX_RESPONSE_BODY
);
1245 response
->blob_uuid
= base::GenerateGUID();
1246 storage::BlobDataBuilder
blob_data(response
->blob_uuid
);
1248 disk_cache::Entry
* temp_entry
= entry
.get();
1249 blob_data
.AppendDiskCacheEntry(
1250 new CacheStorageCacheDataHandle(this, entry
.Pass()), temp_entry
,
1251 INDEX_RESPONSE_BODY
);
1252 return blob_storage_context_
->AddFinishedBlob(&blob_data
);
1255 } // namespace content