| // Copyright 2015 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/cache_storage/cache_storage_blob_to_disk_cache.h" |
| |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "net/base/io_buffer.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "storage/browser/blob/blob_data_handle.h" |
| #include "storage/browser/blob/blob_url_request_job_factory.h" |
| |
| namespace content { |
| |
| const int CacheStorageBlobToDiskCache::kBufferSize = 1024 * 512; |
| |
| CacheStorageBlobToDiskCache::CacheStorageBlobToDiskCache() |
| : cache_entry_offset_(0), |
| disk_cache_body_index_(0), |
| buffer_(new net::IOBufferWithSize(kBufferSize)), |
| weak_ptr_factory_(this) { |
| } |
| |
| CacheStorageBlobToDiskCache::~CacheStorageBlobToDiskCache() { |
| if (blob_request_) |
| request_context_getter_->RemoveObserver(this); |
| } |
| |
| void CacheStorageBlobToDiskCache::StreamBlobToCache( |
| disk_cache::ScopedEntryPtr entry, |
| int disk_cache_body_index, |
| const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, |
| scoped_ptr<storage::BlobDataHandle> blob_data_handle, |
| const EntryAndBoolCallback& callback) { |
| DCHECK(entry); |
| DCHECK_LE(0, disk_cache_body_index); |
| DCHECK(blob_data_handle); |
| DCHECK(!blob_request_); |
| |
| if (!request_context_getter->GetURLRequestContext()) { |
| callback.Run(std::move(entry), false /* success */); |
| return; |
| } |
| |
| disk_cache_body_index_ = disk_cache_body_index; |
| |
| entry_ = std::move(entry); |
| callback_ = callback; |
| request_context_getter_ = request_context_getter; |
| |
| blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( |
| std::move(blob_data_handle), |
| request_context_getter->GetURLRequestContext(), this); |
| request_context_getter_->AddObserver(this); |
| blob_request_->Start(); |
| } |
| |
| void CacheStorageBlobToDiskCache::OnResponseStarted(net::URLRequest* request) { |
| if (!request->status().is_success()) { |
| RunCallbackAndRemoveObserver(false); |
| return; |
| } |
| |
| ReadFromBlob(); |
| } |
| |
| void CacheStorageBlobToDiskCache::OnReadCompleted(net::URLRequest* request, |
| int bytes_read) { |
| if (!request->status().is_success()) { |
| RunCallbackAndRemoveObserver(false); |
| return; |
| } |
| |
| if (bytes_read == 0) { |
| RunCallbackAndRemoveObserver(true); |
| return; |
| } |
| |
| net::CompletionCallback cache_write_callback = |
| base::Bind(&CacheStorageBlobToDiskCache::DidWriteDataToEntry, |
| weak_ptr_factory_.GetWeakPtr(), bytes_read); |
| |
| int rv = entry_->WriteData(disk_cache_body_index_, cache_entry_offset_, |
| buffer_.get(), bytes_read, cache_write_callback, |
| true /* truncate */); |
| if (rv != net::ERR_IO_PENDING) |
| cache_write_callback.Run(rv); |
| } |
| |
| void CacheStorageBlobToDiskCache::OnReceivedRedirect( |
| net::URLRequest* request, |
| const net::RedirectInfo& redirect_info, |
| bool* defer_redirect) { |
| NOTREACHED(); |
| } |
| |
| void CacheStorageBlobToDiskCache::OnAuthRequired( |
| net::URLRequest* request, |
| net::AuthChallengeInfo* auth_info) { |
| NOTREACHED(); |
| } |
| void CacheStorageBlobToDiskCache::OnCertificateRequested( |
| net::URLRequest* request, |
| net::SSLCertRequestInfo* cert_request_info) { |
| NOTREACHED(); |
| } |
| void CacheStorageBlobToDiskCache::OnSSLCertificateError( |
| net::URLRequest* request, |
| const net::SSLInfo& ssl_info, |
| bool fatal) { |
| NOTREACHED(); |
| } |
| void CacheStorageBlobToDiskCache::OnBeforeNetworkStart(net::URLRequest* request, |
| bool* defer) { |
| NOTREACHED(); |
| } |
| |
| void CacheStorageBlobToDiskCache::OnContextShuttingDown() { |
| DCHECK(blob_request_); |
| RunCallbackAndRemoveObserver(false); |
| } |
| |
| void CacheStorageBlobToDiskCache::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 CacheStorageBlobToDiskCache::DidWriteDataToEntry(int expected_bytes, |
| int rv) { |
| if (rv != expected_bytes) { |
| RunCallbackAndRemoveObserver(false); |
| return; |
| } |
| |
| cache_entry_offset_ += rv; |
| ReadFromBlob(); |
| } |
| |
| void CacheStorageBlobToDiskCache::RunCallbackAndRemoveObserver(bool success) { |
| DCHECK(request_context_getter_); |
| |
| request_context_getter_->RemoveObserver(this); |
| blob_request_.reset(); |
| callback_.Run(std::move(entry_), success); |
| } |
| |
| } // namespace content |