| Index: content/browser/service_worker/service_worker_cache.cc
|
| diff --git a/content/browser/service_worker/service_worker_cache.cc b/content/browser/service_worker/service_worker_cache.cc
|
| deleted file mode 100644
|
| index 896d568172102c9eacc7cb52e6c74a79698d725c..0000000000000000000000000000000000000000
|
| --- a/content/browser/service_worker/service_worker_cache.cc
|
| +++ /dev/null
|
| @@ -1,1274 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/browser/service_worker/service_worker_cache.h"
|
| -
|
| -#include <string>
|
| -
|
| -#include "base/files/file_path.h"
|
| -#include "base/guid.h"
|
| -#include "base/message_loop/message_loop_proxy.h"
|
| -#include "base/metrics/histogram_macros.h"
|
| -#include "base/profiler/scoped_tracker.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "content/browser/service_worker/service_worker_cache.pb.h"
|
| -#include "content/browser/service_worker/service_worker_cache_scheduler.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/common/referrer.h"
|
| -#include "net/base/io_buffer.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/disk_cache/disk_cache.h"
|
| -#include "net/url_request/url_request_context.h"
|
| -#include "storage/browser/blob/blob_data_builder.h"
|
| -#include "storage/browser/blob/blob_data_handle.h"
|
| -#include "storage/browser/blob/blob_storage_context.h"
|
| -#include "storage/browser/blob/blob_url_request_job_factory.h"
|
| -#include "storage/browser/quota/quota_manager_proxy.h"
|
| -#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
|
| -
|
| -namespace content {
|
| -
|
| -namespace {
|
| -
|
| -typedef base::Callback<void(bool)> BoolCallback;
|
| -typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
|
| - EntryBoolCallback;
|
| -typedef base::Callback<void(scoped_ptr<ServiceWorkerCacheMetadata>)>
|
| - MetadataCallback;
|
| -
|
| -enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
|
| -
|
| -// The maximum size of an individual cache. Ultimately cache size is controlled
|
| -// per-origin.
|
| -const int kMaxCacheBytes = 512 * 1024 * 1024;
|
| -
|
| -// Buffer size for cache and blob reading/writing.
|
| -const int kBufferSize = 1024 * 512;
|
| -
|
| -void NotReachedCompletionCallback(int rv) {
|
| - NOTREACHED();
|
| -}
|
| -
|
| -blink::WebServiceWorkerResponseType ProtoResponseTypeToWebResponseType(
|
| - ServiceWorkerCacheResponse::ResponseType response_type) {
|
| - switch (response_type) {
|
| - case ServiceWorkerCacheResponse::BASIC_TYPE:
|
| - return blink::WebServiceWorkerResponseTypeBasic;
|
| - case ServiceWorkerCacheResponse::CORS_TYPE:
|
| - return blink::WebServiceWorkerResponseTypeCORS;
|
| - case ServiceWorkerCacheResponse::DEFAULT_TYPE:
|
| - return blink::WebServiceWorkerResponseTypeDefault;
|
| - case ServiceWorkerCacheResponse::ERROR_TYPE:
|
| - return blink::WebServiceWorkerResponseTypeError;
|
| - case ServiceWorkerCacheResponse::OPAQUE_TYPE:
|
| - return blink::WebServiceWorkerResponseTypeOpaque;
|
| - }
|
| - NOTREACHED();
|
| - return blink::WebServiceWorkerResponseTypeOpaque;
|
| -}
|
| -
|
| -ServiceWorkerCacheResponse::ResponseType WebResponseTypeToProtoResponseType(
|
| - blink::WebServiceWorkerResponseType response_type) {
|
| - switch (response_type) {
|
| - case blink::WebServiceWorkerResponseTypeBasic:
|
| - return ServiceWorkerCacheResponse::BASIC_TYPE;
|
| - case blink::WebServiceWorkerResponseTypeCORS:
|
| - return ServiceWorkerCacheResponse::CORS_TYPE;
|
| - case blink::WebServiceWorkerResponseTypeDefault:
|
| - return ServiceWorkerCacheResponse::DEFAULT_TYPE;
|
| - case blink::WebServiceWorkerResponseTypeError:
|
| - return ServiceWorkerCacheResponse::ERROR_TYPE;
|
| - case blink::WebServiceWorkerResponseTypeOpaque:
|
| - return ServiceWorkerCacheResponse::OPAQUE_TYPE;
|
| - }
|
| - NOTREACHED();
|
| - return ServiceWorkerCacheResponse::OPAQUE_TYPE;
|
| -}
|
| -
|
| -// Copy headers out of a cache entry and into a protobuf. The callback is
|
| -// guaranteed to be run.
|
| -void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback);
|
| -void ReadMetadataDidReadMetadata(
|
| - disk_cache::Entry* entry,
|
| - const MetadataCallback& callback,
|
| - const scoped_refptr<net::IOBufferWithSize>& buffer,
|
| - int rv);
|
| -
|
| -
|
| -bool VaryMatches(const ServiceWorkerHeaderMap& request,
|
| - const ServiceWorkerHeaderMap& cached_request,
|
| - const ServiceWorkerHeaderMap& response) {
|
| - ServiceWorkerHeaderMap::const_iterator vary_iter = response.find("vary");
|
| - if (vary_iter == response.end())
|
| - return true;
|
| -
|
| - std::vector<std::string> vary_keys;
|
| - Tokenize(vary_iter->second, ",", &vary_keys);
|
| - for (std::vector<std::string>::const_iterator it = vary_keys.begin();
|
| - it != vary_keys.end();
|
| - ++it) {
|
| - std::string trimmed;
|
| - base::TrimWhitespaceASCII(*it, base::TRIM_ALL, &trimmed);
|
| - if (trimmed == "*")
|
| - return false;
|
| -
|
| - ServiceWorkerHeaderMap::const_iterator request_iter = request.find(trimmed);
|
| - ServiceWorkerHeaderMap::const_iterator cached_request_iter =
|
| - cached_request.find(trimmed);
|
| -
|
| - // If the header exists in one but not the other, no match.
|
| - if ((request_iter == request.end()) !=
|
| - (cached_request_iter == cached_request.end()))
|
| - return false;
|
| -
|
| - // If the header exists in one, it exists in both. Verify that the values
|
| - // are equal.
|
| - if (request_iter != request.end() &&
|
| - request_iter->second != cached_request_iter->second)
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -
|
| -void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
|
| - DCHECK(entry);
|
| -
|
| - scoped_refptr<net::IOBufferWithSize> buffer(
|
| - new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
|
| -
|
| - net::CompletionCallback read_header_callback =
|
| - base::Bind(ReadMetadataDidReadMetadata, entry, callback, buffer);
|
| -
|
| - int read_rv = entry->ReadData(
|
| - INDEX_HEADERS, 0, buffer.get(), buffer->size(),
|
| - tracked_objects::ScopedTracker::TrackCallback(
|
| - FROM_HERE_WITH_EXPLICIT_FUNCTION("422516 ReadMetadata"),
|
| - read_header_callback));
|
| -
|
| - if (read_rv != net::ERR_IO_PENDING)
|
| - read_header_callback.Run(read_rv);
|
| -}
|
| -
|
| -void ReadMetadataDidReadMetadata(
|
| - disk_cache::Entry* entry,
|
| - const MetadataCallback& callback,
|
| - const scoped_refptr<net::IOBufferWithSize>& buffer,
|
| - int rv) {
|
| - if (rv != buffer->size()) {
|
| - callback.Run(scoped_ptr<ServiceWorkerCacheMetadata>());
|
| - return;
|
| - }
|
| -
|
| - scoped_ptr<ServiceWorkerCacheMetadata> metadata(
|
| - new ServiceWorkerCacheMetadata());
|
| -
|
| - if (!metadata->ParseFromArray(buffer->data(), buffer->size())) {
|
| - callback.Run(scoped_ptr<ServiceWorkerCacheMetadata>());
|
| - return;
|
| - }
|
| -
|
| - callback.Run(metadata.Pass());
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// Streams data from a blob and writes it to a given disk_cache::Entry.
|
| -class ServiceWorkerCache::BlobReader : public net::URLRequest::Delegate {
|
| - public:
|
| - typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
|
| - EntryAndBoolCallback;
|
| -
|
| - BlobReader()
|
| - : cache_entry_offset_(0),
|
| - buffer_(new net::IOBufferWithSize(kBufferSize)),
|
| - weak_ptr_factory_(this) {}
|
| -
|
| - // |entry| is passed to the callback once complete.
|
| - void StreamBlobToCache(disk_cache::ScopedEntryPtr entry,
|
| - net::URLRequestContext* request_context,
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle,
|
| - const EntryAndBoolCallback& callback) {
|
| - DCHECK(entry);
|
| - entry_ = entry.Pass();
|
| - callback_ = callback;
|
| - blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
|
| - blob_data_handle.Pass(), request_context, this);
|
| - blob_request_->Start();
|
| - }
|
| -
|
| - // net::URLRequest::Delegate overrides for reading blobs.
|
| - void OnReceivedRedirect(net::URLRequest* request,
|
| - const net::RedirectInfo& redirect_info,
|
| - bool* defer_redirect) override {
|
| - NOTREACHED();
|
| - }
|
| - void OnAuthRequired(net::URLRequest* request,
|
| - net::AuthChallengeInfo* auth_info) override {
|
| - NOTREACHED();
|
| - }
|
| - void OnCertificateRequested(
|
| - net::URLRequest* request,
|
| - net::SSLCertRequestInfo* cert_request_info) override {
|
| - NOTREACHED();
|
| - }
|
| - void OnSSLCertificateError(net::URLRequest* request,
|
| - const net::SSLInfo& ssl_info,
|
| - bool fatal) override {
|
| - NOTREACHED();
|
| - }
|
| - void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override {
|
| - NOTREACHED();
|
| - }
|
| -
|
| - void OnResponseStarted(net::URLRequest* request) override {
|
| - // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
|
| - tracked_objects::ScopedTracker tracking_profile(
|
| - FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| - "423948 ServiceWorkerCache::BlobReader::OnResponseStarted"));
|
| -
|
| - if (!request->status().is_success()) {
|
| - callback_.Run(entry_.Pass(), false);
|
| - return;
|
| - }
|
| - ReadFromBlob();
|
| - }
|
| -
|
| - virtual void ReadFromBlob() {
|
| - int bytes_read = 0;
|
| - bool done =
|
| - blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read);
|
| - if (done)
|
| - OnReadCompleted(blob_request_.get(), bytes_read);
|
| - }
|
| -
|
| - void OnReadCompleted(net::URLRequest* request, int bytes_read) override {
|
| - // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
|
| - tracked_objects::ScopedTracker tracking_profile(
|
| - FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| - "423948 ServiceWorkerCache::BlobReader::OnReadCompleted"));
|
| -
|
| - if (!request->status().is_success()) {
|
| - callback_.Run(entry_.Pass(), false);
|
| - return;
|
| - }
|
| -
|
| - if (bytes_read == 0) {
|
| - callback_.Run(entry_.Pass(), true);
|
| - return;
|
| - }
|
| -
|
| - net::CompletionCallback cache_write_callback =
|
| - base::Bind(&BlobReader::DidWriteDataToEntry,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - bytes_read);
|
| -
|
| - int rv = entry_->WriteData(INDEX_RESPONSE_BODY,
|
| - cache_entry_offset_,
|
| - buffer_.get(),
|
| - bytes_read,
|
| - cache_write_callback,
|
| - true /* truncate */);
|
| - if (rv != net::ERR_IO_PENDING)
|
| - cache_write_callback.Run(rv);
|
| - }
|
| -
|
| - void DidWriteDataToEntry(int expected_bytes, int rv) {
|
| - if (rv != expected_bytes) {
|
| - callback_.Run(entry_.Pass(), false);
|
| - return;
|
| - }
|
| -
|
| - cache_entry_offset_ += rv;
|
| - ReadFromBlob();
|
| - }
|
| -
|
| - private:
|
| - int cache_entry_offset_;
|
| - disk_cache::ScopedEntryPtr entry_;
|
| - scoped_ptr<net::URLRequest> blob_request_;
|
| - EntryAndBoolCallback callback_;
|
| - scoped_refptr<net::IOBufferWithSize> buffer_;
|
| - base::WeakPtrFactory<BlobReader> weak_ptr_factory_;
|
| -};
|
| -
|
| -// The state needed to pass between ServiceWorkerCache::Keys callbacks.
|
| -struct ServiceWorkerCache::KeysContext {
|
| - KeysContext(const ServiceWorkerCache::RequestsCallback& callback)
|
| - : original_callback(callback),
|
| - out_keys(new ServiceWorkerCache::Requests()),
|
| - enumerated_entry(NULL) {}
|
| -
|
| - ~KeysContext() {
|
| - for (size_t i = 0, max = entries.size(); i < max; ++i)
|
| - entries[i]->Close();
|
| - if (enumerated_entry)
|
| - enumerated_entry->Close();
|
| - }
|
| -
|
| - // The callback passed to the Keys() function.
|
| - ServiceWorkerCache::RequestsCallback original_callback;
|
| -
|
| - // The vector of open entries in the backend.
|
| - Entries entries;
|
| -
|
| - // The output of the Keys function.
|
| - scoped_ptr<ServiceWorkerCache::Requests> out_keys;
|
| -
|
| - // Used for enumerating cache entries.
|
| - scoped_ptr<disk_cache::Backend::Iterator> backend_iterator;
|
| - disk_cache::Entry* enumerated_entry;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(KeysContext);
|
| -};
|
| -
|
| -struct ServiceWorkerCache::MatchContext {
|
| - MatchContext(scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ServiceWorkerCache::ResponseCallback& callback,
|
| - base::WeakPtr<storage::BlobStorageContext> blob_storage_context)
|
| - : request(request.Pass()),
|
| - original_callback(callback),
|
| - blob_storage_context(blob_storage_context),
|
| - entry(nullptr),
|
| - total_bytes_read(0) {}
|
| -
|
| - ~MatchContext() {
|
| - if (entry)
|
| - entry->Close();
|
| - }
|
| -
|
| - // Input
|
| - scoped_ptr<ServiceWorkerFetchRequest> request;
|
| - ServiceWorkerCache::ResponseCallback original_callback;
|
| - base::WeakPtr<storage::BlobStorageContext> blob_storage_context;
|
| - disk_cache::Entry* entry;
|
| -
|
| - // Output
|
| - scoped_ptr<ServiceWorkerResponse> response;
|
| - scoped_ptr<storage::BlobDataBuilder> blob_data;
|
| -
|
| - // For reading the cache entry data into a blob.
|
| - scoped_refptr<net::IOBufferWithSize> response_body_buffer;
|
| - size_t total_bytes_read;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MatchContext);
|
| -};
|
| -
|
| -// The state needed to pass between ServiceWorkerCache::Put callbacks.
|
| -struct ServiceWorkerCache::PutContext {
|
| - PutContext(
|
| - const GURL& origin,
|
| - scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - scoped_ptr<ServiceWorkerResponse> response,
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle,
|
| - const ServiceWorkerCache::ResponseCallback& callback,
|
| - net::URLRequestContext* request_context,
|
| - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy)
|
| - : origin(origin),
|
| - request(request.Pass()),
|
| - response(response.Pass()),
|
| - blob_data_handle(blob_data_handle.Pass()),
|
| - callback(callback),
|
| - request_context(request_context),
|
| - quota_manager_proxy(quota_manager_proxy),
|
| - cache_entry(NULL) {}
|
| - ~PutContext() {
|
| - if (cache_entry)
|
| - cache_entry->Close();
|
| - }
|
| -
|
| - // Input parameters to the Put function.
|
| - GURL origin;
|
| - scoped_ptr<ServiceWorkerFetchRequest> request;
|
| - scoped_ptr<ServiceWorkerResponse> response;
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle;
|
| - ServiceWorkerCache::ResponseCallback callback;
|
| - net::URLRequestContext* request_context;
|
| - scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy;
|
| -
|
| - // This isn't a scoped_ptr because the disk_cache needs an Entry** as input to
|
| - // CreateEntry.
|
| - disk_cache::Entry* cache_entry;
|
| -
|
| - // The BlobDataHandle for the output ServiceWorkerResponse.
|
| - scoped_ptr<storage::BlobDataHandle> out_blob_data_handle;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(PutContext);
|
| -};
|
| -
|
| -// static
|
| -scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
|
| - const GURL& origin,
|
| - net::URLRequestContext* request_context,
|
| - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
|
| - base::WeakPtr<storage::BlobStorageContext> blob_context) {
|
| - return make_scoped_refptr(new ServiceWorkerCache(origin,
|
| - base::FilePath(),
|
| - request_context,
|
| - quota_manager_proxy,
|
| - blob_context));
|
| -}
|
| -
|
| -// static
|
| -scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
|
| - const GURL& origin,
|
| - const base::FilePath& path,
|
| - net::URLRequestContext* request_context,
|
| - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
|
| - base::WeakPtr<storage::BlobStorageContext> blob_context) {
|
| - return make_scoped_refptr(new ServiceWorkerCache(
|
| - origin, path, request_context, quota_manager_proxy, blob_context));
|
| -}
|
| -
|
| -ServiceWorkerCache::~ServiceWorkerCache() {
|
| -}
|
| -
|
| -base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
|
| - return weak_ptr_factory_.GetWeakPtr();
|
| -}
|
| -
|
| -void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - scoped_ptr<ServiceWorkerResponse> response,
|
| - const ResponseCallback& callback) {
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle;
|
| -
|
| - if (!response->blob_uuid.empty()) {
|
| - if (!blob_storage_context_) {
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| - blob_data_handle =
|
| - blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
|
| - if (!blob_data_handle) {
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| - }
|
| -
|
| - ResponseCallback pending_callback =
|
| - base::Bind(&ServiceWorkerCache::PendingResponseCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| -
|
| - scoped_ptr<PutContext> put_context(new PutContext(
|
| - origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(),
|
| - pending_callback, request_context_, quota_manager_proxy_));
|
| -
|
| - if (put_context->blob_data_handle) {
|
| - // Grab another handle to the blob for the callback response.
|
| - put_context->out_blob_data_handle =
|
| - blob_storage_context_->GetBlobDataFromUUID(
|
| - put_context->response->blob_uuid);
|
| - }
|
| -
|
| - if (backend_state_ == BACKEND_UNINITIALIZED)
|
| - InitBackend();
|
| -
|
| - scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::PutImpl,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(put_context.Pass())));
|
| -}
|
| -
|
| -void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ResponseCallback& callback) {
|
| - switch (backend_state_) {
|
| - case BACKEND_UNINITIALIZED:
|
| - InitBackend();
|
| - break;
|
| - case BACKEND_CLOSED:
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - case BACKEND_OPEN:
|
| - DCHECK(backend_);
|
| - break;
|
| - }
|
| -
|
| - ResponseCallback pending_callback =
|
| - base::Bind(&ServiceWorkerCache::PendingResponseCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| - scheduler_->ScheduleOperation(
|
| - base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(request.Pass()), pending_callback));
|
| -}
|
| -
|
| -void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ErrorCallback& callback) {
|
| - switch (backend_state_) {
|
| - case BACKEND_UNINITIALIZED:
|
| - InitBackend();
|
| - break;
|
| - case BACKEND_CLOSED:
|
| - callback.Run(ERROR_TYPE_STORAGE);
|
| - return;
|
| - case BACKEND_OPEN:
|
| - DCHECK(backend_);
|
| - break;
|
| - }
|
| - ErrorCallback pending_callback =
|
| - base::Bind(&ServiceWorkerCache::PendingErrorCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| - scheduler_->ScheduleOperation(base::Bind(
|
| - &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(request.Pass()), pending_callback));
|
| -}
|
| -
|
| -void ServiceWorkerCache::Keys(const RequestsCallback& callback) {
|
| - switch (backend_state_) {
|
| - case BACKEND_UNINITIALIZED:
|
| - InitBackend();
|
| - break;
|
| - case BACKEND_CLOSED:
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<Requests>());
|
| - return;
|
| - case BACKEND_OPEN:
|
| - DCHECK(backend_);
|
| - break;
|
| - }
|
| -
|
| - RequestsCallback pending_callback =
|
| - base::Bind(&ServiceWorkerCache::PendingRequestsCallback,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| - scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::KeysImpl,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - pending_callback));
|
| -}
|
| -
|
| -void ServiceWorkerCache::Close(const base::Closure& callback) {
|
| - DCHECK(backend_state_ != BACKEND_CLOSED)
|
| - << "Don't call ServiceWorkerCache::Close() twice.";
|
| -
|
| - base::Closure pending_callback =
|
| - base::Bind(&ServiceWorkerCache::PendingClosure,
|
| - weak_ptr_factory_.GetWeakPtr(), callback);
|
| -
|
| - scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::CloseImpl,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - pending_callback));
|
| -}
|
| -
|
| -int64 ServiceWorkerCache::MemoryBackedSize() const {
|
| - if (backend_state_ != BACKEND_OPEN || !memory_only_)
|
| - return 0;
|
| -
|
| - scoped_ptr<disk_cache::Backend::Iterator> backend_iter =
|
| - backend_->CreateIterator();
|
| - disk_cache::Entry* entry = nullptr;
|
| -
|
| - int64 sum = 0;
|
| -
|
| - std::vector<disk_cache::Entry*> entries;
|
| - int rv = net::OK;
|
| - while ((rv = backend_iter->OpenNextEntry(
|
| - &entry, base::Bind(NotReachedCompletionCallback))) == net::OK) {
|
| - entries.push_back(entry); // Open the entries without mutating them.
|
| - }
|
| - DCHECK(rv !=
|
| - net::ERR_IO_PENDING); // Expect all memory ops to be synchronous.
|
| -
|
| - for (disk_cache::Entry* entry : entries) {
|
| - sum += entry->GetDataSize(INDEX_HEADERS) +
|
| - entry->GetDataSize(INDEX_RESPONSE_BODY);
|
| - entry->Close();
|
| - }
|
| -
|
| - return sum;
|
| -}
|
| -
|
| -ServiceWorkerCache::ServiceWorkerCache(
|
| - const GURL& origin,
|
| - const base::FilePath& path,
|
| - net::URLRequestContext* request_context,
|
| - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
|
| - base::WeakPtr<storage::BlobStorageContext> blob_context)
|
| - : origin_(origin),
|
| - path_(path),
|
| - request_context_(request_context),
|
| - quota_manager_proxy_(quota_manager_proxy),
|
| - blob_storage_context_(blob_context),
|
| - backend_state_(BACKEND_UNINITIALIZED),
|
| - scheduler_(new ServiceWorkerCacheScheduler()),
|
| - initializing_(false),
|
| - memory_only_(path.empty()),
|
| - weak_ptr_factory_(this) {
|
| -}
|
| -
|
| -void ServiceWorkerCache::MatchImpl(
|
| - scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ResponseCallback& callback) {
|
| - DCHECK(backend_state_ != BACKEND_UNINITIALIZED);
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - scoped_ptr<MatchContext> match_context(
|
| - new MatchContext(request.Pass(), callback, blob_storage_context_));
|
| -
|
| - disk_cache::Entry** entry_ptr = &match_context->entry;
|
| - ServiceWorkerFetchRequest* request_ptr = match_context->request.get();
|
| -
|
| - net::CompletionCallback open_entry_callback = base::Bind(
|
| - &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(match_context.Pass()));
|
| -
|
| - int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr,
|
| - open_entry_callback);
|
| - if (rv != net::ERR_IO_PENDING)
|
| - open_entry_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::MatchDidOpenEntry(
|
| - scoped_ptr<MatchContext> match_context,
|
| - int rv) {
|
| - if (rv != net::OK) {
|
| - match_context->original_callback.Run(
|
| - ServiceWorkerCache::ERROR_TYPE_NOT_FOUND,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - // Copy the entry pointer before passing it in base::Bind.
|
| - disk_cache::Entry* tmp_entry_ptr = match_context->entry;
|
| - DCHECK(tmp_entry_ptr);
|
| -
|
| - MetadataCallback headers_callback = base::Bind(
|
| - &ServiceWorkerCache::MatchDidReadMetadata, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(match_context.Pass()));
|
| -
|
| - ReadMetadata(tmp_entry_ptr, headers_callback);
|
| -}
|
| -
|
| -void ServiceWorkerCache::MatchDidReadMetadata(
|
| - scoped_ptr<MatchContext> match_context,
|
| - scoped_ptr<ServiceWorkerCacheMetadata> metadata) {
|
| - if (!metadata) {
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - match_context->response.reset(new ServiceWorkerResponse(
|
| - match_context->request->url, metadata->response().status_code(),
|
| - metadata->response().status_text(),
|
| - ProtoResponseTypeToWebResponseType(metadata->response().response_type()),
|
| - ServiceWorkerHeaderMap(), "", 0, GURL()));
|
| -
|
| - ServiceWorkerResponse* response = match_context->response.get();
|
| -
|
| - if (metadata->response().has_url())
|
| - response->url = GURL(metadata->response().url());
|
| -
|
| - for (int i = 0; i < metadata->response().headers_size(); ++i) {
|
| - const ServiceWorkerCacheHeaderMap header = metadata->response().headers(i);
|
| - DCHECK(header.name().find('\0') == std::string::npos);
|
| - DCHECK(header.value().find('\0') == std::string::npos);
|
| - response->headers.insert(std::make_pair(header.name(), header.value()));
|
| - }
|
| -
|
| - ServiceWorkerHeaderMap cached_request_headers;
|
| - for (int i = 0; i < metadata->request().headers_size(); ++i) {
|
| - const ServiceWorkerCacheHeaderMap header = metadata->request().headers(i);
|
| - DCHECK(header.name().find('\0') == std::string::npos);
|
| - DCHECK(header.value().find('\0') == std::string::npos);
|
| - cached_request_headers[header.name()] = header.value();
|
| - }
|
| -
|
| - if (!VaryMatches(match_context->request->headers, cached_request_headers,
|
| - response->headers)) {
|
| - match_context->original_callback.Run(
|
| - ServiceWorkerCache::ERROR_TYPE_NOT_FOUND,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - if (match_context->entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_OK,
|
| - match_context->response.Pass(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - // Stream the response body into a blob.
|
| - if (!match_context->blob_storage_context) {
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - response->blob_uuid = base::GenerateGUID();
|
| -
|
| - match_context->blob_data.reset(
|
| - new storage::BlobDataBuilder(response->blob_uuid));
|
| - match_context->response_body_buffer = new net::IOBufferWithSize(kBufferSize);
|
| -
|
| - disk_cache::Entry* tmp_entry_ptr = match_context->entry;
|
| - net::IOBufferWithSize* response_body_buffer =
|
| - match_context->response_body_buffer.get();
|
| -
|
| - net::CompletionCallback read_callback = base::Bind(
|
| - &ServiceWorkerCache::MatchDidReadResponseBodyData,
|
| - weak_ptr_factory_.GetWeakPtr(), base::Passed(match_context.Pass()));
|
| -
|
| - int read_rv =
|
| - tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY, 0, response_body_buffer,
|
| - response_body_buffer->size(), read_callback);
|
| -
|
| - if (read_rv != net::ERR_IO_PENDING)
|
| - read_callback.Run(read_rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::MatchDidReadResponseBodyData(
|
| - scoped_ptr<MatchContext> match_context,
|
| - int rv) {
|
| - // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
|
| - tracked_objects::ScopedTracker tracking_profile(
|
| - FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| - "422516 ServiceWorkerCache::MatchDidReadResponseBodyData"));
|
| -
|
| - if (rv < 0) {
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - if (rv == 0) {
|
| - match_context->response->blob_uuid = match_context->blob_data->uuid();
|
| - match_context->response->blob_size = match_context->total_bytes_read;
|
| - MatchDoneWithBody(match_context.Pass());
|
| - return;
|
| - }
|
| -
|
| - // TODO(jkarlin): This copying of the the entire cache response into memory is
|
| - // awful. Create a new interface around SimpleCache that provides access the
|
| - // data directly from the file. See bug http://crbug.com/403493.
|
| - match_context->blob_data->AppendData(
|
| - match_context->response_body_buffer->data(), rv);
|
| - match_context->total_bytes_read += rv;
|
| - int total_bytes_read = match_context->total_bytes_read;
|
| -
|
| - // Grab some pointers before passing match_context in bind.
|
| - net::IOBufferWithSize* buffer = match_context->response_body_buffer.get();
|
| - disk_cache::Entry* tmp_entry_ptr = match_context->entry;
|
| -
|
| - net::CompletionCallback read_callback = base::Bind(
|
| - &ServiceWorkerCache::MatchDidReadResponseBodyData,
|
| - weak_ptr_factory_.GetWeakPtr(), base::Passed(match_context.Pass()));
|
| -
|
| - int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY, total_bytes_read,
|
| - buffer, buffer->size(), read_callback);
|
| -
|
| - if (read_rv != net::ERR_IO_PENDING)
|
| - read_callback.Run(read_rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::MatchDoneWithBody(
|
| - scoped_ptr<MatchContext> match_context) {
|
| - if (!match_context->blob_storage_context) {
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle(
|
| - match_context->blob_storage_context->AddFinishedBlob(
|
| - match_context->blob_data.get()));
|
| -
|
| - match_context->original_callback.Run(ServiceWorkerCache::ERROR_TYPE_OK,
|
| - match_context->response.Pass(),
|
| - blob_data_handle.Pass());
|
| -}
|
| -
|
| -void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) {
|
| - DCHECK(backend_state_ != BACKEND_UNINITIALIZED);
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - put_context->callback.Run(ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - scoped_ptr<ServiceWorkerFetchRequest> request_copy(
|
| - new ServiceWorkerFetchRequest(*put_context->request));
|
| -
|
| - DeleteImpl(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(put_context.Pass())));
|
| -}
|
| -
|
| -void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context,
|
| - ErrorType delete_error) {
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - put_context->callback.Run(ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - disk_cache::Entry** entry_ptr = &put_context->cache_entry;
|
| - ServiceWorkerFetchRequest* request_ptr = put_context->request.get();
|
| - disk_cache::Backend* backend_ptr = backend_.get();
|
| -
|
| - net::CompletionCallback create_entry_callback = base::Bind(
|
| - &ServiceWorkerCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(put_context.Pass()));
|
| -
|
| - int create_rv = backend_ptr->CreateEntry(
|
| - request_ptr->url.spec(), entry_ptr, create_entry_callback);
|
| -
|
| - if (create_rv != net::ERR_IO_PENDING)
|
| - create_entry_callback.Run(create_rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::PutDidCreateEntry(scoped_ptr<PutContext> put_context,
|
| - int rv) {
|
| - if (rv != net::OK) {
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_EXISTS,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - DCHECK(put_context->cache_entry);
|
| -
|
| - ServiceWorkerCacheMetadata metadata;
|
| - ServiceWorkerCacheRequest* request_metadata = metadata.mutable_request();
|
| - request_metadata->set_method(put_context->request->method);
|
| - for (ServiceWorkerHeaderMap::const_iterator it =
|
| - put_context->request->headers.begin();
|
| - it != put_context->request->headers.end();
|
| - ++it) {
|
| - DCHECK(it->first.find('\0') == std::string::npos);
|
| - DCHECK(it->second.find('\0') == std::string::npos);
|
| - ServiceWorkerCacheHeaderMap* header_map = request_metadata->add_headers();
|
| - header_map->set_name(it->first);
|
| - header_map->set_value(it->second);
|
| - }
|
| -
|
| - ServiceWorkerCacheResponse* response_metadata = metadata.mutable_response();
|
| - response_metadata->set_status_code(put_context->response->status_code);
|
| - response_metadata->set_status_text(put_context->response->status_text);
|
| - response_metadata->set_response_type(
|
| - WebResponseTypeToProtoResponseType(put_context->response->response_type));
|
| - response_metadata->set_url(put_context->response->url.spec());
|
| - for (ServiceWorkerHeaderMap::const_iterator it =
|
| - put_context->response->headers.begin();
|
| - it != put_context->response->headers.end();
|
| - ++it) {
|
| - DCHECK(it->first.find('\0') == std::string::npos);
|
| - DCHECK(it->second.find('\0') == std::string::npos);
|
| - ServiceWorkerCacheHeaderMap* header_map = response_metadata->add_headers();
|
| - header_map->set_name(it->first);
|
| - header_map->set_value(it->second);
|
| - }
|
| -
|
| - scoped_ptr<std::string> serialized(new std::string());
|
| - if (!metadata.SerializeToString(serialized.get())) {
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - scoped_refptr<net::StringIOBuffer> buffer(
|
| - new net::StringIOBuffer(serialized.Pass()));
|
| -
|
| - // Get a temporary copy of the entry pointer before passing it in base::Bind.
|
| - disk_cache::Entry* tmp_entry_ptr = put_context->cache_entry;
|
| -
|
| - net::CompletionCallback write_headers_callback = base::Bind(
|
| - &ServiceWorkerCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(put_context.Pass()), buffer->size());
|
| -
|
| - rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
|
| - 0 /* offset */,
|
| - buffer.get(),
|
| - buffer->size(),
|
| - write_headers_callback,
|
| - true /* truncate */);
|
| -
|
| - if (rv != net::ERR_IO_PENDING)
|
| - write_headers_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::PutDidWriteHeaders(scoped_ptr<PutContext> put_context,
|
| - int expected_bytes,
|
| - int rv) {
|
| - if (rv != expected_bytes) {
|
| - put_context->cache_entry->Doom();
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - // The metadata is written, now for the response content. The data is streamed
|
| - // from the blob into the cache entry.
|
| -
|
| - if (put_context->response->blob_uuid.empty()) {
|
| - if (put_context->quota_manager_proxy.get()) {
|
| - put_context->quota_manager_proxy->NotifyStorageModified(
|
| - storage::QuotaClient::kServiceWorkerCache,
|
| - put_context->origin,
|
| - storage::kStorageTypeTemporary,
|
| - put_context->cache_entry->GetDataSize(INDEX_HEADERS));
|
| - }
|
| -
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_OK,
|
| - put_context->response.Pass(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - DCHECK(put_context->blob_data_handle);
|
| -
|
| - disk_cache::ScopedEntryPtr entry(put_context->cache_entry);
|
| - put_context->cache_entry = NULL;
|
| - scoped_ptr<BlobReader> reader(new BlobReader());
|
| - BlobReader* reader_ptr = reader.get();
|
| -
|
| - // Grab some pointers before passing put_context in Bind.
|
| - net::URLRequestContext* request_context = put_context->request_context;
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle =
|
| - put_context->blob_data_handle.Pass();
|
| -
|
| - reader_ptr->StreamBlobToCache(
|
| - entry.Pass(), request_context, blob_data_handle.Pass(),
|
| - base::Bind(&ServiceWorkerCache::PutDidWriteBlobToCache,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(put_context.Pass()),
|
| - base::Passed(reader.Pass())));
|
| -}
|
| -
|
| -void ServiceWorkerCache::PutDidWriteBlobToCache(
|
| - scoped_ptr<PutContext> put_context,
|
| - scoped_ptr<BlobReader> blob_reader,
|
| - disk_cache::ScopedEntryPtr entry,
|
| - bool success) {
|
| - DCHECK(entry);
|
| - put_context->cache_entry = entry.release();
|
| -
|
| - if (!success) {
|
| - put_context->cache_entry->Doom();
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE,
|
| - scoped_ptr<ServiceWorkerResponse>(),
|
| - scoped_ptr<storage::BlobDataHandle>());
|
| - return;
|
| - }
|
| -
|
| - if (put_context->quota_manager_proxy.get()) {
|
| - put_context->quota_manager_proxy->NotifyStorageModified(
|
| - storage::QuotaClient::kServiceWorkerCache,
|
| - put_context->origin,
|
| - storage::kStorageTypeTemporary,
|
| - put_context->cache_entry->GetDataSize(INDEX_HEADERS) +
|
| - put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY));
|
| - }
|
| -
|
| - put_context->callback.Run(ServiceWorkerCache::ERROR_TYPE_OK,
|
| - put_context->response.Pass(),
|
| - put_context->out_blob_data_handle.Pass());
|
| -}
|
| -
|
| -void ServiceWorkerCache::DeleteImpl(
|
| - scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ErrorCallback& callback) {
|
| - DCHECK(backend_state_ != BACKEND_UNINITIALIZED);
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - callback.Run(ERROR_TYPE_STORAGE);
|
| - return;
|
| - }
|
| - scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
|
| -
|
| - disk_cache::Entry** entry_ptr = entry.get();
|
| -
|
| - ServiceWorkerFetchRequest* request_ptr = request.get();
|
| -
|
| - net::CompletionCallback open_entry_callback = base::Bind(
|
| - &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(),
|
| - origin_, base::Passed(request.Pass()), callback,
|
| - base::Passed(entry.Pass()), quota_manager_proxy_);
|
| -
|
| - int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr,
|
| - open_entry_callback);
|
| - if (rv != net::ERR_IO_PENDING)
|
| - open_entry_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::DeleteDidOpenEntry(
|
| - const GURL& origin,
|
| - scoped_ptr<ServiceWorkerFetchRequest> request,
|
| - const ServiceWorkerCache::ErrorCallback& callback,
|
| - scoped_ptr<disk_cache::Entry*> entry_ptr,
|
| - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
|
| - int rv) {
|
| - if (rv != net::OK) {
|
| - callback.Run(ServiceWorkerCache::ERROR_TYPE_NOT_FOUND);
|
| - return;
|
| - }
|
| -
|
| - DCHECK(entry_ptr);
|
| - disk_cache::ScopedEntryPtr entry(*entry_ptr);
|
| -
|
| - if (quota_manager_proxy.get()) {
|
| - quota_manager_proxy->NotifyStorageModified(
|
| - storage::QuotaClient::kServiceWorkerCache, origin,
|
| - storage::kStorageTypeTemporary,
|
| - -1 * (entry->GetDataSize(INDEX_HEADERS) +
|
| - entry->GetDataSize(INDEX_RESPONSE_BODY)));
|
| - }
|
| -
|
| - entry->Doom();
|
| - callback.Run(ServiceWorkerCache::ERROR_TYPE_OK);
|
| -}
|
| -
|
| -void ServiceWorkerCache::KeysImpl(const RequestsCallback& callback) {
|
| - DCHECK(backend_state_ != BACKEND_UNINITIALIZED);
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - callback.Run(ERROR_TYPE_STORAGE, scoped_ptr<Requests>());
|
| - return;
|
| - }
|
| -
|
| - // 1. Iterate through all of the entries, open them, and add them to a vector.
|
| - // 2. For each open entry:
|
| - // 2.1. Read the headers into a protobuf.
|
| - // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key").
|
| - // 2.3. Push the response into a vector of requests to be returned.
|
| - // 3. Return the vector of requests (keys).
|
| -
|
| - // The entries have to be loaded into a vector first because enumeration loops
|
| - // forever if you read data from a cache entry while enumerating.
|
| -
|
| - scoped_ptr<KeysContext> keys_context(new KeysContext(callback));
|
| -
|
| - keys_context->backend_iterator = backend_->CreateIterator();
|
| - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
|
| - disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
|
| -
|
| - net::CompletionCallback open_entry_callback = base::Bind(
|
| - &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(keys_context.Pass()));
|
| -
|
| - int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
|
| -
|
| - if (rv != net::ERR_IO_PENDING)
|
| - open_entry_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::KeysDidOpenNextEntry(
|
| - scoped_ptr<KeysContext> keys_context,
|
| - int rv) {
|
| - if (rv == net::ERR_FAILED) {
|
| - DCHECK(!keys_context->enumerated_entry);
|
| - // Enumeration is complete, extract the requests from the entries.
|
| - Entries::iterator iter = keys_context->entries.begin();
|
| - KeysProcessNextEntry(keys_context.Pass(), iter);
|
| - return;
|
| - }
|
| -
|
| - if (rv < 0) {
|
| - keys_context->original_callback.Run(ERROR_TYPE_STORAGE,
|
| - scoped_ptr<Requests>());
|
| - return;
|
| - }
|
| -
|
| - if (backend_state_ != BACKEND_OPEN) {
|
| - keys_context->original_callback.Run(ERROR_TYPE_NOT_FOUND,
|
| - scoped_ptr<Requests>());
|
| - return;
|
| - }
|
| -
|
| - // Store the entry.
|
| - keys_context->entries.push_back(keys_context->enumerated_entry);
|
| - keys_context->enumerated_entry = NULL;
|
| -
|
| - // Enumerate the next entry.
|
| - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
|
| - disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
|
| - net::CompletionCallback open_entry_callback = base::Bind(
|
| - &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(keys_context.Pass()));
|
| -
|
| - rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
|
| -
|
| - if (rv != net::ERR_IO_PENDING)
|
| - open_entry_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::KeysProcessNextEntry(
|
| - scoped_ptr<KeysContext> keys_context,
|
| - const Entries::iterator& iter) {
|
| - if (iter == keys_context->entries.end()) {
|
| - // All done. Return all of the keys.
|
| - keys_context->original_callback.Run(ERROR_TYPE_OK,
|
| - keys_context->out_keys.Pass());
|
| - return;
|
| - }
|
| -
|
| - ReadMetadata(*iter, base::Bind(&ServiceWorkerCache::KeysDidReadMetadata,
|
| - weak_ptr_factory_.GetWeakPtr(),
|
| - base::Passed(keys_context.Pass()), iter));
|
| -}
|
| -
|
| -void ServiceWorkerCache::KeysDidReadMetadata(
|
| - scoped_ptr<KeysContext> keys_context,
|
| - const Entries::iterator& iter,
|
| - scoped_ptr<ServiceWorkerCacheMetadata> metadata) {
|
| - disk_cache::Entry* entry = *iter;
|
| -
|
| - if (metadata) {
|
| - keys_context->out_keys->push_back(
|
| - ServiceWorkerFetchRequest(GURL(entry->GetKey()),
|
| - metadata->request().method(),
|
| - ServiceWorkerHeaderMap(),
|
| - Referrer(),
|
| - false));
|
| -
|
| - ServiceWorkerHeaderMap& req_headers =
|
| - keys_context->out_keys->back().headers;
|
| -
|
| - for (int i = 0; i < metadata->request().headers_size(); ++i) {
|
| - const ServiceWorkerCacheHeaderMap header = metadata->request().headers(i);
|
| - DCHECK(header.name().find('\0') == std::string::npos);
|
| - DCHECK(header.value().find('\0') == std::string::npos);
|
| - req_headers.insert(std::make_pair(header.name(), header.value()));
|
| - }
|
| - } else {
|
| - entry->Doom();
|
| - }
|
| -
|
| - KeysProcessNextEntry(keys_context.Pass(), iter + 1);
|
| -}
|
| -
|
| -void ServiceWorkerCache::CloseImpl(const base::Closure& callback) {
|
| - DCHECK(backend_state_ != BACKEND_CLOSED);
|
| -
|
| - backend_state_ = BACKEND_CLOSED;
|
| - backend_.reset();
|
| - callback.Run();
|
| -}
|
| -
|
| -void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
|
| - DCHECK(!backend_);
|
| -
|
| - // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
|
| - net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE;
|
| -
|
| - scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
|
| -
|
| - // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
|
| - ScopedBackendPtr* backend = backend_ptr.get();
|
| -
|
| - net::CompletionCallback create_cache_callback =
|
| - base::Bind(&ServiceWorkerCache::CreateBackendDidCreate,
|
| - weak_ptr_factory_.GetWeakPtr(), callback,
|
| - base::Passed(backend_ptr.Pass()));
|
| -
|
| - // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore
|
| - // has for disk caches.
|
| - int rv = disk_cache::CreateCacheBackend(
|
| - cache_type,
|
| - net::CACHE_BACKEND_SIMPLE,
|
| - path_,
|
| - kMaxCacheBytes,
|
| - false, /* force */
|
| - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
|
| - NULL,
|
| - backend,
|
| - create_cache_callback);
|
| - if (rv != net::ERR_IO_PENDING)
|
| - create_cache_callback.Run(rv);
|
| -}
|
| -
|
| -void ServiceWorkerCache::CreateBackendDidCreate(
|
| - const ServiceWorkerCache::ErrorCallback& callback,
|
| - scoped_ptr<ScopedBackendPtr> backend_ptr,
|
| - int rv) {
|
| - if (rv != net::OK) {
|
| - callback.Run(ServiceWorkerCache::ERROR_TYPE_STORAGE);
|
| - return;
|
| - }
|
| -
|
| - backend_ = backend_ptr->Pass();
|
| - callback.Run(ServiceWorkerCache::ERROR_TYPE_OK);
|
| -}
|
| -
|
| -void ServiceWorkerCache::InitBackend() {
|
| - DCHECK(backend_state_ == BACKEND_UNINITIALIZED);
|
| -
|
| - if (initializing_)
|
| - return;
|
| -
|
| - DCHECK(!scheduler_->ScheduledOperations());
|
| - initializing_ = true;
|
| -
|
| - scheduler_->ScheduleOperation(base::Bind(
|
| - &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(),
|
| - base::Bind(&ServiceWorkerCache::InitDone,
|
| - weak_ptr_factory_.GetWeakPtr())));
|
| -}
|
| -
|
| -void ServiceWorkerCache::InitDone(ErrorType error) {
|
| - initializing_ = false;
|
| - backend_state_ = (error == ERROR_TYPE_OK && backend_ &&
|
| - backend_state_ == BACKEND_UNINITIALIZED)
|
| - ? BACKEND_OPEN
|
| - : BACKEND_CLOSED;
|
| -
|
| - UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", error,
|
| - ErrorType::ERROR_TYPE_LAST + 1);
|
| -
|
| - scheduler_->CompleteOperationAndRunNext();
|
| -}
|
| -
|
| -void ServiceWorkerCache::PendingClosure(const base::Closure& callback) {
|
| - base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr();
|
| -
|
| - callback.Run();
|
| - if (cache)
|
| - scheduler_->CompleteOperationAndRunNext();
|
| -}
|
| -
|
| -void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback,
|
| - ErrorType error) {
|
| - base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr();
|
| -
|
| - callback.Run(error);
|
| - if (cache)
|
| - scheduler_->CompleteOperationAndRunNext();
|
| -}
|
| -
|
| -void ServiceWorkerCache::PendingResponseCallback(
|
| - const ResponseCallback& callback,
|
| - ErrorType error,
|
| - scoped_ptr<ServiceWorkerResponse> response,
|
| - scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
|
| - base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr();
|
| -
|
| - callback.Run(error, response.Pass(), blob_data_handle.Pass());
|
| - if (cache)
|
| - scheduler_->CompleteOperationAndRunNext();
|
| -}
|
| -
|
| -void ServiceWorkerCache::PendingRequestsCallback(
|
| - const RequestsCallback& callback,
|
| - ErrorType error,
|
| - scoped_ptr<Requests> requests) {
|
| - base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr();
|
| -
|
| - callback.Run(error, requests.Pass());
|
| - if (cache)
|
| - scheduler_->CompleteOperationAndRunNext();
|
| -}
|
| -
|
| -} // namespace content
|
|
|