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, |