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 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 new ServiceWorkerCache(path, request_context, blob_context)); | 643 new ServiceWorkerCache(path, request_context, blob_context)); |
644 } | 644 } |
645 | 645 |
646 ServiceWorkerCache::~ServiceWorkerCache() { | 646 ServiceWorkerCache::~ServiceWorkerCache() { |
647 } | 647 } |
648 | 648 |
649 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { | 649 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { |
650 return weak_ptr_factory_.GetWeakPtr(); | 650 return weak_ptr_factory_.GetWeakPtr(); |
651 } | 651 } |
652 | 652 |
653 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { | |
654 DCHECK(!backend_); | |
655 | |
656 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. | |
657 net::CacheType cache_type = | |
658 path_.empty() ? net::MEMORY_CACHE : net::APP_CACHE; | |
659 | |
660 scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr()); | |
661 | |
662 // Temporary pointer so that backend_ptr can be Pass()'d in Bind below. | |
663 ScopedBackendPtr* backend = backend_ptr.get(); | |
664 | |
665 net::CompletionCallback create_cache_callback = | |
666 base::Bind(CreateBackendDidCreate, | |
667 callback, | |
668 base::Passed(backend_ptr.Pass()), | |
669 weak_ptr_factory_.GetWeakPtr()); | |
670 | |
671 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore | |
672 // has for disk caches. | |
673 // TODO(jkarlin): Switch to SimpleCache after it supports APP_CACHE and after | |
674 // debugging why the QuickStressBody unittest fails with it. | |
675 int rv = disk_cache::CreateCacheBackend( | |
676 cache_type, | |
677 net::CACHE_BACKEND_SIMPLE, | |
678 path_, | |
679 kMaxCacheBytes, | |
680 false, /* force */ | |
681 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), | |
682 NULL, | |
683 backend, | |
684 create_cache_callback); | |
685 if (rv != net::ERR_IO_PENDING) | |
686 create_cache_callback.Run(rv); | |
687 } | |
688 | |
689 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, | 653 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, |
690 scoped_ptr<ServiceWorkerResponse> response, | 654 scoped_ptr<ServiceWorkerResponse> response, |
691 const ErrorCallback& callback) { | 655 const ErrorCallback& callback) { |
692 DCHECK(backend_); | |
693 | |
694 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
695 | |
696 disk_cache::Entry** entry_ptr = entry.get(); | |
697 | |
698 scoped_ptr<storage::BlobDataHandle> blob_data_handle; | 656 scoped_ptr<storage::BlobDataHandle> blob_data_handle; |
699 | 657 |
700 if (!response->blob_uuid.empty()) { | 658 if (!response->blob_uuid.empty()) { |
701 if (!blob_storage_context_) { | 659 if (!blob_storage_context_) { |
702 callback.Run(ErrorTypeStorage); | 660 callback.Run(ErrorTypeStorage); |
703 return; | 661 return; |
704 } | 662 } |
705 blob_data_handle = | 663 blob_data_handle = |
706 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); | 664 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); |
707 if (!blob_data_handle) { | 665 if (!blob_data_handle) { |
708 callback.Run(ErrorTypeStorage); | 666 callback.Run(ErrorTypeStorage); |
709 return; | 667 return; |
710 } | 668 } |
711 } | 669 } |
712 | 670 |
713 ServiceWorkerFetchRequest* request_ptr = request.get(); | 671 base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl, |
| 672 weak_ptr_factory_.GetWeakPtr(), |
| 673 base::Passed(request.Pass()), |
| 674 base::Passed(response.Pass()), |
| 675 base::Passed(blob_data_handle.Pass()), |
| 676 callback); |
714 | 677 |
715 net::CompletionCallback create_entry_callback = | 678 if (!initialized_) { |
716 base::Bind(PutDidCreateEntry, | 679 Init(continuation); |
717 base::Passed(request.Pass()), | 680 return; |
718 base::Passed(response.Pass()), | 681 } |
719 callback, | |
720 base::Passed(entry.Pass()), | |
721 base::Passed(blob_data_handle.Pass()), | |
722 request_context_); | |
723 | 682 |
724 int rv = backend_->CreateEntry( | 683 continuation.Run(); |
725 request_ptr->url.spec(), entry_ptr, create_entry_callback); | |
726 | |
727 if (rv != net::ERR_IO_PENDING) | |
728 create_entry_callback.Run(rv); | |
729 } | 684 } |
730 | 685 |
731 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 686 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
732 const ResponseCallback& callback) { | 687 const ResponseCallback& callback) { |
733 DCHECK(backend_); | 688 if (!initialized_) { |
| 689 Init(base::Bind(&ServiceWorkerCache::Match, |
| 690 weak_ptr_factory_.GetWeakPtr(), |
| 691 base::Passed(request.Pass()), |
| 692 callback)); |
| 693 return; |
| 694 } |
| 695 if (!backend_) { |
| 696 callback.Run(ErrorTypeStorage, |
| 697 scoped_ptr<ServiceWorkerResponse>(), |
| 698 scoped_ptr<storage::BlobDataHandle>()); |
| 699 return; |
| 700 } |
734 | 701 |
735 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | 702 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
736 | 703 |
737 disk_cache::Entry** entry_ptr = entry.get(); | 704 disk_cache::Entry** entry_ptr = entry.get(); |
738 | 705 |
739 ServiceWorkerFetchRequest* request_ptr = request.get(); | 706 ServiceWorkerFetchRequest* request_ptr = request.get(); |
740 | 707 |
741 net::CompletionCallback open_entry_callback = | 708 net::CompletionCallback open_entry_callback = |
742 base::Bind(MatchDidOpenEntry, | 709 base::Bind(MatchDidOpenEntry, |
743 base::Passed(request.Pass()), | 710 base::Passed(request.Pass()), |
744 callback, | 711 callback, |
745 blob_storage_context_, | 712 blob_storage_context_, |
746 base::Passed(entry.Pass())); | 713 base::Passed(entry.Pass())); |
747 | 714 |
748 int rv = backend_->OpenEntry( | 715 int rv = backend_->OpenEntry( |
749 request_ptr->url.spec(), entry_ptr, open_entry_callback); | 716 request_ptr->url.spec(), entry_ptr, open_entry_callback); |
750 if (rv != net::ERR_IO_PENDING) | 717 if (rv != net::ERR_IO_PENDING) |
751 open_entry_callback.Run(rv); | 718 open_entry_callback.Run(rv); |
752 } | 719 } |
753 | 720 |
754 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, | 721 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, |
755 const ErrorCallback& callback) { | 722 const ErrorCallback& callback) { |
756 DCHECK(backend_); | 723 if (!initialized_) { |
| 724 Init(base::Bind(&ServiceWorkerCache::Delete, |
| 725 weak_ptr_factory_.GetWeakPtr(), |
| 726 base::Passed(request.Pass()), |
| 727 callback)); |
| 728 return; |
| 729 } |
| 730 if (!backend_) { |
| 731 callback.Run(ErrorTypeStorage); |
| 732 return; |
| 733 } |
757 | 734 |
758 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | 735 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
759 | 736 |
760 disk_cache::Entry** entry_ptr = entry.get(); | 737 disk_cache::Entry** entry_ptr = entry.get(); |
761 | 738 |
762 ServiceWorkerFetchRequest* request_ptr = request.get(); | 739 ServiceWorkerFetchRequest* request_ptr = request.get(); |
763 | 740 |
764 net::CompletionCallback open_entry_callback = | 741 net::CompletionCallback open_entry_callback = |
765 base::Bind(DeleteDidOpenEntry, | 742 base::Bind(DeleteDidOpenEntry, |
766 base::Passed(request.Pass()), | 743 base::Passed(request.Pass()), |
767 callback, | 744 callback, |
768 base::Passed(entry.Pass())); | 745 base::Passed(entry.Pass())); |
769 | 746 |
770 int rv = backend_->OpenEntry( | 747 int rv = backend_->OpenEntry( |
771 request_ptr->url.spec(), entry_ptr, open_entry_callback); | 748 request_ptr->url.spec(), entry_ptr, open_entry_callback); |
772 if (rv != net::ERR_IO_PENDING) | 749 if (rv != net::ERR_IO_PENDING) |
773 open_entry_callback.Run(rv); | 750 open_entry_callback.Run(rv); |
774 } | 751 } |
775 | 752 |
776 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | 753 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { |
777 DCHECK(backend_); | 754 if (!initialized_) { |
| 755 Init(base::Bind( |
| 756 &ServiceWorkerCache::Keys, weak_ptr_factory_.GetWeakPtr(), callback)); |
| 757 return; |
| 758 } |
| 759 if (!backend_) { |
| 760 callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
| 761 return; |
| 762 } |
778 | 763 |
779 // 1. Iterate through all of the entries, open them, and add them to a vector. | 764 // 1. Iterate through all of the entries, open them, and add them to a vector. |
780 // 2. For each open entry: | 765 // 2. For each open entry: |
781 // 2.1. Read the headers into a protobuf. | 766 // 2.1. Read the headers into a protobuf. |
782 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | 767 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). |
783 // 2.3. Push the response into a vector of requests to be returned. | 768 // 2.3. Push the response into a vector of requests to be returned. |
784 // 3. Return the vector of requests (keys). | 769 // 3. Return the vector of requests (keys). |
785 | 770 |
786 // The entries have to be loaded into a vector first because enumeration loops | 771 // The entries have to be loaded into a vector first because enumeration loops |
787 // forever if you read data from a cache entry while enumerating. | 772 // forever if you read data from a cache entry while enumerating. |
788 | 773 |
789 scoped_ptr<KeysContext> keys_context( | 774 scoped_ptr<KeysContext> keys_context( |
790 new KeysContext(callback, weak_ptr_factory_.GetWeakPtr())); | 775 new KeysContext(callback, weak_ptr_factory_.GetWeakPtr())); |
791 | 776 |
792 void** backend_iterator = &keys_context->backend_iterator; | 777 void** backend_iterator = &keys_context->backend_iterator; |
793 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | 778 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; |
794 | 779 |
795 net::CompletionCallback open_entry_callback = | 780 net::CompletionCallback open_entry_callback = |
796 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); | 781 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); |
797 | 782 |
798 int rv = backend_->OpenNextEntry( | 783 int rv = backend_->OpenNextEntry( |
799 backend_iterator, enumerated_entry, open_entry_callback); | 784 backend_iterator, enumerated_entry, open_entry_callback); |
800 | 785 |
801 if (rv != net::ERR_IO_PENDING) | 786 if (rv != net::ERR_IO_PENDING) |
802 open_entry_callback.Run(rv); | 787 open_entry_callback.Run(rv); |
803 } | 788 } |
804 | 789 |
805 bool ServiceWorkerCache::HasCreatedBackend() const { | |
806 return backend_; | |
807 } | |
808 | |
809 ServiceWorkerCache::ServiceWorkerCache( | 790 ServiceWorkerCache::ServiceWorkerCache( |
810 const base::FilePath& path, | 791 const base::FilePath& path, |
811 net::URLRequestContext* request_context, | 792 net::URLRequestContext* request_context, |
812 base::WeakPtr<storage::BlobStorageContext> blob_context) | 793 base::WeakPtr<storage::BlobStorageContext> blob_context) |
813 : path_(path), | 794 : path_(path), |
814 request_context_(request_context), | 795 request_context_(request_context), |
815 blob_storage_context_(blob_context), | 796 blob_storage_context_(blob_context), |
| 797 initialized_(false), |
816 weak_ptr_factory_(this) { | 798 weak_ptr_factory_(this) { |
817 } | 799 } |
818 | 800 |
| 801 void ServiceWorkerCache::PutImpl( |
| 802 scoped_ptr<ServiceWorkerFetchRequest> request, |
| 803 scoped_ptr<ServiceWorkerResponse> response, |
| 804 scoped_ptr<storage::BlobDataHandle> blob_data_handle, |
| 805 const ErrorCallback& callback) { |
| 806 if (!backend_) { |
| 807 callback.Run(ErrorTypeStorage); |
| 808 return; |
| 809 } |
| 810 |
| 811 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
| 812 |
| 813 disk_cache::Entry** entry_ptr = entry.get(); |
| 814 |
| 815 ServiceWorkerFetchRequest* request_ptr = request.get(); |
| 816 |
| 817 net::CompletionCallback create_entry_callback = |
| 818 base::Bind(PutDidCreateEntry, |
| 819 base::Passed(request.Pass()), |
| 820 base::Passed(response.Pass()), |
| 821 callback, |
| 822 base::Passed(entry.Pass()), |
| 823 base::Passed(blob_data_handle.Pass()), |
| 824 request_context_); |
| 825 |
| 826 int rv = backend_->CreateEntry( |
| 827 request_ptr->url.spec(), entry_ptr, create_entry_callback); |
| 828 |
| 829 if (rv != net::ERR_IO_PENDING) |
| 830 create_entry_callback.Run(rv); |
| 831 } |
| 832 |
819 // static | 833 // static |
820 void ServiceWorkerCache::KeysDidOpenNextEntry( | 834 void ServiceWorkerCache::KeysDidOpenNextEntry( |
821 scoped_ptr<KeysContext> keys_context, | 835 scoped_ptr<KeysContext> keys_context, |
822 int rv) { | 836 int rv) { |
823 if (rv == net::ERR_FAILED) { | 837 if (rv == net::ERR_FAILED) { |
824 DCHECK(!keys_context->enumerated_entry); | 838 DCHECK(!keys_context->enumerated_entry); |
825 // Enumeration is complete, extract the requests from the entries. | 839 // Enumeration is complete, extract the requests from the entries. |
826 Entries::iterator iter = keys_context->entries.begin(); | 840 Entries::iterator iter = keys_context->entries.begin(); |
827 KeysProcessNextEntry(keys_context.Pass(), iter); | 841 KeysProcessNextEntry(keys_context.Pass(), iter); |
828 return; | 842 return; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 headers->request_headers(i); | 906 headers->request_headers(i); |
893 req_headers.insert(std::make_pair(header.name(), header.value())); | 907 req_headers.insert(std::make_pair(header.name(), header.value())); |
894 } | 908 } |
895 } else { | 909 } else { |
896 entry->Doom(); | 910 entry->Doom(); |
897 } | 911 } |
898 | 912 |
899 KeysProcessNextEntry(keys_context.Pass(), iter + 1); | 913 KeysProcessNextEntry(keys_context.Pass(), iter + 1); |
900 } | 914 } |
901 | 915 |
| 916 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { |
| 917 DCHECK(!backend_); |
| 918 |
| 919 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. |
| 920 net::CacheType cache_type = |
| 921 path_.empty() ? net::MEMORY_CACHE : net::APP_CACHE; |
| 922 |
| 923 scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr()); |
| 924 |
| 925 // Temporary pointer so that backend_ptr can be Pass()'d in Bind below. |
| 926 ScopedBackendPtr* backend = backend_ptr.get(); |
| 927 |
| 928 net::CompletionCallback create_cache_callback = |
| 929 base::Bind(CreateBackendDidCreate, |
| 930 callback, |
| 931 base::Passed(backend_ptr.Pass()), |
| 932 weak_ptr_factory_.GetWeakPtr()); |
| 933 |
| 934 // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore |
| 935 // has for disk caches. |
| 936 int rv = disk_cache::CreateCacheBackend( |
| 937 cache_type, |
| 938 net::CACHE_BACKEND_SIMPLE, |
| 939 path_, |
| 940 kMaxCacheBytes, |
| 941 false, /* force */ |
| 942 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), |
| 943 NULL, |
| 944 backend, |
| 945 create_cache_callback); |
| 946 if (rv != net::ERR_IO_PENDING) |
| 947 create_cache_callback.Run(rv); |
| 948 } |
| 949 |
| 950 void ServiceWorkerCache::Init(const base::Closure& callback) { |
| 951 init_callbacks_.push_back(callback); |
| 952 |
| 953 // If this isn't the first call to Init then return as the initialization |
| 954 // has already started. |
| 955 if (init_callbacks_.size() > 1u) |
| 956 return; |
| 957 |
| 958 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, |
| 959 weak_ptr_factory_.GetWeakPtr())); |
| 960 } |
| 961 |
| 962 void ServiceWorkerCache::InitDone(ErrorType error) { |
| 963 initialized_ = true; |
| 964 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); |
| 965 it != init_callbacks_.end(); |
| 966 ++it) { |
| 967 it->Run(); |
| 968 } |
| 969 init_callbacks_.clear(); |
| 970 } |
| 971 |
902 } // namespace content | 972 } // namespace content |
OLD | NEW |