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