Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_cache.cc
blobc2cfe64ee2c7a49a23dcace09ce7c6e3c2679dde
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_cache.h"
7 #include <string>
9 #include "base/files/file_path.h"
10 #include "base/guid.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "content/browser/service_worker/service_worker_cache.pb.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/disk_cache.h"
17 #include "net/url_request/url_request_context.h"
18 #include "webkit/browser/blob/blob_data_handle.h"
19 #include "webkit/browser/blob/blob_storage_context.h"
20 #include "webkit/browser/blob/blob_url_request_job_factory.h"
22 namespace content {
24 namespace {
26 typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr;
27 typedef base::Callback<void(bool)> BoolCallback;
28 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
29 EntryBoolCallback;
30 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
32 // The maximum size of an individual cache. Ultimately cache size is controlled
33 // per-origin.
34 const int kMaxCacheBytes = 512 * 1024 * 1024;
36 // Buffer size for cache and blob reading/writing.
37 const int kBufferSize = 1024 * 512;
39 struct ResponseReadContext {
40 ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
41 scoped_refptr<storage::BlobData> blob)
42 : buffer(buff), blob_data(blob), total_bytes_read(0) {}
44 scoped_refptr<net::IOBufferWithSize> buffer;
45 scoped_refptr<storage::BlobData> blob_data;
46 int total_bytes_read;
48 DISALLOW_COPY_AND_ASSIGN(ResponseReadContext);
51 // Streams data from a blob and writes it to a given disk_cache::Entry.
52 class BlobReader : public net::URLRequest::Delegate {
53 public:
54 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
55 EntryBoolCallback;
57 BlobReader(disk_cache::ScopedEntryPtr entry)
58 : cache_entry_offset_(0),
59 buffer_(new net::IOBufferWithSize(kBufferSize)),
60 weak_ptr_factory_(this) {
61 DCHECK(entry);
62 entry_ = entry.Pass();
65 void StreamBlobToCache(net::URLRequestContext* request_context,
66 scoped_ptr<storage::BlobDataHandle> blob_data_handle,
67 const EntryBoolCallback& callback) {
68 callback_ = callback;
69 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
70 blob_data_handle.Pass(), request_context, this);
71 blob_request_->Start();
74 // net::URLRequest::Delegate overrides for reading blobs.
75 virtual void OnReceivedRedirect(net::URLRequest* request,
76 const net::RedirectInfo& redirect_info,
77 bool* defer_redirect) OVERRIDE {
78 NOTREACHED();
80 virtual void OnAuthRequired(net::URLRequest* request,
81 net::AuthChallengeInfo* auth_info) OVERRIDE {
82 NOTREACHED();
84 virtual void OnCertificateRequested(
85 net::URLRequest* request,
86 net::SSLCertRequestInfo* cert_request_info) OVERRIDE {
87 NOTREACHED();
89 virtual void OnSSLCertificateError(net::URLRequest* request,
90 const net::SSLInfo& ssl_info,
91 bool fatal) OVERRIDE {
92 NOTREACHED();
94 virtual void OnBeforeNetworkStart(net::URLRequest* request,
95 bool* defer) OVERRIDE {
96 NOTREACHED();
99 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
100 if (!request->status().is_success()) {
101 callback_.Run(entry_.Pass(), false);
102 return;
104 ReadFromBlob();
107 virtual void ReadFromBlob() {
108 int bytes_read = 0;
109 bool done =
110 blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read);
111 if (done)
112 OnReadCompleted(blob_request_.get(), bytes_read);
115 virtual void OnReadCompleted(net::URLRequest* request,
116 int bytes_read) OVERRIDE {
117 if (!request->status().is_success()) {
118 callback_.Run(entry_.Pass(), false);
119 return;
122 if (bytes_read == 0) {
123 callback_.Run(entry_.Pass(), true);
124 return;
127 net::CompletionCallback cache_write_callback =
128 base::Bind(&BlobReader::DidWriteDataToEntry,
129 weak_ptr_factory_.GetWeakPtr(),
130 bytes_read);
132 int rv = entry_->WriteData(INDEX_RESPONSE_BODY,
133 cache_entry_offset_,
134 buffer_.get(),
135 bytes_read,
136 cache_write_callback,
137 true /* truncate */);
138 if (rv != net::ERR_IO_PENDING)
139 cache_write_callback.Run(rv);
142 void DidWriteDataToEntry(int expected_bytes, int rv) {
143 if (rv != expected_bytes) {
144 callback_.Run(entry_.Pass(), false);
145 return;
148 cache_entry_offset_ += rv;
149 ReadFromBlob();
152 private:
153 int cache_entry_offset_;
154 disk_cache::ScopedEntryPtr entry_;
155 scoped_ptr<net::URLRequest> blob_request_;
156 EntryBoolCallback callback_;
157 scoped_refptr<net::IOBufferWithSize> buffer_;
158 base::WeakPtrFactory<BlobReader> weak_ptr_factory_;
161 // Put callbacks
162 void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
163 ServiceWorkerResponse* response,
164 const ServiceWorkerCache::ErrorCallback& callback,
165 scoped_ptr<disk_cache::Entry*> entryptr,
166 scoped_ptr<storage::BlobDataHandle> blob_data_handle,
167 net::URLRequestContext* request_context,
168 int rv);
169 void PutDidWriteHeaders(ServiceWorkerResponse* response,
170 const ServiceWorkerCache::ErrorCallback& callback,
171 disk_cache::ScopedEntryPtr entry,
172 scoped_ptr<storage::BlobDataHandle> blob_data_handle,
173 net::URLRequestContext* request_context,
174 int expected_bytes,
175 int rv);
176 void PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
177 scoped_ptr<BlobReader> blob_reader,
178 disk_cache::ScopedEntryPtr entry,
179 bool success);
181 // Match callbacks
182 void MatchDidOpenEntry(ServiceWorkerFetchRequest* request,
183 const ServiceWorkerCache::ResponseCallback& callback,
184 base::WeakPtr<storage::BlobStorageContext> blob_storage,
185 scoped_ptr<disk_cache::Entry*> entryptr,
186 int rv);
187 void MatchDidReadHeaderData(
188 ServiceWorkerFetchRequest* request,
189 const ServiceWorkerCache::ResponseCallback& callback,
190 base::WeakPtr<storage::BlobStorageContext> blob_storage,
191 disk_cache::ScopedEntryPtr entry,
192 const scoped_refptr<net::IOBufferWithSize>& buffer,
193 int rv);
194 void MatchDidReadResponseBodyData(
195 ServiceWorkerFetchRequest* request,
196 const ServiceWorkerCache::ResponseCallback& callback,
197 base::WeakPtr<storage::BlobStorageContext> blob_storage,
198 disk_cache::ScopedEntryPtr entry,
199 scoped_ptr<ServiceWorkerResponse> response,
200 scoped_ptr<ResponseReadContext> response_context,
201 int rv);
202 void MatchDoneWithBody(ServiceWorkerFetchRequest* request,
203 const ServiceWorkerCache::ResponseCallback& callback,
204 base::WeakPtr<storage::BlobStorageContext> blob_storage,
205 scoped_ptr<ServiceWorkerResponse> response,
206 scoped_ptr<ResponseReadContext> response_context);
208 // Delete callbacks
209 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
210 const ServiceWorkerCache::ErrorCallback& callback,
211 scoped_ptr<disk_cache::Entry*> entryptr,
212 int rv);
214 // CreateBackend callbacks
215 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
216 scoped_ptr<ScopedBackendPtr> backend_ptr,
217 base::WeakPtr<ServiceWorkerCache> cache,
218 int rv);
220 void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
221 ServiceWorkerResponse* response,
222 const ServiceWorkerCache::ErrorCallback& callback,
223 scoped_ptr<disk_cache::Entry*> entryptr,
224 scoped_ptr<storage::BlobDataHandle> blob_data_handle,
225 net::URLRequestContext* request_context,
226 int rv) {
227 if (rv != net::OK) {
228 callback.Run(ServiceWorkerCache::ErrorTypeExists);
229 return;
232 DCHECK(entryptr);
233 disk_cache::ScopedEntryPtr entry(*entryptr);
235 ServiceWorkerRequestResponseHeaders headers;
236 headers.set_method(request->method);
238 headers.set_status_code(response->status_code);
239 headers.set_status_text(response->status_text);
240 for (std::map<std::string, std::string>::const_iterator it =
241 request->headers.begin();
242 it != request->headers.end();
243 ++it) {
244 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
245 headers.add_request_headers();
246 header_map->set_name(it->first);
247 header_map->set_value(it->second);
250 for (std::map<std::string, std::string>::const_iterator it =
251 response->headers.begin();
252 it != response->headers.end();
253 ++it) {
254 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
255 headers.add_response_headers();
256 header_map->set_name(it->first);
257 header_map->set_value(it->second);
260 scoped_ptr<std::string> serialized(new std::string());
261 if (!headers.SerializeToString(serialized.get())) {
262 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
263 return;
266 scoped_refptr<net::StringIOBuffer> buffer(
267 new net::StringIOBuffer(serialized.Pass()));
269 // Get a temporary copy of the entry pointer before passing it in base::Bind.
270 disk_cache::Entry* tmp_entry_ptr = entry.get();
272 net::CompletionCallback write_headers_callback =
273 base::Bind(PutDidWriteHeaders,
274 response,
275 callback,
276 base::Passed(entry.Pass()),
277 base::Passed(blob_data_handle.Pass()),
278 request_context,
279 buffer->size());
281 rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
282 0 /* offset */,
283 buffer.get(),
284 buffer->size(),
285 write_headers_callback,
286 true /* truncate */);
288 if (rv != net::ERR_IO_PENDING)
289 write_headers_callback.Run(rv);
292 void PutDidWriteHeaders(ServiceWorkerResponse* response,
293 const ServiceWorkerCache::ErrorCallback& callback,
294 disk_cache::ScopedEntryPtr entry,
295 scoped_ptr<storage::BlobDataHandle> blob_data_handle,
296 net::URLRequestContext* request_context,
297 int expected_bytes,
298 int rv) {
299 if (rv != expected_bytes) {
300 entry->Doom();
301 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
302 return;
305 // The metadata is written, now for the response content. The data is streamed
306 // from the blob into the cache entry.
308 if (response->blob_uuid.empty()) {
309 callback.Run(ServiceWorkerCache::ErrorTypeOK);
310 return;
313 DCHECK(blob_data_handle);
315 scoped_ptr<BlobReader> reader(new BlobReader(entry.Pass()));
316 BlobReader* reader_ptr = reader.get();
318 reader_ptr->StreamBlobToCache(
319 request_context,
320 blob_data_handle.Pass(),
321 base::Bind(
322 PutDidWriteBlobToCache, callback, base::Passed(reader.Pass())));
325 void PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
326 scoped_ptr<BlobReader> blob_reader,
327 disk_cache::ScopedEntryPtr entry,
328 bool success) {
329 if (!success) {
330 entry->Doom();
331 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
332 return;
335 callback.Run(ServiceWorkerCache::ErrorTypeOK);
338 void MatchDidOpenEntry(ServiceWorkerFetchRequest* request,
339 const ServiceWorkerCache::ResponseCallback& callback,
340 base::WeakPtr<storage::BlobStorageContext> blob_storage,
341 scoped_ptr<disk_cache::Entry*> entryptr,
342 int rv) {
343 if (rv != net::OK) {
344 callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
345 scoped_ptr<ServiceWorkerResponse>(),
346 scoped_ptr<storage::BlobDataHandle>());
347 return;
350 DCHECK(entryptr);
351 disk_cache::ScopedEntryPtr entry(*entryptr);
353 scoped_refptr<net::IOBufferWithSize> buffer(
354 new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
356 // Copy the entry pointer before passing it in base::Bind.
357 disk_cache::Entry* tmp_entry_ptr = entry.get();
359 net::CompletionCallback read_header_callback =
360 base::Bind(MatchDidReadHeaderData,
361 request,
362 callback,
363 blob_storage,
364 base::Passed(entry.Pass()),
365 buffer);
367 int read_rv = tmp_entry_ptr->ReadData(
368 INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
370 if (read_rv != net::ERR_IO_PENDING)
371 read_header_callback.Run(read_rv);
374 void MatchDidReadHeaderData(
375 ServiceWorkerFetchRequest* request,
376 const ServiceWorkerCache::ResponseCallback& callback,
377 base::WeakPtr<storage::BlobStorageContext> blob_storage,
378 disk_cache::ScopedEntryPtr entry,
379 const scoped_refptr<net::IOBufferWithSize>& buffer,
380 int rv) {
381 if (rv != buffer->size()) {
382 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
383 scoped_ptr<ServiceWorkerResponse>(),
384 scoped_ptr<storage::BlobDataHandle>());
386 return;
389 ServiceWorkerRequestResponseHeaders headers;
391 if (!headers.ParseFromArray(buffer->data(), buffer->size())) {
392 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
393 scoped_ptr<ServiceWorkerResponse>(),
394 scoped_ptr<storage::BlobDataHandle>());
396 return;
399 scoped_ptr<ServiceWorkerResponse> response(
400 new ServiceWorkerResponse(request->url,
401 headers.status_code(),
402 headers.status_text(),
403 std::map<std::string, std::string>(),
404 ""));
406 for (int i = 0; i < headers.response_headers_size(); ++i) {
407 const ServiceWorkerRequestResponseHeaders::HeaderMap header =
408 headers.response_headers(i);
409 response->headers.insert(std::make_pair(header.name(), header.value()));
412 // TODO(jkarlin): Insert vary validation here.
414 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
415 callback.Run(ServiceWorkerCache::ErrorTypeOK,
416 response.Pass(),
417 scoped_ptr<storage::BlobDataHandle>());
418 return;
421 // Stream the response body into a blob.
422 if (!blob_storage) {
423 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
424 scoped_ptr<ServiceWorkerResponse>(),
425 scoped_ptr<storage::BlobDataHandle>());
427 return;
430 response->blob_uuid = base::GenerateGUID();
432 scoped_refptr<storage::BlobData> blob_data =
433 new storage::BlobData(response->blob_uuid);
434 scoped_refptr<net::IOBufferWithSize> response_body_buffer(
435 new net::IOBufferWithSize(kBufferSize));
437 scoped_ptr<ResponseReadContext> read_context(
438 new ResponseReadContext(response_body_buffer, blob_data));
440 // Copy the entry pointer before passing it in base::Bind.
441 disk_cache::Entry* tmp_entry_ptr = entry.get();
443 net::CompletionCallback read_callback =
444 base::Bind(MatchDidReadResponseBodyData,
445 request,
446 callback,
447 blob_storage,
448 base::Passed(entry.Pass()),
449 base::Passed(response.Pass()),
450 base::Passed(read_context.Pass()));
452 int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
454 response_body_buffer.get(),
455 response_body_buffer->size(),
456 read_callback);
458 if (read_rv != net::ERR_IO_PENDING)
459 read_callback.Run(read_rv);
462 void MatchDidReadResponseBodyData(
463 ServiceWorkerFetchRequest* request,
464 const ServiceWorkerCache::ResponseCallback& callback,
465 base::WeakPtr<storage::BlobStorageContext> blob_storage,
466 disk_cache::ScopedEntryPtr entry,
467 scoped_ptr<ServiceWorkerResponse> response,
468 scoped_ptr<ResponseReadContext> response_context,
469 int rv) {
470 if (rv < 0) {
471 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
472 scoped_ptr<ServiceWorkerResponse>(),
473 scoped_ptr<storage::BlobDataHandle>());
474 return;
477 if (rv == 0) {
478 MatchDoneWithBody(request,
479 callback,
480 blob_storage,
481 response.Pass(),
482 response_context.Pass());
483 return;
486 // TODO(jkarlin): This copying of the the entire cache response into memory is
487 // awful. Create a new interface around SimpleCache that provides access the
488 // data directly from the file. See bug http://crbug.com/403493.
489 response_context->blob_data->AppendData(response_context->buffer->data(), rv);
490 response_context->total_bytes_read += rv;
491 int total_bytes_read = response_context->total_bytes_read;
493 // Grab some pointers before passing them in bind.
494 net::IOBufferWithSize* buffer = response_context->buffer.get();
495 disk_cache::Entry* tmp_entry_ptr = entry.get();
497 net::CompletionCallback read_callback =
498 base::Bind(MatchDidReadResponseBodyData,
499 request,
500 callback,
501 blob_storage,
502 base::Passed(entry.Pass()),
503 base::Passed(response.Pass()),
504 base::Passed(response_context.Pass()));
506 int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
507 total_bytes_read,
508 buffer,
509 buffer->size(),
510 read_callback);
512 if (read_rv != net::ERR_IO_PENDING)
513 read_callback.Run(read_rv);
516 void MatchDoneWithBody(ServiceWorkerFetchRequest* request,
517 const ServiceWorkerCache::ResponseCallback& callback,
518 base::WeakPtr<storage::BlobStorageContext> blob_storage,
519 scoped_ptr<ServiceWorkerResponse> response,
520 scoped_ptr<ResponseReadContext> response_context) {
521 if (!blob_storage) {
522 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
523 scoped_ptr<ServiceWorkerResponse>(),
524 scoped_ptr<storage::BlobDataHandle>());
525 return;
528 scoped_ptr<storage::BlobDataHandle> blob_data_handle(
529 blob_storage->AddFinishedBlob(response_context->blob_data.get()));
531 callback.Run(ServiceWorkerCache::ErrorTypeOK,
532 response.Pass(),
533 blob_data_handle.Pass());
536 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
537 const ServiceWorkerCache::ErrorCallback& callback,
538 scoped_ptr<disk_cache::Entry*> entryptr,
539 int rv) {
540 if (rv != net::OK) {
541 callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
542 return;
545 DCHECK(entryptr);
546 disk_cache::ScopedEntryPtr entry(*entryptr);
548 entry->Doom();
549 callback.Run(ServiceWorkerCache::ErrorTypeOK);
552 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
553 scoped_ptr<ScopedBackendPtr> backend_ptr,
554 base::WeakPtr<ServiceWorkerCache> cache,
555 int rv) {
556 if (rv != net::OK || !cache) {
557 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
558 return;
560 cache->set_backend(backend_ptr->Pass());
561 callback.Run(ServiceWorkerCache::ErrorTypeOK);
564 } // namespace
566 // static
567 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
568 net::URLRequestContext* request_context,
569 base::WeakPtr<storage::BlobStorageContext> blob_context) {
570 return make_scoped_ptr(
571 new ServiceWorkerCache(base::FilePath(), request_context, blob_context));
574 // static
575 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
576 const base::FilePath& path,
577 net::URLRequestContext* request_context,
578 base::WeakPtr<storage::BlobStorageContext> blob_context) {
579 return make_scoped_ptr(
580 new ServiceWorkerCache(path, request_context, blob_context));
583 ServiceWorkerCache::~ServiceWorkerCache() {
586 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
587 return weak_ptr_factory_.GetWeakPtr();
590 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
591 DCHECK(!backend_);
593 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
594 net::CacheType cache_type =
595 path_.empty() ? net::MEMORY_CACHE : net::APP_CACHE;
597 scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
599 // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
600 ScopedBackendPtr* backend = backend_ptr.get();
602 net::CompletionCallback create_cache_callback =
603 base::Bind(CreateBackendDidCreate,
604 callback,
605 base::Passed(backend_ptr.Pass()),
606 weak_ptr_factory_.GetWeakPtr());
608 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore
609 // has for disk caches.
610 // TODO(jkarlin): Switch to SimpleCache after it supports APP_CACHE and after
611 // debugging why the QuickStressBody unittest fails with it.
612 int rv = disk_cache::CreateCacheBackend(
613 cache_type,
614 net::CACHE_BACKEND_DEFAULT,
615 path_,
616 kMaxCacheBytes,
617 false, /* force */
618 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
619 NULL,
620 backend,
621 create_cache_callback);
622 if (rv != net::ERR_IO_PENDING)
623 create_cache_callback.Run(rv);
626 void ServiceWorkerCache::Put(ServiceWorkerFetchRequest* request,
627 ServiceWorkerResponse* response,
628 const ErrorCallback& callback) {
629 DCHECK(backend_);
631 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
633 disk_cache::Entry** entry_ptr = entry.get();
635 scoped_ptr<storage::BlobDataHandle> blob_data_handle;
637 if (!response->blob_uuid.empty()) {
638 if (!blob_storage_context_) {
639 callback.Run(ErrorTypeStorage);
640 return;
642 blob_data_handle =
643 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
644 if (!blob_data_handle) {
645 callback.Run(ErrorTypeStorage);
646 return;
650 net::CompletionCallback create_entry_callback =
651 base::Bind(PutDidCreateEntry,
652 request,
653 response,
654 callback,
655 base::Passed(entry.Pass()),
656 base::Passed(blob_data_handle.Pass()),
657 request_context_);
659 int rv = backend_->CreateEntry(
660 request->url.spec(), entry_ptr, create_entry_callback);
662 if (rv != net::ERR_IO_PENDING)
663 create_entry_callback.Run(rv);
666 void ServiceWorkerCache::Match(ServiceWorkerFetchRequest* request,
667 const ResponseCallback& callback) {
668 DCHECK(backend_);
670 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
672 disk_cache::Entry** entry_ptr = entry.get();
674 net::CompletionCallback open_entry_callback =
675 base::Bind(MatchDidOpenEntry,
676 request,
677 callback,
678 blob_storage_context_,
679 base::Passed(entry.Pass()));
681 int rv =
682 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
683 if (rv != net::ERR_IO_PENDING)
684 open_entry_callback.Run(rv);
687 void ServiceWorkerCache::Delete(ServiceWorkerFetchRequest* request,
688 const ErrorCallback& callback) {
689 DCHECK(backend_);
691 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
693 disk_cache::Entry** entry_ptr = entry.get();
695 net::CompletionCallback open_entry_callback = base::Bind(
696 DeleteDidOpenEntry, request, callback, base::Passed(entry.Pass()));
698 int rv =
699 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
700 if (rv != net::ERR_IO_PENDING)
701 open_entry_callback.Run(rv);
704 bool ServiceWorkerCache::HasCreatedBackend() const {
705 return backend_;
708 ServiceWorkerCache::ServiceWorkerCache(
709 const base::FilePath& path,
710 net::URLRequestContext* request_context,
711 base::WeakPtr<storage::BlobStorageContext> blob_context)
712 : path_(path),
713 request_context_(request_context),
714 blob_storage_context_(blob_context),
715 weak_ptr_factory_(this) {
718 } // namespace content