Chromium Code Reviews| Index: content/browser/cache_storage/cache_storage_cache.cc |
| diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc |
| index b5da1119e1a99cbfe67d259726b2ed37e8d95b88..988d75f4ef3b044e07919f4a55431ff186cc4c9b 100644 |
| --- a/content/browser/cache_storage/cache_storage_cache.cc |
| +++ b/content/browser/cache_storage/cache_storage_cache.cc |
| @@ -9,6 +9,7 @@ |
| #include "base/barrier_closure.h" |
| #include "base/files/file_path.h" |
| #include "base/guid.h" |
| +#include "base/memory/scoped_vector.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| @@ -178,6 +179,36 @@ void ReadMetadataDidReadMetadata( |
| } // namespace |
| +// The state needed to pass between CacheStorageCache::MatchAll callbacks. |
| +struct CacheStorageCache::MatchAllContext { |
| + explicit MatchAllContext(const CacheStorageCache::ResponsesCallback& callback) |
| + : original_callback(callback), enumerated_entry(nullptr) {} |
| + |
| + ~MatchAllContext() { |
| + for (disk_cache::Entry* entry_ptr : entries) |
| + entry_ptr->Close(); |
| + if (enumerated_entry) |
| + enumerated_entry->Close(); |
| + } |
| + |
| + // The callback passed to the MatchAll() function. |
| + CacheStorageCache::ResponsesCallback original_callback; |
| + |
| + // The list of open entries in the backend. |
| + std::list<disk_cache::Entry*> entries; |
| + |
| + // The outputs of the MatchAll function. |
| + std::vector<ServiceWorkerResponse> out_responses; |
| + ScopedVector<storage::BlobDataHandle> out_blob_data_handles; |
| + |
| + // Used for enumerating cache entries. |
| + scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; |
| + disk_cache::Entry* enumerated_entry; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(MatchAllContext); |
| +}; |
| + |
| // The state needed to pass between CacheStorageCache::Keys callbacks. |
| struct CacheStorageCache::KeysContext { |
| explicit KeysContext(const CacheStorageCache::RequestsCallback& callback) |
| @@ -287,6 +318,22 @@ void CacheStorageCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
| base::Passed(request.Pass()), pending_callback)); |
| } |
| +void CacheStorageCache::MatchAll(const ResponsesCallback& callback) { |
| + if (!LazyInitialize()) { |
| + callback.Run(CACHE_STORAGE_ERROR_STORAGE, |
| + std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + ResponsesCallback pending_callback = |
| + base::Bind(&CacheStorageCache::PendingResponsesCallback, |
| + weak_ptr_factory_.GetWeakPtr(), callback); |
| + scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + pending_callback)); |
| +} |
| + |
| void CacheStorageCache::BatchOperation( |
| const std::vector<CacheStorageBatchOperation>& operations, |
| const ErrorCallback& callback) { |
| @@ -549,6 +596,153 @@ void CacheStorageCache::MatchDidReadMetadata( |
| callback.Run(CACHE_STORAGE_OK, response.Pass(), blob_data_handle.Pass()); |
| } |
| +void CacheStorageCache::MatchAllImpl(const ResponsesCallback& callback) { |
| + DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_); |
| + if (backend_state_ != BACKEND_OPEN) { |
| + callback.Run(CACHE_STORAGE_ERROR_STORAGE, |
| + std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + scoped_ptr<MatchAllContext> context(new MatchAllContext(callback)); |
| + |
| + context->backend_iterator = backend_->CreateIterator(); |
| + disk_cache::Backend::Iterator& iterator = *context->backend_iterator; |
| + disk_cache::Entry** enumerated_entry = &context->enumerated_entry; |
| + |
| + net::CompletionCallback open_entry_callback = |
| + base::Bind(&CacheStorageCache::MatchAllDidOpenNextEntry, |
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(context.Pass())); |
| + |
| + int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| + |
| + if (rv != net::ERR_IO_PENDING) |
| + open_entry_callback.Run(rv); |
| +} |
| + |
| +void CacheStorageCache::MatchAllDidOpenNextEntry( |
|
jkarlin
2015/08/04 13:25:07
This method should go, instead make a common utili
nhiroki
2015/08/05 08:03:04
Done.
|
| + scoped_ptr<MatchAllContext> context, |
| + int rv) { |
| + if (rv == net::ERR_FAILED) { |
| + DCHECK(!context->enumerated_entry); |
| + // Enumeration is complete, extract the requests from the entries. |
| + MatchAllProcessNextEntry(context.Pass()); |
| + return; |
| + } |
| + |
| + if (rv < 0) { |
| + context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE, |
| + std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + if (backend_state_ != BACKEND_OPEN) { |
| + context->original_callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND, |
| + std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + // Store the entry. |
| + context->entries.push_back(context->enumerated_entry); |
| + context->enumerated_entry = nullptr; |
| + |
| + // Enumerate the next entry. |
| + disk_cache::Backend::Iterator& iterator = *context->backend_iterator; |
| + disk_cache::Entry** enumerated_entry = &context->enumerated_entry; |
| + net::CompletionCallback open_entry_callback = |
| + base::Bind(&CacheStorageCache::MatchAllDidOpenNextEntry, |
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(context.Pass())); |
| + |
| + rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| + |
| + if (rv != net::ERR_IO_PENDING) |
| + open_entry_callback.Run(rv); |
| +} |
| + |
| +void CacheStorageCache::MatchAllProcessNextEntry( |
| + scoped_ptr<MatchAllContext> context) { |
| + if (context->entries.empty()) { |
| + // All done. Return all of the responses. |
| + context->original_callback.Run(CACHE_STORAGE_OK, context->out_responses, |
| + context->out_blob_data_handles.Pass()); |
| + return; |
| + } |
| + |
| + disk_cache::ScopedEntryPtr entry(context->entries.front()); |
| + context->entries.pop_front(); |
| + disk_cache::Entry* entry_ptr = entry.get(); |
| + ReadMetadata( |
| + entry_ptr, |
| + base::Bind(&CacheStorageCache::MatchAllDidReadMetadata, |
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(context.Pass()), |
| + base::Passed(entry.Pass()))); |
| +} |
| + |
| +void CacheStorageCache::MatchAllDidReadMetadata( |
| + scoped_ptr<MatchAllContext> context, |
| + disk_cache::ScopedEntryPtr entry, |
| + scoped_ptr<CacheMetadata> metadata) { |
| + if (!metadata) { |
| + entry->Doom(); |
| + MatchAllProcessNextEntry(context.Pass()); |
| + return; |
| + } |
| + |
| + ServiceWorkerResponse response( |
|
jkarlin
2015/08/04 13:25:07
The code below should be combined with MatchDidRea
nhiroki
2015/08/05 08:03:04
Done.
|
| + GURL(metadata->response().url()), metadata->response().status_code(), |
| + metadata->response().status_text(), |
| + ProtoResponseTypeToWebResponseType(metadata->response().response_type()), |
| + ServiceWorkerHeaderMap(), "", 0, GURL(), |
| + blink::WebServiceWorkerResponseErrorUnknown); |
| + |
| + for (int i = 0; i < metadata->response().headers_size(); ++i) { |
| + const CacheHeaderMap header = metadata->response().headers(i); |
| + DCHECK_EQ(std::string::npos, header.name().find('\0')); |
| + DCHECK_EQ(std::string::npos, header.value().find('\0')); |
| + response.headers.insert(std::make_pair(header.name(), header.value())); |
| + } |
| + |
| + ServiceWorkerHeaderMap cached_request_headers; |
| + for (int i = 0; i < metadata->request().headers_size(); ++i) { |
| + const CacheHeaderMap header = metadata->request().headers(i); |
| + DCHECK_EQ(std::string::npos, header.name().find('\0')); |
| + DCHECK_EQ(std::string::npos, header.value().find('\0')); |
| + cached_request_headers[header.name()] = header.value(); |
| + } |
| + |
| + if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { |
| + context->out_responses.push_back(response); |
| + context->out_blob_data_handles.push_back(nullptr); |
| + MatchAllProcessNextEntry(context.Pass()); |
| + return; |
| + } |
| + |
| + if (!blob_storage_context_) { |
| + entry->Doom(); |
| + MatchAllProcessNextEntry(context.Pass()); |
| + return; |
| + } |
| + |
| + // Create a blob with the response body data. |
| + response.blob_size = entry->GetDataSize(INDEX_RESPONSE_BODY); |
| + response.blob_uuid = base::GenerateGUID(); |
| + storage::BlobDataBuilder blob_data(response.blob_uuid); |
| + |
| + disk_cache::Entry* entry_ptr = entry.get(); |
| + blob_data.AppendDiskCacheEntry( |
| + new CacheStorageCacheDataHandle(this, entry.Pass()), entry_ptr, |
| + INDEX_RESPONSE_BODY); |
| + scoped_ptr<storage::BlobDataHandle> blob_data_handle( |
| + blob_storage_context_->AddFinishedBlob(&blob_data)); |
| + |
| + context->out_responses.push_back(response); |
| + context->out_blob_data_handles.push_back(blob_data_handle.release()); |
| + MatchAllProcessNextEntry(context.Pass()); |
| +} |
| + |
| void CacheStorageCache::Put(const CacheStorageBatchOperation& operation, |
| const ErrorCallback& callback) { |
| DCHECK(BACKEND_OPEN == backend_state_ || initializing_); |
| @@ -1063,6 +1257,18 @@ void CacheStorageCache::PendingResponseCallback( |
| scheduler_->CompleteOperationAndRunNext(); |
| } |
| +void CacheStorageCache::PendingResponsesCallback( |
| + const ResponsesCallback& callback, |
| + CacheStorageError error, |
| + const std::vector<ServiceWorkerResponse>& responses, |
| + ScopedVector<storage::BlobDataHandle> blob_data_handles) { |
| + base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| + |
| + callback.Run(error, responses, blob_data_handles.Pass()); |
| + if (cache) |
| + scheduler_->CompleteOperationAndRunNext(); |
| +} |
| + |
| void CacheStorageCache::PendingRequestsCallback( |
| const RequestsCallback& callback, |
| CacheStorageError error, |