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

Side by Side Diff: content/browser/service_worker/service_worker_cache.cc

Issue 465463002: Initial implementation of ServiceWorkerCache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cache2
Patch Set: Comments on inputs (request and response) and back to SimpleCache now that it's fixed 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/service_worker/service_worker_cache.h" 5 #include "content/browser/service_worker/service_worker_cache.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/files/file_path.h" 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"
10 #include "net/url_request/url_request_context.h" 17 #include "net/url_request/url_request_context.h"
18 #include "webkit/browser/blob/blob_data_handle.h"
11 #include "webkit/browser/blob/blob_storage_context.h" 19 #include "webkit/browser/blob/blob_storage_context.h"
20 #include "webkit/browser/blob/blob_url_request_job_factory.h"
12 21
13 namespace content { 22 namespace content {
14 23
24 namespace {
25
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 };
31
32 // The maximum size of an individual cache. Ultimately cache size is controlled
33 // per-origin.
34 const int kMaxCacheBytes = 512 * 1024 * 1024;
35
36 // Buffer size for cache and blob reading/writing.
37 const int kBufferSize = 1024 * 512;
38
39 struct ResponseReadContext {
40 ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
41 scoped_refptr<webkit_blob::BlobData> blob)
42 : buffer(buff), blob_data(blob), total_bytes_read(0) {}
43
44 scoped_refptr<net::IOBufferWithSize> buffer;
45 scoped_refptr<webkit_blob::BlobData> blob_data;
46 int total_bytes_read;
47
48 DISALLOW_COPY_AND_ASSIGN(ResponseReadContext);
49 };
50
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;
56
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();
63 }
64
65 void StreamBlobToCache(
66 net::URLRequestContext* request_context,
67 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
68 const EntryBoolCallback& callback) {
69 callback_ = callback;
70 blob_request_ = webkit_blob::BlobProtocolHandler::CreateBlobRequest(
71 blob_data_handle.Pass(), request_context, this);
72 blob_request_->Start();
73 }
74
75 // net::URLRequest::Delegate overrides for reading blobs.
76 virtual void OnReceivedRedirect(net::URLRequest* request,
77 const net::RedirectInfo& redirect_info,
78 bool* defer_redirect) OVERRIDE {
79 NOTREACHED();
80 }
81 virtual void OnAuthRequired(net::URLRequest* request,
82 net::AuthChallengeInfo* auth_info) OVERRIDE {
83 NOTREACHED();
84 }
85 virtual void OnCertificateRequested(
86 net::URLRequest* request,
87 net::SSLCertRequestInfo* cert_request_info) OVERRIDE {
88 NOTREACHED();
89 }
90 virtual void OnSSLCertificateError(net::URLRequest* request,
91 const net::SSLInfo& ssl_info,
92 bool fatal) OVERRIDE {
93 NOTREACHED();
94 }
95 virtual void OnBeforeNetworkStart(net::URLRequest* request,
96 bool* defer) OVERRIDE {
97 NOTREACHED();
98 }
99
100 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
101 if (!request->status().is_success()) {
102 callback_.Run(entry_.Pass(), false);
103 return;
104 }
105 ReadFromBlob();
106 }
107
108 virtual void ReadFromBlob() {
109 int bytes_read = 0;
110 bool done =
111 blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read);
112 if (done)
113 OnReadCompleted(blob_request_.get(), bytes_read);
114 }
115
116 virtual void OnReadCompleted(net::URLRequest* request,
117 int bytes_read) OVERRIDE {
118 if (!request->status().is_success()) {
119 callback_.Run(entry_.Pass(), false);
120 return;
121 }
122
123 if (bytes_read == 0) {
124 callback_.Run(entry_.Pass(), true);
125 return;
126 }
127
128 net::CompletionCallback cache_write_callback =
129 base::Bind(&BlobReader::DidWriteDataToEntry,
130 weak_ptr_factory_.GetWeakPtr(),
131 bytes_read);
132
133 int rv = entry_->WriteData(INDEX_RESPONSE_BODY,
134 cache_entry_offset_,
135 buffer_,
136 bytes_read,
137 cache_write_callback,
138 true /* truncate */);
139 if (rv != net::ERR_IO_PENDING)
140 cache_write_callback.Run(rv);
141 }
142
143 void DidWriteDataToEntry(int expected_bytes, int rv) {
144 if (rv != expected_bytes) {
145 callback_.Run(entry_.Pass(), false);
146 return;
147 }
148
149 cache_entry_offset_ += rv;
150 ReadFromBlob();
151 }
152
153 private:
154 int cache_entry_offset_;
155 disk_cache::ScopedEntryPtr entry_;
156 scoped_ptr<net::URLRequest> blob_request_;
157 EntryBoolCallback callback_;
158 scoped_refptr<net::IOBufferWithSize> buffer_;
159 base::WeakPtrFactory<BlobReader> weak_ptr_factory_;
160 };
161
162 // Put callbacks
163 void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
164 ServiceWorkerResponse* response,
165 const ServiceWorkerCache::ErrorCallback& callback,
166 scoped_ptr<disk_cache::Entry*> entryptr,
167 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
168 net::URLRequestContext* request_context,
169 int rv);
170 void PutDidWriteHeaders(
171 ServiceWorkerResponse* response,
172 const ServiceWorkerCache::ErrorCallback& callback,
173 disk_cache::ScopedEntryPtr entry,
174 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
175 net::URLRequestContext* request_context,
176 int expected_bytes,
177 int rv);
178 void PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
179 scoped_ptr<BlobReader> blob_reader,
180 disk_cache::ScopedEntryPtr entry,
181 bool success);
182
183 // Match callbacks
184 void MatchDidOpenEntry(
185 ServiceWorkerFetchRequest* request,
186 const ServiceWorkerCache::ResponseCallback& callback,
187 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
188 scoped_ptr<disk_cache::Entry*> entryptr,
189 int rv);
190 void MatchDidReadHeaderData(
191 ServiceWorkerFetchRequest* request,
192 const ServiceWorkerCache::ResponseCallback& callback,
193 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
194 disk_cache::ScopedEntryPtr entry,
195 const scoped_refptr<net::IOBufferWithSize>& buffer,
196 int rv);
197 void MatchDidReadResponseBodyData(
198 ServiceWorkerFetchRequest* request,
199 const ServiceWorkerCache::ResponseCallback& callback,
200 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
201 disk_cache::ScopedEntryPtr entry,
202 scoped_ptr<ServiceWorkerResponse> response,
203 scoped_ptr<ResponseReadContext> response_context,
204 int rv);
205 void MatchDoneWithBody(
206 ServiceWorkerFetchRequest* request,
207 const ServiceWorkerCache::ResponseCallback& callback,
208 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
209 scoped_ptr<ServiceWorkerResponse> response,
210 scoped_ptr<ResponseReadContext> response_context);
211
212 // Delete callbacks
213 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
214 const ServiceWorkerCache::ErrorCallback& callback,
215 scoped_ptr<disk_cache::Entry*> entryptr,
216 int rv);
217
218 // CreateBackend callbacks
219 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
220 scoped_ptr<ScopedBackendPtr> backend_ptr,
221 base::WeakPtr<ServiceWorkerCache> cache,
222 int rv);
223
224 void PutDidCreateEntry(ServiceWorkerFetchRequest* request,
225 ServiceWorkerResponse* response,
226 const ServiceWorkerCache::ErrorCallback& callback,
227 scoped_ptr<disk_cache::Entry*> entryptr,
228 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
229 net::URLRequestContext* request_context,
230 int rv) {
231 if (rv != net::OK) {
232 callback.Run(ServiceWorkerCache::ErrorTypeExists);
233 return;
234 }
235
236 DCHECK(entryptr);
237 disk_cache::ScopedEntryPtr entry(*entryptr);
238
239 ServiceWorkerRequestResponseHeaders headers;
240 headers.set_method(request->method);
241
242 headers.set_status_code(response->status_code);
243 headers.set_status_text(response->status_text);
244 for (std::map<std::string, std::string>::const_iterator it =
245 request->headers.begin();
246 it != request->headers.end();
247 ++it) {
248 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
249 headers.add_request_headers();
250 header_map->set_name(it->first);
251 header_map->set_value(it->second);
252 }
253
254 for (std::map<std::string, std::string>::const_iterator it =
255 response->headers.begin();
256 it != response->headers.end();
257 ++it) {
258 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
259 headers.add_response_headers();
260 header_map->set_name(it->first);
261 header_map->set_value(it->second);
262 }
263
264 scoped_ptr<std::string> serialized(new std::string());
265 if (!headers.SerializeToString(serialized.get())) {
266 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
267 return;
268 }
269
270 scoped_refptr<net::StringIOBuffer> buffer(
271 new net::StringIOBuffer(serialized.Pass()));
272
273 // Get a temporary copy of the entry pointer before passing it in base::Bind.
274 disk_cache::Entry* tmp_entry_ptr = entry.get();
275
276 net::CompletionCallback write_headers_callback =
277 base::Bind(PutDidWriteHeaders,
278 response,
279 callback,
280 base::Passed(entry.Pass()),
281 base::Passed(blob_data_handle.Pass()),
282 request_context,
283 buffer->size());
284
285 rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
286 0 /* offset */,
287 buffer,
288 buffer->size(),
289 write_headers_callback,
290 true /* truncate */);
291
292 if (rv != net::ERR_IO_PENDING)
293 write_headers_callback.Run(rv);
294 }
295
296 void PutDidWriteHeaders(
297 ServiceWorkerResponse* response,
298 const ServiceWorkerCache::ErrorCallback& callback,
299 disk_cache::ScopedEntryPtr entry,
300 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
301 net::URLRequestContext* request_context,
302 int expected_bytes,
303 int rv) {
304 if (rv != expected_bytes) {
305 entry->Doom();
306 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
307 return;
308 }
309
310 // The metadata is written, now for the response content. The data is streamed
311 // from the blob into the cache entry.
312
313 if (response->blob_uuid.empty()) {
314 callback.Run(ServiceWorkerCache::ErrorTypeOK);
315 return;
316 }
317
318 DCHECK(blob_data_handle);
319
320 scoped_ptr<BlobReader> reader(new BlobReader(entry.Pass()));
321 BlobReader* reader_ptr = reader.get();
322
323 reader_ptr->StreamBlobToCache(
324 request_context,
325 blob_data_handle.Pass(),
326 base::Bind(
327 PutDidWriteBlobToCache, callback, base::Passed(reader.Pass())));
328 }
329
330 void PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
331 scoped_ptr<BlobReader> blob_reader,
332 disk_cache::ScopedEntryPtr entry,
333 bool success) {
334 if (!success) {
335 entry->Doom();
336 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
337 return;
338 }
339
340 callback.Run(ServiceWorkerCache::ErrorTypeOK);
341 }
342
343 void MatchDidOpenEntry(
344 ServiceWorkerFetchRequest* request,
345 const ServiceWorkerCache::ResponseCallback& callback,
346 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
347 scoped_ptr<disk_cache::Entry*> entryptr,
348 int rv) {
349 if (rv != net::OK) {
350 callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
351 scoped_ptr<ServiceWorkerResponse>(),
352 scoped_ptr<webkit_blob::BlobDataHandle>());
353 return;
354 }
355
356 DCHECK(entryptr);
357 disk_cache::ScopedEntryPtr entry(*entryptr);
358
359 scoped_refptr<net::IOBufferWithSize> buffer(
360 new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
361
362 // Copy the entry pointer before passing it in base::Bind.
363 disk_cache::Entry* tmp_entry_ptr = entry.get();
364
365 net::CompletionCallback read_header_callback =
366 base::Bind(MatchDidReadHeaderData,
367 request,
368 callback,
369 blob_storage,
370 base::Passed(entry.Pass()),
371 buffer);
372
373 int read_rv = tmp_entry_ptr->ReadData(
374 INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
375
376 if (read_rv != net::ERR_IO_PENDING)
377 read_header_callback.Run(read_rv);
378 }
379
380 void MatchDidReadHeaderData(
381 ServiceWorkerFetchRequest* request,
382 const ServiceWorkerCache::ResponseCallback& callback,
383 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
384 disk_cache::ScopedEntryPtr entry,
385 const scoped_refptr<net::IOBufferWithSize>& buffer,
386 int rv) {
387 if (rv != buffer->size()) {
388 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
389 scoped_ptr<ServiceWorkerResponse>(),
390 scoped_ptr<webkit_blob::BlobDataHandle>());
391
392 return;
393 }
394
395 ServiceWorkerRequestResponseHeaders headers;
396
397 if (!headers.ParseFromArray(buffer->data(), buffer->size())) {
398 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
399 scoped_ptr<ServiceWorkerResponse>(),
400 scoped_ptr<webkit_blob::BlobDataHandle>());
401
402 return;
403 }
404
405 scoped_ptr<ServiceWorkerResponse> response(
406 new ServiceWorkerResponse(request->url,
407 headers.status_code(),
408 headers.status_text(),
409 std::map<std::string, std::string>(),
410 ""));
411
412 for (int i = 0; i < headers.response_headers_size(); ++i) {
413 const ServiceWorkerRequestResponseHeaders::HeaderMap header =
414 headers.response_headers(i);
415 response->headers.insert(std::make_pair(header.name(), header.value()));
416 }
417
418 // TODO(jkarlin): Insert vary validation here.
419
420 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
421 callback.Run(ServiceWorkerCache::ErrorTypeOK,
422 response.Pass(),
423 scoped_ptr<webkit_blob::BlobDataHandle>());
424 return;
425 }
426
427 // Stream the response body into a blob.
428 if (!blob_storage) {
429 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
430 scoped_ptr<ServiceWorkerResponse>(),
431 scoped_ptr<webkit_blob::BlobDataHandle>());
432
433 return;
434 }
435
436 response->blob_uuid = base::GenerateGUID();
437
438 scoped_refptr<webkit_blob::BlobData> blob_data =
439 new webkit_blob::BlobData(response->blob_uuid);
440 scoped_refptr<net::IOBufferWithSize> response_body_buffer(
441 new net::IOBufferWithSize(kBufferSize));
442
443 scoped_ptr<ResponseReadContext> read_context(
444 new ResponseReadContext(response_body_buffer, blob_data));
445
446 // Copy the entry pointer before passing it in base::Bind.
447 disk_cache::Entry* tmp_entry_ptr = entry.get();
448
449 net::CompletionCallback read_callback =
450 base::Bind(MatchDidReadResponseBodyData,
451 request,
452 callback,
453 blob_storage,
454 base::Passed(entry.Pass()),
455 base::Passed(response.Pass()),
456 base::Passed(read_context.Pass()));
457
458 int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
459 0,
460 response_body_buffer.get(),
461 response_body_buffer->size(),
462 read_callback);
463
464 if (read_rv != net::ERR_IO_PENDING)
465 read_callback.Run(read_rv);
466 }
467
468 void MatchDidReadResponseBodyData(
469 ServiceWorkerFetchRequest* request,
470 const ServiceWorkerCache::ResponseCallback& callback,
471 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
472 disk_cache::ScopedEntryPtr entry,
473 scoped_ptr<ServiceWorkerResponse> response,
474 scoped_ptr<ResponseReadContext> response_context,
475 int rv) {
476 if (rv < 0) {
477 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
478 scoped_ptr<ServiceWorkerResponse>(),
479 scoped_ptr<webkit_blob::BlobDataHandle>());
480 return;
481 }
482
483 if (rv == 0) {
484 MatchDoneWithBody(request,
485 callback,
486 blob_storage,
487 response.Pass(),
488 response_context.Pass());
489 return;
490 }
491
492 // TODO(jkarlin): This copying of the the entire cache response into memory is
493 // awful. Create a new interface around SimpleCache that provides access the
494 // data directly from the file. See bug http://crbug.com/403493.
495 response_context->blob_data->AppendData(response_context->buffer->data(), rv);
496 response_context->total_bytes_read += rv;
497 int total_bytes_read = response_context->total_bytes_read;
498
499 // Grab some pointers before passing them in bind.
500 net::IOBufferWithSize* buffer = response_context->buffer;
501 disk_cache::Entry* tmp_entry_ptr = entry.get();
502
503 net::CompletionCallback read_callback =
504 base::Bind(MatchDidReadResponseBodyData,
505 request,
506 callback,
507 blob_storage,
508 base::Passed(entry.Pass()),
509 base::Passed(response.Pass()),
510 base::Passed(response_context.Pass()));
511
512 int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
513 total_bytes_read,
514 buffer,
515 buffer->size(),
516 read_callback);
517
518 if (read_rv != net::ERR_IO_PENDING)
519 read_callback.Run(read_rv);
520 }
521
522 void MatchDoneWithBody(
523 ServiceWorkerFetchRequest* request,
524 const ServiceWorkerCache::ResponseCallback& callback,
525 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage,
526 scoped_ptr<ServiceWorkerResponse> response,
527 scoped_ptr<ResponseReadContext> response_context) {
528 if (!blob_storage) {
529 callback.Run(ServiceWorkerCache::ErrorTypeStorage,
530 scoped_ptr<ServiceWorkerResponse>(),
531 scoped_ptr<webkit_blob::BlobDataHandle>());
532 return;
533 }
534
535 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
536 blob_storage->AddFinishedBlob(response_context->blob_data.get()));
537
538 callback.Run(ServiceWorkerCache::ErrorTypeOK,
539 response.Pass(),
540 blob_data_handle.Pass());
541 }
542
543 void DeleteDidOpenEntry(ServiceWorkerFetchRequest* request,
544 const ServiceWorkerCache::ErrorCallback& callback,
545 scoped_ptr<disk_cache::Entry*> entryptr,
546 int rv) {
547 if (rv != net::OK) {
548 callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
549 return;
550 }
551
552 DCHECK(entryptr);
553 disk_cache::ScopedEntryPtr entry(*entryptr);
554
555 entry->Doom();
556 callback.Run(ServiceWorkerCache::ErrorTypeOK);
557 }
558
559 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
560 scoped_ptr<ScopedBackendPtr> backend_ptr,
561 base::WeakPtr<ServiceWorkerCache> cache,
562 int rv) {
563 if (rv != net::OK || !cache) {
564 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
565 return;
566 }
567 cache->set_backend(backend_ptr->Pass());
568 callback.Run(ServiceWorkerCache::ErrorTypeOK);
569 }
570
571 } // namespace
572
15 // static 573 // static
16 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( 574 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
17 const std::string& name, 575 const std::string& name,
18 net::URLRequestContext* request_context, 576 net::URLRequestContext* request_context,
19 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { 577 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) {
20 return make_scoped_ptr(new ServiceWorkerCache( 578 return make_scoped_ptr(new ServiceWorkerCache(
21 base::FilePath(), name, request_context, blob_context)); 579 base::FilePath(), name, request_context, blob_context));
22 } 580 }
23 581
24 // static 582 // static
25 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache( 583 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
26 const base::FilePath& path, 584 const base::FilePath& path,
27 const std::string& name, 585 const std::string& name,
28 net::URLRequestContext* request_context, 586 net::URLRequestContext* request_context,
29 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { 587 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) {
30 return make_scoped_ptr( 588 return make_scoped_ptr(
31 new ServiceWorkerCache(path, name, request_context, blob_context)); 589 new ServiceWorkerCache(path, name, request_context, blob_context));
32 } 590 }
33 591
34 void ServiceWorkerCache::CreateBackend( 592 ServiceWorkerCache::~ServiceWorkerCache() {
35 const base::Callback<void(bool)>& callback) {
36 callback.Run(true);
37 } 593 }
38 594
39 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { 595 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
40 return weak_ptr_factory_.GetWeakPtr(); 596 return weak_ptr_factory_.GetWeakPtr();
41 } 597 }
42 598
599 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
600 DCHECK(!backend_);
601
602 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
603 net::CacheType cache_type =
604 path_.empty() ? net::MEMORY_CACHE : net::APP_CACHE;
605
606 scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
607
608 // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
609 ScopedBackendPtr* backend = backend_ptr.get();
610
611 net::CompletionCallback create_cache_callback =
612 base::Bind(CreateBackendDidCreate,
613 callback,
614 base::Passed(backend_ptr.Pass()),
615 weak_ptr_factory_.GetWeakPtr());
616
617 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore
618 // has for disk caches.
619 // TODO(jkarlin): Switch to SimpleCache after it supports APP_CACHE and after
620 // debugging why the QuickStressBody unittest fails with it.
621 int rv = disk_cache::CreateCacheBackend(
622 cache_type,
623 net::CACHE_BACKEND_SIMPLE,
624 path_,
625 kMaxCacheBytes,
626 false, /* force */
627 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
628 NULL,
629 backend,
630 create_cache_callback);
631 if (rv != net::ERR_IO_PENDING)
632 create_cache_callback.Run(rv);
633 }
634
635 void ServiceWorkerCache::Put(ServiceWorkerFetchRequest* request,
636 ServiceWorkerResponse* response,
637 const ErrorCallback& callback) {
638 DCHECK(backend_);
639
640 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
641
642 disk_cache::Entry** entry_ptr = entry.get();
643
644 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
645
646 if (!response->blob_uuid.empty()) {
647 if (!blob_storage_context_) {
648 callback.Run(ErrorTypeStorage);
649 return;
650 }
651 blob_data_handle =
652 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
653 if (!blob_data_handle) {
654 callback.Run(ErrorTypeStorage);
655 return;
656 }
657 }
658
659 net::CompletionCallback create_entry_callback =
660 base::Bind(PutDidCreateEntry,
661 request,
662 response,
663 callback,
664 base::Passed(entry.Pass()),
665 base::Passed(blob_data_handle.Pass()),
666 request_context_);
667
668 int rv = backend_->CreateEntry(
669 request->url.spec(), entry_ptr, create_entry_callback);
670
671 if (rv != net::ERR_IO_PENDING)
672 create_entry_callback.Run(rv);
673 }
674
675 void ServiceWorkerCache::Match(ServiceWorkerFetchRequest* request,
676 const ResponseCallback& callback) {
677 DCHECK(backend_);
678
679 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
680
681 disk_cache::Entry** entry_ptr = entry.get();
682
683 net::CompletionCallback open_entry_callback =
684 base::Bind(MatchDidOpenEntry,
685 request,
686 callback,
687 blob_storage_context_,
688 base::Passed(entry.Pass()));
689
690 int rv =
691 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
692 if (rv != net::ERR_IO_PENDING)
693 open_entry_callback.Run(rv);
694 }
695
696 void ServiceWorkerCache::Delete(ServiceWorkerFetchRequest* request,
697 const ErrorCallback& callback) {
698 DCHECK(backend_);
699
700 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
701
702 disk_cache::Entry** entry_ptr = entry.get();
703
704 net::CompletionCallback open_entry_callback = base::Bind(
705 DeleteDidOpenEntry, request, callback, base::Passed(entry.Pass()));
706
707 int rv =
708 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
709 if (rv != net::ERR_IO_PENDING)
710 open_entry_callback.Run(rv);
711 }
712
713 bool ServiceWorkerCache::HasCreatedBackend() const {
714 return backend_;
715 }
716
43 ServiceWorkerCache::ServiceWorkerCache( 717 ServiceWorkerCache::ServiceWorkerCache(
44 const base::FilePath& path, 718 const base::FilePath& path,
45 const std::string& name, 719 const std::string& name,
46 net::URLRequestContext* request_context, 720 net::URLRequestContext* request_context,
47 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) 721 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context)
48 : path_(path), 722 : path_(path),
49 name_(name), 723 name_(name),
50 request_context_(request_context), 724 request_context_(request_context),
51 blob_storage_context_(blob_context), 725 blob_storage_context_(blob_context),
52 id_(0), 726 id_(0),
53 weak_ptr_factory_(this) { 727 weak_ptr_factory_(this) {
54 } 728 }
55 729
56 ServiceWorkerCache::~ServiceWorkerCache() {
57 }
58
59 } // namespace content 730 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698