Chromium Code Reviews| 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 |