| 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 |