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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 ServiceWorkerCache::~ServiceWorkerCache() { | 421 ServiceWorkerCache::~ServiceWorkerCache() { |
422 } | 422 } |
423 | 423 |
424 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { | 424 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { |
425 return weak_ptr_factory_.GetWeakPtr(); | 425 return weak_ptr_factory_.GetWeakPtr(); |
426 } | 426 } |
427 | 427 |
428 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, | 428 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, |
429 scoped_ptr<ServiceWorkerResponse> response, | 429 scoped_ptr<ServiceWorkerResponse> response, |
430 const ResponseCallback& callback) { | 430 const ResponseCallback& callback) { |
431 IncPendingOps(); | |
432 ResponseCallback pending_callback = | |
433 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | |
434 weak_ptr_factory_.GetWeakPtr(), callback); | |
435 scoped_ptr<storage::BlobDataHandle> blob_data_handle; | 431 scoped_ptr<storage::BlobDataHandle> blob_data_handle; |
436 | 432 |
437 if (!response->blob_uuid.empty()) { | 433 if (!response->blob_uuid.empty()) { |
438 if (!blob_storage_context_) { | 434 if (!blob_storage_context_) { |
439 pending_callback.Run(ErrorTypeStorage, | 435 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
440 scoped_ptr<ServiceWorkerResponse>(), | 436 scoped_ptr<storage::BlobDataHandle>()); |
441 scoped_ptr<storage::BlobDataHandle>()); | |
442 return; | 437 return; |
443 } | 438 } |
444 blob_data_handle = | 439 blob_data_handle = |
445 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); | 440 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); |
446 if (!blob_data_handle) { | 441 if (!blob_data_handle) { |
447 pending_callback.Run(ErrorTypeStorage, | 442 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
448 scoped_ptr<ServiceWorkerResponse>(), | 443 scoped_ptr<storage::BlobDataHandle>()); |
449 scoped_ptr<storage::BlobDataHandle>()); | |
450 return; | 444 return; |
451 } | 445 } |
452 } | 446 } |
453 | 447 |
| 448 ResponseCallback pending_callback = |
| 449 base::Bind(&ServiceWorkerCache::PendingResponseCallback, |
| 450 weak_ptr_factory_.GetWeakPtr(), callback); |
| 451 |
454 scoped_ptr<PutContext> put_context(new PutContext( | 452 scoped_ptr<PutContext> put_context(new PutContext( |
455 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), | 453 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), |
456 pending_callback, request_context_, quota_manager_proxy_)); | 454 pending_callback, request_context_, quota_manager_proxy_)); |
457 | 455 |
458 if (put_context->blob_data_handle) { | 456 if (put_context->blob_data_handle) { |
459 // Grab another handle to the blob for the callback response. | 457 // Grab another handle to the blob for the callback response. |
460 put_context->out_blob_data_handle = | 458 put_context->out_blob_data_handle = |
461 blob_storage_context_->GetBlobDataFromUUID( | 459 blob_storage_context_->GetBlobDataFromUUID( |
462 put_context->response->blob_uuid); | 460 put_context->response->blob_uuid); |
463 } | 461 } |
464 | 462 |
465 base::Closure continuation = | 463 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::PutImpl, |
466 base::Bind(&ServiceWorkerCache::PutImpl, weak_ptr_factory_.GetWeakPtr(), | 464 weak_ptr_factory_.GetWeakPtr(), |
467 base::Passed(put_context.Pass())); | 465 base::Passed(put_context.Pass()))); |
468 | 466 |
469 if (backend_state_ == BACKEND_UNINITIALIZED) { | 467 if (backend_state_ == BACKEND_UNINITIALIZED) { |
470 InitBackend(continuation); | 468 InitBackend(); |
471 return; | 469 return; |
472 } | 470 } |
473 | 471 |
474 continuation.Run(); | 472 RunOperationIfIdle(); |
475 } | 473 } |
476 | 474 |
477 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 475 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
478 const ResponseCallback& callback) { | 476 const ResponseCallback& callback) { |
479 IncPendingOps(); | |
480 ResponseCallback pending_callback = | 477 ResponseCallback pending_callback = |
481 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | 478 base::Bind(&ServiceWorkerCache::PendingResponseCallback, |
482 weak_ptr_factory_.GetWeakPtr(), callback); | 479 weak_ptr_factory_.GetWeakPtr(), callback); |
| 480 pending_operations_.push_back( |
| 481 base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(), |
| 482 base::Passed(request.Pass()), pending_callback)); |
483 | 483 |
484 switch (backend_state_) { | 484 switch (backend_state_) { |
485 case BACKEND_UNINITIALIZED: | 485 case BACKEND_UNINITIALIZED: |
486 InitBackend(base::Bind(&ServiceWorkerCache::Match, | 486 InitBackend(); |
487 weak_ptr_factory_.GetWeakPtr(), | |
488 base::Passed(request.Pass()), pending_callback)); | |
489 return; | 487 return; |
490 case BACKEND_CLOSED: | 488 case BACKEND_CLOSED: |
491 pending_callback.Run(ErrorTypeStorage, | 489 pending_callback.Run(ErrorTypeStorage, |
492 scoped_ptr<ServiceWorkerResponse>(), | 490 scoped_ptr<ServiceWorkerResponse>(), |
493 scoped_ptr<storage::BlobDataHandle>()); | 491 scoped_ptr<storage::BlobDataHandle>()); |
494 return; | 492 return; |
495 case BACKEND_OPEN: | 493 case BACKEND_OPEN: |
496 DCHECK(backend_); | 494 DCHECK(backend_); |
497 break; | 495 RunOperationIfIdle(); |
| 496 return; |
498 } | 497 } |
499 | 498 NOTREACHED(); |
500 scoped_ptr<MatchContext> match_context(new MatchContext( | |
501 request.Pass(), pending_callback, blob_storage_context_)); | |
502 | |
503 disk_cache::Entry** entry_ptr = &match_context->entry; | |
504 ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); | |
505 | |
506 net::CompletionCallback open_entry_callback = base::Bind( | |
507 &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
508 base::Passed(match_context.Pass())); | |
509 | |
510 int rv = backend_->OpenEntry( | |
511 request_ptr->url.spec(), entry_ptr, open_entry_callback); | |
512 if (rv != net::ERR_IO_PENDING) | |
513 open_entry_callback.Run(rv); | |
514 } | 499 } |
515 | 500 |
516 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, | 501 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, |
517 const ErrorCallback& callback) { | 502 const ErrorCallback& callback) { |
518 IncPendingOps(); | |
519 ErrorCallback pending_callback = | 503 ErrorCallback pending_callback = |
520 base::Bind(&ServiceWorkerCache::PendingErrorCallback, | 504 base::Bind(&ServiceWorkerCache::PendingErrorCallback, |
521 weak_ptr_factory_.GetWeakPtr(), callback); | 505 weak_ptr_factory_.GetWeakPtr(), callback); |
| 506 pending_operations_.push_back(base::Bind( |
| 507 &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(), |
| 508 base::Passed(request.Pass()), pending_callback)); |
522 | 509 |
523 switch (backend_state_) { | 510 switch (backend_state_) { |
524 case BACKEND_UNINITIALIZED: | 511 case BACKEND_UNINITIALIZED: |
525 InitBackend(base::Bind(&ServiceWorkerCache::Delete, | 512 InitBackend(); |
526 weak_ptr_factory_.GetWeakPtr(), | |
527 base::Passed(request.Pass()), pending_callback)); | |
528 return; | 513 return; |
529 case BACKEND_CLOSED: | 514 case BACKEND_CLOSED: |
530 pending_callback.Run(ErrorTypeStorage); | 515 pending_callback.Run(ErrorTypeStorage); |
531 return; | 516 return; |
532 case BACKEND_OPEN: | 517 case BACKEND_OPEN: |
533 DCHECK(backend_); | 518 DCHECK(backend_); |
534 break; | 519 RunOperationIfIdle(); |
| 520 return; |
535 } | 521 } |
536 | 522 NOTREACHED(); |
537 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
538 | |
539 disk_cache::Entry** entry_ptr = entry.get(); | |
540 | |
541 ServiceWorkerFetchRequest* request_ptr = request.get(); | |
542 | |
543 net::CompletionCallback open_entry_callback = base::Bind( | |
544 &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
545 origin_, base::Passed(request.Pass()), pending_callback, | |
546 base::Passed(entry.Pass()), quota_manager_proxy_); | |
547 | |
548 int rv = backend_->OpenEntry( | |
549 request_ptr->url.spec(), entry_ptr, open_entry_callback); | |
550 if (rv != net::ERR_IO_PENDING) | |
551 open_entry_callback.Run(rv); | |
552 } | 523 } |
553 | 524 |
554 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | 525 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { |
555 IncPendingOps(); | |
556 RequestsCallback pending_callback = | 526 RequestsCallback pending_callback = |
557 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, | 527 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, |
558 weak_ptr_factory_.GetWeakPtr(), callback); | 528 weak_ptr_factory_.GetWeakPtr(), callback); |
| 529 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::KeysImpl, |
| 530 weak_ptr_factory_.GetWeakPtr(), |
| 531 pending_callback)); |
559 | 532 |
560 switch (backend_state_) { | 533 switch (backend_state_) { |
561 case BACKEND_UNINITIALIZED: | 534 case BACKEND_UNINITIALIZED: |
562 InitBackend(base::Bind(&ServiceWorkerCache::Keys, | 535 InitBackend(); |
563 weak_ptr_factory_.GetWeakPtr(), pending_callback)); | |
564 return; | 536 return; |
565 case BACKEND_CLOSED: | 537 case BACKEND_CLOSED: |
566 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); | 538 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
567 return; | 539 return; |
568 case BACKEND_OPEN: | 540 case BACKEND_OPEN: |
569 DCHECK(backend_); | 541 DCHECK(backend_); |
570 break; | 542 RunOperationIfIdle(); |
| 543 return; |
571 } | 544 } |
572 | 545 NOTREACHED(); |
573 // 1. Iterate through all of the entries, open them, and add them to a vector. | |
574 // 2. For each open entry: | |
575 // 2.1. Read the headers into a protobuf. | |
576 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | |
577 // 2.3. Push the response into a vector of requests to be returned. | |
578 // 3. Return the vector of requests (keys). | |
579 | |
580 // The entries have to be loaded into a vector first because enumeration loops | |
581 // forever if you read data from a cache entry while enumerating. | |
582 | |
583 scoped_ptr<KeysContext> keys_context(new KeysContext(pending_callback)); | |
584 | |
585 keys_context->backend_iterator = backend_->CreateIterator(); | |
586 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; | |
587 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | |
588 | |
589 net::CompletionCallback open_entry_callback = base::Bind( | |
590 &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), | |
591 base::Passed(keys_context.Pass())); | |
592 | |
593 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); | |
594 | |
595 if (rv != net::ERR_IO_PENDING) | |
596 open_entry_callback.Run(rv); | |
597 } | 546 } |
598 | 547 |
599 void ServiceWorkerCache::Close(const base::Closure& callback) { | 548 void ServiceWorkerCache::Close(const base::Closure& callback) { |
600 DCHECK(backend_state_ != BACKEND_CLOSED) | 549 DCHECK(backend_state_ != BACKEND_CLOSED) |
601 << "Don't call ServiceWorkerCache::Close() twice."; | 550 << "Don't call ServiceWorkerCache::Close() twice."; |
602 | 551 |
603 backend_state_ = BACKEND_CLOSED; | 552 base::Closure pending_callback = |
604 if (pending_ops_ > 0) { | 553 base::Bind(&ServiceWorkerCache::PendingClosure, |
605 DCHECK(ops_complete_callback_.is_null()); | 554 weak_ptr_factory_.GetWeakPtr(), callback); |
606 ops_complete_callback_ = | |
607 base::Bind(&ServiceWorkerCache::CloseImpl, | |
608 weak_ptr_factory_.GetWeakPtr(), callback); | |
609 return; | |
610 } | |
611 | 555 |
612 CloseImpl(callback); | 556 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::CloseImpl, |
| 557 weak_ptr_factory_.GetWeakPtr(), |
| 558 pending_callback)); |
| 559 RunOperationIfIdle(); |
613 } | 560 } |
614 | 561 |
615 int64 ServiceWorkerCache::MemoryBackedSize() const { | 562 int64 ServiceWorkerCache::MemoryBackedSize() const { |
616 if (backend_state_ != BACKEND_OPEN || !memory_only_) | 563 if (backend_state_ != BACKEND_OPEN || !memory_only_) |
617 return 0; | 564 return 0; |
618 | 565 |
619 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = | 566 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = |
620 backend_->CreateIterator(); | 567 backend_->CreateIterator(); |
621 disk_cache::Entry* entry = nullptr; | 568 disk_cache::Entry* entry = nullptr; |
622 | 569 |
(...skipping 22 matching lines...) Expand all Loading... |
645 const base::FilePath& path, | 592 const base::FilePath& path, |
646 net::URLRequestContext* request_context, | 593 net::URLRequestContext* request_context, |
647 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 594 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
648 base::WeakPtr<storage::BlobStorageContext> blob_context) | 595 base::WeakPtr<storage::BlobStorageContext> blob_context) |
649 : origin_(origin), | 596 : origin_(origin), |
650 path_(path), | 597 path_(path), |
651 request_context_(request_context), | 598 request_context_(request_context), |
652 quota_manager_proxy_(quota_manager_proxy), | 599 quota_manager_proxy_(quota_manager_proxy), |
653 blob_storage_context_(blob_context), | 600 blob_storage_context_(blob_context), |
654 backend_state_(BACKEND_UNINITIALIZED), | 601 backend_state_(BACKEND_UNINITIALIZED), |
| 602 operation_running_(false), |
| 603 initializing_(false), |
655 memory_only_(path.empty()), | 604 memory_only_(path.empty()), |
656 pending_ops_(0), | |
657 weak_ptr_factory_(this) { | 605 weak_ptr_factory_(this) { |
658 } | 606 } |
659 | 607 |
| 608 void ServiceWorkerCache::MatchImpl( |
| 609 scoped_ptr<ServiceWorkerFetchRequest> request, |
| 610 const ResponseCallback& callback) { |
| 611 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); |
| 612 if (backend_state_ != BACKEND_OPEN) { |
| 613 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
| 614 scoped_ptr<storage::BlobDataHandle>()); |
| 615 return; |
| 616 } |
| 617 |
| 618 scoped_ptr<MatchContext> match_context( |
| 619 new MatchContext(request.Pass(), callback, blob_storage_context_)); |
| 620 |
| 621 disk_cache::Entry** entry_ptr = &match_context->entry; |
| 622 ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); |
| 623 |
| 624 net::CompletionCallback open_entry_callback = base::Bind( |
| 625 &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), |
| 626 base::Passed(match_context.Pass())); |
| 627 |
| 628 int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, |
| 629 open_entry_callback); |
| 630 if (rv != net::ERR_IO_PENDING) |
| 631 open_entry_callback.Run(rv); |
| 632 } |
| 633 |
660 void ServiceWorkerCache::MatchDidOpenEntry( | 634 void ServiceWorkerCache::MatchDidOpenEntry( |
661 scoped_ptr<MatchContext> match_context, | 635 scoped_ptr<MatchContext> match_context, |
662 int rv) { | 636 int rv) { |
663 if (rv != net::OK) { | 637 if (rv != net::OK) { |
664 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeNotFound, | 638 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeNotFound, |
665 scoped_ptr<ServiceWorkerResponse>(), | 639 scoped_ptr<ServiceWorkerResponse>(), |
666 scoped_ptr<storage::BlobDataHandle>()); | 640 scoped_ptr<storage::BlobDataHandle>()); |
667 return; | 641 return; |
668 } | 642 } |
669 | 643 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 scoped_ptr<storage::BlobDataHandle> blob_data_handle( | 785 scoped_ptr<storage::BlobDataHandle> blob_data_handle( |
812 match_context->blob_storage_context->AddFinishedBlob( | 786 match_context->blob_storage_context->AddFinishedBlob( |
813 match_context->blob_data.get())); | 787 match_context->blob_data.get())); |
814 | 788 |
815 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeOK, | 789 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeOK, |
816 match_context->response.Pass(), | 790 match_context->response.Pass(), |
817 blob_data_handle.Pass()); | 791 blob_data_handle.Pass()); |
818 } | 792 } |
819 | 793 |
820 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { | 794 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { |
| 795 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); |
821 if (backend_state_ != BACKEND_OPEN) { | 796 if (backend_state_ != BACKEND_OPEN) { |
822 put_context->callback.Run(ErrorTypeStorage, | 797 put_context->callback.Run(ErrorTypeStorage, |
823 scoped_ptr<ServiceWorkerResponse>(), | 798 scoped_ptr<ServiceWorkerResponse>(), |
824 scoped_ptr<storage::BlobDataHandle>()); | 799 scoped_ptr<storage::BlobDataHandle>()); |
825 return; | 800 return; |
826 } | 801 } |
827 | 802 |
828 scoped_ptr<ServiceWorkerFetchRequest> request_copy( | 803 scoped_ptr<ServiceWorkerFetchRequest> request_copy( |
829 new ServiceWorkerFetchRequest(*put_context->request)); | 804 new ServiceWorkerFetchRequest(*put_context->request)); |
830 | 805 |
831 Delete(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, | 806 DeleteImpl(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, |
832 weak_ptr_factory_.GetWeakPtr(), | 807 weak_ptr_factory_.GetWeakPtr(), |
833 base::Passed(put_context.Pass()))); | 808 base::Passed(put_context.Pass()))); |
834 } | 809 } |
835 | 810 |
836 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, | 811 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, |
837 ErrorType delete_error) { | 812 ErrorType delete_error) { |
838 if (backend_state_ != BACKEND_OPEN) { | 813 if (backend_state_ != BACKEND_OPEN) { |
839 put_context->callback.Run(ErrorTypeStorage, | 814 put_context->callback.Run(ErrorTypeStorage, |
840 scoped_ptr<ServiceWorkerResponse>(), | 815 scoped_ptr<ServiceWorkerResponse>(), |
841 scoped_ptr<storage::BlobDataHandle>()); | 816 scoped_ptr<storage::BlobDataHandle>()); |
842 return; | 817 return; |
843 } | 818 } |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 storage::kStorageTypeTemporary, | 971 storage::kStorageTypeTemporary, |
997 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + | 972 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + |
998 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); | 973 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); |
999 } | 974 } |
1000 | 975 |
1001 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, | 976 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, |
1002 put_context->response.Pass(), | 977 put_context->response.Pass(), |
1003 put_context->out_blob_data_handle.Pass()); | 978 put_context->out_blob_data_handle.Pass()); |
1004 } | 979 } |
1005 | 980 |
| 981 void ServiceWorkerCache::DeleteImpl( |
| 982 scoped_ptr<ServiceWorkerFetchRequest> request, |
| 983 const ErrorCallback& callback) { |
| 984 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); |
| 985 if (backend_state_ != BACKEND_OPEN) { |
| 986 callback.Run(ErrorTypeStorage); |
| 987 return; |
| 988 } |
| 989 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
| 990 |
| 991 disk_cache::Entry** entry_ptr = entry.get(); |
| 992 |
| 993 ServiceWorkerFetchRequest* request_ptr = request.get(); |
| 994 |
| 995 net::CompletionCallback open_entry_callback = base::Bind( |
| 996 &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), |
| 997 origin_, base::Passed(request.Pass()), callback, |
| 998 base::Passed(entry.Pass()), quota_manager_proxy_); |
| 999 |
| 1000 int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, |
| 1001 open_entry_callback); |
| 1002 if (rv != net::ERR_IO_PENDING) |
| 1003 open_entry_callback.Run(rv); |
| 1004 } |
| 1005 |
1006 void ServiceWorkerCache::DeleteDidOpenEntry( | 1006 void ServiceWorkerCache::DeleteDidOpenEntry( |
1007 const GURL& origin, | 1007 const GURL& origin, |
1008 scoped_ptr<ServiceWorkerFetchRequest> request, | 1008 scoped_ptr<ServiceWorkerFetchRequest> request, |
1009 const ServiceWorkerCache::ErrorCallback& callback, | 1009 const ServiceWorkerCache::ErrorCallback& callback, |
1010 scoped_ptr<disk_cache::Entry*> entry_ptr, | 1010 scoped_ptr<disk_cache::Entry*> entry_ptr, |
1011 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 1011 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
1012 int rv) { | 1012 int rv) { |
1013 if (rv != net::OK) { | 1013 if (rv != net::OK) { |
1014 callback.Run(ServiceWorkerCache::ErrorTypeNotFound); | 1014 callback.Run(ServiceWorkerCache::ErrorTypeNotFound); |
1015 return; | 1015 return; |
1016 } | 1016 } |
1017 | 1017 |
1018 DCHECK(entry_ptr); | 1018 DCHECK(entry_ptr); |
1019 disk_cache::ScopedEntryPtr entry(*entry_ptr); | 1019 disk_cache::ScopedEntryPtr entry(*entry_ptr); |
1020 | 1020 |
1021 if (quota_manager_proxy.get()) { | 1021 if (quota_manager_proxy.get()) { |
1022 quota_manager_proxy->NotifyStorageModified( | 1022 quota_manager_proxy->NotifyStorageModified( |
1023 storage::QuotaClient::kServiceWorkerCache, origin, | 1023 storage::QuotaClient::kServiceWorkerCache, origin, |
1024 storage::kStorageTypeTemporary, | 1024 storage::kStorageTypeTemporary, |
1025 -1 * (entry->GetDataSize(INDEX_HEADERS) + | 1025 -1 * (entry->GetDataSize(INDEX_HEADERS) + |
1026 entry->GetDataSize(INDEX_RESPONSE_BODY))); | 1026 entry->GetDataSize(INDEX_RESPONSE_BODY))); |
1027 } | 1027 } |
1028 | 1028 |
1029 entry->Doom(); | 1029 entry->Doom(); |
1030 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 1030 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
1031 } | 1031 } |
1032 | 1032 |
| 1033 void ServiceWorkerCache::KeysImpl(const RequestsCallback& callback) { |
| 1034 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); |
| 1035 if (backend_state_ != BACKEND_OPEN) { |
| 1036 callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
| 1037 return; |
| 1038 } |
| 1039 |
| 1040 // 1. Iterate through all of the entries, open them, and add them to a vector. |
| 1041 // 2. For each open entry: |
| 1042 // 2.1. Read the headers into a protobuf. |
| 1043 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). |
| 1044 // 2.3. Push the response into a vector of requests to be returned. |
| 1045 // 3. Return the vector of requests (keys). |
| 1046 |
| 1047 // The entries have to be loaded into a vector first because enumeration loops |
| 1048 // forever if you read data from a cache entry while enumerating. |
| 1049 |
| 1050 scoped_ptr<KeysContext> keys_context(new KeysContext(callback)); |
| 1051 |
| 1052 keys_context->backend_iterator = backend_->CreateIterator(); |
| 1053 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; |
| 1054 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; |
| 1055 |
| 1056 net::CompletionCallback open_entry_callback = base::Bind( |
| 1057 &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), |
| 1058 base::Passed(keys_context.Pass())); |
| 1059 |
| 1060 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
| 1061 |
| 1062 if (rv != net::ERR_IO_PENDING) |
| 1063 open_entry_callback.Run(rv); |
| 1064 } |
| 1065 |
1033 void ServiceWorkerCache::KeysDidOpenNextEntry( | 1066 void ServiceWorkerCache::KeysDidOpenNextEntry( |
1034 scoped_ptr<KeysContext> keys_context, | 1067 scoped_ptr<KeysContext> keys_context, |
1035 int rv) { | 1068 int rv) { |
1036 if (rv == net::ERR_FAILED) { | 1069 if (rv == net::ERR_FAILED) { |
1037 DCHECK(!keys_context->enumerated_entry); | 1070 DCHECK(!keys_context->enumerated_entry); |
1038 // Enumeration is complete, extract the requests from the entries. | 1071 // Enumeration is complete, extract the requests from the entries. |
1039 Entries::iterator iter = keys_context->entries.begin(); | 1072 Entries::iterator iter = keys_context->entries.begin(); |
1040 KeysProcessNextEntry(keys_context.Pass(), iter); | 1073 KeysProcessNextEntry(keys_context.Pass(), iter); |
1041 return; | 1074 return; |
1042 } | 1075 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 req_headers.insert(std::make_pair(header.name(), header.value())); | 1140 req_headers.insert(std::make_pair(header.name(), header.value())); |
1108 } | 1141 } |
1109 } else { | 1142 } else { |
1110 entry->Doom(); | 1143 entry->Doom(); |
1111 } | 1144 } |
1112 | 1145 |
1113 KeysProcessNextEntry(keys_context.Pass(), iter + 1); | 1146 KeysProcessNextEntry(keys_context.Pass(), iter + 1); |
1114 } | 1147 } |
1115 | 1148 |
1116 void ServiceWorkerCache::CloseImpl(const base::Closure& callback) { | 1149 void ServiceWorkerCache::CloseImpl(const base::Closure& callback) { |
1117 DCHECK(backend_state_ == BACKEND_CLOSED); | 1150 DCHECK(backend_state_ != BACKEND_CLOSED); |
| 1151 |
| 1152 backend_state_ = BACKEND_CLOSED; |
1118 backend_.reset(); | 1153 backend_.reset(); |
1119 callback.Run(); | 1154 callback.Run(); |
1120 } | 1155 } |
1121 | 1156 |
1122 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { | 1157 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { |
1123 DCHECK(!backend_); | 1158 DCHECK(!backend_); |
1124 | 1159 |
1125 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. | 1160 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. |
1126 net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE; | 1161 net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE; |
1127 | 1162 |
(...skipping 29 matching lines...) Expand all Loading... |
1157 int rv) { | 1192 int rv) { |
1158 if (rv != net::OK) { | 1193 if (rv != net::OK) { |
1159 callback.Run(ServiceWorkerCache::ErrorTypeStorage); | 1194 callback.Run(ServiceWorkerCache::ErrorTypeStorage); |
1160 return; | 1195 return; |
1161 } | 1196 } |
1162 | 1197 |
1163 backend_ = backend_ptr->Pass(); | 1198 backend_ = backend_ptr->Pass(); |
1164 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 1199 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
1165 } | 1200 } |
1166 | 1201 |
1167 void ServiceWorkerCache::InitBackend(const base::Closure& callback) { | 1202 void ServiceWorkerCache::InitBackend() { |
1168 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); | 1203 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); |
1169 init_callbacks_.push_back(callback); | |
1170 | 1204 |
1171 // If this isn't the first call to Init then return as the initialization | 1205 if (initializing_) { |
1172 // has already started. | 1206 DCHECK(operation_running_); |
1173 if (init_callbacks_.size() > 1u) | |
1174 return; | 1207 return; |
| 1208 } |
1175 | 1209 |
1176 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, | 1210 DCHECK(!operation_running_); // All ops should wait for backend init. |
1177 weak_ptr_factory_.GetWeakPtr())); | 1211 initializing_ = true; |
| 1212 // Note that this operation pushes to the front of the queue. |
| 1213 pending_operations_.push_front(base::Bind( |
| 1214 &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(), |
| 1215 base::Bind(&ServiceWorkerCache::InitDone, |
| 1216 weak_ptr_factory_.GetWeakPtr()))); |
| 1217 RunOperationIfIdle(); |
1178 } | 1218 } |
1179 | 1219 |
1180 void ServiceWorkerCache::InitDone(ErrorType error) { | 1220 void ServiceWorkerCache::InitDone(ErrorType error) { |
| 1221 initializing_ = false; |
1181 backend_state_ = (error == ErrorTypeOK && backend_ && | 1222 backend_state_ = (error == ErrorTypeOK && backend_ && |
1182 backend_state_ == BACKEND_UNINITIALIZED) | 1223 backend_state_ == BACKEND_UNINITIALIZED) |
1183 ? BACKEND_OPEN | 1224 ? BACKEND_OPEN |
1184 : BACKEND_CLOSED; | 1225 : BACKEND_CLOSED; |
1185 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 1226 CompleteOperationAndRunNext(); |
1186 it != init_callbacks_.end(); ++it) { | |
1187 it->Run(); | |
1188 } | |
1189 init_callbacks_.clear(); | |
1190 } | 1227 } |
1191 | 1228 |
1192 void ServiceWorkerCache::DecPendingOps() { | 1229 void ServiceWorkerCache::CompleteOperationAndRunNext() { |
1193 DCHECK(pending_ops_ > 0); | 1230 DCHECK(!pending_operations_.empty()); |
1194 pending_ops_--; | 1231 operation_running_ = false; |
1195 if (pending_ops_ == 0 && !ops_complete_callback_.is_null()) { | 1232 pending_operations_.pop_front(); |
1196 ops_complete_callback_.Run(); | 1233 RunOperationIfIdle(); |
1197 ops_complete_callback_.Reset(); | 1234 } |
| 1235 |
| 1236 void ServiceWorkerCache::RunOperationIfIdle() { |
| 1237 DCHECK(!operation_running_ || !pending_operations_.empty()); |
| 1238 |
| 1239 if (!operation_running_ && !pending_operations_.empty()) { |
| 1240 operation_running_ = true; |
| 1241 // TODO(jkarlin): Run multiple operations in parallel where allowed (e.g., |
| 1242 // if they're for different keys then they won't interfere). See |
| 1243 // https://crbug.com/451174. |
| 1244 pending_operations_.front().Run(); |
1198 } | 1245 } |
1199 } | 1246 } |
1200 | 1247 |
| 1248 void ServiceWorkerCache::PendingClosure(const base::Closure& callback) { |
| 1249 callback.Run(); |
| 1250 CompleteOperationAndRunNext(); |
| 1251 } |
| 1252 |
1201 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, | 1253 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, |
1202 ErrorType error) { | 1254 ErrorType error) { |
1203 callback.Run(error); | 1255 callback.Run(error); |
1204 DecPendingOps(); | 1256 CompleteOperationAndRunNext(); |
1205 } | 1257 } |
1206 | 1258 |
1207 void ServiceWorkerCache::PendingResponseCallback( | 1259 void ServiceWorkerCache::PendingResponseCallback( |
1208 const ResponseCallback& callback, | 1260 const ResponseCallback& callback, |
1209 ErrorType error, | 1261 ErrorType error, |
1210 scoped_ptr<ServiceWorkerResponse> response, | 1262 scoped_ptr<ServiceWorkerResponse> response, |
1211 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { | 1263 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { |
1212 callback.Run(error, response.Pass(), blob_data_handle.Pass()); | 1264 callback.Run(error, response.Pass(), blob_data_handle.Pass()); |
1213 DecPendingOps(); | 1265 CompleteOperationAndRunNext(); |
1214 } | 1266 } |
1215 | 1267 |
1216 void ServiceWorkerCache::PendingRequestsCallback( | 1268 void ServiceWorkerCache::PendingRequestsCallback( |
1217 const RequestsCallback& callback, | 1269 const RequestsCallback& callback, |
1218 ErrorType error, | 1270 ErrorType error, |
1219 scoped_ptr<Requests> requests) { | 1271 scoped_ptr<Requests> requests) { |
1220 callback.Run(error, requests.Pass()); | 1272 callback.Run(error, requests.Pass()); |
1221 DecPendingOps(); | 1273 CompleteOperationAndRunNext(); |
1222 } | 1274 } |
1223 | 1275 |
1224 } // namespace content | 1276 } // namespace content |
OLD | NEW |