| 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 cf98e5007e766edb459f3638331454e433be7520..dcc9c3d0da7d3ac00b00b734ac7636d3e6dd5bc7 100644
|
| --- a/content/browser/cache_storage/cache_storage_cache.cc
|
| +++ b/content/browser/cache_storage/cache_storage_cache.cc
|
| @@ -182,34 +182,67 @@ void ReadMetadataDidReadMetadata(
|
|
|
| } // namespace
|
|
|
| -// 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();
|
| +// 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)
|
| enumerated_entry->Close();
|
| }
|
|
|
| - // 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;
|
|
|
| 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),
|
| + out_responses(new Responses),
|
| + out_blob_data_handles(new BlobDataHandles) {}
|
| + ~MatchAllContext() {}
|
| +
|
| + // The callback passed to the MatchAll() function.
|
| + ResponsesCallback original_callback;
|
| +
|
| + // The outputs of the MatchAll function.
|
| + scoped_ptr<Responses> out_responses;
|
| + scoped_ptr<BlobDataHandles> 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 Requests()) {}
|
| + ~KeysContext() {}
|
| +
|
| + // The callback passed to the Keys() function.
|
| + RequestsCallback original_callback;
|
| +
|
| + // The output of the Keys function.
|
| + scoped_ptr<Requests> out_keys;
|
| +
|
| + // The context holding open entries.
|
| + scoped_ptr<OpenAllEntriesContext> entries_context;
|
| +
|
| + private:
|
| DISALLOW_COPY_AND_ASSIGN(KeysContext);
|
| };
|
|
|
| @@ -291,6 +324,21 @@ 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, scoped_ptr<Responses>(),
|
| + scoped_ptr<BlobDataHandles>());
|
| + 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) {
|
| @@ -436,6 +484,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_);
|
| @@ -493,22 +595,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);
|
| + PopulateResponseMetadata(*metadata, response.get());
|
|
|
| ServiceWorkerHeaderMap cached_request_headers;
|
| for (int i = 0; i < metadata->request().headers_size(); ++i) {
|
| @@ -539,20 +627,92 @@ void CacheStorageCache::MatchDidReadMetadata(
|
| 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* temp_entry = entry.get();
|
| - blob_data.AppendDiskCacheEntry(
|
| - new CacheStorageCacheDataHandle(this, entry.Pass()), temp_entry,
|
| - INDEX_RESPONSE_BODY);
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle(
|
| - blob_storage_context_->AddFinishedBlob(&blob_data));
|
| + scoped_ptr<storage::BlobDataHandle> blob_data_handle =
|
| + PopulateResponseBody(entry.Pass(), response.get());
|
| 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, scoped_ptr<Responses>(),
|
| + scoped_ptr<BlobDataHandles>());
|
| + 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, scoped_ptr<Responses>(), scoped_ptr<BlobDataHandles>());
|
| + 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.Pass(),
|
| + 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;
|
| + PopulateResponseMetadata(*metadata, &response);
|
| +
|
| + if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
|
| + context->out_responses->push_back(response);
|
| + MatchAllProcessNextEntry(context.Pass(), iter + 1);
|
| + return;
|
| + }
|
| +
|
| + if (!blob_storage_context_) {
|
| + context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE,
|
| + scoped_ptr<Responses>(),
|
| + scoped_ptr<BlobDataHandles>());
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<storage::BlobDataHandle> blob_data_handle =
|
| + PopulateResponseBody(entry.Pass(), &response);
|
| +
|
| + context->out_responses->push_back(response);
|
| + context->out_blob_data_handles->push_back(*blob_data_handle);
|
| + MatchAllProcessNextEntry(context.Pass(), iter + 1);
|
| +}
|
| +
|
| void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
|
| const ErrorCallback& callback) {
|
| DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
|
| @@ -864,66 +1024,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());
|
| @@ -1067,6 +1190,18 @@ void CacheStorageCache::PendingResponseCallback(
|
| scheduler_->CompleteOperationAndRunNext();
|
| }
|
|
|
| +void CacheStorageCache::PendingResponsesCallback(
|
| + const ResponsesCallback& callback,
|
| + CacheStorageError error,
|
| + scoped_ptr<Responses> responses,
|
| + scoped_ptr<BlobDataHandles> blob_data_handles) {
|
| + base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr();
|
| +
|
| + callback.Run(error, responses.Pass(), blob_data_handles.Pass());
|
| + if (cache)
|
| + scheduler_->CompleteOperationAndRunNext();
|
| +}
|
| +
|
| void CacheStorageCache::PendingRequestsCallback(
|
| const RequestsCallback& callback,
|
| CacheStorageError error,
|
| @@ -1078,4 +1213,39 @@ void CacheStorageCache::PendingRequestsCallback(
|
| scheduler_->CompleteOperationAndRunNext();
|
| }
|
|
|
| +void CacheStorageCache::PopulateResponseMetadata(
|
| + const CacheMetadata& metadata,
|
| + 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()));
|
| + }
|
| +}
|
| +
|
| +scoped_ptr<storage::BlobDataHandle> CacheStorageCache::PopulateResponseBody(
|
| + disk_cache::ScopedEntryPtr entry,
|
| + ServiceWorkerResponse* response) {
|
| + DCHECK(blob_storage_context_);
|
| +
|
| + // 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* temp_entry = entry.get();
|
| + blob_data.AppendDiskCacheEntry(
|
| + new CacheStorageCacheDataHandle(this, entry.Pass()), temp_entry,
|
| + INDEX_RESPONSE_BODY);
|
| + return blob_storage_context_->AddFinishedBlob(&blob_data);
|
| +}
|
| +
|
| } // namespace content
|
|
|