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..95974fa4bed5a074cd11317ae637db39c16a5322 100644 |
| --- a/content/browser/cache_storage/cache_storage_cache.cc |
| +++ b/content/browser/cache_storage/cache_storage_cache.cc |
| @@ -176,34 +176,83 @@ void ReadMetadataDidReadMetadata( |
| callback.Run(metadata.Pass()); |
| } |
| +void PopulateServiceWorkerResponse(const CacheMetadata& metadata, |
|
jkarlin
2015/08/05 12:09:05
Perhaps rename to PopularResponseMetadata or Popul
nhiroki
2015/08/06 03:36:53
Good point. Renamed this.
|
| + ServiceWorkerResponse* response) { |
| + *response = ServiceWorkerResponse( |
| + 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())); |
| + } |
| +} |
| + |
| } // namespace |
| +// The state needed to iterate all entries in the cache. |
| +struct CacheStorageCache::OpenAllEntriesContext { |
| + OpenAllEntriesContext() : enumerated_entry(nullptr) {} |
| + ~OpenAllEntriesContext() { |
| + for (size_t i = 0, max = entries.size(); i < max; ++i) { |
| + if (entries[i]) |
| + entries[i]->Close(); |
| + if (enumerated_entry) |
|
jkarlin
2015/08/05 12:09:05
Why is this in the for loop now?
nhiroki
2015/08/06 03:36:53
Oh..., this is just a mistake. Fixed. Thanks!
|
| + enumerated_entry->Close(); |
| + } |
| + } |
| + |
| + // The vector of open entries in the backend. |
| + Entries entries; |
| + |
| + // Used for enumerating cache entries. |
| + scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; |
| + disk_cache::Entry* enumerated_entry; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(OpenAllEntriesContext); |
| +}; |
| + |
| +// The state needed to pass between CacheStorageCache::MatchAll callbacks. |
| +struct CacheStorageCache::MatchAllContext { |
| + explicit MatchAllContext(const CacheStorageCache::ResponsesCallback& callback) |
| + : original_callback(callback) {} |
| + ~MatchAllContext() {} |
| + |
| + // The callback passed to the MatchAll() function. |
| + CacheStorageCache::ResponsesCallback original_callback; |
| + |
| + // The outputs of the MatchAll function. |
| + std::vector<ServiceWorkerResponse> out_responses; |
|
jkarlin
2015/08/05 12:09:05
scoped_ptr<std::vector<ServiceWorkerResponse>> to
nhiroki
2015/08/06 03:36:53
Done.
|
| + ScopedVector<storage::BlobDataHandle> out_blob_data_handles; |
| + |
| + // The context holding open entries. |
| + scoped_ptr<OpenAllEntriesContext> entries_context; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(MatchAllContext); |
| +}; |
| + |
| // The state needed to pass between CacheStorageCache::Keys callbacks. |
| struct CacheStorageCache::KeysContext { |
| explicit KeysContext(const CacheStorageCache::RequestsCallback& callback) |
| : original_callback(callback), |
| - out_keys(new CacheStorageCache::Requests()), |
| - enumerated_entry(NULL) {} |
| - |
| - ~KeysContext() { |
| - for (size_t i = 0, max = entries.size(); i < max; ++i) |
| - entries[i]->Close(); |
| - if (enumerated_entry) |
| - enumerated_entry->Close(); |
| - } |
| + out_keys(new CacheStorageCache::Requests()) {} |
| + ~KeysContext() {} |
| // The callback passed to the Keys() function. |
| CacheStorageCache::RequestsCallback original_callback; |
| - // The vector of open entries in the backend. |
| - Entries entries; |
| - |
| // The output of the Keys function. |
| scoped_ptr<CacheStorageCache::Requests> out_keys; |
| - // Used for enumerating cache entries. |
| - scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; |
| - disk_cache::Entry* enumerated_entry; |
| + // The context holding open entries. |
| + scoped_ptr<OpenAllEntriesContext> entries_context; |
| private: |
| DISALLOW_COPY_AND_ASSIGN(KeysContext); |
| @@ -287,6 +336,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) { |
| @@ -432,6 +497,60 @@ bool CacheStorageCache::LazyInitialize() { |
| return false; |
| } |
| +void CacheStorageCache::OpenAllEntries(const OpenAllEntriesCallback& callback) { |
| + scoped_ptr<OpenAllEntriesContext> entries_context(new OpenAllEntriesContext); |
| + entries_context->backend_iterator = backend_->CreateIterator(); |
| + disk_cache::Backend::Iterator& iterator = *entries_context->backend_iterator; |
| + disk_cache::Entry** enumerated_entry = &entries_context->enumerated_entry; |
| + |
| + net::CompletionCallback open_entry_callback = base::Bind( |
| + &CacheStorageCache::DidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), |
| + base::Passed(entries_context.Pass()), callback); |
| + |
| + int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| + |
| + if (rv != net::ERR_IO_PENDING) |
| + open_entry_callback.Run(rv); |
| +} |
| + |
| +void CacheStorageCache::DidOpenNextEntry( |
| + scoped_ptr<OpenAllEntriesContext> entries_context, |
| + const OpenAllEntriesCallback& callback, |
| + int rv) { |
| + if (rv == net::ERR_FAILED) { |
| + DCHECK(!entries_context->enumerated_entry); |
| + // Enumeration is complete, extract the requests from the entries. |
| + callback.Run(entries_context.Pass(), CACHE_STORAGE_OK); |
| + return; |
| + } |
| + |
| + if (rv < 0) { |
| + callback.Run(entries_context.Pass(), CACHE_STORAGE_ERROR_STORAGE); |
| + return; |
| + } |
| + |
| + if (backend_state_ != BACKEND_OPEN) { |
| + callback.Run(entries_context.Pass(), CACHE_STORAGE_ERROR_NOT_FOUND); |
| + return; |
| + } |
| + |
| + // Store the entry. |
| + entries_context->entries.push_back(entries_context->enumerated_entry); |
| + entries_context->enumerated_entry = nullptr; |
| + |
| + // Enumerate the next entry. |
| + disk_cache::Backend::Iterator& iterator = *entries_context->backend_iterator; |
| + disk_cache::Entry** enumerated_entry = &entries_context->enumerated_entry; |
| + net::CompletionCallback open_entry_callback = base::Bind( |
| + &CacheStorageCache::DidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), |
| + base::Passed(entries_context.Pass()), callback); |
| + |
| + rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| + |
| + if (rv != net::ERR_IO_PENDING) |
| + open_entry_callback.Run(rv); |
| +} |
| + |
| void CacheStorageCache::MatchImpl(scoped_ptr<ServiceWorkerFetchRequest> request, |
| const ResponseCallback& callback) { |
| DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_); |
| @@ -489,22 +608,8 @@ void CacheStorageCache::MatchDidReadMetadata( |
| return; |
| } |
| - scoped_ptr<ServiceWorkerResponse> response(new ServiceWorkerResponse( |
| - request->url, metadata->response().status_code(), |
| - metadata->response().status_text(), |
| - ProtoResponseTypeToWebResponseType(metadata->response().response_type()), |
| - ServiceWorkerHeaderMap(), "", 0, GURL(), |
| - blink::WebServiceWorkerResponseErrorUnknown)); |
| - |
| - if (metadata->response().has_url()) |
| - response->url = GURL(metadata->response().url()); |
| - |
| - 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())); |
| - } |
| + scoped_ptr<ServiceWorkerResponse> response(new ServiceWorkerResponse); |
| + PopulateServiceWorkerResponse(*metadata, response.get()); |
| ServiceWorkerHeaderMap cached_request_headers; |
| for (int i = 0; i < metadata->request().headers_size(); ++i) { |
| @@ -549,6 +654,99 @@ 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; |
| + } |
| + |
| + OpenAllEntries(base::Bind(&CacheStorageCache::MatchAllDidOpenAllEntries, |
| + weak_ptr_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void CacheStorageCache::MatchAllDidOpenAllEntries( |
| + const ResponsesCallback& callback, |
| + scoped_ptr<OpenAllEntriesContext> entries_context, |
| + CacheStorageError error) { |
| + if (error != CACHE_STORAGE_OK) { |
| + callback.Run(error, std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + scoped_ptr<MatchAllContext> context(new MatchAllContext(callback)); |
| + context->entries_context.swap(entries_context); |
| + Entries::iterator iter = context->entries_context->entries.begin(); |
| + MatchAllProcessNextEntry(context.Pass(), iter); |
| +} |
| + |
| +void CacheStorageCache::MatchAllProcessNextEntry( |
| + scoped_ptr<MatchAllContext> context, |
| + const Entries::iterator& iter) { |
| + if (iter == context->entries_context->entries.end()) { |
| + // All done. Return all of the responses. |
| + context->original_callback.Run(CACHE_STORAGE_OK, context->out_responses, |
| + context->out_blob_data_handles.Pass()); |
| + return; |
| + } |
| + |
| + ReadMetadata(*iter, base::Bind(&CacheStorageCache::MatchAllDidReadMetadata, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + base::Passed(context.Pass()), iter)); |
| +} |
| + |
| +void CacheStorageCache::MatchAllDidReadMetadata( |
| + scoped_ptr<MatchAllContext> context, |
| + const Entries::iterator& iter, |
| + scoped_ptr<CacheMetadata> metadata) { |
| + // Move ownership of the entry from the context. |
| + disk_cache::ScopedEntryPtr entry(*iter); |
| + *iter = nullptr; |
| + |
| + if (!metadata) { |
| + entry->Doom(); |
| + MatchAllProcessNextEntry(context.Pass(), iter + 1); |
| + return; |
| + } |
| + |
| + ServiceWorkerResponse response; |
| + PopulateServiceWorkerResponse(*metadata, &response); |
| + |
| + if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { |
| + context->out_responses.push_back(response); |
| + context->out_blob_data_handles.push_back(nullptr); |
| + MatchAllProcessNextEntry(context.Pass(), iter + 1); |
| + return; |
| + } |
| + |
| + if (!blob_storage_context_) { |
| + context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE, |
| + std::vector<ServiceWorkerResponse>(), |
| + ScopedVector<storage::BlobDataHandle>()); |
| + return; |
| + } |
| + |
| + // Create a blob with the response body data. |
|
jkarlin
2015/08/05 12:09:05
The block of code below is duplicated from MatchDi
nhiroki
2015/08/06 03:36:53
Factored out the block into PopulateResponseBody()
|
| + response.blob_size = entry->GetDataSize(INDEX_RESPONSE_BODY); |
| + response.blob_uuid = base::GenerateGUID(); |
| + storage::BlobDataBuilder blob_data(response.blob_uuid); |
| + |
| + // Pass ownership of |entry| from the context to the handle. |
| + 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(), iter + 1); |
| +} |
| + |
| void CacheStorageCache::Put(const CacheStorageBatchOperation& operation, |
| const ErrorCallback& callback) { |
| DCHECK(BACKEND_OPEN == backend_state_ || initializing_); |
| @@ -860,66 +1058,29 @@ void CacheStorageCache::KeysImpl(const RequestsCallback& callback) { |
| // The entries have to be loaded into a vector first because enumeration loops |
| // forever if you read data from a cache entry while enumerating. |
| - scoped_ptr<KeysContext> keys_context(new KeysContext(callback)); |
| - |
| - keys_context->backend_iterator = backend_->CreateIterator(); |
| - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; |
| - disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; |
| - |
| - net::CompletionCallback open_entry_callback = base::Bind( |
| - &CacheStorageCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), |
| - base::Passed(keys_context.Pass())); |
| - |
| - int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| - |
| - if (rv != net::ERR_IO_PENDING) |
| - open_entry_callback.Run(rv); |
| + OpenAllEntries(base::Bind(&CacheStorageCache::KeysDidOpenAllEntries, |
| + weak_ptr_factory_.GetWeakPtr(), callback)); |
| } |
| -void CacheStorageCache::KeysDidOpenNextEntry( |
| - scoped_ptr<KeysContext> keys_context, |
| - int rv) { |
| - if (rv == net::ERR_FAILED) { |
| - DCHECK(!keys_context->enumerated_entry); |
| - // Enumeration is complete, extract the requests from the entries. |
| - Entries::iterator iter = keys_context->entries.begin(); |
| - KeysProcessNextEntry(keys_context.Pass(), iter); |
| - return; |
| - } |
| - |
| - if (rv < 0) { |
| - keys_context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE, |
| - scoped_ptr<Requests>()); |
| - return; |
| - } |
| - |
| - if (backend_state_ != BACKEND_OPEN) { |
| - keys_context->original_callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND, |
| - scoped_ptr<Requests>()); |
| +void CacheStorageCache::KeysDidOpenAllEntries( |
| + const RequestsCallback& callback, |
| + scoped_ptr<OpenAllEntriesContext> entries_context, |
| + CacheStorageError error) { |
| + if (error != CACHE_STORAGE_OK) { |
| + callback.Run(error, scoped_ptr<Requests>()); |
| return; |
| } |
| - // Store the entry. |
| - keys_context->entries.push_back(keys_context->enumerated_entry); |
| - keys_context->enumerated_entry = NULL; |
| - |
| - // Enumerate the next entry. |
| - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; |
| - disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; |
| - net::CompletionCallback open_entry_callback = base::Bind( |
| - &CacheStorageCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), |
| - base::Passed(keys_context.Pass())); |
| - |
| - rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| - |
| - if (rv != net::ERR_IO_PENDING) |
| - open_entry_callback.Run(rv); |
| + scoped_ptr<KeysContext> keys_context(new KeysContext(callback)); |
| + keys_context->entries_context.swap(entries_context); |
| + Entries::iterator iter = keys_context->entries_context->entries.begin(); |
| + KeysProcessNextEntry(keys_context.Pass(), iter); |
| } |
| void CacheStorageCache::KeysProcessNextEntry( |
| scoped_ptr<KeysContext> keys_context, |
| const Entries::iterator& iter) { |
| - if (iter == keys_context->entries.end()) { |
| + if (iter == keys_context->entries_context->entries.end()) { |
| // All done. Return all of the keys. |
| keys_context->original_callback.Run(CACHE_STORAGE_OK, |
| keys_context->out_keys.Pass()); |
| @@ -1063,6 +1224,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, |