blob: 46a8d4a5fb79aeedfa3fc45921e2bfc0b4ad7a07 [file] [log] [blame]
// 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/cache_storage/cache_storage_manager.h"
#include <stddef.h>
#include <stdint.h>
#include <list>
#include <set>
#include <utility>
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/sha1.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_context_impl.h"
#include "content/browser/cache_storage/cache_storage_index.h"
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cache_storage_usage_info.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/disk_cache/disk_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "services/network/public/interfaces/fetch_api.mojom.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 "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
using network::mojom::FetchResponseType;
namespace content {
namespace {
bool IsIndexFileCurrent(const base::FilePath& cache_dir) {
base::File::Info info;
const base::FilePath index_path =
cache_dir.AppendASCII(CacheStorage::kIndexFileName);
if (!GetFileInfo(index_path, &info))
return false;
base::Time index_last_modified = info.last_modified;
base::FileEnumerator enumerator(cache_dir, false,
base::FileEnumerator::DIRECTORIES);
for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
file_path = enumerator.Next()) {
if (!GetFileInfo(file_path, &info))
return false;
if (index_last_modified < info.last_modified)
return false;
}
return true;
}
void CopyCacheStorageIndex(CacheStorageIndex* dest,
const CacheStorageIndex& src) {
DCHECK_EQ(0U, dest->num_entries());
for (const auto& cache_metadata : src.ordered_cache_metadata())
dest->Insert(cache_metadata);
}
class TestCacheStorageObserver : public CacheStorageContextImpl::Observer {
public:
void OnCacheListChanged(const url::Origin& origin) override {
++notify_list_changed_count;
}
void OnCacheContentChanged(const url::Origin& origin,
const std::string& cache_name) override {
++notify_content_changed_count;
}
int notify_list_changed_count = 0;
int notify_content_changed_count = 0;
};
} // anonymous namespace
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
// the memory.
std::unique_ptr<storage::BlobProtocolHandler> CreateMockBlobProtocolHandler(
storage::BlobStorageContext* blob_storage_context) {
return base::WrapUnique(
new storage::BlobProtocolHandler(blob_storage_context, nullptr));
}
class CacheStorageManagerTest : public testing::Test {
public:
CacheStorageManagerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
blob_storage_context_(nullptr),
callback_bool_(false),
callback_error_(CACHE_STORAGE_OK),
origin1_("http://example1.com"),
origin2_("http://example2.com") {}
void SetUp() override {
base::FilePath temp_dir_path;
if (!MemoryOnly())
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
CreateStorageManager();
}
void TearDown() override {
DestroyStorageManager();
disk_cache::FlushCacheThreadForTesting();
content::RunAllTasksUntilIdle();
}
virtual bool MemoryOnly() { return false; }
void BoolCallback(base::RunLoop* run_loop, bool value) {
callback_bool_ = value;
run_loop->Quit();
}
void BoolAndErrorCallback(base::RunLoop* run_loop,
bool value,
CacheStorageError error) {
callback_bool_ = value;
callback_error_ = error;
run_loop->Quit();
}
void CacheAndErrorCallback(
base::RunLoop* run_loop,
std::unique_ptr<CacheStorageCacheHandle> cache_handle,
CacheStorageError error) {
callback_cache_handle_ = std::move(cache_handle);
callback_error_ = error;
run_loop->Quit();
}
void CacheMetadataCallback(base::RunLoop* run_loop,
const CacheStorageIndex& cache_index) {
callback_cache_index_ = CacheStorageIndex();
CopyCacheStorageIndex(&callback_cache_index_, cache_index);
run_loop->Quit();
}
const std::string& GetFirstIndexName() const {
return callback_cache_index_.ordered_cache_metadata().front().name;
}
std::vector<std::string> GetIndexNames() const {
std::vector<std::string> cache_names;
for (const auto& metadata : callback_cache_index_.ordered_cache_metadata())
cache_names.push_back(metadata.name);
return cache_names;
}
void CachePutCallback(base::RunLoop* run_loop, CacheStorageError error) {
callback_error_ = error;
run_loop->Quit();
}
void CacheDeleteCallback(base::RunLoop* run_loop, CacheStorageError error) {
callback_error_ = error;
run_loop->Quit();
}
void CacheMatchCallback(
base::RunLoop* run_loop,
CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
callback_error_ = error;
callback_cache_handle_response_ = std::move(response);
callback_data_handle_ = std::move(blob_data_handle);
run_loop->Quit();
}
void CreateStorageManager() {
ChromeBlobStorageContext* blob_storage_context(
ChromeBlobStorageContext::GetFor(&browser_context_));
// Wait for ChromeBlobStorageContext to finish initializing.
base::RunLoop().RunUntilIdle();
blob_storage_context_ = blob_storage_context->context();
url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
url_request_job_factory_->SetProtocolHandler(
"blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
net::URLRequestContext* url_request_context =
BrowserContext::GetDefaultStoragePartition(&browser_context_)->
GetURLRequestContext()->GetURLRequestContext();
url_request_context->set_job_factory(url_request_job_factory_.get());
base::FilePath temp_dir_path;
if (!MemoryOnly())
temp_dir_path = temp_dir_.GetPath();
quota_policy_ = new MockSpecialStoragePolicy;
mock_quota_manager_ = new MockQuotaManager(
MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
quota_policy_.get());
mock_quota_manager_->SetQuota(
GURL(origin1_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
mock_quota_manager_->SetQuota(
GURL(origin2_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
quota_manager_proxy_ = new MockQuotaManagerProxy(
mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
cache_manager_ = CacheStorageManager::Create(
temp_dir_path, base::ThreadTaskRunnerHandle::Get(),
quota_manager_proxy_);
cache_manager_->SetBlobParametersForCache(
BrowserContext::GetDefaultStoragePartition(&browser_context_)
->GetURLRequestContext(),
blob_storage_context->context()->AsWeakPtr());
}
bool FlushCacheStorageIndex(const GURL& origin) {
callback_bool_ = false;
base::RunLoop loop;
bool write_was_scheduled =
CacheStorageForOrigin(origin)->InitiateScheduledIndexWriteForTest(
base::BindOnce(&CacheStorageManagerTest::BoolCallback,
base::Unretained(this), &loop));
loop.Run();
DCHECK(callback_bool_);
return write_was_scheduled;
}
void DestroyStorageManager() {
if (quota_manager_proxy_)
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
base::RunLoop().RunUntilIdle();
quota_manager_proxy_ = nullptr;
url_request_job_factory_.reset();
blob_storage_context_ = nullptr;
quota_policy_ = nullptr;
mock_quota_manager_ = nullptr;
callback_cache_handle_ = nullptr;
callback_bool_ = false;
callback_cache_handle_response_ = nullptr;
callback_data_handle_ = nullptr;
callback_cache_index_ = CacheStorageIndex();
callback_all_origins_usage_.clear();
cache_manager_ = nullptr;
}
bool Open(const GURL& origin, const std::string& cache_name) {
base::RunLoop loop;
cache_manager_->OpenCache(
origin, cache_name,
base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
bool error = callback_error_ != CACHE_STORAGE_OK;
if (error)
EXPECT_FALSE(callback_cache_handle_);
else
EXPECT_TRUE(callback_cache_handle_);
return !error;
}
bool Has(const GURL& origin, const std::string& cache_name) {
base::RunLoop loop;
cache_manager_->HasCache(
origin, cache_name,
base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_bool_;
}
bool Delete(const GURL& origin, const std::string& cache_name) {
base::RunLoop loop;
cache_manager_->DeleteCache(
origin, cache_name,
base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_bool_;
}
size_t Keys(const GURL& origin) {
base::RunLoop loop;
cache_manager_->EnumerateCaches(
origin,
base::BindOnce(&CacheStorageManagerTest::CacheMetadataCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_cache_index_.num_entries();
}
bool StorageMatch(const GURL& origin,
const std::string& cache_name,
const GURL& url,
const CacheStorageCacheQueryParams& match_params =
CacheStorageCacheQueryParams()) {
ServiceWorkerFetchRequest request;
request.url = url;
return StorageMatchWithRequest(origin, cache_name, request, match_params);
}
bool StorageMatchWithRequest(
const GURL& origin,
const std::string& cache_name,
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params =
CacheStorageCacheQueryParams()) {
std::unique_ptr<ServiceWorkerFetchRequest> unique_request =
base::MakeUnique<ServiceWorkerFetchRequest>(request);
base::RunLoop loop;
cache_manager_->MatchCache(
origin, cache_name, std::move(unique_request), match_params,
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
bool StorageMatchAll(const GURL& origin,
const GURL& url,
const CacheStorageCacheQueryParams& match_params =
CacheStorageCacheQueryParams()) {
ServiceWorkerFetchRequest request;
request.url = url;
return StorageMatchAllWithRequest(origin, request, match_params);
}
bool StorageMatchAllWithRequest(
const GURL& origin,
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params =
CacheStorageCacheQueryParams()) {
std::unique_ptr<ServiceWorkerFetchRequest> unique_request =
base::MakeUnique<ServiceWorkerFetchRequest>(request);
base::RunLoop loop;
cache_manager_->MatchAllCaches(
origin, std::move(unique_request), match_params,
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
bool CachePut(CacheStorageCache* cache,
const GURL& url,
FetchResponseType response_type = FetchResponseType::kDefault) {
ServiceWorkerFetchRequest request;
request.url = url;
return CachePutWithStatusCode(cache, request, 200, response_type);
}
bool CachePutWithRequestAndHeaders(
CacheStorageCache* cache,
const ServiceWorkerFetchRequest& request,
const ServiceWorkerHeaderMap& response_headers,
FetchResponseType response_type = FetchResponseType::kDefault) {
return CachePutWithStatusCode(cache, request, 200, response_type,
response_headers);
}
bool CachePutWithStatusCode(
CacheStorageCache* cache,
const ServiceWorkerFetchRequest& request,
int status_code,
FetchResponseType response_type = FetchResponseType::kDefault,
const ServiceWorkerHeaderMap& response_headers =
ServiceWorkerHeaderMap()) {
std::unique_ptr<storage::BlobDataBuilder> blob_data(
new storage::BlobDataBuilder(base::GenerateGUID()));
blob_data->AppendData(request.url.spec());
std::unique_ptr<storage::BlobDataHandle> blob_handle =
blob_storage_context_->AddFinishedBlob(blob_data.get());
std::unique_ptr<std::vector<GURL>> url_list =
base::MakeUnique<std::vector<GURL>>();
url_list->push_back(request.url);
ServiceWorkerResponse response(
std::move(url_list), status_code, "OK", response_type,
base::MakeUnique<ServiceWorkerHeaderMap>(response_headers),
blob_handle->uuid(), request.url.spec().size(), nullptr /* blob */,
blink::kWebServiceWorkerResponseErrorUnknown, base::Time(),
false /* is_in_cache_storage */,
std::string() /* cache_storage_cache_name */,
base::MakeUnique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
CacheStorageBatchOperation operation;
operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
operation.request = request;
operation.response = response;
base::RunLoop loop;
cache->BatchOperation(
std::vector<CacheStorageBatchOperation>(1, operation),
base::BindOnce(&CacheStorageManagerTest::CachePutCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
bool CacheDelete(CacheStorageCache* cache, const GURL& url) {
ServiceWorkerFetchRequest request;
request.url = url;
ServiceWorkerResponse response;
CacheStorageBatchOperation operation;
operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
operation.request = request;
operation.response = response;
base::RunLoop loop;
cache->BatchOperation(
std::vector<CacheStorageBatchOperation>(1, operation),
base::BindOnce(&CacheStorageManagerTest::CacheDeleteCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
bool CacheMatch(CacheStorageCache* cache, const GURL& url) {
std::unique_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest());
request->url = url;
base::RunLoop loop;
cache->Match(
std::move(request), CacheStorageCacheQueryParams(),
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
CacheStorage* CacheStorageForOrigin(const GURL& origin) {
return cache_manager_->FindOrCreateCacheStorage(origin);
}
int64_t GetOriginUsage(const GURL& origin) {
base::RunLoop loop;
cache_manager_->GetOriginUsage(
origin, base::Bind(&CacheStorageManagerTest::UsageCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_usage_;
}
void UsageCallback(base::RunLoop* run_loop, int64_t usage) {
callback_usage_ = usage;
run_loop->Quit();
}
std::vector<CacheStorageUsageInfo> GetAllOriginsUsage() {
base::RunLoop loop;
cache_manager_->GetAllOriginsUsage(
base::Bind(&CacheStorageManagerTest::AllOriginsUsageCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_all_origins_usage_;
}
void AllOriginsUsageCallback(
base::RunLoop* run_loop,
const std::vector<CacheStorageUsageInfo>& usage) {
callback_all_origins_usage_ = usage;
run_loop->Quit();
}
int64_t GetSizeThenCloseAllCaches(const GURL& origin) {
base::RunLoop loop;
CacheStorage* cache_storage = CacheStorageForOrigin(origin);
cache_storage->GetSizeThenCloseAllCaches(
base::BindOnce(&CacheStorageManagerTest::UsageCallback,
base::Unretained(this), &loop));
loop.Run();
return callback_usage_;
}
int64_t Size(const GURL& origin) {
base::RunLoop loop;
CacheStorage* cache_storage = CacheStorageForOrigin(origin);
cache_storage->Size(base::BindOnce(&CacheStorageManagerTest::UsageCallback,
base::Unretained(this), &loop));
loop.Run();
return callback_usage_;
}
int64_t GetQuotaOriginUsage(const GURL& origin) {
int64_t usage(CacheStorage::kSizeUnknown);
base::RunLoop loop;
quota_manager_proxy_->GetUsageAndQuota(
base::ThreadTaskRunnerHandle::Get().get(), origin,
StorageType::kStorageTypeTemporary,
base::Bind(&CacheStorageManagerTest::DidGetQuotaOriginUsage,
base::Unretained(this), base::Unretained(&usage), &loop));
loop.Run();
return usage;
}
void DidGetQuotaOriginUsage(int64_t* out_usage,
base::RunLoop* run_loop,
QuotaStatusCode status_code,
int64_t usage,
int64_t quota) {
if (status_code == storage::kQuotaStatusOk)
*out_usage = usage;
run_loop->Quit();
}
protected:
// Temporary directory must be allocated first so as to be destroyed last.
base::ScopedTempDir temp_dir_;
TestBrowserThreadBundle browser_thread_bundle_;
TestBrowserContext browser_context_;
std::unique_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
storage::BlobStorageContext* blob_storage_context_;
scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
std::unique_ptr<CacheStorageManager> cache_manager_;
std::unique_ptr<CacheStorageCacheHandle> callback_cache_handle_;
int callback_bool_;
CacheStorageError callback_error_;
std::unique_ptr<ServiceWorkerResponse> callback_cache_handle_response_;
std::unique_ptr<storage::BlobDataHandle> callback_data_handle_;
CacheStorageIndex callback_cache_index_;
const GURL origin1_;
const GURL origin2_;
int64_t callback_usage_;
std::vector<CacheStorageUsageInfo> callback_all_origins_usage_;
private:
DISALLOW_COPY_AND_ASSIGN(CacheStorageManagerTest);
};
class CacheStorageManagerMemoryOnlyTest : public CacheStorageManagerTest {
public:
bool MemoryOnly() override { return true; }
};
class CacheStorageManagerTestP : public CacheStorageManagerTest,
public testing::WithParamInterface<bool> {
public:
bool MemoryOnly() override { return !GetParam(); }
};
TEST_F(CacheStorageManagerTest, TestsRunOnIOThread) {
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
TEST_P(CacheStorageManagerTestP, OpenCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
}
TEST_P(CacheStorageManagerTestP, OpenTwoCaches) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
}
TEST_P(CacheStorageManagerTestP, CachePointersDiffer) {
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_NE(callback_cache_handle_->value(), cache_handle->value());
}
TEST_P(CacheStorageManagerTestP, Open2CachesSameNameDiffOrigins) {
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin2_, "foo"));
EXPECT_NE(cache_handle->value(), callback_cache_handle_->value());
}
TEST_P(CacheStorageManagerTestP, OpenExistingCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value());
}
TEST_P(CacheStorageManagerTestP, HasCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Has(origin1_, "foo"));
EXPECT_TRUE(callback_bool_);
}
TEST_P(CacheStorageManagerTestP, HasNonExistent) {
EXPECT_FALSE(Has(origin1_, "foo"));
}
TEST_P(CacheStorageManagerTestP, DeleteCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_FALSE(Has(origin1_, "foo"));
}
TEST_P(CacheStorageManagerTestP, DeleteTwice) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_FALSE(Delete(origin1_, "foo"));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
// The quota manager gets updated after the put operation runs its callback so
// run the event loop.
base::RunLoop().RunUntilIdle();
int64_t put_delta = quota_manager_proxy_->last_notified_delta();
EXPECT_LT(0, put_delta);
EXPECT_TRUE(Delete(origin1_, "foo"));
// Drop the cache handle so that the cache can be erased from disk.
callback_cache_handle_ = nullptr;
base::RunLoop().RunUntilIdle();
EXPECT_EQ(-1 * quota_manager_proxy_->last_notified_delta(), put_delta);
}
TEST_P(CacheStorageManagerTestP, EmptyKeys) {
EXPECT_EQ(0u, Keys(origin1_));
}
TEST_P(CacheStorageManagerTestP, SomeKeys) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
EXPECT_EQ(2u, Keys(origin1_));
std::vector<std::string> expected_keys;
expected_keys.push_back("foo");
expected_keys.push_back("bar");
EXPECT_EQ(expected_keys, GetIndexNames());
EXPECT_EQ(1u, Keys(origin2_));
EXPECT_STREQ("baz", GetFirstIndexName().c_str());
}
TEST_P(CacheStorageManagerTestP, DeletedKeysGone) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
EXPECT_TRUE(Delete(origin1_, "bar"));
EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("foo", GetFirstIndexName().c_str());
}
TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo")));
EXPECT_EQ(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllNoCaches) {
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// Deleting a cache and creating one with the same name and adding an entry
// with the same URL should work. (see crbug.com/542668)
const GURL kTestURL = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL));
EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), kTestURL));
std::unique_ptr<storage::BlobDataHandle> data_handle =
std::move(callback_data_handle_);
EXPECT_TRUE(Delete(origin1_, "foo"));
// The cache is deleted but the handle to one of its entries is still
// open. Creating a new cache in the same directory would fail on Windows.
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL));
}
TEST_P(CacheStorageManagerTestP, DropRefAfterNewCacheWithSameNameCreated) {
// Make sure that dropping the final cache handle to a doomed cache doesn't
// affect newer caches with the same name. (see crbug.com/631467)
// 1. Create cache A and hang onto the handle
const GURL kTestURL = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
// 2. Doom the cache
EXPECT_TRUE(Delete(origin1_, "foo"));
// 3. Create cache B (with the same name)
EXPECT_TRUE(Open(origin1_, "foo"));
// 4. Drop handle to A
cache_handle.reset();
// 5. Verify that B still works
EXPECT_FALSE(CacheMatch(callback_cache_handle_->value(), kTestURL));
}
TEST_P(CacheStorageManagerTestP, DeleteCorrectDirectory) {
// This test reproduces crbug.com/630036.
// 1. Cache A with name "foo" is created
const GURL kTestURL = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
// 2. Cache A is doomed, but js hangs onto the handle.
EXPECT_TRUE(Delete(origin1_, "foo"));
// 3. Cache B with name "foo" is created
EXPECT_TRUE(Open(origin1_, "foo"));
// 4. Cache B is doomed, and both handles are reset.
EXPECT_TRUE(Delete(origin1_, "foo"));
cache_handle.reset();
callback_cache_handle_.reset();
// Do some busy work on a different cache to move the cache pool threads
// along and trigger the bug.
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(), kTestURL));
EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(), kTestURL));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) {
EXPECT_TRUE(Open(origin1_, "foo"));
ServiceWorkerFetchRequest request;
request.url = GURL("http://example.com/foo");
EXPECT_TRUE(
CachePutWithStatusCode(callback_cache_handle_->value(), request, 200));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(
CachePutWithStatusCode(callback_cache_handle_->value(), request, 201));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
// The caches need to be searched in order of creation, so verify that the
// response came from the first cache.
EXPECT_EQ(200, callback_cache_handle_response_->status_code);
}
TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "baz"));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, Chinese) {
EXPECT_TRUE(Open(origin1_, "你好"));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, "你好"));
EXPECT_EQ(callback_cache_handle_->value(), cache_handle->value());
EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("你好", GetFirstIndexName().c_str());
}
TEST_F(CacheStorageManagerTest, EmptyKey) {
EXPECT_TRUE(Open(origin1_, ""));
std::unique_ptr<CacheStorageCacheHandle> cache_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(Open(origin1_, ""));
EXPECT_EQ(cache_handle->value(), callback_cache_handle_->value());
EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ("", GetFirstIndexName().c_str());
EXPECT_TRUE(Has(origin1_, ""));
EXPECT_TRUE(Delete(origin1_, ""));
EXPECT_EQ(0u, Keys(origin1_));
}
TEST_F(CacheStorageManagerTest, DataPersists) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin1_, "baz"));
EXPECT_TRUE(Open(origin2_, "raz"));
EXPECT_TRUE(Delete(origin1_, "bar"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
EXPECT_EQ(2u, Keys(origin1_));
std::vector<std::string> expected_keys;
expected_keys.push_back("foo");
expected_keys.push_back("baz");
EXPECT_EQ(expected_keys, GetIndexNames());
}
TEST_F(CacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin2_, "baz"));
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
EXPECT_EQ(0u, Keys(origin1_));
}
TEST_F(CacheStorageManagerTest, BadCacheName) {
// Since the implementation writes cache names to disk, ensure that we don't
// escape the directory.
const std::string bad_name = "../../../../../../../../../../../../../../foo";
EXPECT_TRUE(Open(origin1_, bad_name));
EXPECT_EQ(1u, Keys(origin1_));
EXPECT_STREQ(bad_name.c_str(), GetFirstIndexName().c_str());
}
TEST_F(CacheStorageManagerTest, BadOriginName) {
// Since the implementation writes origin names to disk, ensure that we don't
// escape the directory.
GURL bad_origin("http://../../../../../../../../../../../../../../foo");
EXPECT_TRUE(Open(bad_origin, "foo"));
EXPECT_EQ(1u, Keys(bad_origin));
EXPECT_STREQ("foo", GetFirstIndexName().c_str());
}
// With a persistent cache if the client drops its reference to a
// CacheStorageCache it should be deleted.
TEST_F(CacheStorageManagerTest, DropReference) {
EXPECT_TRUE(Open(origin1_, "foo"));
base::WeakPtr<CacheStorageCache> cache =
callback_cache_handle_->value()->AsWeakPtr();
// Run a cache operation to ensure that the cache has finished initializing so
// that when the handle is dropped it can close immediately.
EXPECT_FALSE(CacheMatch(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
callback_cache_handle_ = nullptr;
EXPECT_FALSE(cache);
}
// A cache continues to work so long as there is a handle to it. Only after the
// last cache handle is deleted can the cache be freed.
TEST_P(CacheStorageManagerTestP, CacheWorksAfterDelete) {
const GURL kFooURL("http://example.com/foo");
const GURL kBarURL("http://example.com/bar");
const GURL kBazURL("http://example.com/baz");
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> original_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
EXPECT_TRUE(Delete(origin1_, "foo"));
// Verify that the existing cache handle still works.
EXPECT_TRUE(CacheMatch(original_handle->value(), kFooURL));
EXPECT_TRUE(CachePut(original_handle->value(), kBarURL));
EXPECT_TRUE(CacheMatch(original_handle->value(), kBarURL));
// The cache shouldn't be visible to subsequent storage operations.
EXPECT_EQ(0u, Keys(origin1_));
// Open a new cache with the same name, it should create a new cache, but not
// interfere with the original cache.
EXPECT_TRUE(Open(origin1_, "foo"));
std::unique_ptr<CacheStorageCacheHandle> new_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(new_handle->value(), kBazURL));
EXPECT_FALSE(CacheMatch(new_handle->value(), kFooURL));
EXPECT_FALSE(CacheMatch(new_handle->value(), kBarURL));
EXPECT_TRUE(CacheMatch(new_handle->value(), kBazURL));
EXPECT_TRUE(CacheMatch(original_handle->value(), kFooURL));
EXPECT_TRUE(CacheMatch(original_handle->value(), kBarURL));
EXPECT_FALSE(CacheMatch(original_handle->value(), kBazURL));
}
// Deleted caches can still be modified, but all changes will eventually be
// thrown away when all references are released.
TEST_F(CacheStorageManagerTest, DeletedCacheIgnoredInIndex) {
const GURL kFooURL("http://example.com/foo");
const GURL kBarURL("http://example.com/bar");
const GURL kBazURL("http://example.com/baz");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
auto original_handle = std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
EXPECT_TRUE(Delete(origin1_, kCacheName));
// Now a second cache using the same name, but with different data.
EXPECT_TRUE(Open(origin1_, kCacheName));
auto new_handle = std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(new_handle->value(), kFooURL));
EXPECT_TRUE(CachePut(new_handle->value(), kBarURL));
EXPECT_TRUE(CachePut(new_handle->value(), kBazURL));
auto new_cache_size = Size(origin1_);
// Now modify the first cache.
EXPECT_TRUE(CachePut(original_handle->value(), kBarURL));
// Now deref both caches, and recreate the storage manager.
original_handle = nullptr;
new_handle = nullptr;
EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
DestroyStorageManager();
CreateStorageManager();
EXPECT_TRUE(Open(origin1_, kCacheName));
EXPECT_EQ(new_cache_size, Size(origin1_));
}
TEST_F(CacheStorageManagerTest, TestErrorInitializingCache) {
if (MemoryOnly())
return;
const GURL kFooURL("http://example.com/foo");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
auto original_handle = std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
auto size_before_close = Size(origin1_);
EXPECT_GT(size_before_close, 0);
CacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
auto cache_handle = cache_storage->GetLoadedCache(kCacheName);
CacheStorageCache* cache = cache_handle->value();
base::FilePath index_path = cache->path().AppendASCII("index");
cache_handle.reset();
DestroyStorageManager();
// Truncate the SimpleCache index to force an error when next opened.
ASSERT_FALSE(index_path.empty());
ASSERT_EQ(5, base::WriteFile(index_path, "hello", 5));
CreateStorageManager();
EXPECT_TRUE(Open(origin1_, kCacheName));
EXPECT_EQ(0, Size(origin1_));
}
TEST_F(CacheStorageManagerTest, CacheSizeCorrectAfterReopen) {
const GURL kFooURL("http://example.com/foo");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
auto original_handle = std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
auto size_before_close = Size(origin1_);
EXPECT_GT(size_before_close, 0);
DestroyStorageManager();
CreateStorageManager();
EXPECT_TRUE(Open(origin1_, kCacheName));
EXPECT_EQ(size_before_close, Size(origin1_));
}
TEST_F(CacheStorageManagerTest, CacheSizePaddedAfterReopen) {
const GURL kFooURL = origin1_.Resolve("foo");
const std::string kCacheName = "foo";
int64_t put_delta = quota_manager_proxy_->last_notified_delta();
EXPECT_EQ(0, put_delta);
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_TRUE(Open(origin1_, kCacheName));
std::unique_ptr<CacheStorageCacheHandle> original_handle =
std::move(callback_cache_handle_);
base::RunLoop().RunUntilIdle();
put_delta += quota_manager_proxy_->last_notified_delta();
EXPECT_EQ(0, put_delta);
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_TRUE(
CachePut(original_handle->value(), kFooURL, FetchResponseType::kOpaque));
int64_t cache_size_before_close = Size(origin1_);
base::FilePath storage_dir = original_handle->value()->path().DirName();
original_handle = nullptr;
EXPECT_GT(cache_size_before_close, 0);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(cache_size_before_close, GetQuotaOriginUsage(origin1_));
base::RunLoop().RunUntilIdle();
put_delta = quota_manager_proxy_->last_notified_delta();
EXPECT_GT(put_delta, 0);
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_EQ(GetQuotaOriginUsage(origin1_), put_delta);
// Close the caches and cache manager.
EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
DestroyStorageManager();
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
EXPECT_TRUE(Open(origin1_, kCacheName));
base::RunLoop().RunUntilIdle();
put_delta = quota_manager_proxy_->last_notified_delta();
EXPECT_EQ(0, put_delta);
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_EQ(cache_size_before_close, Size(origin1_));
}
TEST_F(CacheStorageManagerTest, PersistedCacheKeyUsed) {
const GURL kFooURL = origin1_.Resolve("foo");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
std::unique_ptr<CacheStorageCacheHandle> original_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(
CachePut(original_handle->value(), kFooURL, FetchResponseType::kOpaque));
int64_t cache_size_after_put = Size(origin1_);
EXPECT_LT(0, cache_size_after_put);
// Close the caches and cache manager.
EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
DestroyStorageManager();
// GenerateNewKeyForTest isn't thread safe so
base::RunLoop().RunUntilIdle();
CacheStorage::GenerateNewKeyForTesting();
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
// Reopening the origin/cache creates a new CacheStorage instance with a new
// random key.
EXPECT_TRUE(Open(origin1_, kCacheName));
// Size (before any change) should be the same as before it was closed.
EXPECT_EQ(cache_size_after_put, Size(origin1_));
// Delete the value. If the new padding key was used to deduct the padded size
// then after deletion we would expect to see a non-zero cache size.
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_EQ(0, Size(origin1_));
// Now put the exact same resource back into the cache. This time we expect to
// see a different size as the padding is calculated with a different key.
std::unique_ptr<CacheStorageCacheHandle> new_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(
CachePut(new_handle->value(), kFooURL, FetchResponseType::kOpaque));
EXPECT_NE(cache_size_after_put, Size(origin1_));
}
// With a memory cache the cache can't be freed from memory until the client
// calls delete.
TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryLosesReferenceOnlyAfterDelete) {
EXPECT_TRUE(Open(origin1_, "foo"));
base::WeakPtr<CacheStorageCache> cache =
callback_cache_handle_->value()->AsWeakPtr();
callback_cache_handle_ = nullptr;
EXPECT_TRUE(cache);
EXPECT_TRUE(Delete(origin1_, "foo"));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(cache);
}
TEST_P(CacheStorageManagerTestP, DeleteBeforeRelease) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_TRUE(callback_cache_handle_->value());
}
TEST_P(CacheStorageManagerTestP, OpenRunsSerially) {
EXPECT_FALSE(Delete(origin1_, "tmp")); // Init storage.
CacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
cache_storage->StartAsyncOperationForTesting();
base::RunLoop open_loop;
cache_manager_->OpenCache(
origin1_, "foo",
base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
base::Unretained(this), base::Unretained(&open_loop)));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback_cache_handle_);
cache_storage->CompleteAsyncOperationForTesting();
open_loop.Run();
EXPECT_TRUE(callback_cache_handle_);
}
TEST_P(CacheStorageManagerTestP, GetOriginUsage) {
EXPECT_EQ(0, GetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(0, GetOriginUsage(origin1_));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
int64_t foo_size = GetOriginUsage(origin1_);
EXPECT_LT(0, GetOriginUsage(origin1_));
EXPECT_EQ(0, GetOriginUsage(origin2_));
// Add the same entry into a second cache, the size should double.
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(2 * foo_size, GetOriginUsage(origin1_));
}
TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
EXPECT_EQ(0ULL, GetAllOriginsUsage().size());
// Put one entry in a cache on origin 1.
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
// Put two entries (of identical size) in a cache on origin 2.
EXPECT_TRUE(Open(origin2_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/bar")));
std::vector<CacheStorageUsageInfo> usage = GetAllOriginsUsage();
EXPECT_EQ(2ULL, usage.size());
int origin1_index = usage[0].origin == origin1_ ? 0 : 1;
int origin2_index = usage[1].origin == origin2_ ? 1 : 0;
EXPECT_NE(origin1_index, origin2_index);
int64_t origin1_size = usage[origin1_index].total_size_bytes;
int64_t origin2_size = usage[origin2_index].total_size_bytes;
EXPECT_EQ(2 * origin1_size, origin2_size);
if (MemoryOnly()) {
EXPECT_TRUE(usage[origin1_index].last_modified.is_null());
EXPECT_TRUE(usage[origin2_index].last_modified.is_null());
} else {
EXPECT_FALSE(usage[origin1_index].last_modified.is_null());
EXPECT_FALSE(usage[origin2_index].last_modified.is_null());
}
}
TEST_F(CacheStorageManagerTest, GetAllOriginsUsageWithOldIndex) {
// Write a single value (V1) to the cache.
const GURL kFooURL = origin1_.Resolve("foo");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
std::unique_ptr<CacheStorageCacheHandle> original_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
int64_t cache_size_v1 = Size(origin1_);
base::FilePath storage_dir = original_handle->value()->path().DirName();
original_handle = nullptr;
EXPECT_GE(cache_size_v1, 0);
// Close the caches and cache manager.
EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
DestroyStorageManager();
// Save a copy of the V1 index.
EXPECT_TRUE(IsIndexFileCurrent(storage_dir));
base::FilePath index_path = storage_dir.AppendASCII("index.txt");
EXPECT_TRUE(base::PathExists(index_path));
base::FilePath backup_index_path = storage_dir.AppendASCII("index.txt.bak");
EXPECT_TRUE(base::CopyFile(index_path, backup_index_path));
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
// Create a second value (V2) in the cache.
EXPECT_TRUE(Open(origin1_, kCacheName));
original_handle = std::move(callback_cache_handle_);
const GURL kBarURL = origin1_.Resolve("bar");
EXPECT_TRUE(CachePut(original_handle->value(), kBarURL));
original_handle = nullptr;
std::vector<CacheStorageUsageInfo> usage = GetAllOriginsUsage();
ASSERT_EQ(1ULL, usage.size());
int64_t usage_before_close = usage[0].total_size_bytes;
EXPECT_GT(usage_before_close, 0);
// Close the caches and cache manager.
DestroyStorageManager();
// Restore the index to the V1 state. Make the access/mod times of index file
// older than the other directories in the store to trigger size
// recalculation.
EXPECT_TRUE(base::CopyFile(backup_index_path, index_path));
base::Time t = base::Time::Now() - base::TimeDelta::FromHours(1);
EXPECT_TRUE(base::TouchFile(index_path, t, t));
EXPECT_FALSE(IsIndexFileCurrent(storage_dir));
CreateStorageManager();
usage = GetAllOriginsUsage();
ASSERT_EQ(1ULL, usage.size());
EXPECT_EQ(usage_before_close, usage[0].total_size_bytes);
EXPECT_FALSE(usage[0].last_modified.is_null());
}
TEST_F(CacheStorageManagerTest, GetOriginSizeWithOldIndex) {
// Write a single value (V1) to the cache.
const GURL kFooURL = origin1_.Resolve("foo");
const std::string kCacheName = "foo";
EXPECT_TRUE(Open(origin1_, kCacheName));
std::unique_ptr<CacheStorageCacheHandle> original_handle =
std::move(callback_cache_handle_);
EXPECT_TRUE(CachePut(original_handle->value(), kFooURL));
int64_t cache_size_v1 = Size(origin1_);
base::FilePath storage_dir = original_handle->value()->path().DirName();
original_handle = nullptr;
EXPECT_GE(cache_size_v1, 0);
// Close the caches and cache manager.
EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
DestroyStorageManager();
// Save a copy of the V1 index.
EXPECT_TRUE(IsIndexFileCurrent(storage_dir));
base::FilePath index_path = storage_dir.AppendASCII("index.txt");
EXPECT_TRUE(base::PathExists(index_path));
base::FilePath backup_index_path = storage_dir.AppendASCII("index.txt.bak");
EXPECT_TRUE(base::CopyFile(index_path, backup_index_path));
// Create a new CacheStorageManager that hasn't yet loaded the origin.
CreateStorageManager();
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
// Reopen the cache and write a second value (V2).
EXPECT_TRUE(Open(origin1_, kCacheName));
original_handle = std::move(callback_cache_handle_);
const GURL kBarURL = origin1_.Resolve("bar");
EXPECT_TRUE(CachePut(original_handle->value(), kBarURL));
original_handle = nullptr;
int64_t cache_size_v2 = Size(origin1_);
EXPECT_GE(cache_size_v2, 0);
// Close the caches and cache manager.
DestroyStorageManager();
// Restore the index to the V1 state.
EXPECT_TRUE(base::CopyFile(backup_index_path, index_path));
// Make the access/mod times of index file older than the other files in the
// cache to trigger size recalculation.
base::Time t = base::Time::Now() - base::TimeDelta::FromHours(1);
EXPECT_TRUE(base::TouchFile(index_path, t, t));
EXPECT_FALSE(IsIndexFileCurrent(storage_dir));
// Reopen the cache and ensure the size is correct for the V2 value.
CreateStorageManager();
EXPECT_TRUE(Open(origin1_, kCacheName));
EXPECT_EQ(cache_size_v2, Size(origin1_));
}
TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo2")));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/bar")));
int64_t origin_size = GetOriginUsage(origin1_);
EXPECT_LT(0, origin_size);
EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
EXPECT_FALSE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/baz")));
}
TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Create a referenced cache.
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
// Create an unreferenced directory next to the referenced one.
base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
cache_manager_->root_path(), origin1_);
base::FilePath unreferenced_path = origin_path.AppendASCII("bar");
EXPECT_TRUE(CreateDirectory(unreferenced_path));
EXPECT_TRUE(base::DirectoryExists(unreferenced_path));
// Create a new StorageManager so that the next time the cache is opened
// the unreferenced directory can be deleted.
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
// Verify that the referenced cache still works.
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CacheMatch(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
// Verify that the unreferenced cache is gone.
EXPECT_FALSE(base::DirectoryExists(unreferenced_path));
}
TEST_P(CacheStorageManagerTestP, OpenCacheStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, HasStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_FALSE(Has(origin1_, "foo"));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, DeleteStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_FALSE(Delete(origin1_, "foo"));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, KeysStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_EQ(0u, Keys(origin1_));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, MatchCacheStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, MatchAllCachesStorageAccessed) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, SizeStorageAccessed) {
EXPECT_EQ(0, Size(origin1_));
// Size is not part of the web API and should not notify the quota manager of
// an access.
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, SizeThenCloseStorageAccessed) {
EXPECT_EQ(0, GetSizeThenCloseAllCaches(origin1_));
// GetSizeThenCloseAllCaches is not part of the web API and should not notify
// the quota manager of an access.
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
}
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Created) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(1, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Deleted) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_FALSE(Delete(origin1_, "foo"));
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_EQ(2, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_DeletedThenCreated) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(1, observer.notify_list_changed_count);
EXPECT_TRUE(Delete(origin1_, "foo"));
EXPECT_EQ(2, observer.notify_list_changed_count);
EXPECT_TRUE(Open(origin2_, "foo2"));
EXPECT_EQ(3, observer.notify_list_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_PutEntry) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo1")));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo2")));
EXPECT_EQ(3, observer.notify_content_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteEntry) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_FALSE(Delete(origin1_, "foo"));
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(2, observer.notify_content_changed_count);
EXPECT_FALSE(CacheDelete(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(2, observer.notify_content_changed_count);
}
TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteThenPutEntry) {
TestCacheStorageObserver observer;
cache_manager_->AddObserver(&observer);
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_EQ(0, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(1, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(2, observer.notify_content_changed_count);
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(3, observer.notify_content_changed_count);
EXPECT_TRUE(CacheDelete(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_EQ(4, observer.notify_content_changed_count);
}
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreSearch) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo?bar")));
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
CacheStorageCacheQueryParams match_params;
match_params.ignore_search = true;
EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
match_params));
}
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreMethod) {
GURL url = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(), url));
ServiceWorkerFetchRequest post_request;
post_request.url = url;
post_request.method = "POST";
EXPECT_FALSE(StorageMatchWithRequest(origin1_, "foo", post_request));
CacheStorageCacheQueryParams match_params;
match_params.ignore_method = true;
EXPECT_TRUE(
StorageMatchWithRequest(origin1_, "foo", post_request, match_params));
}
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) {
GURL url = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
ServiceWorkerFetchRequest request;
request.url = url;
request.headers["vary_foo"] = "foo";
ServiceWorkerHeaderMap response_headers;
response_headers["vary"] = "vary_foo";
EXPECT_TRUE(CachePutWithRequestAndHeaders(callback_cache_handle_->value(),
request, response_headers));
EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", request));
request.headers["vary_foo"] = "bar";
EXPECT_FALSE(StorageMatchWithRequest(origin1_, "foo", request));
CacheStorageCacheQueryParams match_params;
match_params.ignore_vary = true;
EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", request, match_params));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreSearch) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo?bar")));
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
CacheStorageCacheQueryParams match_params;
match_params.ignore_search = true;
EXPECT_TRUE(
StorageMatchAll(origin1_, GURL("http://example.com/foo"), match_params));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreMethod) {
GURL url = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(), url));
ServiceWorkerFetchRequest post_request;
post_request.url = url;
post_request.method = "POST";
EXPECT_FALSE(StorageMatchAllWithRequest(origin1_, post_request));
CacheStorageCacheQueryParams match_params;
match_params.ignore_method = true;
EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, post_request, match_params));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
GURL url = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
ServiceWorkerFetchRequest request;
request.url = url;
request.headers["vary_foo"] = "foo";
ServiceWorkerHeaderMap response_headers;
response_headers["vary"] = "vary_foo";
EXPECT_TRUE(CachePutWithRequestAndHeaders(callback_cache_handle_->value(),
request, response_headers));
EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, request));
request.headers["vary_foo"] = "bar";
EXPECT_FALSE(StorageMatchAllWithRequest(origin1_, request));
CacheStorageCacheQueryParams match_params;
match_params.ignore_vary = true;
EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, request, match_params));
}
class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
protected:
CacheStorageQuotaClientTest() {}
void SetUp() override {
CacheStorageManagerTest::SetUp();
quota_client_.reset(
new CacheStorageQuotaClient(cache_manager_->AsWeakPtr()));
}
void QuotaUsageCallback(base::RunLoop* run_loop, int64_t usage) {
callback_quota_usage_ = usage;
run_loop->Quit();
}
void OriginsCallback(base::RunLoop* run_loop, const std::set<GURL>& origins) {
callback_origins_ = origins;
run_loop->Quit();
}
void DeleteOriginCallback(base::RunLoop* run_loop,
storage::QuotaStatusCode status) {
callback_status_ = status;
run_loop->Quit();
}
int64_t QuotaGetOriginUsage(const GURL& origin) {
base::RunLoop loop;
quota_client_->GetOriginUsage(
origin, storage::kStorageTypeTemporary,
base::Bind(&CacheStorageQuotaClientTest::QuotaUsageCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_quota_usage_;
}
size_t QuotaGetOriginsForType() {
base::RunLoop loop;
quota_client_->GetOriginsForType(
storage::kStorageTypeTemporary,
base::Bind(&CacheStorageQuotaClientTest::OriginsCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_origins_.size();
}
size_t QuotaGetOriginsForHost(const std::string& host) {
base::RunLoop loop;
quota_client_->GetOriginsForHost(
storage::kStorageTypeTemporary, host,
base::Bind(&CacheStorageQuotaClientTest::OriginsCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_origins_.size();
}
bool QuotaDeleteOriginData(const GURL& origin) {
base::RunLoop loop;
quota_client_->DeleteOriginData(
origin, storage::kStorageTypeTemporary,
base::Bind(&CacheStorageQuotaClientTest::DeleteOriginCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_status_ == storage::kQuotaStatusOk;
}
bool QuotaDoesSupport(storage::StorageType type) {
return quota_client_->DoesSupport(type);
}
std::unique_ptr<CacheStorageQuotaClient> quota_client_;
storage::QuotaStatusCode callback_status_;
int64_t callback_quota_usage_ = 0;
std::set<GURL> callback_origins_;
private:
DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClientTest);
};
class CacheStorageQuotaClientDiskOnlyTest : public CacheStorageQuotaClientTest {
public:
bool MemoryOnly() override { return false; }
};
class CacheStorageQuotaClientTestP : public CacheStorageQuotaClientTest,
public testing::WithParamInterface<bool> {
bool MemoryOnly() override { return !GetParam(); }
};
TEST_P(CacheStorageQuotaClientTestP, QuotaID) {
EXPECT_EQ(storage::QuotaClient::kServiceWorkerCache, quota_client_->id());
}
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginUsage) {
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_LT(0, QuotaGetOriginUsage(origin1_));
}
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForType) {
EXPECT_EQ(0u, QuotaGetOriginsForType());
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "foo"));
EXPECT_EQ(2u, QuotaGetOriginsForType());
}
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForHost) {
EXPECT_EQ(0u, QuotaGetOriginsForHost("example.com"));
EXPECT_TRUE(Open(GURL("http://example.com:8080"), "foo"));
EXPECT_TRUE(Open(GURL("http://example.com:9000"), "foo"));
EXPECT_TRUE(Open(GURL("ftp://example.com"), "foo"));
EXPECT_TRUE(Open(GURL("http://example2.com"), "foo"));
EXPECT_EQ(3u, QuotaGetOriginsForHost("example.com"));
EXPECT_EQ(1u, QuotaGetOriginsForHost("example2.com"));
EXPECT_TRUE(callback_origins_.find(GURL("http://example2.com")) !=
callback_origins_.end());
EXPECT_EQ(0u, QuotaGetOriginsForHost("unknown.com"));
}
TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteOriginData) {
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
// Call put to test that initialized caches are properly deleted too.
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
int64_t origin1_size = QuotaGetOriginUsage(origin1_);
EXPECT_LT(0, origin1_size);
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
EXPECT_EQ(-1 * origin1_size, quota_manager_proxy_->last_notified_delta());
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_FALSE(Has(origin1_, "foo"));
EXPECT_FALSE(Has(origin1_, "bar"));
EXPECT_TRUE(Has(origin2_, "baz"));
EXPECT_TRUE(Open(origin1_, "foo"));
}
TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyOrigin) {
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
}
TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
EXPECT_TRUE(Open(origin1_, "foo"));
// Call put to test that initialized caches are properly deleted too.
EXPECT_TRUE(CachePut(callback_cache_handle_->value(),
GURL("http://example.com/foo")));
// Close the cache backend so that it writes out its index to disk.
base::RunLoop run_loop;
callback_cache_handle_->value()->Close(run_loop.QuitClosure());
run_loop.Run();
// Create a new CacheStorageManager that hasn't yet loaded the origin.
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
quota_client_.reset(new CacheStorageQuotaClient(cache_manager_->AsWeakPtr()));
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
}
TEST_P(CacheStorageQuotaClientTestP, QuotaDoesSupport) {
EXPECT_TRUE(QuotaDoesSupport(storage::kStorageTypeTemporary));
EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypePersistent));
EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeSyncable));
EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeQuotaNotManaged));
EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeUnknown));
}
INSTANTIATE_TEST_CASE_P(CacheStorageManagerTests,
CacheStorageManagerTestP,
::testing::Values(false, true));
INSTANTIATE_TEST_CASE_P(CacheStorageQuotaClientTests,
CacheStorageQuotaClientTestP,
::testing::Values(false, true));
} // namespace content