[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / cache_storage / cache_storage_cache.cc
blob687f6908c0480fdf6cd2eb2234c833637e6a178c
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"
7 #include <string>
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"
32 namespace content {
34 namespace {
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 {
40 public:
41 CacheStorageCacheDataHandle(const scoped_refptr<CacheStorageCache>& cache,
42 disk_cache::ScopedEntryPtr entry)
43 : cache_(cache), entry_(entry.Pass()) {}
45 private:
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
59 // per-origin.
60 const int kMaxCacheBytes = 512 * 1024 * 1024;
62 void NotReachedCompletionCallback(int rv) {
63 NOTREACHED();
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;
82 NOTREACHED();
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;
102 NOTREACHED();
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,
113 int rv);
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())
120 return true;
122 for (const std::string& trimmed :
123 base::SplitString(vary_iter->second, ",",
124 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
125 if (trimmed == "*")
126 return false;
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()))
135 return false;
137 // If the header exists in one, it exists in both. Verify that the values
138 // are equal.
139 if (request_iter != request.end() &&
140 request_iter->second != cached_request_iter->second)
141 return false;
144 return true;
147 void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
148 DCHECK(entry);
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,
167 int rv) {
168 if (rv != buffer->size()) {
169 callback.Run(scoped_ptr<CacheMetadata>());
170 return;
173 scoped_ptr<CacheMetadata> metadata(new CacheMetadata());
175 if (!metadata->ParseFromArray(buffer->data(), buffer->size())) {
176 callback.Run(scoped_ptr<CacheMetadata>());
177 return;
180 callback.Run(metadata.Pass());
183 } // namespace
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) {
190 if (entries[i])
191 entries[i]->Close();
193 if (enumerated_entry)
194 enumerated_entry->Close();
197 // The vector of open entries in the backend.
198 Entries entries;
200 // Used for enumerating cache entries.
201 scoped_ptr<disk_cache::Backend::Iterator> backend_iterator;
202 disk_cache::Entry* enumerated_entry;
204 private:
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;
226 private:
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()) {}
234 ~KeysContext() {}
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;
245 private:
246 DISALLOW_COPY_AND_ASSIGN(KeysContext);
249 // The state needed to pass between CacheStorageCache::Put callbacks.
250 struct CacheStorageCache::PutContext {
251 PutContext(
252 const GURL& origin,
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)
259 : origin(origin),
260 request(request.Pass()),
261 response(response.Pass()),
262 blob_data_handle(blob_data_handle.Pass()),
263 callback(callback),
264 request_context_getter(request_context_getter),
265 quota_manager_proxy(quota_manager_proxy) {}
267 // Input parameters to the Put function.
268 GURL origin;
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;
277 private:
278 DISALLOW_COPY_AND_ASSIGN(PutContext);
281 // static
282 scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
283 const GURL& origin,
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));
292 // static
293 scoped_refptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
294 const GURL& origin,
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>());
316 return;
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>());
331 return;
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(),
339 pending_callback));
342 void CacheStorageCache::BatchOperation(
343 const std::vector<CacheStorageBatchOperation>& operations,
344 const ErrorCallback& callback) {
345 if (!LazyInitialize()) {
346 callback.Run(CACHE_STORAGE_ERROR_STORAGE);
347 return;
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);
363 break;
364 case CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE:
365 DCHECK_EQ(1u, operations.size());
366 Delete(operation, completion_callback);
367 break;
368 case CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED:
369 NOTREACHED();
370 // TODO(nhiroki): This should return "TypeError".
371 // http://crbug.com/425505
372 completion_callback.Run(CACHE_STORAGE_ERROR_STORAGE);
373 break;
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();
384 return;
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())
395 return;
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>());
402 return;
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(),
410 pending_callback));
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(),
423 pending_callback));
426 int64 CacheStorageCache::MemoryBackedSize() const {
427 if (backend_state_ != BACKEND_OPEN || !memory_only_)
428 return 0;
430 scoped_ptr<disk_cache::Backend::Iterator> backend_iter =
431 backend_->CreateIterator();
432 disk_cache::Entry* entry = nullptr;
434 int64 sum = 0;
436 std::vector<disk_cache::Entry*> entries;
437 int rv = net::OK;
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);
448 entry->Close();
451 return sum;
454 CacheStorageCache::CacheStorageCache(
455 const GURL& origin,
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)
460 : origin_(origin),
461 path_(path),
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:
475 InitBackend();
476 return true;
477 case BACKEND_CLOSED:
478 return false;
479 case BACKEND_OPEN:
480 DCHECK(backend_);
481 return true;
483 NOTREACHED();
484 return false;
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,
506 int rv) {
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);
511 return;
514 if (rv < 0) {
515 callback.Run(entries_context.Pass(), CACHE_STORAGE_ERROR_STORAGE);
516 return;
519 if (backend_state_ != BACKEND_OPEN) {
520 callback.Run(entries_context.Pass(), CACHE_STORAGE_ERROR_NOT_FOUND);
521 return;
524 // Store the entry.
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>());
548 return;
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,
570 int rv) {
571 if (rv != net::OK) {
572 callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND,
573 scoped_ptr<ServiceWorkerResponse>(),
574 scoped_ptr<storage::BlobDataHandle>());
575 return;
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) {
591 if (!metadata) {
592 callback.Run(CACHE_STORAGE_ERROR_STORAGE,
593 scoped_ptr<ServiceWorkerResponse>(),
594 scoped_ptr<storage::BlobDataHandle>());
595 return;
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>());
614 return;
617 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
618 callback.Run(CACHE_STORAGE_OK, response.Pass(),
619 scoped_ptr<storage::BlobDataHandle>());
620 return;
623 if (!blob_storage_context_) {
624 callback.Run(CACHE_STORAGE_ERROR_STORAGE,
625 scoped_ptr<ServiceWorkerResponse>(),
626 scoped_ptr<storage::BlobDataHandle>());
627 return;
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>());
640 return;
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>());
653 return;
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());
670 return;
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);
684 *iter = nullptr;
686 if (!metadata) {
687 entry->Doom();
688 MatchAllProcessNextEntry(context.Pass(), iter + 1);
689 return;
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);
698 return;
701 if (!blob_storage_context_) {
702 context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE,
703 scoped_ptr<Responses>(),
704 scoped_ptr<BlobDataHandles>());
705 return;
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);
744 return;
746 blob_data_handle =
747 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
748 if (!blob_data_handle) {
749 callback.Run(CACHE_STORAGE_ERROR_STORAGE);
750 return;
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);
771 return;
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);
786 return;
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,
808 int rv) {
809 if (rv != net::OK) {
810 put_context->callback.Run(CACHE_STORAGE_ERROR_EXISTS);
811 return;
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);
847 return;
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,
869 int expected_bytes,
870 int rv) {
871 if (rv != expected_bytes) {
872 put_context->cache_entry->Doom();
873 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
874 return;
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);
889 return;
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,
920 bool success) {
921 DCHECK(entry);
922 put_context->cache_entry = entry.Pass();
924 active_blob_to_disk_cache_writers_.Remove(blob_to_cache_key);
926 if (!success) {
927 put_context->cache_entry->Doom();
928 put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
929 return;
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);
968 return;
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(
988 const GURL& origin,
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,
993 int rv) {
994 if (rv != net::OK) {
995 callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND);
996 return;
999 DCHECK(entry_ptr);
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)));
1010 entry->Doom();
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>());
1018 return;
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>());
1041 return;
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());
1057 return;
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;
1071 if (metadata) {
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()));
1085 } else {
1086 entry->Doom();
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;
1096 backend_.reset();
1097 callback.Run();
1100 void CacheStorageCache::CreateBackend(const ErrorCallback& callback) {
1101 DCHECK(!backend_);
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,
1120 false, /* force */
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,
1130 int rv) {
1131 if (rv != net::OK) {
1132 callback.Run(CACHE_STORAGE_ERROR_STORAGE);
1133 return;
1136 backend_ = backend_ptr->Pass();
1137 callback.Run(CACHE_STORAGE_OK);
1140 void CacheStorageCache::InitBackend() {
1141 DCHECK_EQ(BACKEND_UNINITIALIZED, backend_state_);
1143 if (initializing_)
1144 return;
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)
1159 ? BACKEND_OPEN
1160 : BACKEND_CLOSED;
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();
1171 callback.Run();
1172 if (cache)
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);
1181 if (cache)
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());
1193 if (cache)
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());
1205 if (cache)
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());
1216 if (cache)
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