Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: content/browser/service_worker/service_worker_cache.cc

Issue 477973002: Add Keys() function to ServiceWorkerCache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cache_patch
Patch Set: Rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/service_worker/service_worker_cache.cc
diff --git a/content/browser/service_worker/service_worker_cache.cc b/content/browser/service_worker/service_worker_cache.cc
index 6a63b6b3e37d2dac223c3d911def4bc2636f3135..59fbbd4747a849df3034423e55c3be171e6ae993 100644
--- a/content/browser/service_worker/service_worker_cache.cc
+++ b/content/browser/service_worker/service_worker_cache.cc
@@ -22,11 +22,20 @@
namespace content {
namespace {
+struct EntriesDeleter;
typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr;
typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
EntryBoolCallback;
+typedef base::Callback<void(scoped_ptr<ServiceWorkerRequestResponseHeaders>)>
+ HeadersCallback;
+typedef std::vector<disk_cache::Entry*> Entries;
+
+// Automatically closes all of the entries in the vector when it goes out of
+// scope.
+typedef scoped_ptr<Entries, EntriesDeleter> ScopedEntriesPtr;
+
enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
// The maximum size of an individual cache. Ultimately cache size is controlled
@@ -36,6 +45,13 @@ const int kMaxCacheBytes = 512 * 1024 * 1024;
// Buffer size for cache and blob reading/writing.
const int kBufferSize = 1024 * 512;
+struct EntriesDeleter {
+ void operator()(Entries* entries) {
+ for (size_t i = 0, max = entries->size(); i < max; ++i)
+ entries->at(i)->Close();
michaeln 2014/08/27 23:45:20 delete entries too?
jkarlin 2014/08/28 15:16:11 Done.
+ }
+};
+
struct ResponseReadContext {
ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
scoped_refptr<storage::BlobData> blob)
@@ -189,8 +205,7 @@ void MatchDidReadHeaderData(
const ServiceWorkerCache::ResponseCallback& callback,
base::WeakPtr<storage::BlobStorageContext> blob_storage,
disk_cache::ScopedEntryPtr entry,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
- int rv);
+ scoped_ptr<ServiceWorkerRequestResponseHeaders> headers);
void MatchDidReadResponseBodyData(
ServiceWorkerFetchRequest* request,
const ServiceWorkerCache::ResponseCallback& callback,
@@ -211,6 +226,33 @@ void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
scoped_ptr<disk_cache::Entry*> entryptr,
int rv);
+// Keys callback
+void KeysDidOpenNextEntry(const ServiceWorkerCache::RequestsCallback& callback,
+ base::WeakPtr<ServiceWorkerCache> cache,
+ scoped_ptr<void*> iter,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ ScopedEntriesPtr entries,
+ int rv);
+void KeysProcessNextEntry(const ServiceWorkerCache::RequestsCallback& callback,
+ scoped_ptr<ServiceWorkerCache::Requests> requests,
+ ScopedEntriesPtr entries,
+ const Entries::iterator& iter);
+void KeysDidReadHeaders(
+ const ServiceWorkerCache::RequestsCallback& callback,
+ scoped_ptr<ServiceWorkerCache::Requests> out_requests,
+ ScopedEntriesPtr entries,
+ const Entries::iterator& iter,
+ scoped_ptr<ServiceWorkerRequestResponseHeaders> headers);
+
+// Copy headers out of a cache entry and into a protobuf. The callback is
+// guaranteed to be run.
+void ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback);
+void ReadHeadersDidReadHeaderData(
+ disk_cache::Entry* entry,
+ const HeadersCallback& callback,
+ const scoped_refptr<net::IOBufferWithSize>& buffer,
+ int rv);
+
// CreateBackend callbacks
void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
scoped_ptr<ScopedBackendPtr> backend_ptr,
@@ -224,10 +266,8 @@ void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
scoped_ptr<storage::BlobDataHandle> blob_data_handle,
net::URLRequestContext* request_context,
int rv) {
- if (rv != net::OK) {
- callback.Run(ServiceWorkerCache::ErrorTypeExists);
- return;
- }
+ if (rv != net::OK)
+ return callback.Run(ServiceWorkerCache::ErrorTypeExists);
DCHECK(entryptr);
disk_cache::ScopedEntryPtr entry(*entryptr);
@@ -258,10 +298,8 @@ void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
}
scoped_ptr<std::string> serialized(new std::string());
- if (!headers.SerializeToString(serialized.get())) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage);
- return;
- }
+ if (!headers.SerializeToString(serialized.get()))
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage);
scoped_refptr<net::StringIOBuffer> buffer(
new net::StringIOBuffer(serialized.Pass()));
@@ -298,17 +336,14 @@ void PutDidWriteHeaders(ServiceWorkerResponse* response,
int rv) {
if (rv != expected_bytes) {
entry->Doom();
- callback.Run(ServiceWorkerCache::ErrorTypeStorage);
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage);
}
// The metadata is written, now for the response content. The data is streamed
// from the blob into the cache entry.
- if (response->blob_uuid.empty()) {
- callback.Run(ServiceWorkerCache::ErrorTypeOK);
- return;
- }
+ if (response->blob_uuid.empty())
+ return callback.Run(ServiceWorkerCache::ErrorTypeOK);
DCHECK(blob_data_handle);
@@ -328,8 +363,7 @@ void PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
bool success) {
if (!success) {
entry->Doom();
- callback.Run(ServiceWorkerCache::ErrorTypeStorage);
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage);
}
callback.Run(ServiceWorkerCache::ErrorTypeOK);
@@ -341,34 +375,24 @@ void MatchDidOpenEntry(ServiceWorkerFetchRequest* request,
scoped_ptr<disk_cache::Entry*> entryptr,
int rv) {
if (rv != net::OK) {
- callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
DCHECK(entryptr);
disk_cache::ScopedEntryPtr entry(*entryptr);
- scoped_refptr<net::IOBufferWithSize> buffer(
- new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
-
// Copy the entry pointer before passing it in base::Bind.
disk_cache::Entry* tmp_entry_ptr = entry.get();
- net::CompletionCallback read_header_callback =
- base::Bind(MatchDidReadHeaderData,
- request,
- callback,
- blob_storage,
- base::Passed(entry.Pass()),
- buffer);
-
- int read_rv = tmp_entry_ptr->ReadData(
- INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
+ HeadersCallback headers_callback = base::Bind(MatchDidReadHeaderData,
+ request,
+ callback,
+ blob_storage,
+ base::Passed(entry.Pass()));
- if (read_rv != net::ERR_IO_PENDING)
- read_header_callback.Run(read_rv);
+ ReadHeaders(tmp_entry_ptr, headers_callback);
}
void MatchDidReadHeaderData(
@@ -376,55 +400,39 @@ void MatchDidReadHeaderData(
const ServiceWorkerCache::ResponseCallback& callback,
base::WeakPtr<storage::BlobStorageContext> blob_storage,
disk_cache::ScopedEntryPtr entry,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
- int rv) {
- if (rv != buffer->size()) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
-
- return;
- }
-
- ServiceWorkerRequestResponseHeaders headers;
-
- if (!headers.ParseFromArray(buffer->data(), buffer->size())) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
-
- return;
+ scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) {
+ if (!headers) {
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
scoped_ptr<ServiceWorkerResponse> response(
new ServiceWorkerResponse(request->url,
- headers.status_code(),
- headers.status_text(),
+ headers->status_code(),
+ headers->status_text(),
std::map<std::string, std::string>(),
""));
- for (int i = 0; i < headers.response_headers_size(); ++i) {
+ for (int i = 0; i < headers->response_headers_size(); ++i) {
const ServiceWorkerRequestResponseHeaders::HeaderMap header =
- headers.response_headers(i);
+ headers->response_headers(i);
response->headers.insert(std::make_pair(header.name(), header.value()));
}
// TODO(jkarlin): Insert vary validation here.
if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
- callback.Run(ServiceWorkerCache::ErrorTypeOK,
- response.Pass(),
- scoped_ptr<storage::BlobDataHandle>());
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeOK,
+ response.Pass(),
+ scoped_ptr<storage::BlobDataHandle>());
}
// Stream the response body into a blob.
if (!blob_storage) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
-
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
response->blob_uuid = base::GenerateGUID();
@@ -468,10 +476,9 @@ void MatchDidReadResponseBodyData(
scoped_ptr<ResponseReadContext> response_context,
int rv) {
if (rv < 0) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
if (rv == 0) {
@@ -519,10 +526,9 @@ void MatchDoneWithBody(ServiceWorkerFetchRequest* request,
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<ResponseReadContext> response_context) {
if (!blob_storage) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
- return;
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
scoped_ptr<storage::BlobDataHandle> blob_data_handle(
@@ -537,10 +543,8 @@ void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
const ServiceWorkerCache::ErrorCallback& callback,
scoped_ptr<disk_cache::Entry*> entryptr,
int rv) {
- if (rv != net::OK) {
- callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
- return;
- }
+ if (rv != net::OK)
+ return callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
DCHECK(entryptr);
disk_cache::ScopedEntryPtr entry(*entryptr);
@@ -549,14 +553,135 @@ void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
callback.Run(ServiceWorkerCache::ErrorTypeOK);
}
+void KeysDidOpenNextEntry(const ServiceWorkerCache::RequestsCallback& callback,
+ base::WeakPtr<ServiceWorkerCache> cache,
+ scoped_ptr<void*> iter,
michaeln 2014/08/27 23:45:20 might be nice to distinguish the void* iter from t
jkarlin 2014/08/28 15:16:11 Done.
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ ScopedEntriesPtr entries,
+ int rv) {
+ if (rv == net::ERR_FAILED) {
+ // Enumeration is complete, extract the requests from the entries.
+ Entries::iterator iter = entries->begin();
+ scoped_ptr<ServiceWorkerCache::Requests> out_requests(
+ new ServiceWorkerCache::Requests());
michaeln 2014/08/27 23:45:20 ah ha, here's where the collection to hold the res
jkarlin 2014/08/28 15:16:10 Done.
+ return KeysProcessNextEntry(
michaeln 2014/08/27 23:45:20 its odd to see return <something> in a function wi
jkarlin 2014/08/28 15:16:10 Done for the whole file.
+ callback, out_requests.Pass(), entries.Pass(), iter);
+ }
+
+ if (rv < 0 || !cache) {
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerCache::Requests>());
+ }
+
+ entries->push_back(*entryptr);
+
+ void** iter_ptr = iter.get();
+ disk_cache::Entry** entry_ptr = entryptr.get();
+
+ net::CompletionCallback open_entry_callback =
+ base::Bind(KeysDidOpenNextEntry,
+ callback,
+ cache,
+ base::Passed(iter.Pass()),
+ base::Passed(entryptr.Pass()),
+ base::Passed(entries.Pass()));
+
+ // Enumerate the next entry.
+ int rvv =
michaeln 2014/08/27 23:45:20 looks like you could just use the existing paramet
jkarlin 2014/08/28 15:16:11 Done.
+ cache->backend()->OpenNextEntry(iter_ptr, entry_ptr, open_entry_callback);
michaeln 2014/08/27 23:45:20 i was wondering what caused backend() to be added
jkarlin 2014/08/28 15:16:10 You're right, better to hide backend. I'm not gai
+
+ if (rvv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rvv);
+}
+
+void KeysProcessNextEntry(const ServiceWorkerCache::RequestsCallback& callback,
+ scoped_ptr<ServiceWorkerCache::Requests> requests,
+ ScopedEntriesPtr entries,
+ const Entries::iterator& iter) {
+ if (iter == entries->end())
+ return callback.Run(ServiceWorkerCache::ErrorTypeOK, requests.Pass());
michaeln 2014/08/27 23:45:20 This is the end of the line in the expected case,
jkarlin 2014/08/28 15:16:11 Done.
+
+ ReadHeaders(*iter,
+ base::Bind(KeysDidReadHeaders,
+ callback,
+ base::Passed(requests.Pass()),
+ base::Passed(entries.Pass()),
+ iter));
+}
+
+void KeysDidReadHeaders(
+ const ServiceWorkerCache::RequestsCallback& callback,
+ scoped_ptr<ServiceWorkerCache::Requests> out_requests,
+ ScopedEntriesPtr entries,
+ const Entries::iterator& iter,
+ scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) {
+ disk_cache::Entry* entry = *iter;
+
+ if (!headers) {
+ entry->Doom();
michaeln 2014/08/27 23:45:20 Interesting, a subsequent call to Keys() will yeil
jkarlin 2014/08/28 15:16:10 Done.
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ out_requests.Pass());
+ }
+
+ out_requests->push_back(
+ ServiceWorkerFetchRequest(GURL(entry->GetKey()),
+ headers->method(),
+ std::map<std::string, std::string>(),
+ GURL(),
+ false));
+
+ std::map<std::string, std::string>& req_headers =
+ out_requests->back().headers;
+
+ for (int i = 0; i < headers->request_headers_size(); ++i) {
+ const ServiceWorkerRequestResponseHeaders::HeaderMap header =
+ headers->request_headers(i);
+ req_headers.insert(std::make_pair(header.name(), header.value()));
+ }
+
+ KeysProcessNextEntry(callback, out_requests.Pass(), entries.Pass(), iter + 1);
+}
+
+void ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback) {
+ DCHECK(entry);
+
+ scoped_refptr<net::IOBufferWithSize> buffer(
+ new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
+
+ net::CompletionCallback read_header_callback =
+ base::Bind(ReadHeadersDidReadHeaderData, entry, callback, buffer);
+
+ int read_rv = entry->ReadData(
+ INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
+
+ if (read_rv != net::ERR_IO_PENDING)
+ read_header_callback.Run(read_rv);
+}
+
+void ReadHeadersDidReadHeaderData(
+ disk_cache::Entry* entry,
+ const HeadersCallback& callback,
+ const scoped_refptr<net::IOBufferWithSize>& buffer,
+ int rv) {
+ if (rv != buffer->size())
+ return callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>());
+
+ scoped_ptr<ServiceWorkerRequestResponseHeaders> headers(
+ new ServiceWorkerRequestResponseHeaders());
+
+ if (!headers->ParseFromArray(buffer->data(), buffer->size()))
+ return callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>());
+
+ callback.Run(headers.Pass());
+}
+
void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
scoped_ptr<ScopedBackendPtr> backend_ptr,
base::WeakPtr<ServiceWorkerCache> cache,
int rv) {
- if (rv != net::OK || !cache) {
- callback.Run(ServiceWorkerCache::ErrorTypeStorage);
- return;
- }
+ if (rv != net::OK || !cache)
+ return callback.Run(ServiceWorkerCache::ErrorTypeStorage);
+
cache->set_backend(backend_ptr->Pass());
callback.Run(ServiceWorkerCache::ErrorTypeOK);
}
@@ -636,14 +761,12 @@ void ServiceWorkerCache::Put(ServiceWorkerFetchRequest* request,
if (!response->blob_uuid.empty()) {
if (!blob_storage_context_) {
- callback.Run(ErrorTypeStorage);
- return;
+ return callback.Run(ErrorTypeStorage);
michaeln 2014/08/27 23:45:20 why?
jkarlin 2014/08/28 15:16:10 Done.
}
blob_data_handle =
blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
if (!blob_data_handle) {
- callback.Run(ErrorTypeStorage);
- return;
+ return callback.Run(ErrorTypeStorage);
}
}
@@ -701,6 +824,34 @@ void ServiceWorkerCache::Delete(ServiceWorkerFetchRequest* request,
open_entry_callback.Run(rv);
}
+void ServiceWorkerCache::Keys(const RequestsCallback& callback) {
+ DCHECK(backend_);
+
+ scoped_ptr<void*> iter(new void*(NULL));
+ scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
+
+ void** iter_ptr = iter.get();
+ disk_cache::Entry** entry_ptr = entry.get();
+
+ // Load up all of the entries into a vector and then read the request data
michaeln 2014/08/27 23:45:20 It might help to expand on this comment to better
jkarlin 2014/08/28 15:16:10 Done.
+ // from them. This has to be done in two steps because enumeration breaks if
+ // entries are altered (such as reading header data) while enumerating.
michaeln 2014/08/27 23:45:20 how does reading header data alter it?
jkarlin 2014/08/28 15:16:10 It changes the "last_used" field which seems buggy
+ ScopedEntriesPtr entries(new Entries());
+
+ net::CompletionCallback open_entry_callback =
+ base::Bind(KeysDidOpenNextEntry,
+ callback,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(iter.Pass()),
+ base::Passed(entry.Pass()),
+ base::Passed(entries.Pass()));
+
+ int rv = backend_->OpenNextEntry(iter_ptr, entry_ptr, open_entry_callback);
+
+ if (rv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rv);
+}
+
bool ServiceWorkerCache::HasCreatedBackend() const {
return backend_;
}
« no previous file with comments | « content/browser/service_worker/service_worker_cache.h ('k') | content/browser/service_worker/service_worker_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698