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" | |
11 #include "base/message_loop/message_loop_proxy.h" | |
12 #include "content/browser/fileapi/chrome_blob_storage_context.h" | |
13 #include "content/browser/service_worker/service_worker_cache.pb.h" | |
14 #include "content/public/browser/browser_thread.h" | |
15 #include "net/base/io_buffer.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/disk_cache/disk_cache.h" | |
10 #include "net/url_request/url_request_context.h" | 18 #include "net/url_request/url_request_context.h" |
19 #include "webkit/browser/blob/blob_data_handle.h" | |
11 #include "webkit/browser/blob/blob_storage_context.h" | 20 #include "webkit/browser/blob/blob_storage_context.h" |
21 #include "webkit/browser/blob/blob_url_request_job_factory.h" | |
12 | 22 |
13 namespace content { | 23 namespace content { |
14 | 24 |
25 namespace { | |
26 // The maximum size of an individual cache. | |
27 const int kMaxCacheBytes = 5 * 1024 * 1024; | |
michaeln
2014/08/14 10:35:20
why so small?
jkarlin
2014/08/14 19:53:32
Great question. No idea what's proper. Upped to
| |
28 | |
29 // Buffer size for cache and blob reading/writing. | |
30 const int kBufferSize = 1024 * 512; | |
michaeln
2014/08/14 10:35:19
why so big :)
jkarlin
2014/08/14 19:53:33
This is the size that we read from the cache when
| |
31 } | |
32 | |
33 struct ServiceWorkerCache::ResponseReadContext { | |
34 explicit ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff, | |
michaeln
2014/08/14 10:35:20
is explicit needed with two args
jkarlin
2014/08/14 19:53:32
Done.
| |
35 scoped_refptr<webkit_blob::BlobData> blob) | |
36 : buffer(buff), blob_data(blob), total_bytes_read(0) {} | |
37 | |
38 scoped_refptr<net::IOBufferWithSize> buffer; | |
39 scoped_refptr<webkit_blob::BlobData> blob_data; | |
40 int total_bytes_read; | |
41 | |
42 DISALLOW_COPY_AND_ASSIGN(ResponseReadContext); | |
43 }; | |
44 | |
45 // Streams data from a blob and writes it to a given disk_cache::Entry. | |
46 // This class is owned by the callback function passed to Start(). | |
47 class ServiceWorkerCache::BlobReader : public net::URLRequest::Delegate { | |
michaeln
2014/08/14 10:35:20
this is very similar to what ServiceWorkerWriteToC
jkarlin
2014/08/14 19:53:33
True, but not a straight-forward adaptation.
| |
48 public: | |
49 BlobReader(disk_cache::Entry* entry) | |
50 : cache_entry_offset_(0), | |
51 entry_(entry), | |
52 buffer_(new net::IOBufferWithSize(kBufferSize)) { | |
53 DCHECK(entry_); | |
54 } | |
55 | |
56 void StreamBlobToCache( | |
57 net::URLRequestContext* request_context, | |
58 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle, | |
59 const BoolCallback& callback) { | |
60 callback_ = callback; | |
61 blob_request_ = webkit_blob::BlobProtocolHandler::CreateBlobRequest( | |
62 blob_data_handle.Pass(), request_context, this); | |
63 blob_request_->Start(); | |
64 } | |
65 | |
66 // net::URLRequest::Delegate overrides for reading blobs. | |
67 virtual void OnReceivedRedirect(net::URLRequest* request, | |
68 const GURL& new_url, | |
69 bool* defer_redirect) OVERRIDE { | |
70 NOTREACHED(); | |
71 } | |
72 virtual void OnAuthRequired(net::URLRequest* request, | |
73 net::AuthChallengeInfo* auth_info) OVERRIDE { | |
74 NOTREACHED(); | |
75 } | |
76 virtual void OnCertificateRequested( | |
77 net::URLRequest* request, | |
78 net::SSLCertRequestInfo* cert_request_info) OVERRIDE { | |
79 NOTREACHED(); | |
80 } | |
81 virtual void OnSSLCertificateError(net::URLRequest* request, | |
82 const net::SSLInfo& ssl_info, | |
83 bool fatal) OVERRIDE { | |
84 NOTREACHED(); | |
85 } | |
86 virtual void OnBeforeNetworkStart(net::URLRequest* request, | |
87 bool* defer) OVERRIDE { | |
88 NOTREACHED(); | |
89 } | |
90 | |
91 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE { | |
92 if (!request->status().is_success()) { | |
93 callback_.Run(false); | |
94 return; | |
95 } | |
96 ReadFromBlob(); | |
97 } | |
98 | |
99 virtual void ReadFromBlob() { | |
100 int bytes_read; | |
101 bool done = | |
102 blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read); | |
103 if (done) | |
104 OnReadCompleted(blob_request_.get(), bytes_read); | |
105 } | |
106 | |
107 virtual void OnReadCompleted(net::URLRequest* request, | |
108 int bytes_read) OVERRIDE { | |
109 if (!request->status().is_success()) { | |
110 callback_.Run(false); | |
111 return; | |
112 } | |
113 | |
114 if (bytes_read == 0) { | |
115 callback_.Run(true); // what should we really return here? | |
116 return; | |
117 } | |
118 | |
119 net::CompletionCallback cache_write_callback = base::Bind( | |
120 &BlobReader::DidWriteDataToEntry, base::Unretained(this), bytes_read); | |
121 | |
122 LOG(ERROR) << "Writing: " << std::string(buffer_->data(), bytes_read); | |
123 | |
124 int rv = entry_->WriteData(ServiceWorkerCache::INDEX_RESPONSE_BODY, | |
125 cache_entry_offset_, | |
126 buffer_, | |
127 bytes_read, | |
128 cache_write_callback, | |
129 false /* truncate */); // what should this be? | |
130 if (rv != net::ERR_IO_PENDING) { | |
131 DidWriteDataToEntry(bytes_read, rv); | |
132 } | |
133 } | |
134 | |
135 void DidWriteDataToEntry(int expected_bytes, int rv) { | |
136 if (rv != expected_bytes) { | |
137 callback_.Run(false); | |
138 return; | |
139 } | |
140 | |
141 cache_entry_offset_ += rv; | |
142 ReadFromBlob(); | |
143 } | |
144 | |
145 private: | |
146 int cache_entry_offset_; | |
147 disk_cache::Entry* entry_; | |
148 scoped_ptr<net::URLRequest> blob_request_; | |
149 BoolCallback callback_; | |
150 scoped_refptr<net::IOBufferWithSize> buffer_; | |
151 }; | |
152 | |
15 // static | 153 // static |
16 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( | 154 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache( |
17 const std::string& name, | 155 const std::string& name, |
18 net::URLRequestContext* request_context, | 156 net::URLRequestContext* request_context, |
19 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { | 157 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { |
20 return make_scoped_ptr(new ServiceWorkerCache( | 158 return make_scoped_ptr(new ServiceWorkerCache( |
21 base::FilePath(), name, request_context, blob_context)); | 159 base::FilePath(), name, request_context, blob_context)); |
22 } | 160 } |
23 | 161 |
24 // static | 162 // static |
25 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache( | 163 scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache( |
26 const base::FilePath& path, | 164 const base::FilePath& path, |
27 const std::string& name, | 165 const std::string& name, |
28 net::URLRequestContext* request_context, | 166 net::URLRequestContext* request_context, |
29 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { | 167 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) { |
30 return make_scoped_ptr( | 168 return make_scoped_ptr( |
31 new ServiceWorkerCache(path, name, request_context, blob_context)); | 169 new ServiceWorkerCache(path, name, request_context, blob_context)); |
32 } | 170 } |
33 | 171 |
34 void ServiceWorkerCache::CreateBackend( | 172 ServiceWorkerCache::~ServiceWorkerCache() { |
35 const base::Callback<void(bool)>& callback) { | |
36 callback.Run(true); | |
37 } | 173 } |
38 | 174 |
39 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { | 175 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { |
40 return weak_ptr_factory_.GetWeakPtr(); | 176 return weak_ptr_factory_.GetWeakPtr(); |
41 } | 177 } |
42 | 178 |
179 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { | |
180 net::CacheType cache_type = | |
181 path_.empty() ? net::MEMORY_CACHE : net::DISK_CACHE; | |
182 | |
183 net::CompletionCallback create_cache_callback = | |
184 base::Bind(&ServiceWorkerCache::CreateBackendDidCreate, | |
185 base::Unretained(this), | |
186 callback); | |
187 int rv = disk_cache::CreateCacheBackend( | |
188 cache_type, | |
189 net::CACHE_BACKEND_SIMPLE, | |
190 path_, | |
191 kMaxCacheBytes, | |
192 true, /* force */ | |
193 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), | |
michaeln
2014/08/14 10:35:20
ServiceWorkerContextCore constructor has the cache
jkarlin
2014/08/14 19:53:32
Agree, added a TODO to do that in another CL.
| |
194 NULL, | |
195 &backend_, | |
michaeln
2014/08/14 10:35:20
initialization is treacherous, i think if ServiceW
jkarlin
2014/08/14 19:53:33
The ServiceWorkerCacheStorage::Delete(cache) can't
michaeln1
2014/08/14 22:57:09
The callback won't get called but &backend_ is wri
jkarlin
2014/08/15 11:49:44
Done.
| |
196 create_cache_callback); | |
197 if (rv != net::ERR_IO_PENDING) | |
198 CreateBackendDidCreate(callback, rv); | |
199 } | |
200 | |
201 void ServiceWorkerCache::CreateBackendDidCreate(const ErrorCallback& callback, | |
202 int rv) { | |
203 if (rv != net::OK) { | |
204 callback.Run(ErrorTypeStorage); | |
205 return; | |
206 } | |
207 callback.Run(ErrorTypeOK); | |
208 } | |
209 | |
210 void ServiceWorkerCache::Put(ServiceWorkerFetchRequest* request, | |
211 ServiceWorkerResponse* response, | |
212 const ErrorCallback& callback) { | |
213 DCHECK(backend_); | |
214 | |
215 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
216 | |
217 disk_cache::Entry** entry_ptr = entry.get(); | |
218 | |
219 net::CompletionCallback create_entry_callback = | |
220 base::Bind(&ServiceWorkerCache::PutDidCreateEntry, | |
221 base::Unretained(this), | |
222 request, | |
223 response, | |
224 callback, | |
225 base::Passed(entry.Pass())); | |
226 | |
227 int rv = backend_->CreateEntry( | |
228 request->url.spec(), entry_ptr, create_entry_callback); | |
229 | |
230 if (rv != net::ERR_IO_PENDING) | |
231 create_entry_callback.Run(rv); | |
232 } | |
233 | |
234 void ServiceWorkerCache::Match(ServiceWorkerFetchRequest* request, | |
235 const ResponseCallback& callback) { | |
236 DCHECK(backend_); | |
237 | |
238 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
239 | |
240 disk_cache::Entry** entry_ptr = entry.get(); | |
241 | |
242 net::CompletionCallback open_entry_callback = | |
243 base::Bind(&ServiceWorkerCache::MatchDidOpenEntry, | |
244 weak_ptr_factory_.GetWeakPtr(), | |
245 request, | |
246 callback, | |
247 base::Passed(entry.Pass())); | |
248 | |
249 int rv = | |
250 backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback); | |
251 if (rv != net::ERR_IO_PENDING) | |
252 open_entry_callback.Run(rv); | |
253 } | |
254 | |
255 void ServiceWorkerCache::MatchDidOpenEntry( | |
256 ServiceWorkerFetchRequest* request, | |
257 const ResponseCallback& callback, | |
258 scoped_ptr<disk_cache::Entry*> entryptr, | |
259 int rv) { | |
260 if (rv != net::OK) { | |
261 callback.Run(ErrorNotFound, | |
262 scoped_ptr<ServiceWorkerResponse>(), | |
263 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
264 return; | |
265 } | |
266 | |
267 DCHECK(entryptr); | |
268 disk_cache::Entry* entry = *entryptr; | |
269 | |
270 scoped_refptr<net::IOBufferWithSize> buffer( | |
271 new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS))); | |
272 | |
273 int read_rv = | |
274 entry->ReadData(INDEX_HEADERS, | |
275 0, | |
276 buffer.get(), | |
277 buffer->size(), | |
278 base::Bind(&ServiceWorkerCache::MatchDidReadHeaderData, | |
279 weak_ptr_factory_.GetWeakPtr(), | |
280 request, | |
281 callback, | |
282 base::Unretained(entry), | |
michaeln
2014/08/14 10:35:20
if ServiceWorkerCache is deleted while in flight,
jkarlin
2014/08/14 19:53:32
Yes, thanks. Hadn't gotten to all of the pointers
| |
283 buffer)); | |
284 if (read_rv != net::ERR_IO_PENDING) | |
285 MatchDidReadHeaderData(request, callback, entry, buffer, read_rv); | |
286 } | |
287 | |
288 void ServiceWorkerCache::MatchDidReadHeaderData( | |
289 ServiceWorkerFetchRequest* request, | |
290 const ResponseCallback& callback, | |
291 disk_cache::Entry* entry, | |
292 const scoped_refptr<net::IOBufferWithSize>& buffer, | |
293 int rv) { | |
294 if (rv != buffer->size()) { | |
295 entry->Close(); | |
296 callback.Run(ErrorTypeStorage, | |
297 scoped_ptr<ServiceWorkerResponse>(), | |
298 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
299 return; | |
300 } | |
301 | |
302 ServiceWorkerRequestResponseHeaders headers; | |
303 | |
304 if (!headers.ParseFromArray(buffer->data(), buffer->size())) { | |
305 entry->Close(); | |
306 callback.Run(ErrorTypeStorage, | |
307 scoped_ptr<ServiceWorkerResponse>(), | |
308 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
309 return; | |
310 } | |
311 | |
312 scoped_ptr<ServiceWorkerResponse> response( | |
313 new ServiceWorkerResponse(request->url, | |
314 headers.status_code(), | |
315 headers.status_text(), | |
316 std::map<std::string, std::string>(), | |
317 "")); | |
318 | |
319 for (int i = 0; i < headers.response_headers_size(); ++i) { | |
320 const ServiceWorkerRequestResponseHeaders::HeaderMap header = | |
321 headers.response_headers(i); | |
322 response->headers.insert(std::make_pair(header.name(), header.value())); | |
323 } | |
324 | |
325 // TODO(jkarlin): Insert vary validation here. | |
326 | |
327 if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) { | |
328 entry->Close(); | |
329 callback.Run(ErrorTypeOK, | |
330 response.Pass(), | |
331 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
332 return; | |
333 } | |
334 | |
335 // Stream the response body into a blob. | |
336 if (!blob_storage_context_) { | |
337 entry->Close(); | |
338 callback.Run(ErrorTypeStorage, | |
339 scoped_ptr<ServiceWorkerResponse>(), | |
340 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
341 return; | |
342 } | |
343 | |
344 response->blob_uuid = base::GenerateGUID(); | |
345 | |
346 scoped_refptr<webkit_blob::BlobData> blob_data = | |
347 new webkit_blob::BlobData(response->blob_uuid); | |
348 scoped_refptr<net::IOBufferWithSize> response_body_buffer( | |
349 new net::IOBufferWithSize(kBufferSize)); | |
350 | |
351 scoped_ptr<ResponseReadContext> read_context( | |
352 new ResponseReadContext(response_body_buffer, blob_data)); | |
353 | |
354 net::CompletionCallback read_callback = | |
355 base::Bind(&ServiceWorkerCache::MatchDidReadResponseBodyData, | |
356 weak_ptr_factory_.GetWeakPtr(), | |
357 request, | |
358 callback, | |
359 base::Unretained(entry), | |
360 base::Passed(response.Pass()), | |
361 base::Passed(read_context.Pass())); | |
362 | |
363 int read_rv = entry->ReadData( | |
364 INDEX_RESPONSE_BODY, 0, buffer.get(), buffer->size(), read_callback); | |
365 | |
366 if (read_rv != net::ERR_IO_PENDING) | |
367 read_callback.Run(read_rv); | |
368 } | |
369 | |
370 void ServiceWorkerCache::MatchDidReadResponseBodyData( | |
371 ServiceWorkerFetchRequest* request, | |
372 const ResponseCallback& callback, | |
373 disk_cache::Entry* entry, | |
374 scoped_ptr<ServiceWorkerResponse> response, | |
375 scoped_ptr<ResponseReadContext> response_context, | |
376 int rv) { | |
377 if (entry < 0) { | |
378 entry->Close(); | |
379 callback.Run(ErrorTypeStorage, | |
380 scoped_ptr<ServiceWorkerResponse>(), | |
381 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
382 } | |
383 | |
384 if (rv == 0) { | |
385 entry->Close(); | |
386 | |
387 MatchDoneWithBody( | |
388 request, callback, response.Pass(), response_context.Pass()); | |
389 return; | |
390 } | |
391 | |
392 // TODO(jkarlin): This copying of the the entire cache response into memory is | |
393 // awful. Create a new interface around SimpleCache that provides access the | |
394 // data directly from the file. See bug http://crbug.com/403493. | |
395 response_context->blob_data->AppendData(response_context->buffer->data(), rv); | |
396 response_context->total_bytes_read += rv; | |
397 int total_bytes_read = response_context->total_bytes_read; | |
398 | |
399 LOG(ERROR) << "Reading: " << std::string(response_context->buffer->data(), | |
400 rv); | |
401 // Grab the pointer before response_context is Pass()ed. | |
402 net::IOBufferWithSize* buffer = response_context->buffer; | |
403 | |
404 net::CompletionCallback read_callback = | |
405 base::Bind(&ServiceWorkerCache::MatchDidReadResponseBodyData, | |
406 weak_ptr_factory_.GetWeakPtr(), | |
407 request, | |
408 callback, | |
409 base::Unretained(entry), | |
410 base::Passed(response.Pass()), | |
411 base::Passed(response_context.Pass())); | |
412 | |
413 int read_rv = entry->ReadData(INDEX_RESPONSE_BODY, | |
414 total_bytes_read, | |
415 buffer, | |
416 buffer->size(), | |
417 read_callback); | |
418 | |
419 if (read_rv != net::ERR_IO_PENDING) | |
420 read_callback.Run(read_rv); | |
421 } | |
422 | |
423 void ServiceWorkerCache::MatchDoneWithBody( | |
424 ServiceWorkerFetchRequest* request, | |
425 const ResponseCallback& callback, | |
426 scoped_ptr<ServiceWorkerResponse> response, | |
427 scoped_ptr<ResponseReadContext> response_context) { | |
428 // TODO(jkarlin): Create a blob and pass it back to the renderer. How do we | |
429 // reference count that? | |
michaeln
2014/08/14 10:35:20
1) the uuid is sent from browser->renderer in the
jkarlin
2014/08/14 19:53:32
Acknowledged.
| |
430 if (!blob_storage_context_) { | |
431 callback.Run(ErrorTypeStorage, | |
432 scoped_ptr<ServiceWorkerResponse>(), | |
433 scoped_ptr<webkit_blob::BlobDataHandle>()); | |
434 return; | |
435 } | |
436 | |
437 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle( | |
438 blob_storage_context_->AddFinishedBlob( | |
439 response_context->blob_data.get())); | |
440 | |
441 callback.Run(ErrorTypeOK, response.Pass(), blob_data_handle.Pass()); | |
442 } | |
443 | |
444 void ServiceWorkerCache::PutDidCreateEntry( | |
445 ServiceWorkerFetchRequest* request, | |
446 ServiceWorkerResponse* response, | |
447 const ErrorCallback& callback, | |
448 scoped_ptr<disk_cache::Entry*> entryptr, | |
449 int rv) { | |
450 if (rv != net::OK) { | |
451 callback.Run(ErrorTypeExists); | |
452 return; | |
453 } | |
454 | |
455 DCHECK(entryptr); | |
456 disk_cache::Entry* entry = *entryptr; | |
457 | |
458 ServiceWorkerRequestResponseHeaders headers; | |
459 headers.set_method(request->method); | |
460 | |
461 headers.set_status_code(response->status_code); | |
462 headers.set_status_text(response->status_text); | |
463 for (std::map<std::string, std::string>::const_iterator it = | |
464 request->headers.begin(); | |
465 it != request->headers.end(); | |
466 ++it) { | |
467 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map = | |
468 headers.add_request_headers(); | |
469 header_map->set_name(it->first); | |
470 header_map->set_value(it->second); | |
471 } | |
472 | |
473 for (std::map<std::string, std::string>::const_iterator it = | |
474 response->headers.begin(); | |
475 it != response->headers.end(); | |
476 ++it) { | |
477 ServiceWorkerRequestResponseHeaders::HeaderMap* header_map = | |
478 headers.add_response_headers(); | |
479 header_map->set_name(it->first); | |
480 header_map->set_value(it->second); | |
481 } | |
482 | |
483 scoped_refptr<net::ZeroCopyStringIOBuffer> buffer( | |
michaeln
2014/08/14 10:35:20
would it make sense for the existing StringIOBuffe
jkarlin
2014/08/14 19:53:33
I like the idea of using std::string:swap. I chan
| |
484 new net::ZeroCopyStringIOBuffer()); | |
485 if (!headers.SerializeToString(buffer->string())) { | |
486 callback.Run(ErrorTypeStorage); | |
487 } | |
488 | |
489 buffer->Done(); | |
490 | |
491 net::CompletionCallback write_headers_callback = | |
492 base::Bind(&ServiceWorkerCache::PutDidWriteHeaders, | |
493 weak_ptr_factory_.GetWeakPtr(), | |
494 request, | |
495 response, | |
496 callback, | |
497 entry, | |
498 buffer->string()->size()); | |
499 | |
500 rv = entry->WriteData(INDEX_HEADERS, | |
501 0 /* offset */, | |
502 buffer, | |
503 buffer->string()->size(), | |
504 write_headers_callback, | |
505 true /* truncate */); | |
506 | |
507 if (rv != net::ERR_IO_PENDING) | |
508 write_headers_callback.Run(rv); | |
509 } | |
510 | |
511 void ServiceWorkerCache::PutDidWriteHeaders(ServiceWorkerFetchRequest* request, | |
512 ServiceWorkerResponse* response, | |
513 const ErrorCallback& callback, | |
514 disk_cache::Entry* entry, | |
515 int expected_bytes, | |
516 int rv) { | |
517 if (rv != expected_bytes) { | |
518 entry->Doom(); | |
519 entry->Close(); | |
520 callback.Run(ErrorTypeStorage); | |
521 return; | |
522 } | |
523 | |
524 // The metadata is written, now for the response content. The data is streamed | |
525 // from the blob into the cache entry. | |
526 | |
527 if (response->blob_uuid.empty()) { | |
528 entry->Close(); | |
529 callback.Run(ErrorTypeOK); | |
530 return; | |
531 } | |
532 | |
533 if (!blob_storage_context_) { | |
534 entry->Doom(); | |
535 entry->Close(); | |
536 callback.Run(ErrorTypeStorage); | |
537 return; | |
538 } | |
539 | |
540 scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle = | |
541 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); | |
michaeln
2014/08/14 10:35:20
you should get this handle up front in ServiceWork
jkarlin
2014/08/14 19:53:32
Thanks! Done and added test.
| |
542 | |
543 if (!blob_data_handle) { | |
544 entry->Doom(); | |
545 entry->Close(); | |
546 callback.Run(ErrorTypeStorage); | |
547 return; | |
548 } | |
549 | |
550 scoped_ptr<BlobReader> reader(new BlobReader(entry)); | |
551 | |
552 reader->StreamBlobToCache( | |
553 request_context_, | |
554 blob_data_handle.Pass(), | |
555 base::Bind(&ServiceWorkerCache::PutDidWriteBlobToCache, | |
556 weak_ptr_factory_.GetWeakPtr(), | |
557 callback, | |
558 entry, | |
michaeln
2014/08/14 10:35:20
if ServiceWorkerCache is deleted prior to completi
jkarlin
2014/08/14 19:53:33
Done.
| |
559 base::Passed(reader.Pass()))); | |
560 } | |
561 | |
562 void ServiceWorkerCache::PutDidWriteBlobToCache( | |
563 const ErrorCallback& callback, | |
564 disk_cache::Entry* entry, | |
565 scoped_ptr<BlobReader> blob_reader, | |
566 bool success) { | |
567 if (!success) { | |
568 entry->Doom(); | |
569 entry->Close(); | |
570 callback.Run(ErrorTypeStorage); | |
571 return; | |
572 } | |
573 | |
574 entry->Close(); | |
575 callback.Run(ErrorTypeOK); | |
576 } | |
577 | |
43 ServiceWorkerCache::ServiceWorkerCache( | 578 ServiceWorkerCache::ServiceWorkerCache( |
44 const base::FilePath& path, | 579 const base::FilePath& path, |
45 const std::string& name, | 580 const std::string& name, |
46 net::URLRequestContext* request_context, | 581 net::URLRequestContext* request_context, |
47 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) | 582 base::WeakPtr<webkit_blob::BlobStorageContext> blob_context) |
48 : path_(path), | 583 : path_(path), |
49 name_(name), | 584 name_(name), |
50 request_context_(request_context), | 585 request_context_(request_context), |
51 blob_storage_context_(blob_context), | 586 blob_storage_context_(blob_context), |
52 id_(0), | 587 id_(0), |
53 weak_ptr_factory_(this) { | 588 weak_ptr_factory_(this) { |
54 } | 589 } |
55 | 590 |
56 ServiceWorkerCache::~ServiceWorkerCache() { | |
57 } | |
58 | |
59 } // namespace content | 591 } // namespace content |
OLD | NEW |