OLD | NEW |
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" | 10 #include "base/guid.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 scoped_refptr<storage::BlobData> blob) | 87 scoped_refptr<storage::BlobData> blob) |
88 : buffer(buff), blob_data(blob), total_bytes_read(0) {} | 88 : buffer(buff), blob_data(blob), total_bytes_read(0) {} |
89 | 89 |
90 scoped_refptr<net::IOBufferWithSize> buffer; | 90 scoped_refptr<net::IOBufferWithSize> buffer; |
91 scoped_refptr<storage::BlobData> blob_data; | 91 scoped_refptr<storage::BlobData> blob_data; |
92 int total_bytes_read; | 92 int total_bytes_read; |
93 | 93 |
94 DISALLOW_COPY_AND_ASSIGN(ResponseReadContext); | 94 DISALLOW_COPY_AND_ASSIGN(ResponseReadContext); |
95 }; | 95 }; |
96 | 96 |
97 // Streams data from a blob and writes it to a given disk_cache::Entry. | |
98 class BlobReader : public net::URLRequest::Delegate { | |
99 public: | |
100 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> | |
101 EntryAndBoolCallback; | |
102 | |
103 BlobReader() | |
104 : cache_entry_offset_(0), | |
105 buffer_(new net::IOBufferWithSize(kBufferSize)), | |
106 weak_ptr_factory_(this) {} | |
107 | |
108 // |entry| is passed to the callback once complete. | |
109 void StreamBlobToCache(disk_cache::ScopedEntryPtr entry, | |
110 net::URLRequestContext* request_context, | |
111 scoped_ptr<storage::BlobDataHandle> blob_data_handle, | |
112 const EntryAndBoolCallback& callback) { | |
113 DCHECK(entry); | |
114 entry_ = entry.Pass(); | |
115 callback_ = callback; | |
116 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( | |
117 blob_data_handle.Pass(), request_context, this); | |
118 blob_request_->Start(); | |
119 } | |
120 | |
121 // net::URLRequest::Delegate overrides for reading blobs. | |
122 void OnReceivedRedirect(net::URLRequest* request, | |
123 const net::RedirectInfo& redirect_info, | |
124 bool* defer_redirect) override { | |
125 NOTREACHED(); | |
126 } | |
127 void OnAuthRequired(net::URLRequest* request, | |
128 net::AuthChallengeInfo* auth_info) override { | |
129 NOTREACHED(); | |
130 } | |
131 void OnCertificateRequested( | |
132 net::URLRequest* request, | |
133 net::SSLCertRequestInfo* cert_request_info) override { | |
134 NOTREACHED(); | |
135 } | |
136 void OnSSLCertificateError(net::URLRequest* request, | |
137 const net::SSLInfo& ssl_info, | |
138 bool fatal) override { | |
139 NOTREACHED(); | |
140 } | |
141 void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override { | |
142 NOTREACHED(); | |
143 } | |
144 | |
145 void OnResponseStarted(net::URLRequest* request) override { | |
146 if (!request->status().is_success()) { | |
147 callback_.Run(entry_.Pass(), false); | |
148 return; | |
149 } | |
150 ReadFromBlob(); | |
151 } | |
152 | |
153 virtual void ReadFromBlob() { | |
154 int bytes_read = 0; | |
155 bool done = | |
156 blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read); | |
157 if (done) | |
158 OnReadCompleted(blob_request_.get(), bytes_read); | |
159 } | |
160 | |
161 void OnReadCompleted(net::URLRequest* request, int bytes_read) override { | |
162 if (!request->status().is_success()) { | |
163 callback_.Run(entry_.Pass(), false); | |
164 return; | |
165 } | |
166 | |
167 if (bytes_read == 0) { | |
168 callback_.Run(entry_.Pass(), true); | |
169 return; | |
170 } | |
171 | |
172 net::CompletionCallback cache_write_callback = | |
173 base::Bind(&BlobReader::DidWriteDataToEntry, | |
174 weak_ptr_factory_.GetWeakPtr(), | |
175 bytes_read); | |
176 | |
177 int rv = entry_->WriteData(INDEX_RESPONSE_BODY, | |
178 cache_entry_offset_, | |
179 buffer_.get(), | |
180 bytes_read, | |
181 cache_write_callback, | |
182 true /* truncate */); | |
183 if (rv != net::ERR_IO_PENDING) | |
184 cache_write_callback.Run(rv); | |
185 } | |
186 | |
187 void DidWriteDataToEntry(int expected_bytes, int rv) { | |
188 if (rv != expected_bytes) { | |
189 callback_.Run(entry_.Pass(), false); | |
190 return; | |
191 } | |
192 | |
193 cache_entry_offset_ += rv; | |
194 ReadFromBlob(); | |
195 } | |
196 | |
197 private: | |
198 int cache_entry_offset_; | |
199 disk_cache::ScopedEntryPtr entry_; | |
200 scoped_ptr<net::URLRequest> blob_request_; | |
201 EntryAndBoolCallback callback_; | |
202 scoped_refptr<net::IOBufferWithSize> buffer_; | |
203 base::WeakPtrFactory<BlobReader> weak_ptr_factory_; | |
204 }; | |
205 | |
206 // The state needed to pass between ServiceWorkerCache::Put callbacks. | |
207 struct PutContext { | |
208 PutContext( | |
209 const GURL& origin, | |
210 scoped_ptr<ServiceWorkerFetchRequest> request, | |
211 scoped_ptr<ServiceWorkerResponse> response, | |
212 scoped_ptr<storage::BlobDataHandle> blob_data_handle, | |
213 const ServiceWorkerCache::ResponseCallback& callback, | |
214 net::URLRequestContext* request_context, | |
215 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy) | |
216 : origin(origin), | |
217 request(request.Pass()), | |
218 response(response.Pass()), | |
219 blob_data_handle(blob_data_handle.Pass()), | |
220 callback(callback), | |
221 request_context(request_context), | |
222 quota_manager_proxy(quota_manager_proxy), | |
223 cache_entry(NULL) {} | |
224 ~PutContext() { | |
225 if (cache_entry) | |
226 cache_entry->Close(); | |
227 } | |
228 | |
229 // Input parameters to the Put function. | |
230 GURL origin; | |
231 scoped_ptr<ServiceWorkerFetchRequest> request; | |
232 scoped_ptr<ServiceWorkerResponse> response; | |
233 scoped_ptr<storage::BlobDataHandle> blob_data_handle; | |
234 ServiceWorkerCache::ResponseCallback callback; | |
235 net::URLRequestContext* request_context; | |
236 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy; | |
237 | |
238 // This isn't a scoped_ptr because the disk_cache needs an Entry** as input to | |
239 // CreateEntry. | |
240 disk_cache::Entry* cache_entry; | |
241 | |
242 // The BlobDataHandle for the output ServiceWorkerResponse. | |
243 scoped_ptr<storage::BlobDataHandle> out_blob_data_handle; | |
244 | |
245 DISALLOW_COPY_AND_ASSIGN(PutContext); | |
246 }; | |
247 | |
248 // Put callbacks | |
249 void PutDidCreateEntry(scoped_ptr<PutContext> put_context, int rv); | |
250 void PutDidWriteHeaders(scoped_ptr<PutContext> put_context, | |
251 int expected_bytes, | |
252 int rv); | |
253 void PutDidWriteBlobToCache(scoped_ptr<PutContext> put_context, | |
254 scoped_ptr<BlobReader> blob_reader, | |
255 disk_cache::ScopedEntryPtr entry, | |
256 bool success); | |
257 | |
258 // Match callbacks | 97 // Match callbacks |
259 void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request, | 98 void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request, |
260 const ServiceWorkerCache::ResponseCallback& callback, | 99 const ServiceWorkerCache::ResponseCallback& callback, |
261 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 100 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
262 scoped_ptr<disk_cache::Entry*> entryptr, | 101 scoped_ptr<disk_cache::Entry*> entryptr, |
263 int rv); | 102 int rv); |
264 void MatchDidReadMetadata( | 103 void MatchDidReadMetadata( |
265 scoped_ptr<ServiceWorkerFetchRequest> request, | 104 scoped_ptr<ServiceWorkerFetchRequest> request, |
266 const ServiceWorkerCache::ResponseCallback& callback, | 105 const ServiceWorkerCache::ResponseCallback& callback, |
267 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 106 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
(...skipping 30 matching lines...) Expand all Loading... |
298 const MetadataCallback& callback, | 137 const MetadataCallback& callback, |
299 const scoped_refptr<net::IOBufferWithSize>& buffer, | 138 const scoped_refptr<net::IOBufferWithSize>& buffer, |
300 int rv); | 139 int rv); |
301 | 140 |
302 // CreateBackend callbacks | 141 // CreateBackend callbacks |
303 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, | 142 void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback, |
304 scoped_ptr<ScopedBackendPtr> backend_ptr, | 143 scoped_ptr<ScopedBackendPtr> backend_ptr, |
305 base::WeakPtr<ServiceWorkerCache> cache, | 144 base::WeakPtr<ServiceWorkerCache> cache, |
306 int rv); | 145 int rv); |
307 | 146 |
308 void PutDidCreateEntry(scoped_ptr<PutContext> put_context, int rv) { | |
309 if (rv != net::OK) { | |
310 put_context->callback.Run(ServiceWorkerCache::ErrorTypeExists, | |
311 scoped_ptr<ServiceWorkerResponse>(), | |
312 scoped_ptr<storage::BlobDataHandle>()); | |
313 return; | |
314 } | |
315 | |
316 DCHECK(put_context->cache_entry); | |
317 | |
318 ServiceWorkerCacheMetadata metadata; | |
319 ServiceWorkerCacheRequest* request_metadata = metadata.mutable_request(); | |
320 request_metadata->set_method(put_context->request->method); | |
321 for (ServiceWorkerHeaderMap::const_iterator it = | |
322 put_context->request->headers.begin(); | |
323 it != put_context->request->headers.end(); | |
324 ++it) { | |
325 ServiceWorkerCacheHeaderMap* header_map = request_metadata->add_headers(); | |
326 header_map->set_name(it->first); | |
327 header_map->set_value(it->second); | |
328 } | |
329 | |
330 ServiceWorkerCacheResponse* response_metadata = metadata.mutable_response(); | |
331 response_metadata->set_status_code(put_context->response->status_code); | |
332 response_metadata->set_status_text(put_context->response->status_text); | |
333 response_metadata->set_response_type( | |
334 WebResponseTypeToProtoResponseType(put_context->response->response_type)); | |
335 for (ServiceWorkerHeaderMap::const_iterator it = | |
336 put_context->response->headers.begin(); | |
337 it != put_context->response->headers.end(); | |
338 ++it) { | |
339 ServiceWorkerCacheHeaderMap* header_map = response_metadata->add_headers(); | |
340 header_map->set_name(it->first); | |
341 header_map->set_value(it->second); | |
342 } | |
343 | |
344 scoped_ptr<std::string> serialized(new std::string()); | |
345 if (!metadata.SerializeToString(serialized.get())) { | |
346 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, | |
347 scoped_ptr<ServiceWorkerResponse>(), | |
348 scoped_ptr<storage::BlobDataHandle>()); | |
349 return; | |
350 } | |
351 | |
352 scoped_refptr<net::StringIOBuffer> buffer( | |
353 new net::StringIOBuffer(serialized.Pass())); | |
354 | |
355 // Get a temporary copy of the entry pointer before passing it in base::Bind. | |
356 disk_cache::Entry* tmp_entry_ptr = put_context->cache_entry; | |
357 | |
358 net::CompletionCallback write_headers_callback = base::Bind( | |
359 PutDidWriteHeaders, base::Passed(put_context.Pass()), buffer->size()); | |
360 | |
361 rv = tmp_entry_ptr->WriteData(INDEX_HEADERS, | |
362 0 /* offset */, | |
363 buffer.get(), | |
364 buffer->size(), | |
365 write_headers_callback, | |
366 true /* truncate */); | |
367 | |
368 if (rv != net::ERR_IO_PENDING) | |
369 write_headers_callback.Run(rv); | |
370 } | |
371 | |
372 void PutDidWriteHeaders(scoped_ptr<PutContext> put_context, | |
373 int expected_bytes, | |
374 int rv) { | |
375 if (rv != expected_bytes) { | |
376 put_context->cache_entry->Doom(); | |
377 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, | |
378 scoped_ptr<ServiceWorkerResponse>(), | |
379 scoped_ptr<storage::BlobDataHandle>()); | |
380 return; | |
381 } | |
382 | |
383 // The metadata is written, now for the response content. The data is streamed | |
384 // from the blob into the cache entry. | |
385 | |
386 if (put_context->response->blob_uuid.empty()) { | |
387 if (put_context->quota_manager_proxy.get()) { | |
388 put_context->quota_manager_proxy->NotifyStorageModified( | |
389 storage::QuotaClient::kServiceWorkerCache, | |
390 put_context->origin, | |
391 storage::kStorageTypeTemporary, | |
392 put_context->cache_entry->GetDataSize(INDEX_HEADERS)); | |
393 } | |
394 | |
395 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, | |
396 put_context->response.Pass(), | |
397 scoped_ptr<storage::BlobDataHandle>()); | |
398 return; | |
399 } | |
400 | |
401 DCHECK(put_context->blob_data_handle); | |
402 | |
403 disk_cache::ScopedEntryPtr entry(put_context->cache_entry); | |
404 put_context->cache_entry = NULL; | |
405 scoped_ptr<BlobReader> reader(new BlobReader()); | |
406 BlobReader* reader_ptr = reader.get(); | |
407 | |
408 // Grab some pointers before passing put_context in Bind. | |
409 net::URLRequestContext* request_context = put_context->request_context; | |
410 scoped_ptr<storage::BlobDataHandle> blob_data_handle = | |
411 put_context->blob_data_handle.Pass(); | |
412 | |
413 reader_ptr->StreamBlobToCache(entry.Pass(), | |
414 request_context, | |
415 blob_data_handle.Pass(), | |
416 base::Bind(PutDidWriteBlobToCache, | |
417 base::Passed(put_context.Pass()), | |
418 base::Passed(reader.Pass()))); | |
419 } | |
420 | |
421 void PutDidWriteBlobToCache(scoped_ptr<PutContext> put_context, | |
422 scoped_ptr<BlobReader> blob_reader, | |
423 disk_cache::ScopedEntryPtr entry, | |
424 bool success) { | |
425 DCHECK(entry); | |
426 put_context->cache_entry = entry.release(); | |
427 | |
428 if (!success) { | |
429 put_context->cache_entry->Doom(); | |
430 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, | |
431 scoped_ptr<ServiceWorkerResponse>(), | |
432 scoped_ptr<storage::BlobDataHandle>()); | |
433 return; | |
434 } | |
435 | |
436 if (put_context->quota_manager_proxy.get()) { | |
437 put_context->quota_manager_proxy->NotifyStorageModified( | |
438 storage::QuotaClient::kServiceWorkerCache, | |
439 put_context->origin, | |
440 storage::kStorageTypeTemporary, | |
441 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + | |
442 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); | |
443 } | |
444 | |
445 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, | |
446 put_context->response.Pass(), | |
447 put_context->out_blob_data_handle.Pass()); | |
448 } | |
449 | |
450 void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request, | 147 void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request, |
451 const ServiceWorkerCache::ResponseCallback& callback, | 148 const ServiceWorkerCache::ResponseCallback& callback, |
452 base::WeakPtr<storage::BlobStorageContext> blob_storage, | 149 base::WeakPtr<storage::BlobStorageContext> blob_storage, |
453 scoped_ptr<disk_cache::Entry*> entryptr, | 150 scoped_ptr<disk_cache::Entry*> entryptr, |
454 int rv) { | 151 int rv) { |
455 if (rv != net::OK) { | 152 if (rv != net::OK) { |
456 callback.Run(ServiceWorkerCache::ErrorTypeNotFound, | 153 callback.Run(ServiceWorkerCache::ErrorTypeNotFound, |
457 scoped_ptr<ServiceWorkerResponse>(), | 154 scoped_ptr<ServiceWorkerResponse>(), |
458 scoped_ptr<storage::BlobDataHandle>()); | 155 scoped_ptr<storage::BlobDataHandle>()); |
459 return; | 156 return; |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 callback.Run(ServiceWorkerCache::ErrorTypeStorage); | 444 callback.Run(ServiceWorkerCache::ErrorTypeStorage); |
748 return; | 445 return; |
749 } | 446 } |
750 | 447 |
751 cache->set_backend(backend_ptr->Pass()); | 448 cache->set_backend(backend_ptr->Pass()); |
752 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 449 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
753 } | 450 } |
754 | 451 |
755 } // namespace | 452 } // namespace |
756 | 453 |
| 454 // Streams data from a blob and writes it to a given disk_cache::Entry. |
| 455 class ServiceWorkerCache::BlobReader : public net::URLRequest::Delegate { |
| 456 public: |
| 457 typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> |
| 458 EntryAndBoolCallback; |
| 459 |
| 460 BlobReader() |
| 461 : cache_entry_offset_(0), |
| 462 buffer_(new net::IOBufferWithSize(kBufferSize)), |
| 463 weak_ptr_factory_(this) {} |
| 464 |
| 465 // |entry| is passed to the callback once complete. |
| 466 void StreamBlobToCache(disk_cache::ScopedEntryPtr entry, |
| 467 net::URLRequestContext* request_context, |
| 468 scoped_ptr<storage::BlobDataHandle> blob_data_handle, |
| 469 const EntryAndBoolCallback& callback) { |
| 470 DCHECK(entry); |
| 471 entry_ = entry.Pass(); |
| 472 callback_ = callback; |
| 473 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( |
| 474 blob_data_handle.Pass(), request_context, this); |
| 475 blob_request_->Start(); |
| 476 } |
| 477 |
| 478 // net::URLRequest::Delegate overrides for reading blobs. |
| 479 void OnReceivedRedirect(net::URLRequest* request, |
| 480 const net::RedirectInfo& redirect_info, |
| 481 bool* defer_redirect) override { |
| 482 NOTREACHED(); |
| 483 } |
| 484 void OnAuthRequired(net::URLRequest* request, |
| 485 net::AuthChallengeInfo* auth_info) override { |
| 486 NOTREACHED(); |
| 487 } |
| 488 void OnCertificateRequested( |
| 489 net::URLRequest* request, |
| 490 net::SSLCertRequestInfo* cert_request_info) override { |
| 491 NOTREACHED(); |
| 492 } |
| 493 void OnSSLCertificateError(net::URLRequest* request, |
| 494 const net::SSLInfo& ssl_info, |
| 495 bool fatal) override { |
| 496 NOTREACHED(); |
| 497 } |
| 498 void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override { |
| 499 NOTREACHED(); |
| 500 } |
| 501 |
| 502 void OnResponseStarted(net::URLRequest* request) override { |
| 503 if (!request->status().is_success()) { |
| 504 callback_.Run(entry_.Pass(), false); |
| 505 return; |
| 506 } |
| 507 ReadFromBlob(); |
| 508 } |
| 509 |
| 510 virtual void ReadFromBlob() { |
| 511 int bytes_read = 0; |
| 512 bool done = |
| 513 blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read); |
| 514 if (done) |
| 515 OnReadCompleted(blob_request_.get(), bytes_read); |
| 516 } |
| 517 |
| 518 void OnReadCompleted(net::URLRequest* request, int bytes_read) override { |
| 519 if (!request->status().is_success()) { |
| 520 callback_.Run(entry_.Pass(), false); |
| 521 return; |
| 522 } |
| 523 |
| 524 if (bytes_read == 0) { |
| 525 callback_.Run(entry_.Pass(), true); |
| 526 return; |
| 527 } |
| 528 |
| 529 net::CompletionCallback cache_write_callback = |
| 530 base::Bind(&BlobReader::DidWriteDataToEntry, |
| 531 weak_ptr_factory_.GetWeakPtr(), |
| 532 bytes_read); |
| 533 |
| 534 int rv = entry_->WriteData(INDEX_RESPONSE_BODY, |
| 535 cache_entry_offset_, |
| 536 buffer_.get(), |
| 537 bytes_read, |
| 538 cache_write_callback, |
| 539 true /* truncate */); |
| 540 if (rv != net::ERR_IO_PENDING) |
| 541 cache_write_callback.Run(rv); |
| 542 } |
| 543 |
| 544 void DidWriteDataToEntry(int expected_bytes, int rv) { |
| 545 if (rv != expected_bytes) { |
| 546 callback_.Run(entry_.Pass(), false); |
| 547 return; |
| 548 } |
| 549 |
| 550 cache_entry_offset_ += rv; |
| 551 ReadFromBlob(); |
| 552 } |
| 553 |
| 554 private: |
| 555 int cache_entry_offset_; |
| 556 disk_cache::ScopedEntryPtr entry_; |
| 557 scoped_ptr<net::URLRequest> blob_request_; |
| 558 EntryAndBoolCallback callback_; |
| 559 scoped_refptr<net::IOBufferWithSize> buffer_; |
| 560 base::WeakPtrFactory<BlobReader> weak_ptr_factory_; |
| 561 }; |
| 562 |
757 // The state needed to pass between ServiceWorkerCache::Keys callbacks. | 563 // The state needed to pass between ServiceWorkerCache::Keys callbacks. |
758 struct ServiceWorkerCache::KeysContext { | 564 struct ServiceWorkerCache::KeysContext { |
759 KeysContext(const ServiceWorkerCache::RequestsCallback& callback, | 565 KeysContext(const ServiceWorkerCache::RequestsCallback& callback, |
760 base::WeakPtr<ServiceWorkerCache> cache) | 566 base::WeakPtr<ServiceWorkerCache> cache) |
761 : original_callback(callback), | 567 : original_callback(callback), |
762 cache(cache), | 568 cache(cache), |
763 out_keys(new ServiceWorkerCache::Requests()), | 569 out_keys(new ServiceWorkerCache::Requests()), |
764 enumerated_entry(NULL) {} | 570 enumerated_entry(NULL) {} |
765 | 571 |
766 ~KeysContext() { | 572 ~KeysContext() { |
(...skipping 15 matching lines...) Expand all Loading... |
782 // The output of the Keys function. | 588 // The output of the Keys function. |
783 scoped_ptr<ServiceWorkerCache::Requests> out_keys; | 589 scoped_ptr<ServiceWorkerCache::Requests> out_keys; |
784 | 590 |
785 // Used for enumerating cache entries. | 591 // Used for enumerating cache entries. |
786 scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; | 592 scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; |
787 disk_cache::Entry* enumerated_entry; | 593 disk_cache::Entry* enumerated_entry; |
788 | 594 |
789 DISALLOW_COPY_AND_ASSIGN(KeysContext); | 595 DISALLOW_COPY_AND_ASSIGN(KeysContext); |
790 }; | 596 }; |
791 | 597 |
| 598 // The state needed to pass between ServiceWorkerCache::Put callbacks. |
| 599 struct ServiceWorkerCache::PutContext { |
| 600 PutContext( |
| 601 const GURL& origin, |
| 602 scoped_ptr<ServiceWorkerFetchRequest> request, |
| 603 scoped_ptr<ServiceWorkerResponse> response, |
| 604 scoped_ptr<storage::BlobDataHandle> blob_data_handle, |
| 605 const ServiceWorkerCache::ResponseCallback& callback, |
| 606 base::WeakPtr<ServiceWorkerCache> cache, |
| 607 net::URLRequestContext* request_context, |
| 608 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy) |
| 609 : origin(origin), |
| 610 request(request.Pass()), |
| 611 response(response.Pass()), |
| 612 blob_data_handle(blob_data_handle.Pass()), |
| 613 callback(callback), |
| 614 cache(cache), |
| 615 request_context(request_context), |
| 616 quota_manager_proxy(quota_manager_proxy), |
| 617 cache_entry(NULL) {} |
| 618 ~PutContext() { |
| 619 if (cache_entry) |
| 620 cache_entry->Close(); |
| 621 } |
| 622 |
| 623 // Input parameters to the Put function. |
| 624 GURL origin; |
| 625 scoped_ptr<ServiceWorkerFetchRequest> request; |
| 626 scoped_ptr<ServiceWorkerResponse> response; |
| 627 scoped_ptr<storage::BlobDataHandle> blob_data_handle; |
| 628 ServiceWorkerCache::ResponseCallback callback; |
| 629 base::WeakPtr<ServiceWorkerCache> cache; |
| 630 net::URLRequestContext* request_context; |
| 631 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy; |
| 632 |
| 633 // This isn't a scoped_ptr because the disk_cache needs an Entry** as input to |
| 634 // CreateEntry. |
| 635 disk_cache::Entry* cache_entry; |
| 636 |
| 637 // The BlobDataHandle for the output ServiceWorkerResponse. |
| 638 scoped_ptr<storage::BlobDataHandle> out_blob_data_handle; |
| 639 |
| 640 DISALLOW_COPY_AND_ASSIGN(PutContext); |
| 641 }; |
| 642 |
792 // static | 643 // static |
793 scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( | 644 scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( |
794 const GURL& origin, | 645 const GURL& origin, |
795 net::URLRequestContext* request_context, | 646 net::URLRequestContext* request_context, |
796 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 647 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
797 base::WeakPtr<storage::BlobStorageContext> blob_context) { | 648 base::WeakPtr<storage::BlobStorageContext> blob_context) { |
798 return make_scoped_refptr(new ServiceWorkerCache(origin, | 649 return make_scoped_refptr(new ServiceWorkerCache(origin, |
799 base::FilePath(), | 650 base::FilePath(), |
800 request_context, | 651 request_context, |
801 quota_manager_proxy, | 652 quota_manager_proxy, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 blob_data_handle = | 686 blob_data_handle = |
836 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); | 687 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); |
837 if (!blob_data_handle) { | 688 if (!blob_data_handle) { |
838 callback.Run(ErrorTypeStorage, | 689 callback.Run(ErrorTypeStorage, |
839 scoped_ptr<ServiceWorkerResponse>(), | 690 scoped_ptr<ServiceWorkerResponse>(), |
840 scoped_ptr<storage::BlobDataHandle>()); | 691 scoped_ptr<storage::BlobDataHandle>()); |
841 return; | 692 return; |
842 } | 693 } |
843 } | 694 } |
844 | 695 |
| 696 scoped_ptr<PutContext> put_context( |
| 697 new PutContext(origin_, |
| 698 request.Pass(), |
| 699 response.Pass(), |
| 700 blob_data_handle.Pass(), |
| 701 callback, |
| 702 weak_ptr_factory_.GetWeakPtr(), |
| 703 request_context_, |
| 704 quota_manager_proxy_)); |
| 705 |
| 706 if (put_context->blob_data_handle) { |
| 707 // Grab another handle to the blob for the callback response. |
| 708 put_context->out_blob_data_handle = |
| 709 blob_storage_context_->GetBlobDataFromUUID( |
| 710 put_context->response->blob_uuid); |
| 711 } |
| 712 |
845 base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl, | 713 base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl, |
846 weak_ptr_factory_.GetWeakPtr(), | 714 base::Passed(put_context.Pass())); |
847 base::Passed(request.Pass()), | |
848 base::Passed(response.Pass()), | |
849 base::Passed(blob_data_handle.Pass()), | |
850 callback); | |
851 | 715 |
852 if (!initialized_) { | 716 if (!initialized_) { |
853 Init(continuation); | 717 Init(continuation); |
854 return; | 718 return; |
855 } | 719 } |
856 | 720 |
857 continuation.Run(); | 721 continuation.Run(); |
858 } | 722 } |
859 | 723 |
860 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 724 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 : origin_(origin), | 868 : origin_(origin), |
1005 path_(path), | 869 path_(path), |
1006 request_context_(request_context), | 870 request_context_(request_context), |
1007 quota_manager_proxy_(quota_manager_proxy), | 871 quota_manager_proxy_(quota_manager_proxy), |
1008 blob_storage_context_(blob_context), | 872 blob_storage_context_(blob_context), |
1009 initialized_(false), | 873 initialized_(false), |
1010 memory_only_(path.empty()), | 874 memory_only_(path.empty()), |
1011 weak_ptr_factory_(this) { | 875 weak_ptr_factory_(this) { |
1012 } | 876 } |
1013 | 877 |
1014 void ServiceWorkerCache::PutImpl( | 878 // static |
1015 scoped_ptr<ServiceWorkerFetchRequest> request, | 879 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { |
1016 scoped_ptr<ServiceWorkerResponse> response, | 880 if (!put_context->cache || !put_context->cache->backend_) { |
1017 scoped_ptr<storage::BlobDataHandle> blob_data_handle, | 881 put_context->callback.Run(ErrorTypeStorage, |
1018 const ResponseCallback& callback) { | 882 scoped_ptr<ServiceWorkerResponse>(), |
1019 if (!backend_) { | 883 scoped_ptr<storage::BlobDataHandle>()); |
1020 callback.Run(ErrorTypeStorage, | |
1021 scoped_ptr<ServiceWorkerResponse>(), | |
1022 scoped_ptr<storage::BlobDataHandle>()); | |
1023 return; | 884 return; |
1024 } | 885 } |
1025 | 886 |
1026 scoped_ptr<PutContext> put_context(new PutContext(origin_, | |
1027 request.Pass(), | |
1028 response.Pass(), | |
1029 blob_data_handle.Pass(), | |
1030 callback, | |
1031 request_context_, | |
1032 quota_manager_proxy_)); | |
1033 | |
1034 if (put_context->blob_data_handle) { | |
1035 // Grab another handle to the blob for the callback response. | |
1036 put_context->out_blob_data_handle = | |
1037 blob_storage_context_->GetBlobDataFromUUID( | |
1038 put_context->response->blob_uuid); | |
1039 } | |
1040 | |
1041 disk_cache::Entry** entry_ptr = &put_context->cache_entry; | 887 disk_cache::Entry** entry_ptr = &put_context->cache_entry; |
1042 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); | 888 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); |
| 889 disk_cache::Backend* backend_ptr = put_context->cache->backend_.get(); |
1043 | 890 |
1044 net::CompletionCallback create_entry_callback = | 891 net::CompletionCallback create_entry_callback = |
1045 base::Bind(PutDidCreateEntry, base::Passed(put_context.Pass())); | 892 base::Bind(PutDidCreateEntry, base::Passed(put_context.Pass())); |
1046 | 893 |
1047 int rv = backend_->CreateEntry( | 894 int create_rv = backend_ptr->CreateEntry( |
1048 request_ptr->url.spec(), entry_ptr, create_entry_callback); | 895 request_ptr->url.spec(), entry_ptr, create_entry_callback); |
1049 | 896 |
1050 if (rv != net::ERR_IO_PENDING) | 897 if (create_rv != net::ERR_IO_PENDING) |
1051 create_entry_callback.Run(rv); | 898 create_entry_callback.Run(create_rv); |
1052 } | 899 } |
1053 | 900 |
1054 // static | 901 // static |
| 902 void ServiceWorkerCache::PutDidCreateEntry(scoped_ptr<PutContext> put_context, |
| 903 int rv) { |
| 904 if (rv != net::OK) { |
| 905 put_context->callback.Run(ServiceWorkerCache::ErrorTypeExists, |
| 906 scoped_ptr<ServiceWorkerResponse>(), |
| 907 scoped_ptr<storage::BlobDataHandle>()); |
| 908 return; |
| 909 } |
| 910 |
| 911 DCHECK(put_context->cache_entry); |
| 912 |
| 913 ServiceWorkerCacheMetadata metadata; |
| 914 ServiceWorkerCacheRequest* request_metadata = metadata.mutable_request(); |
| 915 request_metadata->set_method(put_context->request->method); |
| 916 for (ServiceWorkerHeaderMap::const_iterator it = |
| 917 put_context->request->headers.begin(); |
| 918 it != put_context->request->headers.end(); |
| 919 ++it) { |
| 920 ServiceWorkerCacheHeaderMap* header_map = request_metadata->add_headers(); |
| 921 header_map->set_name(it->first); |
| 922 header_map->set_value(it->second); |
| 923 } |
| 924 |
| 925 ServiceWorkerCacheResponse* response_metadata = metadata.mutable_response(); |
| 926 response_metadata->set_status_code(put_context->response->status_code); |
| 927 response_metadata->set_status_text(put_context->response->status_text); |
| 928 response_metadata->set_response_type( |
| 929 WebResponseTypeToProtoResponseType(put_context->response->response_type)); |
| 930 for (ServiceWorkerHeaderMap::const_iterator it = |
| 931 put_context->response->headers.begin(); |
| 932 it != put_context->response->headers.end(); |
| 933 ++it) { |
| 934 ServiceWorkerCacheHeaderMap* header_map = response_metadata->add_headers(); |
| 935 header_map->set_name(it->first); |
| 936 header_map->set_value(it->second); |
| 937 } |
| 938 |
| 939 scoped_ptr<std::string> serialized(new std::string()); |
| 940 if (!metadata.SerializeToString(serialized.get())) { |
| 941 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
| 942 scoped_ptr<ServiceWorkerResponse>(), |
| 943 scoped_ptr<storage::BlobDataHandle>()); |
| 944 return; |
| 945 } |
| 946 |
| 947 scoped_refptr<net::StringIOBuffer> buffer( |
| 948 new net::StringIOBuffer(serialized.Pass())); |
| 949 |
| 950 // Get a temporary copy of the entry pointer before passing it in base::Bind. |
| 951 disk_cache::Entry* tmp_entry_ptr = put_context->cache_entry; |
| 952 |
| 953 net::CompletionCallback write_headers_callback = base::Bind( |
| 954 PutDidWriteHeaders, base::Passed(put_context.Pass()), buffer->size()); |
| 955 |
| 956 rv = tmp_entry_ptr->WriteData(INDEX_HEADERS, |
| 957 0 /* offset */, |
| 958 buffer.get(), |
| 959 buffer->size(), |
| 960 write_headers_callback, |
| 961 true /* truncate */); |
| 962 |
| 963 if (rv != net::ERR_IO_PENDING) |
| 964 write_headers_callback.Run(rv); |
| 965 } |
| 966 |
| 967 // static |
| 968 void ServiceWorkerCache::PutDidWriteHeaders(scoped_ptr<PutContext> put_context, |
| 969 int expected_bytes, |
| 970 int rv) { |
| 971 if (rv != expected_bytes) { |
| 972 put_context->cache_entry->Doom(); |
| 973 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
| 974 scoped_ptr<ServiceWorkerResponse>(), |
| 975 scoped_ptr<storage::BlobDataHandle>()); |
| 976 return; |
| 977 } |
| 978 |
| 979 // The metadata is written, now for the response content. The data is streamed |
| 980 // from the blob into the cache entry. |
| 981 |
| 982 if (put_context->response->blob_uuid.empty()) { |
| 983 if (put_context->quota_manager_proxy.get()) { |
| 984 put_context->quota_manager_proxy->NotifyStorageModified( |
| 985 storage::QuotaClient::kServiceWorkerCache, |
| 986 put_context->origin, |
| 987 storage::kStorageTypeTemporary, |
| 988 put_context->cache_entry->GetDataSize(INDEX_HEADERS)); |
| 989 } |
| 990 |
| 991 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, |
| 992 put_context->response.Pass(), |
| 993 scoped_ptr<storage::BlobDataHandle>()); |
| 994 return; |
| 995 } |
| 996 |
| 997 DCHECK(put_context->blob_data_handle); |
| 998 |
| 999 disk_cache::ScopedEntryPtr entry(put_context->cache_entry); |
| 1000 put_context->cache_entry = NULL; |
| 1001 scoped_ptr<BlobReader> reader(new BlobReader()); |
| 1002 BlobReader* reader_ptr = reader.get(); |
| 1003 |
| 1004 // Grab some pointers before passing put_context in Bind. |
| 1005 net::URLRequestContext* request_context = put_context->request_context; |
| 1006 scoped_ptr<storage::BlobDataHandle> blob_data_handle = |
| 1007 put_context->blob_data_handle.Pass(); |
| 1008 |
| 1009 reader_ptr->StreamBlobToCache(entry.Pass(), |
| 1010 request_context, |
| 1011 blob_data_handle.Pass(), |
| 1012 base::Bind(PutDidWriteBlobToCache, |
| 1013 base::Passed(put_context.Pass()), |
| 1014 base::Passed(reader.Pass()))); |
| 1015 } |
| 1016 |
| 1017 // static |
| 1018 void ServiceWorkerCache::PutDidWriteBlobToCache( |
| 1019 scoped_ptr<PutContext> put_context, |
| 1020 scoped_ptr<BlobReader> blob_reader, |
| 1021 disk_cache::ScopedEntryPtr entry, |
| 1022 bool success) { |
| 1023 DCHECK(entry); |
| 1024 put_context->cache_entry = entry.release(); |
| 1025 |
| 1026 if (!success) { |
| 1027 put_context->cache_entry->Doom(); |
| 1028 put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage, |
| 1029 scoped_ptr<ServiceWorkerResponse>(), |
| 1030 scoped_ptr<storage::BlobDataHandle>()); |
| 1031 return; |
| 1032 } |
| 1033 |
| 1034 if (put_context->quota_manager_proxy.get()) { |
| 1035 put_context->quota_manager_proxy->NotifyStorageModified( |
| 1036 storage::QuotaClient::kServiceWorkerCache, |
| 1037 put_context->origin, |
| 1038 storage::kStorageTypeTemporary, |
| 1039 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + |
| 1040 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); |
| 1041 } |
| 1042 |
| 1043 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, |
| 1044 put_context->response.Pass(), |
| 1045 put_context->out_blob_data_handle.Pass()); |
| 1046 } |
| 1047 |
| 1048 // static |
1055 void ServiceWorkerCache::KeysDidOpenNextEntry( | 1049 void ServiceWorkerCache::KeysDidOpenNextEntry( |
1056 scoped_ptr<KeysContext> keys_context, | 1050 scoped_ptr<KeysContext> keys_context, |
1057 int rv) { | 1051 int rv) { |
1058 if (rv == net::ERR_FAILED) { | 1052 if (rv == net::ERR_FAILED) { |
1059 DCHECK(!keys_context->enumerated_entry); | 1053 DCHECK(!keys_context->enumerated_entry); |
1060 // Enumeration is complete, extract the requests from the entries. | 1054 // Enumeration is complete, extract the requests from the entries. |
1061 Entries::iterator iter = keys_context->entries.begin(); | 1055 Entries::iterator iter = keys_context->entries.begin(); |
1062 KeysProcessNextEntry(keys_context.Pass(), iter); | 1056 KeysProcessNextEntry(keys_context.Pass(), iter); |
1063 return; | 1057 return; |
1064 } | 1058 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 initialized_ = true; | 1180 initialized_ = true; |
1187 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 1181 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); |
1188 it != init_callbacks_.end(); | 1182 it != init_callbacks_.end(); |
1189 ++it) { | 1183 ++it) { |
1190 it->Run(); | 1184 it->Run(); |
1191 } | 1185 } |
1192 init_callbacks_.clear(); | 1186 init_callbacks_.clear(); |
1193 } | 1187 } |
1194 | 1188 |
1195 } // namespace content | 1189 } // namespace content |
OLD | NEW |