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 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 if (put_context->blob_data_handle) { | 708 if (put_context->blob_data_handle) { |
709 // Grab another handle to the blob for the callback response. | 709 // Grab another handle to the blob for the callback response. |
710 put_context->out_blob_data_handle = | 710 put_context->out_blob_data_handle = |
711 blob_storage_context_->GetBlobDataFromUUID( | 711 blob_storage_context_->GetBlobDataFromUUID( |
712 put_context->response->blob_uuid); | 712 put_context->response->blob_uuid); |
713 } | 713 } |
714 | 714 |
715 base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl, | 715 base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl, |
716 base::Passed(put_context.Pass())); | 716 base::Passed(put_context.Pass())); |
717 | 717 |
718 if (backend_state_ == BackendUninitialized) { | 718 if (!initialized_) { |
719 InitBackend(continuation); | 719 Init(continuation); |
720 return; | 720 return; |
721 } | 721 } |
722 | 722 |
723 continuation.Run(); | 723 continuation.Run(); |
724 } | 724 } |
725 | 725 |
726 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 726 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
727 const ResponseCallback& callback) { | 727 const ResponseCallback& callback) { |
728 IncPendingOps(); | 728 IncPendingOps(); |
729 ResponseCallback pending_callback = | 729 ResponseCallback pending_callback = |
730 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | 730 base::Bind(&ServiceWorkerCache::PendingResponseCallback, |
731 weak_ptr_factory_.GetWeakPtr(), callback); | 731 weak_ptr_factory_.GetWeakPtr(), callback); |
732 | 732 |
733 switch (backend_state_) { | 733 if (!initialized_) { |
734 case BackendUninitialized: | 734 Init(base::Bind(&ServiceWorkerCache::Match, weak_ptr_factory_.GetWeakPtr(), |
735 InitBackend(base::Bind(&ServiceWorkerCache::Match, | 735 base::Passed(request.Pass()), pending_callback)); |
736 weak_ptr_factory_.GetWeakPtr(), | 736 return; |
737 base::Passed(request.Pass()), pending_callback)); | 737 } |
738 return; | 738 if (!backend_) { |
739 case BackendClosed: | 739 pending_callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
740 pending_callback.Run(ErrorTypeStorage, | 740 scoped_ptr<storage::BlobDataHandle>()); |
741 scoped_ptr<ServiceWorkerResponse>(), | 741 return; |
742 scoped_ptr<storage::BlobDataHandle>()); | |
743 return; | |
744 case BackendOpen: | |
745 DCHECK(backend_); | |
746 break; | |
747 } | 742 } |
748 | 743 |
749 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | 744 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
750 | 745 |
751 disk_cache::Entry** entry_ptr = entry.get(); | 746 disk_cache::Entry** entry_ptr = entry.get(); |
752 | 747 |
753 ServiceWorkerFetchRequest* request_ptr = request.get(); | 748 ServiceWorkerFetchRequest* request_ptr = request.get(); |
754 | 749 |
755 net::CompletionCallback open_entry_callback = base::Bind( | 750 net::CompletionCallback open_entry_callback = base::Bind( |
756 MatchDidOpenEntry, base::Passed(request.Pass()), pending_callback, | 751 MatchDidOpenEntry, base::Passed(request.Pass()), pending_callback, |
757 blob_storage_context_, base::Passed(entry.Pass())); | 752 blob_storage_context_, base::Passed(entry.Pass())); |
758 | 753 |
759 int rv = backend_->OpenEntry( | 754 int rv = backend_->OpenEntry( |
760 request_ptr->url.spec(), entry_ptr, open_entry_callback); | 755 request_ptr->url.spec(), entry_ptr, open_entry_callback); |
761 if (rv != net::ERR_IO_PENDING) | 756 if (rv != net::ERR_IO_PENDING) |
762 open_entry_callback.Run(rv); | 757 open_entry_callback.Run(rv); |
763 } | 758 } |
764 | 759 |
765 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, | 760 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, |
766 const ErrorCallback& callback) { | 761 const ErrorCallback& callback) { |
767 IncPendingOps(); | 762 IncPendingOps(); |
768 ErrorCallback pending_callback = | 763 ErrorCallback pending_callback = |
769 base::Bind(&ServiceWorkerCache::PendingErrorCallback, | 764 base::Bind(&ServiceWorkerCache::PendingErrorCallback, |
770 weak_ptr_factory_.GetWeakPtr(), callback); | 765 weak_ptr_factory_.GetWeakPtr(), callback); |
771 | 766 |
772 switch (backend_state_) { | 767 if (!initialized_) { |
773 case BackendUninitialized: | 768 Init(base::Bind(&ServiceWorkerCache::Delete, weak_ptr_factory_.GetWeakPtr(), |
774 InitBackend(base::Bind(&ServiceWorkerCache::Delete, | 769 base::Passed(request.Pass()), pending_callback)); |
775 weak_ptr_factory_.GetWeakPtr(), | 770 return; |
776 base::Passed(request.Pass()), pending_callback)); | 771 } |
777 return; | 772 if (!backend_) { |
778 case BackendClosed: | 773 pending_callback.Run(ErrorTypeStorage); |
779 pending_callback.Run(ErrorTypeStorage); | 774 return; |
780 return; | |
781 case BackendOpen: | |
782 DCHECK(backend_); | |
783 break; | |
784 } | 775 } |
785 | 776 |
786 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | 777 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); |
787 | 778 |
788 disk_cache::Entry** entry_ptr = entry.get(); | 779 disk_cache::Entry** entry_ptr = entry.get(); |
789 | 780 |
790 ServiceWorkerFetchRequest* request_ptr = request.get(); | 781 ServiceWorkerFetchRequest* request_ptr = request.get(); |
791 | 782 |
792 net::CompletionCallback open_entry_callback = base::Bind( | 783 net::CompletionCallback open_entry_callback = base::Bind( |
793 DeleteDidOpenEntry, origin_, base::Passed(request.Pass()), | 784 DeleteDidOpenEntry, origin_, base::Passed(request.Pass()), |
794 pending_callback, base::Passed(entry.Pass()), quota_manager_proxy_); | 785 pending_callback, base::Passed(entry.Pass()), quota_manager_proxy_); |
795 | 786 |
796 int rv = backend_->OpenEntry( | 787 int rv = backend_->OpenEntry( |
797 request_ptr->url.spec(), entry_ptr, open_entry_callback); | 788 request_ptr->url.spec(), entry_ptr, open_entry_callback); |
798 if (rv != net::ERR_IO_PENDING) | 789 if (rv != net::ERR_IO_PENDING) |
799 open_entry_callback.Run(rv); | 790 open_entry_callback.Run(rv); |
800 } | 791 } |
801 | 792 |
802 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | 793 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { |
803 IncPendingOps(); | 794 IncPendingOps(); |
804 RequestsCallback pending_callback = | 795 RequestsCallback pending_callback = |
805 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, | 796 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, |
806 weak_ptr_factory_.GetWeakPtr(), callback); | 797 weak_ptr_factory_.GetWeakPtr(), callback); |
807 | 798 if (!initialized_) { |
808 switch (backend_state_) { | 799 Init(base::Bind(&ServiceWorkerCache::Keys, weak_ptr_factory_.GetWeakPtr(), |
809 case BackendUninitialized: | 800 pending_callback)); |
810 InitBackend(base::Bind(&ServiceWorkerCache::Keys, | 801 return; |
811 weak_ptr_factory_.GetWeakPtr(), pending_callback)); | 802 } |
812 return; | 803 if (!backend_) { |
813 case BackendClosed: | 804 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
814 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); | 805 return; |
815 return; | |
816 case BackendOpen: | |
817 DCHECK(backend_); | |
818 break; | |
819 } | 806 } |
820 | 807 |
821 // 1. Iterate through all of the entries, open them, and add them to a vector. | 808 // 1. Iterate through all of the entries, open them, and add them to a vector. |
822 // 2. For each open entry: | 809 // 2. For each open entry: |
823 // 2.1. Read the headers into a protobuf. | 810 // 2.1. Read the headers into a protobuf. |
824 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | 811 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). |
825 // 2.3. Push the response into a vector of requests to be returned. | 812 // 2.3. Push the response into a vector of requests to be returned. |
826 // 3. Return the vector of requests (keys). | 813 // 3. Return the vector of requests (keys). |
827 | 814 |
828 // The entries have to be loaded into a vector first because enumeration loops | 815 // The entries have to be loaded into a vector first because enumeration loops |
829 // forever if you read data from a cache entry while enumerating. | 816 // forever if you read data from a cache entry while enumerating. |
830 | 817 |
831 scoped_ptr<KeysContext> keys_context( | 818 scoped_ptr<KeysContext> keys_context( |
832 new KeysContext(pending_callback, weak_ptr_factory_.GetWeakPtr())); | 819 new KeysContext(pending_callback, weak_ptr_factory_.GetWeakPtr())); |
833 | 820 |
834 keys_context->backend_iterator = backend_->CreateIterator(); | 821 keys_context->backend_iterator = backend_->CreateIterator(); |
835 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; | 822 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; |
836 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | 823 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; |
837 | 824 |
838 net::CompletionCallback open_entry_callback = | 825 net::CompletionCallback open_entry_callback = |
839 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); | 826 base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); |
840 | 827 |
841 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); | 828 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); |
842 | 829 |
843 if (rv != net::ERR_IO_PENDING) | 830 if (rv != net::ERR_IO_PENDING) |
844 open_entry_callback.Run(rv); | 831 open_entry_callback.Run(rv); |
845 } | 832 } |
846 | 833 |
847 void ServiceWorkerCache::Close(const base::Closure& callback) { | 834 void ServiceWorkerCache::Close(const base::Closure& callback) { |
848 DCHECK(backend_state_ != BackendClosed) | 835 DCHECK(!initialized_ || backend_) |
849 << "Don't call ServiceWorkerCache::Close() twice."; | 836 << "Don't call ServiceWorkerCache::Close() twice."; |
850 | 837 |
851 backend_state_ = BackendClosed; | |
852 | |
853 if (pending_ops_ > 0) { | 838 if (pending_ops_ > 0) { |
854 DCHECK(ops_complete_callback_.is_null()); | 839 DCHECK(ops_complete_callback_.is_null()); |
| 840 initialized_ = true; // So that future operations halt. |
855 ops_complete_callback_ = base::Bind( | 841 ops_complete_callback_ = base::Bind( |
856 &ServiceWorkerCache::Close, weak_ptr_factory_.GetWeakPtr(), callback); | 842 &ServiceWorkerCache::Close, weak_ptr_factory_.GetWeakPtr(), callback); |
857 return; | 843 return; |
858 } | 844 } |
859 | 845 |
| 846 initialized_ = true; |
860 backend_.reset(); | 847 backend_.reset(); |
861 callback.Run(); | 848 callback.Run(); |
862 } | 849 } |
863 | 850 |
864 int64 ServiceWorkerCache::MemoryBackedSize() const { | 851 int64 ServiceWorkerCache::MemoryBackedSize() const { |
865 if (backend_state_ != BackendOpen || !memory_only_) | 852 if (!backend_ || !memory_only_) |
866 return 0; | 853 return 0; |
867 | 854 |
868 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = | 855 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = |
869 backend_->CreateIterator(); | 856 backend_->CreateIterator(); |
870 disk_cache::Entry* entry = nullptr; | 857 disk_cache::Entry* entry = nullptr; |
871 | 858 |
872 int64 sum = 0; | 859 int64 sum = 0; |
873 | 860 |
874 std::vector<disk_cache::Entry*> entries; | 861 std::vector<disk_cache::Entry*> entries; |
875 int rv = net::OK; | 862 int rv = net::OK; |
(...skipping 17 matching lines...) Expand all Loading... |
893 const GURL& origin, | 880 const GURL& origin, |
894 const base::FilePath& path, | 881 const base::FilePath& path, |
895 net::URLRequestContext* request_context, | 882 net::URLRequestContext* request_context, |
896 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 883 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
897 base::WeakPtr<storage::BlobStorageContext> blob_context) | 884 base::WeakPtr<storage::BlobStorageContext> blob_context) |
898 : origin_(origin), | 885 : origin_(origin), |
899 path_(path), | 886 path_(path), |
900 request_context_(request_context), | 887 request_context_(request_context), |
901 quota_manager_proxy_(quota_manager_proxy), | 888 quota_manager_proxy_(quota_manager_proxy), |
902 blob_storage_context_(blob_context), | 889 blob_storage_context_(blob_context), |
903 backend_state_(BackendUninitialized), | 890 initialized_(false), |
904 memory_only_(path.empty()), | 891 memory_only_(path.empty()), |
905 pending_ops_(0), | 892 pending_ops_(0), |
906 weak_ptr_factory_(this) { | 893 weak_ptr_factory_(this) { |
907 } | 894 } |
908 | 895 |
909 // static | 896 // static |
910 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { | 897 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { |
911 if (!put_context->cache || | 898 if (!put_context->cache || !put_context->cache->backend_) { |
912 put_context->cache->backend_state_ != BackendOpen) { | |
913 put_context->callback.Run(ErrorTypeStorage, | 899 put_context->callback.Run(ErrorTypeStorage, |
914 scoped_ptr<ServiceWorkerResponse>(), | 900 scoped_ptr<ServiceWorkerResponse>(), |
915 scoped_ptr<storage::BlobDataHandle>()); | 901 scoped_ptr<storage::BlobDataHandle>()); |
916 return; | 902 return; |
917 } | 903 } |
918 | 904 |
919 scoped_ptr<ServiceWorkerFetchRequest> request_copy( | 905 scoped_ptr<ServiceWorkerFetchRequest> request_copy( |
920 new ServiceWorkerFetchRequest(*put_context->request)); | 906 new ServiceWorkerFetchRequest(*put_context->request)); |
921 ServiceWorkerCache* cache_ptr = put_context->cache.get(); | 907 ServiceWorkerCache* cache_ptr = put_context->cache.get(); |
922 | 908 |
923 cache_ptr->Delete(request_copy.Pass(), | 909 cache_ptr->Delete(request_copy.Pass(), |
924 base::Bind(PutDidDelete, base::Passed(put_context.Pass()))); | 910 base::Bind(PutDidDelete, base::Passed(put_context.Pass()))); |
925 } | 911 } |
926 | 912 |
927 // static | 913 // static |
928 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, | 914 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, |
929 ErrorType delete_error) { | 915 ErrorType delete_error) { |
930 if (!put_context->cache || | 916 if (!put_context->cache || !put_context->cache->backend_) { |
931 put_context->cache->backend_state_ != BackendOpen) { | |
932 put_context->callback.Run(ErrorTypeStorage, | 917 put_context->callback.Run(ErrorTypeStorage, |
933 scoped_ptr<ServiceWorkerResponse>(), | 918 scoped_ptr<ServiceWorkerResponse>(), |
934 scoped_ptr<storage::BlobDataHandle>()); | 919 scoped_ptr<storage::BlobDataHandle>()); |
935 return; | 920 return; |
936 } | 921 } |
937 | 922 |
938 disk_cache::Entry** entry_ptr = &put_context->cache_entry; | 923 disk_cache::Entry** entry_ptr = &put_context->cache_entry; |
939 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); | 924 ServiceWorkerFetchRequest* request_ptr = put_context->request.get(); |
940 disk_cache::Backend* backend_ptr = put_context->cache->backend_.get(); | 925 disk_cache::Backend* backend_ptr = put_context->cache->backend_.get(); |
941 | 926 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 return; | 1094 return; |
1110 } | 1095 } |
1111 | 1096 |
1112 base::WeakPtr<ServiceWorkerCache> cache = keys_context->cache; | 1097 base::WeakPtr<ServiceWorkerCache> cache = keys_context->cache; |
1113 if (rv < 0 || !cache) { | 1098 if (rv < 0 || !cache) { |
1114 keys_context->original_callback.Run(ErrorTypeStorage, | 1099 keys_context->original_callback.Run(ErrorTypeStorage, |
1115 scoped_ptr<Requests>()); | 1100 scoped_ptr<Requests>()); |
1116 return; | 1101 return; |
1117 } | 1102 } |
1118 | 1103 |
1119 if (cache->backend_state_ != BackendOpen) { | 1104 if (!cache->backend_) { |
1120 keys_context->original_callback.Run(ErrorTypeNotFound, | 1105 keys_context->original_callback.Run(ErrorTypeNotFound, |
1121 scoped_ptr<Requests>()); | 1106 scoped_ptr<Requests>()); |
1122 return; | 1107 return; |
1123 } | 1108 } |
1124 | 1109 |
1125 // Store the entry. | 1110 // Store the entry. |
1126 keys_context->entries.push_back(keys_context->enumerated_entry); | 1111 keys_context->entries.push_back(keys_context->enumerated_entry); |
1127 keys_context->enumerated_entry = NULL; | 1112 keys_context->enumerated_entry = NULL; |
1128 | 1113 |
1129 // Enumerate the next entry. | 1114 // Enumerate the next entry. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 kMaxCacheBytes, | 1194 kMaxCacheBytes, |
1210 false, /* force */ | 1195 false, /* force */ |
1211 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), | 1196 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(), |
1212 NULL, | 1197 NULL, |
1213 backend, | 1198 backend, |
1214 create_cache_callback); | 1199 create_cache_callback); |
1215 if (rv != net::ERR_IO_PENDING) | 1200 if (rv != net::ERR_IO_PENDING) |
1216 create_cache_callback.Run(rv); | 1201 create_cache_callback.Run(rv); |
1217 } | 1202 } |
1218 | 1203 |
1219 void ServiceWorkerCache::InitBackend(const base::Closure& callback) { | 1204 void ServiceWorkerCache::Init(const base::Closure& callback) { |
1220 DCHECK(backend_state_ == BackendUninitialized); | 1205 DCHECK(!initialized_); |
1221 init_callbacks_.push_back(callback); | 1206 init_callbacks_.push_back(callback); |
1222 | 1207 |
1223 // If this isn't the first call to Init then return as the initialization | 1208 // If this isn't the first call to Init then return as the initialization |
1224 // has already started. | 1209 // has already started. |
1225 if (init_callbacks_.size() > 1u) | 1210 if (init_callbacks_.size() > 1u) |
1226 return; | 1211 return; |
1227 | 1212 |
1228 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, | 1213 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, |
1229 weak_ptr_factory_.GetWeakPtr())); | 1214 weak_ptr_factory_.GetWeakPtr())); |
1230 } | 1215 } |
1231 | 1216 |
1232 void ServiceWorkerCache::InitDone(ErrorType error) { | 1217 void ServiceWorkerCache::InitDone(ErrorType error) { |
1233 backend_state_ = | 1218 initialized_ = true; |
1234 (error == ErrorTypeOK && backend_) ? BackendOpen : BackendClosed; | |
1235 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 1219 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); |
1236 it != init_callbacks_.end(); | 1220 it != init_callbacks_.end(); |
1237 ++it) { | 1221 ++it) { |
1238 it->Run(); | 1222 it->Run(); |
1239 } | 1223 } |
1240 init_callbacks_.clear(); | 1224 init_callbacks_.clear(); |
1241 } | 1225 } |
1242 | 1226 |
1243 void ServiceWorkerCache::DecPendingOps() { | 1227 void ServiceWorkerCache::DecPendingOps() { |
1244 DCHECK(pending_ops_ > 0); | 1228 DCHECK(pending_ops_ > 0); |
(...skipping 21 matching lines...) Expand all Loading... |
1266 | 1250 |
1267 void ServiceWorkerCache::PendingRequestsCallback( | 1251 void ServiceWorkerCache::PendingRequestsCallback( |
1268 const RequestsCallback& callback, | 1252 const RequestsCallback& callback, |
1269 ErrorType error, | 1253 ErrorType error, |
1270 scoped_ptr<Requests> requests) { | 1254 scoped_ptr<Requests> requests) { |
1271 callback.Run(error, requests.Pass()); | 1255 callback.Run(error, requests.Pass()); |
1272 DecPendingOps(); | 1256 DecPendingOps(); |
1273 } | 1257 } |
1274 | 1258 |
1275 } // namespace content | 1259 } // namespace content |
OLD | NEW |