| 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
|
| index d5028f00854f1f2d1241105442ee5f1ec94bb289..9c7589fa9f550d998dbd2eeb403aea9847ba61b5 100644
|
| --- a/content/browser/service_worker/service_worker_cache.cc
|
| +++ b/content/browser/service_worker/service_worker_cache.cc
|
| @@ -7,11 +7,149 @@
|
| #include <string>
|
|
|
| #include "base/files/file_path.h"
|
| +#include "base/guid.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "content/browser/service_worker/service_worker_cache.pb.h"
|
| +#include "content/public/browser/browser_thread.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 "webkit/browser/blob/blob_data_handle.h"
|
| #include "webkit/browser/blob/blob_storage_context.h"
|
| +#include "webkit/browser/blob/blob_url_request_job_factory.h"
|
|
|
| namespace content {
|
|
|
| +namespace {
|
| +// 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;
|
| +}
|
| +
|
| +struct ServiceWorkerCache::ResponseReadContext {
|
| + ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
|
| + scoped_refptr<webkit_blob::BlobData> blob)
|
| + : buffer(buff), blob_data(blob), total_bytes_read(0) {}
|
| +
|
| + scoped_refptr<net::IOBufferWithSize> buffer;
|
| + scoped_refptr<webkit_blob::BlobData> blob_data;
|
| + int total_bytes_read;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ResponseReadContext);
|
| +};
|
| +
|
| +// Streams data from a blob and writes it to a given disk_cache::Entry.
|
| +class ServiceWorkerCache::BlobReader : public net::URLRequest::Delegate {
|
| + public:
|
| + BlobReader(disk_cache::ScopedEntryPtr entry)
|
| + : cache_entry_offset_(0),
|
| + buffer_(new net::IOBufferWithSize(kBufferSize)),
|
| + weak_ptr_factory_(this) {
|
| + DCHECK(entry);
|
| + entry_ = entry.Pass();
|
| + }
|
| +
|
| + void StreamBlobToCache(
|
| + net::URLRequestContext* request_context,
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
|
| + const EntryBoolCallback& callback) {
|
| + callback_ = callback;
|
| + blob_request_ = webkit_blob::BlobProtocolHandler::CreateBlobRequest(
|
| + blob_data_handle.Pass(), request_context, this);
|
| + blob_request_->Start();
|
| + }
|
| +
|
| + // net::URLRequest::Delegate overrides for reading blobs.
|
| + virtual void OnReceivedRedirect(net::URLRequest* request,
|
| + const GURL& new_url,
|
| + bool* defer_redirect) OVERRIDE {
|
| + NOTREACHED();
|
| + }
|
| + virtual void OnAuthRequired(net::URLRequest* request,
|
| + net::AuthChallengeInfo* auth_info) OVERRIDE {
|
| + NOTREACHED();
|
| + }
|
| + virtual void OnCertificateRequested(
|
| + net::URLRequest* request,
|
| + net::SSLCertRequestInfo* cert_request_info) OVERRIDE {
|
| + NOTREACHED();
|
| + }
|
| + virtual void OnSSLCertificateError(net::URLRequest* request,
|
| + const net::SSLInfo& ssl_info,
|
| + bool fatal) OVERRIDE {
|
| + NOTREACHED();
|
| + }
|
| + virtual void OnBeforeNetworkStart(net::URLRequest* request,
|
| + bool* defer) OVERRIDE {
|
| + NOTREACHED();
|
| + }
|
| +
|
| + virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
|
| + 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);
|
| + }
|
| +
|
| + virtual void OnReadCompleted(net::URLRequest* request,
|
| + int bytes_read) OVERRIDE {
|
| + 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(ServiceWorkerCache::INDEX_RESPONSE_BODY,
|
| + cache_entry_offset_,
|
| + buffer_,
|
| + 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_;
|
| + EntryBoolCallback callback_;
|
| + scoped_refptr<net::IOBufferWithSize> buffer_;
|
| + base::WeakPtrFactory<ServiceWorkerCache::BlobReader> weak_ptr_factory_;
|
| +};
|
| +
|
| // static
|
| scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
|
| const std::string& name,
|
| @@ -31,15 +169,133 @@ scoped_ptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
|
| new ServiceWorkerCache(path, name, request_context, blob_context));
|
| }
|
|
|
| -void ServiceWorkerCache::CreateBackend(
|
| - const base::Callback<void(bool)>& callback) {
|
| - callback.Run(true);
|
| +ServiceWorkerCache::~ServiceWorkerCache() {
|
| }
|
|
|
| base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
|
| return weak_ptr_factory_.GetWeakPtr();
|
| }
|
|
|
| +void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
|
| + net::CacheType cache_type =
|
| + path_.empty() ? net::MEMORY_CACHE : net::DISK_CACHE;
|
| +
|
| + net::CompletionCallback create_cache_callback =
|
| + base::Bind(&ServiceWorkerCache::CreateBackendDidCreate,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + callback);
|
| +
|
| + // 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,
|
| + true, /* 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 ErrorCallback& callback,
|
| + int rv) {
|
| + if (rv != net::OK) {
|
| + callback.Run(ErrorTypeStorage);
|
| + return;
|
| + }
|
| + callback.Run(ErrorTypeOK);
|
| +}
|
| +
|
| +void ServiceWorkerCache::Put(ServiceWorkerFetchRequest* request,
|
| + ServiceWorkerResponse* response,
|
| + const ErrorCallback& callback) {
|
| + DCHECK(backend_);
|
| +
|
| + scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
|
| +
|
| + disk_cache::Entry** entry_ptr = entry.get();
|
| +
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
|
| +
|
| + if (!response->blob_uuid.empty()) {
|
| + if (!blob_storage_context_) {
|
| + callback.Run(ErrorTypeStorage);
|
| + return;
|
| + }
|
| + blob_data_handle =
|
| + blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
|
| + if (!blob_data_handle) {
|
| + callback.Run(ErrorTypeStorage);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + net::CompletionCallback create_entry_callback =
|
| + base::Bind(&ServiceWorkerCache::PutDidCreateEntry,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + response,
|
| + callback,
|
| + base::Passed(entry.Pass()),
|
| + base::Passed(blob_data_handle.Pass()));
|
| +
|
| + int rv = backend_->CreateEntry(
|
| + request->url.spec(), entry_ptr, create_entry_callback);
|
| +
|
| + if (rv != net::ERR_IO_PENDING)
|
| + create_entry_callback.Run(rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::Match(ServiceWorkerFetchRequest* request,
|
| + const ResponseCallback& callback) {
|
| + DCHECK(backend_);
|
| +
|
| + scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
|
| +
|
| + disk_cache::Entry** entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback open_entry_callback =
|
| + base::Bind(&ServiceWorkerCache::MatchDidOpenEntry,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + callback,
|
| + base::Passed(entry.Pass()));
|
| +
|
| + int rv =
|
| + backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
|
| + if (rv != net::ERR_IO_PENDING)
|
| + open_entry_callback.Run(rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::Delete(ServiceWorkerFetchRequest* request,
|
| + const ErrorCallback& callback) {
|
| + DCHECK(backend_);
|
| +
|
| + scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
|
| +
|
| + disk_cache::Entry** entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback open_entry_callback =
|
| + base::Bind(&ServiceWorkerCache::DeleteDidOpenEntry,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + callback,
|
| + base::Passed(entry.Pass()));
|
| +
|
| + int rv =
|
| + backend_->OpenEntry(request->url.spec(), entry_ptr, open_entry_callback);
|
| + if (rv != net::ERR_IO_PENDING)
|
| + open_entry_callback.Run(rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::DerefBlob(const std::string& uuid) {
|
| + DropBlobDataHandle(uuid);
|
| +}
|
| +
|
| ServiceWorkerCache::ServiceWorkerCache(
|
| const base::FilePath& path,
|
| const std::string& name,
|
| @@ -53,7 +309,336 @@ ServiceWorkerCache::ServiceWorkerCache(
|
| weak_ptr_factory_(this) {
|
| }
|
|
|
| -ServiceWorkerCache::~ServiceWorkerCache() {
|
| +void ServiceWorkerCache::MatchDidOpenEntry(
|
| + ServiceWorkerFetchRequest* request,
|
| + const ResponseCallback& callback,
|
| + scoped_ptr<disk_cache::Entry*> entryptr,
|
| + int rv) {
|
| + if (rv != net::OK) {
|
| + callback.Run(ErrorTypeNotFound, scoped_ptr<ServiceWorkerResponse>());
|
| + return;
|
| + }
|
| +
|
| + DCHECK(entryptr);
|
| + disk_cache::ScopedEntryPtr entry(*entryptr);
|
| +
|
| + scoped_refptr<net::IOBufferWithSize> buffer(
|
| + new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
|
| +
|
| + // Copy the entry pointer before passing it in base::Bind.
|
| + disk_cache::Entry* tmp_entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback read_header_callback =
|
| + base::Bind(&ServiceWorkerCache::MatchDidReadHeaderData,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + callback,
|
| + base::Passed(entry.Pass()),
|
| + buffer);
|
| +
|
| + int read_rv = tmp_entry_ptr->ReadData(
|
| + INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
|
| +
|
| + if (read_rv != net::ERR_IO_PENDING)
|
| + read_header_callback.Run(read_rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::MatchDidReadHeaderData(
|
| + ServiceWorkerFetchRequest* request,
|
| + const ResponseCallback& callback,
|
| + disk_cache::ScopedEntryPtr entry,
|
| + const scoped_refptr<net::IOBufferWithSize>& buffer,
|
| + int rv) {
|
| + if (rv != buffer->size()) {
|
| + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>());
|
| +
|
| + return;
|
| + }
|
| +
|
| + ServiceWorkerRequestResponseHeaders headers;
|
| +
|
| + if (!headers.ParseFromArray(buffer->data(), buffer->size())) {
|
| + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>());
|
| +
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<ServiceWorkerResponse> response(
|
| + new ServiceWorkerResponse(request->url,
|
| + headers.status_code(),
|
| + headers.status_text(),
|
| + std::map<std::string, std::string>(),
|
| + ""));
|
| +
|
| + for (int i = 0; i < headers.response_headers_size(); ++i) {
|
| + const ServiceWorkerRequestResponseHeaders::HeaderMap header =
|
| + headers.response_headers(i);
|
| + response->headers.insert(std::make_pair(header.name(), header.value()));
|
| + }
|
| +
|
| + // TODO(jkarlin): Insert vary validation here.
|
| +
|
| + if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
|
| + callback.Run(ErrorTypeOK, response.Pass());
|
| +
|
| + return;
|
| + }
|
| +
|
| + // Stream the response body into a blob.
|
| + if (!blob_storage_context_) {
|
| + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>());
|
| +
|
| + return;
|
| + }
|
| +
|
| + response->blob_uuid = base::GenerateGUID();
|
| +
|
| + scoped_refptr<webkit_blob::BlobData> blob_data =
|
| + new webkit_blob::BlobData(response->blob_uuid);
|
| + scoped_refptr<net::IOBufferWithSize> response_body_buffer(
|
| + new net::IOBufferWithSize(kBufferSize));
|
| +
|
| + scoped_ptr<ResponseReadContext> read_context(
|
| + new ResponseReadContext(response_body_buffer, blob_data));
|
| +
|
| + // Copy the entry pointer before passing it in base::Bind.
|
| + disk_cache::Entry* tmp_entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback read_callback =
|
| + base::Bind(&ServiceWorkerCache::MatchDidReadResponseBodyData,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + callback,
|
| + base::Passed(entry.Pass()),
|
| + base::Passed(response.Pass()),
|
| + base::Passed(read_context.Pass()));
|
| +
|
| + int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
|
| + 0,
|
| + response_body_buffer.get(),
|
| + response_body_buffer->size(),
|
| + read_callback);
|
| +
|
| + if (read_rv != net::ERR_IO_PENDING)
|
| + read_callback.Run(read_rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::MatchDidReadResponseBodyData(
|
| + ServiceWorkerFetchRequest* request,
|
| + const ResponseCallback& callback,
|
| + disk_cache::ScopedEntryPtr entry,
|
| + scoped_ptr<ServiceWorkerResponse> response,
|
| + scoped_ptr<ResponseReadContext> response_context,
|
| + int rv) {
|
| + if (rv < 0) {
|
| + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>());
|
| + }
|
| +
|
| + if (rv == 0) {
|
| + MatchDoneWithBody(
|
| + request, callback, response.Pass(), response_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.
|
| + response_context->blob_data->AppendData(response_context->buffer->data(), rv);
|
| + response_context->total_bytes_read += rv;
|
| + int total_bytes_read = response_context->total_bytes_read;
|
| +
|
| + // Grab some pointers before passing them in bind.
|
| + net::IOBufferWithSize* buffer = response_context->buffer;
|
| + disk_cache::Entry* tmp_entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback read_callback =
|
| + base::Bind(&ServiceWorkerCache::MatchDidReadResponseBodyData,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + request,
|
| + callback,
|
| + base::Passed(entry.Pass()),
|
| + base::Passed(response.Pass()),
|
| + base::Passed(response_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(
|
| + ServiceWorkerFetchRequest* request,
|
| + const ResponseCallback& callback,
|
| + scoped_ptr<ServiceWorkerResponse> response,
|
| + scoped_ptr<ResponseReadContext> response_context) {
|
| + if (!blob_storage_context_) {
|
| + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>());
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
|
| + blob_storage_context_->AddFinishedBlob(
|
| + response_context->blob_data.get()));
|
| +
|
| + HoldBlobDataHandle(response->blob_uuid, blob_data_handle.Pass());
|
| + callback.Run(ErrorTypeOK, response.Pass());
|
| +}
|
| +
|
| +void ServiceWorkerCache::PutDidCreateEntry(
|
| + ServiceWorkerFetchRequest* request,
|
| + ServiceWorkerResponse* response,
|
| + const ErrorCallback& callback,
|
| + scoped_ptr<disk_cache::Entry*> entryptr,
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
|
| + int rv) {
|
| + if (rv != net::OK) {
|
| + callback.Run(ErrorTypeExists);
|
| + return;
|
| + }
|
| +
|
| + DCHECK(entryptr);
|
| + disk_cache::ScopedEntryPtr entry(*entryptr);
|
| +
|
| + ServiceWorkerRequestResponseHeaders headers;
|
| + headers.set_method(request->method);
|
| +
|
| + headers.set_status_code(response->status_code);
|
| + headers.set_status_text(response->status_text);
|
| + for (std::map<std::string, std::string>::const_iterator it =
|
| + request->headers.begin();
|
| + it != request->headers.end();
|
| + ++it) {
|
| + ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
|
| + headers.add_request_headers();
|
| + header_map->set_name(it->first);
|
| + header_map->set_value(it->second);
|
| + }
|
| +
|
| + for (std::map<std::string, std::string>::const_iterator it =
|
| + response->headers.begin();
|
| + it != response->headers.end();
|
| + ++it) {
|
| + ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
|
| + headers.add_response_headers();
|
| + header_map->set_name(it->first);
|
| + header_map->set_value(it->second);
|
| + }
|
| +
|
| + std::string serialized;
|
| + if (!headers.SerializeToString(&serialized)) {
|
| + callback.Run(ErrorTypeStorage);
|
| + }
|
| +
|
| + scoped_refptr<net::ZeroCopyStringIOBuffer> buffer(
|
| + new net::ZeroCopyStringIOBuffer(&serialized));
|
| +
|
| + // Get a temporary copy of the entry pointer before passing it in base::Bind.
|
| + disk_cache::Entry* tmp_entry_ptr = entry.get();
|
| +
|
| + net::CompletionCallback write_headers_callback =
|
| + base::Bind(&ServiceWorkerCache::PutDidWriteHeaders,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + response,
|
| + callback,
|
| + base::Passed(entry.Pass()),
|
| + base::Passed(blob_data_handle.Pass()),
|
| + buffer->string()->size());
|
| +
|
| + rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
|
| + 0 /* offset */,
|
| + buffer,
|
| + buffer->string()->size(),
|
| + write_headers_callback,
|
| + true /* truncate */);
|
| +
|
| + if (rv != net::ERR_IO_PENDING)
|
| + write_headers_callback.Run(rv);
|
| +}
|
| +
|
| +void ServiceWorkerCache::PutDidWriteHeaders(
|
| + ServiceWorkerResponse* response,
|
| + const ErrorCallback& callback,
|
| + disk_cache::ScopedEntryPtr entry,
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle,
|
| + int expected_bytes,
|
| + int rv) {
|
| + if (rv != expected_bytes) {
|
| + entry->Doom();
|
| + callback.Run(ErrorTypeStorage);
|
| + return;
|
| + }
|
| +
|
| + // The metadata is written, now for the response content. The data is streamed
|
| + // from the blob into the cache entry.
|
| +
|
| + if (response->blob_uuid.empty()) {
|
| + callback.Run(ErrorTypeOK);
|
| + return;
|
| + }
|
| +
|
| + DCHECK(blob_data_handle);
|
| +
|
| + scoped_ptr<BlobReader> reader(new BlobReader(entry.Pass()));
|
| +
|
| + reader->StreamBlobToCache(
|
| + request_context_,
|
| + blob_data_handle.Pass(),
|
| + base::Bind(&ServiceWorkerCache::PutDidWriteBlobToCache,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + callback,
|
| + base::Passed(reader.Pass())));
|
| +}
|
| +
|
| +void ServiceWorkerCache::PutDidWriteBlobToCache(
|
| + const ErrorCallback& callback,
|
| + scoped_ptr<BlobReader> blob_reader,
|
| + disk_cache::ScopedEntryPtr entry,
|
| + bool success) {
|
| + if (!success) {
|
| + entry->Doom();
|
| + callback.Run(ErrorTypeStorage);
|
| + return;
|
| + }
|
| +
|
| + callback.Run(ErrorTypeOK);
|
| +}
|
| +
|
| +void ServiceWorkerCache::DeleteDidOpenEntry(
|
| + ServiceWorkerFetchRequest* request,
|
| + const ErrorCallback& callback,
|
| + scoped_ptr<disk_cache::Entry*> entryptr,
|
| + int rv) {
|
| + if (rv != net::OK) {
|
| + callback.Run(ErrorTypeNotFound);
|
| + return;
|
| + }
|
| +
|
| + DCHECK(entryptr);
|
| + disk_cache::ScopedEntryPtr entry(*entryptr);
|
| +
|
| + entry->Doom();
|
| + callback.Run(ErrorTypeOK);
|
| +}
|
| +
|
| +void ServiceWorkerCache::HoldBlobDataHandle(
|
| + const std::string& uuid,
|
| + scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle) {
|
| + DCHECK(!ContainsKey(blob_data_handle_map_, uuid));
|
| + blob_data_handle_map_[uuid] = blob_data_handle.release();
|
| +}
|
| +
|
| +void ServiceWorkerCache::DropBlobDataHandle(const std::string& uuid) {
|
| + BlobDataHandleMap::iterator iter = blob_data_handle_map_.find(uuid);
|
| + if (iter != blob_data_handle_map_.end()) {
|
| + delete iter->second;
|
| + blob_data_handle_map_.erase(iter);
|
| + } else {
|
| + DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid;
|
| + }
|
| }
|
|
|
| } // namespace content
|
|
|