blob: 3cc348b830ed2feb39d37baf3ca38f444d94bd4d [file] [log] [blame]
// Copyright 2018 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_cache_entry_handler.h"
#include "base/guid.h"
#include "base/optional.h"
#include "content/browser/background_fetch/storage/cache_entry_handler_impl.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
namespace content {
CacheStorageCacheEntryHandler::BlobDataHandle::BlobDataHandle(
base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler,
CacheStorageCacheHandle cache_handle,
disk_cache::ScopedEntryPtr entry)
: entry_handler_(std::move(entry_handler)),
cache_handle_(std::move(cache_handle)),
entry_(std::move(entry)) {}
bool CacheStorageCacheEntryHandler::BlobDataHandle::IsValid() {
return entry_ != nullptr;
}
void CacheStorageCacheEntryHandler::BlobDataHandle::Invalidate() {
cache_handle_ = base::nullopt;
entry_handler_ = nullptr;
entry_ = nullptr;
}
CacheStorageCacheEntryHandler::BlobDataHandle::~BlobDataHandle() {
if (entry_handler_)
entry_handler_->EraseBlobDataHandle(this);
}
PutContext::PutContext(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::BlobPtr blob,
uint64_t blob_size,
blink::mojom::BlobPtr side_data_blob,
uint64_t side_data_blob_size)
: request(std::move(request)),
response(std::move(response)),
blob(std::move(blob)),
blob_size(blob_size),
side_data_blob(std::move(side_data_blob)),
side_data_blob_size(side_data_blob_size) {}
PutContext::~PutContext() = default;
// Default implemetation of CacheStorageCacheEntryHandler.
class CacheStorageCacheEntryHandlerImpl : public CacheStorageCacheEntryHandler {
public:
CacheStorageCacheEntryHandlerImpl(
base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheStorageCacheEntryHandler(std::move(blob_context)),
weak_ptr_factory_(this) {}
~CacheStorageCacheEntryHandlerImpl() override = default;
std::unique_ptr<PutContext> CreatePutContext(
blink::mojom::FetchAPIRequestPtr request,
blink::mojom::FetchAPIResponsePtr response) override {
blink::mojom::BlobPtr blob;
uint64_t blob_size = blink::BlobUtils::kUnknownSize;
blink::mojom::BlobPtr side_data_blob;
uint64_t side_data_blob_size = blink::BlobUtils::kUnknownSize;
if (response->blob) {
blob.Bind(std::move(response->blob->blob));
blob_size = response->blob->size;
}
if (response->side_data_blob) {
side_data_blob.Bind(std::move(response->side_data_blob->blob));
side_data_blob_size = response->side_data_blob->size;
}
return std::make_unique<PutContext>(
std::move(request), std::move(response), std::move(blob), blob_size,
std::move(side_data_blob), side_data_blob_size);
}
void PopulateResponseBody(scoped_refptr<BlobDataHandle> data_handle,
blink::mojom::FetchAPIResponse* response) override {
disk_cache::Entry* entry = data_handle->entry().get();
DCHECK(entry);
// Create a blob with the response body data.
response->blob = blink::mojom::SerializedBlob::New();
response->blob->size =
entry->GetDataSize(CacheStorageCache::INDEX_RESPONSE_BODY);
response->blob->uuid = base::GenerateGUID();
auto blob_data =
std::make_unique<storage::BlobDataBuilder>(response->blob->uuid);
blob_data->AppendDiskCacheEntryWithSideData(
std::move(data_handle), entry, CacheStorageCache::INDEX_RESPONSE_BODY,
CacheStorageCache::INDEX_SIDE_DATA);
auto blob_handle = blob_context_->AddFinishedBlob(std::move(blob_data));
storage::BlobImpl::Create(std::move(blob_handle),
MakeRequest(&response->blob->blob));
}
void PopulateRequestBody(scoped_refptr<BlobDataHandle> data_handle,
blink::mojom::FetchAPIRequest* request) override {}
private:
base::WeakPtr<CacheStorageCacheEntryHandler> GetWeakPtr() override {
return weak_ptr_factory_.GetWeakPtr();
}
base::WeakPtrFactory<CacheStorageCacheEntryHandlerImpl> weak_ptr_factory_;
};
CacheStorageCacheEntryHandler::CacheStorageCacheEntryHandler(
base::WeakPtr<storage::BlobStorageContext> blob_context)
: blob_context_(blob_context) {}
scoped_refptr<CacheStorageCacheEntryHandler::BlobDataHandle>
CacheStorageCacheEntryHandler::CreateBlobDataHandle(
CacheStorageCacheHandle cache_handle,
disk_cache::ScopedEntryPtr entry) {
auto handle =
base::MakeRefCounted<CacheStorageCacheEntryHandler::BlobDataHandle>(
GetWeakPtr(), std::move(cache_handle), std::move(entry));
DCHECK_EQ(blob_data_handles_.count(handle.get()), 0u);
blob_data_handles_.insert(handle.get());
return handle;
}
CacheStorageCacheEntryHandler::~CacheStorageCacheEntryHandler() = default;
void CacheStorageCacheEntryHandler::InvalidateBlobDataHandles() {
// Calling Invalidate() can cause the CacheStorageCacheEntryHandler to be
// destroyed. Be careful not to touch |this| after calling Invalidate().
std::set<BlobDataHandle*> handles = std::move(blob_data_handles_);
for (auto* handle : handles)
handle->Invalidate();
}
void CacheStorageCacheEntryHandler::EraseBlobDataHandle(
BlobDataHandle* handle) {
DCHECK_NE(blob_data_handles_.count(handle), 0u);
blob_data_handles_.erase(handle);
}
// static
std::unique_ptr<CacheStorageCacheEntryHandler>
CacheStorageCacheEntryHandler::CreateCacheEntryHandler(
CacheStorageOwner owner,
base::WeakPtr<storage::BlobStorageContext> blob_context) {
switch (owner) {
case CacheStorageOwner::kCacheAPI:
return std::make_unique<CacheStorageCacheEntryHandlerImpl>(
std::move(blob_context));
case CacheStorageOwner::kBackgroundFetch:
return std::make_unique<background_fetch::CacheEntryHandlerImpl>(
std::move(blob_context));
}
NOTREACHED();
}
} // namespace content